aboutsummaryrefslogtreecommitdiff
path: root/target-s390x
diff options
context:
space:
mode:
Diffstat (limited to 'target-s390x')
-rw-r--r--target-s390x/cpu.h14
-rw-r--r--target-s390x/kvm.c45
2 files changed, 59 insertions, 0 deletions
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 56c02931ad..143b631369 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -1029,6 +1029,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,
@@ -1066,8 +1067,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 6c4360be65..a585fe3e1c 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 = {