diff options
author | Dominik Dingel <dingel@linux.vnet.ibm.com> | 2014-04-11 13:47:40 +0200 |
---|---|---|
committer | Cornelia Huck <cornelia.huck@de.ibm.com> | 2014-06-10 09:50:27 +0200 |
commit | 4cb88c3c378ae8c86c0ba53619caf6924f72239c (patch) | |
tree | 9a1c2b712ab288b337c25daaec48e627961bcb6b | |
parent | 08da527fd07cf01dc29ca60a144fbdd60b0fb7c0 (diff) | |
download | qemu-4cb88c3c378ae8c86c0ba53619caf6924f72239c.zip qemu-4cb88c3c378ae8c86c0ba53619caf6924f72239c.tar.gz qemu-4cb88c3c378ae8c86c0ba53619caf6924f72239c.tar.bz2 |
s390x/kvm: enable/reset cmma via vm attributes
Exploit the new api for userspace-controlled cmma. If supported, enable
cmma during kvm initialization and register a reset handler for cmma,
which is also called directly from the load IPL code.
The reset functionality is needed to reset the cmma state of the guest
pages, e.g. if a system reset is triggered via qemu monitor; otherwise
this could result in data corruption.
A guest triggered reboot may now lead to multiple cmma resets; this is
OK, however, as this is slowpath anyway and the simplest way to achieve
the intended effects.
Signed-off-by: Dominik Dingel <dingel@linux.vnet.ibm.com>
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
Acked-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
-rw-r--r-- | target-s390x/cpu.h | 12 | ||||
-rw-r--r-- | target-s390x/kvm.c | 58 | ||||
-rw-r--r-- | target-s390x/misc_helper.c | 2 | ||||
-rw-r--r-- | trace-events | 4 |
4 files changed, 76 insertions, 0 deletions
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index 06454d6..808b906 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -1074,6 +1074,7 @@ void kvm_s390_enable_css_support(S390CPU *cpu); int kvm_s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch, int vq, bool assign); int kvm_s390_cpu_restart(S390CPU *cpu); +void kvm_s390_clear_cmma_callback(void *opaque); #else static inline void kvm_s390_io_interrupt(S390CPU *cpu, uint16_t subchannel_id, @@ -1098,8 +1099,19 @@ static inline int kvm_s390_cpu_restart(S390CPU *cpu) { return -ENOSYS; } +static inline void kvm_s390_clear_cmma_callback(void *opaque) +{ +} #endif +static inline void cmma_reset(S390CPU *cpu) +{ + if (kvm_enabled()) { + CPUState *cs = CPU(cpu); + kvm_s390_clear_cmma_callback(cs->kvm_state); + } +} + static inline int s390_cpu_restart(S390CPU *cpu) { if (kvm_enabled()) { diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index 7a07f9d..0a2a205 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -32,6 +32,7 @@ #include "qemu/timer.h" #include "sysemu/sysemu.h" #include "sysemu/kvm.h" +#include "hw/hw.h" #include "cpu.h" #include "sysemu/device_tree.h" #include "qapi/qmp/qjson.h" @@ -104,10 +105,67 @@ static int cap_async_pf; static void *legacy_s390_alloc(size_t size); +static int kvm_s390_check_clear_cmma(KVMState *s) +{ + struct kvm_device_attr attr = { + .group = KVM_S390_VM_MEM_CTRL, + .attr = KVM_S390_VM_MEM_CLR_CMMA, + }; + + return kvm_vm_ioctl(s, KVM_HAS_DEVICE_ATTR, &attr); +} + +static int kvm_s390_check_enable_cmma(KVMState *s) +{ + struct kvm_device_attr attr = { + .group = KVM_S390_VM_MEM_CTRL, + .attr = KVM_S390_VM_MEM_ENABLE_CMMA, + }; + + return kvm_vm_ioctl(s, KVM_HAS_DEVICE_ATTR, &attr); +} + +void kvm_s390_clear_cmma_callback(void *opaque) +{ + int rc; + KVMState *s = opaque; + struct kvm_device_attr attr = { + .group = KVM_S390_VM_MEM_CTRL, + .attr = KVM_S390_VM_MEM_CLR_CMMA, + }; + + rc = kvm_vm_ioctl(s, KVM_SET_DEVICE_ATTR, &attr); + trace_kvm_clear_cmma(rc); +} + +static void kvm_s390_enable_cmma(KVMState *s) +{ + int rc; + struct kvm_device_attr attr = { + .group = KVM_S390_VM_MEM_CTRL, + .attr = KVM_S390_VM_MEM_ENABLE_CMMA, + }; + + if (kvm_s390_check_enable_cmma(s) || kvm_s390_check_clear_cmma(s)) { + return; + } + + rc = kvm_vm_ioctl(s, KVM_SET_DEVICE_ATTR, &attr); + if (!rc) { + qemu_register_reset(kvm_s390_clear_cmma_callback, s); + } + trace_kvm_enable_cmma(rc); +} + int kvm_arch_init(KVMState *s) { cap_sync_regs = kvm_check_extension(s, KVM_CAP_SYNC_REGS); cap_async_pf = kvm_check_extension(s, KVM_CAP_ASYNC_PF); + + if (kvm_check_extension(s, KVM_CAP_VM_ATTRIBUTES)) { + kvm_s390_enable_cmma(s); + } + if (!kvm_check_extension(s, KVM_CAP_S390_GMAP) || !kvm_check_extension(s, KVM_CAP_S390_COW)) { phys_mem_set_alloc(legacy_s390_alloc); diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c index 9dae025..519edb8 100644 --- a/target-s390x/misc_helper.c +++ b/target-s390x/misc_helper.c @@ -136,6 +136,7 @@ static int modified_clear_reset(S390CPU *cpu) pause_all_vcpus(); cpu_synchronize_all_states(); cpu_full_reset_all(); + cmma_reset(cpu); io_subsystem_reset(); scc->load_normal(CPU(cpu)); cpu_synchronize_all_post_reset(); @@ -150,6 +151,7 @@ static int load_normal_reset(S390CPU *cpu) pause_all_vcpus(); cpu_synchronize_all_states(); cpu_reset_all(); + cmma_reset(cpu); io_subsystem_reset(); scc->initial_cpu_reset(CPU(cpu)); scc->load_normal(CPU(cpu)); diff --git a/trace-events b/trace-events index ffe6e62..e984e76 100644 --- a/trace-events +++ b/trace-events @@ -1258,3 +1258,7 @@ xen_pv_mmio_write(uint64_t addr) "WARNING: write to Xen PV Device MMIO space (ad # hw/pci/pci_host.c pci_cfg_read(const char *dev, unsigned devid, unsigned fnid, unsigned offs, unsigned val) "%s %02u:%u @0x%x -> 0x%x" pci_cfg_write(const char *dev, unsigned devid, unsigned fnid, unsigned offs, unsigned val) "%s %02u:%u @0x%x <- 0x%x" + +# target-s390x/kvm.c +kvm_enable_cmma(int rc) "CMMA: enabling with result code %d" +kvm_clear_cmma(int rc) "CMMA: clearing with result code %d" |