Message ID | 1425570981-40609-3-git-send-email-jfrei@linux.vnet.ibm.com |
---|---|
State | New |
Headers | show |
Am 05.03.2015 um 16:56 schrieb Jens Freimann: > From: Dominik Dingel <dingel@linux.vnet.ibm.com> > > With "KVM: s390: Allow userspace to limit guest memory size" KVM is able to > do some optimizations based on the guest memory limit. > > The guest memory limit is computed by the initial definition and with the notion of > hotplugged memory. > > Reviewed-by: Thomas Huth <thuth@linux.vnet.ibm.com> > Reviewed-by: Guenther Hutzl <hutzl@linux.vnet.ibm.com> > Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com> > Signed-off-by: Dominik Dingel <dingel@linux.vnet.ibm.com> > Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com> Applied to s390-next. (Still waiting for Peter to pull the header update from Michael) > --- > hw/s390x/s390-virtio-ccw.c | 10 ++++++++++ > target-s390x/cpu.h | 14 ++++++++++++++ > target-s390x/kvm.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 69 insertions(+) > > diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c > index 078371a..eea0742 100644 > --- a/hw/s390x/s390-virtio-ccw.c > +++ b/hw/s390x/s390-virtio-ccw.c > @@ -97,6 +97,7 @@ static void ccw_init(MachineState *machine) > ram_addr_t pad_size = 0; > ram_addr_t maxmem = qemu_opt_get_size(opts, "maxmem", my_ram_size); > ram_addr_t standby_mem_size = maxmem - my_ram_size; > + uint64_t kvm_limit; > > /* The storage increment size is a multiple of 1M and is a power of 2. > * The number of storage increments must be MAX_STORAGE_INCREMENTS or fewer. > @@ -121,6 +122,15 @@ static void ccw_init(MachineState *machine) > > /* let's propagate the changed ram size into the global variable. */ > ram_size = my_ram_size; > + machine->maxram_size = my_ram_size + standby_mem_size; > + > + ret = s390_set_memory_limit(machine->maxram_size, &kvm_limit); > + if (ret == -E2BIG) { > + hw_error("qemu: host supports a maximum of %" PRIu64 " GB", > + kvm_limit >> 30); > + } else if (ret) { > + hw_error("qemu: setting the guest size failed"); > + } > > /* get a BUS */ > css_bus = virtual_css_bus_init(); > diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h > index be53b5a..f89e1e3 100644 > --- a/target-s390x/cpu.h > +++ b/target-s390x/cpu.h > @@ -1062,6 +1062,7 @@ int kvm_s390_get_memslot_count(KVMState *s); > void kvm_s390_clear_cmma_callback(void *opaque); > int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state); > void kvm_s390_reset_vcpu(S390CPU *cpu); > +int kvm_s390_set_mem_limit(KVMState *s, uint64_t new_limit, uint64_t *hw_limit); > #else > static inline void kvm_s390_io_interrupt(uint16_t subchannel_id, > uint16_t subchannel_nr, > @@ -1099,8 +1100,21 @@ static inline int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state) > static inline void kvm_s390_reset_vcpu(S390CPU *cpu) > { > } > +static inline int kvm_s390_set_mem_limit(KVMState *s, uint64_t new_limit, > + uint64_t *hw_limit) > +{ > + return 0; > +} > #endif > > +static inline int s390_set_memory_limit(uint64_t new_limit, uint64_t *hw_limit) > +{ > + if (kvm_enabled()) { > + return kvm_s390_set_mem_limit(kvm_state, new_limit, hw_limit); > + } > + return 0; > +} > + > static inline void cmma_reset(S390CPU *cpu) > { > if (kvm_enabled()) { > diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c > index 6ef714c..f4bcca1 100644 > --- a/target-s390x/kvm.c > +++ b/target-s390x/kvm.c > @@ -122,6 +122,51 @@ static int cap_async_pf; > > static void *legacy_s390_alloc(size_t size, uint64_t *align); > > +static int kvm_s390_supports_mem_limit(KVMState *s) > +{ > + struct kvm_device_attr attr = { > + .group = KVM_S390_VM_MEM_CTRL, > + .attr = KVM_S390_VM_MEM_LIMIT_SIZE, > + }; > + > + return (kvm_vm_ioctl(s, KVM_HAS_DEVICE_ATTR, &attr) == 0); > +} > + > +static int kvm_s390_query_mem_limit(KVMState *s, uint64_t *memory_limit) > +{ > + struct kvm_device_attr attr = { > + .group = KVM_S390_VM_MEM_CTRL, > + .attr = KVM_S390_VM_MEM_LIMIT_SIZE, > + .addr = (uint64_t) memory_limit, > + }; > + > + return kvm_vm_ioctl(s, KVM_GET_DEVICE_ATTR, &attr); > +} > + > +int kvm_s390_set_mem_limit(KVMState *s, uint64_t new_limit, uint64_t *hw_limit) > +{ > + int rc; > + > + struct kvm_device_attr attr = { > + .group = KVM_S390_VM_MEM_CTRL, > + .attr = KVM_S390_VM_MEM_LIMIT_SIZE, > + .addr = (uint64_t) &new_limit, > + }; > + > + if (!kvm_s390_supports_mem_limit(s)) { > + return 0; > + } > + > + rc = kvm_s390_query_mem_limit(s, hw_limit); > + if (rc) { > + return rc; > + } else if (*hw_limit < new_limit) { > + return -E2BIG; > + } > + > + return kvm_vm_ioctl(s, KVM_SET_DEVICE_ATTR, &attr); > +} > + > static int kvm_s390_check_clear_cmma(KVMState *s) > { > struct kvm_device_attr attr = { >
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index 078371a..eea0742 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -97,6 +97,7 @@ static void ccw_init(MachineState *machine) ram_addr_t pad_size = 0; ram_addr_t maxmem = qemu_opt_get_size(opts, "maxmem", my_ram_size); ram_addr_t standby_mem_size = maxmem - my_ram_size; + uint64_t kvm_limit; /* The storage increment size is a multiple of 1M and is a power of 2. * The number of storage increments must be MAX_STORAGE_INCREMENTS or fewer. @@ -121,6 +122,15 @@ static void ccw_init(MachineState *machine) /* let's propagate the changed ram size into the global variable. */ ram_size = my_ram_size; + machine->maxram_size = my_ram_size + standby_mem_size; + + ret = s390_set_memory_limit(machine->maxram_size, &kvm_limit); + if (ret == -E2BIG) { + hw_error("qemu: host supports a maximum of %" PRIu64 " GB", + kvm_limit >> 30); + } else if (ret) { + hw_error("qemu: setting the guest size failed"); + } /* get a BUS */ css_bus = virtual_css_bus_init(); diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index be53b5a..f89e1e3 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -1062,6 +1062,7 @@ int kvm_s390_get_memslot_count(KVMState *s); void kvm_s390_clear_cmma_callback(void *opaque); int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state); void kvm_s390_reset_vcpu(S390CPU *cpu); +int kvm_s390_set_mem_limit(KVMState *s, uint64_t new_limit, uint64_t *hw_limit); #else static inline void kvm_s390_io_interrupt(uint16_t subchannel_id, uint16_t subchannel_nr, @@ -1099,8 +1100,21 @@ static inline int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state) static inline void kvm_s390_reset_vcpu(S390CPU *cpu) { } +static inline int kvm_s390_set_mem_limit(KVMState *s, uint64_t new_limit, + uint64_t *hw_limit) +{ + return 0; +} #endif +static inline int s390_set_memory_limit(uint64_t new_limit, uint64_t *hw_limit) +{ + if (kvm_enabled()) { + return kvm_s390_set_mem_limit(kvm_state, new_limit, hw_limit); + } + return 0; +} + static inline void cmma_reset(S390CPU *cpu) { if (kvm_enabled()) { diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index 6ef714c..f4bcca1 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -122,6 +122,51 @@ static int cap_async_pf; static void *legacy_s390_alloc(size_t size, uint64_t *align); +static int kvm_s390_supports_mem_limit(KVMState *s) +{ + struct kvm_device_attr attr = { + .group = KVM_S390_VM_MEM_CTRL, + .attr = KVM_S390_VM_MEM_LIMIT_SIZE, + }; + + return (kvm_vm_ioctl(s, KVM_HAS_DEVICE_ATTR, &attr) == 0); +} + +static int kvm_s390_query_mem_limit(KVMState *s, uint64_t *memory_limit) +{ + struct kvm_device_attr attr = { + .group = KVM_S390_VM_MEM_CTRL, + .attr = KVM_S390_VM_MEM_LIMIT_SIZE, + .addr = (uint64_t) memory_limit, + }; + + return kvm_vm_ioctl(s, KVM_GET_DEVICE_ATTR, &attr); +} + +int kvm_s390_set_mem_limit(KVMState *s, uint64_t new_limit, uint64_t *hw_limit) +{ + int rc; + + struct kvm_device_attr attr = { + .group = KVM_S390_VM_MEM_CTRL, + .attr = KVM_S390_VM_MEM_LIMIT_SIZE, + .addr = (uint64_t) &new_limit, + }; + + if (!kvm_s390_supports_mem_limit(s)) { + return 0; + } + + rc = kvm_s390_query_mem_limit(s, hw_limit); + if (rc) { + return rc; + } else if (*hw_limit < new_limit) { + return -E2BIG; + } + + return kvm_vm_ioctl(s, KVM_SET_DEVICE_ATTR, &attr); +} + static int kvm_s390_check_clear_cmma(KVMState *s) { struct kvm_device_attr attr = {