瀏覽代碼

Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20160128' into staging

Mostly bugfixes and small improvements; and the gdb target.xml
patch.

# gpg: Signature made Thu 28 Jan 2016 11:02:14 GMT using RSA key ID C6F02FAF
# gpg: Good signature from "Cornelia Huck <huckc@linux.vnet.ibm.com>"
# gpg:                 aka "Cornelia Huck <cornelia.huck@de.ibm.com>"

* remotes/cohuck/tags/s390x-20160128:
  s390x: s390_cpu_get_phys_page_debug has to return -1
  gdb: provide the name of the architecture in the target.xml
  s390x/css: fix control flags during csch
  watchdog/diag288: don't reset for action=none|debug|pause
  watchdog: introduction of get_watchdog_action
  s390x: fix generation of event information crw
  s390x/ioinst: set type and len for SEI response
  s390x/sclp: add device to the sysbus in sclp_realize
  s390x/machine: make addon register fields static
  s390x/skeys: Fix instance and class size

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Peter Maydell 9 年之前
父節點
當前提交
357e81c7e8

+ 14 - 7
gdbstub.c

@@ -540,13 +540,20 @@ static const char *get_feature_xml(const char *p, const char **newp,
             GDBRegisterState *r;
             GDBRegisterState *r;
             CPUState *cpu = first_cpu;
             CPUState *cpu = first_cpu;
 
 
-            snprintf(target_xml, sizeof(target_xml),
-                     "<?xml version=\"1.0\"?>"
-                     "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">"
-                     "<target>"
-                     "<xi:include href=\"%s\"/>",
-                     cc->gdb_core_xml_file);
-
+            pstrcat(target_xml, sizeof(target_xml),
+                    "<?xml version=\"1.0\"?>"
+                    "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">"
+                    "<target>");
+            if (cc->gdb_arch_name) {
+                gchar *arch = cc->gdb_arch_name(cpu);
+                pstrcat(target_xml, sizeof(target_xml), "<architecture>");
+                pstrcat(target_xml, sizeof(target_xml), arch);
+                pstrcat(target_xml, sizeof(target_xml), "</architecture>");
+                g_free(arch);
+            }
+            pstrcat(target_xml, sizeof(target_xml), "<xi:include href=\"");
+            pstrcat(target_xml, sizeof(target_xml), cc->gdb_core_xml_file);
+            pstrcat(target_xml, sizeof(target_xml), "\"/>");
             for (r = cpu->gdb_regs; r; r = r->next) {
             for (r = cpu->gdb_regs; r; r = r->next) {
                 pstrcat(target_xml, sizeof(target_xml), "<xi:include href=\"");
                 pstrcat(target_xml, sizeof(target_xml), "<xi:include href=\"");
                 pstrcat(target_xml, sizeof(target_xml), r->xml);
                 pstrcat(target_xml, sizeof(target_xml), r->xml);

+ 13 - 2
hw/s390x/css.c

@@ -49,6 +49,7 @@ typedef struct IoAdapter {
 
 
 typedef struct ChannelSubSys {
 typedef struct ChannelSubSys {
     QTAILQ_HEAD(, CrwContainer) pending_crws;
     QTAILQ_HEAD(, CrwContainer) pending_crws;
+    bool sei_pending;
     bool do_crw_mchk;
     bool do_crw_mchk;
     bool crws_lost;
     bool crws_lost;
     uint8_t max_cssid;
     uint8_t max_cssid;
@@ -701,7 +702,7 @@ int css_do_csch(SubchDev *sch)
 
 
     /* Trigger the clear function. */
     /* Trigger the clear function. */
     s->ctrl &= ~(SCSW_CTRL_MASK_FCTL | SCSW_CTRL_MASK_ACTL);
     s->ctrl &= ~(SCSW_CTRL_MASK_FCTL | SCSW_CTRL_MASK_ACTL);
-    s->ctrl |= SCSW_FCTL_CLEAR_FUNC | SCSW_FCTL_CLEAR_FUNC;
+    s->ctrl |= SCSW_FCTL_CLEAR_FUNC | SCSW_ACTL_CLEAR_PEND;
 
 
     do_subchannel_work(sch, NULL);
     do_subchannel_work(sch, NULL);
     ret = 0;
     ret = 0;
@@ -1359,7 +1360,15 @@ void css_generate_chp_crws(uint8_t cssid, uint8_t chpid)
 
 
 void css_generate_css_crws(uint8_t cssid)
 void css_generate_css_crws(uint8_t cssid)
 {
 {
-    css_queue_crw(CRW_RSC_CSS, 0, 0, cssid);
+    if (!channel_subsys->sei_pending) {
+        css_queue_crw(CRW_RSC_CSS, 0, 0, cssid);
+    }
+    channel_subsys->sei_pending = true;
+}
+
+void css_clear_sei_pending(void)
+{
+    channel_subsys->sei_pending = false;
 }
 }
 
 
 int css_enable_mcsse(void)
 int css_enable_mcsse(void)
@@ -1509,6 +1518,7 @@ static void css_init(void)
 {
 {
     channel_subsys = g_malloc0(sizeof(*channel_subsys));
     channel_subsys = g_malloc0(sizeof(*channel_subsys));
     QTAILQ_INIT(&channel_subsys->pending_crws);
     QTAILQ_INIT(&channel_subsys->pending_crws);
+    channel_subsys->sei_pending = false;
     channel_subsys->do_crw_mchk = true;
     channel_subsys->do_crw_mchk = true;
     channel_subsys->crws_lost = false;
     channel_subsys->crws_lost = false;
     channel_subsys->chnmon_active = false;
     channel_subsys->chnmon_active = false;
@@ -1561,6 +1571,7 @@ void css_reset(void)
         QTAILQ_REMOVE(&channel_subsys->pending_crws, crw_cont, sibling);
         QTAILQ_REMOVE(&channel_subsys->pending_crws, crw_cont, sibling);
         g_free(crw_cont);
         g_free(crw_cont);
     }
     }
+    channel_subsys->sei_pending = false;
     channel_subsys->do_crw_mchk = true;
     channel_subsys->do_crw_mchk = true;
     channel_subsys->crws_lost = false;
     channel_subsys->crws_lost = false;
 
 

+ 1 - 0
hw/s390x/css.h

@@ -103,6 +103,7 @@ void css_generate_sch_crws(uint8_t cssid, uint8_t ssid, uint16_t schid,
                            int hotplugged, int add);
                            int hotplugged, int add);
 void css_generate_chp_crws(uint8_t cssid, uint8_t chpid);
 void css_generate_chp_crws(uint8_t cssid, uint8_t chpid);
 void css_generate_css_crws(uint8_t cssid);
 void css_generate_css_crws(uint8_t cssid);
+void css_clear_sei_pending(void);
 void css_adapter_interrupt(uint8_t isc);
 void css_adapter_interrupt(uint8_t isc);
 
 
 #define CSS_IO_ADAPTER_VIRTIO 1
 #define CSS_IO_ADAPTER_VIRTIO 1

+ 1 - 1
hw/s390x/s390-skeys.c

@@ -237,7 +237,7 @@ static const TypeInfo qemu_s390_skeys_info = {
     .instance_init = qemu_s390_skeys_init,
     .instance_init = qemu_s390_skeys_init,
     .instance_size = sizeof(QEMUS390SKeysState),
     .instance_size = sizeof(QEMUS390SKeysState),
     .class_init    = qemu_s390_skeys_class_init,
     .class_init    = qemu_s390_skeys_class_init,
-    .instance_size = sizeof(S390SKeysClass),
+    .class_size    = sizeof(S390SKeysClass),
 };
 };
 
 
 static void s390_storage_keys_save(QEMUFile *f, void *opaque)
 static void s390_storage_keys_save(QEMUFile *f, void *opaque)

+ 6 - 2
hw/s390x/sclp.c

@@ -465,6 +465,12 @@ static void sclp_realize(DeviceState *dev, Error **errp)
     if (err) {
     if (err) {
         goto out;
         goto out;
     }
     }
+    /*
+     * qdev_device_add searches the sysbus for TYPE_SCLP_EVENTS_BUS. As long
+     * as we can't find a fitting bus via the qom tree, we have to add the
+     * event facility to the sysbus, so e.g. a sclp console can be created.
+     */
+    qdev_set_parent_bus(DEVICE(sclp->event_facility), sysbus_get_default());
 
 
     ret = s390_set_memory_limit(machine->maxram_size, &hw_limit);
     ret = s390_set_memory_limit(machine->maxram_size, &hw_limit);
     if (ret == -E2BIG) {
     if (ret == -E2BIG) {
@@ -533,8 +539,6 @@ static void sclp_init(Object *obj)
 
 
     new = object_new(TYPE_SCLP_EVENT_FACILITY);
     new = object_new(TYPE_SCLP_EVENT_FACILITY);
     object_property_add_child(obj, TYPE_SCLP_EVENT_FACILITY, new, NULL);
     object_property_add_child(obj, TYPE_SCLP_EVENT_FACILITY, new, NULL);
-    /* qdev_device_add searches the sysbus for TYPE_SCLP_EVENTS_BUS */
-    qdev_set_parent_bus(DEVICE(new), sysbus_get_default());
     object_unref(new);
     object_unref(new);
     sclp->event_facility = EVENT_FACILITY(new);
     sclp->event_facility = EVENT_FACILITY(new);
 
 

+ 5 - 9
hw/watchdog/watchdog.c

@@ -29,15 +29,6 @@
 #include "qapi-event.h"
 #include "qapi-event.h"
 #include "hw/nmi.h"
 #include "hw/nmi.h"
 
 
-/* Possible values for action parameter. */
-#define WDT_RESET        1	/* Hard reset. */
-#define WDT_SHUTDOWN     2	/* Shutdown. */
-#define WDT_POWEROFF     3	/* Quit. */
-#define WDT_PAUSE        4	/* Pause. */
-#define WDT_DEBUG        5	/* Prints a message and continues running. */
-#define WDT_NONE         6	/* Do nothing. */
-#define WDT_NMI          7	/* Inject nmi into the guest */
-
 static int watchdog_action = WDT_RESET;
 static int watchdog_action = WDT_RESET;
 static QLIST_HEAD(watchdog_list, WatchdogTimerModel) watchdog_list;
 static QLIST_HEAD(watchdog_list, WatchdogTimerModel) watchdog_list;
 
 
@@ -105,6 +96,11 @@ int select_watchdog_action(const char *p)
     return 0;
     return 0;
 }
 }
 
 
+int get_watchdog_action(void)
+{
+    return watchdog_action;
+}
+
 /* This actually performs the "action" once a watchdog has expired,
 /* This actually performs the "action" once a watchdog has expired,
  * ie. reboot, shutdown, exit, etc.
  * ie. reboot, shutdown, exit, etc.
  */
  */

+ 7 - 0
hw/watchdog/wdt_diag288.c

@@ -51,6 +51,13 @@ static void diag288_timer_expired(void *dev)
 {
 {
     qemu_log_mask(CPU_LOG_RESET, "Watchdog timer expired.\n");
     qemu_log_mask(CPU_LOG_RESET, "Watchdog timer expired.\n");
     watchdog_perform_action();
     watchdog_perform_action();
+    /* Reset the watchdog only if the guest was notified about expiry. */
+    switch (get_watchdog_action()) {
+    case WDT_DEBUG:
+    case WDT_NONE:
+    case WDT_PAUSE:
+         return;
+    }
     wdt_diag288_reset(dev);
     wdt_diag288_reset(dev);
 }
 }
 
 

+ 3 - 0
include/qom/cpu.h

@@ -120,6 +120,8 @@ struct TranslationBlock;
  * @gdb_core_xml_file: File name for core registers GDB XML description.
  * @gdb_core_xml_file: File name for core registers GDB XML description.
  * @gdb_stop_before_watchpoint: Indicates whether GDB expects the CPU to stop
  * @gdb_stop_before_watchpoint: Indicates whether GDB expects the CPU to stop
  *           before the insn which triggers a watchpoint rather than after it.
  *           before the insn which triggers a watchpoint rather than after it.
+ * @gdb_arch_name: Optional callback that returns the architecture name known
+ * to GDB. The caller must free the returned string with g_free.
  * @cpu_exec_enter: Callback for cpu_exec preparation.
  * @cpu_exec_enter: Callback for cpu_exec preparation.
  * @cpu_exec_exit: Callback for cpu_exec cleanup.
  * @cpu_exec_exit: Callback for cpu_exec cleanup.
  * @cpu_exec_interrupt: Callback for processing interrupts in cpu_exec.
  * @cpu_exec_interrupt: Callback for processing interrupts in cpu_exec.
@@ -177,6 +179,7 @@ typedef struct CPUClass {
     const struct VMStateDescription *vmsd;
     const struct VMStateDescription *vmsd;
     int gdb_num_core_regs;
     int gdb_num_core_regs;
     const char *gdb_core_xml_file;
     const char *gdb_core_xml_file;
+    gchar * (*gdb_arch_name)(CPUState *cpu);
     bool gdb_stop_before_watchpoint;
     bool gdb_stop_before_watchpoint;
 
 
     void (*cpu_exec_enter)(CPUState *cpu);
     void (*cpu_exec_enter)(CPUState *cpu);

+ 10 - 0
include/sysemu/watchdog.h

@@ -24,6 +24,15 @@
 
 
 #include "qemu/queue.h"
 #include "qemu/queue.h"
 
 
+/* Possible values for action parameter. */
+#define WDT_RESET        1      /* Hard reset. */
+#define WDT_SHUTDOWN     2      /* Shutdown. */
+#define WDT_POWEROFF     3      /* Quit. */
+#define WDT_PAUSE        4      /* Pause. */
+#define WDT_DEBUG        5      /* Prints a message and continues running. */
+#define WDT_NONE         6      /* Do nothing. */
+#define WDT_NMI          7      /* Inject nmi into the guest. */
+
 struct WatchdogTimerModel {
 struct WatchdogTimerModel {
     QLIST_ENTRY(WatchdogTimerModel) entry;
     QLIST_ENTRY(WatchdogTimerModel) entry;
 
 
@@ -37,6 +46,7 @@ typedef struct WatchdogTimerModel WatchdogTimerModel;
 /* in hw/watchdog.c */
 /* in hw/watchdog.c */
 int select_watchdog(const char *p);
 int select_watchdog(const char *p);
 int select_watchdog_action(const char *action);
 int select_watchdog_action(const char *action);
+int get_watchdog_action(void);
 void watchdog_add_model(WatchdogTimerModel *model);
 void watchdog_add_model(WatchdogTimerModel *model);
 void watchdog_perform_action(void);
 void watchdog_perform_action(void);
 
 

+ 12 - 0
target-arm/cpu.c

@@ -1426,6 +1426,17 @@ static int arm_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw,
 }
 }
 #endif
 #endif
 
 
+static gchar *arm_gdb_arch_name(CPUState *cs)
+{
+    ARMCPU *cpu = ARM_CPU(cs);
+    CPUARMState *env = &cpu->env;
+
+    if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
+        return g_strdup("iwmmxt");
+    }
+    return g_strdup("arm");
+}
+
 static void arm_cpu_class_init(ObjectClass *oc, void *data)
 static void arm_cpu_class_init(ObjectClass *oc, void *data)
 {
 {
     ARMCPUClass *acc = ARM_CPU_CLASS(oc);
     ARMCPUClass *acc = ARM_CPU_CLASS(oc);
@@ -1460,6 +1471,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
 #endif
 #endif
     cc->gdb_num_core_regs = 26;
     cc->gdb_num_core_regs = 26;
     cc->gdb_core_xml_file = "arm-core.xml";
     cc->gdb_core_xml_file = "arm-core.xml";
+    cc->gdb_arch_name = arm_gdb_arch_name;
     cc->gdb_stop_before_watchpoint = true;
     cc->gdb_stop_before_watchpoint = true;
     cc->debug_excp_handler = arm_debug_excp_handler;
     cc->debug_excp_handler = arm_debug_excp_handler;
 
 

+ 6 - 0
target-arm/cpu64.c

@@ -287,6 +287,11 @@ static void aarch64_cpu_set_pc(CPUState *cs, vaddr value)
     }
     }
 }
 }
 
 
+static gchar *aarch64_gdb_arch_name(CPUState *cs)
+{
+    return g_strdup("aarch64");
+}
+
 static void aarch64_cpu_class_init(ObjectClass *oc, void *data)
 static void aarch64_cpu_class_init(ObjectClass *oc, void *data)
 {
 {
     CPUClass *cc = CPU_CLASS(oc);
     CPUClass *cc = CPU_CLASS(oc);
@@ -297,6 +302,7 @@ static void aarch64_cpu_class_init(ObjectClass *oc, void *data)
     cc->gdb_write_register = aarch64_cpu_gdb_write_register;
     cc->gdb_write_register = aarch64_cpu_gdb_write_register;
     cc->gdb_num_core_regs = 34;
     cc->gdb_num_core_regs = 34;
     cc->gdb_core_xml_file = "aarch64-core.xml";
     cc->gdb_core_xml_file = "aarch64-core.xml";
+    cc->gdb_arch_name = aarch64_gdb_arch_name;
 }
 }
 
 
 static void aarch64_cpu_register(const ARMCPUInfo *info)
 static void aarch64_cpu_register(const ARMCPUInfo *info)

+ 10 - 0
target-ppc/translate_init.c

@@ -9681,6 +9681,15 @@ static bool ppc_pvr_match_default(PowerPCCPUClass *pcc, uint32_t pvr)
     return pcc->pvr == pvr;
     return pcc->pvr == pvr;
 }
 }
 
 
+static gchar *ppc_gdb_arch_name(CPUState *cs)
+{
+#if defined(TARGET_PPC64)
+    return g_strdup("powerpc:common64");
+#else
+    return g_strdup("powerpc:common");
+#endif
+}
+
 static void ppc_cpu_class_init(ObjectClass *oc, void *data)
 static void ppc_cpu_class_init(ObjectClass *oc, void *data)
 {
 {
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
@@ -9724,6 +9733,7 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data)
     cc->gdb_num_core_regs = 71 + 32;
     cc->gdb_num_core_regs = 71 + 32;
 #endif
 #endif
 
 
+    cc->gdb_arch_name = ppc_gdb_arch_name;
 #if defined(TARGET_PPC64)
 #if defined(TARGET_PPC64)
     cc->gdb_core_xml_file = "power64-core.xml";
     cc->gdb_core_xml_file = "power64-core.xml";
 #else
 #else

+ 6 - 0
target-s390x/cpu.c

@@ -325,6 +325,11 @@ unsigned int s390_cpu_set_state(uint8_t cpu_state, S390CPU *cpu)
 }
 }
 #endif
 #endif
 
 
+static gchar *s390_gdb_arch_name(CPUState *cs)
+{
+    return g_strdup("s390:64-bit");
+}
+
 static void s390_cpu_class_init(ObjectClass *oc, void *data)
 static void s390_cpu_class_init(ObjectClass *oc, void *data)
 {
 {
     S390CPUClass *scc = S390_CPU_CLASS(oc);
     S390CPUClass *scc = S390_CPU_CLASS(oc);
@@ -360,6 +365,7 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data)
 
 
     cc->gdb_num_core_regs = S390_NUM_CORE_REGS;
     cc->gdb_num_core_regs = S390_NUM_CORE_REGS;
     cc->gdb_core_xml_file = "s390x-core64.xml";
     cc->gdb_core_xml_file = "s390x-core64.xml";
+    cc->gdb_arch_name = s390_gdb_arch_name;
 
 
     /*
     /*
      * Reason: s390_cpu_initfn() calls cpu_exec_init(), which saves
      * Reason: s390_cpu_initfn() calls cpu_exec_init(), which saves

+ 3 - 2
target-s390x/helper.c

@@ -162,8 +162,9 @@ hwaddr s390_cpu_get_phys_page_debug(CPUState *cs, vaddr vaddr)
         vaddr &= 0x7fffffff;
         vaddr &= 0x7fffffff;
     }
     }
 
 
-    mmu_translate(env, vaddr, MMU_INST_FETCH, asc, &raddr, &prot, false);
-
+    if (mmu_translate(env, vaddr, MMU_INST_FETCH, asc, &raddr, &prot, false)) {
+        return -1;
+    }
     return raddr;
     return raddr;
 }
 }
 
 

+ 3 - 1
target-s390x/ioinst.c

@@ -614,9 +614,11 @@ static void ioinst_handle_chsc_sei(ChscReq *req, ChscResp *res)
             (*res_flags) |= 0x80;
             (*res_flags) |= 0x80;
         } else {
         } else {
             (*res_flags) &= ~0x80;
             (*res_flags) &= ~0x80;
+            css_clear_sei_pending();
         }
         }
     } else {
     } else {
-        res->code = cpu_to_be16(0x0004);
+        res->code = cpu_to_be16(0x0005);
+        res->len = cpu_to_be16(CHSC_MIN_RESP_LEN);
     }
     }
 }
 }
 
 

+ 2 - 2
target-s390x/machine.c

@@ -48,7 +48,7 @@ static inline bool fpu_needed(void *opaque)
     return true;
     return true;
 }
 }
 
 
-const VMStateDescription vmstate_fpu = {
+static const VMStateDescription vmstate_fpu = {
     .name = "cpu/fpu",
     .name = "cpu/fpu",
     .version_id = 1,
     .version_id = 1,
     .minimum_version_id = 1,
     .minimum_version_id = 1,
@@ -75,7 +75,7 @@ const VMStateDescription vmstate_fpu = {
     }
     }
 };
 };
 
 
-const VMStateDescription vmstate_vregs = {
+static const VMStateDescription vmstate_vregs = {
     .name = "cpu/vregs",
     .name = "cpu/vregs",
     .version_id = 1,
     .version_id = 1,
     .minimum_version_id = 1,
     .minimum_version_id = 1,