From 946e55f3c7ff3eb9fa49e57e15c209858aaa9ac9 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Mon, 25 Apr 2016 10:37:23 +0200 Subject: [PATCH 01/20] s390x: add compat machine for 2.7 Also add some of the option cascading we were missing. Signed-off-by: Cornelia Huck --- hw/s390x/s390-virtio-ccw.c | 21 ++++++++++++++++++++- include/hw/compat.h | 3 +++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index e3df9c78ba..57f10c5ca1 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -299,7 +299,11 @@ static const TypeInfo ccw_machine_info = { } \ type_init(ccw_machine_register_##suffix) +#define CCW_COMPAT_2_6 \ + HW_COMPAT_2_6 + #define CCW_COMPAT_2_5 \ + CCW_COMPAT_2_6 \ HW_COMPAT_2_5 #define CCW_COMPAT_2_4 \ @@ -343,21 +347,35 @@ static const TypeInfo ccw_machine_info = { .value = "0",\ }, +static void ccw_machine_2_7_instance_options(MachineState *machine) +{ +} + +static void ccw_machine_2_7_class_options(MachineClass *mc) +{ +} +DEFINE_CCW_MACHINE(2_7, "2.7", true); + static void ccw_machine_2_6_instance_options(MachineState *machine) { + ccw_machine_2_7_instance_options(machine); } static void ccw_machine_2_6_class_options(MachineClass *mc) { + ccw_machine_2_7_class_options(mc); + SET_MACHINE_COMPAT(mc, CCW_COMPAT_2_6); } -DEFINE_CCW_MACHINE(2_6, "2.6", true); +DEFINE_CCW_MACHINE(2_6, "2.6", false); static void ccw_machine_2_5_instance_options(MachineState *machine) { + ccw_machine_2_6_instance_options(machine); } static void ccw_machine_2_5_class_options(MachineClass *mc) { + ccw_machine_2_6_class_options(mc); SET_MACHINE_COMPAT(mc, CCW_COMPAT_2_5); } DEFINE_CCW_MACHINE(2_5, "2.5", false); @@ -369,6 +387,7 @@ static void ccw_machine_2_4_instance_options(MachineState *machine) static void ccw_machine_2_4_class_options(MachineClass *mc) { + ccw_machine_2_5_class_options(mc); SET_MACHINE_COMPAT(mc, CCW_COMPAT_2_4); } DEFINE_CCW_MACHINE(2_4, "2.4", false); diff --git a/include/hw/compat.h b/include/hw/compat.h index a5dbbf8984..636befedb4 100644 --- a/include/hw/compat.h +++ b/include/hw/compat.h @@ -1,6 +1,9 @@ #ifndef HW_COMPAT_H #define HW_COMPAT_H +#define HW_COMPAT_2_6 \ + /* empty */ + #define HW_COMPAT_2_5 \ {\ .driver = "isa-fdc",\ From 9700230b0d6d68d8650206ffd10d132219678db1 Mon Sep 17 00:00:00 2001 From: Fan Zhang Date: Wed, 9 Mar 2016 13:11:17 +0100 Subject: [PATCH 02/20] s390x: enable runtime instrumentation Introduce run-time-instrumentation support when running under kvm for virtio-ccw 2.7 machine and make sure older machines can not enable it. The new ri_allowed field in the s390MachineClass serves as an indicator whether the feature can be used by the machine and should therefore be activated if available. riccb_needed() is used to check whether riccb is needed or not in live migration. Signed-off-by: Fan Zhang Signed-off-by: Cornelia Huck --- hw/s390x/s390-virtio-ccw.c | 20 ++++++++++++++++++++ include/hw/s390x/s390-virtio-ccw.h | 4 ++++ target-s390x/cpu.h | 18 ++++++++++++++++++ target-s390x/kvm.c | 21 +++++++++++++++++++++ target-s390x/machine.c | 12 ++++++++++++ 5 files changed, 75 insertions(+) diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index 57f10c5ca1..1390a98391 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -190,7 +190,9 @@ static void ccw_machine_class_init(ObjectClass *oc, void *data) MachineClass *mc = MACHINE_CLASS(oc); NMIClass *nc = NMI_CLASS(oc); HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); + S390CcwMachineClass *s390mc = S390_MACHINE_CLASS(mc); + s390mc->ri_allowed = true; mc->init = ccw_init; mc->reset = s390_machine_reset; mc->hot_add_cpu = s390_hot_add_cpu; @@ -237,6 +239,20 @@ static inline void machine_set_dea_key_wrap(Object *obj, bool value, ms->dea_key_wrap = value; } +bool ri_allowed(void) +{ + if (kvm_enabled()) { + MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine()); + if (object_class_dynamic_cast(OBJECT_CLASS(mc), + TYPE_S390_CCW_MACHINE)) { + S390CcwMachineClass *s390mc = S390_MACHINE_CLASS(mc); + + return s390mc->ri_allowed; + } + } + return 0; +} + static inline void s390_machine_initfn(Object *obj) { object_property_add_bool(obj, "aes-key-wrap", @@ -262,6 +278,7 @@ static const TypeInfo ccw_machine_info = { .abstract = true, .instance_size = sizeof(S390CcwMachineState), .instance_init = s390_machine_initfn, + .class_size = sizeof(S390CcwMachineClass), .class_init = ccw_machine_class_init, .interfaces = (InterfaceInfo[]) { { TYPE_NMI }, @@ -363,6 +380,9 @@ static void ccw_machine_2_6_instance_options(MachineState *machine) static void ccw_machine_2_6_class_options(MachineClass *mc) { + S390CcwMachineClass *s390mc = S390_MACHINE_CLASS(mc); + + s390mc->ri_allowed = false; ccw_machine_2_7_class_options(mc); SET_MACHINE_COMPAT(mc, CCW_COMPAT_2_6); } diff --git a/include/hw/s390x/s390-virtio-ccw.h b/include/hw/s390x/s390-virtio-ccw.h index ab08332fe1..a0c1fc8083 100644 --- a/include/hw/s390x/s390-virtio-ccw.h +++ b/include/hw/s390x/s390-virtio-ccw.h @@ -35,6 +35,10 @@ typedef struct S390CcwMachineClass { MachineClass parent_class; /*< public >*/ + bool ri_allowed; } S390CcwMachineClass; +/* runtime-instrumentation allowed by the machine */ +bool ri_allowed(void); + #endif diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index 07f76ad884..996b79023e 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -135,6 +135,8 @@ typedef struct CPUS390XState { uint64_t gbea; uint64_t pp; + uint8_t riccb[64]; + CPU_COMMON /* reset does memset(0) up to here */ @@ -1159,6 +1161,7 @@ void kvm_s390_reset_vcpu(S390CPU *cpu); int kvm_s390_set_mem_limit(KVMState *s, uint64_t new_limit, uint64_t *hw_limit); void kvm_s390_vcpu_interrupt_pre_save(S390CPU *cpu); int kvm_s390_vcpu_interrupt_post_load(S390CPU *cpu); +int kvm_s390_get_ri(void); void kvm_s390_crypto_reset(void); #else static inline void kvm_s390_io_interrupt(uint16_t subchannel_id, @@ -1209,6 +1212,10 @@ static inline int kvm_s390_vcpu_interrupt_post_load(S390CPU *cpu) { return 0; } +static inline int kvm_s390_get_ri(void) +{ + return 0; +} static inline void kvm_s390_crypto_reset(void) { } @@ -1272,11 +1279,22 @@ static inline bool vregs_needed(void *opaque) } return 0; } +static inline bool riccb_needed(void *opaque) +{ + if (kvm_enabled()) { + return kvm_s390_get_ri(); + } + return 0; +} #else static inline bool vregs_needed(void *opaque) { return 0; } +static inline bool riccb_needed(void *opaque) +{ + return 0; +} #endif /* machine check interruption code */ diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index e1859cae04..55ae6d3304 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -46,6 +46,7 @@ #include "hw/s390x/ipl.h" #include "hw/s390x/ebcdic.h" #include "exec/memattrs.h" +#include "hw/s390x/s390-virtio-ccw.h" /* #define DEBUG_KVM */ @@ -135,6 +136,7 @@ static int cap_sync_regs; static int cap_async_pf; static int cap_mem_op; static int cap_s390_irq; +static int cap_ri; static void *legacy_s390_alloc(size_t size, uint64_t *align); @@ -270,6 +272,11 @@ int kvm_arch_init(MachineState *ms, KVMState *s) kvm_vm_enable_cap(s, KVM_CAP_S390_USER_SIGP, 0); kvm_vm_enable_cap(s, KVM_CAP_S390_VECTOR_REGISTERS, 0); kvm_vm_enable_cap(s, KVM_CAP_S390_USER_STSI, 0); + if (ri_allowed()) { + if (kvm_vm_enable_cap(s, KVM_CAP_S390_RI, 0) == 0) { + cap_ri = 1; + } + } return 0; } @@ -386,6 +393,11 @@ int kvm_arch_put_registers(CPUState *cs, int level) kvm_set_one_reg(cs, KVM_REG_S390_PP, &env->pp); } + if (can_sync_regs(cs, KVM_SYNC_RICCB)) { + memcpy(cs->kvm_run->s.regs.riccb, env->riccb, 64); + cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_RICCB; + } + /* pfault parameters */ if (can_sync_regs(cs, KVM_SYNC_PFAULT)) { cs->kvm_run->s.regs.pft = env->pfault_token; @@ -528,6 +540,10 @@ int kvm_arch_get_registers(CPUState *cs) kvm_get_one_reg(cs, KVM_REG_S390_PP, &env->pp); } + if (can_sync_regs(cs, KVM_SYNC_RICCB)) { + memcpy(env->riccb, cs->kvm_run->s.regs.riccb, 64); + } + /* pfault parameters */ if (can_sync_regs(cs, KVM_SYNC_PFAULT)) { env->pfault_token = cs->kvm_run->s.regs.pft; @@ -2136,6 +2152,11 @@ int kvm_s390_get_memslot_count(KVMState *s) return kvm_check_extension(s, KVM_CAP_NR_MEMSLOTS); } +int kvm_s390_get_ri(void) +{ + return cap_ri; +} + int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state) { struct kvm_mp_state mp_state = {}; diff --git a/target-s390x/machine.c b/target-s390x/machine.c index 6b2609054b..a30b16fe3d 100644 --- a/target-s390x/machine.c +++ b/target-s390x/machine.c @@ -135,6 +135,17 @@ static const VMStateDescription vmstate_vregs = { } }; +const VMStateDescription vmstate_riccb = { + .name = "cpu/riccb", + .version_id = 1, + .minimum_version_id = 1, + .needed = riccb_needed, + .fields = (VMStateField[]) { + VMSTATE_UINT8_ARRAY(env.riccb, S390CPU, 64), + VMSTATE_END_OF_LIST() + } +}; + const VMStateDescription vmstate_s390_cpu = { .name = "cpu", .post_load = cpu_post_load, @@ -166,6 +177,7 @@ const VMStateDescription vmstate_s390_cpu = { .subsections = (const VMStateDescription*[]) { &vmstate_fpu, &vmstate_vregs, + &vmstate_riccb, NULL }, }; From 04ca4b92ecb33703b03b8501bfb3d8b0c551e2e5 Mon Sep 17 00:00:00 2001 From: Alexander Yarygin Date: Mon, 13 Jul 2015 15:04:36 +0300 Subject: [PATCH 03/20] s390x/ipl: Extend the IplParameterBlock struct The IplParameterBlock struct currently has only 200 bytes filled, but it can be up to 4K. This patch converts the struct to union with a fully populated struct inside it and second struct with old values. For compatibility reasons we disable migration of the extended iplb field for pre-2.7 machines. Also a guest still can read/write only the first 200 bytes of IPLB for now. Signed-off-by: Alexander Yarygin Reviewed-by: David Hildenbrand Acked-by: Christian Borntraeger Signed-off-by: Cornelia Huck --- hw/s390x/ipl.c | 24 +++++++++++++++ hw/s390x/ipl.h | 61 ++++++++++++++++++++++++++++++++++---- hw/s390x/s390-virtio-ccw.c | 8 ++++- target-s390x/misc_helper.c | 7 ++--- 4 files changed, 90 insertions(+), 10 deletions(-) diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c index f104200273..236e2c937f 100644 --- a/hw/s390x/ipl.c +++ b/hw/s390x/ipl.c @@ -30,6 +30,24 @@ #define ZIPL_IMAGE_START 0x009000UL #define IPL_PSW_MASK (PSW_MASK_32 | PSW_MASK_64) +static bool iplb_extended_needed(void *opaque) +{ + S390IPLState *ipl = S390_IPL(object_resolve_path(TYPE_S390_IPL, NULL)); + + return ipl->iplbext_migration; +} + +static const VMStateDescription vmstate_iplb_extended = { + .name = "ipl/iplb_extended", + .version_id = 0, + .minimum_version_id = 0, + .needed = iplb_extended_needed, + .fields = (VMStateField[]) { + VMSTATE_UINT8_ARRAY(reserved_ext, IplParameterBlock, 4096 - 200), + VMSTATE_END_OF_LIST() + } +}; + static const VMStateDescription vmstate_iplb = { .name = "ipl/iplb", .version_id = 0, @@ -39,6 +57,10 @@ static const VMStateDescription vmstate_iplb = { VMSTATE_UINT16(devno, IplParameterBlock), VMSTATE_UINT8_ARRAY(reserved2, IplParameterBlock, 88), VMSTATE_END_OF_LIST() + }, + .subsections = (const VMStateDescription*[]) { + &vmstate_iplb_extended, + NULL } }; @@ -181,6 +203,8 @@ static Property s390_ipl_properties[] = { DEFINE_PROP_STRING("cmdline", S390IPLState, cmdline), DEFINE_PROP_STRING("firmware", S390IPLState, firmware), DEFINE_PROP_BOOL("enforce_bios", S390IPLState, enforce_bios, false), + DEFINE_PROP_BOOL("iplbext_migration", S390IPLState, iplbext_migration, + true), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h index 6b48ed7b93..73b86e3f81 100644 --- a/hw/s390x/ipl.h +++ b/hw/s390x/ipl.h @@ -15,11 +15,59 @@ #include "hw/qdev.h" #include "cpu.h" -typedef struct IplParameterBlock { - uint8_t reserved1[110]; - uint16_t devno; - uint8_t reserved2[88]; -} IplParameterBlock; +struct IplBlockCcw { + uint8_t reserved0[86]; + uint16_t devno; + uint8_t vm_flags; + uint8_t reserved3[3]; + uint32_t vm_parm_len; + uint8_t nss_name[8]; + uint8_t vm_parm[64]; + uint8_t reserved4[8]; +} QEMU_PACKED; +typedef struct IplBlockCcw IplBlockCcw; + +struct IplBlockFcp { + uint8_t reserved1[305 - 1]; + uint8_t opt; + uint8_t reserved2[3]; + uint16_t reserved3; + uint16_t devno; + uint8_t reserved4[4]; + uint64_t wwpn; + uint64_t lun; + uint32_t bootprog; + uint8_t reserved5[12]; + uint64_t br_lba; + uint32_t scp_data_len; + uint8_t reserved6[260]; + uint8_t scp_data[]; +} QEMU_PACKED; +typedef struct IplBlockFcp IplBlockFcp; + +union IplParameterBlock { + struct { + uint32_t len; + uint8_t reserved0[3]; + uint8_t version; + uint32_t blk0_len; + uint8_t pbt; + uint8_t flags; + uint16_t reserved01; + uint8_t loadparm[8]; + union { + IplBlockCcw ccw; + IplBlockFcp fcp; + }; + } QEMU_PACKED; + struct { + uint8_t reserved1[110]; + uint16_t devno; + uint8_t reserved2[88]; + uint8_t reserved_ext[4096 - 200]; + } QEMU_PACKED; +} QEMU_PACKED; +typedef union IplParameterBlock IplParameterBlock; void s390_ipl_update_diag308(IplParameterBlock *iplb); void s390_ipl_prepare_cpu(S390CPU *cpu); @@ -47,7 +95,10 @@ struct S390IPLState { uint8_t cssid; uint8_t ssid; uint16_t devno; + bool iplbext_migration; }; typedef struct S390IPLState S390IPLState; +#define S390_IPLB_MIN_CCW_LEN 200 + #endif diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index 1390a98391..4456fce9f1 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -25,6 +25,7 @@ #include "s390-pci-bus.h" #include "hw/s390x/storage-keys.h" #include "hw/compat.h" +#include "ipl.h" #include "hw/s390x/s390-virtio-ccw.h" static const char *const reset_dev_types[] = { @@ -317,7 +318,12 @@ static const TypeInfo ccw_machine_info = { type_init(ccw_machine_register_##suffix) #define CCW_COMPAT_2_6 \ - HW_COMPAT_2_6 + HW_COMPAT_2_6 \ + {\ + .driver = TYPE_S390_IPL,\ + .property = "iplbext_migration",\ + .value = "off",\ + }, #define CCW_COMPAT_2_5 \ CCW_COMPAT_2_6 \ diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c index 71cbe34e05..fab7f87a8f 100644 --- a/target-s390x/misc_helper.c +++ b/target-s390x/misc_helper.c @@ -232,8 +232,8 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3) program_interrupt(env, PGM_ADDRESSING, ILEN_LATER_INC); return; } - iplb = g_malloc0(sizeof(struct IplParameterBlock)); - cpu_physical_memory_read(addr, iplb, sizeof(struct IplParameterBlock)); + iplb = g_malloc0(sizeof(IplParameterBlock)); + cpu_physical_memory_read(addr, iplb, S390_IPLB_MIN_CCW_LEN); s390_ipl_update_diag308(iplb); env->regs[r1 + 1] = DIAG_308_RC_OK; g_free(iplb); @@ -250,8 +250,7 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3) } iplb = s390_ipl_get_iplb(); if (iplb) { - cpu_physical_memory_write(addr, iplb, - sizeof(struct IplParameterBlock)); + cpu_physical_memory_write(addr, iplb, S390_IPLB_MIN_CCW_LEN); env->regs[r1 + 1] = DIAG_308_RC_OK; } else { env->regs[r1 + 1] = DIAG_308_RC_NO_CONF; From 9946a9113cf5d84c9381342100343aa97f736ee0 Mon Sep 17 00:00:00 2001 From: Alexander Yarygin Date: Mon, 10 Aug 2015 13:57:03 +0300 Subject: [PATCH 04/20] s390x/ipl: Add type and length checks for IplParameterBlock values We can check for valid type and lengths of the IplParameterBlock fields when receiving the struct from the guest. Length of the IplParameterBlock can be less than 4K. To play safe we can read and write only required amount of data. Signed-off-by: Alexander Yarygin Reviewed-by: David Hildenband Acked-by: Christian Borntraeger Signed-off-by: Cornelia Huck --- hw/s390x/ipl.h | 21 +++++++++++++++++++++ target-s390x/misc_helper.c | 17 +++++++++++++++-- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h index 73b86e3f81..08f1d5c385 100644 --- a/hw/s390x/ipl.h +++ b/hw/s390x/ipl.h @@ -99,6 +99,27 @@ struct S390IPLState { }; typedef struct S390IPLState S390IPLState; +#define S390_IPL_TYPE_FCP 0x00 +#define S390_IPL_TYPE_CCW 0x02 + #define S390_IPLB_MIN_CCW_LEN 200 +#define S390_IPLB_MIN_FCP_LEN 384 + +static inline bool iplb_valid_len(IplParameterBlock *iplb) +{ + return be32_to_cpu(iplb->len) <= sizeof(IplParameterBlock); +} + +static inline bool iplb_valid_ccw(IplParameterBlock *iplb) +{ + return be32_to_cpu(iplb->len) >= S390_IPLB_MIN_CCW_LEN && + iplb->pbt == S390_IPL_TYPE_CCW; +} + +static inline bool iplb_valid_fcp(IplParameterBlock *iplb) +{ + return be32_to_cpu(iplb->len) >= S390_IPLB_MIN_FCP_LEN && + iplb->pbt == S390_IPL_TYPE_FCP; +} #endif diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c index fab7f87a8f..462cfc85fc 100644 --- a/target-s390x/misc_helper.c +++ b/target-s390x/misc_helper.c @@ -233,9 +233,22 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3) return; } iplb = g_malloc0(sizeof(IplParameterBlock)); - cpu_physical_memory_read(addr, iplb, S390_IPLB_MIN_CCW_LEN); + cpu_physical_memory_read(addr, iplb, sizeof(iplb->len)); + if (!iplb_valid_len(iplb)) { + env->regs[r1 + 1] = DIAG_308_RC_INVALID; + goto out; + } + + cpu_physical_memory_read(addr, iplb, be32_to_cpu(iplb->len)); + + if (!iplb_valid_ccw(iplb) && !iplb_valid_fcp(iplb)) { + env->regs[r1 + 1] = DIAG_308_RC_INVALID; + goto out; + } + s390_ipl_update_diag308(iplb); env->regs[r1 + 1] = DIAG_308_RC_OK; +out: g_free(iplb); return; case 6: @@ -250,7 +263,7 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3) } iplb = s390_ipl_get_iplb(); if (iplb) { - cpu_physical_memory_write(addr, iplb, S390_IPLB_MIN_CCW_LEN); + cpu_physical_memory_write(addr, iplb, be32_to_cpu(iplb->len)); env->regs[r1 + 1] = DIAG_308_RC_OK; } else { env->regs[r1 + 1] = DIAG_308_RC_NO_CONF; From 6aed958978ba9e32301b131e1c5dcadcf952a1ed Mon Sep 17 00:00:00 2001 From: Alexander Yarygin Date: Tue, 21 Jul 2015 14:10:39 +0300 Subject: [PATCH 05/20] s390x/ipl: Provide ipl parameter block Right now we return the ipl parameter block only if the guest specified one. Let's fill in the parameter block when bootindex parameter is available and not booting from an external kernel. Signed-off-by: Alexander Yarygin Reviewed-by: David Hildenbrand Signed-off-by: Cornelia Huck --- hw/s390x/ipl.c | 7 +++++++ hw/s390x/ipl.h | 1 + 2 files changed, 8 insertions(+) diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c index 236e2c937f..9a73820fd1 100644 --- a/hw/s390x/ipl.c +++ b/hw/s390x/ipl.c @@ -238,6 +238,12 @@ static uint64_t s390_update_iplstate(S390IPLState *ipl) ipl->cssid = ccw_dev->sch->cssid; ipl->ssid = ccw_dev->sch->ssid; ipl->devno = ccw_dev->sch->devno; + ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_CCW_LEN); + ipl->iplb.blk0_len = + cpu_to_be32(S390_IPLB_MIN_CCW_LEN - S390_IPLB_HEADER_LEN); + ipl->iplb.pbt = S390_IPL_TYPE_CCW; + ipl->iplb.ccw.devno = cpu_to_be16(ccw_dev->sch->devno); + ipl->iplb_valid = true; goto out; } } @@ -292,6 +298,7 @@ static void s390_ipl_reset(DeviceState *dev) if (!ipl->reipl_requested) { ipl->iplb_valid = false; + memset(&ipl->iplb, 0, sizeof(IplParameterBlock)); } ipl->reipl_requested = false; } diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h index 08f1d5c385..0b7f6cbecb 100644 --- a/hw/s390x/ipl.h +++ b/hw/s390x/ipl.h @@ -102,6 +102,7 @@ typedef struct S390IPLState S390IPLState; #define S390_IPL_TYPE_FCP 0x00 #define S390_IPL_TYPE_CCW 0x02 +#define S390_IPLB_HEADER_LEN 8 #define S390_IPLB_MIN_CCW_LEN 200 #define S390_IPLB_MIN_FCP_LEN 384 From 3041e3bead8df443e5212ae8a608cbec81bc90bd Mon Sep 17 00:00:00 2001 From: Alexander Yarygin Date: Thu, 1 Oct 2015 20:21:33 +0300 Subject: [PATCH 06/20] s390x/ipl: Add ssid field to IplParameterBlock Add the ssid field to the ipl parameter block struct and fill it when necessary so the guest can use it. Signed-off-by: Alexander Yarygin Reviewed-by: David Hildenbrand Signed-off-by: Cornelia Huck --- hw/s390x/ipl.c | 1 + hw/s390x/ipl.h | 3 ++- target-s390x/ioinst.c | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c index 9a73820fd1..2da0f1eaef 100644 --- a/hw/s390x/ipl.c +++ b/hw/s390x/ipl.c @@ -243,6 +243,7 @@ static uint64_t s390_update_iplstate(S390IPLState *ipl) cpu_to_be32(S390_IPLB_MIN_CCW_LEN - S390_IPLB_HEADER_LEN); ipl->iplb.pbt = S390_IPL_TYPE_CCW; ipl->iplb.ccw.devno = cpu_to_be16(ccw_dev->sch->devno); + ipl->iplb.ccw.ssid = ccw_dev->sch->ssid & 3; ipl->iplb_valid = true; goto out; } diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h index 0b7f6cbecb..9aa4d942a7 100644 --- a/hw/s390x/ipl.h +++ b/hw/s390x/ipl.h @@ -16,7 +16,8 @@ #include "cpu.h" struct IplBlockCcw { - uint8_t reserved0[86]; + uint8_t reserved0[85]; + uint8_t ssid; uint16_t devno; uint8_t vm_flags; uint8_t reserved3[3]; diff --git a/target-s390x/ioinst.c b/target-s390x/ioinst.c index 142ff93844..f5498aa023 100644 --- a/target-s390x/ioinst.c +++ b/target-s390x/ioinst.c @@ -509,6 +509,7 @@ static void ioinst_handle_chsc_scsc(ChscReq *req, ChscResp *res) general_chars[0] = cpu_to_be32(0x03000000); general_chars[1] = cpu_to_be32(0x00059000); + general_chars[3] = cpu_to_be32(0x00080000); chsc_chars[0] = cpu_to_be32(0x40000000); chsc_chars[3] = cpu_to_be32(0x00040000); From d046c51dad3bda03e4c012c83411842b92271542 Mon Sep 17 00:00:00 2001 From: Alexander Yarygin Date: Fri, 31 Jul 2015 17:04:51 +0300 Subject: [PATCH 07/20] pc-bios/s390-ccw: Get device address via diag 308/6 To IPL from a device, pc-bios receives from qemu a device address via general register 7. The better way to do it is to use diag308/6 instruction which returns so called "IplParameterBlock". IplParameterBlock contains the device address for IPL and additional parameters that can be used by pc-bios. This patch allows pc-bios to get device address via diag308/6 and doesn't use gr7 passed boot information anymore. Signed-off-by: Alexander Yarygin Reviewed-by: David Hildenbrand Signed-off-by: Cornelia Huck --- pc-bios/s390-ccw/iplb.h | 79 +++++++++++++++++++++++++++++++++++++ pc-bios/s390-ccw/main.c | 25 +++++++----- pc-bios/s390-ccw/s390-ccw.h | 2 +- pc-bios/s390-ccw/start.S | 2 - 4 files changed, 95 insertions(+), 13 deletions(-) create mode 100644 pc-bios/s390-ccw/iplb.h diff --git a/pc-bios/s390-ccw/iplb.h b/pc-bios/s390-ccw/iplb.h new file mode 100644 index 0000000000..1cf509f497 --- /dev/null +++ b/pc-bios/s390-ccw/iplb.h @@ -0,0 +1,79 @@ +/* + * QEMU S390 IPL Block + * + * Copyright 2015 IBM Corp. + * Author(s): Alexander Yarygin + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#ifndef IPLB_H +#define IPLB_H + +struct IplBlockCcw { + uint8_t reserved0[85]; + uint8_t ssid; + uint16_t devno; + uint8_t vm_flags; + uint8_t reserved3[3]; + uint32_t vm_parm_len; + uint8_t nss_name[8]; + uint8_t vm_parm[64]; + uint8_t reserved4[8]; +} __attribute__ ((packed)); +typedef struct IplBlockCcw IplBlockCcw; + +struct IplBlockFcp { + uint8_t reserved1[305 - 1]; + uint8_t opt; + uint8_t reserved2[3]; + uint16_t reserved3; + uint16_t devno; + uint8_t reserved4[4]; + uint64_t wwpn; + uint64_t lun; + uint32_t bootprog; + uint8_t reserved5[12]; + uint64_t br_lba; + uint32_t scp_data_len; + uint8_t reserved6[260]; + uint8_t scp_data[]; +} __attribute__ ((packed)); +typedef struct IplBlockFcp IplBlockFcp; + +struct IplParameterBlock { + uint32_t len; + uint8_t reserved0[3]; + uint8_t version; + uint32_t blk0_len; + uint8_t pbt; + uint8_t flags; + uint16_t reserved01; + uint8_t loadparm[8]; + union { + IplBlockCcw ccw; + IplBlockFcp fcp; + }; +} __attribute__ ((packed)); +typedef struct IplParameterBlock IplParameterBlock; + +extern IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE))); + +#define S390_IPL_TYPE_FCP 0x00 +#define S390_IPL_TYPE_CCW 0x02 + +static inline bool store_iplb(IplParameterBlock *iplb) +{ + register unsigned long addr asm("0") = (unsigned long) iplb; + register unsigned long rc asm("1") = 0; + + asm volatile ("diag %0,%2,0x308\n" + : "+d" (addr), "+d" (rc) + : "d" (6) + : "memory", "cc"); + return rc == 0x01; +} + +#endif /* IPLB_H */ diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c index 1c9e0791ab..9446ecc235 100644 --- a/pc-bios/s390-ccw/main.c +++ b/pc-bios/s390-ccw/main.c @@ -12,8 +12,8 @@ #include "virtio.h" char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE))); -uint64_t boot_value; static SubChannelId blk_schid = { .one = 1 }; +IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE))); /* * Priniciples of Operations (SA22-7832-09) chapter 17 requires that @@ -61,7 +61,7 @@ static bool find_dev(Schib *schib, int dev_no) return false; } -static void virtio_setup(uint64_t dev_info) +static void virtio_setup(void) { Schib schib; int ssid; @@ -75,12 +75,18 @@ static void virtio_setup(uint64_t dev_info) */ enable_mss_facility(); - if (dev_info != -1) { - dev_no = dev_info & 0xffff; - debug_print_int("device no. ", dev_no); - blk_schid.ssid = (dev_info >> 16) & 0x3; - debug_print_int("ssid ", blk_schid.ssid); - found = find_dev(&schib, dev_no); + if (store_iplb(&iplb)) { + switch (iplb.pbt) { + case S390_IPL_TYPE_CCW: + dev_no = iplb.ccw.devno; + debug_print_int("device no. ", dev_no); + blk_schid.ssid = iplb.ccw.ssid & 0x3; + debug_print_int("ssid ", blk_schid.ssid); + found = find_dev(&schib, dev_no); + break; + default: + panic("List-directed IPL not supported yet!\n"); + } } else { for (ssid = 0; ssid < 0x3; ssid++) { blk_schid.ssid = ssid; @@ -101,8 +107,7 @@ static void virtio_setup(uint64_t dev_info) int main(void) { sclp_setup(); - debug_print_int("boot reg[7] ", boot_value); - virtio_setup(boot_value); + virtio_setup(); zipl_load(); /* no return */ diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h index 616d96738d..ded67bcbc6 100644 --- a/pc-bios/s390-ccw/s390-ccw.h +++ b/pc-bios/s390-ccw/s390-ccw.h @@ -44,6 +44,7 @@ typedef unsigned long long __u64; #endif #include "cio.h" +#include "iplb.h" typedef struct irb Irb; typedef struct ccw1 Ccw1; @@ -61,7 +62,6 @@ void consume_sclp_int(void); void panic(const char *string); void write_subsystem_identification(void); extern char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE))); -extern uint64_t boot_value; /* sclp-ascii.c */ void sclp_print(const char *string); diff --git a/pc-bios/s390-ccw/start.S b/pc-bios/s390-ccw/start.S index b6dd8c2fbe..43f9bd243e 100644 --- a/pc-bios/s390-ccw/start.S +++ b/pc-bios/s390-ccw/start.S @@ -14,8 +14,6 @@ _start: larl %r15, stack + 0x8000 /* Set up stack */ -larl %r6, boot_value -stg %r7, 0(%r6) /* save the boot_value before any function calls */ j main /* And call C */ /* From a388ac74dee9fe3bed24dc96041f51caf615ec52 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Mon, 25 Apr 2016 11:07:13 +0200 Subject: [PATCH 08/20] s390-ccw.img: rebuild image Contains the following change: pc-bios/s390-ccw: Get device address via diag 308/6 Signed-off-by: Cornelia Huck --- pc-bios/s390-ccw.img | Bin 26424 -> 26424 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/pc-bios/s390-ccw.img b/pc-bios/s390-ccw.img index d3978ba0506cb24050f596b2e4e710dec3486fba..ea5fd9a4797530e79e88f591f66c4de8e93a604e 100644 GIT binary patch delta 5377 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 delta 5310 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 aJGjS>F6@E&)zgD%(($u6t*?8vQ~n1|+<-Cw From 010d45d279067f66caecccf178a3c58e3e73cb5a Mon Sep 17 00:00:00 2001 From: Alexander Yarygin Date: Tue, 22 Sep 2015 12:58:09 +0300 Subject: [PATCH 09/20] s390x/ipl: Remove redundant usage of gr7 We don't need to pass device address for pc-bios using gr7 anymore as the pcbios completely relies on diag308 now, so we can remove it from qemu. devno, ssid and cssid are migrated but the value was never reused, so we can safely ignore these fields and migrate 0. Signed-off-by: Alexander Yarygin Reviewed-by: David Hildenbrand Signed-off-by: Cornelia Huck --- hw/s390x/ipl.c | 33 ++++++--------------------------- 1 file changed, 6 insertions(+), 27 deletions(-) diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c index 2da0f1eaef..5786b5e451 100644 --- a/hw/s390x/ipl.c +++ b/hw/s390x/ipl.c @@ -208,50 +208,27 @@ static Property s390_ipl_properties[] = { DEFINE_PROP_END_OF_LIST(), }; -/* - * In addition to updating the iplstate, this function returns: - * - 0 if system was ipled with external kernel - * - -1 if no valid boot device was found - * - ccw id of the boot device otherwise - */ -static uint64_t s390_update_iplstate(S390IPLState *ipl) +static bool s390_gen_initial_iplb(S390IPLState *ipl) { DeviceState *dev_st; - if (ipl->iplb_valid) { - ipl->cssid = 0; - ipl->ssid = 0; - ipl->devno = ipl->iplb.devno; - goto out; - } - - if (ipl->kernel) { - return 0; - } - dev_st = get_boot_device(0); if (dev_st) { VirtioCcwDevice *ccw_dev = (VirtioCcwDevice *) object_dynamic_cast( OBJECT(qdev_get_parent_bus(dev_st)->parent), TYPE_VIRTIO_CCW_DEVICE); if (ccw_dev) { - ipl->cssid = ccw_dev->sch->cssid; - ipl->ssid = ccw_dev->sch->ssid; - ipl->devno = ccw_dev->sch->devno; ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_CCW_LEN); ipl->iplb.blk0_len = cpu_to_be32(S390_IPLB_MIN_CCW_LEN - S390_IPLB_HEADER_LEN); ipl->iplb.pbt = S390_IPL_TYPE_CCW; ipl->iplb.ccw.devno = cpu_to_be16(ccw_dev->sch->devno); ipl->iplb.ccw.ssid = ccw_dev->sch->ssid & 3; - ipl->iplb_valid = true; - goto out; + return true; } } - return -1; -out: - return (uint32_t) (ipl->cssid << 24 | ipl->ssid << 16 | ipl->devno); + return false; } void s390_ipl_update_diag308(IplParameterBlock *iplb) @@ -289,7 +266,9 @@ void s390_ipl_prepare_cpu(S390CPU *cpu) if (!ipl->kernel || ipl->iplb_valid) { cpu->env.psw.addr = ipl->bios_start_addr; - cpu->env.regs[7] = s390_update_iplstate(ipl); + if (!ipl->iplb_valid) { + ipl->iplb_valid = s390_gen_initial_iplb(ipl); + } } } From e563c59b6ada51da76eaba9dc8b39085546ebd02 Mon Sep 17 00:00:00 2001 From: xiaoqiang zhao Date: Tue, 29 Mar 2016 15:47:24 +0800 Subject: [PATCH 10/20] hw/char: QOM'ify sclpconsole-lm.c Drop the DO_UPCAST macro Signed-off-by: xiaoqiang zhao Message-Id: <1459237645-17227-6-git-send-email-zxq_yx_007@163.com> Signed-off-by: Cornelia Huck --- hw/char/sclpconsole-lm.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/hw/char/sclpconsole-lm.c b/hw/char/sclpconsole-lm.c index 7d4ff8120a..a22ad8d016 100644 --- a/hw/char/sclpconsole-lm.c +++ b/hw/char/sclpconsole-lm.c @@ -44,6 +44,10 @@ typedef struct SCLPConsoleLM { uint8_t buf[SIZE_CONSOLE_BUFFER]; } SCLPConsoleLM; +#define TYPE_SCLPLM_CONSOLE "sclplmconsole" +#define SCLPLM_CONSOLE(obj) \ + OBJECT_CHECK(SCLPConsoleLM, (obj), TYPE_SCLPLM_CONSOLE) + /* * Character layer call-back functions * @@ -116,7 +120,7 @@ static int get_console_data(SCLPEvent *event, uint8_t *buf, size_t *size, { int len; - SCLPConsoleLM *cons = DO_UPCAST(SCLPConsoleLM, event, event); + SCLPConsoleLM *cons = SCLPLM_CONSOLE(event); len = cons->length; /* data need to fit into provided SCLP buffer */ @@ -190,7 +194,7 @@ static int write_console_data(SCLPEvent *event, const uint8_t *buf, int len) int ret = 0; const uint8_t *buf_offset; - SCLPConsoleLM *scon = DO_UPCAST(SCLPConsoleLM, event, event); + SCLPConsoleLM *scon = SCLPLM_CONSOLE(event); if (!scon->chr) { /* If there's no backend, we can just say we consumed all data. */ @@ -244,7 +248,7 @@ static int write_event_data(SCLPEvent *event, EventBufferHeader *ebh) int errors = 0; MDBO *mdbo; SclpMsg *data = (SclpMsg *) ebh; - SCLPConsoleLM *scon = DO_UPCAST(SCLPConsoleLM, event, event); + SCLPConsoleLM *scon = SCLPLM_CONSOLE(event); len = be16_to_cpu(data->mdb.header.length); if (len < sizeof(data->mdb.header)) { @@ -313,7 +317,7 @@ static int console_init(SCLPEvent *event) { static bool console_available; - SCLPConsoleLM *scon = DO_UPCAST(SCLPConsoleLM, event, event); + SCLPConsoleLM *scon = SCLPLM_CONSOLE(event); if (console_available) { error_report("Multiple line-mode operator consoles are not supported"); @@ -336,7 +340,7 @@ static int console_exit(SCLPEvent *event) static void console_reset(DeviceState *dev) { SCLPEvent *event = SCLP_EVENT(dev); - SCLPConsoleLM *scon = DO_UPCAST(SCLPConsoleLM, event, event); + SCLPConsoleLM *scon = SCLPLM_CONSOLE(event); event->event_pending = false; scon->length = 0; From 3f6ec642ae84cde9375bd4e624ab4e3fe23f60b9 Mon Sep 17 00:00:00 2001 From: xiaoqiang zhao Date: Tue, 29 Mar 2016 15:47:25 +0800 Subject: [PATCH 11/20] hw/char: QOM'ify sclpconsole.c Drop the DO_UPCAST macro Signed-off-by: xiaoqiang zhao Message-Id: <1459237645-17227-7-git-send-email-zxq_yx_007@163.com> Signed-off-by: Cornelia Huck --- hw/char/sclpconsole.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/hw/char/sclpconsole.c b/hw/char/sclpconsole.c index 45997ff4ae..15a5b2b2b5 100644 --- a/hw/char/sclpconsole.c +++ b/hw/char/sclpconsole.c @@ -40,6 +40,10 @@ typedef struct SCLPConsole { bool notify; /* qemu_notify_event() req'd if true */ } SCLPConsole; +#define TYPE_SCLP_CONSOLE "sclpconsole" +#define SCLP_CONSOLE(obj) \ + OBJECT_CHECK(SCLPConsole, (obj), TYPE_SCLP_CONSOLE) + /* character layer call-back functions */ /* Return number of bytes that fit into iov buffer */ @@ -95,7 +99,7 @@ static unsigned int receive_mask(void) static void get_console_data(SCLPEvent *event, uint8_t *buf, size_t *size, int avail) { - SCLPConsole *cons = DO_UPCAST(SCLPConsole, event, event); + SCLPConsole *cons = SCLP_CONSOLE(event); /* first byte is hex 0 saying an ascii string follows */ *buf++ = '\0'; @@ -157,7 +161,7 @@ static int read_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr, static ssize_t write_console_data(SCLPEvent *event, const uint8_t *buf, size_t len) { - SCLPConsole *scon = DO_UPCAST(SCLPConsole, event, event); + SCLPConsole *scon = SCLP_CONSOLE(event); if (!scon->chr) { /* If there's no backend, we can just say we consumed all data. */ @@ -214,7 +218,7 @@ static int console_init(SCLPEvent *event) { static bool console_available; - SCLPConsole *scon = DO_UPCAST(SCLPConsole, event, event); + SCLPConsole *scon = SCLP_CONSOLE(event); if (console_available) { error_report("Multiple VT220 operator consoles are not supported"); @@ -232,7 +236,7 @@ static int console_init(SCLPEvent *event) static void console_reset(DeviceState *dev) { SCLPEvent *event = SCLP_EVENT(dev); - SCLPConsole *scon = DO_UPCAST(SCLPConsole, event, event); + SCLPConsole *scon = SCLP_CONSOLE(event); event->event_pending = false; scon->iov_sclp = 0; From bac45d5147fbe832428944610c70484b18539292 Mon Sep 17 00:00:00 2001 From: Yi Min Zhao Date: Tue, 26 Apr 2016 19:26:32 +0800 Subject: [PATCH 12/20] s390x/pci: fix reg_irqs() In reg_irqs(), present code assumes that map_indicator() always issues successfully. Let's check it and return the error to caller in order to inform guest. Signed-off-by: Yi Min Zhao Reviewed-by: Cornelia Huck Reviewed-by: Pierre Morel Reviewed-by: Dong Jia Shi Signed-off-by: Cornelia Huck --- hw/s390x/s390-pci-inst.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c index b28e7d14f8..90d9fda77c 100644 --- a/hw/s390x/s390-pci-inst.c +++ b/hw/s390x/s390-pci-inst.c @@ -634,8 +634,15 @@ static int reg_irqs(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib) len = BITS_TO_LONGS(FIB_DATA_NOI(ldl_p(&fib.data))) * sizeof(unsigned long); pbdev->indicator = get_indicator(ldq_p(&fib.aibv), len); - map_indicator(&pbdev->routes.adapter, pbdev->summary_ind); - map_indicator(&pbdev->routes.adapter, pbdev->indicator); + ret = map_indicator(&pbdev->routes.adapter, pbdev->summary_ind); + if (ret) { + goto out; + } + + ret = map_indicator(&pbdev->routes.adapter, pbdev->indicator); + if (ret) { + goto out; + } pbdev->routes.adapter.summary_addr = ldq_p(&fib.aisb); pbdev->routes.adapter.summary_offset = FIB_DATA_AISBO(ldl_p(&fib.data)); @@ -647,6 +654,12 @@ static int reg_irqs(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib) DPRINTF("reg_irqs adapter id %d\n", pbdev->routes.adapter.adapter_id); return 0; +out: + release_indicator(&pbdev->routes.adapter, pbdev->summary_ind); + release_indicator(&pbdev->routes.adapter, pbdev->indicator); + pbdev->summary_ind = NULL; + pbdev->indicator = NULL; + return ret; } static int dereg_irqs(S390PCIBusDevice *pbdev) From 8f5cb69313acac264201289c08f255f0ddac71a4 Mon Sep 17 00:00:00 2001 From: Yi Min Zhao Date: Thu, 28 Apr 2016 12:33:53 +0800 Subject: [PATCH 13/20] s390x/pci: separate s390_sclp_configure function Split s390_sclp_configure() into separate functions for sclp configuring and deconfiguring in order to make the code more readable. Signed-off-by: Yi Min Zhao Reviewed-by: Pierre Morel Signed-off-by: Cornelia Huck --- hw/s390x/s390-pci-bus.c | 30 +++++++++++++++++++++++++----- hw/s390x/s390-pci-bus.h | 3 ++- hw/s390x/sclp.c | 4 ++-- 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index 918b58543e..c749d00de8 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -106,22 +106,42 @@ S390PCIBusDevice *s390_pci_find_dev_by_fid(uint32_t fid) return NULL; } -void s390_pci_sclp_configure(int configure, SCCB *sccb) +void s390_pci_sclp_configure(SCCB *sccb) { PciCfgSccb *psccb = (PciCfgSccb *)sccb; S390PCIBusDevice *pbdev = s390_pci_find_dev_by_fid(be32_to_cpu(psccb->aid)); uint16_t rc; if (pbdev) { - if ((configure == 1 && pbdev->configured == true) || - (configure == 0 && pbdev->configured == false)) { + if (pbdev->configured) { rc = SCLP_RC_NO_ACTION_REQUIRED; } else { - pbdev->configured = !pbdev->configured; + pbdev->configured = true; rc = SCLP_RC_NORMAL_COMPLETION; } } else { - DPRINTF("sclp config %d no dev found\n", configure); + DPRINTF("sclp config no dev found\n"); + rc = SCLP_RC_ADAPTER_ID_NOT_RECOGNIZED; + } + + psccb->header.response_code = cpu_to_be16(rc); +} + +void s390_pci_sclp_deconfigure(SCCB *sccb) +{ + PciCfgSccb *psccb = (PciCfgSccb *)sccb; + S390PCIBusDevice *pbdev = s390_pci_find_dev_by_fid(be32_to_cpu(psccb->aid)); + uint16_t rc; + + if (pbdev) { + if (!pbdev->configured) { + rc = SCLP_RC_NO_ACTION_REQUIRED; + } else { + pbdev->configured = false; + rc = SCLP_RC_NORMAL_COMPLETION; + } + } else { + DPRINTF("sclp deconfig no dev found\n"); rc = SCLP_RC_ADAPTER_ID_NOT_RECOGNIZED; } diff --git a/hw/s390x/s390-pci-bus.h b/hw/s390x/s390-pci-bus.h index 59fd5c9583..d6e17d2eeb 100644 --- a/hw/s390x/s390-pci-bus.h +++ b/hw/s390x/s390-pci-bus.h @@ -247,7 +247,8 @@ typedef struct S390pciState { int chsc_sei_nt2_get_event(void *res); int chsc_sei_nt2_have_event(void); -void s390_pci_sclp_configure(int configure, SCCB *sccb); +void s390_pci_sclp_configure(SCCB *sccb); +void s390_pci_sclp_deconfigure(SCCB *sccb); void s390_pcihost_iommu_configure(S390PCIBusDevice *pbdev, bool enable); S390PCIBusDevice *s390_pci_find_dev_by_idx(uint32_t idx); S390PCIBusDevice *s390_pci_find_dev_by_fh(uint32_t fh); diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c index 85dbe1b600..fca37f511e 100644 --- a/hw/s390x/sclp.c +++ b/hw/s390x/sclp.c @@ -357,10 +357,10 @@ static void sclp_execute(SCLPDevice *sclp, SCCB *sccb, uint32_t code) sclp_c->unassign_storage(sclp, sccb); break; case SCLP_CMDW_CONFIGURE_PCI: - s390_pci_sclp_configure(1, sccb); + s390_pci_sclp_configure(sccb); break; case SCLP_CMDW_DECONFIGURE_PCI: - s390_pci_sclp_configure(0, sccb); + s390_pci_sclp_deconfigure(sccb); break; default: efc->command_handler(ef, sccb, code); From 715838881fdcab07aff26ce2f5fd37a4af8f243f Mon Sep 17 00:00:00 2001 From: Yi Min Zhao Date: Wed, 4 May 2016 15:06:44 +0800 Subject: [PATCH 14/20] s390x/pci: separate s390_pcihost_iommu_configure function Split s390_pcihost_iommu_configure() into separate functions for configuring and deconfiguring in order to make the code more readable. Signed-off-by: Yi Min Zhao Reviewed-by: Pierre Morel Signed-off-by: Cornelia Huck --- hw/s390x/s390-pci-bus.c | 21 ++++++++++++--------- hw/s390x/s390-pci-bus.h | 3 ++- hw/s390x/s390-pci-inst.c | 5 ++--- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index c749d00de8..b934fc80c2 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -478,19 +478,22 @@ static const MemoryRegionOps s390_msi_ctrl_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; -void s390_pcihost_iommu_configure(S390PCIBusDevice *pbdev, bool enable) +void s390_pci_iommu_enable(S390PCIBusDevice *pbdev) { pbdev->configured = false; + uint64_t size = pbdev->pal - pbdev->pba + 1; - if (enable) { - uint64_t size = pbdev->pal - pbdev->pba + 1; - memory_region_init_iommu(&pbdev->iommu_mr, OBJECT(&pbdev->mr), - &s390_iommu_ops, "iommu-s390", size); - memory_region_add_subregion(&pbdev->mr, pbdev->pba, &pbdev->iommu_mr); - } else { - memory_region_del_subregion(&pbdev->mr, &pbdev->iommu_mr); - } + memory_region_init_iommu(&pbdev->iommu_mr, OBJECT(&pbdev->mr), + &s390_iommu_ops, "iommu-s390", size); + memory_region_add_subregion(&pbdev->mr, pbdev->pba, &pbdev->iommu_mr); + pbdev->configured = true; +} +void s390_pci_iommu_disable(S390PCIBusDevice *pbdev) +{ + pbdev->configured = false; + memory_region_del_subregion(&pbdev->mr, &pbdev->iommu_mr); + object_unparent(OBJECT(&pbdev->iommu_mr)); pbdev->configured = true; } diff --git a/hw/s390x/s390-pci-bus.h b/hw/s390x/s390-pci-bus.h index d6e17d2eeb..426f690bba 100644 --- a/hw/s390x/s390-pci-bus.h +++ b/hw/s390x/s390-pci-bus.h @@ -249,7 +249,8 @@ int chsc_sei_nt2_get_event(void *res); int chsc_sei_nt2_have_event(void); void s390_pci_sclp_configure(SCCB *sccb); void s390_pci_sclp_deconfigure(SCCB *sccb); -void s390_pcihost_iommu_configure(S390PCIBusDevice *pbdev, bool enable); +void s390_pci_iommu_enable(S390PCIBusDevice *pbdev); +void s390_pci_iommu_disable(S390PCIBusDevice *pbdev); S390PCIBusDevice *s390_pci_find_dev_by_idx(uint32_t idx); S390PCIBusDevice *s390_pci_find_dev_by_fh(uint32_t fh); S390PCIBusDevice *s390_pci_find_dev_by_fid(uint32_t fid); diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c index 90d9fda77c..eb03f480c4 100644 --- a/hw/s390x/s390-pci-inst.c +++ b/hw/s390x/s390-pci-inst.c @@ -705,18 +705,17 @@ static int reg_ioat(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib) pbdev->pal = pal; pbdev->g_iota = g_iota; - s390_pcihost_iommu_configure(pbdev, true); + s390_pci_iommu_enable(pbdev); return 0; } static void dereg_ioat(S390PCIBusDevice *pbdev) { + s390_pci_iommu_disable(pbdev); pbdev->pba = 0; pbdev->pal = 0; pbdev->g_iota = 0; - - s390_pcihost_iommu_configure(pbdev, false); } int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar) From e141dbadfa405a4ae16515c80a0e215e462a259f Mon Sep 17 00:00:00 2001 From: Yi Min Zhao Date: Tue, 26 Apr 2016 14:50:16 +0800 Subject: [PATCH 15/20] s390x/pci: export pci_dereg_ioat and pci_dereg_irqs dereg_irqs and dereg_ioat are needed by external functions. Let's rename and export both of them in s390-pci-inst.h. Signed-off-by: Yi Min Zhao Reviewed-by: Pierre Morel Signed-off-by: Cornelia Huck --- hw/s390x/s390-pci-inst.c | 10 +++++----- hw/s390x/s390-pci-inst.h | 3 +++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c index eb03f480c4..4b4dd63b5f 100644 --- a/hw/s390x/s390-pci-inst.c +++ b/hw/s390x/s390-pci-inst.c @@ -662,7 +662,7 @@ out: return ret; } -static int dereg_irqs(S390PCIBusDevice *pbdev) +int pci_dereg_irqs(S390PCIBusDevice *pbdev) { release_indicator(&pbdev->routes.adapter, pbdev->summary_ind); release_indicator(&pbdev->routes.adapter, pbdev->indicator); @@ -710,7 +710,7 @@ static int reg_ioat(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib) return 0; } -static void dereg_ioat(S390PCIBusDevice *pbdev) +void pci_dereg_ioat(S390PCIBusDevice *pbdev) { s390_pci_iommu_disable(pbdev); pbdev->pba = 0; @@ -758,7 +758,7 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar) } break; case ZPCI_MOD_FC_DEREG_INT: - dereg_irqs(pbdev); + pci_dereg_irqs(pbdev); break; case ZPCI_MOD_FC_REG_IOAT: if (reg_ioat(env, pbdev, fib)) { @@ -766,10 +766,10 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar) } break; case ZPCI_MOD_FC_DEREG_IOAT: - dereg_ioat(pbdev); + pci_dereg_ioat(pbdev); break; case ZPCI_MOD_FC_REREG_IOAT: - dereg_ioat(pbdev); + pci_dereg_ioat(pbdev); if (reg_ioat(env, pbdev, fib)) { cc = ZPCI_PCI_LS_ERR; } diff --git a/hw/s390x/s390-pci-inst.h b/hw/s390x/s390-pci-inst.h index 70fa71395f..9fc94e91cc 100644 --- a/hw/s390x/s390-pci-inst.h +++ b/hw/s390x/s390-pci-inst.h @@ -14,6 +14,7 @@ #ifndef HW_S390_PCI_INST_H #define HW_S390_PCI_INST_H +#include "s390-pci-bus.h" #include /* CLP common request & response block size */ @@ -277,6 +278,8 @@ typedef struct ZpciFib { uint32_t gd; } QEMU_PACKED ZpciFib; +int pci_dereg_irqs(S390PCIBusDevice *pbdev); +void pci_dereg_ioat(S390PCIBusDevice *pbdev); int clp_service_call(S390CPU *cpu, uint8_t r2); int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2); int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2); From df6a050c82e56fc7a0afeb62cf4bc2e0c4c6d888 Mon Sep 17 00:00:00 2001 From: Yi Min Zhao Date: Wed, 4 May 2016 15:07:11 +0800 Subject: [PATCH 16/20] s390x/pci: introduce S390PCIBusDevice.iommu_enabled We introduce iommu_enabled field for S390PCIBusDevice struct to track whether the iommu has been enabled for the device. This allows us to stop temporarily changing ->configured while en/disabling the iommu and to do conditional cleanup later. Signed-off-by: Yi Min Zhao Reviewed-by: Pierre Morel Signed-off-by: Cornelia Huck --- hw/s390x/s390-pci-bus.c | 9 ++++----- hw/s390x/s390-pci-bus.h | 1 + 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index b934fc80c2..5d54c73774 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -340,7 +340,8 @@ static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *iommu, hwaddr addr, .perm = IOMMU_NONE, }; - if (!pbdev->configured || !pbdev->pdev || !(pbdev->fh & FH_ENABLED)) { + if (!pbdev->configured || !pbdev->pdev || + !(pbdev->fh & FH_ENABLED) || !pbdev->iommu_enabled) { return ret; } @@ -480,21 +481,19 @@ static const MemoryRegionOps s390_msi_ctrl_ops = { void s390_pci_iommu_enable(S390PCIBusDevice *pbdev) { - pbdev->configured = false; uint64_t size = pbdev->pal - pbdev->pba + 1; memory_region_init_iommu(&pbdev->iommu_mr, OBJECT(&pbdev->mr), &s390_iommu_ops, "iommu-s390", size); memory_region_add_subregion(&pbdev->mr, pbdev->pba, &pbdev->iommu_mr); - pbdev->configured = true; + pbdev->iommu_enabled = true; } void s390_pci_iommu_disable(S390PCIBusDevice *pbdev) { - pbdev->configured = false; memory_region_del_subregion(&pbdev->mr, &pbdev->iommu_mr); object_unparent(OBJECT(&pbdev->iommu_mr)); - pbdev->configured = true; + pbdev->iommu_enabled = false; } static void s390_pcihost_init_as(S390pciState *s) diff --git a/hw/s390x/s390-pci-bus.h b/hw/s390x/s390-pci-bus.h index 426f690bba..8b64884e3d 100644 --- a/hw/s390x/s390-pci-bus.h +++ b/hw/s390x/s390-pci-bus.h @@ -219,6 +219,7 @@ typedef struct S390PCIBusDevice { bool configured; bool error_state; bool lgstg_blocked; + bool iommu_enabled; uint32_t fh; uint32_t fid; uint64_t g_iota; From 259a4f0a7619fef69427555839e0c9db84fd0561 Mon Sep 17 00:00:00 2001 From: Yi Min Zhao Date: Thu, 28 Apr 2016 13:22:51 +0800 Subject: [PATCH 17/20] s390x/pci: fix s390_pci_sclp_deconfigure When deconfiguring a s390 pci device, we should deconfigure the corresponding IOMMU memory region and the IRQs for the device. Signed-off-by: Yi Min Zhao Reviewed-by: Pierre Morel Signed-off-by: Cornelia Huck --- hw/s390x/s390-pci-bus.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index 5d54c73774..b2cd31c15f 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -15,6 +15,7 @@ #include "qemu-common.h" #include "cpu.h" #include "s390-pci-bus.h" +#include "s390-pci-inst.h" #include #include #include @@ -137,6 +138,12 @@ void s390_pci_sclp_deconfigure(SCCB *sccb) if (!pbdev->configured) { rc = SCLP_RC_NO_ACTION_REQUIRED; } else { + if (pbdev->summary_ind) { + pci_dereg_irqs(pbdev); + } + if (pbdev->iommu_enabled) { + pci_dereg_ioat(pbdev); + } pbdev->configured = false; rc = SCLP_RC_NORMAL_COMPLETION; } From a6d9d4f26afc2c2fcfe6a89f0766371a60143d5a Mon Sep 17 00:00:00 2001 From: Yi Min Zhao Date: Thu, 28 Apr 2016 13:24:07 +0800 Subject: [PATCH 18/20] s390x/pci: enhance mpcifc_service_call Enhance error handling for mpcifc_service_call() to propagate errors to guest by setting status codes or triggering program interrupts. Signed-off-by: Yi Min Zhao Reviewed-by: Pierre Morel Signed-off-by: Cornelia Huck --- hw/s390x/s390-pci-inst.c | 53 ++++++++++++++++++++++++++++++++++------ hw/s390x/s390-pci-inst.h | 8 ++++++ 2 files changed, 54 insertions(+), 7 deletions(-) diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c index 4b4dd63b5f..479375f65d 100644 --- a/hw/s390x/s390-pci-inst.c +++ b/hw/s390x/s390-pci-inst.c @@ -721,7 +721,7 @@ void pci_dereg_ioat(S390PCIBusDevice *pbdev) int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar) { CPUS390XState *env = &cpu->env; - uint8_t oc; + uint8_t oc, dmaas; uint32_t fh; ZpciFib fib; S390PCIBusDevice *pbdev; @@ -733,6 +733,7 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar) } oc = env->regs[r1] & 0xff; + dmaas = (env->regs[r1] >> 16) & 0xff; fh = env->regs[r1] >> 32; if (fiba & 0x7) { @@ -751,27 +752,65 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar) return 0; } + if (fib.fmt != 0) { + program_interrupt(env, PGM_OPERAND, 6); + return 0; + } + switch (oc) { case ZPCI_MOD_FC_REG_INT: - if (reg_irqs(env, pbdev, fib)) { + if (pbdev->summary_ind) { cc = ZPCI_PCI_LS_ERR; + s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE); + } else if (reg_irqs(env, pbdev, fib)) { + cc = ZPCI_PCI_LS_ERR; + s390_set_status_code(env, r1, ZPCI_MOD_ST_RES_NOT_AVAIL); } break; case ZPCI_MOD_FC_DEREG_INT: - pci_dereg_irqs(pbdev); + if (!pbdev->summary_ind) { + cc = ZPCI_PCI_LS_ERR; + s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE); + } else { + pci_dereg_irqs(pbdev); + } break; case ZPCI_MOD_FC_REG_IOAT: - if (reg_ioat(env, pbdev, fib)) { + if (dmaas != 0) { cc = ZPCI_PCI_LS_ERR; + s390_set_status_code(env, r1, ZPCI_MOD_ST_DMAAS_INVAL); + } else if (pbdev->iommu_enabled) { + cc = ZPCI_PCI_LS_ERR; + s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE); + } else if (reg_ioat(env, pbdev, fib)) { + cc = ZPCI_PCI_LS_ERR; + s390_set_status_code(env, r1, ZPCI_MOD_ST_INSUF_RES); } break; case ZPCI_MOD_FC_DEREG_IOAT: - pci_dereg_ioat(pbdev); + if (dmaas != 0) { + cc = ZPCI_PCI_LS_ERR; + s390_set_status_code(env, r1, ZPCI_MOD_ST_DMAAS_INVAL); + } else if (!pbdev->iommu_enabled) { + cc = ZPCI_PCI_LS_ERR; + s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE); + } else { + pci_dereg_ioat(pbdev); + } break; case ZPCI_MOD_FC_REREG_IOAT: - pci_dereg_ioat(pbdev); - if (reg_ioat(env, pbdev, fib)) { + if (dmaas != 0) { cc = ZPCI_PCI_LS_ERR; + s390_set_status_code(env, r1, ZPCI_MOD_ST_DMAAS_INVAL); + } else if (!pbdev->iommu_enabled) { + cc = ZPCI_PCI_LS_ERR; + s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE); + } else { + pci_dereg_ioat(pbdev); + if (reg_ioat(env, pbdev, fib)) { + cc = ZPCI_PCI_LS_ERR; + s390_set_status_code(env, r1, ZPCI_MOD_ST_INSUF_RES); + } } break; case ZPCI_MOD_FC_RESET_ERROR: diff --git a/hw/s390x/s390-pci-inst.h b/hw/s390x/s390-pci-inst.h index 9fc94e91cc..b084f2346b 100644 --- a/hw/s390x/s390-pci-inst.h +++ b/hw/s390x/s390-pci-inst.h @@ -231,6 +231,14 @@ typedef struct ClpReqRspQueryPciGrp { #define ZPCI_PCI_LS_BUSY 2 #define ZPCI_PCI_LS_INVAL_HANDLE 3 +/* Modify PCI status codes */ +#define ZPCI_MOD_ST_RES_NOT_AVAIL 4 +#define ZPCI_MOD_ST_INSUF_RES 16 +#define ZPCI_MOD_ST_SEQUENCE 24 +#define ZPCI_MOD_ST_DMAAS_INVAL 28 +#define ZPCI_MOD_ST_FRAME_INVAL 32 +#define ZPCI_MOD_ST_ERROR_RECOVER 40 + /* Modify PCI Function Controls */ #define ZPCI_MOD_FC_REG_INT 2 #define ZPCI_MOD_FC_DEREG_INT 3 From 3b40ea2957683bc7bea1a358f25045e6184077cf Mon Sep 17 00:00:00 2001 From: Yi Min Zhao Date: Wed, 4 May 2016 15:56:53 +0800 Subject: [PATCH 19/20] s390x/pci: add length checking for pci sclp handlers The configure/deconfigure sclp commands need a SCCB with a length of at least 16. Indicate in the response code if this is not fulfilled. Signed-off-by: Yi Min Zhao Reviewed-by: Pierre Morel Signed-off-by: Cornelia Huck --- hw/s390x/s390-pci-bus.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index b2cd31c15f..a77c10ce9e 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -113,6 +113,11 @@ void s390_pci_sclp_configure(SCCB *sccb) S390PCIBusDevice *pbdev = s390_pci_find_dev_by_fid(be32_to_cpu(psccb->aid)); uint16_t rc; + if (be16_to_cpu(sccb->h.length) < 16) { + rc = SCLP_RC_INSUFFICIENT_SCCB_LENGTH; + goto out; + } + if (pbdev) { if (pbdev->configured) { rc = SCLP_RC_NO_ACTION_REQUIRED; @@ -124,7 +129,7 @@ void s390_pci_sclp_configure(SCCB *sccb) DPRINTF("sclp config no dev found\n"); rc = SCLP_RC_ADAPTER_ID_NOT_RECOGNIZED; } - +out: psccb->header.response_code = cpu_to_be16(rc); } @@ -134,6 +139,11 @@ void s390_pci_sclp_deconfigure(SCCB *sccb) S390PCIBusDevice *pbdev = s390_pci_find_dev_by_fid(be32_to_cpu(psccb->aid)); uint16_t rc; + if (be16_to_cpu(sccb->h.length) < 16) { + rc = SCLP_RC_INSUFFICIENT_SCCB_LENGTH; + goto out; + } + if (pbdev) { if (!pbdev->configured) { rc = SCLP_RC_NO_ACTION_REQUIRED; @@ -151,7 +161,7 @@ void s390_pci_sclp_deconfigure(SCCB *sccb) DPRINTF("sclp deconfig no dev found\n"); rc = SCLP_RC_ADAPTER_ID_NOT_RECOGNIZED; } - +out: psccb->header.response_code = cpu_to_be16(rc); } From c26916942a4a085b316fd102d1725412a6544b04 Mon Sep 17 00:00:00 2001 From: Yi Min Zhao Date: Mon, 9 May 2016 18:26:44 +0800 Subject: [PATCH 20/20] s390x/pci: remove whitespace Fix indentation of PciCfgSccb struct. Signed-off-by: Yi Min Zhao Signed-off-by: Cornelia Huck --- hw/s390x/s390-pci-bus.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/hw/s390x/s390-pci-bus.h b/hw/s390x/s390-pci-bus.h index 8b64884e3d..2c852d47fa 100644 --- a/hw/s390x/s390-pci-bus.h +++ b/hw/s390x/s390-pci-bus.h @@ -198,11 +198,11 @@ typedef struct ChscSeiNt2Res { } QEMU_PACKED ChscSeiNt2Res; typedef struct PciCfgSccb { - SCCBHeader header; - uint8_t atype; - uint8_t reserved1; - uint16_t reserved2; - uint32_t aid; + SCCBHeader header; + uint8_t atype; + uint8_t reserved1; + uint16_t reserved2; + uint32_t aid; } QEMU_PACKED PciCfgSccb; typedef struct S390MsixInfo {