From 03f47ee49e1478b5ffffb3a9b6203c672903196c Mon Sep 17 00:00:00 2001 From: Janosch Frank Date: Mon, 29 May 2017 14:19:02 +0200 Subject: [PATCH 01/40] s390x/kvm: Rework cmma management Let's keep track of cmma enablement and move the mem_path check into the actual enablement. This now also warns users that do not use cpu-models about disabled cmma when using huge pages. Signed-off-by: Janosch Frank Reviewed-by: Cornelia Huck Signed-off-by: Christian Borntraeger --- target/s390x/cpu.h | 1 + target/s390x/kvm.c | 26 +++++++++++++++++--------- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h index bdb9bdbc9d..8ab75c0d43 100644 --- a/target/s390x/cpu.h +++ b/target/s390x/cpu.h @@ -1158,6 +1158,7 @@ int kvm_s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch, int vq, bool assign); int kvm_s390_cpu_restart(S390CPU *cpu); int kvm_s390_get_memslot_count(KVMState *s); +int kvm_s390_cmma_active(void); void kvm_s390_cmma_reset(void); int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state); void kvm_s390_reset_vcpu(S390CPU *cpu); diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c index a3d00196f4..7a2a7c0895 100644 --- a/target/s390x/kvm.c +++ b/target/s390x/kvm.c @@ -140,6 +140,8 @@ static int cap_mem_op; static int cap_s390_irq; static int cap_ri; +static int active_cmma; + static void *legacy_s390_alloc(size_t size, uint64_t *align); static int kvm_s390_query_mem_limit(KVMState *s, uint64_t *memory_limit) @@ -177,6 +179,11 @@ int kvm_s390_set_mem_limit(KVMState *s, uint64_t new_limit, uint64_t *hw_limit) return kvm_vm_ioctl(s, KVM_SET_DEVICE_ATTR, &attr); } +int kvm_s390_cmma_active(void) +{ + return active_cmma; +} + static bool kvm_s390_cmma_available(void) { static bool initialized, value; @@ -197,7 +204,7 @@ void kvm_s390_cmma_reset(void) .attr = KVM_S390_VM_MEM_CLR_CMMA, }; - if (mem_path || !kvm_s390_cmma_available()) { + if (!kvm_s390_cmma_active()) { return; } @@ -213,7 +220,13 @@ static void kvm_s390_enable_cmma(void) .attr = KVM_S390_VM_MEM_ENABLE_CMMA, }; + if (mem_path) { + error_report("Warning: CMM will not be enabled because it is not " + "compatible to hugetlbfs."); + return; + } rc = kvm_vm_ioctl(kvm_state, KVM_SET_DEVICE_ATTR, &attr); + active_cmma = !rc; trace_kvm_enable_cmma(rc); } @@ -2641,7 +2654,7 @@ void kvm_s390_apply_cpu_model(const S390CPUModel *model, Error **errp) if (!model) { /* compatibility handling if cpu models are disabled */ - if (kvm_s390_cmma_available() && !mem_path) { + if (kvm_s390_cmma_available()) { kvm_s390_enable_cmma(); } return; @@ -2672,13 +2685,8 @@ void kvm_s390_apply_cpu_model(const S390CPUModel *model, Error **errp) error_setg(errp, "KVM: Error configuring CPU subfunctions: %d", rc); return; } - /* enable CMM via CMMA - disable on hugetlbfs */ + /* enable CMM via CMMA */ if (test_bit(S390_FEAT_CMM, model->features)) { - if (mem_path) { - error_report("Warning: CMM will not be enabled because it is not " - "compatible to hugetlbfs."); - } else { - kvm_s390_enable_cmma(); - } + kvm_s390_enable_cmma(); } } From 3272f0e22fefa4a364cdbdb01975f9178177ab37 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Mon, 15 Aug 2016 18:25:52 +0200 Subject: [PATCH 02/40] linux-headers: update to 4.13-rc0 commit af3c8d98508d37541d4bf57f13a984a7f73a328c Merge tag 'drm-for-v4.13' of git://people.freedesktop.org/~airlied/linux There is a change pending for v4.13-rc1 in linux-headers/linux/kvm.h I will submit a fixup patch for 2.10 as soon as it hits the kernel. Signed-off-by: Christian Borntraeger --- include/standard-headers/asm-x86/hyperv.h | 21 ++++++----- .../linux/input-event-codes.h | 1 + include/standard-headers/linux/pci_regs.h | 1 + linux-headers/asm-arm/kvm.h | 8 +++++ linux-headers/asm-arm64/kvm.h | 3 ++ linux-headers/asm-powerpc/kvm.h | 6 ++++ linux-headers/asm-s390/kvm.h | 12 +++++++ linux-headers/linux/kvm.h | 35 +++++++++++++++++++ 8 files changed, 78 insertions(+), 9 deletions(-) diff --git a/include/standard-headers/asm-x86/hyperv.h b/include/standard-headers/asm-x86/hyperv.h index d0c6e0a079..fac7651740 100644 --- a/include/standard-headers/asm-x86/hyperv.h +++ b/include/standard-headers/asm-x86/hyperv.h @@ -34,16 +34,10 @@ #define HV_X64_MSR_REFERENCE_TSC 0x40000021 /* - * There is a single feature flag that signifies the presence of the MSR - * that can be used to retrieve both the local APIC Timer frequency as - * well as the TSC frequency. + * There is a single feature flag that signifies if the partition has access + * to MSRs with local APIC and TSC frequencies. */ - -/* Local APIC timer frequency MSR (HV_X64_MSR_APIC_FREQUENCY) is available */ -#define HV_X64_MSR_APIC_FREQUENCY_AVAILABLE (1 << 11) - -/* TSC frequency MSR (HV_X64_MSR_TSC_FREQUENCY) is available */ -#define HV_X64_MSR_TSC_FREQUENCY_AVAILABLE (1 << 11) +#define HV_X64_ACCESS_FREQUENCY_MSRS (1 << 11) /* * Basic SynIC MSRs (HV_X64_MSR_SCONTROL through HV_X64_MSR_EOM @@ -73,6 +67,9 @@ */ #define HV_X64_MSR_STAT_PAGES_AVAILABLE (1 << 8) +/* Frequency MSRs available */ +#define HV_FEATURE_FREQUENCY_MSRS_AVAILABLE (1 << 8) + /* Crash MSR available */ #define HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE (1 << 10) @@ -152,6 +149,12 @@ */ #define HV_X64_DEPRECATING_AEOI_RECOMMENDED (1 << 9) +/* + * HV_VP_SET available + */ +#define HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED (1 << 11) + + /* * Crash notification flag. */ diff --git a/include/standard-headers/linux/input-event-codes.h b/include/standard-headers/linux/input-event-codes.h index 29d463af37..2fa0f4ea6b 100644 --- a/include/standard-headers/linux/input-event-codes.h +++ b/include/standard-headers/linux/input-event-codes.h @@ -600,6 +600,7 @@ #define KEY_APPSELECT 0x244 /* AL Select Task/Application */ #define KEY_SCREENSAVER 0x245 /* AL Screen Saver */ #define KEY_VOICECOMMAND 0x246 /* Listening Voice Command */ +#define KEY_ASSISTANT 0x247 /* AL Context-aware desktop assistant */ #define KEY_BRIGHTNESS_MIN 0x250 /* Set Brightness to Minimum */ #define KEY_BRIGHTNESS_MAX 0x251 /* Set Brightness to Maximum */ diff --git a/include/standard-headers/linux/pci_regs.h b/include/standard-headers/linux/pci_regs.h index d56bb00510..c22d3ebaca 100644 --- a/include/standard-headers/linux/pci_regs.h +++ b/include/standard-headers/linux/pci_regs.h @@ -517,6 +517,7 @@ #define PCI_EXP_LNKCAP_SLS 0x0000000f /* Supported Link Speeds */ #define PCI_EXP_LNKCAP_SLS_2_5GB 0x00000001 /* LNKCAP2 SLS Vector bit 0 */ #define PCI_EXP_LNKCAP_SLS_5_0GB 0x00000002 /* LNKCAP2 SLS Vector bit 1 */ +#define PCI_EXP_LNKCAP_SLS_8_0GB 0x00000003 /* LNKCAP2 SLS Vector bit 2 */ #define PCI_EXP_LNKCAP_MLW 0x000003f0 /* Maximum Link Width */ #define PCI_EXP_LNKCAP_ASPMS 0x00000c00 /* ASPM Support */ #define PCI_EXP_LNKCAP_L0SEL 0x00007000 /* L0s Exit Latency */ diff --git a/linux-headers/asm-arm/kvm.h b/linux-headers/asm-arm/kvm.h index 7258a00225..fa9fae8dc2 100644 --- a/linux-headers/asm-arm/kvm.h +++ b/linux-headers/asm-arm/kvm.h @@ -203,6 +203,14 @@ struct kvm_arch_memory_slot { #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK 0x3ff #define VGIC_LEVEL_INFO_LINE_LEVEL 0 +/* Device Control API on vcpu fd */ +#define KVM_ARM_VCPU_PMU_V3_CTRL 0 +#define KVM_ARM_VCPU_PMU_V3_IRQ 0 +#define KVM_ARM_VCPU_PMU_V3_INIT 1 +#define KVM_ARM_VCPU_TIMER_CTRL 1 +#define KVM_ARM_VCPU_TIMER_IRQ_VTIMER 0 +#define KVM_ARM_VCPU_TIMER_IRQ_PTIMER 1 + #define KVM_DEV_ARM_VGIC_CTRL_INIT 0 #define KVM_DEV_ARM_ITS_SAVE_TABLES 1 #define KVM_DEV_ARM_ITS_RESTORE_TABLES 2 diff --git a/linux-headers/asm-arm64/kvm.h b/linux-headers/asm-arm64/kvm.h index 31bb1dd924..d254700b08 100644 --- a/linux-headers/asm-arm64/kvm.h +++ b/linux-headers/asm-arm64/kvm.h @@ -232,6 +232,9 @@ struct kvm_arch_memory_slot { #define KVM_ARM_VCPU_PMU_V3_CTRL 0 #define KVM_ARM_VCPU_PMU_V3_IRQ 0 #define KVM_ARM_VCPU_PMU_V3_INIT 1 +#define KVM_ARM_VCPU_TIMER_CTRL 1 +#define KVM_ARM_VCPU_TIMER_IRQ_VTIMER 0 +#define KVM_ARM_VCPU_TIMER_IRQ_PTIMER 1 /* KVM_IRQ_LINE irq field index values */ #define KVM_ARM_IRQ_TYPE_SHIFT 24 diff --git a/linux-headers/asm-powerpc/kvm.h b/linux-headers/asm-powerpc/kvm.h index 07fbeb9278..8cf8f0c969 100644 --- a/linux-headers/asm-powerpc/kvm.h +++ b/linux-headers/asm-powerpc/kvm.h @@ -60,6 +60,12 @@ struct kvm_regs { #define KVM_SREGS_E_FSL_PIDn (1 << 0) /* PID1/PID2 */ +/* flags for kvm_run.flags */ +#define KVM_RUN_PPC_NMI_DISP_MASK (3 << 0) +#define KVM_RUN_PPC_NMI_DISP_FULLY_RECOV (1 << 0) +#define KVM_RUN_PPC_NMI_DISP_LIMITED_RECOV (2 << 0) +#define KVM_RUN_PPC_NMI_DISP_NOT_RECOV (3 << 0) + /* * Feature bits indicate which sections of the sregs struct are valid, * both in KVM_GET_SREGS and KVM_SET_SREGS. On KVM_SET_SREGS, registers diff --git a/linux-headers/asm-s390/kvm.h b/linux-headers/asm-s390/kvm.h index 243f195776..8387d71c7e 100644 --- a/linux-headers/asm-s390/kvm.h +++ b/linux-headers/asm-s390/kvm.h @@ -28,6 +28,7 @@ #define KVM_DEV_FLIC_CLEAR_IO_IRQ 8 #define KVM_DEV_FLIC_AISM 9 #define KVM_DEV_FLIC_AIRQ_INJECT 10 +#define KVM_DEV_FLIC_AISM_ALL 11 /* * We can have up to 4*64k pending subchannels + 8 adapter interrupts, * as well as up to ASYNC_PF_PER_VCPU*KVM_MAX_VCPUS pfault done interrupts. @@ -53,6 +54,11 @@ struct kvm_s390_ais_req { __u16 mode; }; +struct kvm_s390_ais_all { + __u8 simm; + __u8 nimm; +}; + #define KVM_S390_IO_ADAPTER_MASK 1 #define KVM_S390_IO_ADAPTER_MAP 2 #define KVM_S390_IO_ADAPTER_UNMAP 3 @@ -70,6 +76,7 @@ struct kvm_s390_io_adapter_req { #define KVM_S390_VM_TOD 1 #define KVM_S390_VM_CRYPTO 2 #define KVM_S390_VM_CPU_MODEL 3 +#define KVM_S390_VM_MIGRATION 4 /* kvm attributes for mem_ctrl */ #define KVM_S390_VM_MEM_ENABLE_CMMA 0 @@ -151,6 +158,11 @@ struct kvm_s390_vm_cpu_subfunc { #define KVM_S390_VM_CRYPTO_DISABLE_AES_KW 2 #define KVM_S390_VM_CRYPTO_DISABLE_DEA_KW 3 +/* kvm attributes for migration mode */ +#define KVM_S390_VM_MIGRATION_STOP 0 +#define KVM_S390_VM_MIGRATION_START 1 +#define KVM_S390_VM_MIGRATION_STATUS 2 + /* for KVM_GET_REGS and KVM_SET_REGS */ struct kvm_regs { /* general purpose regs for s390 */ diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h index d2892da172..43e2d82be1 100644 --- a/linux-headers/linux/kvm.h +++ b/linux-headers/linux/kvm.h @@ -155,6 +155,35 @@ struct kvm_s390_skeys { __u32 reserved[9]; }; +#define KVM_S390_CMMA_PEEK (1 << 0) + +/** + * kvm_s390_cmma_log - Used for CMMA migration. + * + * Used both for input and output. + * + * @start_gfn: Guest page number to start from. + * @count: Size of the result buffer. + * @flags: Control operation mode via KVM_S390_CMMA_* flags + * @remaining: Used with KVM_S390_GET_CMMA_BITS. Indicates how many dirty + * pages are still remaining. + * @mask: Used with KVM_S390_SET_CMMA_BITS. Bitmap of bits to actually set + * in the PGSTE. + * @values: Pointer to the values buffer. + * + * Used in KVM_S390_{G,S}ET_CMMA_BITS ioctls. + */ +struct kvm_s390_cmma_log { + __u64 start_gfn; + __u32 count; + __u32 flags; + union { + __u64 remaining; + __u64 mask; + }; + __u64 values; +}; + struct kvm_hyperv_exit { #define KVM_EXIT_HYPERV_SYNIC 1 #define KVM_EXIT_HYPERV_HCALL 2 @@ -895,6 +924,9 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_SPAPR_TCE_VFIO 142 #define KVM_CAP_X86_GUEST_MWAIT 143 #define KVM_CAP_ARM_USER_IRQ 144 +#define KVM_CAP_S390_CMMA_MIGRATION 145 +#define KVM_CAP_PPC_FWNMI 146 +#define KVM_CAP_PPC_SMT_POSSIBLE 147 #ifdef KVM_CAP_IRQ_ROUTING @@ -1318,6 +1350,9 @@ struct kvm_s390_ucas_mapping { #define KVM_S390_GET_IRQ_STATE _IOW(KVMIO, 0xb6, struct kvm_s390_irq_state) /* Available with KVM_CAP_X86_SMM */ #define KVM_SMI _IO(KVMIO, 0xb7) +/* Available with KVM_CAP_S390_CMMA_MIGRATION */ +#define KVM_S390_GET_CMMA_BITS _IOW(KVMIO, 0xb8, struct kvm_s390_cmma_log) +#define KVM_S390_SET_CMMA_BITS _IOW(KVMIO, 0xb9, struct kvm_s390_cmma_log) #define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0) #define KVM_DEV_ASSIGN_PCI_2_3 (1 << 1) From 903fd80b03243476a97522b79d4a7c8546dfe3df Mon Sep 17 00:00:00 2001 From: Claudio Imbrenda Date: Mon, 15 Aug 2016 18:43:14 +0200 Subject: [PATCH 03/40] s390x/migration: Storage attributes device Storage attributes device, like we have for storage keys. Signed-off-by: Claudio Imbrenda Signed-off-by: Christian Borntraeger --- hw/s390x/Makefile.objs | 2 + hw/s390x/s390-stattrib-kvm.c | 190 ++++++++++++++ hw/s390x/s390-stattrib.c | 342 ++++++++++++++++++++++++++ hw/s390x/s390-virtio-ccw.c | 10 +- include/hw/s390x/storage-attributes.h | 77 ++++++ 5 files changed, 620 insertions(+), 1 deletion(-) create mode 100644 hw/s390x/s390-stattrib-kvm.c create mode 100644 hw/s390x/s390-stattrib.c create mode 100644 include/hw/s390x/storage-attributes.h diff --git a/hw/s390x/Makefile.objs b/hw/s390x/Makefile.objs index a8e5575a8a..b2aade2466 100644 --- a/hw/s390x/Makefile.objs +++ b/hw/s390x/Makefile.objs @@ -13,5 +13,7 @@ obj-y += css-bridge.o obj-y += ccw-device.o obj-y += s390-pci-bus.o s390-pci-inst.o obj-y += s390-skeys.o +obj-y += s390-stattrib.o obj-$(CONFIG_KVM) += s390-skeys-kvm.o +obj-$(CONFIG_KVM) += s390-stattrib-kvm.o obj-y += s390-ccw.o diff --git a/hw/s390x/s390-stattrib-kvm.c b/hw/s390x/s390-stattrib-kvm.c new file mode 100644 index 0000000000..ff3f89fd2d --- /dev/null +++ b/hw/s390x/s390-stattrib-kvm.c @@ -0,0 +1,190 @@ +/* + * s390 storage attributes device -- KVM object + * + * Copyright 2016 IBM Corp. + * Author(s): Claudio Imbrenda + * + * 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. + */ + +#include "qemu/osdep.h" +#include "hw/boards.h" +#include "migration/qemu-file.h" +#include "hw/s390x/storage-attributes.h" +#include "qemu/error-report.h" +#include "sysemu/kvm.h" +#include "exec/ram_addr.h" +#include "cpu.h" + +Object *kvm_s390_stattrib_create(void) +{ + if (kvm_enabled() && + kvm_check_extension(kvm_state, KVM_CAP_S390_CMMA_MIGRATION)) { + return object_new(TYPE_KVM_S390_STATTRIB); + } + return NULL; +} + +static void kvm_s390_stattrib_instance_init(Object *obj) +{ + KVMS390StAttribState *sas = KVM_S390_STATTRIB(obj); + + sas->still_dirty = 0; +} + +static int kvm_s390_stattrib_read_helper(S390StAttribState *sa, + uint64_t *start_gfn, + uint32_t count, + uint8_t *values, + uint32_t flags) +{ + KVMS390StAttribState *sas = KVM_S390_STATTRIB(sa); + int r; + struct kvm_s390_cmma_log clog = { + .values = (uint64_t)values, + .start_gfn = *start_gfn, + .count = count, + .flags = flags, + }; + + r = kvm_vm_ioctl(kvm_state, KVM_S390_GET_CMMA_BITS, &clog); + if (r < 0) { + error_report("KVM_S390_GET_CMMA_BITS failed: %s", strerror(-r)); + return r; + } + + *start_gfn = clog.start_gfn; + sas->still_dirty = clog.remaining; + return clog.count; +} + +static int kvm_s390_stattrib_get_stattr(S390StAttribState *sa, + uint64_t *start_gfn, + uint32_t count, + uint8_t *values) +{ + return kvm_s390_stattrib_read_helper(sa, start_gfn, count, values, 0); +} + +static int kvm_s390_stattrib_peek_stattr(S390StAttribState *sa, + uint64_t start_gfn, + uint32_t count, + uint8_t *values) +{ + return kvm_s390_stattrib_read_helper(sa, &start_gfn, count, values, + KVM_S390_CMMA_PEEK); +} + +static int kvm_s390_stattrib_set_stattr(S390StAttribState *sa, + uint64_t start_gfn, + uint32_t count, + uint8_t *values) +{ + KVMS390StAttribState *sas = KVM_S390_STATTRIB(sa); + MachineState *machine = MACHINE(qdev_get_machine()); + unsigned long max = machine->maxram_size / TARGET_PAGE_SIZE; + + if (start_gfn + count > max) { + error_report("Out of memory bounds when setting storage attributes"); + return -1; + } + if (!sas->incoming_buffer) { + sas->incoming_buffer = g_malloc0(max); + } + + memcpy(sas->incoming_buffer + start_gfn, values, count); + + return 0; +} + +static void kvm_s390_stattrib_synchronize(S390StAttribState *sa) +{ + KVMS390StAttribState *sas = KVM_S390_STATTRIB(sa); + MachineState *machine = MACHINE(qdev_get_machine()); + unsigned long max = machine->maxram_size / TARGET_PAGE_SIZE; + unsigned long cx, len = 1 << 19; + int r; + struct kvm_s390_cmma_log clog = { + .flags = 0, + .mask = ~0ULL, + }; + + if (sas->incoming_buffer) { + for (cx = 0; cx + len <= max; cx += len) { + clog.start_gfn = cx; + clog.count = len; + clog.values = (uint64_t)(sas->incoming_buffer + cx * len); + r = kvm_vm_ioctl(kvm_state, KVM_S390_SET_CMMA_BITS, &clog); + if (r) { + error_report("KVM_S390_SET_CMMA_BITS failed: %s", strerror(-r)); + return; + } + } + if (cx < max) { + clog.start_gfn = cx; + clog.count = max - cx; + clog.values = (uint64_t)(sas->incoming_buffer + cx * len); + r = kvm_vm_ioctl(kvm_state, KVM_S390_SET_CMMA_BITS, &clog); + if (r) { + error_report("KVM_S390_SET_CMMA_BITS failed: %s", strerror(-r)); + } + } + g_free(sas->incoming_buffer); + sas->incoming_buffer = NULL; + } +} + +static int kvm_s390_stattrib_set_migrationmode(S390StAttribState *sa, bool val) +{ + struct kvm_device_attr attr = { + .group = KVM_S390_VM_MIGRATION, + .attr = val, + .addr = 0, + }; + return kvm_vm_ioctl(kvm_state, KVM_SET_DEVICE_ATTR, &attr); +} + +static long long kvm_s390_stattrib_get_dirtycount(S390StAttribState *sa) +{ + KVMS390StAttribState *sas = KVM_S390_STATTRIB(sa); + uint8_t val[8]; + + kvm_s390_stattrib_peek_stattr(sa, 0, 1, val); + return sas->still_dirty; +} + +static int kvm_s390_stattrib_get_active(S390StAttribState *sa) +{ + return kvm_s390_cmma_active() && sa->migration_enabled; +} + +static void kvm_s390_stattrib_class_init(ObjectClass *oc, void *data) +{ + S390StAttribClass *sac = S390_STATTRIB_CLASS(oc); + + sac->get_stattr = kvm_s390_stattrib_get_stattr; + sac->peek_stattr = kvm_s390_stattrib_peek_stattr; + sac->set_stattr = kvm_s390_stattrib_set_stattr; + sac->set_migrationmode = kvm_s390_stattrib_set_migrationmode; + sac->get_dirtycount = kvm_s390_stattrib_get_dirtycount; + sac->synchronize = kvm_s390_stattrib_synchronize; + sac->get_active = kvm_s390_stattrib_get_active; +} + +static const TypeInfo kvm_s390_stattrib_info = { + .name = TYPE_KVM_S390_STATTRIB, + .parent = TYPE_S390_STATTRIB, + .instance_init = kvm_s390_stattrib_instance_init, + .instance_size = sizeof(KVMS390StAttribState), + .class_init = kvm_s390_stattrib_class_init, + .class_size = sizeof(S390StAttribClass), +}; + +static void kvm_s390_stattrib_register_types(void) +{ + type_register_static(&kvm_s390_stattrib_info); +} + +type_init(kvm_s390_stattrib_register_types) diff --git a/hw/s390x/s390-stattrib.c b/hw/s390x/s390-stattrib.c new file mode 100644 index 0000000000..922b75638e --- /dev/null +++ b/hw/s390x/s390-stattrib.c @@ -0,0 +1,342 @@ +/* + * s390 storage attributes device + * + * Copyright 2016 IBM Corp. + * Author(s): Claudio Imbrenda + * + * 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. + */ + +#include "qemu/osdep.h" +#include "hw/boards.h" +#include "migration/qemu-file.h" +#include "migration/register.h" +#include "hw/s390x/storage-attributes.h" +#include "qemu/error-report.h" +#include "sysemu/kvm.h" +#include "exec/ram_addr.h" +#include "qapi/error.h" + +#define CMMA_BLOCK_SIZE (1 << 10) + +#define STATTR_FLAG_EOS 0x01ULL +#define STATTR_FLAG_MORE 0x02ULL +#define STATTR_FLAG_ERROR 0x04ULL +#define STATTR_FLAG_DONE 0x08ULL + +void s390_stattrib_init(void) +{ + Object *obj; + + obj = kvm_s390_stattrib_create(); + if (!obj) { + obj = object_new(TYPE_QEMU_S390_STATTRIB); + } + + object_property_add_child(qdev_get_machine(), TYPE_S390_STATTRIB, + obj, NULL); + object_unref(obj); + + qdev_init_nofail(DEVICE(obj)); +} + +/* Migration support: */ + +static int cmma_load(QEMUFile *f, void *opaque, int version_id) +{ + S390StAttribState *sas = S390_STATTRIB(opaque); + S390StAttribClass *sac = S390_STATTRIB_GET_CLASS(sas); + uint64_t count, cur_gfn; + int flags, ret = 0; + ram_addr_t addr; + uint8_t *buf; + + while (!ret) { + addr = qemu_get_be64(f); + flags = addr & ~TARGET_PAGE_MASK; + addr &= TARGET_PAGE_MASK; + + switch (flags) { + case STATTR_FLAG_MORE: { + cur_gfn = addr / TARGET_PAGE_SIZE; + count = qemu_get_be64(f); + buf = g_try_malloc(count); + if (!buf) { + error_report("cmma_load could not allocate memory"); + ret = -ENOMEM; + break; + } + + qemu_get_buffer(f, buf, count); + ret = sac->set_stattr(sas, cur_gfn, count, buf); + if (ret < 0) { + error_report("Error %d while setting storage attributes", ret); + } + g_free(buf); + break; + } + case STATTR_FLAG_ERROR: { + error_report("Storage attributes data is incomplete"); + ret = -EINVAL; + break; + } + case STATTR_FLAG_DONE: + /* This is after the last pre-copied value has been sent, nothing + * more will be sent after this. Pre-copy has finished, and we + * are done flushing all the remaining values. Now the target + * system is about to take over. We synchronize the buffer to + * apply the actual correct values where needed. + */ + sac->synchronize(sas); + break; + case STATTR_FLAG_EOS: + /* Normal exit */ + return 0; + default: + error_report("Unexpected storage attribute flag data: %#x", flags); + ret = -EINVAL; + } + } + + return ret; +} + +static int cmma_save_setup(QEMUFile *f, void *opaque) +{ + S390StAttribState *sas = S390_STATTRIB(opaque); + S390StAttribClass *sac = S390_STATTRIB_GET_CLASS(sas); + int res; + /* + * Signal that we want to start a migration, thus needing PGSTE dirty + * tracking. + */ + res = sac->set_migrationmode(sas, 1); + if (res) { + return res; + } + qemu_put_be64(f, STATTR_FLAG_EOS); + return 0; +} + +static void cmma_save_pending(QEMUFile *f, void *opaque, uint64_t max_size, + uint64_t *non_postcopiable_pending, + uint64_t *postcopiable_pending) +{ + S390StAttribState *sas = S390_STATTRIB(opaque); + S390StAttribClass *sac = S390_STATTRIB_GET_CLASS(sas); + long long res = sac->get_dirtycount(sas); + + if (res >= 0) { + *non_postcopiable_pending += res; + } +} + +static int cmma_save(QEMUFile *f, void *opaque, int final) +{ + S390StAttribState *sas = S390_STATTRIB(opaque); + S390StAttribClass *sac = S390_STATTRIB_GET_CLASS(sas); + uint8_t *buf; + int r, cx, reallen = 0, ret = 0; + uint32_t buflen = 1 << 19; /* 512kB cover 2GB of guest memory */ + uint64_t start_gfn = sas->migration_cur_gfn; + + buf = g_try_malloc(buflen); + if (!buf) { + error_report("Could not allocate memory to save storage attributes"); + return -ENOMEM; + } + + while (final ? 1 : qemu_file_rate_limit(f) == 0) { + reallen = sac->get_stattr(sas, &start_gfn, buflen, buf); + if (reallen < 0) { + g_free(buf); + return reallen; + } + + ret = 1; + if (!reallen) { + break; + } + qemu_put_be64(f, (start_gfn << TARGET_PAGE_BITS) | STATTR_FLAG_MORE); + qemu_put_be64(f, reallen); + for (cx = 0; cx < reallen; cx++) { + qemu_put_byte(f, buf[cx]); + } + if (!sac->get_dirtycount(sas)) { + break; + } + } + + sas->migration_cur_gfn = start_gfn + reallen; + g_free(buf); + if (final) { + qemu_put_be64(f, STATTR_FLAG_DONE); + } + qemu_put_be64(f, STATTR_FLAG_EOS); + + r = qemu_file_get_error(f); + if (r < 0) { + return r; + } + + return ret; +} + +static int cmma_save_iterate(QEMUFile *f, void *opaque) +{ + return cmma_save(f, opaque, 0); +} + +static int cmma_save_complete(QEMUFile *f, void *opaque) +{ + return cmma_save(f, opaque, 1); +} + +static void cmma_save_cleanup(void *opaque) +{ + S390StAttribState *sas = S390_STATTRIB(opaque); + S390StAttribClass *sac = S390_STATTRIB_GET_CLASS(sas); + sac->set_migrationmode(sas, 0); +} + +static bool cmma_active(void *opaque) +{ + S390StAttribState *sas = S390_STATTRIB(opaque); + S390StAttribClass *sac = S390_STATTRIB_GET_CLASS(sas); + return sac->get_active(sas); +} + +/* QEMU object: */ + +static void qemu_s390_stattrib_instance_init(Object *obj) +{ +} + +static int qemu_s390_peek_stattr_stub(S390StAttribState *sa, uint64_t start_gfn, + uint32_t count, uint8_t *values) +{ + return 0; +} +static void qemu_s390_synchronize_stub(S390StAttribState *sa) +{ +} +static int qemu_s390_get_stattr_stub(S390StAttribState *sa, uint64_t *start_gfn, + uint32_t count, uint8_t *values) +{ + return 0; +} +static long long qemu_s390_get_dirtycount_stub(S390StAttribState *sa) +{ + return 0; +} +static int qemu_s390_set_migrationmode_stub(S390StAttribState *sa, bool value) +{ + return 0; +} + +static int qemu_s390_get_active(S390StAttribState *sa) +{ + return sa->migration_enabled; +} + +static void qemu_s390_stattrib_class_init(ObjectClass *oc, void *data) +{ + S390StAttribClass *sa_cl = S390_STATTRIB_CLASS(oc); + + sa_cl->synchronize = qemu_s390_synchronize_stub; + sa_cl->get_stattr = qemu_s390_get_stattr_stub; + sa_cl->set_stattr = qemu_s390_peek_stattr_stub; + sa_cl->peek_stattr = qemu_s390_peek_stattr_stub; + sa_cl->set_migrationmode = qemu_s390_set_migrationmode_stub; + sa_cl->get_dirtycount = qemu_s390_get_dirtycount_stub; + sa_cl->get_active = qemu_s390_get_active; +} + +static const TypeInfo qemu_s390_stattrib_info = { + .name = TYPE_QEMU_S390_STATTRIB, + .parent = TYPE_S390_STATTRIB, + .instance_init = qemu_s390_stattrib_instance_init, + .instance_size = sizeof(QEMUS390StAttribState), + .class_init = qemu_s390_stattrib_class_init, + .class_size = sizeof(S390StAttribClass), +}; + +/* Generic abstract object: */ + +static void s390_stattrib_realize(DeviceState *dev, Error **errp) +{ + bool ambiguous = false; + + object_resolve_path_type("", TYPE_S390_STATTRIB, &ambiguous); + if (ambiguous) { + error_setg(errp, "storage_attributes device already exists"); + } +} + +static void s390_stattrib_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->hotpluggable = false; + set_bit(DEVICE_CATEGORY_MISC, dc->categories); + dc->realize = s390_stattrib_realize; +} + +static inline bool s390_stattrib_get_migration_enabled(Object *obj, Error **e) +{ + S390StAttribState *s = S390_STATTRIB(obj); + + return s->migration_enabled; +} + +static inline void s390_stattrib_set_migration_enabled(Object *obj, bool value, + Error **errp) +{ + S390StAttribState *s = S390_STATTRIB(obj); + + s->migration_enabled = value; +} + +static void s390_stattrib_instance_init(Object *obj) +{ + S390StAttribState *sas = S390_STATTRIB(obj); + SaveVMHandlers *ops; + + /* ops will always be freed by qemu when unregistering */ + ops = g_new0(SaveVMHandlers, 1); + + ops->save_setup = cmma_save_setup; + ops->save_live_iterate = cmma_save_iterate; + ops->save_live_complete_precopy = cmma_save_complete; + ops->save_live_pending = cmma_save_pending; + ops->save_cleanup = cmma_save_cleanup; + ops->load_state = cmma_load; + ops->is_active = cmma_active; + register_savevm_live(NULL, TYPE_S390_STATTRIB, 0, 0, ops, sas); + + object_property_add_bool(obj, "migration-enabled", + s390_stattrib_get_migration_enabled, + s390_stattrib_set_migration_enabled, NULL); + object_property_set_bool(obj, true, "migration-enabled", NULL); + sas->migration_cur_gfn = 0; +} + +static const TypeInfo s390_stattrib_info = { + .name = TYPE_S390_STATTRIB, + .parent = TYPE_DEVICE, + .instance_init = s390_stattrib_instance_init, + .instance_size = sizeof(S390StAttribState), + .class_init = s390_stattrib_class_init, + .class_size = sizeof(S390StAttribClass), + .abstract = true, +}; + +static void s390_stattrib_register_types(void) +{ + type_register_static(&s390_stattrib_info); + type_register_static(&qemu_s390_stattrib_info); +} + +type_init(s390_stattrib_register_types) diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index 41ca6668e2..0c8f758130 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -24,6 +24,7 @@ #include "qemu/config-file.h" #include "s390-pci-bus.h" #include "hw/s390x/storage-keys.h" +#include "hw/s390x/storage-attributes.h" #include "hw/compat.h" #include "ipl.h" #include "hw/s390x/s390-virtio-ccw.h" @@ -103,6 +104,8 @@ void s390_memory_init(ram_addr_t mem_size) /* Initialize storage key device */ s390_skeys_init(); + /* Initialize storage attributes device */ + s390_stattrib_init(); } static SaveVMHandlers savevm_gtod = { @@ -406,7 +409,12 @@ static const TypeInfo ccw_machine_info = { type_init(ccw_machine_register_##suffix) #define CCW_COMPAT_2_9 \ - HW_COMPAT_2_9 + HW_COMPAT_2_9 \ + {\ + .driver = TYPE_S390_STATTRIB,\ + .property = "migration-enabled",\ + .value = "off",\ + }, #define CCW_COMPAT_2_8 \ HW_COMPAT_2_8 \ diff --git a/include/hw/s390x/storage-attributes.h b/include/hw/s390x/storage-attributes.h new file mode 100644 index 0000000000..678df958e8 --- /dev/null +++ b/include/hw/s390x/storage-attributes.h @@ -0,0 +1,77 @@ +/* + * s390 storage attributes device + * + * Copyright 2016 IBM Corp. + * Author(s): Claudio Imbrenda + * + * 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 S390_STORAGE_ATTRIBUTES_H +#define S390_STORAGE_ATTRIBUTES_H + +#include + +#define TYPE_S390_STATTRIB "s390-storage_attributes" +#define TYPE_QEMU_S390_STATTRIB "s390-storage_attributes-qemu" +#define TYPE_KVM_S390_STATTRIB "s390-storage_attributes-kvm" + +#define S390_STATTRIB(obj) \ + OBJECT_CHECK(S390StAttribState, (obj), TYPE_S390_STATTRIB) + +typedef struct S390StAttribState { + DeviceState parent_obj; + uint64_t migration_cur_gfn; + bool migration_enabled; +} S390StAttribState; + +#define S390_STATTRIB_CLASS(klass) \ + OBJECT_CLASS_CHECK(S390StAttribClass, (klass), TYPE_S390_STATTRIB) +#define S390_STATTRIB_GET_CLASS(obj) \ + OBJECT_GET_CLASS(S390StAttribClass, (obj), TYPE_S390_STATTRIB) + +typedef struct S390StAttribClass { + DeviceClass parent_class; + /* Return value: < 0 on error, or new count */ + int (*get_stattr)(S390StAttribState *sa, uint64_t *start_gfn, + uint32_t count, uint8_t *values); + int (*peek_stattr)(S390StAttribState *sa, uint64_t start_gfn, + uint32_t count, uint8_t *values); + int (*set_stattr)(S390StAttribState *sa, uint64_t start_gfn, + uint32_t count, uint8_t *values); + void (*synchronize)(S390StAttribState *sa); + int (*set_migrationmode)(S390StAttribState *sa, bool value); + int (*get_active)(S390StAttribState *sa); + long long (*get_dirtycount)(S390StAttribState *sa); +} S390StAttribClass; + +#define QEMU_S390_STATTRIB(obj) \ + OBJECT_CHECK(QEMUS390StAttribState, (obj), TYPE_QEMU_S390_STATTRIB) + +typedef struct QEMUS390StAttribState { + S390StAttribState parent_obj; +} QEMUS390StAttribState; + +#define KVM_S390_STATTRIB(obj) \ + OBJECT_CHECK(KVMS390StAttribState, (obj), TYPE_KVM_S390_STATTRIB) + +typedef struct KVMS390StAttribState { + S390StAttribState parent_obj; + uint64_t still_dirty; + uint8_t *incoming_buffer; +} KVMS390StAttribState; + +void s390_stattrib_init(void); + +#ifdef CONFIG_KVM +Object *kvm_s390_stattrib_create(void); +#else +static inline Object *kvm_s390_stattrib_create(void) +{ + return NULL; +} +#endif + +#endif /* S390_STORAGE_ATTRIBUTES_H */ From f860d49753300d4e57f49e4d9016e79e5c5ac2ee Mon Sep 17 00:00:00 2001 From: Claudio Imbrenda Date: Mon, 15 Aug 2016 18:44:04 +0200 Subject: [PATCH 04/40] s390x/migration: Monitor commands for storage attributes Add an "info" monitor command to non-destructively inspect the state of the storage attributes of the guest, and a normal command to toggle migration mode (useful for debugging). Signed-off-by: Claudio Imbrenda Acked-by: Cornelia Huck Signed-off-by: Christian Borntraeger --- hmp-commands-info.hx | 16 +++++++ hmp-commands.hx | 16 +++++++ hw/s390x/s390-stattrib.c | 62 +++++++++++++++++++++++++++ include/hw/s390x/storage-attributes.h | 4 ++ monitor.c | 1 + 5 files changed, 99 insertions(+) diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx index 07500ef787..d9df238a5f 100644 --- a/hmp-commands-info.hx +++ b/hmp-commands-info.hx @@ -775,6 +775,22 @@ STEXI @item info skeys @var{address} @findex skeys Display the value of a storage key (s390 only) +ETEXI + +#if defined(TARGET_S390X) + { + .name = "cmma", + .args_type = "addr:l,count:l?", + .params = "address [count]", + .help = "Display the values of the CMMA storage attributes for a range of pages", + .cmd = hmp_info_cmma, + }, +#endif + +STEXI +@item info cmma @var{address} +@findex cmma +Display the values of the CMMA storage attributes for a range of pages (s390 only) ETEXI { diff --git a/hmp-commands.hx b/hmp-commands.hx index 75f8bac01b..f93bc15aea 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1151,6 +1151,22 @@ STEXI @item dump-skeys @var{filename} @findex dump-skeys Save guest storage keys to a file. +ETEXI + +#if defined(TARGET_S390X) + { + .name = "migration_mode", + .args_type = "mode:i", + .params = "mode", + .help = "Enables or disables migration mode\n", + .cmd = hmp_migrationmode, + }, +#endif + +STEXI +@item migration_mode @var{mode} +@findex migration_mode +Enables or disables migration mode. ETEXI { diff --git a/hw/s390x/s390-stattrib.c b/hw/s390x/s390-stattrib.c index 922b75638e..d14923f099 100644 --- a/hw/s390x/s390-stattrib.c +++ b/hw/s390x/s390-stattrib.c @@ -11,6 +11,7 @@ #include "qemu/osdep.h" #include "hw/boards.h" +#include "qmp-commands.h" #include "migration/qemu-file.h" #include "migration/register.h" #include "hw/s390x/storage-attributes.h" @@ -26,6 +27,15 @@ #define STATTR_FLAG_ERROR 0x04ULL #define STATTR_FLAG_DONE 0x08ULL +static S390StAttribState *s390_get_stattrib_device(void) +{ + S390StAttribState *sas; + + sas = S390_STATTRIB(object_resolve_path_type("", TYPE_S390_STATTRIB, NULL)); + assert(sas); + return sas; +} + void s390_stattrib_init(void) { Object *obj; @@ -42,6 +52,58 @@ void s390_stattrib_init(void) qdev_init_nofail(DEVICE(obj)); } +/* Console commands: */ + +void hmp_migrationmode(Monitor *mon, const QDict *qdict) +{ + S390StAttribState *sas = s390_get_stattrib_device(); + S390StAttribClass *sac = S390_STATTRIB_GET_CLASS(sas); + uint64_t what = qdict_get_int(qdict, "mode"); + int r; + + r = sac->set_migrationmode(sas, what); + if (r < 0) { + monitor_printf(mon, "Error: %s", strerror(-r)); + } +} + +void hmp_info_cmma(Monitor *mon, const QDict *qdict) +{ + S390StAttribState *sas = s390_get_stattrib_device(); + S390StAttribClass *sac = S390_STATTRIB_GET_CLASS(sas); + uint64_t addr = qdict_get_int(qdict, "addr"); + uint64_t buflen = qdict_get_try_int(qdict, "count", 8); + uint8_t *vals; + int cx, len; + + vals = g_try_malloc(buflen); + if (!vals) { + monitor_printf(mon, "Error: %s\n", strerror(errno)); + return; + } + + len = sac->peek_stattr(sas, addr / TARGET_PAGE_SIZE, buflen, vals); + if (len < 0) { + monitor_printf(mon, "Error: %s", strerror(-len)); + goto out; + } + + monitor_printf(mon, " CMMA attributes, " + "pages %" PRIu64 "+%d (0x%" PRIx64 "):\n", + addr / TARGET_PAGE_SIZE, len, addr & ~TARGET_PAGE_MASK); + for (cx = 0; cx < len; cx++) { + if (cx % 8 == 7) { + monitor_printf(mon, "%02x\n", vals[cx]); + } else { + monitor_printf(mon, "%02x", vals[cx]); + } + } + monitor_printf(mon, "\n"); + +out: + g_free(vals); +} + /* Migration support: */ static int cmma_load(QEMUFile *f, void *opaque, int version_id) diff --git a/include/hw/s390x/storage-attributes.h b/include/hw/s390x/storage-attributes.h index 678df958e8..9be954d163 100644 --- a/include/hw/s390x/storage-attributes.h +++ b/include/hw/s390x/storage-attributes.h @@ -13,6 +13,7 @@ #define S390_STORAGE_ATTRIBUTES_H #include +#include "monitor/monitor.h" #define TYPE_S390_STATTRIB "s390-storage_attributes" #define TYPE_QEMU_S390_STATTRIB "s390-storage_attributes-qemu" @@ -74,4 +75,7 @@ static inline Object *kvm_s390_stattrib_create(void) } #endif +void hmp_info_cmma(Monitor *mon, const QDict *qdict); +void hmp_migrationmode(Monitor *mon, const QDict *qdict); + #endif /* S390_STORAGE_ATTRIBUTES_H */ diff --git a/monitor.c b/monitor.c index 12935a7d71..6a7c98848f 100644 --- a/monitor.c +++ b/monitor.c @@ -81,6 +81,7 @@ #if defined(TARGET_S390X) #include "hw/s390x/storage-keys.h" +#include "hw/s390x/storage-attributes.h" #endif /* From ec3aadb13ed601f8d77bd4efd80b545ddc84c697 Mon Sep 17 00:00:00 2001 From: "Jason J. Herne" Date: Wed, 22 Feb 2017 10:32:20 -0500 Subject: [PATCH 05/40] s390x/cpumodel: clean up spacing and comments Clean up spacing and add comments to clarify difference between base, full and default models. Not having spacing around the model definitions in gen-features.c is particularly frustrating as the reader tends to misinterpret which model they are looking at or editing. Signed-off-by: Jason J. Herne Acked-by: Christian Borntraeger Acked-by: Cornelia Huck Signed-off-by: Christian Borntraeger --- target/s390x/cpu_features.c | 3 ++ target/s390x/cpu_features_def.h | 35 ++++++++++++++++++++ target/s390x/gen-features.c | 58 +++++++++++++++++++++++++++++++-- 3 files changed, 93 insertions(+), 3 deletions(-) diff --git a/target/s390x/cpu_features.c b/target/s390x/cpu_features.c index 42fd9d792b..0436dc25d3 100644 --- a/target/s390x/cpu_features.c +++ b/target/s390x/cpu_features.c @@ -83,9 +83,11 @@ static const S390FeatDef s390_features[] = { FEAT_INIT("dfppc", S390_FEAT_TYPE_STFL, 80, "Decimal-floating-point packed-conversion facility"), FEAT_INIT("vx", S390_FEAT_TYPE_STFL, 129, "Vector facility"), + /* SCLP SCCB Byte 80 - 98 (bit numbers relative to byte-80) */ FEAT_INIT("gsls", S390_FEAT_TYPE_SCLP_CONF_CHAR, 40, "SIE: Guest-storage-limit-suppression facility"), FEAT_INIT("esop", S390_FEAT_TYPE_SCLP_CONF_CHAR, 46, "Enhanced-suppression-on-protection facility"), + /* SCLP SCCB Byte 116 - 119 (bit numbers relative to byte-116) */ FEAT_INIT("64bscao", S390_FEAT_TYPE_SCLP_CONF_CHAR_EXT, 0, "SIE: 64-bit-SCAO facility"), FEAT_INIT("cmma", S390_FEAT_TYPE_SCLP_CONF_CHAR_EXT, 1, "SIE: Collaborative-memory-management assist"), FEAT_INIT("pfmfi", S390_FEAT_TYPE_SCLP_CONF_CHAR_EXT, 9, "SIE: PFMF interpretation facility"), @@ -183,6 +185,7 @@ static const S390FeatDef s390_features[] = { FEAT_INIT("kimd-sha-256", S390_FEAT_TYPE_KIMD, 2, "KIMD SHA-256"), FEAT_INIT("kimd-sha-512", S390_FEAT_TYPE_KIMD, 3, "KIMD SHA-512"), FEAT_INIT("kimd-ghash", S390_FEAT_TYPE_KIMD, 65, "KIMD GHASH"), + FEAT_INIT("klmd-sha-1", S390_FEAT_TYPE_KLMD, 1, "KLMD SHA-1"), FEAT_INIT("klmd-sha-256", S390_FEAT_TYPE_KLMD, 2, "KLMD SHA-256"), FEAT_INIT("klmd-sha-512", S390_FEAT_TYPE_KLMD, 3, "KLMD SHA-512"), diff --git a/target/s390x/cpu_features_def.h b/target/s390x/cpu_features_def.h index aa5ab8d371..f5bb7ed4b6 100644 --- a/target/s390x/cpu_features_def.h +++ b/target/s390x/cpu_features_def.h @@ -15,6 +15,7 @@ #define TARGET_S390X_CPU_FEATURES_DEF_H typedef enum { + /* Stfle */ S390_FEAT_ESAN3 = 0, S390_FEAT_ZARCH, S390_FEAT_DAT_ENH, @@ -72,12 +73,18 @@ typedef enum { S390_FEAT_EDAT_2, S390_FEAT_DFP_PACKED_CONVERSION, S390_FEAT_VECTOR, + + /* Sclp Conf Char */ S390_FEAT_SIE_GSLS, S390_FEAT_ESOP, + + /* Sclp Conf Char Ext */ S390_FEAT_SIE_64BSCAO, S390_FEAT_SIE_CMMA, S390_FEAT_SIE_PFMFI, S390_FEAT_SIE_IBS, + + /* Sclp Cpu */ S390_FEAT_SIE_F2, S390_FEAT_SIE_SKEY, S390_FEAT_SIE_GPERE, @@ -85,8 +92,12 @@ typedef enum { S390_FEAT_SIE_SIGPIF, S390_FEAT_SIE_IB, S390_FEAT_SIE_CEI, + + /* Misc */ S390_FEAT_DAT_ENH_2, S390_FEAT_CMM, + + /* PLO */ S390_FEAT_PLO_CL, S390_FEAT_PLO_CLG, S390_FEAT_PLO_CLGR, @@ -111,6 +122,8 @@ typedef enum { S390_FEAT_PLO_CSTSTG, S390_FEAT_PLO_CSTSTGR, S390_FEAT_PLO_CSTSTX, + + /* PTFF */ S390_FEAT_PTFF_QTO, S390_FEAT_PTFF_QSI, S390_FEAT_PTFF_QPT, @@ -118,6 +131,8 @@ typedef enum { S390_FEAT_PTFF_QTOU, S390_FEAT_PTFF_STO, S390_FEAT_PTFF_STOU, + + /* KMAC */ S390_FEAT_KMAC_DEA, S390_FEAT_KMAC_TDEA_128, S390_FEAT_KMAC_TDEA_192, @@ -130,6 +145,8 @@ typedef enum { S390_FEAT_KMAC_EAES_128, S390_FEAT_KMAC_EAES_192, S390_FEAT_KMAC_EAES_256, + + /* KMC */ S390_FEAT_KMC_DEA, S390_FEAT_KMC_TDEA_128, S390_FEAT_KMC_TDEA_192, @@ -143,6 +160,8 @@ typedef enum { S390_FEAT_KMC_EAES_192, S390_FEAT_KMC_EAES_256, S390_FEAT_KMC_PRNG, + + /* KM */ S390_FEAT_KM_DEA, S390_FEAT_KM_TDEA_128, S390_FEAT_KM_TDEA_192, @@ -159,19 +178,27 @@ typedef enum { S390_FEAT_KM_XTS_AES_256, S390_FEAT_KM_XTS_EAES_128, S390_FEAT_KM_XTS_EAES_256, + + /* KIMD */ S390_FEAT_KIMD_SHA_1, S390_FEAT_KIMD_SHA_256, S390_FEAT_KIMD_SHA_512, S390_FEAT_KIMD_GHASH, + + /* KLMD */ S390_FEAT_KLMD_SHA_1, S390_FEAT_KLMD_SHA_256, S390_FEAT_KLMD_SHA_512, + + /* PCKMO */ S390_FEAT_PCKMO_EDEA, S390_FEAT_PCKMO_ETDEA_128, S390_FEAT_PCKMO_ETDEA_256, S390_FEAT_PCKMO_AES_128, S390_FEAT_PCKMO_AES_192, S390_FEAT_PCKMO_AES_256, + + /* KMCTR */ S390_FEAT_KMCTR_DEA, S390_FEAT_KMCTR_TDEA_128, S390_FEAT_KMCTR_TDEA_192, @@ -184,6 +211,8 @@ typedef enum { S390_FEAT_KMCTR_EAES_128, S390_FEAT_KMCTR_EAES_192, S390_FEAT_KMCTR_EAES_256, + + /* KMF */ S390_FEAT_KMF_DEA, S390_FEAT_KMF_TDEA_128, S390_FEAT_KMF_TDEA_192, @@ -196,6 +225,8 @@ typedef enum { S390_FEAT_KMF_EAES_128, S390_FEAT_KMF_EAES_192, S390_FEAT_KMF_EAES_256, + + /* KMO */ S390_FEAT_KMO_DEA, S390_FEAT_KMO_TDEA_128, S390_FEAT_KMO_TDEA_192, @@ -208,6 +239,8 @@ typedef enum { S390_FEAT_KMO_EAES_128, S390_FEAT_KMO_EAES_192, S390_FEAT_KMO_EAES_256, + + /* PCC */ S390_FEAT_PCC_CMAC_DEA, S390_FEAT_PCC_CMAC_TDEA_128, S390_FEAT_PCC_CMAC_TDEA_192, @@ -224,6 +257,8 @@ typedef enum { S390_FEAT_PCC_XTS_AES_256, S390_FEAT_PCC_XTS_EAES_128, S390_FEAT_PCC_XTS_EAES_256, + + /* PPNO */ S390_FEAT_PPNO_SHA_512_DRNG, S390_FEAT_MAX, } S390Feat; diff --git a/target/s390x/gen-features.c b/target/s390x/gen-features.c index e674738ae3..8ca2b47fe8 100644 --- a/target/s390x/gen-features.c +++ b/target/s390x/gen-features.c @@ -211,14 +211,20 @@ static uint16_t group_MSA_EXT_5[] = { S390_FEAT_GROUP_MSA_EXT_5, }; -/* base features in order of release */ +/* Base features (in order of release) + * Only non-hypervisor managed features belong here. + * Base feature sets are static meaning they do not change in future QEMU + * releases. + */ static uint16_t base_GEN7_GA1[] = { S390_FEAT_GROUP_PLO, S390_FEAT_ESAN3, S390_FEAT_ZARCH, }; + #define base_GEN7_GA2 EmptyFeat #define base_GEN7_GA3 EmptyFeat + static uint16_t base_GEN8_GA1[] = { S390_FEAT_DAT_ENH, S390_FEAT_EXTENDED_TRANSLATION_2, @@ -227,10 +233,12 @@ static uint16_t base_GEN8_GA1[] = { S390_FEAT_LONG_DISPLACEMENT_FAST, S390_FEAT_HFP_MADDSUB, }; + #define base_GEN8_GA2 EmptyFeat #define base_GEN8_GA3 EmptyFeat #define base_GEN8_GA4 EmptyFeat #define base_GEN8_GA5 EmptyFeat + static uint16_t base_GEN9_GA1[] = { S390_FEAT_IDTE_SEGMENT, S390_FEAT_ASN_LX_REUSE, @@ -245,8 +253,10 @@ static uint16_t base_GEN9_GA1[] = { S390_FEAT_ETF3_ENH, S390_FEAT_DAT_ENH_2, }; + #define base_GEN9_GA2 EmptyFeat #define base_GEN9_GA3 EmptyFeat + static uint16_t base_GEN10_GA1[] = { S390_FEAT_CONDITIONAL_SSKE, S390_FEAT_PARSING_ENH, @@ -263,6 +273,7 @@ static uint16_t base_GEN10_GA1[] = { }; #define base_GEN10_GA2 EmptyFeat #define base_GEN10_GA3 EmptyFeat + static uint16_t base_GEN11_GA1[] = { S390_FEAT_NONQ_KEY_SETTING, S390_FEAT_ENHANCED_MONITOR, @@ -272,21 +283,30 @@ static uint16_t base_GEN11_GA1[] = { S390_FEAT_CMPSC_ENH, S390_FEAT_INTERLOCKED_ACCESS_2, }; + #define base_GEN11_GA2 EmptyFeat + static uint16_t base_GEN12_GA1[] = { S390_FEAT_DFP_ZONED_CONVERSION, S390_FEAT_STFLE_49, S390_FEAT_LOCAL_TLB_CLEARING, }; + #define base_GEN12_GA2 EmptyFeat + static uint16_t base_GEN13_GA1[] = { S390_FEAT_STFLE_53, S390_FEAT_DFP_PACKED_CONVERSION, S390_FEAT_GROUP_GEN13_PTFF, }; + #define base_GEN13_GA2 EmptyFeat -/* full features differing to the base in order of release */ +/* Full features (in order of release) + * Automatically includes corresponding base features. + * Full features are all features this hardware supports even if kvm/QEMU do not + * support these features yet. + */ static uint16_t full_GEN7_GA1[] = { S390_FEAT_SIE_F2, S390_FEAT_SIE_SKEY, @@ -294,30 +314,38 @@ static uint16_t full_GEN7_GA1[] = { S390_FEAT_SIE_IB, S390_FEAT_SIE_CEI, }; + static uint16_t full_GEN7_GA2[] = { S390_FEAT_EXTENDED_TRANSLATION_2, }; + static uint16_t full_GEN7_GA3[] = { S390_FEAT_LONG_DISPLACEMENT, S390_FEAT_SIE_SIIF, }; + static uint16_t full_GEN8_GA1[] = { S390_FEAT_SIE_GSLS, S390_FEAT_SIE_64BSCAO, }; + #define full_GEN8_GA2 EmptyFeat + static uint16_t full_GEN8_GA3[] = { S390_FEAT_ASN_LX_REUSE, S390_FEAT_EXTENDED_TRANSLATION_3, }; + #define full_GEN8_GA4 EmptyFeat #define full_GEN8_GA5 EmptyFeat + static uint16_t full_GEN9_GA1[] = { S390_FEAT_STORE_HYPERVISOR_INFO, S390_FEAT_GROUP_MSA_EXT_1, S390_FEAT_CMM, S390_FEAT_SIE_CMMA, }; + static uint16_t full_GEN9_GA2[] = { S390_FEAT_MOVE_WITH_OPTIONAL_SPEC, S390_FEAT_EXTRACT_CPU_TIME, @@ -325,10 +353,12 @@ static uint16_t full_GEN9_GA2[] = { S390_FEAT_FLOATING_POINT_SUPPPORT_ENH, S390_FEAT_DFP, }; + static uint16_t full_GEN9_GA3[] = { S390_FEAT_CONDITIONAL_SSKE, S390_FEAT_PFPO, }; + static uint16_t full_GEN10_GA1[] = { S390_FEAT_EDAT, S390_FEAT_CONFIGURATION_TOPOLOGY, @@ -337,34 +367,46 @@ static uint16_t full_GEN10_GA1[] = { S390_FEAT_SIE_PFMFI, S390_FEAT_SIE_SIGPIF, }; + static uint16_t full_GEN10_GA2[] = { S390_FEAT_SET_PROGRAM_PARAMETERS, S390_FEAT_SIE_IBS, }; + static uint16_t full_GEN10_GA3[] = { S390_FEAT_GROUP_MSA_EXT_3, }; + static uint16_t full_GEN11_GA1[] = { S390_FEAT_IPTE_RANGE, S390_FEAT_ACCESS_EXCEPTION_FS_INDICATION, S390_FEAT_GROUP_MSA_EXT_4, }; + #define full_GEN11_GA2 EmptyFeat + static uint16_t full_GEN12_GA1[] = { S390_FEAT_CONSTRAINT_TRANSACTIONAL_EXE, S390_FEAT_TRANSACTIONAL_EXE, S390_FEAT_RUNTIME_INSTRUMENTATION, S390_FEAT_EDAT_2, }; + static uint16_t full_GEN12_GA2[] = { S390_FEAT_GROUP_MSA_EXT_5, }; + static uint16_t full_GEN13_GA1[] = { S390_FEAT_VECTOR, }; + #define full_GEN13_GA2 EmptyFeat -/* default features differing to the base in order of release */ +/* Default features (in order of release) + * Automatically includes corresponding base features. + * Default features are all features this version of QEMU supports for this + * hardware model. Default feature sets can grow with new QEMU releases. + */ #define default_GEN7_GA1 EmptyFeat #define default_GEN7_GA2 EmptyFeat #define default_GEN7_GA3 EmptyFeat @@ -373,37 +415,47 @@ static uint16_t full_GEN13_GA1[] = { #define default_GEN8_GA3 EmptyFeat #define default_GEN8_GA4 EmptyFeat #define default_GEN8_GA5 EmptyFeat + static uint16_t default_GEN9_GA1[] = { S390_FEAT_STORE_HYPERVISOR_INFO, S390_FEAT_GROUP_MSA_EXT_1, S390_FEAT_CMM, }; + #define default_GEN9_GA2 EmptyFeat #define default_GEN9_GA3 EmptyFeat + static uint16_t default_GEN10_GA1[] = { S390_FEAT_EDAT, S390_FEAT_GROUP_MSA_EXT_2, }; + #define default_GEN10_GA2 EmptyFeat #define default_GEN10_GA3 EmptyFeat + static uint16_t default_GEN11_GA1[] = { S390_FEAT_GROUP_MSA_EXT_3, S390_FEAT_IPTE_RANGE, S390_FEAT_ACCESS_EXCEPTION_FS_INDICATION, S390_FEAT_GROUP_MSA_EXT_4, }; + #define default_GEN11_GA2 EmptyFeat + static uint16_t default_GEN12_GA1[] = { S390_FEAT_CONSTRAINT_TRANSACTIONAL_EXE, S390_FEAT_TRANSACTIONAL_EXE, S390_FEAT_RUNTIME_INSTRUMENTATION, S390_FEAT_EDAT_2, }; + #define default_GEN12_GA2 EmptyFeat + static uint16_t default_GEN13_GA1[] = { S390_FEAT_GROUP_MSA_EXT_5, S390_FEAT_VECTOR, }; + #define default_GEN13_GA2 EmptyFeat /****** END FEATURE DEFS ******/ From c9ad8a7a53b9f167626a32fe7c1116f8844156db Mon Sep 17 00:00:00 2001 From: "Jason J. Herne" Date: Mon, 10 Apr 2017 09:39:00 -0400 Subject: [PATCH 06/40] s390x/cpumodel: provide compat handling for new cpu features Provide a mechanism to disable features in compatibility machines. Signed-off-by: Jason J. Herne Acked-by: Christian Borntraeger Signed-off-by: Christian Borntraeger --- target/s390x/cpu_models.c | 26 ++++++++++++++++++++++++++ target/s390x/cpu_models.h | 2 ++ 2 files changed, 28 insertions(+) diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c index 7cb55dc7e3..fd3f459caa 100644 --- a/target/s390x/cpu_models.c +++ b/target/s390x/cpu_models.c @@ -77,6 +77,32 @@ static S390CPUDef s390_cpu_defs[] = { CPUDEF_INIT(0x2965, 13, 2, 47, 0x08000000U, "z13s", "IBM z13s GA1"), }; +void s390_cpudef_featoff(uint8_t gen, uint8_t ec_ga, S390Feat feat) +{ + const S390CPUDef *def; + + def = s390_find_cpu_def(0, gen, ec_ga, NULL); + clear_bit(feat, (unsigned long *)&def->default_feat); +} + +void s390_cpudef_featoff_greater(uint8_t gen, uint8_t ec_ga, S390Feat feat) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(s390_cpu_defs); i++) { + const S390CPUDef *def = &s390_cpu_defs[i]; + + if (def->gen < gen) { + continue; + } + if (def->gen == gen && def->ec_ga < ec_ga) { + continue; + } + + clear_bit(feat, (unsigned long *)&def->default_feat); + } +} + uint32_t s390_get_hmfai(void) { static S390CPU *cpu; diff --git a/target/s390x/cpu_models.h b/target/s390x/cpu_models.h index d41f8d6e38..c0bee15d7a 100644 --- a/target/s390x/cpu_models.h +++ b/target/s390x/cpu_models.h @@ -72,6 +72,8 @@ typedef struct S390CPUModel { #define ibc_gen(x) (x == 0 ? 0 : ((x >> 4) + S390_GEN_Z10)) #define ibc_ec_ga(x) (x & 0xf) +void s390_cpudef_featoff(uint8_t gen, uint8_t ec_ga, S390Feat feat); +void s390_cpudef_featoff_greater(uint8_t gen, uint8_t ec_ga, S390Feat feat); uint32_t s390_get_hmfai(void); uint8_t s390_get_mha_pow(void); uint32_t s390_get_ibc_val(void); From 1497c1606615b0b08d1b1f78afd1dcf2585879c0 Mon Sep 17 00:00:00 2001 From: Fei Li Date: Tue, 7 Mar 2017 04:07:44 +0100 Subject: [PATCH 07/40] s390x: add flags field for registering I/O adapter Introduce a new 'flags' field to IoAdapter to contain further characteristics of the adapter, like whether the adapter is subject to adapter-interruption suppression. For the kvm case, pass this value in the 'flags' field when registering an adapter. Signed-off-by: Fei Li Signed-off-by: Christian Borntraeger --- hw/intc/s390_flic.c | 2 +- hw/intc/s390_flic_kvm.c | 3 ++- hw/s390x/css-bridge.c | 2 +- hw/s390x/css.c | 8 ++++++-- hw/s390x/s390-pci-bus.c | 3 ++- include/hw/s390x/css.h | 8 +++++++- include/hw/s390x/s390_flic.h | 2 +- 7 files changed, 20 insertions(+), 8 deletions(-) diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c index 837158bdaf..d3938b332b 100644 --- a/hw/intc/s390_flic.c +++ b/hw/intc/s390_flic.c @@ -48,7 +48,7 @@ void s390_flic_init(void) static int qemu_s390_register_io_adapter(S390FLICState *fs, uint32_t id, uint8_t isc, bool swap, - bool is_maskable) + bool is_maskable, uint8_t flags) { /* nothing to do */ return 0; diff --git a/hw/intc/s390_flic_kvm.c b/hw/intc/s390_flic_kvm.c index 0bcd49f08b..15ff534fd1 100644 --- a/hw/intc/s390_flic_kvm.c +++ b/hw/intc/s390_flic_kvm.c @@ -186,13 +186,14 @@ static int __get_all_irqs(KVMS390FLICState *flic, static int kvm_s390_register_io_adapter(S390FLICState *fs, uint32_t id, uint8_t isc, bool swap, - bool is_maskable) + bool is_maskable, uint8_t flags) { struct kvm_s390_io_adapter adapter = { .id = id, .isc = isc, .maskable = is_maskable, .swap = swap, + .flags = flags, }; KVMS390FLICState *flic = KVM_S390_FLIC(fs); int r; diff --git a/hw/s390x/css-bridge.c b/hw/s390x/css-bridge.c index 823747fcd7..c4a9735d71 100644 --- a/hw/s390x/css-bridge.c +++ b/hw/s390x/css-bridge.c @@ -110,7 +110,7 @@ VirtualCssBus *virtual_css_bus_init(void) qbus_set_hotplug_handler(bus, dev, &error_abort); css_register_io_adapters(CSS_IO_ADAPTER_VIRTIO, true, false, - &error_abort); + 0, &error_abort); return cbus; } diff --git a/hw/s390x/css.c b/hw/s390x/css.c index d67fffae30..1fcbc84581 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -225,6 +225,7 @@ typedef struct IoAdapter { uint32_t id; uint8_t type; uint8_t isc; + uint8_t flags; } IoAdapter; typedef struct ChannelSubSys { @@ -392,10 +393,12 @@ uint32_t css_get_adapter_id(CssIoAdapterType type, uint8_t isc) * * @swap: an indication if byte swap is needed. * @maskable: an indication if the adapter is subject to the mask operation. + * @flags: further characteristics of the adapter. + * e.g. suppressible, an indication if the adapter is subject to AIS. * @errp: location to store error information. */ void css_register_io_adapters(CssIoAdapterType type, bool swap, bool maskable, - Error **errp) + uint8_t flags, Error **errp) { uint32_t id; int ret, isc; @@ -413,12 +416,13 @@ void css_register_io_adapters(CssIoAdapterType type, bool swap, bool maskable, for (isc = 0; isc <= MAX_ISC; isc++) { id = (type << 3) | isc; - ret = fsc->register_io_adapter(fs, id, isc, swap, maskable); + ret = fsc->register_io_adapter(fs, id, isc, swap, maskable, flags); if (ret == 0) { adapter = g_new0(IoAdapter, 1); adapter->id = id; adapter->isc = isc; adapter->type = type; + adapter->flags = flags; channel_subsys.io_adapters[type][isc] = adapter; } else { error_setg_errno(errp, -ret, "Unexpected error %d when " diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index 5651483781..b9603e7802 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -582,7 +582,8 @@ static int s390_pcihost_init(SysBusDevice *dev) QTAILQ_INIT(&s->pending_sei); QTAILQ_INIT(&s->zpci_devs); - css_register_io_adapters(CSS_IO_ADAPTER_PCI, true, false, &error_abort); + css_register_io_adapters(CSS_IO_ADAPTER_PCI, true, false, + S390_ADAPTER_SUPPRESSIBLE, &error_abort); return 0; } diff --git a/include/hw/s390x/css.h b/include/hw/s390x/css.h index eb0e26f258..e028960885 100644 --- a/include/hw/s390x/css.h +++ b/include/hw/s390x/css.h @@ -167,7 +167,13 @@ typedef enum { uint32_t css_get_adapter_id(CssIoAdapterType type, uint8_t isc); void css_register_io_adapters(CssIoAdapterType type, bool swap, bool maskable, - Error **errp); + uint8_t flags, Error **errp); + +#ifndef CONFIG_KVM +#define S390_ADAPTER_SUPPRESSIBLE 0x01 +#else +#define S390_ADAPTER_SUPPRESSIBLE KVM_S390_ADAPTER_SUPPRESSIBLE +#endif #ifndef CONFIG_USER_ONLY SubchDev *css_find_subch(uint8_t m, uint8_t cssid, uint8_t ssid, diff --git a/include/hw/s390x/s390_flic.h b/include/hw/s390x/s390_flic.h index caa6fc608d..d4145ad8eb 100644 --- a/include/hw/s390x/s390_flic.h +++ b/include/hw/s390x/s390_flic.h @@ -56,7 +56,7 @@ typedef struct S390FLICStateClass { DeviceClass parent_class; int (*register_io_adapter)(S390FLICState *fs, uint32_t id, uint8_t isc, - bool swap, bool maskable); + bool swap, bool maskable, uint8_t flags); int (*io_adapter_map)(S390FLICState *fs, uint32_t id, uint64_t map_addr, bool do_map); int (*add_adapter_routes)(S390FLICState *fs, AdapterRoutes *routes); From 6c1dd652a606f4446cdb8883ac68d6fb54b02e5c Mon Sep 17 00:00:00 2001 From: Fei Li Date: Fri, 17 Feb 2017 14:23:44 +0800 Subject: [PATCH 08/40] s390x/flic: introduce modify_ais_mode callback In order to emulate the adapter interruption suppression (AIS) facility properly, the guest needs to be able to modify the AIS mask. Interrupt suppression will be handled via the flic (for kvm, via a recently introduced kernel backend; for !kvm, in the flic code), so let's introduce a method to change the mode via the flic interface. We introduce the 'simm' and 'nimm' fields to QEMUS390FLICState to store interruption modes for each ISC. Each bit in 'simm' and 'nimm' targets one ISC, and collaboratively indicate three modes: ALL-Interruptions, SINGLE-Interruption and NO-Interruptions. This interface can initiate most transitions between the states; transition from SINGLE-Interruption to NO-Interruptions via adapter interrupt injection will be introduced in a following patch. The meaningful combinations are as follows: interruption mode | simm bit | nimm bit ------------------|----------|---------- ALL | 0 | 0 SINGLE | 1 | 0 NO | 1 | 1 Co-authored-by: Yi Min Zhao Signed-off-by: Yi Min Zhao Signed-off-by: Fei Li Signed-off-by: Christian Borntraeger --- hw/intc/s390_flic.c | 37 +++++++++++++++++++++++++++++++++++- hw/intc/s390_flic_kvm.c | 36 +++++++++++++++++++++++++++++++++++ include/hw/s390x/s390_flic.h | 9 ++++++++- 3 files changed, 80 insertions(+), 2 deletions(-) diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c index d3938b332b..ce7f355248 100644 --- a/hw/intc/s390_flic.c +++ b/hw/intc/s390_flic.c @@ -79,15 +79,47 @@ static int qemu_s390_clear_io_flic(S390FLICState *fs, uint16_t subchannel_id, return -ENOSYS; } +static int qemu_s390_modify_ais_mode(S390FLICState *fs, uint8_t isc, + uint16_t mode) +{ + QEMUS390FLICState *flic = QEMU_S390_FLIC(fs); + + switch (mode) { + case SIC_IRQ_MODE_ALL: + flic->simm &= ~AIS_MODE_MASK(isc); + flic->nimm &= ~AIS_MODE_MASK(isc); + break; + case SIC_IRQ_MODE_SINGLE: + flic->simm |= AIS_MODE_MASK(isc); + flic->nimm &= ~AIS_MODE_MASK(isc); + break; + default: + return -EINVAL; + } + + return 0; +} + +static void qemu_s390_flic_reset(DeviceState *dev) +{ + QEMUS390FLICState *flic = QEMU_S390_FLIC(dev); + + flic->simm = 0; + flic->nimm = 0; +} + static void qemu_s390_flic_class_init(ObjectClass *oc, void *data) { + DeviceClass *dc = DEVICE_CLASS(oc); S390FLICStateClass *fsc = S390_FLIC_COMMON_CLASS(oc); + dc->reset = qemu_s390_flic_reset; fsc->register_io_adapter = qemu_s390_register_io_adapter; fsc->io_adapter_map = qemu_s390_io_adapter_map; fsc->add_adapter_routes = qemu_s390_add_adapter_routes; fsc->release_adapter_routes = qemu_s390_release_adapter_routes; fsc->clear_io_irq = qemu_s390_clear_io_flic; + fsc->modify_ais_mode = qemu_s390_modify_ais_mode; } static Property s390_flic_common_properties[] = { @@ -98,12 +130,15 @@ static Property s390_flic_common_properties[] = { static void s390_flic_common_realize(DeviceState *dev, Error **errp) { - uint32_t max_batch = S390_FLIC_COMMON(dev)->adapter_routes_max_batch; + S390FLICState *fs = S390_FLIC_COMMON(dev); + uint32_t max_batch = fs->adapter_routes_max_batch; if (max_batch > ADAPTER_ROUTES_MAX_GSI) { error_setg(errp, "flic property adapter_routes_max_batch too big" " (%d > %d)", max_batch, ADAPTER_ROUTES_MAX_GSI); } + + fs->ais_supported = true; } static void s390_flic_class_init(ObjectClass *oc, void *data) diff --git a/hw/intc/s390_flic_kvm.c b/hw/intc/s390_flic_kvm.c index 15ff534fd1..55aa35fc6a 100644 --- a/hw/intc/s390_flic_kvm.c +++ b/hw/intc/s390_flic_kvm.c @@ -20,6 +20,7 @@ #include "sysemu/kvm.h" #include "hw/s390x/s390_flic.h" #include "hw/s390x/adapter.h" +#include "hw/s390x/css.h" #include "trace.h" #define FLIC_SAVE_INITIAL_SIZE getpagesize() @@ -149,6 +150,26 @@ static int kvm_s390_clear_io_flic(S390FLICState *fs, uint16_t subchannel_id, return rc ? -errno : 0; } +static int kvm_s390_modify_ais_mode(S390FLICState *fs, uint8_t isc, + uint16_t mode) +{ + KVMS390FLICState *flic = KVM_S390_FLIC(fs); + struct kvm_s390_ais_req req = { + .isc = isc, + .mode = mode, + }; + struct kvm_device_attr attr = { + .group = KVM_DEV_FLIC_AISM, + .addr = (uint64_t)&req, + }; + + if (!fs->ais_supported) { + return -ENOSYS; + } + + return ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr) ? -errno : 0; +} + /** * __get_all_irqs - store all pending irqs in buffer * @flic: pointer to flic device state @@ -406,6 +427,7 @@ typedef struct KVMS390FLICStateClass { static void kvm_s390_flic_realize(DeviceState *dev, Error **errp) { + S390FLICState *fs = S390_FLIC_COMMON(dev); KVMS390FLICState *flic_state = KVM_S390_FLIC(dev); struct kvm_create_device cd = {0}; struct kvm_device_attr test_attr = {0}; @@ -438,6 +460,7 @@ static void kvm_s390_flic_realize(DeviceState *dev, Error **errp) flic_state->clear_io_supported = !ioctl(flic_state->fd, KVM_HAS_DEVICE_ATTR, test_attr); + fs->ais_supported = false; return; fail: error_propagate(errp, errp_local); @@ -446,10 +469,12 @@ fail: static void kvm_s390_flic_reset(DeviceState *dev) { KVMS390FLICState *flic = KVM_S390_FLIC(dev); + S390FLICState *fs = S390_FLIC_COMMON(dev); struct kvm_device_attr attr = { .group = KVM_DEV_FLIC_CLEAR_IRQS, }; int rc = 0; + uint8_t isc; if (flic->fd == -1) { return; @@ -457,6 +482,16 @@ static void kvm_s390_flic_reset(DeviceState *dev) flic_disable_wait_pfault(flic); + if (fs->ais_supported) { + for (isc = 0; isc <= MAX_ISC; isc++) { + rc = kvm_s390_modify_ais_mode(fs, isc, SIC_IRQ_MODE_ALL); + if (rc) { + error_report("Failed to reset ais mode for isc %d: %s", + isc, strerror(-rc)); + } + } + } + rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr); if (rc) { trace_flic_reset_failed(errno); @@ -479,6 +514,7 @@ static void kvm_s390_flic_class_init(ObjectClass *oc, void *data) fsc->add_adapter_routes = kvm_s390_add_adapter_routes; fsc->release_adapter_routes = kvm_s390_release_adapter_routes; fsc->clear_io_irq = kvm_s390_clear_io_flic; + fsc->modify_ais_mode = kvm_s390_modify_ais_mode; } static const TypeInfo kvm_s390_flic_info = { diff --git a/include/hw/s390x/s390_flic.h b/include/hw/s390x/s390_flic.h index d4145ad8eb..f500184794 100644 --- a/include/hw/s390x/s390_flic.h +++ b/include/hw/s390x/s390_flic.h @@ -44,7 +44,7 @@ typedef struct S390FLICState { SysBusDevice parent_obj; /* to limit AdapterRoutes.num_routes for compat */ uint32_t adapter_routes_max_batch; - + bool ais_supported; } S390FLICState; #define S390_FLIC_COMMON_CLASS(klass) \ @@ -63,6 +63,7 @@ typedef struct S390FLICStateClass { void (*release_adapter_routes)(S390FLICState *fs, AdapterRoutes *routes); int (*clear_io_irq)(S390FLICState *fs, uint16_t subchannel_id, uint16_t subchannel_nr); + int (*modify_ais_mode)(S390FLICState *fs, uint8_t isc, uint16_t mode); } S390FLICStateClass; #define TYPE_KVM_S390_FLIC "s390-flic-kvm" @@ -73,8 +74,14 @@ typedef struct S390FLICStateClass { #define QEMU_S390_FLIC(obj) \ OBJECT_CHECK(QEMUS390FLICState, (obj), TYPE_QEMU_S390_FLIC) +#define SIC_IRQ_MODE_ALL 0 +#define SIC_IRQ_MODE_SINGLE 1 +#define AIS_MODE_MASK(isc) (0x80 >> isc) + typedef struct QEMUS390FLICState { S390FLICState parent_obj; + uint8_t simm; + uint8_t nimm; } QEMUS390FLICState; void s390_flic_init(void); From 1622ffd5151ad09c47785a380531ef1ebfc95be8 Mon Sep 17 00:00:00 2001 From: Yi Min Zhao Date: Fri, 17 Feb 2017 15:00:59 +0800 Subject: [PATCH 09/40] s390x/flic: introduce inject_airq callback Let's introduce a specialized way to inject adapter interrupts that, unlike the common interrupt injection method, allows to take the characteristics of the adapter into account. For adapters subject to AIS facility: - for non-kvm case, we handle the suppression for a given ISC in QEMU. - for kvm case, we pass adapter id to kvm to do airq injection. Add add tracepoint for suppressed airq and suppressing airq. Signed-off-by: Yi Min Zhao Signed-off-by: Fei Li Signed-off-by: Christian Borntraeger --- hw/intc/s390_flic.c | 27 +++++++++++++++++++++++++++ hw/intc/s390_flic_kvm.c | 18 ++++++++++++++++++ hw/intc/trace-events | 4 ++++ include/hw/s390x/s390_flic.h | 2 ++ 4 files changed, 51 insertions(+) diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c index ce7f355248..efcb1dd0f1 100644 --- a/hw/intc/s390_flic.c +++ b/hw/intc/s390_flic.c @@ -13,8 +13,11 @@ #include "qemu/osdep.h" #include "qemu/error-report.h" #include "hw/sysbus.h" +#include "hw/s390x/ioinst.h" #include "hw/s390x/s390_flic.h" +#include "hw/s390x/css.h" #include "trace.h" +#include "cpu.h" #include "hw/qdev.h" #include "qapi/error.h" #include "hw/s390x/s390-virtio-ccw.h" @@ -100,6 +103,29 @@ static int qemu_s390_modify_ais_mode(S390FLICState *fs, uint8_t isc, return 0; } +static int qemu_s390_inject_airq(S390FLICState *fs, uint8_t type, + uint8_t isc, uint8_t flags) +{ + QEMUS390FLICState *flic = QEMU_S390_FLIC(fs); + bool flag = flags & S390_ADAPTER_SUPPRESSIBLE; + uint32_t io_int_word = (isc << 27) | IO_INT_WORD_AI; + + if (flag && (flic->nimm & AIS_MODE_MASK(isc))) { + trace_qemu_s390_airq_suppressed(type, isc); + return 0; + } + + s390_io_interrupt(0, 0, 0, io_int_word); + + if (flag && (flic->simm & AIS_MODE_MASK(isc))) { + flic->nimm |= AIS_MODE_MASK(isc); + trace_qemu_s390_suppress_airq(isc, "Single-Interruption Mode", + "NO-Interruptions Mode"); + } + + return 0; +} + static void qemu_s390_flic_reset(DeviceState *dev) { QEMUS390FLICState *flic = QEMU_S390_FLIC(dev); @@ -120,6 +146,7 @@ static void qemu_s390_flic_class_init(ObjectClass *oc, void *data) fsc->release_adapter_routes = qemu_s390_release_adapter_routes; fsc->clear_io_irq = qemu_s390_clear_io_flic; fsc->modify_ais_mode = qemu_s390_modify_ais_mode; + fsc->inject_airq = qemu_s390_inject_airq; } static Property s390_flic_common_properties[] = { diff --git a/hw/intc/s390_flic_kvm.c b/hw/intc/s390_flic_kvm.c index 55aa35fc6a..a587ace3df 100644 --- a/hw/intc/s390_flic_kvm.c +++ b/hw/intc/s390_flic_kvm.c @@ -170,6 +170,23 @@ static int kvm_s390_modify_ais_mode(S390FLICState *fs, uint8_t isc, return ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr) ? -errno : 0; } +static int kvm_s390_inject_airq(S390FLICState *fs, uint8_t type, + uint8_t isc, uint8_t flags) +{ + KVMS390FLICState *flic = KVM_S390_FLIC(fs); + uint32_t id = css_get_adapter_id(type, isc); + struct kvm_device_attr attr = { + .group = KVM_DEV_FLIC_AIRQ_INJECT, + .attr = id, + }; + + if (!fs->ais_supported) { + return -ENOSYS; + } + + return ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr) ? -errno : 0; +} + /** * __get_all_irqs - store all pending irqs in buffer * @flic: pointer to flic device state @@ -515,6 +532,7 @@ static void kvm_s390_flic_class_init(ObjectClass *oc, void *data) fsc->release_adapter_routes = kvm_s390_release_adapter_routes; fsc->clear_io_irq = kvm_s390_clear_io_flic; fsc->modify_ais_mode = kvm_s390_modify_ais_mode; + fsc->inject_airq = kvm_s390_inject_airq; } static const TypeInfo kvm_s390_flic_info = { diff --git a/hw/intc/trace-events b/hw/intc/trace-events index 729c1288f1..c586714d89 100644 --- a/hw/intc/trace-events +++ b/hw/intc/trace-events @@ -73,6 +73,10 @@ flic_create_device(int err) "flic: create device failed %d" flic_no_device_api(int err) "flic: no Device Contral API support %d" flic_reset_failed(int err) "flic: reset failed %d" +# hw/intc/s390_flic.c +qemu_s390_airq_suppressed(uint8_t type, uint8_t isc) "flic: adapter I/O interrupt suppressed (type %x isc %x)" +qemu_s390_suppress_airq(uint8_t isc, const char *from, const char *to) "flic: for isc %x, suppress airq by modifying ais mode from %s to %s" + # hw/intc/aspeed_vic.c aspeed_vic_set_irq(int irq, int level) "Enabling IRQ %d: %d" aspeed_vic_update_fiq(int flags) "Raising FIQ: %d" diff --git a/include/hw/s390x/s390_flic.h b/include/hw/s390x/s390_flic.h index f500184794..2f173d905c 100644 --- a/include/hw/s390x/s390_flic.h +++ b/include/hw/s390x/s390_flic.h @@ -64,6 +64,8 @@ typedef struct S390FLICStateClass { int (*clear_io_irq)(S390FLICState *fs, uint16_t subchannel_id, uint16_t subchannel_nr); int (*modify_ais_mode)(S390FLICState *fs, uint8_t isc, uint16_t mode); + int (*inject_airq)(S390FLICState *fs, uint8_t type, uint8_t isc, + uint8_t flags); } S390FLICStateClass; #define TYPE_KVM_S390_FLIC "s390-flic-kvm" From 2283f4d67a0e05ae056d2077f65496c3c4df5d6f Mon Sep 17 00:00:00 2001 From: Fei Li Date: Fri, 17 Feb 2017 15:40:41 +0800 Subject: [PATCH 10/40] s390x/sic: realize SIC handling Currently, we do nothing for the SIC instruction, but we need to implement it properly. Let's add proper handling in the backend code. Co-authored-by: Yi Min Zhao Signed-off-by: Yi Min Zhao Signed-off-by: Fei Li Signed-off-by: Christian Borntraeger --- hw/s390x/css.c | 26 ++++++++++++++++++++++++++ hw/s390x/trace-events | 1 + include/hw/s390x/css.h | 2 ++ target/s390x/kvm.c | 16 +++++++++++++++- 4 files changed, 44 insertions(+), 1 deletion(-) diff --git a/hw/s390x/css.c b/hw/s390x/css.c index 1fcbc84581..7b82176bc2 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -521,6 +521,32 @@ void css_conditional_io_interrupt(SubchDev *sch) } } +int css_do_sic(CPUS390XState *env, uint8_t isc, uint16_t mode) +{ + S390FLICState *fs = s390_get_flic(); + S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs); + int r; + + if (env->psw.mask & PSW_MASK_PSTATE) { + r = -PGM_PRIVILEGED; + goto out; + } + + trace_css_do_sic(mode, isc); + switch (mode) { + case SIC_IRQ_MODE_ALL: + case SIC_IRQ_MODE_SINGLE: + break; + default: + r = -PGM_OPERAND; + goto out; + } + + r = fsc->modify_ais_mode(fs, isc, mode) ? -PGM_OPERATION : 0; +out: + return r; +} + void css_adapter_interrupt(uint8_t isc) { uint32_t io_int_word = (isc << 27) | IO_INT_WORD_AI; diff --git a/hw/s390x/trace-events b/hw/s390x/trace-events index 84ea964875..f07e974678 100644 --- a/hw/s390x/trace-events +++ b/hw/s390x/trace-events @@ -8,6 +8,7 @@ css_new_image(uint8_t cssid, const char *default_cssid) "CSS: add css image %02x css_assign_subch(const char *do_assign, uint8_t cssid, uint8_t ssid, uint16_t schid, uint16_t devno) "CSS: %s %x.%x.%04x (devno %04x)" css_io_interrupt(int cssid, int ssid, int schid, uint32_t intparm, uint8_t isc, const char *conditional) "CSS: I/O interrupt on sch %x.%x.%04x (intparm %08x, isc %x) %s" css_adapter_interrupt(uint8_t isc) "CSS: adapter I/O interrupt (isc %x)" +css_do_sic(uint16_t mode, uint8_t isc) "CSS: set interruption mode %x on isc %x" # hw/s390x/virtio-ccw.c virtio_ccw_interpret_ccw(int cssid, int ssid, int schid, int cmd_code) "VIRTIO-CCW: %x.%x.%04x: interpret command %x" diff --git a/include/hw/s390x/css.h b/include/hw/s390x/css.h index e028960885..5ee6d522a3 100644 --- a/include/hw/s390x/css.h +++ b/include/hw/s390x/css.h @@ -12,6 +12,7 @@ #ifndef CSS_H #define CSS_H +#include "cpu.h" #include "hw/s390x/adapter.h" #include "hw/s390x/s390_flic.h" #include "hw/s390x/ioinst.h" @@ -165,6 +166,7 @@ typedef enum { CSS_IO_ADAPTER_TYPE_NUMS, } CssIoAdapterType; +int css_do_sic(CPUS390XState *env, uint8_t isc, uint16_t mode); uint32_t css_get_adapter_id(CssIoAdapterType type, uint8_t isc); void css_register_io_adapters(CssIoAdapterType type, bool swap, bool maskable, uint8_t flags, Error **errp); diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c index 7a2a7c0895..78ebe831fb 100644 --- a/target/s390x/kvm.c +++ b/target/s390x/kvm.c @@ -1206,7 +1206,21 @@ static int kvm_stpcifc_service_call(S390CPU *cpu, struct kvm_run *run) static int kvm_sic_service_call(S390CPU *cpu, struct kvm_run *run) { - /* NOOP */ + CPUS390XState *env = &cpu->env; + uint8_t r1 = (run->s390_sieic.ipa & 0x00f0) >> 4; + uint8_t r3 = run->s390_sieic.ipa & 0x000f; + uint8_t isc; + uint16_t mode; + int r; + + cpu_synchronize_state(CPU(cpu)); + mode = env->regs[r1] & 0xffff; + isc = (env->regs[r3] >> 27) & 0x7; + r = css_do_sic(env, isc, mode); + if (r) { + enter_pgmcheck(cpu, -r); + } + return 0; } From 25a08b8ded0f4f898b6b12c7ee2cf4c1c55cfcce Mon Sep 17 00:00:00 2001 From: Yi Min Zhao Date: Fri, 17 Feb 2017 15:26:48 +0800 Subject: [PATCH 11/40] s390x/css: update css_adapter_interrupt Let's use the new inject_airq callback of flic to inject adapter interrupts. For kvm case, if the kernel flic doesn't support the new interface, the irq routine remains unchanged. For non-kvm case, qemu-flic handles the suppression process. Signed-off-by: Yi Min Zhao Signed-off-by: Fei Li Signed-off-by: Christian Borntraeger --- hw/s390x/css.c | 18 ++++++++++++++++-- hw/s390x/s390-pci-bus.c | 2 +- hw/s390x/virtio-ccw.c | 2 +- include/hw/s390x/css.h | 2 +- 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/hw/s390x/css.c b/hw/s390x/css.c index 7b82176bc2..1aed89fd85 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -547,12 +547,26 @@ out: return r; } -void css_adapter_interrupt(uint8_t isc) +void css_adapter_interrupt(CssIoAdapterType type, uint8_t isc) { + S390FLICState *fs = s390_get_flic(); + S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs); uint32_t io_int_word = (isc << 27) | IO_INT_WORD_AI; + IoAdapter *adapter = channel_subsys.io_adapters[type][isc]; + + if (!adapter) { + return; + } trace_css_adapter_interrupt(isc); - s390_io_interrupt(0, 0, 0, io_int_word); + if (fs->ais_supported) { + if (fsc->inject_airq(fs, type, isc, adapter->flags)) { + error_report("Failed to inject airq with AIS supported"); + exit(1); + } + } else { + s390_io_interrupt(0, 0, 0, io_int_word); + } } static void sch_handle_clear_func(SubchDev *sch) diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index b9603e7802..2de4435da8 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -504,7 +504,7 @@ static void s390_msi_ctrl_write(void *opaque, hwaddr addr, uint64_t data, 0x80 >> ((ind_bit + vec) % 8)); if (!set_ind_atomic(pbdev->routes.adapter.summary_addr + sum_bit / 8, 0x80 >> (sum_bit % 8))) { - css_adapter_interrupt(pbdev->isc); + css_adapter_interrupt(CSS_IO_ADAPTER_PCI, pbdev->isc); } } diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index e18fd2600d..5afd9bb019 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -1074,7 +1074,7 @@ static void virtio_ccw_notify(DeviceState *d, uint16_t vector) 0x80 >> ((ind_bit + vector) % 8)); if (!virtio_set_ind_atomic(sch, dev->summary_indicator->addr, 0x01)) { - css_adapter_interrupt(dev->thinint_isc); + css_adapter_interrupt(CSS_IO_ADAPTER_VIRTIO, dev->thinint_isc); } } else { indicators = address_space_ldq(&address_space_memory, diff --git a/include/hw/s390x/css.h b/include/hw/s390x/css.h index 5ee6d522a3..dd36d39de5 100644 --- a/include/hw/s390x/css.h +++ b/include/hw/s390x/css.h @@ -155,7 +155,6 @@ void css_generate_sch_crws(uint8_t cssid, uint8_t ssid, uint16_t schid, void css_generate_chp_crws(uint8_t cssid, uint8_t chpid); void css_generate_css_crws(uint8_t cssid); void css_clear_sei_pending(void); -void css_adapter_interrupt(uint8_t isc); int s390_ccw_cmd_request(ORB *orb, SCSW *scsw, void *data); int do_subchannel_work_virtual(SubchDev *sub, ORB *orb); int do_subchannel_work_passthrough(SubchDev *sub, ORB *orb); @@ -166,6 +165,7 @@ typedef enum { CSS_IO_ADAPTER_TYPE_NUMS, } CssIoAdapterType; +void css_adapter_interrupt(CssIoAdapterType type, uint8_t isc); int css_do_sic(CPUS390XState *env, uint8_t isc, uint16_t mode); uint32_t css_get_adapter_id(CssIoAdapterType type, uint8_t isc); void css_register_io_adapters(CssIoAdapterType type, bool swap, bool maskable, From cec8bbf7d64a7f9d95921c99faca8ff62241572b Mon Sep 17 00:00:00 2001 From: Halil Pasic Date: Tue, 11 Jul 2017 16:54:36 +0200 Subject: [PATCH 12/40] s390x: add helper get_machine_class We will need the machine class at machine initialization time, so the usual way via qdev won't do. Let's cache the machine class and also use the default values of the base machine for capability discovery. Signed-off-by: Halil Pasic Acked-by: Cornelia Huck Message-Id: <20170711145441.33925-2-pasic@linux.vnet.ibm.com> Signed-off-by: Christian Borntraeger --- hw/s390x/s390-virtio-ccw.c | 46 +++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index 0c8f758130..df2b0556c5 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -255,36 +255,35 @@ static inline void machine_set_dea_key_wrap(Object *obj, bool value, ms->dea_key_wrap = value; } +static S390CcwMachineClass *current_mc; + +static S390CcwMachineClass *get_machine_class(void) +{ + if (unlikely(!current_mc)) { + /* + * No s390 ccw machine was instantiated, we are likely to + * be called for the 'none' machine. The properties will + * have their after-initialization values. + */ + current_mc = S390_MACHINE_CLASS( + object_class_by_name(TYPE_S390_CCW_MACHINE)); + } + return current_mc; +} + 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; - } - /* - * Make sure the "none" machine can have ri, otherwise it won't * be - * unlocked in KVM and therefore the host CPU model might be wrong. - */ - return true; + if (!kvm_enabled()) { + return false; } - return 0; + /* for "none" machine this results in true */ + return get_machine_class()->ri_allowed; } bool cpu_model_allowed(void) { - 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->cpu_model_allowed; - } - /* allow CPU model qmp queries with the "none" machine */ - return true; + /* for "none" machine this results in true */ + return get_machine_class()->cpu_model_allowed; } static char *machine_get_loadparm(Object *obj, Error **errp) @@ -394,6 +393,7 @@ static const TypeInfo ccw_machine_info = { static void ccw_machine_##suffix##_instance_init(Object *obj) \ { \ MachineState *machine = MACHINE(obj); \ + current_mc = S390_MACHINE_CLASS(MACHINE_GET_CLASS(machine)); \ ccw_machine_##suffix##_instance_options(machine); \ } \ static const TypeInfo ccw_machine_##suffix##_info = { \ From 52629b3ba871e606a55e4366d82193055ad34d11 Mon Sep 17 00:00:00 2001 From: Halil Pasic Date: Tue, 11 Jul 2017 16:54:37 +0200 Subject: [PATCH 13/40] s390x: add css_migration_enabled to machine class Currently the migration of the channel subsystem (css) is only partial and is done by the virtio ccw proxies -- the only migratable css devices existing at the moment. With the current work on emulated and passthrough devices we need to decouple the migration of the channel subsystem state from virtio ccw, and have a separate section for it. A new section however necessarily breaks the migration compatibility. So let us introduce a switch at the machine class, and put it in 'off' state for now. We will turn the switch 'on' for future machines once all preparations are met. For compatibility machines the switch will stay 'off'. Signed-off-by: Halil Pasic Acked-by: Cornelia Huck Message-Id: <20170711145441.33925-3-pasic@linux.vnet.ibm.com> Signed-off-by: Christian Borntraeger --- hw/s390x/s390-virtio-ccw.c | 13 +++++++++++++ include/hw/s390x/s390-virtio-ccw.h | 7 +++++++ 2 files changed, 20 insertions(+) diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index df2b0556c5..75bce6be3a 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -209,6 +209,7 @@ static void ccw_machine_class_init(ObjectClass *oc, void *data) s390mc->ri_allowed = true; s390mc->cpu_model_allowed = true; + s390mc->css_migration_enabled = false; /* TODO: set to true */ mc->init = ccw_init; mc->reset = s390_machine_reset; mc->hot_add_cpu = s390_hot_add_cpu; @@ -378,6 +379,11 @@ static const TypeInfo ccw_machine_info = { }, }; +bool css_migration_enabled(void) +{ + return get_machine_class()->css_migration_enabled; +} + #define DEFINE_CCW_MACHINE(suffix, verstr, latest) \ static void ccw_machine_##suffix##_class_init(ObjectClass *oc, \ void *data) \ @@ -484,6 +490,10 @@ static const TypeInfo ccw_machine_info = { static void ccw_machine_2_10_instance_options(MachineState *machine) { + /* + * TODO Once preparations are done register vmstate for the css if + * css_migration_enabled(). + */ } static void ccw_machine_2_10_class_options(MachineClass *mc) @@ -498,8 +508,11 @@ static void ccw_machine_2_9_instance_options(MachineState *machine) static void ccw_machine_2_9_class_options(MachineClass *mc) { + S390CcwMachineClass *s390mc = S390_MACHINE_CLASS(mc); + ccw_machine_2_10_class_options(mc); SET_MACHINE_COMPAT(mc, CCW_COMPAT_2_9); + s390mc->css_migration_enabled = false; } DEFINE_CCW_MACHINE(2_9, "2.9", false); diff --git a/include/hw/s390x/s390-virtio-ccw.h b/include/hw/s390x/s390-virtio-ccw.h index 3027555f6d..ab88d49d10 100644 --- a/include/hw/s390x/s390-virtio-ccw.h +++ b/include/hw/s390x/s390-virtio-ccw.h @@ -39,6 +39,7 @@ typedef struct S390CcwMachineClass { /*< public >*/ bool ri_allowed; bool cpu_model_allowed; + bool css_migration_enabled; } S390CcwMachineClass; /* runtime-instrumentation allowed by the machine */ @@ -46,4 +47,10 @@ bool ri_allowed(void); /* cpu model allowed by the machine */ bool cpu_model_allowed(void); +/** + * Returns true if (vmstate based) migration of the channel subsystem + * is enabled, false if it is disabled. + */ +bool css_migration_enabled(void); + #endif From 457af62603c835a9fc235857b40140eaedcf999c Mon Sep 17 00:00:00 2001 From: Halil Pasic Date: Tue, 11 Jul 2017 16:54:38 +0200 Subject: [PATCH 14/40] s390x/css: add missing css state conditionally Although we have recently vmstatified the migration of some css infrastructure, for some css entities there is still state to be migrated left, because the focus was keeping migration stream compatibility (that is basically everything as-is). Let us add vmstate helpers and extend existing vmstate descriptions so that we have everything we need. Let us guard the added state via css_migration_enabled, so we keep the compatible behavior if css migration is disabled. Let's also annotate the bits which do not need to be migrated for better readability. Signed-off-by: Halil Pasic Reviewed-by: Cornelia Huck Reviewed-by: Juan Quintela Message-Id: <20170711145441.33925-4-pasic@linux.vnet.ibm.com> Signed-off-by: Christian Borntraeger --- hw/intc/s390_flic.c | 20 ++++++++++++ hw/s390x/css.c | 74 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c index efcb1dd0f1..ff6e4ec839 100644 --- a/hw/intc/s390_flic.c +++ b/hw/intc/s390_flic.c @@ -200,6 +200,22 @@ static void qemu_s390_flic_register_types(void) type_init(qemu_s390_flic_register_types) +static bool adapter_info_so_needed(void *opaque) +{ + return css_migration_enabled(); +} + +const VMStateDescription vmstate_adapter_info_so = { + .name = "s390_adapter_info/summary_offset", + .version_id = 1, + .minimum_version_id = 1, + .needed = adapter_info_so_needed, + .fields = (VMStateField[]) { + VMSTATE_UINT32(summary_offset, AdapterInfo), + VMSTATE_END_OF_LIST() + } +}; + const VMStateDescription vmstate_adapter_info = { .name = "s390_adapter_info", .version_id = 1, @@ -213,6 +229,10 @@ const VMStateDescription vmstate_adapter_info = { */ VMSTATE_END_OF_LIST() }, + .subsections = (const VMStateDescription * []) { + &vmstate_adapter_info_so, + NULL + } }; const VMStateDescription vmstate_adapter_routes = { diff --git a/hw/s390x/css.c b/hw/s390x/css.c index 1aed89fd85..e9a0613e05 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -29,12 +29,45 @@ typedef struct CrwContainer { QTAILQ_ENTRY(CrwContainer) sibling; } CrwContainer; +static const VMStateDescription vmstate_crw = { + .name = "s390_crw", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT16(flags, CRW), + VMSTATE_UINT16(rsid, CRW), + VMSTATE_END_OF_LIST() + }, +}; + +static const VMStateDescription vmstate_crw_container = { + .name = "s390_crw_container", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_STRUCT(crw, CrwContainer, 0, vmstate_crw, CRW), + VMSTATE_END_OF_LIST() + }, +}; + typedef struct ChpInfo { uint8_t in_use; uint8_t type; uint8_t is_virtual; } ChpInfo; +static const VMStateDescription vmstate_chp_info = { + .name = "s390_chp_info", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT8(in_use, ChpInfo), + VMSTATE_UINT8(type, ChpInfo), + VMSTATE_UINT8(is_virtual, ChpInfo), + VMSTATE_END_OF_LIST() + } +}; + typedef struct SubchSet { SubchDev *sch[MAX_SCHID + 1]; unsigned long schids_used[BITS_TO_LONGS(MAX_SCHID + 1)]; @@ -221,6 +254,19 @@ typedef struct CssImage { ChpInfo chpids[MAX_CHPID + 1]; } CssImage; +static const VMStateDescription vmstate_css_img = { + .name = "s390_css_img", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + /* Subchannel sets have no relevant state. */ + VMSTATE_STRUCT_ARRAY(chpids, CssImage, MAX_CHPID + 1, 0, + vmstate_chp_info, ChpInfo), + VMSTATE_END_OF_LIST() + } + +}; + typedef struct IoAdapter { uint32_t id; uint8_t type; @@ -239,10 +285,34 @@ typedef struct ChannelSubSys { uint64_t chnmon_area; CssImage *css[MAX_CSSID + 1]; uint8_t default_cssid; + /* don't migrate, see css_register_io_adapters */ IoAdapter *io_adapters[CSS_IO_ADAPTER_TYPE_NUMS][MAX_ISC + 1]; + /* don't migrate, see get_indicator and IndAddrPtrTmp */ QTAILQ_HEAD(, IndAddr) indicator_addresses; } ChannelSubSys; +static const VMStateDescription vmstate_css = { + .name = "s390_css", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_QTAILQ_V(pending_crws, ChannelSubSys, 1, vmstate_crw_container, + CrwContainer, sibling), + VMSTATE_BOOL(sei_pending, ChannelSubSys), + VMSTATE_BOOL(do_crw_mchk, ChannelSubSys), + VMSTATE_BOOL(crws_lost, ChannelSubSys), + /* These were kind of migrated by virtio */ + VMSTATE_UINT8(max_cssid, ChannelSubSys), + VMSTATE_UINT8(max_ssid, ChannelSubSys), + VMSTATE_BOOL(chnmon_active, ChannelSubSys), + VMSTATE_UINT64(chnmon_area, ChannelSubSys), + VMSTATE_ARRAY_OF_POINTER_TO_STRUCT(css, ChannelSubSys, MAX_CSSID + 1, + 0, vmstate_css_img, CssImage), + VMSTATE_UINT8(default_cssid, ChannelSubSys), + VMSTATE_END_OF_LIST() + } +}; + static ChannelSubSys channel_subsys = { .pending_crws = QTAILQ_HEAD_INITIALIZER(channel_subsys.pending_crws), .do_crw_mchk = true, @@ -282,6 +352,10 @@ static int subch_dev_post_load(void *opaque, int version_id) css_subch_assign(s->cssid, s->ssid, s->schid, s->devno, s); } + if (css_migration_enabled()) { + /* No compat voodoo to do ;) */ + return 0; + } /* * Hack alert. If we don't migrate the channel subsystem status * we still need to find out if the guest enabled mss/mcss-e. From ff443fe6b59cbbb4beb6186cc3986748626a2b57 Mon Sep 17 00:00:00 2001 From: Halil Pasic Date: Tue, 11 Jul 2017 16:54:39 +0200 Subject: [PATCH 15/40] s390x/css: add ORB to SubchDev Since we are going to need a migration compatibility breaking change to activate ChannelSubSys migration let us use the opportunity to introduce ORB to the SubchDev before that (otherwise we would need separate handling e.g. a compat property). The ORB will be useful for implementing IDA, or async handling of subchannel work. Signed-off-by: Halil Pasic Reviewed-by: Guenther Hutzl Reviewed-by: Cornelia Huck Message-Id: <20170711145441.33925-5-pasic@linux.vnet.ibm.com> Signed-off-by: Christian Borntraeger --- hw/s390x/css.c | 35 +++++++++++++++++++++++++++++++++++ include/hw/s390x/css.h | 1 + 2 files changed, 36 insertions(+) diff --git a/hw/s390x/css.c b/hw/s390x/css.c index e9a0613e05..0768fec68c 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -165,6 +165,36 @@ static const VMStateDescription vmstate_sense_id = { } }; +static const VMStateDescription vmstate_orb = { + .name = "s390_orb", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32(intparm, ORB), + VMSTATE_UINT16(ctrl0, ORB), + VMSTATE_UINT8(lpm, ORB), + VMSTATE_UINT8(ctrl1, ORB), + VMSTATE_UINT32(cpa, ORB), + VMSTATE_END_OF_LIST() + } +}; + +static bool vmstate_schdev_orb_needed(void *opaque) +{ + return css_migration_enabled(); +} + +static const VMStateDescription vmstate_schdev_orb = { + .name = "s390_subch_dev/orb", + .version_id = 1, + .minimum_version_id = 1, + .needed = vmstate_schdev_orb_needed, + .fields = (VMStateField[]) { + VMSTATE_STRUCT(orb, SubchDev, 1, vmstate_orb, ORB), + VMSTATE_END_OF_LIST() + } +}; + static int subch_dev_post_load(void *opaque, int version_id); static void subch_dev_pre_save(void *opaque); @@ -193,6 +223,10 @@ const VMStateDescription vmstate_subch_dev = { VMSTATE_BOOL(ccw_fmt_1, SubchDev), VMSTATE_UINT8(ccw_no_data_cnt, SubchDev), VMSTATE_END_OF_LIST() + }, + .subsections = (const VMStateDescription * []) { + &vmstate_schdev_orb, + NULL } }; @@ -1386,6 +1420,7 @@ int css_do_ssch(SubchDev *sch, ORB *orb) if (channel_subsys.chnmon_active) { css_update_chnmon(sch); } + sch->orb = *orb; sch->channel_prog = orb->cpa; /* Trigger the start function. */ s->ctrl |= (SCSW_FCTL_START_FUNC | SCSW_ACTL_START_PEND); diff --git a/include/hw/s390x/css.h b/include/hw/s390x/css.h index dd36d39de5..8f08126365 100644 --- a/include/hw/s390x/css.h +++ b/include/hw/s390x/css.h @@ -90,6 +90,7 @@ struct SubchDev { bool thinint_active; uint8_t ccw_no_data_cnt; uint16_t migrated_schid; /* used for missmatch detection */ + ORB orb; /* transport-provided data: */ int (*ccw_cb) (SubchDev *, CCW1); void (*disable_cb)(SubchDev *); From e996583eb35c8e3a182ed599318d30cb0be6a001 Mon Sep 17 00:00:00 2001 From: Halil Pasic Date: Tue, 11 Jul 2017 16:54:40 +0200 Subject: [PATCH 16/40] s390x/css: activate ChannelSubSys migration Turn on migration for the channel subsystem for the next machine. For legacy machines we still have to do things the old way. Signed-off-by: Halil Pasic Reviewed-by: Cornelia Huck Message-Id: <20170711145441.33925-6-pasic@linux.vnet.ibm.com> Signed-off-by: Christian Borntraeger --- hw/s390x/css.c | 5 +++++ hw/s390x/s390-virtio-ccw.c | 9 ++++----- include/hw/s390x/css.h | 4 ++++ 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/hw/s390x/css.c b/hw/s390x/css.c index 0768fec68c..62db7f646c 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -408,6 +408,11 @@ static int subch_dev_post_load(void *opaque, int version_id) return 0; } +void css_register_vmstate(void) +{ + vmstate_register(NULL, 0, &vmstate_css, &channel_subsys); +} + IndAddr *get_indicator(hwaddr ind_addr, int len) { IndAddr *indicator; diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index 75bce6be3a..e086cb517e 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -209,7 +209,7 @@ static void ccw_machine_class_init(ObjectClass *oc, void *data) s390mc->ri_allowed = true; s390mc->cpu_model_allowed = true; - s390mc->css_migration_enabled = false; /* TODO: set to true */ + s390mc->css_migration_enabled = true; mc->init = ccw_init; mc->reset = s390_machine_reset; mc->hot_add_cpu = s390_hot_add_cpu; @@ -490,10 +490,9 @@ bool css_migration_enabled(void) static void ccw_machine_2_10_instance_options(MachineState *machine) { - /* - * TODO Once preparations are done register vmstate for the css if - * css_migration_enabled(). - */ + if (css_migration_enabled()) { + css_register_vmstate(); + } } static void ccw_machine_2_10_class_options(MachineClass *mc) diff --git a/include/hw/s390x/css.h b/include/hw/s390x/css.h index 8f08126365..71076cb98f 100644 --- a/include/hw/s390x/css.h +++ b/include/hw/s390x/css.h @@ -234,4 +234,8 @@ extern PropertyInfo css_devid_ro_propinfo; */ SubchDev *css_create_sch(CssDevId bus_id, bool is_virtual, bool squash_mcss, Error **errp); + +/** Turn on css migration */ +void css_register_vmstate(void); + #endif From b5f5a3afb635109fa6c1d03a9c6e2653adde09a1 Mon Sep 17 00:00:00 2001 From: Halil Pasic Date: Tue, 11 Jul 2017 16:54:41 +0200 Subject: [PATCH 17/40] s390x/css: use SubchDev.orb Instead of passing around a pointer to ORB let us simplify some function signatures by using the previously introduced ORB saved at the subchannel (SubchDev). Signed-off-by: Halil Pasic Reviewed-by: Cornelia Huck Message-Id: <20170711145441.33925-7-pasic@linux.vnet.ibm.com> Signed-off-by: Christian Borntraeger --- hw/s390x/css.c | 30 +++++++++++++++--------------- include/hw/s390x/css.h | 6 +++--- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/hw/s390x/css.c b/hw/s390x/css.c index 62db7f646c..997815cd8f 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -909,7 +909,7 @@ static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr, return ret; } -static void sch_handle_start_func_virtual(SubchDev *sch, ORB *orb) +static void sch_handle_start_func_virtual(SubchDev *sch) { PMCW *p = &sch->curr_status.pmcw; @@ -923,10 +923,10 @@ static void sch_handle_start_func_virtual(SubchDev *sch, ORB *orb) if (!(s->ctrl & SCSW_ACTL_SUSP)) { /* Start Function triggered via ssch, i.e. we have an ORB */ + ORB *orb = &sch->orb; s->cstat = 0; s->dstat = 0; /* Look at the orb and try to execute the channel program. */ - assert(orb != NULL); /* resume does not pass an orb */ p->intparm = orb->intparm; if (!(orb->lpm & path)) { /* Generate a deferred cc 3 condition. */ @@ -940,8 +940,7 @@ static void sch_handle_start_func_virtual(SubchDev *sch, ORB *orb) sch->ccw_no_data_cnt = 0; suspend_allowed = !!(orb->ctrl0 & ORB_CTRL0_MASK_SPND); } else { - /* Start Function resumed via rsch, i.e. we don't have an - * ORB */ + /* Start Function resumed via rsch */ s->ctrl &= ~(SCSW_ACTL_SUSP | SCSW_ACTL_RESUME_PEND); /* The channel program had been suspended before. */ suspend_allowed = true; @@ -1011,13 +1010,14 @@ static void sch_handle_start_func_virtual(SubchDev *sch, ORB *orb) } -static int sch_handle_start_func_passthrough(SubchDev *sch, ORB *orb) +static int sch_handle_start_func_passthrough(SubchDev *sch) { PMCW *p = &sch->curr_status.pmcw; SCSW *s = &sch->curr_status.scsw; int ret; + ORB *orb = &sch->orb; if (!(s->ctrl & SCSW_ACTL_SUSP)) { assert(orb != NULL); p->intparm = orb->intparm; @@ -1062,7 +1062,7 @@ static int sch_handle_start_func_passthrough(SubchDev *sch, ORB *orb) * read/writes) asynchronous later on if we start supporting more than * our current very simple devices. */ -int do_subchannel_work_virtual(SubchDev *sch, ORB *orb) +int do_subchannel_work_virtual(SubchDev *sch) { SCSW *s = &sch->curr_status.scsw; @@ -1073,7 +1073,7 @@ int do_subchannel_work_virtual(SubchDev *sch, ORB *orb) sch_handle_halt_func(sch); } else if (s->ctrl & SCSW_FCTL_START_FUNC) { /* Triggered by both ssch and rsch. */ - sch_handle_start_func_virtual(sch, orb); + sch_handle_start_func_virtual(sch); } else { /* Cannot happen. */ return 0; @@ -1082,7 +1082,7 @@ int do_subchannel_work_virtual(SubchDev *sch, ORB *orb) return 0; } -int do_subchannel_work_passthrough(SubchDev *sch, ORB *orb) +int do_subchannel_work_passthrough(SubchDev *sch) { int ret; SCSW *s = &sch->curr_status.scsw; @@ -1096,7 +1096,7 @@ int do_subchannel_work_passthrough(SubchDev *sch, ORB *orb) sch_handle_halt_func(sch); ret = 0; } else if (s->ctrl & SCSW_FCTL_START_FUNC) { - ret = sch_handle_start_func_passthrough(sch, orb); + ret = sch_handle_start_func_passthrough(sch); } else { /* Cannot happen. */ return -ENODEV; @@ -1105,10 +1105,10 @@ int do_subchannel_work_passthrough(SubchDev *sch, ORB *orb) return ret; } -static int do_subchannel_work(SubchDev *sch, ORB *orb) +static int do_subchannel_work(SubchDev *sch) { if (sch->do_subchannel_work) { - return sch->do_subchannel_work(sch, orb); + return sch->do_subchannel_work(sch); } else { return -EINVAL; } @@ -1315,7 +1315,7 @@ int css_do_csch(SubchDev *sch) s->ctrl &= ~(SCSW_CTRL_MASK_FCTL | SCSW_CTRL_MASK_ACTL); s->ctrl |= SCSW_FCTL_CLEAR_FUNC | SCSW_ACTL_CLEAR_PEND; - do_subchannel_work(sch, NULL); + do_subchannel_work(sch); ret = 0; out: @@ -1356,7 +1356,7 @@ int css_do_hsch(SubchDev *sch) } s->ctrl |= SCSW_ACTL_HALT_PEND; - do_subchannel_work(sch, NULL); + do_subchannel_work(sch); ret = 0; out: @@ -1431,7 +1431,7 @@ int css_do_ssch(SubchDev *sch, ORB *orb) s->ctrl |= (SCSW_FCTL_START_FUNC | SCSW_ACTL_START_PEND); s->flags &= ~SCSW_FLAGS_MASK_PNO; - ret = do_subchannel_work(sch, orb); + ret = do_subchannel_work(sch); out: return ret; @@ -1710,7 +1710,7 @@ int css_do_rsch(SubchDev *sch) } s->ctrl |= SCSW_ACTL_RESUME_PEND; - do_subchannel_work(sch, NULL); + do_subchannel_work(sch); ret = 0; out: diff --git a/include/hw/s390x/css.h b/include/hw/s390x/css.h index 71076cb98f..c9edd0721b 100644 --- a/include/hw/s390x/css.h +++ b/include/hw/s390x/css.h @@ -94,7 +94,7 @@ struct SubchDev { /* transport-provided data: */ int (*ccw_cb) (SubchDev *, CCW1); void (*disable_cb)(SubchDev *); - int (*do_subchannel_work) (SubchDev *, ORB *); + int (*do_subchannel_work) (SubchDev *); SenseId id; void *driver_data; }; @@ -157,8 +157,8 @@ void css_generate_chp_crws(uint8_t cssid, uint8_t chpid); void css_generate_css_crws(uint8_t cssid); void css_clear_sei_pending(void); int s390_ccw_cmd_request(ORB *orb, SCSW *scsw, void *data); -int do_subchannel_work_virtual(SubchDev *sub, ORB *orb); -int do_subchannel_work_passthrough(SubchDev *sub, ORB *orb); +int do_subchannel_work_virtual(SubchDev *sub); +int do_subchannel_work_passthrough(SubchDev *sub); typedef enum { CSS_IO_ADAPTER_VIRTIO = 0, From 90806fec99d6cf32f627b66be3757901091dc7e9 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 12 Jul 2017 14:49:43 +0200 Subject: [PATCH 18/40] pc-bios/s390-ccw: Move libc functions to separate header The upcoming netboot code will use the libc from SLOF. To be able to still use s390-ccw.h there, the libc related functions in this header have to be moved to a different location. And while we're at it, remove the duplicate memcpy() function from sclp.c. Reviewed-by: Christian Borntraeger Reviewed-by: Cornelia Huck Signed-off-by: Thomas Huth Message-Id: <1499863793-18627-2-git-send-email-thuth@redhat.com> Signed-off-by: Christian Borntraeger --- pc-bios/s390-ccw/bootmap.c | 1 + pc-bios/s390-ccw/libc.h | 45 ++++++++++++++++++++++++++++++++++ pc-bios/s390-ccw/main.c | 1 + pc-bios/s390-ccw/s390-ccw.h | 29 ---------------------- pc-bios/s390-ccw/sclp.c | 10 ++------ pc-bios/s390-ccw/virtio-scsi.c | 1 + pc-bios/s390-ccw/virtio.c | 1 + 7 files changed, 51 insertions(+), 37 deletions(-) create mode 100644 pc-bios/s390-ccw/libc.h diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c index 523fa78c5f..458d3dac36 100644 --- a/pc-bios/s390-ccw/bootmap.c +++ b/pc-bios/s390-ccw/bootmap.c @@ -8,6 +8,7 @@ * directory. */ +#include "libc.h" #include "s390-ccw.h" #include "bootmap.h" #include "virtio.h" diff --git a/pc-bios/s390-ccw/libc.h b/pc-bios/s390-ccw/libc.h new file mode 100644 index 0000000000..0142ea8e7b --- /dev/null +++ b/pc-bios/s390-ccw/libc.h @@ -0,0 +1,45 @@ +/* + * libc-style definitions and functions + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#ifndef S390_CCW_LIBC_H +#define S390_CCW_LIBC_H + +typedef long size_t; +typedef int bool; +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long long uint64_t; + +static inline void *memset(void *s, int c, size_t n) +{ + int i; + unsigned char *p = s; + + for (i = 0; i < n; i++) { + p[i] = c; + } + + return s; +} + +static inline void *memcpy(void *s1, const void *s2, size_t n) +{ + uint8_t *dest = s1; + const uint8_t *src = s2; + int i; + + for (i = 0; i < n; i++) { + dest[i] = src[i]; + } + + return s1; +} + +#endif diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c index 1cacc1b46f..40cba8d63a 100644 --- a/pc-bios/s390-ccw/main.c +++ b/pc-bios/s390-ccw/main.c @@ -8,6 +8,7 @@ * directory. */ +#include "libc.h" #include "s390-ccw.h" #include "virtio.h" diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h index 2089274842..43e2d429fa 100644 --- a/pc-bios/s390-ccw/s390-ccw.h +++ b/pc-bios/s390-ccw/s390-ccw.h @@ -18,12 +18,6 @@ typedef unsigned short u16; typedef unsigned int u32; typedef unsigned long long u64; typedef unsigned long ulong; -typedef long size_t; -typedef int bool; -typedef unsigned char uint8_t; -typedef unsigned short uint16_t; -typedef unsigned int uint32_t; -typedef unsigned long long uint64_t; typedef unsigned char __u8; typedef unsigned short __u16; typedef unsigned int __u32; @@ -88,18 +82,6 @@ ulong get_second(void); /* bootmap.c */ void zipl_load(void); -static inline void *memset(void *s, int c, size_t n) -{ - int i; - unsigned char *p = s; - - for (i = 0; i < n; i++) { - p[i] = c; - } - - return s; -} - static inline void fill_hex(char *out, unsigned char val) { const char hex[] = "0123456789abcdef"; @@ -169,17 +151,6 @@ static inline void sleep(unsigned int seconds) } } -static inline void *memcpy(void *s1, const void *s2, size_t n) -{ - uint8_t *p1 = s1; - const uint8_t *p2 = s2; - - while (n--) { - p1[n] = p2[n]; - } - return s1; -} - static inline void IPL_assert(bool term, const char *message) { if (!term) { diff --git a/pc-bios/s390-ccw/sclp.c b/pc-bios/s390-ccw/sclp.c index a1639baed7..aa1c86290d 100644 --- a/pc-bios/s390-ccw/sclp.c +++ b/pc-bios/s390-ccw/sclp.c @@ -8,6 +8,7 @@ * directory. */ +#include "libc.h" #include "s390-ccw.h" #include "sclp.h" @@ -59,13 +60,6 @@ static int _strlen(const char *str) return i; } -static void _memcpy(char *dest, const char *src, int len) -{ - int i; - for (i = 0; i < len; i++) - dest[i] = src[i]; -} - void sclp_print(const char *str) { int len = _strlen(str); @@ -76,7 +70,7 @@ void sclp_print(const char *str) sccb->ebh.length = sizeof(EventBufferHeader) + len; sccb->ebh.type = SCLP_EVENT_ASCII_CONSOLE_DATA; sccb->ebh.flags = 0; - _memcpy(sccb->data, str, len); + memcpy(sccb->data, str, len); sclp_service_call(SCLP_CMD_WRITE_EVENT_DATA, sccb); } diff --git a/pc-bios/s390-ccw/virtio-scsi.c b/pc-bios/s390-ccw/virtio-scsi.c index f61ecf0205..c92f5d3fa0 100644 --- a/pc-bios/s390-ccw/virtio-scsi.c +++ b/pc-bios/s390-ccw/virtio-scsi.c @@ -9,6 +9,7 @@ * directory. */ +#include "libc.h" #include "s390-ccw.h" #include "virtio.h" #include "scsi.h" diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c index 6ee93d56db..87683314cf 100644 --- a/pc-bios/s390-ccw/virtio.c +++ b/pc-bios/s390-ccw/virtio.c @@ -8,6 +8,7 @@ * directory. */ +#include "libc.h" #include "s390-ccw.h" #include "virtio.h" #include "virtio-scsi.h" From af3bb73ab1352287848eec7f0ae395f26e004929 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 12 Jul 2017 14:49:44 +0200 Subject: [PATCH 19/40] pc-bios/s390-ccw: Move ebc2asc to sclp.c We will later need this array in a file that we will link to the netboot code, too. Since there is some ebcdic conversion done in sclp_get_loadparm_ascii(), the sclp.c file seems to be a good candidate. Acked-by: Cornelia Huck Reviewed-by: David Hildenbrand Signed-off-by: Thomas Huth Message-Id: <1499863793-18627-3-git-send-email-thuth@redhat.com> Signed-off-by: Christian Borntraeger --- pc-bios/s390-ccw/main.c | 11 ----------- pc-bios/s390-ccw/sclp.c | 11 +++++++++++ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c index 40cba8d63a..0580eace15 100644 --- a/pc-bios/s390-ccw/main.c +++ b/pc-bios/s390-ccw/main.c @@ -17,17 +17,6 @@ static SubChannelId blk_schid = { .one = 1 }; IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE))); static char loadparm[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; -const unsigned char ebc2asc[256] = - /* 0123456789abcdef0123456789abcdef */ - "................................" /* 1F */ - "................................" /* 3F */ - " ...........<(+|&.........!$*);." /* 5F first.chr.here.is.real.space */ - "-/.........,%_>?.........`:#@'=\""/* 7F */ - ".abcdefghi.......jklmnopqr......" /* 9F */ - "..stuvwxyz......................" /* BF */ - ".ABCDEFGHI.......JKLMNOPQR......" /* DF */ - "..STUVWXYZ......0123456789......";/* FF */ - /* * Priniciples of Operations (SA22-7832-09) chapter 17 requires that * a subsystem-identification is at 184-187 and bytes 188-191 are zero diff --git a/pc-bios/s390-ccw/sclp.c b/pc-bios/s390-ccw/sclp.c index aa1c86290d..2ee204a971 100644 --- a/pc-bios/s390-ccw/sclp.c +++ b/pc-bios/s390-ccw/sclp.c @@ -14,6 +14,17 @@ static char _sccb[PAGE_SIZE] __attribute__((__aligned__(4096))); +const unsigned char ebc2asc[256] = + /* 0123456789abcdef0123456789abcdef */ + "................................" /* 1F */ + "................................" /* 3F */ + " ...........<(+|&.........!$*);." /* 5F first.chr.here.is.real.space */ + "-/.........,%_>?.........`:#@'=\""/* 7F */ + ".abcdefghi.......jklmnopqr......" /* 9F */ + "..stuvwxyz......................" /* BF */ + ".ABCDEFGHI.......JKLMNOPQR......" /* DF */ + "..STUVWXYZ......0123456789......";/* FF */ + /* Perform service call. Return 0 on success, non-zero otherwise. */ static int sclp_service_call(unsigned int command, void *sccb) { From 867e039a06a02d3f2f8fa9e0246bda7917150fd9 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 12 Jul 2017 14:49:45 +0200 Subject: [PATCH 20/40] pc-bios/s390-ccw: Move virtio-block related functions into a separate file The netboot code is going to link against the code from virtio.c, too, so we've got to move the virtio-block and -scsi related code out of the way. Reviewed-by: Cornelia Huck Reviewed-by: David Hildenbrand Signed-off-by: Thomas Huth Message-Id: <1499863793-18627-4-git-send-email-thuth@redhat.com> Signed-off-by: Christian Borntraeger --- pc-bios/s390-ccw/Makefile | 2 +- pc-bios/s390-ccw/main.c | 2 +- pc-bios/s390-ccw/s390-ccw.h | 2 +- pc-bios/s390-ccw/virtio-blkdev.c | 296 +++++++++++++++++++++++++++++++ pc-bios/s390-ccw/virtio.c | 277 +---------------------------- pc-bios/s390-ccw/virtio.h | 6 + 6 files changed, 311 insertions(+), 274 deletions(-) create mode 100644 pc-bios/s390-ccw/virtio-blkdev.c diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile index fb88c13bc7..82b41ef671 100644 --- a/pc-bios/s390-ccw/Makefile +++ b/pc-bios/s390-ccw/Makefile @@ -9,7 +9,7 @@ $(call set-vpath, $(SRC_PATH)/pc-bios/s390-ccw) .PHONY : all clean build-all -OBJECTS = start.o main.o bootmap.o sclp.o virtio.o virtio-scsi.o +OBJECTS = start.o main.o bootmap.o sclp.o virtio.o virtio-scsi.o virtio-blkdev.o QEMU_CFLAGS := $(filter -W%, $(QEMU_CFLAGS)) QEMU_CFLAGS += -ffreestanding -fno-delete-null-pointer-checks -msoft-float QEMU_CFLAGS += -march=z900 -fPIE -fno-strict-aliasing diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c index 0580eace15..401e9dbb5f 100644 --- a/pc-bios/s390-ccw/main.c +++ b/pc-bios/s390-ccw/main.c @@ -144,7 +144,7 @@ static void virtio_setup(void) sclp_print("Network boot device detected\n"); vdev->netboot_start_addr = iplb.ccw.netboot_start_addr; } else { - virtio_setup_device(blk_schid); + virtio_blk_setup_device(blk_schid); IPL_assert(virtio_ipl_disk_is_valid(), "No valid IPL device detected"); } diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h index 43e2d429fa..6fdc8589cf 100644 --- a/pc-bios/s390-ccw/s390-ccw.h +++ b/pc-bios/s390-ccw/s390-ccw.h @@ -74,7 +74,7 @@ void sclp_get_loadparm_ascii(char *loadparm); unsigned long virtio_load_direct(ulong rec_list1, ulong rec_list2, ulong subchan_id, void *load_addr); bool virtio_is_supported(SubChannelId schid); -void virtio_setup_device(SubChannelId schid); +void virtio_blk_setup_device(SubChannelId schid); int virtio_read(ulong sector, void *load_addr); int enable_mss_facility(void); ulong get_second(void); diff --git a/pc-bios/s390-ccw/virtio-blkdev.c b/pc-bios/s390-ccw/virtio-blkdev.c new file mode 100644 index 0000000000..11c56261ca --- /dev/null +++ b/pc-bios/s390-ccw/virtio-blkdev.c @@ -0,0 +1,296 @@ +/* + * Virtio driver bits + * + * Copyright (c) 2013 Alexander Graf + * + * 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. + */ + +#include "libc.h" +#include "s390-ccw.h" +#include "virtio.h" +#include "virtio-scsi.h" + +static int virtio_blk_read_many(VDev *vdev, ulong sector, void *load_addr, + int sec_num) +{ + VirtioBlkOuthdr out_hdr; + u8 status; + VRing *vr = &vdev->vrings[vdev->cmd_vr_idx]; + + /* Tell the host we want to read */ + out_hdr.type = VIRTIO_BLK_T_IN; + out_hdr.ioprio = 99; + out_hdr.sector = virtio_sector_adjust(sector); + + vring_send_buf(vr, &out_hdr, sizeof(out_hdr), VRING_DESC_F_NEXT); + + /* This is where we want to receive data */ + vring_send_buf(vr, load_addr, virtio_get_block_size() * sec_num, + VRING_DESC_F_WRITE | VRING_HIDDEN_IS_CHAIN | + VRING_DESC_F_NEXT); + + /* status field */ + vring_send_buf(vr, &status, sizeof(u8), + VRING_DESC_F_WRITE | VRING_HIDDEN_IS_CHAIN); + + /* Now we can tell the host to read */ + vring_wait_reply(); + + if (drain_irqs(vr->schid)) { + /* Well, whatever status is supposed to contain... */ + status = 1; + } + return status; +} + +int virtio_read_many(ulong sector, void *load_addr, int sec_num) +{ + VDev *vdev = virtio_get_device(); + + switch (vdev->senseid.cu_model) { + case VIRTIO_ID_BLOCK: + return virtio_blk_read_many(vdev, sector, load_addr, sec_num); + case VIRTIO_ID_SCSI: + return virtio_scsi_read_many(vdev, sector, load_addr, sec_num); + } + panic("\n! No readable IPL device !\n"); + return -1; +} + +unsigned long virtio_load_direct(ulong rec_list1, ulong rec_list2, + ulong subchan_id, void *load_addr) +{ + u8 status; + int sec = rec_list1; + int sec_num = ((rec_list2 >> 32) & 0xffff) + 1; + int sec_len = rec_list2 >> 48; + ulong addr = (ulong)load_addr; + + if (sec_len != virtio_get_block_size()) { + return -1; + } + + sclp_print("."); + status = virtio_read_many(sec, (void *)addr, sec_num); + if (status) { + panic("I/O Error"); + } + addr += sec_num * virtio_get_block_size(); + + return addr; +} + +int virtio_read(ulong sector, void *load_addr) +{ + return virtio_read_many(sector, load_addr, 1); +} + +/* + * Other supported value pairs, if any, would need to be added here. + * Note: head count is always 15. + */ +static inline u8 virtio_eckd_sectors_for_block_size(int size) +{ + switch (size) { + case 512: + return 49; + case 1024: + return 33; + case 2048: + return 21; + case 4096: + return 12; + } + return 0; +} + +VirtioGDN virtio_guessed_disk_nature(void) +{ + return virtio_get_device()->guessed_disk_nature; +} + +void virtio_assume_scsi(void) +{ + VDev *vdev = virtio_get_device(); + + switch (vdev->senseid.cu_model) { + case VIRTIO_ID_BLOCK: + vdev->guessed_disk_nature = VIRTIO_GDN_SCSI; + vdev->config.blk.blk_size = VIRTIO_SCSI_BLOCK_SIZE; + vdev->config.blk.physical_block_exp = 0; + vdev->blk_factor = 1; + break; + case VIRTIO_ID_SCSI: + vdev->scsi_block_size = VIRTIO_SCSI_BLOCK_SIZE; + break; + } +} + +void virtio_assume_iso9660(void) +{ + VDev *vdev = virtio_get_device(); + + switch (vdev->senseid.cu_model) { + case VIRTIO_ID_BLOCK: + vdev->guessed_disk_nature = VIRTIO_GDN_SCSI; + vdev->config.blk.blk_size = VIRTIO_ISO_BLOCK_SIZE; + vdev->config.blk.physical_block_exp = 0; + vdev->blk_factor = VIRTIO_ISO_BLOCK_SIZE / VIRTIO_SECTOR_SIZE; + break; + case VIRTIO_ID_SCSI: + vdev->scsi_block_size = VIRTIO_ISO_BLOCK_SIZE; + break; + } +} + +void virtio_assume_eckd(void) +{ + VDev *vdev = virtio_get_device(); + + vdev->guessed_disk_nature = VIRTIO_GDN_DASD; + vdev->blk_factor = 1; + vdev->config.blk.physical_block_exp = 0; + switch (vdev->senseid.cu_model) { + case VIRTIO_ID_BLOCK: + vdev->config.blk.blk_size = 4096; + break; + case VIRTIO_ID_SCSI: + vdev->config.blk.blk_size = vdev->scsi_block_size; + break; + } + vdev->config.blk.geometry.heads = 15; + vdev->config.blk.geometry.sectors = + virtio_eckd_sectors_for_block_size(vdev->config.blk.blk_size); +} + +bool virtio_disk_is_scsi(void) +{ + VDev *vdev = virtio_get_device(); + + if (vdev->guessed_disk_nature == VIRTIO_GDN_SCSI) { + return true; + } + switch (vdev->senseid.cu_model) { + case VIRTIO_ID_BLOCK: + return (vdev->config.blk.geometry.heads == 255) + && (vdev->config.blk.geometry.sectors == 63) + && (virtio_get_block_size() == VIRTIO_SCSI_BLOCK_SIZE); + case VIRTIO_ID_SCSI: + return true; + } + return false; +} + +bool virtio_disk_is_eckd(void) +{ + VDev *vdev = virtio_get_device(); + const int block_size = virtio_get_block_size(); + + if (vdev->guessed_disk_nature == VIRTIO_GDN_DASD) { + return true; + } + switch (vdev->senseid.cu_model) { + case VIRTIO_ID_BLOCK: + return (vdev->config.blk.geometry.heads == 15) + && (vdev->config.blk.geometry.sectors == + virtio_eckd_sectors_for_block_size(block_size)); + case VIRTIO_ID_SCSI: + return false; + } + return false; +} + +bool virtio_ipl_disk_is_valid(void) +{ + return virtio_disk_is_scsi() || virtio_disk_is_eckd(); +} + +int virtio_get_block_size(void) +{ + VDev *vdev = virtio_get_device(); + + switch (vdev->senseid.cu_model) { + case VIRTIO_ID_BLOCK: + return vdev->config.blk.blk_size << vdev->config.blk.physical_block_exp; + case VIRTIO_ID_SCSI: + return vdev->scsi_block_size; + } + return 0; +} + +uint8_t virtio_get_heads(void) +{ + VDev *vdev = virtio_get_device(); + + switch (vdev->senseid.cu_model) { + case VIRTIO_ID_BLOCK: + return vdev->config.blk.geometry.heads; + case VIRTIO_ID_SCSI: + return vdev->guessed_disk_nature == VIRTIO_GDN_DASD + ? vdev->config.blk.geometry.heads : 255; + } + return 0; +} + +uint8_t virtio_get_sectors(void) +{ + VDev *vdev = virtio_get_device(); + + switch (vdev->senseid.cu_model) { + case VIRTIO_ID_BLOCK: + return vdev->config.blk.geometry.sectors; + case VIRTIO_ID_SCSI: + return vdev->guessed_disk_nature == VIRTIO_GDN_DASD + ? vdev->config.blk.geometry.sectors : 63; + } + return 0; +} + +uint64_t virtio_get_blocks(void) +{ + VDev *vdev = virtio_get_device(); + const uint64_t factor = virtio_get_block_size() / VIRTIO_SECTOR_SIZE; + + switch (vdev->senseid.cu_model) { + case VIRTIO_ID_BLOCK: + return vdev->config.blk.capacity / factor; + case VIRTIO_ID_SCSI: + return vdev->scsi_last_block / factor; + } + return 0; +} + +void virtio_blk_setup_device(SubChannelId schid) +{ + VDev *vdev = virtio_get_device(); + + vdev->schid = schid; + virtio_setup_ccw(vdev); + + switch (vdev->senseid.cu_model) { + case VIRTIO_ID_BLOCK: + sclp_print("Using virtio-blk.\n"); + if (!virtio_ipl_disk_is_valid()) { + /* make sure all getters but blocksize return 0 for + * invalid IPL disk + */ + memset(&vdev->config.blk, 0, sizeof(vdev->config.blk)); + virtio_assume_scsi(); + } + break; + case VIRTIO_ID_SCSI: + IPL_assert(vdev->config.scsi.sense_size == VIRTIO_SCSI_SENSE_SIZE, + "Config: sense size mismatch"); + IPL_assert(vdev->config.scsi.cdb_size == VIRTIO_SCSI_CDB_SIZE, + "Config: CDB size mismatch"); + + sclp_print("Using virtio-scsi.\n"); + virtio_scsi_setup(vdev); + break; + default: + panic("\n! No IPL device available !\n"); + } +} diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c index 87683314cf..9d9e61faa3 100644 --- a/pc-bios/s390-ccw/virtio.c +++ b/pc-bios/s390-ccw/virtio.c @@ -70,7 +70,7 @@ static long virtio_notify(SubChannelId schid, int vq_idx, long cookie) * Virtio functions * ***********************************************/ -static int drain_irqs(SubChannelId schid) +int drain_irqs(SubChannelId schid) { Irb irb = {}; int r = 0; @@ -149,13 +149,13 @@ static void vring_init(VRing *vr, VqInfo *info) debug_print_addr("init vr", vr); } -static bool vring_notify(VRing *vr) +bool vring_notify(VRing *vr) { vr->cookie = virtio_notify(vr->schid, vr->id, vr->cookie); return vr->cookie >= 0; } -static void vring_send_buf(VRing *vr, void *p, int len, int flags) +void vring_send_buf(VRing *vr, void *p, int len, int flags) { /* For follow-up chains we need to keep the first entry point */ if (!(flags & VRING_HIDDEN_IS_CHAIN)) { @@ -188,7 +188,7 @@ ulong get_second(void) return (get_clock() >> 12) / 1000000; } -static int vr_poll(VRing *vr) +int vr_poll(VRing *vr) { if (vr->used->idx == vr->used_idx) { vring_notify(vr); @@ -210,7 +210,7 @@ static int vr_poll(VRing *vr) * * Returns 0 on success, 1 on timeout. */ -static int vring_wait_reply(void) +int vring_wait_reply(void) { ulong target_second = get_second() + vdev.wait_reply_timeout; @@ -247,242 +247,7 @@ int virtio_run(VDev *vdev, int vqid, VirtioCmd *cmd) return 0; } -/*********************************************** - * Virtio block * - ***********************************************/ - -static int virtio_blk_read_many(VDev *vdev, - ulong sector, void *load_addr, int sec_num) -{ - VirtioBlkOuthdr out_hdr; - u8 status; - VRing *vr = &vdev->vrings[vdev->cmd_vr_idx]; - - /* Tell the host we want to read */ - out_hdr.type = VIRTIO_BLK_T_IN; - out_hdr.ioprio = 99; - out_hdr.sector = virtio_sector_adjust(sector); - - vring_send_buf(vr, &out_hdr, sizeof(out_hdr), VRING_DESC_F_NEXT); - - /* This is where we want to receive data */ - vring_send_buf(vr, load_addr, virtio_get_block_size() * sec_num, - VRING_DESC_F_WRITE | VRING_HIDDEN_IS_CHAIN | - VRING_DESC_F_NEXT); - - /* status field */ - vring_send_buf(vr, &status, sizeof(u8), - VRING_DESC_F_WRITE | VRING_HIDDEN_IS_CHAIN); - - /* Now we can tell the host to read */ - vring_wait_reply(); - - if (drain_irqs(vr->schid)) { - /* Well, whatever status is supposed to contain... */ - status = 1; - } - return status; -} - -int virtio_read_many(ulong sector, void *load_addr, int sec_num) -{ - switch (vdev.senseid.cu_model) { - case VIRTIO_ID_BLOCK: - return virtio_blk_read_many(&vdev, sector, load_addr, sec_num); - case VIRTIO_ID_SCSI: - return virtio_scsi_read_many(&vdev, sector, load_addr, sec_num); - } - panic("\n! No readable IPL device !\n"); - return -1; -} - -unsigned long virtio_load_direct(ulong rec_list1, ulong rec_list2, - ulong subchan_id, void *load_addr) -{ - u8 status; - int sec = rec_list1; - int sec_num = ((rec_list2 >> 32) & 0xffff) + 1; - int sec_len = rec_list2 >> 48; - ulong addr = (ulong)load_addr; - - if (sec_len != virtio_get_block_size()) { - return -1; - } - - sclp_print("."); - status = virtio_read_many(sec, (void *)addr, sec_num); - if (status) { - panic("I/O Error"); - } - addr += sec_num * virtio_get_block_size(); - - return addr; -} - -int virtio_read(ulong sector, void *load_addr) -{ - return virtio_read_many(sector, load_addr, 1); -} - -/* - * Other supported value pairs, if any, would need to be added here. - * Note: head count is always 15. - */ -static inline u8 virtio_eckd_sectors_for_block_size(int size) -{ - switch (size) { - case 512: - return 49; - case 1024: - return 33; - case 2048: - return 21; - case 4096: - return 12; - } - return 0; -} - -VirtioGDN virtio_guessed_disk_nature(void) -{ - return vdev.guessed_disk_nature; -} - -void virtio_assume_scsi(void) -{ - switch (vdev.senseid.cu_model) { - case VIRTIO_ID_BLOCK: - vdev.guessed_disk_nature = VIRTIO_GDN_SCSI; - vdev.config.blk.blk_size = VIRTIO_SCSI_BLOCK_SIZE; - vdev.config.blk.physical_block_exp = 0; - vdev.blk_factor = 1; - break; - case VIRTIO_ID_SCSI: - vdev.scsi_block_size = VIRTIO_SCSI_BLOCK_SIZE; - break; - } -} - -void virtio_assume_iso9660(void) -{ - switch (vdev.senseid.cu_model) { - case VIRTIO_ID_BLOCK: - vdev.guessed_disk_nature = VIRTIO_GDN_SCSI; - vdev.config.blk.blk_size = VIRTIO_ISO_BLOCK_SIZE; - vdev.config.blk.physical_block_exp = 0; - vdev.blk_factor = VIRTIO_ISO_BLOCK_SIZE / VIRTIO_SECTOR_SIZE; - break; - case VIRTIO_ID_SCSI: - vdev.scsi_block_size = VIRTIO_ISO_BLOCK_SIZE; - break; - } -} - -void virtio_assume_eckd(void) -{ - vdev.guessed_disk_nature = VIRTIO_GDN_DASD; - vdev.blk_factor = 1; - vdev.config.blk.physical_block_exp = 0; - switch (vdev.senseid.cu_model) { - case VIRTIO_ID_BLOCK: - vdev.config.blk.blk_size = 4096; - break; - case VIRTIO_ID_SCSI: - vdev.config.blk.blk_size = vdev.scsi_block_size; - break; - } - vdev.config.blk.geometry.heads = 15; - vdev.config.blk.geometry.sectors = - virtio_eckd_sectors_for_block_size(vdev.config.blk.blk_size); -} - -bool virtio_disk_is_scsi(void) -{ - if (vdev.guessed_disk_nature == VIRTIO_GDN_SCSI) { - return true; - } - switch (vdev.senseid.cu_model) { - case VIRTIO_ID_BLOCK: - return (vdev.config.blk.geometry.heads == 255) - && (vdev.config.blk.geometry.sectors == 63) - && (virtio_get_block_size() == VIRTIO_SCSI_BLOCK_SIZE); - case VIRTIO_ID_SCSI: - return true; - } - return false; -} - -bool virtio_disk_is_eckd(void) -{ - const int block_size = virtio_get_block_size(); - - if (vdev.guessed_disk_nature == VIRTIO_GDN_DASD) { - return true; - } - switch (vdev.senseid.cu_model) { - case VIRTIO_ID_BLOCK: - return (vdev.config.blk.geometry.heads == 15) - && (vdev.config.blk.geometry.sectors == - virtio_eckd_sectors_for_block_size(block_size)); - case VIRTIO_ID_SCSI: - return false; - } - return false; -} - -bool virtio_ipl_disk_is_valid(void) -{ - return virtio_disk_is_scsi() || virtio_disk_is_eckd(); -} - -int virtio_get_block_size(void) -{ - switch (vdev.senseid.cu_model) { - case VIRTIO_ID_BLOCK: - return vdev.config.blk.blk_size << vdev.config.blk.physical_block_exp; - case VIRTIO_ID_SCSI: - return vdev.scsi_block_size; - } - return 0; -} - -uint8_t virtio_get_heads(void) -{ - switch (vdev.senseid.cu_model) { - case VIRTIO_ID_BLOCK: - return vdev.config.blk.geometry.heads; - case VIRTIO_ID_SCSI: - return vdev.guessed_disk_nature == VIRTIO_GDN_DASD - ? vdev.config.blk.geometry.heads : 255; - } - return 0; -} - -uint8_t virtio_get_sectors(void) -{ - switch (vdev.senseid.cu_model) { - case VIRTIO_ID_BLOCK: - return vdev.config.blk.geometry.sectors; - case VIRTIO_ID_SCSI: - return vdev.guessed_disk_nature == VIRTIO_GDN_DASD - ? vdev.config.blk.geometry.sectors : 63; - } - return 0; -} - -uint64_t virtio_get_blocks(void) -{ - const uint64_t factor = virtio_get_block_size() / VIRTIO_SECTOR_SIZE; - switch (vdev.senseid.cu_model) { - case VIRTIO_ID_BLOCK: - return vdev.config.blk.capacity / factor; - case VIRTIO_ID_SCSI: - return vdev.scsi_last_block / factor; - } - return 0; -} - -static void virtio_setup_ccw(VDev *vdev) +void virtio_setup_ccw(VDev *vdev) { int i, cfg_size = 0; unsigned char status = VIRTIO_CONFIG_S_DRIVER_OK; @@ -544,36 +309,6 @@ static void virtio_setup_ccw(VDev *vdev) "Could not write status to host"); } -void virtio_setup_device(SubChannelId schid) -{ - vdev.schid = schid; - virtio_setup_ccw(&vdev); - - switch (vdev.senseid.cu_model) { - case VIRTIO_ID_BLOCK: - sclp_print("Using virtio-blk.\n"); - if (!virtio_ipl_disk_is_valid()) { - /* make sure all getters but blocksize return 0 for - * invalid IPL disk - */ - memset(&vdev.config.blk, 0, sizeof(vdev.config.blk)); - virtio_assume_scsi(); - } - break; - case VIRTIO_ID_SCSI: - IPL_assert(vdev.config.scsi.sense_size == VIRTIO_SCSI_SENSE_SIZE, - "Config: sense size mismatch"); - IPL_assert(vdev.config.scsi.cdb_size == VIRTIO_SCSI_CDB_SIZE, - "Config: CDB size mismatch"); - - sclp_print("Using virtio-scsi.\n"); - virtio_scsi_setup(&vdev); - break; - default: - panic("\n! No IPL device available !\n"); - } -} - bool virtio_is_supported(SubChannelId schid) { vdev.schid = schid; diff --git a/pc-bios/s390-ccw/virtio.h b/pc-bios/s390-ccw/virtio.h index 1eaf865b1f..024e9a6590 100644 --- a/pc-bios/s390-ccw/virtio.h +++ b/pc-bios/s390-ccw/virtio.h @@ -291,6 +291,12 @@ struct VirtioCmd { }; typedef struct VirtioCmd VirtioCmd; +bool vring_notify(VRing *vr); +int drain_irqs(SubChannelId schid); +void vring_send_buf(VRing *vr, void *p, int len, int flags); +int vr_poll(VRing *vr); +int vring_wait_reply(void); int virtio_run(VDev *vdev, int vqid, VirtioCmd *cmd); +void virtio_setup_ccw(VDev *vdev); #endif /* VIRTIO_H */ From 3639f93f91fcba2c4d686653dcffb8224555b0a8 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 12 Jul 2017 14:49:46 +0200 Subject: [PATCH 21/40] pc-bios/s390-ccw: Add a write() function for stdio The stdio functions from the SLOF libc need a write() function for printing text to stdout/stderr. Let's implement this function by refactoring the code from sclp_print(). Acked-by: Cornelia Huck Reviewed-by: David Hildenbrand Signed-off-by: Thomas Huth Message-Id: <1499863793-18627-5-git-send-email-thuth@redhat.com> Signed-off-by: Christian Borntraeger --- pc-bios/s390-ccw/sclp.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/pc-bios/s390-ccw/sclp.c b/pc-bios/s390-ccw/sclp.c index 2ee204a971..b1fc8ff44b 100644 --- a/pc-bios/s390-ccw/sclp.c +++ b/pc-bios/s390-ccw/sclp.c @@ -12,6 +12,8 @@ #include "s390-ccw.h" #include "sclp.h" +long write(int fd, const void *str, size_t len); + static char _sccb[PAGE_SIZE] __attribute__((__aligned__(4096))); const unsigned char ebc2asc[256] = @@ -71,11 +73,14 @@ static int _strlen(const char *str) return i; } -void sclp_print(const char *str) +long write(int fd, const void *str, size_t len) { - int len = _strlen(str); WriteEventData *sccb = (void *)_sccb; + if (fd != 1 && fd != 2) { + return -EIO; + } + sccb->h.length = sizeof(WriteEventData) + len; sccb->h.function_code = SCLP_FC_NORMAL_WRITE; sccb->ebh.length = sizeof(EventBufferHeader) + len; @@ -84,6 +89,13 @@ void sclp_print(const char *str) memcpy(sccb->data, str, len); sclp_service_call(SCLP_CMD_WRITE_EVENT_DATA, sccb); + + return len; +} + +void sclp_print(const char *str) +{ + write(1, str, _strlen(str)); } void sclp_get_loadparm_ascii(char *loadparm) From 824df3b84b653e9069764c802048d98da51e19c3 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 12 Jul 2017 14:49:47 +0200 Subject: [PATCH 22/40] pc-bios/s390-ccw: Move byteswap functions to a separate header We'll need them in code that is not related to bootmap.h, so they should reside in an independent header. Reviewed-by: Christian Borntraeger Acked-by: Cornelia Huck Signed-off-by: Thomas Huth Message-Id: <1499863793-18627-6-git-send-email-thuth@redhat.com> Signed-off-by: Christian Borntraeger --- pc-bios/s390-ccw/bootmap.c | 1 + pc-bios/s390-ccw/bootmap.h | 26 -------------------------- pc-bios/s390-ccw/bswap.h | 30 ++++++++++++++++++++++++++++++ 3 files changed, 31 insertions(+), 26 deletions(-) create mode 100644 pc-bios/s390-ccw/bswap.h diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c index 458d3dac36..67a6123ed4 100644 --- a/pc-bios/s390-ccw/bootmap.c +++ b/pc-bios/s390-ccw/bootmap.c @@ -12,6 +12,7 @@ #include "s390-ccw.h" #include "bootmap.h" #include "virtio.h" +#include "bswap.h" #ifdef DEBUG /* #define DEBUG_FALLBACK */ diff --git a/pc-bios/s390-ccw/bootmap.h b/pc-bios/s390-ccw/bootmap.h index 7f367820f3..cf99a4c728 100644 --- a/pc-bios/s390-ccw/bootmap.h +++ b/pc-bios/s390-ccw/bootmap.h @@ -324,32 +324,6 @@ static inline int _memcmp(const void *s1, const void *s2, size_t n) return 0; } -/* from include/qemu/bswap.h */ - -/* El Torito is always little-endian */ -static inline uint16_t bswap16(uint16_t x) -{ - return ((x & 0x00ff) << 8) | ((x & 0xff00) >> 8); -} - -static inline uint32_t bswap32(uint32_t x) -{ - return ((x & 0x000000ffU) << 24) | ((x & 0x0000ff00U) << 8) | - ((x & 0x00ff0000U) >> 8) | ((x & 0xff000000U) >> 24); -} - -static inline uint64_t bswap64(uint64_t x) -{ - return ((x & 0x00000000000000ffULL) << 56) | - ((x & 0x000000000000ff00ULL) << 40) | - ((x & 0x0000000000ff0000ULL) << 24) | - ((x & 0x00000000ff000000ULL) << 8) | - ((x & 0x000000ff00000000ULL) >> 8) | - ((x & 0x0000ff0000000000ULL) >> 24) | - ((x & 0x00ff000000000000ULL) >> 40) | - ((x & 0xff00000000000000ULL) >> 56); -} - static inline uint32_t iso_733_to_u32(uint64_t x) { return (uint32_t)x; diff --git a/pc-bios/s390-ccw/bswap.h b/pc-bios/s390-ccw/bswap.h new file mode 100644 index 0000000000..a4226042bc --- /dev/null +++ b/pc-bios/s390-ccw/bswap.h @@ -0,0 +1,30 @@ +/* + * Byte swap functions - taken from include/qemu/bswap.h + * + * 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. + */ + +static inline uint16_t bswap16(uint16_t x) +{ + return ((x & 0x00ff) << 8) | ((x & 0xff00) >> 8); +} + +static inline uint32_t bswap32(uint32_t x) +{ + return ((x & 0x000000ffU) << 24) | ((x & 0x0000ff00U) << 8) | + ((x & 0x00ff0000U) >> 8) | ((x & 0xff000000U) >> 24); +} + +static inline uint64_t bswap64(uint64_t x) +{ + return ((x & 0x00000000000000ffULL) << 56) | + ((x & 0x000000000000ff00ULL) << 40) | + ((x & 0x0000000000ff0000ULL) << 24) | + ((x & 0x00000000ff000000ULL) << 8) | + ((x & 0x000000ff00000000ULL) >> 8) | + ((x & 0x0000ff0000000000ULL) >> 24) | + ((x & 0x00ff000000000000ULL) >> 40) | + ((x & 0xff00000000000000ULL) >> 56); +} From ac7bec7cf9a203607b96935519457086e53b6b1f Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 12 Jul 2017 14:49:48 +0200 Subject: [PATCH 23/40] pc-bios/s390-ccw: Remove unused structs from virtio.h Looks like they have never been used, so let's simply remove them. Acked-by: Cornelia Huck Signed-off-by: Thomas Huth Message-Id: <1499863793-18627-7-git-send-email-thuth@redhat.com> Signed-off-by: Christian Borntraeger --- pc-bios/s390-ccw/virtio.h | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/pc-bios/s390-ccw/virtio.h b/pc-bios/s390-ccw/virtio.h index 024e9a6590..d7337803ee 100644 --- a/pc-bios/s390-ccw/virtio.h +++ b/pc-bios/s390-ccw/virtio.h @@ -32,24 +32,6 @@ enum VirtioDevType { }; typedef enum VirtioDevType VirtioDevType; -struct VirtioDevHeader { - VirtioDevType type:8; - uint8_t num_vq; - uint8_t feature_len; - uint8_t config_len; - uint8_t status; - uint8_t vqconfig[]; -} __attribute__((packed)); -typedef struct VirtioDevHeader VirtioDevHeader; - -struct VirtioVqConfig { - uint64_t token; - uint64_t address; - uint16_t num; - uint8_t pad[6]; -} __attribute__((packed)); -typedef struct VirtioVqConfig VirtioVqConfig; - struct VqInfo { uint64_t queue; uint32_t align; @@ -64,15 +46,6 @@ struct VqConfig { } __attribute__((packed)); typedef struct VqConfig VqConfig; -struct VirtioDev { - VirtioDevHeader *header; - VirtioVqConfig *vqconfig; - char *host_features; - char *guest_features; - char *config; -}; -typedef struct VirtioDev VirtioDev; - #define VIRTIO_RING_SIZE (PAGE_SIZE * 8) #define VIRTIO_MAX_VQS 3 #define KVM_S390_VIRTIO_RING_ALIGN 4096 From 59efbff1cb9dab4b02cadd639474ce1fee19277d Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 12 Jul 2017 14:49:49 +0200 Subject: [PATCH 24/40] pc-bios/s390-ccw: Add code for virtio feature negotiation The upcoming virtio-net driver needs to negotiate some features, so we need the possibility to do this in the core virtio code. Reviewed-by: Cornelia Huck Signed-off-by: Thomas Huth Message-Id: <1499863793-18627-8-git-send-email-thuth@redhat.com> Signed-off-by: Christian Borntraeger --- pc-bios/s390-ccw/s390-ccw.h | 2 ++ pc-bios/s390-ccw/virtio.c | 23 +++++++++++++++++------ pc-bios/s390-ccw/virtio.h | 1 + 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h index 6fdc8589cf..25d4d213ea 100644 --- a/pc-bios/s390-ccw/s390-ccw.h +++ b/pc-bios/s390-ccw/s390-ccw.h @@ -44,6 +44,8 @@ typedef unsigned long long __u64; ((b) == 0 ? (a) : (MIN(a, b)))) #endif +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) + #include "cio.h" #include "iplb.h" diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c index 9d9e61faa3..18fc5d1672 100644 --- a/pc-bios/s390-ccw/virtio.c +++ b/pc-bios/s390-ccw/virtio.c @@ -12,6 +12,7 @@ #include "s390-ccw.h" #include "virtio.h" #include "virtio-scsi.h" +#include "bswap.h" #define VRING_WAIT_REPLY_TIMEOUT 3 @@ -249,8 +250,12 @@ int virtio_run(VDev *vdev, int vqid, VirtioCmd *cmd) void virtio_setup_ccw(VDev *vdev) { - int i, cfg_size = 0; + int i, rc, cfg_size = 0; unsigned char status = VIRTIO_CONFIG_S_DRIVER_OK; + struct VirtioFeatureDesc { + uint32_t features; + uint8_t index; + } __attribute__((packed)) feats; IPL_assert(virtio_is_supported(vdev->schid), "PE"); /* device ID has been established now */ @@ -277,11 +282,17 @@ void virtio_setup_ccw(VDev *vdev) IPL_assert(run_ccw(vdev, CCW_CMD_READ_CONF, &vdev->config, cfg_size) == 0, "Could not get block device configuration"); - /* - * Skipping CCW_CMD_READ_FEAT. We're not doing anything fancy, and - * we'll just stop dead anyway if anything does not work like we - * expect it. - */ + /* Feature negotiation */ + for (i = 0; i < ARRAY_SIZE(vdev->guest_features); i++) { + feats.features = 0; + feats.index = i; + rc = run_ccw(vdev, CCW_CMD_READ_FEAT, &feats, sizeof(feats)); + IPL_assert(rc == 0, "Could not get features bits"); + vdev->guest_features[i] &= bswap32(feats.features); + feats.features = bswap32(vdev->guest_features[i]); + rc = run_ccw(vdev, CCW_CMD_WRITE_FEAT, &feats, sizeof(feats)); + IPL_assert(rc == 0, "Could not set features bits"); + } for (i = 0; i < vdev->nr_vqs; i++) { VqInfo info = { diff --git a/pc-bios/s390-ccw/virtio.h b/pc-bios/s390-ccw/virtio.h index d7337803ee..a00a320968 100644 --- a/pc-bios/s390-ccw/virtio.h +++ b/pc-bios/s390-ccw/virtio.h @@ -251,6 +251,7 @@ struct VDev { ScsiDevice selected_scsi_device; uint64_t netboot_start_addr; uint32_t max_transfer; + uint32_t guest_features[2]; }; typedef struct VDev VDev; From 4bfd755ff35c00204c79577a1c4756d4d2310724 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 12 Jul 2017 14:49:50 +0200 Subject: [PATCH 25/40] roms/SLOF: Update submodule to latest status We need the latest fixes for building the libc and libnet of SLOF for the s390-ccw network bootloader firmware. Signed-off-by: Thomas Huth Message-Id: <1499863793-18627-9-git-send-email-thuth@redhat.com> Signed-off-by: Christian Borntraeger --- roms/SLOF | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roms/SLOF b/roms/SLOF index 66d250ef0f..834113a1c6 160000 --- a/roms/SLOF +++ b/roms/SLOF @@ -1 +1 @@ -Subproject commit 66d250ef0fd06bb88b7399b9563b5008201f2d63 +Subproject commit 834113a1c67d6fb53dea153c3313d182238f2d36 From 3e4415a751d2474052ac5e62e8c793d978ed080e Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 12 Jul 2017 14:49:51 +0200 Subject: [PATCH 26/40] pc-bios/s390-ccw: Add core files for the network bootloading program This is just a preparation for the next steps: Add a makefile and a stripped down copy of pc-bios/s390-ccw/main.c as a basis for the network bootloader program, linked against the libc from SLOF already (which we will need for SLOF's libnet). The networking code is not included yet. Reviewed-by: Cornelia Huck Signed-off-by: Thomas Huth Message-Id: <1499863793-18627-10-git-send-email-thuth@redhat.com> Signed-off-by: Christian Borntraeger --- pc-bios/s390-ccw/Makefile | 11 ++- pc-bios/s390-ccw/netboot.mak | 47 ++++++++++++ pc-bios/s390-ccw/netmain.c | 136 +++++++++++++++++++++++++++++++++++ 3 files changed, 192 insertions(+), 2 deletions(-) create mode 100644 pc-bios/s390-ccw/netboot.mak create mode 100644 pc-bios/s390-ccw/netmain.c diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile index 82b41ef671..cbae74522a 100644 --- a/pc-bios/s390-ccw/Makefile +++ b/pc-bios/s390-ccw/Makefile @@ -16,7 +16,7 @@ QEMU_CFLAGS += -march=z900 -fPIE -fno-strict-aliasing QEMU_CFLAGS += $(call cc-option, $(QEMU_CFLAGS), -fno-stack-protector) LDFLAGS += -Wl,-pie -nostdlib -build-all: s390-ccw.img +build-all: s390-ccw.img s390-netboot.img s390-ccw.elf: $(OBJECTS) $(call quiet-command,$(CC) $(LDFLAGS) -o $@ $(OBJECTS),"BUILD","$(TARGET_DIR)$@") @@ -28,5 +28,12 @@ s390-ccw.img: s390-ccw.elf $(OBJECTS): Makefile +ifneq ($(wildcard $(SRC_PATH)/roms/SLOF/lib/libnet),) +include $(SRC_PATH)/pc-bios/s390-ccw/netboot.mak +else +s390-netboot.img: + @echo "s390-netboot.img not built since roms/SLOF/ is not available." +endif + clean: - rm -f *.o *.d *.img *.elf *~ + $(RM) *.o *.d *.img *.elf *~ *.a diff --git a/pc-bios/s390-ccw/netboot.mak b/pc-bios/s390-ccw/netboot.mak new file mode 100644 index 0000000000..44b7645a8f --- /dev/null +++ b/pc-bios/s390-ccw/netboot.mak @@ -0,0 +1,47 @@ + +SLOF_DIR := $(SRC_PATH)/roms/SLOF + +NETOBJS := start.o sclp.o virtio.o netmain.o libc.a + +LIBC_INC := -nostdinc -I$(SLOF_DIR)/lib/libc/include +LIBNET_INC := -I$(SLOF_DIR)/lib/libnet + +NETLDFLAGS := $(LDFLAGS) -Ttext=0x7800000 + +$(NETOBJS): QEMU_CFLAGS += $(LIBC_INC) $(LIBNET_INC) + +s390-netboot.elf: $(NETOBJS) + $(call quiet-command,$(CC) $(NETLDFLAGS) -o $@ $(NETOBJS),"BUILD","$(TARGET_DIR)$@") + +s390-netboot.img: s390-netboot.elf + $(call quiet-command,$(STRIP) --strip-unneeded $< -o $@,"STRIP","$(TARGET_DIR)$@") + +# libc files: + +LIBC_CFLAGS := $(QEMU_CFLAGS) $(LIBC_INC) $(LIBNET_INC) + +CTYPE_OBJS = isdigit.o isxdigit.o toupper.o +%.o : $(SLOF_DIR)/lib/libc/ctype/%.c + $(call quiet-command,$(CC) $(LIBC_CFLAGS) -c -o $@ $<,"CC","$(TARGET_DIR)$@") + +STRING_OBJS = strcat.o strchr.o strcmp.o strcpy.o strlen.o strncmp.o strncpy.o \ + strstr.o memset.o memcpy.o memmove.o memcmp.o +%.o : $(SLOF_DIR)/lib/libc/string/%.c + $(call quiet-command,$(CC) $(LIBC_CFLAGS) -c -o $@ $<,"CC","$(TARGET_DIR)$@") + +STDLIB_OBJS = atoi.o atol.o strtoul.o strtol.o rand.o malloc.o free.o +%.o : $(SLOF_DIR)/lib/libc/stdlib/%.c + $(call quiet-command,$(CC) $(LIBC_CFLAGS) -c -o $@ $<,"CC","$(TARGET_DIR)$@") + +STDIO_OBJS = sprintf.o vfprintf.o vsnprintf.o vsprintf.o fprintf.o \ + printf.o putc.o puts.o putchar.o stdchnls.o fileno.o +%.o : $(SLOF_DIR)/lib/libc/stdio/%.c + $(call quiet-command,$(CC) $(LIBC_CFLAGS) -c -o $@ $<,"CC","$(TARGET_DIR)$@") + +sbrk.o: $(SLOF_DIR)/slof/sbrk.c + $(call quiet-command,$(CC) $(LIBC_CFLAGS) -c -o $@ $<,"CC","$(TARGET_DIR)$@") + +LIBCOBJS := $(STRING_OBJS) $(CTYPE_OBJS) $(STDLIB_OBJS) $(STDIO_OBJS) sbrk.o + +libc.a: $(LIBCOBJS) + $(call quiet-command,$(AR) -rc $@ $^,"AR","$(TARGET_DIR)$@") diff --git a/pc-bios/s390-ccw/netmain.c b/pc-bios/s390-ccw/netmain.c new file mode 100644 index 0000000000..a69b3dd181 --- /dev/null +++ b/pc-bios/s390-ccw/netmain.c @@ -0,0 +1,136 @@ +/* + * S390 virtio-ccw network boot loading program + * + * Copyright 2017 Thomas Huth, Red Hat Inc. + * + * Based on the S390 virtio-ccw loading program (main.c) + * Copyright (c) 2013 Alexander Graf + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "s390-ccw.h" +#include "virtio.h" + +extern char _start[]; + +char stack[PAGE_SIZE * 8] __attribute__((aligned(PAGE_SIZE))); +IplParameterBlock iplb __attribute__((aligned(PAGE_SIZE))); + +static SubChannelId net_schid = { .one = 1 }; +static uint64_t dest_timer; + +static uint64_t get_timer_ms(void) +{ + uint64_t clk; + + asm volatile(" stck %0 " : : "Q"(clk) : "memory"); + + /* Bit 51 is incremented each microsecond */ + return (clk >> (63 - 51)) / 1000; +} + +void set_timer(int val) +{ + dest_timer = get_timer_ms() + val; +} + +int get_timer(void) +{ + return dest_timer - get_timer_ms(); +} + +int get_sec_ticks(void) +{ + return 1000; /* number of ticks in 1 second */ +} + +void panic(const char *string) +{ + sclp_print(string); + for (;;) { + disabled_wait(); + } +} + +static bool find_net_dev(Schib *schib, int dev_no) +{ + int i, r; + + for (i = 0; i < 0x10000; i++) { + net_schid.sch_no = i; + r = stsch_err(net_schid, schib); + if (r == 3 || r == -EIO) { + break; + } + if (!schib->pmcw.dnv) { + continue; + } + if (!virtio_is_supported(net_schid)) { + continue; + } + if (virtio_get_device_type() != VIRTIO_ID_NET) { + continue; + } + if (dev_no < 0 || schib->pmcw.dev == dev_no) { + return true; + } + } + + return false; +} + +static void virtio_setup(void) +{ + Schib schib; + int ssid; + bool found = false; + uint16_t dev_no; + + /* + * We unconditionally enable mss support. In every sane configuration, + * this will succeed; and even if it doesn't, stsch_err() can deal + * with the consequences. + */ + enable_mss_facility(); + + if (store_iplb(&iplb)) { + IPL_assert(iplb.pbt == S390_IPL_TYPE_CCW, "IPL_TYPE_CCW expected"); + dev_no = iplb.ccw.devno; + debug_print_int("device no. ", dev_no); + net_schid.ssid = iplb.ccw.ssid & 0x3; + debug_print_int("ssid ", net_schid.ssid); + found = find_net_dev(&schib, dev_no); + } else { + for (ssid = 0; ssid < 0x3; ssid++) { + net_schid.ssid = ssid; + found = find_net_dev(&schib, -1); + if (found) { + break; + } + } + } + + IPL_assert(found, "No virtio net device found"); +} + +void main(void) +{ + sclp_setup(); + sclp_print("Network boot starting...\n"); + + virtio_setup(); + + panic("Failed to load OS from network\n"); +} From 00dde1e60dd334b6a27b208132c9a57c36852ea1 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 12 Jul 2017 14:49:52 +0200 Subject: [PATCH 27/40] pc-bios/s390-ccw: Add virtio-net driver code The driver provides the recv() and send() functions which will be required by SLOF's libnet code for receiving and sending packets. Reviewed-by: Cornelia Huck Signed-off-by: Thomas Huth Message-Id: <1499863793-18627-11-git-send-email-thuth@redhat.com> Signed-off-by: Christian Borntraeger --- pc-bios/s390-ccw/netboot.mak | 2 +- pc-bios/s390-ccw/virtio-net.c | 135 ++++++++++++++++++++++++++++++++++ pc-bios/s390-ccw/virtio.c | 5 ++ pc-bios/s390-ccw/virtio.h | 12 ++- 4 files changed, 151 insertions(+), 3 deletions(-) create mode 100644 pc-bios/s390-ccw/virtio-net.c diff --git a/pc-bios/s390-ccw/netboot.mak b/pc-bios/s390-ccw/netboot.mak index 44b7645a8f..eb7043095b 100644 --- a/pc-bios/s390-ccw/netboot.mak +++ b/pc-bios/s390-ccw/netboot.mak @@ -1,7 +1,7 @@ SLOF_DIR := $(SRC_PATH)/roms/SLOF -NETOBJS := start.o sclp.o virtio.o netmain.o libc.a +NETOBJS := start.o sclp.o virtio.o virtio-net.o netmain.o libc.a LIBC_INC := -nostdinc -I$(SLOF_DIR)/lib/libc/include LIBNET_INC := -I$(SLOF_DIR)/lib/libnet diff --git a/pc-bios/s390-ccw/virtio-net.c b/pc-bios/s390-ccw/virtio-net.c new file mode 100644 index 0000000000..ff7f4dad25 --- /dev/null +++ b/pc-bios/s390-ccw/virtio-net.c @@ -0,0 +1,135 @@ +/* + * Virtio-net driver for the s390-ccw firmware + * + * Copyright 2017 Thomas Huth, Red Hat Inc. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "s390-ccw.h" +#include "virtio.h" + +#ifndef DEBUG_VIRTIO_NET +#define DEBUG_VIRTIO_NET 0 +#endif + +#define VIRTIO_NET_F_MAC_BIT (1 << 5) + +#define VQ_RX 0 /* Receive queue */ +#define VQ_TX 1 /* Transmit queue */ + +struct VirtioNetHdr { + uint8_t flags; + uint8_t gso_type; + uint16_t hdr_len; + uint16_t gso_size; + uint16_t csum_start; + uint16_t csum_offset; + /*uint16_t num_buffers;*/ /* Only with VIRTIO_NET_F_MRG_RXBUF or VIRTIO1 */ +}; +typedef struct VirtioNetHdr VirtioNetHdr; + +static uint16_t rx_last_idx; /* Last index in receive queue "used" ring */ + +int virtio_net_init(void *mac_addr) +{ + VDev *vdev = virtio_get_device(); + VRing *rxvq = &vdev->vrings[VQ_RX]; + void *buf; + int i; + + vdev->guest_features[0] = VIRTIO_NET_F_MAC_BIT; + virtio_setup_ccw(vdev); + + IPL_assert(vdev->guest_features[0] & VIRTIO_NET_F_MAC_BIT, + "virtio-net device does not support the MAC address feature"); + memcpy(mac_addr, vdev->config.net.mac, ETH_ALEN); + + for (i = 0; i < 64; i++) { + buf = malloc(ETH_MTU_SIZE + sizeof(VirtioNetHdr)); + IPL_assert(buf != NULL, "Can not allocate memory for receive buffers"); + vring_send_buf(rxvq, buf, ETH_MTU_SIZE + sizeof(VirtioNetHdr), + VRING_DESC_F_WRITE); + } + vring_notify(rxvq); + + return 0; +} + +int send(int fd, const void *buf, int len, int flags) +{ + VirtioNetHdr tx_hdr; + VDev *vdev = virtio_get_device(); + VRing *txvq = &vdev->vrings[VQ_TX]; + + /* Set up header - we do not use anything special, so simply clear it */ + memset(&tx_hdr, 0, sizeof(tx_hdr)); + + vring_send_buf(txvq, &tx_hdr, sizeof(tx_hdr), VRING_DESC_F_NEXT); + vring_send_buf(txvq, (void *)buf, len, VRING_HIDDEN_IS_CHAIN); + while (!vr_poll(txvq)) { + yield(); + } + if (drain_irqs(txvq->schid)) { + puts("send: drain irqs failed"); + return -1; + } + + return len; +} + +int recv(int fd, void *buf, int maxlen, int flags) +{ + VDev *vdev = virtio_get_device(); + VRing *rxvq = &vdev->vrings[VQ_RX]; + int len, id; + uint8_t *pkt; + + if (rx_last_idx == rxvq->used->idx) { + return 0; + } + + len = rxvq->used->ring[rx_last_idx % rxvq->num].len - sizeof(VirtioNetHdr); + if (len > maxlen) { + puts("virtio-net: Receive buffer too small"); + len = maxlen; + } + id = rxvq->used->ring[rx_last_idx % rxvq->num].id % rxvq->num; + pkt = (uint8_t *)(rxvq->desc[id].addr + sizeof(VirtioNetHdr)); + +#if DEBUG_VIRTIO_NET /* Dump packet */ + int i; + printf("\nbuf %p: len=%i\n", (void *)rxvq->desc[id].addr, len); + for (i = 0; i < 64; i++) { + printf(" %02x", pkt[i]); + if ((i % 16) == 15) { + printf("\n"); + } + } + printf("\n"); +#endif + + /* Copy data to destination buffer */ + memcpy(buf, pkt, len); + + /* Mark buffer as available to the host again */ + rxvq->avail->ring[rxvq->avail->idx % rxvq->num] = id; + rxvq->avail->idx = rxvq->avail->idx + 1; + vring_notify(rxvq); + + /* Move index to next entry */ + rx_last_idx = rx_last_idx + 1; + + return len; +} diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c index 18fc5d1672..c890a0330b 100644 --- a/pc-bios/s390-ccw/virtio.c +++ b/pc-bios/s390-ccw/virtio.c @@ -266,6 +266,11 @@ void virtio_setup_ccw(VDev *vdev) run_ccw(vdev, CCW_CMD_VDEV_RESET, NULL, 0); switch (vdev->senseid.cu_model) { + case VIRTIO_ID_NET: + vdev->nr_vqs = 2; + vdev->cmd_vr_idx = 0; + cfg_size = sizeof(vdev->config.net); + break; case VIRTIO_ID_BLOCK: vdev->nr_vqs = 1; vdev->cmd_vr_idx = 0; diff --git a/pc-bios/s390-ccw/virtio.h b/pc-bios/s390-ccw/virtio.h index a00a320968..19fceb6495 100644 --- a/pc-bios/s390-ccw/virtio.h +++ b/pc-bios/s390-ccw/virtio.h @@ -11,8 +11,6 @@ #ifndef VIRTIO_H #define VIRTIO_H -#include "s390-ccw.h" - /* Status byte for guest to report progress, and synchronize features. */ /* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */ #define VIRTIO_CONFIG_S_ACKNOWLEDGE 1 @@ -227,6 +225,13 @@ struct ScsiDevice { }; typedef struct ScsiDevice ScsiDevice; +struct VirtioNetConfig { + uint8_t mac[6]; + /* uint16_t status; */ /* Only with VIRTIO_NET_F_STATUS */ + /* uint16_t max_virtqueue_pairs; */ /* Only with VIRTIO_NET_F_MQ */ +}; +typedef struct VirtioNetConfig VirtioNetConfig; + struct VDev { int nr_vqs; VRing *vrings; @@ -239,6 +244,7 @@ struct VDev { union { VirtioBlkConfig blk; VirtioScsiConfig scsi; + VirtioNetConfig net; } config; ScsiDevice *scsi_device; bool is_cdrom; @@ -273,4 +279,6 @@ int vring_wait_reply(void); int virtio_run(VDev *vdev, int vqid, VirtioCmd *cmd); void virtio_setup_ccw(VDev *vdev); +int virtio_net_init(void *mac_addr); + #endif /* VIRTIO_H */ From 29d12216dae487a35f54141c6a397a64ec86cfe8 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 12 Jul 2017 14:49:53 +0200 Subject: [PATCH 28/40] pc-bios/s390-ccw: Link libnet into the netboot image and do the TFTP load Most of the code has been taken from SLOF's netload.c file. Now we can finally load an image via TFTP and execute the downloaded kernel. Acked-by: Cornelia Huck Signed-off-by: Thomas Huth Message-Id: <1499863793-18627-12-git-send-email-thuth@redhat.com> Tested-by: Viktor Mihajlovski Signed-off-by: Christian Borntraeger --- pc-bios/s390-ccw/netboot.mak | 14 ++- pc-bios/s390-ccw/netmain.c | 225 +++++++++++++++++++++++++++++++++++ 2 files changed, 238 insertions(+), 1 deletion(-) diff --git a/pc-bios/s390-ccw/netboot.mak b/pc-bios/s390-ccw/netboot.mak index eb7043095b..a9e1374e97 100644 --- a/pc-bios/s390-ccw/netboot.mak +++ b/pc-bios/s390-ccw/netboot.mak @@ -1,7 +1,7 @@ SLOF_DIR := $(SRC_PATH)/roms/SLOF -NETOBJS := start.o sclp.o virtio.o virtio-net.o netmain.o libc.a +NETOBJS := start.o sclp.o virtio.o virtio-net.o netmain.o libnet.a libc.a LIBC_INC := -nostdinc -I$(SLOF_DIR)/lib/libc/include LIBNET_INC := -I$(SLOF_DIR)/lib/libnet @@ -45,3 +45,15 @@ LIBCOBJS := $(STRING_OBJS) $(CTYPE_OBJS) $(STDLIB_OBJS) $(STDIO_OBJS) sbrk.o libc.a: $(LIBCOBJS) $(call quiet-command,$(AR) -rc $@ $^,"AR","$(TARGET_DIR)$@") + +# libnet files: + +LIBNETOBJS := args.o dhcp.o dns.o icmpv6.o ipv6.o tcp.o udp.o bootp.o \ + dhcpv6.o ethernet.o ipv4.o ndp.o tftp.o +LIBNETCFLAGS := $(QEMU_CFLAGS) $(LIBC_INC) $(LIBNET_INC) + +%.o : $(SLOF_DIR)/lib/libnet/%.c + $(call quiet-command,$(CC) $(LIBNETCFLAGS) -c -o $@ $<,"CC","$(TARGET_DIR)$@") + +libnet.a: $(LIBNETOBJS) + $(call quiet-command,$(AR) -rc $@ $^,"AR","$(TARGET_DIR)$@") diff --git a/pc-bios/s390-ccw/netmain.c b/pc-bios/s390-ccw/netmain.c index a69b3dd181..d86d46b03f 100644 --- a/pc-bios/s390-ccw/netmain.c +++ b/pc-bios/s390-ccw/netmain.c @@ -6,6 +6,9 @@ * Based on the S390 virtio-ccw loading program (main.c) * Copyright (c) 2013 Alexander Graf * + * And based on the network loading code from SLOF (netload.c) + * Copyright (c) 2004, 2008 IBM Corporation + * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your @@ -18,17 +21,29 @@ #include #include #include + +#include +#include +#include +#include +#include +#include +#include #include #include "s390-ccw.h" #include "virtio.h" +#define DEFAULT_BOOT_RETRIES 10 +#define DEFAULT_TFTP_RETRIES 20 + extern char _start[]; char stack[PAGE_SIZE * 8] __attribute__((aligned(PAGE_SIZE))); IplParameterBlock iplb __attribute__((aligned(PAGE_SIZE))); static SubChannelId net_schid = { .one = 1 }; +static int ip_version = 4; static uint64_t dest_timer; static uint64_t get_timer_ms(void) @@ -56,6 +71,208 @@ int get_sec_ticks(void) return 1000; /* number of ticks in 1 second */ } +/** + * Obtain IP and configuration info from DHCP server (either IPv4 or IPv6). + * @param fn_ip contains the following configuration information: + * client MAC, client IP, TFTP-server MAC, TFTP-server IP, + * boot file name + * @param retries Number of DHCP attempts + * @return 0 : IP and configuration info obtained; + * non-0 : error condition occurred. + */ +static int dhcp(struct filename_ip *fn_ip, int retries) +{ + int i = retries + 1; + int rc = -1; + + printf(" Requesting information via DHCP: "); + + dhcpv4_generate_transaction_id(); + dhcpv6_generate_transaction_id(); + + do { + printf("\b\b\b%03d", i - 1); + if (!--i) { + printf("\nGiving up after %d DHCP requests\n", retries); + return -1; + } + ip_version = 4; + rc = dhcpv4(NULL, fn_ip); + if (rc == -1) { + ip_version = 6; + set_ipv6_address(fn_ip->fd, 0); + rc = dhcpv6(NULL, fn_ip); + if (rc == 0) { + memcpy(&fn_ip->own_ip6, get_ipv6_address(), 16); + break; + } + } + if (rc != -1) { /* either success or non-dhcp failure */ + break; + } + } while (1); + printf("\b\b\b\bdone\n"); + + return rc; +} + +/** + * Seed the random number generator with our mac and current timestamp + */ +static void seed_rng(uint8_t mac[]) +{ + uint64_t seed; + + asm volatile(" stck %0 " : : "Q"(seed) : "memory"); + seed ^= (mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5]; + srand(seed); +} + +static int tftp_load(filename_ip_t *fnip, void *buffer, int len, + unsigned int retries, int ip_vers) +{ + tftp_err_t tftp_err; + int rc; + + rc = tftp(fnip, buffer, len, retries, &tftp_err, 1, 1428, ip_vers); + + if (rc > 0) { + printf(" TFTP: Received %s (%d KBytes)\n", fnip->filename, + rc / 1024); + } else if (rc == -1) { + puts("unknown TFTP error"); + } else if (rc == -2) { + printf("TFTP buffer of %d bytes is too small for %s\n", + len, fnip->filename); + } else if (rc == -3) { + printf("file not found: %s\n", fnip->filename); + } else if (rc == -4) { + puts("TFTP access violation"); + } else if (rc == -5) { + puts("illegal TFTP operation"); + } else if (rc == -6) { + puts("unknown TFTP transfer ID"); + } else if (rc == -7) { + puts("no such TFTP user"); + } else if (rc == -8) { + puts("TFTP blocksize negotiation failed"); + } else if (rc == -9) { + puts("file exceeds maximum TFTP transfer size"); + } else if (rc <= -10 && rc >= -15) { + const char *icmp_err_str; + switch (rc) { + case -ICMP_NET_UNREACHABLE - 10: + icmp_err_str = "net unreachable"; + break; + case -ICMP_HOST_UNREACHABLE - 10: + icmp_err_str = "host unreachable"; + break; + case -ICMP_PROTOCOL_UNREACHABLE - 10: + icmp_err_str = "protocol unreachable"; + break; + case -ICMP_PORT_UNREACHABLE - 10: + icmp_err_str = "port unreachable"; + break; + case -ICMP_FRAGMENTATION_NEEDED - 10: + icmp_err_str = "fragmentation needed and DF set"; + break; + case -ICMP_SOURCE_ROUTE_FAILED - 10: + icmp_err_str = "source route failed"; + break; + default: + icmp_err_str = " UNKNOWN"; + break; + } + printf("ICMP ERROR \"%s\"\n", icmp_err_str); + } else if (rc == -40) { + printf("TFTP error occurred after %d bad packets received", + tftp_err.bad_tftp_packets); + } else if (rc == -41) { + printf("TFTP error occurred after missing %d responses", + tftp_err.no_packets); + } else if (rc == -42) { + printf("TFTP error missing block %d, expected block was %d", + tftp_err.blocks_missed, + tftp_err.blocks_received); + } + + return rc; +} + +static int net_load(char *buffer, int len) +{ + filename_ip_t fn_ip; + uint8_t mac[6]; + int rc; + + memset(&fn_ip, 0, sizeof(filename_ip_t)); + + rc = virtio_net_init(mac); + if (rc < 0) { + puts("Could not initialize network device"); + return -101; + } + fn_ip.fd = rc; + + printf(" Using MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + set_mac_address(mac); /* init ethernet layer */ + seed_rng(mac); + + rc = dhcp(&fn_ip, DEFAULT_BOOT_RETRIES); + if (rc >= 0) { + if (ip_version == 4) { + set_ipv4_address(fn_ip.own_ip); + } + } else { + puts("Could not get IP address"); + return -101; + } + + if (ip_version == 4) { + printf(" Using IPv4 address: %d.%d.%d.%d\n", + (fn_ip.own_ip >> 24) & 0xFF, (fn_ip.own_ip >> 16) & 0xFF, + (fn_ip.own_ip >> 8) & 0xFF, fn_ip.own_ip & 0xFF); + } else if (ip_version == 6) { + char ip6_str[40]; + ipv6_to_str(fn_ip.own_ip6.addr, ip6_str); + printf(" Using IPv6 address: %s\n", ip6_str); + } + + if (rc == -2) { + printf("ARP request to TFTP server (%d.%d.%d.%d) failed\n", + (fn_ip.server_ip >> 24) & 0xFF, (fn_ip.server_ip >> 16) & 0xFF, + (fn_ip.server_ip >> 8) & 0xFF, fn_ip.server_ip & 0xFF); + return -102; + } + if (rc == -4 || rc == -3) { + puts("Can't obtain TFTP server IP address"); + return -107; + } + + if (ip_version == 4) { + printf(" Requesting file \"%s\" via TFTP from %d.%d.%d.%d\n", + fn_ip.filename, + (fn_ip.server_ip >> 24) & 0xFF, (fn_ip.server_ip >> 16) & 0xFF, + (fn_ip.server_ip >> 8) & 0xFF, fn_ip.server_ip & 0xFF); + } else if (ip_version == 6) { + char ip6_str[40]; + printf(" Requesting file \"%s\" via TFTP from ", fn_ip.filename); + ipv6_to_str(fn_ip.server_ip6.addr, ip6_str); + printf("%s\n", ip6_str); + } + + /* Do the TFTP load and print error message if necessary */ + rc = tftp_load(&fn_ip, buffer, len, DEFAULT_TFTP_RETRIES, ip_version); + + if (ip_version == 4) { + dhcp_send_release(fn_ip.fd); + } + + return rc; +} + void panic(const char *string) { sclp_print(string); @@ -127,10 +344,18 @@ static void virtio_setup(void) void main(void) { + int rc; + sclp_setup(); sclp_print("Network boot starting...\n"); virtio_setup(); + rc = net_load(NULL, (long)_start); + if (rc > 0) { + sclp_print("Network loading done, starting kernel...\n"); + asm volatile (" lpsw 0(%0) " : : "r"(0) : "memory"); + } + panic("Failed to load OS from network\n"); } From 6c5359e161b8e90e14940c0c72025dcfb8ce32f9 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Wed, 12 Jul 2017 16:00:41 +0200 Subject: [PATCH 29/40] pc-bios/s390: add s390-netboot.img It's already possible to do a network boot of an s390x guest with an external netboot image based on a Linux installation, but it would be much more convenient if the s390-ccw firmware supported network booting right out of the box, without the need to assemble such an external image first. This is an s390-netboot.img that can be used for network booting. You can download a combined kernel + initrd image via TFTP by starting QEMU for example with: qemu-system-s390x ... -device virtio-net,netdev=n1,bootindex=1 \ -netdev user,id=n1,tftp=/path/to/tftp,bootfile=kernel.img Note that this version does not support downloading via config files (i.e. pxelinux config files or .INS config files) yet. This will be added later. Signed-off-by: Christian Borntraeger --- Makefile | 2 +- pc-bios/s390-netboot.img | Bin 0 -> 83864 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100755 pc-bios/s390-netboot.img diff --git a/Makefile b/Makefile index 16a0430c6c..38814f9a61 100644 --- a/Makefile +++ b/Makefile @@ -553,7 +553,7 @@ efi-e1000e.rom efi-vmxnet3.rom \ qemu-icon.bmp qemu_logo_no_text.svg \ bamboo.dtb petalogix-s3adsp1800.dtb petalogix-ml605.dtb \ multiboot.bin linuxboot.bin linuxboot_dma.bin kvmvapic.bin \ -s390-ccw.img \ +s390-ccw.img s390-netboot.img \ spapr-rtas.bin slof.bin skiboot.lid \ palcode-clipper \ u-boot.e500 \ diff --git a/pc-bios/s390-netboot.img b/pc-bios/s390-netboot.img new file mode 100755 index 0000000000000000000000000000000000000000..295ddfcf6a37e7bd7b537410a78b499d56b2e924 GIT binary patch literal 83864 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 literal 0 HcmV?d00001 From fb32d2385a4eded144f6e5ee4c439f7bb0e69e97 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Thu, 13 Jul 2017 09:50:57 +0200 Subject: [PATCH 30/40] pc-bios/s390: rebuild s390-ccw.img rebuild after the following commits 4b996d0 pc-bios/s390-ccw: Link libnet into the netboot image and do the TFTP load e6879a6 pc-bios/s390-ccw: Add virtio-net driver code 766500f pc-bios/s390-ccw: Add core files for the network bootloading program f807e55 pc-bios/s390-ccw: Add code for virtio feature negotiation b4e3b4f pc-bios/s390-ccw: Remove unused structs from virtio.h dd3dc5e pc-bios/s390-ccw: Move byteswap functions to a separate header a20b4fe pc-bios/s390-ccw: Add a write() function for stdio 262e07c pc-bios/s390-ccw: Move virtio-block related functions into a separate file 7438d32 pc-bios/s390-ccw: Move ebc2asc to sclp.c 8760bad pc-bios/s390-ccw: Move libc functions to separate header c68f450 pc-bios/s390-ccw: use STRIP variable in Makefile Signed-off-by: Christian Borntraeger --- pc-bios/s390-ccw.img | Bin 26480 -> 30520 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/pc-bios/s390-ccw.img b/pc-bios/s390-ccw.img index 5ad056400073c7e1c5e862576c76f0e674ff3c60..0a08c3936a62bb225a3ed6a61e6e527dfecb8f40 100644 GIT binary patch literal 30520 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 literal 26480 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 Date: Wed, 14 Jun 2017 13:16:20 +0800 Subject: [PATCH 31/40] s390x: initialize cpu firstly By initializing the CPU firstly, we are able to retrieve and use the CPU model features when initializing other subsystem or devices. Signed-off-by: Yi Min Zhao Reviewed-by: Pierre Morel Reviewed-by: Cornelia Huck Signed-off-by: Christian Borntraeger --- hw/s390x/s390-virtio-ccw.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index e086cb517e..23e9658382 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -122,6 +122,9 @@ static void ccw_init(MachineState *machine) s390_sclp_init(); s390_memory_init(machine->ram_size); + /* init CPUs */ + s390_init_cpus(machine); + s390_flic_init(); /* get a BUS */ @@ -138,9 +141,6 @@ static void ccw_init(MachineState *machine) /* register hypercalls */ virtio_ccw_register_hcalls(); - /* init CPUs */ - s390_init_cpus(machine); - if (kvm_enabled()) { kvm_s390_enable_css_support(s390_cpu_addr2state(0)); } From 3b00f702c236900cca403bdcbed48d59bfec0fba Mon Sep 17 00:00:00 2001 From: Yi Min Zhao Date: Wed, 14 Jun 2017 13:25:58 +0800 Subject: [PATCH 32/40] s390x/cpumodel: add zpci, aen and ais facilities zPCI instructions and facilities are available since IBM zEnterprise EC12. To support z/PCI in QEMU we enable zpci, aen and ais facilities starting with zEC12 GA1. And we always set zpci and aen bits in max cpu model. Later they might be switched off due to applied real cpu model. For ais bit, we only provide it in the full cpu model beginning with zEC12 and defer its enablement in the default cpu model to a later point in time. At the same time, disable them for 2.9 and older machines. Because of introducing AIS facility, we could check if it's enabled to initialize flic->ais_supported with the real value. Signed-off-by: Yi Min Zhao Signed-off-by: Christian Borntraeger Reviewed-by: Cornelia Huck --- hw/intc/s390_flic.c | 3 ++- hw/intc/s390_flic_kvm.c | 3 --- hw/s390x/s390-virtio-ccw.c | 3 +++ target/s390x/cpu_features.c | 3 +++ target/s390x/cpu_features_def.h | 3 +++ target/s390x/gen-features.c | 5 +++++ target/s390x/kvm.c | 7 +++++++ 7 files changed, 23 insertions(+), 4 deletions(-) diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c index ff6e4ec839..6e7c610e52 100644 --- a/hw/intc/s390_flic.c +++ b/hw/intc/s390_flic.c @@ -163,9 +163,10 @@ static void s390_flic_common_realize(DeviceState *dev, Error **errp) if (max_batch > ADAPTER_ROUTES_MAX_GSI) { error_setg(errp, "flic property adapter_routes_max_batch too big" " (%d > %d)", max_batch, ADAPTER_ROUTES_MAX_GSI); + return; } - fs->ais_supported = true; + fs->ais_supported = s390_has_feat(S390_FEAT_ADAPTER_INT_SUPPRESSION); } static void s390_flic_class_init(ObjectClass *oc, void *data) diff --git a/hw/intc/s390_flic_kvm.c b/hw/intc/s390_flic_kvm.c index a587ace3df..d93503fcba 100644 --- a/hw/intc/s390_flic_kvm.c +++ b/hw/intc/s390_flic_kvm.c @@ -444,7 +444,6 @@ typedef struct KVMS390FLICStateClass { static void kvm_s390_flic_realize(DeviceState *dev, Error **errp) { - S390FLICState *fs = S390_FLIC_COMMON(dev); KVMS390FLICState *flic_state = KVM_S390_FLIC(dev); struct kvm_create_device cd = {0}; struct kvm_device_attr test_attr = {0}; @@ -476,8 +475,6 @@ static void kvm_s390_flic_realize(DeviceState *dev, Error **errp) test_attr.group = KVM_DEV_FLIC_CLEAR_IO_IRQ; flic_state->clear_io_supported = !ioctl(flic_state->fd, KVM_HAS_DEVICE_ATTR, test_attr); - - fs->ais_supported = false; return; fail: error_propagate(errp, errp_local); diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index 23e9658382..e484aedee9 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -503,6 +503,9 @@ DEFINE_CCW_MACHINE(2_10, "2.10", true); static void ccw_machine_2_9_instance_options(MachineState *machine) { ccw_machine_2_10_instance_options(machine); + s390_cpudef_featoff_greater(12, 1, S390_FEAT_ZPCI); + s390_cpudef_featoff_greater(12, 1, S390_FEAT_ADAPTER_INT_SUPPRESSION); + s390_cpudef_featoff_greater(12, 1, S390_FEAT_ADAPTER_EVENT_NOTIFICATION); } static void ccw_machine_2_9_class_options(MachineClass *mc) diff --git a/target/s390x/cpu_features.c b/target/s390x/cpu_features.c index 0436dc25d3..8ab5cd707c 100644 --- a/target/s390x/cpu_features.c +++ b/target/s390x/cpu_features.c @@ -74,6 +74,9 @@ static const S390FeatDef s390_features[] = { FEAT_INIT("stfle53", S390_FEAT_TYPE_STFL, 53, "Various facilities introduced with z13"), FEAT_INIT("msa5-base", S390_FEAT_TYPE_STFL, 57, "Message-security-assist-extension-5 facility (excluding subfunctions)"), FEAT_INIT("ri", S390_FEAT_TYPE_STFL, 64, "CPU runtime-instrumentation facility"), + FEAT_INIT("zpci", S390_FEAT_TYPE_STFL, 69, "z/PCI facility"), + FEAT_INIT("aen", S390_FEAT_TYPE_STFL, 71, "General-purpose-adapter-event-notification facility"), + FEAT_INIT("ais", S390_FEAT_TYPE_STFL, 72, "General-purpose-adapter-interruption-suppression facility"), FEAT_INIT("te", S390_FEAT_TYPE_STFL, 73, "Transactional-execution facility"), FEAT_INIT("sthyi", S390_FEAT_TYPE_STFL, 74, "Store-hypervisor-information facility"), FEAT_INIT("aefsi", S390_FEAT_TYPE_STFL, 75, "Access-exception-fetch/store-indication facility"), diff --git a/target/s390x/cpu_features_def.h b/target/s390x/cpu_features_def.h index f5bb7ed4b6..c939a00a6a 100644 --- a/target/s390x/cpu_features_def.h +++ b/target/s390x/cpu_features_def.h @@ -65,6 +65,9 @@ typedef enum { S390_FEAT_STFLE_53, S390_FEAT_MSA_EXT_5, S390_FEAT_RUNTIME_INSTRUMENTATION, + S390_FEAT_ZPCI, + S390_FEAT_ADAPTER_EVENT_NOTIFICATION, + S390_FEAT_ADAPTER_INT_SUPPRESSION, S390_FEAT_TRANSACTIONAL_EXE, S390_FEAT_STORE_HYPERVISOR_INFO, S390_FEAT_ACCESS_EXCEPTION_FS_INDICATION, diff --git a/target/s390x/gen-features.c b/target/s390x/gen-features.c index 8ca2b47fe8..622ee2492c 100644 --- a/target/s390x/gen-features.c +++ b/target/s390x/gen-features.c @@ -389,6 +389,9 @@ static uint16_t full_GEN12_GA1[] = { S390_FEAT_CONSTRAINT_TRANSACTIONAL_EXE, S390_FEAT_TRANSACTIONAL_EXE, S390_FEAT_RUNTIME_INSTRUMENTATION, + S390_FEAT_ZPCI, + S390_FEAT_ADAPTER_EVENT_NOTIFICATION, + S390_FEAT_ADAPTER_INT_SUPPRESSION, S390_FEAT_EDAT_2, }; @@ -446,6 +449,8 @@ static uint16_t default_GEN12_GA1[] = { S390_FEAT_CONSTRAINT_TRANSACTIONAL_EXE, S390_FEAT_TRANSACTIONAL_EXE, S390_FEAT_RUNTIME_INSTRUMENTATION, + S390_FEAT_ZPCI, + S390_FEAT_ADAPTER_EVENT_NOTIFICATION, S390_FEAT_EDAT_2, }; diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c index 78ebe831fb..1901153c58 100644 --- a/target/s390x/kvm.c +++ b/target/s390x/kvm.c @@ -302,6 +302,9 @@ int kvm_arch_init(MachineState *ms, KVMState *s) } } + /* Try to enable AIS facility */ + kvm_vm_enable_cap(s, KVM_CAP_S390_AIS, 0); + qemu_mutex_init(&qemu_sigp_mutex); return 0; @@ -2635,6 +2638,10 @@ void kvm_s390_get_host_cpu_model(S390CPUModel *model, Error **errp) set_bit(S390_FEAT_CMM, model->features); } + /* set zpci and aen facilities */ + set_bit(S390_FEAT_ZPCI, model->features); + set_bit(S390_FEAT_ADAPTER_EVENT_NOTIFICATION, model->features); + if (s390_known_cpu_type(cpu_type)) { /* we want the exact model, even if some features are missing */ model->def = s390_find_cpu_def(cpu_type, ibc_gen(unblocked_ibc), From e7be8d499700f1ebdbfe8094aa19237998c0e1e3 Mon Sep 17 00:00:00 2001 From: Yi Min Zhao Date: Tue, 16 May 2017 18:58:44 +0800 Subject: [PATCH 33/40] s390x/flic: migrate ais states During migration we should transfer ais states to the target guest. This patch introduces a subsection to kvm_s390_flic_vmstate and new vmsd for qemu_flic. The ais states need to be migrated only when ais is supported. Signed-off-by: Yi Min Zhao Signed-off-by: Christian Borntraeger Reviewed-by: Cornelia Huck --- hw/intc/s390_flic.c | 20 +++++++++ hw/intc/s390_flic_kvm.c | 81 ++++++++++++++++++++++++++++++++++++ include/hw/s390x/s390_flic.h | 1 + 3 files changed, 102 insertions(+) diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c index 6e7c610e52..6eaf178d79 100644 --- a/hw/intc/s390_flic.c +++ b/hw/intc/s390_flic.c @@ -134,12 +134,32 @@ static void qemu_s390_flic_reset(DeviceState *dev) flic->nimm = 0; } +bool ais_needed(void *opaque) +{ + S390FLICState *s = opaque; + + return s->ais_supported; +} + +static const VMStateDescription qemu_s390_flic_vmstate = { + .name = "qemu-s390-flic", + .version_id = 1, + .minimum_version_id = 1, + .needed = ais_needed, + .fields = (VMStateField[]) { + VMSTATE_UINT8(simm, QEMUS390FLICState), + VMSTATE_UINT8(nimm, QEMUS390FLICState), + VMSTATE_END_OF_LIST() + } +}; + static void qemu_s390_flic_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); S390FLICStateClass *fsc = S390_FLIC_COMMON_CLASS(oc); dc->reset = qemu_s390_flic_reset; + dc->vmsd = &qemu_s390_flic_vmstate; fsc->register_io_adapter = qemu_s390_register_io_adapter; fsc->io_adapter_map = qemu_s390_io_adapter_map; fsc->add_adapter_routes = qemu_s390_add_adapter_routes; diff --git a/hw/intc/s390_flic_kvm.c b/hw/intc/s390_flic_kvm.c index d93503fcba..be3fd00a57 100644 --- a/hw/intc/s390_flic_kvm.c +++ b/hw/intc/s390_flic_kvm.c @@ -413,7 +413,84 @@ out: return r; } +typedef struct KVMS390FLICStateMigTmp { + KVMS390FLICState *parent; + uint8_t simm; + uint8_t nimm; +} KVMS390FLICStateMigTmp; + +static void kvm_flic_ais_pre_save(void *opaque) +{ + KVMS390FLICStateMigTmp *tmp = opaque; + KVMS390FLICState *flic = tmp->parent; + struct kvm_s390_ais_all ais; + struct kvm_device_attr attr = { + .group = KVM_DEV_FLIC_AISM_ALL, + .addr = (uint64_t)&ais, + .attr = sizeof(ais), + }; + + if (ioctl(flic->fd, KVM_GET_DEVICE_ATTR, &attr)) { + error_report("Failed to retrieve kvm flic ais states"); + return; + } + + tmp->simm = ais.simm; + tmp->nimm = ais.nimm; +} + +static int kvm_flic_ais_post_load(void *opaque, int version_id) +{ + KVMS390FLICStateMigTmp *tmp = opaque; + KVMS390FLICState *flic = tmp->parent; + struct kvm_s390_ais_all ais = { + .simm = tmp->simm, + .nimm = tmp->nimm, + }; + struct kvm_device_attr attr = { + .group = KVM_DEV_FLIC_AISM_ALL, + .addr = (uint64_t)&ais, + }; + + /* This can happen when the user mis-configures its guests in an + * incompatible fashion or without a CPU model. For example using + * qemu with -cpu host (which is not migration safe) and do a + * migration from a host that has AIS to a host that has no AIS. + * In that case the target system will reject the migration here. + */ + if (!ais_needed(flic)) { + return -ENOSYS; + } + + return ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr) ? -errno : 0; +} + +static const VMStateDescription kvm_s390_flic_ais_tmp = { + .name = "s390-flic-ais-tmp", + .pre_save = kvm_flic_ais_pre_save, + .post_load = kvm_flic_ais_post_load, + .fields = (VMStateField[]) { + VMSTATE_UINT8(simm, KVMS390FLICStateMigTmp), + VMSTATE_UINT8(nimm, KVMS390FLICStateMigTmp), + VMSTATE_END_OF_LIST() + } +}; + +static const VMStateDescription kvm_s390_flic_vmstate_ais = { + .name = "s390-flic/ais", + .version_id = 1, + .minimum_version_id = 1, + .needed = ais_needed, + .fields = (VMStateField[]) { + VMSTATE_WITH_TMP(KVMS390FLICState, KVMS390FLICStateMigTmp, + kvm_s390_flic_ais_tmp), + VMSTATE_END_OF_LIST() + } +}; + static const VMStateDescription kvm_s390_flic_vmstate = { + /* should have been like kvm-s390-flic, + * can't change without breaking compat */ .name = "s390-flic", .version_id = FLIC_SAVEVM_VERSION, .minimum_version_id = FLIC_SAVEVM_VERSION, @@ -428,6 +505,10 @@ static const VMStateDescription kvm_s390_flic_vmstate = { .flags = VMS_SINGLE, }, VMSTATE_END_OF_LIST() + }, + .subsections = (const VMStateDescription * []) { + &kvm_s390_flic_vmstate_ais, + NULL } }; diff --git a/include/hw/s390x/s390_flic.h b/include/hw/s390x/s390_flic.h index 2f173d905c..7aab6ef7f0 100644 --- a/include/hw/s390x/s390_flic.h +++ b/include/hw/s390x/s390_flic.h @@ -89,6 +89,7 @@ typedef struct QEMUS390FLICState { void s390_flic_init(void); S390FLICState *s390_get_flic(void); +bool ais_needed(void *opaque); #ifdef CONFIG_KVM DeviceState *s390_flic_kvm_create(void); From 6da5c593bb2c27cef5fbfc4b37342bbf66133cc1 Mon Sep 17 00:00:00 2001 From: "Jason J. Herne" Date: Thu, 13 Apr 2017 10:28:41 -0400 Subject: [PATCH 34/40] s390x/cpumodel: wire up new hardware features Some new guest features have been introduced recently. Let's wire them up in the CPU model. Signed-off-by: Jason J. Herne Acked-by: Christian Borntraeger Acked-by: Cornelia Huck Signed-off-by: Christian Borntraeger [split patch] --- include/hw/s390x/sclp.h | 3 +-- target/s390x/cpu_features.c | 41 +++++++++++++++++++++++++++++++++ target/s390x/cpu_features.h | 4 ++++ target/s390x/cpu_features_def.h | 41 ++++++++++++++++++++++++++++++++- target/s390x/cpu_models.c | 25 ++++++++++++++++++++ target/s390x/gen-features.c | 39 +++++++++++++++++++++++++++++++ target/s390x/kvm.c | 10 ++++++++ 7 files changed, 160 insertions(+), 3 deletions(-) diff --git a/include/hw/s390x/sclp.h b/include/hw/s390x/sclp.h index 3008a5148a..e71d526605 100644 --- a/include/hw/s390x/sclp.h +++ b/include/hw/s390x/sclp.h @@ -123,8 +123,7 @@ typedef struct ReadInfo { uint64_t facilities; /* 48-55 */ uint8_t _reserved0[76 - 56]; /* 56-75 */ uint32_t ibc_val; - uint8_t conf_char[96 - 80]; /* 80-95 */ - uint8_t _reserved4[99 - 96]; /* 96-98 */ + uint8_t conf_char[99 - 80]; /* 80-98 */ uint8_t mha_pow; uint32_t rnsize2; uint64_t rnmax2; diff --git a/target/s390x/cpu_features.c b/target/s390x/cpu_features.c index 8ab5cd707c..e5a3f71492 100644 --- a/target/s390x/cpu_features.c +++ b/target/s390x/cpu_features.c @@ -59,6 +59,7 @@ static const S390FeatDef s390_features[] = { FEAT_INIT("exrl", S390_FEAT_TYPE_STFL, 35, "Execute-extensions facility"), FEAT_INIT("emon", S390_FEAT_TYPE_STFL, 36, "Enhanced-monitor facility"), FEAT_INIT("fpe", S390_FEAT_TYPE_STFL, 37, "Floating-point extension facility"), + FEAT_INIT("opc", S390_FEAT_TYPE_STFL, 38, "Order Preserving Compression facility"), FEAT_INIT("sprogp", S390_FEAT_TYPE_STFL, 40, "Set-program-parameters facility"), FEAT_INIT("fpseh", S390_FEAT_TYPE_STFL, 41, "Floating-point-support-enhancement facilities"), FEAT_INIT("dfp", S390_FEAT_TYPE_STFL, 42, "DFP (decimal-floating-point) facility"), @@ -72,7 +73,11 @@ static const S390FeatDef s390_features[] = { FEAT_INIT("ltlbc", S390_FEAT_TYPE_STFL, 51, "Local-TLB-clearing facility"), FEAT_INIT("iacc2", S390_FEAT_TYPE_STFL, 52, "Interlocked-access facility 2"), FEAT_INIT("stfle53", S390_FEAT_TYPE_STFL, 53, "Various facilities introduced with z13"), + FEAT_INIT("eec", S390_FEAT_TYPE_STFL, 54, "Entropy encoding compression facility"), FEAT_INIT("msa5-base", S390_FEAT_TYPE_STFL, 57, "Message-security-assist-extension-5 facility (excluding subfunctions)"), + FEAT_INIT("minste2", S390_FEAT_TYPE_STFL, 58, "Miscellaneous-instruction-extensions facility 2"), + FEAT_INIT("sema", S390_FEAT_TYPE_STFL, 59, "Semaphore-assist facility"), + FEAT_INIT("tsi", S390_FEAT_TYPE_STFL, 60, "Time-slice Instrumentation facility"), FEAT_INIT("ri", S390_FEAT_TYPE_STFL, 64, "CPU runtime-instrumentation facility"), FEAT_INIT("zpci", S390_FEAT_TYPE_STFL, 69, "z/PCI facility"), FEAT_INIT("aen", S390_FEAT_TYPE_STFL, 71, "General-purpose-adapter-event-notification facility"), @@ -85,10 +90,22 @@ static const S390FeatDef s390_features[] = { FEAT_INIT("edat2", S390_FEAT_TYPE_STFL, 78, "Enhanced-DAT facility 2"), FEAT_INIT("dfppc", S390_FEAT_TYPE_STFL, 80, "Decimal-floating-point packed-conversion facility"), FEAT_INIT("vx", S390_FEAT_TYPE_STFL, 129, "Vector facility"), + FEAT_INIT("iep", S390_FEAT_TYPE_STFL, 130, "Instruction-execution-protection facility"), + FEAT_INIT("sea_esop2", S390_FEAT_TYPE_STFL, 131, "Side-effect-access facility and Enhanced-suppression-on-protection facility 2"), + FEAT_INIT("gs", S390_FEAT_TYPE_STFL, 133, "Guarded-storage facility"), + FEAT_INIT("vxpd", S390_FEAT_TYPE_STFL, 134, "Vector packed decimal facility"), + FEAT_INIT("vxeh", S390_FEAT_TYPE_STFL, 135, "Vector enhancements facility"), + FEAT_INIT("mepoch", S390_FEAT_TYPE_STFL, 139, "Multiple-epoch facility"), + FEAT_INIT("tpei", S390_FEAT_TYPE_STFL, 144, "Test-pending-external-interruption facility"), + FEAT_INIT("irbm", S390_FEAT_TYPE_STFL, 145, "Insert-reference-bits-multiple facility"), + FEAT_INIT("msa8-base", S390_FEAT_TYPE_STFL, 146, "Message-security-assist-extension-8 facility (excluding subfunctions)"), + FEAT_INIT("cmmnt", S390_FEAT_TYPE_STFL, 147, "CMM: ESSA-enhancement (no translate) facility"), /* SCLP SCCB Byte 80 - 98 (bit numbers relative to byte-80) */ FEAT_INIT("gsls", S390_FEAT_TYPE_SCLP_CONF_CHAR, 40, "SIE: Guest-storage-limit-suppression facility"), FEAT_INIT("esop", S390_FEAT_TYPE_SCLP_CONF_CHAR, 46, "Enhanced-suppression-on-protection facility"), + FEAT_INIT("hpma2", S390_FEAT_TYPE_SCLP_CONF_CHAR, 90, "Host page management assist 2 Facility"), /* 91-2 */ + FEAT_INIT("kss", S390_FEAT_TYPE_SCLP_CONF_CHAR, 151, "SIE: Keyless-subset facility"), /* 98-7 */ /* SCLP SCCB Byte 116 - 119 (bit numbers relative to byte-116) */ FEAT_INIT("64bscao", S390_FEAT_TYPE_SCLP_CONF_CHAR_EXT, 0, "SIE: 64-bit-SCAO facility"), @@ -187,11 +204,23 @@ static const S390FeatDef s390_features[] = { FEAT_INIT("kimd-sha-1", S390_FEAT_TYPE_KIMD, 1, "KIMD SHA-1"), FEAT_INIT("kimd-sha-256", S390_FEAT_TYPE_KIMD, 2, "KIMD SHA-256"), FEAT_INIT("kimd-sha-512", S390_FEAT_TYPE_KIMD, 3, "KIMD SHA-512"), + FEAT_INIT("kimd-sha3-224", S390_FEAT_TYPE_KIMD, 32, "KIMD SHA3-224"), + FEAT_INIT("kimd-sha3-256", S390_FEAT_TYPE_KIMD, 33, "KIMD SHA3-256"), + FEAT_INIT("kimd-sha3-384", S390_FEAT_TYPE_KIMD, 34, "KIMD SHA3-384"), + FEAT_INIT("kimd-sha3-512", S390_FEAT_TYPE_KIMD, 35, "KIMD SHA3-512"), + FEAT_INIT("kimd-shake-128", S390_FEAT_TYPE_KIMD, 36, "KIMD SHAKE-128"), + FEAT_INIT("kimd-shake-256", S390_FEAT_TYPE_KIMD, 37, "KIMD SHAKE-256"), FEAT_INIT("kimd-ghash", S390_FEAT_TYPE_KIMD, 65, "KIMD GHASH"), FEAT_INIT("klmd-sha-1", S390_FEAT_TYPE_KLMD, 1, "KLMD SHA-1"), FEAT_INIT("klmd-sha-256", S390_FEAT_TYPE_KLMD, 2, "KLMD SHA-256"), FEAT_INIT("klmd-sha-512", S390_FEAT_TYPE_KLMD, 3, "KLMD SHA-512"), + FEAT_INIT("klmd-sha3-224", S390_FEAT_TYPE_KLMD, 32, "KLMD SHA3-224"), + FEAT_INIT("klmd-sha3-256", S390_FEAT_TYPE_KLMD, 33, "KLMD SHA3-256"), + FEAT_INIT("klmd-sha3-384", S390_FEAT_TYPE_KLMD, 34, "KLMD SHA3-384"), + FEAT_INIT("klmd-sha3-512", S390_FEAT_TYPE_KLMD, 35, "KLMD SHA3-512"), + FEAT_INIT("klmd-shake-128", S390_FEAT_TYPE_KLMD, 36, "KLMD SHAKE-128"), + FEAT_INIT("klmd-shake-256", S390_FEAT_TYPE_KLMD, 37, "KLMD SHAKE-256"), FEAT_INIT("pckmo-edea", S390_FEAT_TYPE_PCKMO, 1, "PCKMO Encrypted-DEA-Key"), FEAT_INIT("pckmo-etdea-128", S390_FEAT_TYPE_PCKMO, 2, "PCKMO Encrypted-TDEA-128-Key"), @@ -257,6 +286,15 @@ static const S390FeatDef s390_features[] = { FEAT_INIT("pcc-xts-eaes-256", S390_FEAT_TYPE_PCC, 60, "PCC Compute-XTS-Parameter-Using-Encrypted-AES-256"), FEAT_INIT("ppno-sha-512-drng", S390_FEAT_TYPE_PPNO, 3, "PPNO SHA-512-DRNG"), + FEAT_INIT("prno-trng-qrtcr", S390_FEAT_TYPE_PPNO, 112, "PRNO TRNG-Query-Raw-to-Conditioned-Ratio"), + FEAT_INIT("prno-trng", S390_FEAT_TYPE_PPNO, 114, "PRNO TRNG"), + + FEAT_INIT("kma-gcm-aes-128", S390_FEAT_TYPE_KMA, 18, "KMA GCM-AES-128"), + FEAT_INIT("kma-gcm-aes-192", S390_FEAT_TYPE_KMA, 19, "KMA GCM-AES-192"), + FEAT_INIT("kma-gcm-aes-256", S390_FEAT_TYPE_KMA, 20, "KMA GCM-AES-256"), + FEAT_INIT("kma-gcm-eaes-128", S390_FEAT_TYPE_KMA, 26, "KMA GCM-Encrypted-AES-128"), + FEAT_INIT("kma-gcm-eaes-192", S390_FEAT_TYPE_KMA, 27, "KMA GCM-Encrypted-AES-192"), + FEAT_INIT("kma-gcm-eaes-256", S390_FEAT_TYPE_KMA, 28, "KMA GCM-Encrypted-AES-256"), }; const S390FeatDef *s390_feat_def(S390Feat feat) @@ -389,6 +427,9 @@ static S390FeatGroupDef s390_feature_groups[] = { FEAT_GROUP_INIT("msa3", MSA_EXT_3, "Message-security-assist-extension 3 facility"), FEAT_GROUP_INIT("msa4", MSA_EXT_4, "Message-security-assist-extension 4 facility"), FEAT_GROUP_INIT("msa5", MSA_EXT_5, "Message-security-assist-extension 5 facility"), + FEAT_GROUP_INIT("msa6", MSA_EXT_6, "Message-security-assist-extension 6 facility"), + FEAT_GROUP_INIT("msa7", MSA_EXT_7, "Message-security-assist-extension 7 facility"), + FEAT_GROUP_INIT("msa8", MSA_EXT_8, "Message-security-assist-extension 8 facility"), }; const S390FeatGroupDef *s390_feat_group_def(S390FeatGroup group) diff --git a/target/s390x/cpu_features.h b/target/s390x/cpu_features.h index d669121786..14bc311dbe 100644 --- a/target/s390x/cpu_features.h +++ b/target/s390x/cpu_features.h @@ -37,6 +37,7 @@ typedef enum { S390_FEAT_TYPE_KMO, S390_FEAT_TYPE_PCC, S390_FEAT_TYPE_PPNO, + S390_FEAT_TYPE_KMA, } S390FeatType; /* Definition of a CPU feature */ @@ -74,6 +75,9 @@ typedef enum { S390_FEAT_GROUP_MSA_EXT_3, S390_FEAT_GROUP_MSA_EXT_4, S390_FEAT_GROUP_MSA_EXT_5, + S390_FEAT_GROUP_MSA_EXT_6, + S390_FEAT_GROUP_MSA_EXT_7, + S390_FEAT_GROUP_MSA_EXT_8, S390_FEAT_GROUP_MAX, } S390FeatGroup; diff --git a/target/s390x/cpu_features_def.h b/target/s390x/cpu_features_def.h index c939a00a6a..4b6d4e9cc0 100644 --- a/target/s390x/cpu_features_def.h +++ b/target/s390x/cpu_features_def.h @@ -50,6 +50,7 @@ typedef enum { S390_FEAT_EXECUTE_EXT, S390_FEAT_ENHANCED_MONITOR, S390_FEAT_FLOATING_POINT_EXT, + S390_FEAT_ORDER_PRESERVING_COMPRESSION, S390_FEAT_SET_PROGRAM_PARAMETERS, S390_FEAT_FLOATING_POINT_SUPPPORT_ENH, S390_FEAT_DFP, @@ -63,7 +64,11 @@ typedef enum { S390_FEAT_LOCAL_TLB_CLEARING, S390_FEAT_INTERLOCKED_ACCESS_2, S390_FEAT_STFLE_53, + S390_FEAT_ENTROPY_ENC_COMP, S390_FEAT_MSA_EXT_5, + S390_FEAT_MISC_INSTRUCTION_EXT, + S390_FEAT_SEMAPHORE_ASSIST, + S390_FEAT_TIME_SLICE_INSTRUMENTATION, S390_FEAT_RUNTIME_INSTRUMENTATION, S390_FEAT_ZPCI, S390_FEAT_ADAPTER_EVENT_NOTIFICATION, @@ -76,10 +81,22 @@ typedef enum { S390_FEAT_EDAT_2, S390_FEAT_DFP_PACKED_CONVERSION, S390_FEAT_VECTOR, + S390_FEAT_INSTRUCTION_EXEC_PROT, + S390_FEAT_SIDE_EFFECT_ACCESS_ESOP2, + S390_FEAT_GUARDED_STORAGE, + S390_FEAT_VECTOR_PACKED_DECIMAL, + S390_FEAT_VECTOR_ENH, + S390_FEAT_MULTIPLE_EPOCH, + S390_FEAT_TEST_PENDING_EXT_INTERRUPTION, + S390_FEAT_INSERT_REFERENCE_BITS_MULT, + S390_FEAT_MSA_EXT_8, + S390_FEAT_CMM_NT, /* Sclp Conf Char */ S390_FEAT_SIE_GSLS, S390_FEAT_ESOP, + S390_FEAT_HPMA2, + S390_FEAT_SIE_KSS, /* Sclp Conf Char Ext */ S390_FEAT_SIE_64BSCAO, @@ -186,12 +203,24 @@ typedef enum { S390_FEAT_KIMD_SHA_1, S390_FEAT_KIMD_SHA_256, S390_FEAT_KIMD_SHA_512, + S390_FEAT_KIMD_SHA3_224, + S390_FEAT_KIMD_SHA3_256, + S390_FEAT_KIMD_SHA3_384, + S390_FEAT_KIMD_SHA3_512, + S390_FEAT_KIMD_SHAKE_128, + S390_FEAT_KIMD_SHAKE_256, S390_FEAT_KIMD_GHASH, /* KLMD */ S390_FEAT_KLMD_SHA_1, S390_FEAT_KLMD_SHA_256, S390_FEAT_KLMD_SHA_512, + S390_FEAT_KLMD_SHA3_224, + S390_FEAT_KLMD_SHA3_256, + S390_FEAT_KLMD_SHA3_384, + S390_FEAT_KLMD_SHA3_512, + S390_FEAT_KLMD_SHAKE_128, + S390_FEAT_KLMD_SHAKE_256, /* PCKMO */ S390_FEAT_PCKMO_EDEA, @@ -261,8 +290,18 @@ typedef enum { S390_FEAT_PCC_XTS_EAES_128, S390_FEAT_PCC_XTS_EAES_256, - /* PPNO */ + /* PPNO/PRNO */ S390_FEAT_PPNO_SHA_512_DRNG, + S390_FEAT_PRNO_TRNG_QRTCR, + S390_FEAT_PRNO_TRNG, + + /* KMA */ + S390_FEAT_KMA_GCM_AES_128, + S390_FEAT_KMA_GCM_AES_192, + S390_FEAT_KMA_GCM_AES_256 , + S390_FEAT_KMA_GCM_EAES_128, + S390_FEAT_KMA_GCM_EAES_192, + S390_FEAT_KMA_GCM_EAES_256, S390_FEAT_MAX, } S390Feat; diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c index fd3f459caa..16100ec88e 100644 --- a/target/s390x/cpu_models.c +++ b/target/s390x/cpu_models.c @@ -697,6 +697,31 @@ static void check_consistency(const S390CPUModel *model) { S390_FEAT_SIE_CMMA, S390_FEAT_CMM }, { S390_FEAT_SIE_CMMA, S390_FEAT_SIE_GSLS }, { S390_FEAT_SIE_PFMFI, S390_FEAT_EDAT }, + { S390_FEAT_MSA_EXT_8, S390_FEAT_MSA_EXT_3 }, + { S390_FEAT_MULTIPLE_EPOCH, S390_FEAT_TOD_CLOCK_STEERING }, + { S390_FEAT_VECTOR_PACKED_DECIMAL, S390_FEAT_VECTOR }, + { S390_FEAT_VECTOR_ENH, S390_FEAT_VECTOR }, + { S390_FEAT_INSTRUCTION_EXEC_PROT, S390_FEAT_SIDE_EFFECT_ACCESS_ESOP2 }, + { S390_FEAT_SIDE_EFFECT_ACCESS_ESOP2, S390_FEAT_ESOP }, + { S390_FEAT_CMM_NT, S390_FEAT_CMM }, + { S390_FEAT_GUARDED_STORAGE, S390_FEAT_SIDE_EFFECT_ACCESS_ESOP2 }, + { S390_FEAT_MULTIPLE_EPOCH, S390_FEAT_STORE_CLOCK_FAST }, + { S390_FEAT_MULTIPLE_EPOCH, S390_FEAT_TOD_CLOCK_STEERING }, + { S390_FEAT_SEMAPHORE_ASSIST, S390_FEAT_STFLE_49 }, + { S390_FEAT_KIMD_SHA3_224, S390_FEAT_MSA }, + { S390_FEAT_KIMD_SHA3_256, S390_FEAT_MSA }, + { S390_FEAT_KIMD_SHA3_384, S390_FEAT_MSA }, + { S390_FEAT_KIMD_SHA3_512, S390_FEAT_MSA }, + { S390_FEAT_KIMD_SHAKE_128, S390_FEAT_MSA }, + { S390_FEAT_KIMD_SHAKE_256, S390_FEAT_MSA }, + { S390_FEAT_KLMD_SHA3_224, S390_FEAT_MSA }, + { S390_FEAT_KLMD_SHA3_256, S390_FEAT_MSA }, + { S390_FEAT_KLMD_SHA3_384, S390_FEAT_MSA }, + { S390_FEAT_KLMD_SHA3_512, S390_FEAT_MSA }, + { S390_FEAT_KLMD_SHAKE_128, S390_FEAT_MSA }, + { S390_FEAT_KLMD_SHAKE_256, S390_FEAT_MSA }, + { S390_FEAT_PRNO_TRNG_QRTCR, S390_FEAT_MSA_EXT_5 }, + { S390_FEAT_PRNO_TRNG, S390_FEAT_MSA_EXT_5 }, }; int i; diff --git a/target/s390x/gen-features.c b/target/s390x/gen-features.c index 622ee2492c..33404e4b07 100644 --- a/target/s390x/gen-features.c +++ b/target/s390x/gen-features.c @@ -182,6 +182,33 @@ S390_FEAT_MSA_EXT_5, \ S390_FEAT_PPNO_SHA_512_DRNG +#define S390_FEAT_GROUP_MSA_EXT_6 \ + S390_FEAT_KIMD_SHA3_224, \ + S390_FEAT_KIMD_SHA3_256, \ + S390_FEAT_KIMD_SHA3_384, \ + S390_FEAT_KIMD_SHA3_512, \ + S390_FEAT_KIMD_SHAKE_128, \ + S390_FEAT_KIMD_SHAKE_256, \ + S390_FEAT_KLMD_SHA3_224, \ + S390_FEAT_KLMD_SHA3_256, \ + S390_FEAT_KLMD_SHA3_384, \ + S390_FEAT_KLMD_SHA3_512, \ + S390_FEAT_KLMD_SHAKE_128, \ + S390_FEAT_KLMD_SHAKE_256 + +#define S390_FEAT_GROUP_MSA_EXT_7 \ + S390_FEAT_PRNO_TRNG_QRTCR, \ + S390_FEAT_PRNO_TRNG + +#define S390_FEAT_GROUP_MSA_EXT_8 \ + S390_FEAT_MSA_EXT_8, \ + S390_FEAT_KMA_GCM_AES_128, \ + S390_FEAT_KMA_GCM_AES_192, \ + S390_FEAT_KMA_GCM_AES_256 , \ + S390_FEAT_KMA_GCM_EAES_128, \ + S390_FEAT_KMA_GCM_EAES_192, \ + S390_FEAT_KMA_GCM_EAES_256 + /* cpu feature groups */ static uint16_t group_PLO[] = { S390_FEAT_GROUP_PLO, @@ -210,6 +237,15 @@ static uint16_t group_MSA_EXT_4[] = { static uint16_t group_MSA_EXT_5[] = { S390_FEAT_GROUP_MSA_EXT_5, }; +static uint16_t group_MSA_EXT_6[] = { + S390_FEAT_GROUP_MSA_EXT_6, +}; +static uint16_t group_MSA_EXT_7[] = { + S390_FEAT_GROUP_MSA_EXT_7, +}; +static uint16_t group_MSA_EXT_8[] = { + S390_FEAT_GROUP_MSA_EXT_8, +}; /* Base features (in order of release) * Only non-hypervisor managed features belong here. @@ -548,6 +584,9 @@ static FeatGroupDefSpec FeatGroupDef[] = { FEAT_GROUP_INITIALIZER(MSA_EXT_3), FEAT_GROUP_INITIALIZER(MSA_EXT_4), FEAT_GROUP_INITIALIZER(MSA_EXT_5), + FEAT_GROUP_INITIALIZER(MSA_EXT_6), + FEAT_GROUP_INITIALIZER(MSA_EXT_7), + FEAT_GROUP_INITIALIZER(MSA_EXT_8), }; static void set_bits(uint64_t list[], BitSpec bits) diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c index 1901153c58..3a80f1fc49 100644 --- a/target/s390x/kvm.c +++ b/target/s390x/kvm.c @@ -2447,6 +2447,9 @@ static int query_cpu_subfunc(S390FeatBitmap features) if (test_bit(S390_FEAT_MSA_EXT_5, features)) { s390_add_from_feat_block(features, S390_FEAT_TYPE_PPNO, prop.ppno); } + if (test_bit(S390_FEAT_MSA_EXT_8, features)) { + s390_add_from_feat_block(features, S390_FEAT_TYPE_KMA, prop.kma); + } return 0; } @@ -2500,6 +2503,10 @@ static int configure_cpu_subfunc(const S390FeatBitmap features) s390_fill_feat_block(features, S390_FEAT_TYPE_PPNO, prop.ppno); prop.ppno[0] |= 0x80; /* query is always available */ } + if (test_bit(S390_FEAT_MSA_EXT_8, features)) { + s390_fill_feat_block(features, S390_FEAT_TYPE_KMA, prop.kma); + prop.kma[0] |= 0x80; /* query is always available */ + } return kvm_vm_ioctl(kvm_state, KVM_SET_DEVICE_ATTR, &attr); } @@ -2636,6 +2643,9 @@ void kvm_s390_get_host_cpu_model(S390CPUModel *model, Error **errp) /* with cpu model support, CMM is only indicated if really available */ if (kvm_s390_cmma_available()) { set_bit(S390_FEAT_CMM, model->features); + } else { + /* no cmm -> no cmm nt */ + clear_bit(S390_FEAT_CMM_NT, model->features); } /* set zpci and aen facilities */ From 075e52b816648f21ca6bf5cc01624dff3993c99e Mon Sep 17 00:00:00 2001 From: "Jason J. Herne" Date: Thu, 1 Sep 2016 10:56:49 +0200 Subject: [PATCH 35/40] s390x/cpumodel: we are always in zarchitecture mode In QEMU, a guest VCPU always started in and never was able to leave z/Architecture mode. Now we have an architected way of showing this condition. The SIGP SET ARCHITECTURE instruction is simply rejected. Linux as guest seems to not care about the return value, which is a good thing The new handling is just like already being in z/Architecture mode. We'll not try to fake absence of this facility, but still not indicate the facility in case some strange CPU model turned z/Architecture off completely (which doesn't work either way but let's us see how a guest would react on a lack of this facility). Signed-off-by: Jason J. Herne Acked-by: Christian Borntraeger Acked-by: Cornelia Huck Signed-off-by: Christian Borntraeger --- target/s390x/cpu_features.c | 5 +++-- target/s390x/kvm.c | 38 +++++++++++-------------------------- 2 files changed, 14 insertions(+), 29 deletions(-) diff --git a/target/s390x/cpu_features.c b/target/s390x/cpu_features.c index e5a3f71492..fa887d9b6f 100644 --- a/target/s390x/cpu_features.c +++ b/target/s390x/cpu_features.c @@ -337,8 +337,9 @@ void s390_fill_feat_block(const S390FeatBitmap features, S390FeatType type, int bit_nr; if (type == S390_FEAT_TYPE_STFL && test_bit(S390_FEAT_ZARCH, features)) { - /* z/Architecture is always active if around */ - data[0] |= 0x20; + /* Features that are always active */ + data[0] |= 0x20; /* z/Architecture */ + data[17] |= 0x20; /* Configuration-z-architectural-mode */ } feat = find_first_bit(features, S390_FEAT_MAX); diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c index 3a80f1fc49..8c6cc0aaf7 100644 --- a/target/s390x/kvm.c +++ b/target/s390x/kvm.c @@ -1757,41 +1757,25 @@ static int sigp_set_architecture(S390CPU *cpu, uint32_t param, { CPUState *cur_cs; S390CPU *cur_cpu; + bool all_stopped = true; - /* due to the BQL, we are the only active cpu */ CPU_FOREACH(cur_cs) { cur_cpu = S390_CPU(cur_cs); - if (cur_cpu->env.sigp_order != 0) { - return SIGP_CC_BUSY; + + if (cur_cpu == cpu) { + continue; } - cpu_synchronize_state(cur_cs); - /* all but the current one have to be stopped */ - if (cur_cpu != cpu && - s390_cpu_get_state(cur_cpu) != CPU_STATE_STOPPED) { - *status_reg &= 0xffffffff00000000ULL; - *status_reg |= SIGP_STAT_INCORRECT_STATE; - return SIGP_CC_STATUS_STORED; + if (s390_cpu_get_state(cur_cpu) != CPU_STATE_STOPPED) { + all_stopped = false; } } - switch (param & 0xff) { - case SIGP_MODE_ESA_S390: - /* not supported */ - return SIGP_CC_NOT_OPERATIONAL; - case SIGP_MODE_Z_ARCH_TRANS_ALL_PSW: - case SIGP_MODE_Z_ARCH_TRANS_CUR_PSW: - CPU_FOREACH(cur_cs) { - cur_cpu = S390_CPU(cur_cs); - cur_cpu->env.pfault_token = -1UL; - } - break; - default: - *status_reg &= 0xffffffff00000000ULL; - *status_reg |= SIGP_STAT_INVALID_PARAMETER; - return SIGP_CC_STATUS_STORED; - } + *status_reg &= 0xffffffff00000000ULL; - return SIGP_CC_ORDER_CODE_ACCEPTED; + /* Reject set arch order, with czam we're always in z/Arch mode. */ + *status_reg |= (all_stopped ? SIGP_STAT_INVALID_PARAMETER : + SIGP_STAT_INCORRECT_STATE); + return SIGP_CC_STATUS_STORED; } static int handle_sigp(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1) From 7223bccea3654b6bd6e10f0fb6d0099f1a4b0e80 Mon Sep 17 00:00:00 2001 From: "Jason J. Herne" Date: Mon, 10 Apr 2017 09:39:00 -0400 Subject: [PATCH 36/40] s390x/cpumodel: add esop/esop2 to z12 model Add esop and esop2 features to z12 model where esop2 was originally introduced. Disable esop and esop2 when using compatibility machine v2.9 or earlier. Signed-off-by: Jason J. Herne Acked-by: Christian Borntraeger Reviewed-by: Cornelia Huck Signed-off-by: Christian Borntraeger --- hw/s390x/s390-virtio-ccw.c | 3 +++ target/s390x/gen-features.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index e484aedee9..657a45ff95 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -30,6 +30,7 @@ #include "hw/s390x/s390-virtio-ccw.h" #include "hw/s390x/css-bridge.h" #include "migration/register.h" +#include "cpu_models.h" static const char *const reset_dev_types[] = { TYPE_VIRTUAL_CSS_BRIDGE, @@ -503,6 +504,8 @@ DEFINE_CCW_MACHINE(2_10, "2.10", true); static void ccw_machine_2_9_instance_options(MachineState *machine) { ccw_machine_2_10_instance_options(machine); + s390_cpudef_featoff_greater(12, 1, S390_FEAT_ESOP); + s390_cpudef_featoff_greater(12, 1, S390_FEAT_SIDE_EFFECT_ACCESS_ESOP2); s390_cpudef_featoff_greater(12, 1, S390_FEAT_ZPCI); s390_cpudef_featoff_greater(12, 1, S390_FEAT_ADAPTER_INT_SUPPRESSION); s390_cpudef_featoff_greater(12, 1, S390_FEAT_ADAPTER_EVENT_NOTIFICATION); diff --git a/target/s390x/gen-features.c b/target/s390x/gen-features.c index 33404e4b07..af14b11199 100644 --- a/target/s390x/gen-features.c +++ b/target/s390x/gen-features.c @@ -429,6 +429,7 @@ static uint16_t full_GEN12_GA1[] = { S390_FEAT_ADAPTER_EVENT_NOTIFICATION, S390_FEAT_ADAPTER_INT_SUPPRESSION, S390_FEAT_EDAT_2, + S390_FEAT_SIDE_EFFECT_ACCESS_ESOP2, }; static uint16_t full_GEN12_GA2[] = { @@ -488,6 +489,8 @@ static uint16_t default_GEN12_GA1[] = { S390_FEAT_ZPCI, S390_FEAT_ADAPTER_EVENT_NOTIFICATION, S390_FEAT_EDAT_2, + S390_FEAT_ESOP, + S390_FEAT_SIDE_EFFECT_ACCESS_ESOP2, }; #define default_GEN12_GA2 EmptyFeat From c0a9cd940e6bbad75cef3b5e87b826125702c353 Mon Sep 17 00:00:00 2001 From: Farhan Ali Date: Wed, 3 May 2017 16:54:50 -0400 Subject: [PATCH 37/40] s390x/kvm: Enable KSS facility for nested virtualization If the host supports keyless subset (KSS) then first level guest (G2) should enable KSS facility as well. Signed-off-by: Farhan Ali Reviewed-by: Eric Farman Acked-by: Cornelia Huck Signed-off-by: Christian Borntraeger --- target/s390x/kvm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c index 8c6cc0aaf7..c773bd6eac 100644 --- a/target/s390x/kvm.c +++ b/target/s390x/kvm.c @@ -2508,6 +2508,7 @@ static int kvm_to_feat[][2] = { { KVM_S390_VM_CPU_FEAT_CMMA, S390_FEAT_SIE_CMMA }, { KVM_S390_VM_CPU_FEAT_PFMFI, S390_FEAT_SIE_PFMFI}, { KVM_S390_VM_CPU_FEAT_SIGPIF, S390_FEAT_SIE_SIGPIF}, + { KVM_S390_VM_CPU_FEAT_KSS, S390_FEAT_SIE_KSS}, }; static int query_cpu_feat(S390FeatBitmap features) From 62deb62d999cf9e2be61272c6b720104f764bd6a Mon Sep 17 00:00:00 2001 From: Fan Zhang Date: Wed, 15 Feb 2017 04:47:49 +0100 Subject: [PATCH 38/40] s390x/kvm: enable guarded storage Introduce guarded storage support for KVM guests on s390. We need to enable the capability, extend machine check validity, sigp store-additional-status-at-address, and migration. The feature is fenced for older machine type versions. Signed-off-by: Fan Zhang Reviewed-by: Cornelia Huck Signed-off-by: Christian Borntraeger --- hw/s390x/s390-virtio-ccw.c | 18 ++++++++ include/hw/s390x/s390-virtio-ccw.h | 3 ++ target/s390x/cpu.h | 7 +++ target/s390x/kvm.c | 71 +++++++++++++++++++++++++----- target/s390x/machine.c | 17 +++++++ 5 files changed, 106 insertions(+), 10 deletions(-) diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index 657a45ff95..ce3921e4de 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -211,6 +211,7 @@ static void ccw_machine_class_init(ObjectClass *oc, void *data) s390mc->ri_allowed = true; s390mc->cpu_model_allowed = true; s390mc->css_migration_enabled = true; + s390mc->gs_allowed = true; mc->init = ccw_init; mc->reset = s390_machine_reset; mc->hot_add_cpu = s390_hot_add_cpu; @@ -288,6 +289,22 @@ bool cpu_model_allowed(void) return get_machine_class()->cpu_model_allowed; } +bool gs_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->gs_allowed; + } + /* Make sure the "none" machine can have gs */ + return true; + } + return false; +} + static char *machine_get_loadparm(Object *obj, Error **errp) { S390CcwMachineState *ms = S390_CCW_MACHINE(obj); @@ -515,6 +532,7 @@ static void ccw_machine_2_9_class_options(MachineClass *mc) { S390CcwMachineClass *s390mc = S390_MACHINE_CLASS(mc); + s390mc->gs_allowed = false; ccw_machine_2_10_class_options(mc); SET_MACHINE_COMPAT(mc, CCW_COMPAT_2_9); s390mc->css_migration_enabled = false; diff --git a/include/hw/s390x/s390-virtio-ccw.h b/include/hw/s390x/s390-virtio-ccw.h index ab88d49d10..41a9d2862b 100644 --- a/include/hw/s390x/s390-virtio-ccw.h +++ b/include/hw/s390x/s390-virtio-ccw.h @@ -40,12 +40,15 @@ typedef struct S390CcwMachineClass { bool ri_allowed; bool cpu_model_allowed; bool css_migration_enabled; + bool gs_allowed; } S390CcwMachineClass; /* runtime-instrumentation allowed by the machine */ bool ri_allowed(void); /* cpu model allowed by the machine */ bool cpu_model_allowed(void); +/* guarded-storage allowed by the machine */ +bool gs_allowed(void); /** * Returns true if (vmstate based) migration of the channel subsystem diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h index 8ab75c0d43..7732d01784 100644 --- a/target/s390x/cpu.h +++ b/target/s390x/cpu.h @@ -89,6 +89,7 @@ typedef struct CPUS390XState { CPU_DoubleU vregs[32][2]; /* vector registers */ uint32_t aregs[16]; /* access registers */ uint8_t riccb[64]; /* runtime instrumentation control */ + uint64_t gscb[4]; /* guarded storage control */ /* Fields up to this point are not cleared by initial CPU reset */ struct {} start_initial_reset_fields; @@ -1166,6 +1167,7 @@ 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); +int kvm_s390_get_gs(void); void kvm_s390_crypto_reset(void); #else static inline void kvm_s390_io_interrupt(uint16_t subchannel_id, @@ -1220,6 +1222,10 @@ static inline int kvm_s390_get_ri(void) { return 0; } +static inline int kvm_s390_get_gs(void) +{ + return 0; +} static inline void kvm_s390_crypto_reset(void) { } @@ -1328,6 +1334,7 @@ static inline bool s390_get_squash_mcss(void) #define MCIC_VB_CR 0x0000000400000000ULL #define MCIC_VB_ST 0x0000000100000000ULL #define MCIC_VB_AR 0x0000000040000000ULL +#define MCIC_VB_GS 0x0000000008000000ULL #define MCIC_VB_PR 0x0000000000200000ULL #define MCIC_VB_FC 0x0000000000100000ULL #define MCIC_VB_CT 0x0000000000020000ULL diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c index c773bd6eac..831492f9a2 100644 --- a/target/s390x/kvm.c +++ b/target/s390x/kvm.c @@ -139,6 +139,7 @@ static int cap_async_pf; static int cap_mem_op; static int cap_s390_irq; static int cap_ri; +static int cap_gs; static int active_cmma; @@ -301,6 +302,11 @@ int kvm_arch_init(MachineState *ms, KVMState *s) cap_ri = 1; } } + if (gs_allowed()) { + if (kvm_vm_enable_cap(s, KVM_CAP_S390_GS, 0) == 0) { + cap_gs = 1; + } + } /* Try to enable AIS facility */ kvm_vm_enable_cap(s, KVM_CAP_S390_AIS, 0); @@ -472,6 +478,11 @@ int kvm_arch_put_registers(CPUState *cs, int level) } } + if (can_sync_regs(cs, KVM_SYNC_GSCB)) { + memcpy(cs->kvm_run->s.regs.gscb, env->gscb, 32); + cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_GSCB; + } + /* Finally the prefix */ if (can_sync_regs(cs, KVM_SYNC_PREFIX)) { cs->kvm_run->s.regs.prefix = env->psa; @@ -578,6 +589,10 @@ int kvm_arch_get_registers(CPUState *cs) memcpy(env->riccb, cs->kvm_run->s.regs.riccb, 64); } + if (can_sync_regs(cs, KVM_SYNC_GSCB)) { + memcpy(env->gscb, cs->kvm_run->s.regs.gscb, 32); + } + /* pfault parameters */ if (can_sync_regs(cs, KVM_SYNC_PFAULT)) { env->pfault_token = cs->kvm_run->s.regs.pft; @@ -1474,22 +1489,28 @@ static void sigp_stop(CPUState *cs, run_on_cpu_data arg) si->cc = SIGP_CC_ORDER_CODE_ACCEPTED; } -#define ADTL_SAVE_AREA_SIZE 1024 -static int kvm_s390_store_adtl_status(S390CPU *cpu, hwaddr addr) +#define ADTL_GS_OFFSET 1024 /* offset of GS data in adtl save area */ +#define ADTL_GS_MIN_SIZE 2048 /* minimal size of adtl save area for GS */ +static int do_store_adtl_status(S390CPU *cpu, hwaddr addr, hwaddr len) { + hwaddr save = len; void *mem; - hwaddr len = ADTL_SAVE_AREA_SIZE; - mem = cpu_physical_memory_map(addr, &len, 1); + mem = cpu_physical_memory_map(addr, &save, 1); if (!mem) { return -EFAULT; } - if (len != ADTL_SAVE_AREA_SIZE) { + if (save != len) { cpu_physical_memory_unmap(mem, len, 1, 0); return -EFAULT; } - memcpy(mem, &cpu->env.vregs, 512); + if (s390_has_feat(S390_FEAT_VECTOR)) { + memcpy(mem, &cpu->env.vregs, 512); + } + if (s390_has_feat(S390_FEAT_GUARDED_STORAGE) && len >= ADTL_GS_MIN_SIZE) { + memcpy(mem + ADTL_GS_OFFSET, &cpu->env.gscb, 32); + } cpu_physical_memory_unmap(mem, len, 1, len); @@ -1585,12 +1606,17 @@ static void sigp_store_status_at_address(CPUState *cs, run_on_cpu_data arg) si->cc = SIGP_CC_ORDER_CODE_ACCEPTED; } +#define ADTL_SAVE_LC_MASK 0xfUL static void sigp_store_adtl_status(CPUState *cs, run_on_cpu_data arg) { S390CPU *cpu = S390_CPU(cs); SigpInfo *si = arg.host_ptr; + uint8_t lc = si->param & ADTL_SAVE_LC_MASK; + hwaddr addr = si->param & ~ADTL_SAVE_LC_MASK; + hwaddr len = 1UL << (lc ? lc : 10); - if (!s390_has_feat(S390_FEAT_VECTOR)) { + if (!s390_has_feat(S390_FEAT_VECTOR) && + !s390_has_feat(S390_FEAT_GUARDED_STORAGE)) { set_sigp_status(si, SIGP_STAT_INVALID_ORDER); return; } @@ -1601,15 +1627,32 @@ static void sigp_store_adtl_status(CPUState *cs, run_on_cpu_data arg) return; } - /* parameter must be aligned to 1024-byte boundary */ - if (si->param & 0x3ff) { + /* address must be aligned to length */ + if (addr & (len - 1)) { + set_sigp_status(si, SIGP_STAT_INVALID_PARAMETER); + return; + } + + /* no GS: only lc == 0 is valid */ + if (!s390_has_feat(S390_FEAT_GUARDED_STORAGE) && + lc != 0) { + set_sigp_status(si, SIGP_STAT_INVALID_PARAMETER); + return; + } + + /* GS: 0, 10, 11, 12 are valid */ + if (s390_has_feat(S390_FEAT_GUARDED_STORAGE) && + lc != 0 && + lc != 10 && + lc != 11 && + lc != 12) { set_sigp_status(si, SIGP_STAT_INVALID_PARAMETER); return; } cpu_synchronize_state(cs); - if (kvm_s390_store_adtl_status(cpu, si->param)) { + if (do_store_adtl_status(cpu, addr, len)) { set_sigp_status(si, SIGP_STAT_INVALID_PARAMETER); return; } @@ -2188,6 +2231,9 @@ static uint64_t build_channel_report_mcic(void) if (s390_has_feat(S390_FEAT_VECTOR)) { mcic |= MCIC_VB_VR; } + if (s390_has_feat(S390_FEAT_GUARDED_STORAGE)) { + mcic |= MCIC_VB_GS; + } return mcic; } @@ -2253,6 +2299,11 @@ int kvm_s390_get_ri(void) return cap_ri; } +int kvm_s390_get_gs(void) +{ + return cap_gs; +} + 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 8f908bbe82..2dcadfdd29 100644 --- a/target/s390x/machine.c +++ b/target/s390x/machine.c @@ -174,6 +174,22 @@ const VMStateDescription vmstate_exval = { } }; +static bool gscb_needed(void *opaque) +{ + return kvm_s390_get_gs(); +} + +const VMStateDescription vmstate_gscb = { + .name = "cpu/gscb", + .version_id = 1, + .minimum_version_id = 1, + .needed = gscb_needed, + .fields = (VMStateField[]) { + VMSTATE_UINT64_ARRAY(env.gscb, S390CPU, 4), + VMSTATE_END_OF_LIST() + } +}; + const VMStateDescription vmstate_s390_cpu = { .name = "cpu", .post_load = cpu_post_load, @@ -207,6 +223,7 @@ const VMStateDescription vmstate_s390_cpu = { &vmstate_vregs, &vmstate_riccb, &vmstate_exval, + &vmstate_gscb, NULL }, }; From 21a106904b5336b6ea60c22a95feb7d61c664d7f Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Wed, 8 Mar 2017 10:36:04 +0100 Subject: [PATCH 39/40] s390x/arch_dump: also dump guarded storage control block Write the new note section of type 30b (guarded storage control block). Signed-off-by: Christian Borntraeger --- include/elf.h | 1 + target/s390x/arch_dump.c | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/include/elf.h b/include/elf.h index 0dbd3e968b..cd51434877 100644 --- a/include/elf.h +++ b/include/elf.h @@ -1476,6 +1476,7 @@ typedef struct elf64_shdr { #define NT_TASKSTRUCT 4 #define NT_AUXV 6 #define NT_PRXFPREG 0x46e62b7f /* copied from gdb5.1/include/elf/common.h */ +#define NT_S390_GS_CB 0x30b /* s390 guarded storage registers */ #define NT_S390_VXRS_HIGH 0x30a /* s390 vector registers 16-31 */ #define NT_S390_VXRS_LOW 0x309 /* s390 vector registers 0-15 (lower half) */ #define NT_S390_PREFIX 0x305 /* s390 prefix register */ diff --git a/target/s390x/arch_dump.c b/target/s390x/arch_dump.c index 105ae9a5d8..96c9fb97cb 100644 --- a/target/s390x/arch_dump.c +++ b/target/s390x/arch_dump.c @@ -57,6 +57,12 @@ struct S390xElfVregsHiStruct { typedef struct S390xElfVregsHiStruct S390xElfVregsHi; +struct S390xElfGSCBStruct { + uint64_t gsregs[4]; +} QEMU_PACKED; + +typedef struct S390xElfGSCBStruct S390xElfGSCB; + typedef struct noteStruct { Elf64_Nhdr hdr; char name[8]; @@ -65,6 +71,7 @@ typedef struct noteStruct { S390xElfFpregset fpregset; S390xElfVregsLo vregslo; S390xElfVregsHi vregshi; + S390xElfGSCB gscb; uint32_t prefix; uint64_t timer; uint64_t todcmp; @@ -126,6 +133,16 @@ static void s390x_write_elf64_vregshi(Note *note, S390CPU *cpu, int id) } } +static void s390x_write_elf64_gscb(Note *note, S390CPU *cpu, int id) +{ + int i; + + note->hdr.n_type = cpu_to_be32(NT_S390_GS_CB); + for (i = 0; i < 4; i++) { + note->contents.gscb.gsregs[i] = cpu_to_be64(cpu->env.gscb[i]); + } +} + static void s390x_write_elf64_timer(Note *note, S390CPU *cpu, int id) { note->hdr.n_type = cpu_to_be32(NT_S390_TIMER); @@ -181,6 +198,7 @@ static const NoteFuncDesc note_linux[] = { {sizeof(((Note *)0)->contents.todpreg), s390x_write_elf64_todpreg}, {sizeof(((Note *)0)->contents.vregslo), s390x_write_elf64_vregslo}, {sizeof(((Note *)0)->contents.vregshi), s390x_write_elf64_vregshi}, + {sizeof(((Note *)0)->contents.gscb), s390x_write_elf64_gscb}, { 0, NULL} }; From 86158a2a2b81f075c84d0b95c6d72b98dbf1dc61 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Wed, 8 Mar 2017 12:41:14 +0100 Subject: [PATCH 40/40] s390x/gdb: add gs registers Let's provide the guarded storage registers via gdb server. Signed-off-by: Christian Borntraeger --- configure | 2 +- gdb-xml/s390-gs.xml | 14 ++++++++++++++ target/s390x/gdbstub.c | 24 ++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 gdb-xml/s390-gs.xml diff --git a/configure b/configure index 902653ae03..8cc4afb2f6 100755 --- a/configure +++ b/configure @@ -6231,7 +6231,7 @@ case "$target_name" in echo "TARGET_ABI32=y" >> $config_target_mak ;; s390x) - gdb_xml_files="s390x-core64.xml s390-acr.xml s390-fpr.xml s390-vx.xml s390-cr.xml s390-virt.xml" + gdb_xml_files="s390x-core64.xml s390-acr.xml s390-fpr.xml s390-vx.xml s390-cr.xml s390-virt.xml s390-gs.xml" ;; tilegx) ;; diff --git a/gdb-xml/s390-gs.xml b/gdb-xml/s390-gs.xml new file mode 100644 index 0000000000..0487d31c07 --- /dev/null +++ b/gdb-xml/s390-gs.xml @@ -0,0 +1,14 @@ + + + + + + + + + + diff --git a/target/s390x/gdbstub.c b/target/s390x/gdbstub.c index 94ab74d58f..a7efafee9f 100644 --- a/target/s390x/gdbstub.c +++ b/target/s390x/gdbstub.c @@ -286,6 +286,26 @@ static int cpu_write_virt_reg(CPUS390XState *env, uint8_t *mem_buf, int n) } #endif +/* the values represent the positions in s390-gs.xml */ +#define S390_GS_RESERVED_REGNUM 0 +#define S390_GS_GSD_REGNUM 1 +#define S390_GS_GSSM_REGNUM 2 +#define S390_GS_GSEPLA_REGNUM 3 +/* total number of registers in s390-gs.xml */ +#define S390_NUM_GS_REGS 4 + +static int cpu_read_gs_reg(CPUS390XState *env, uint8_t *mem_buf, int n) +{ + return gdb_get_regl(mem_buf, env->gscb[n]); +} + +static int cpu_write_gs_reg(CPUS390XState *env, uint8_t *mem_buf, int n) +{ + env->gscb[n] = ldtul_p(mem_buf); + cpu_synchronize_post_init(ENV_GET_CPU(env)); + return 8; +} + void s390_cpu_gdb_init(CPUState *cs) { gdb_register_coprocessor(cs, cpu_read_ac_reg, @@ -300,6 +320,10 @@ void s390_cpu_gdb_init(CPUState *cs) cpu_write_vreg, S390_NUM_VREGS, "s390-vx.xml", 0); + gdb_register_coprocessor(cs, cpu_read_gs_reg, + cpu_write_gs_reg, + S390_NUM_GS_REGS, "s390-gs.xml", 0); + #ifndef CONFIG_USER_ONLY gdb_register_coprocessor(cs, cpu_read_c_reg, cpu_write_c_reg,