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>
This commit is contained in:
parent
08da527fd0
commit
4cb88c3c37
@ -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()) {
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user