qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Ani Sinha <anisinha@redhat.com>
To: "Michael S. Tsirkin" <mst@redhat.com>,
	"Marcel Apfelbaum" <marcel.apfelbaum@gmail.com>,
	"Paolo Bonzini" <pbonzini@redhat.com>,
	"Richard Henderson" <richard.henderson@linaro.org>,
	"Eduardo Habkost" <eduardo@habkost.net>,
	"David Hildenbrand" <david@redhat.com>,
	"Igor Mammedov" <imammedo@redhat.com>,
	"Xiao Guangrong" <xiaoguangrong.eric@gmail.com>,
	"Philippe Mathieu-Daudé" <philmd@linaro.org>,
	"Yanan Wang" <wangyanan55@huawei.com>
Cc: Ani Sinha <anisinha@redhat.com>, qemu-devel@nongnu.org
Subject: [PATCH] mem/x86: add processor address space check for VM memory
Date: Fri,  8 Sep 2023 15:20:24 +0530	[thread overview]
Message-ID: <20230908095024.270946-1-anisinha@redhat.com> (raw)

Depending on the number of available address bits of the current processor, a
VM can only use a certain maximum amount of memory and no more. This change
makes sure that a VM is not configured to have more memory than what it can use
with the current processor settings when started. Additionally, the change adds
checks during memory hotplug to ensure that the VM does not end up getting more
memory than what it can actually use after hotplug.
Currently, both the above checks are only for pc (x86) platform.

Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1235403
CC: imammedo@redhat.com
Signed-off-by: Ani Sinha <anisinha@redhat.com>
---
 hw/i386/pc.c           | 45 ++++++++++++++++++++++++++++++++++++++++++
 hw/mem/memory-device.c |  6 ++++++
 include/hw/boards.h    |  9 +++++++++
 3 files changed, 60 insertions(+)

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 54838c0c41..f84e4c4916 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -31,6 +31,7 @@
 #include "hw/i386/topology.h"
 #include "hw/i386/fw_cfg.h"
 #include "hw/i386/vmport.h"
+#include "hw/mem/memory-device.h"
 #include "sysemu/cpus.h"
 #include "hw/block/fdc.h"
 #include "hw/ide/internal.h"
@@ -1006,6 +1007,17 @@ void pc_memory_init(PCMachineState *pcms,
         exit(EXIT_FAILURE);
     }
 
+    /*
+     * check if the VM started with more ram configured than max physical
+     * address available with the current processor.
+     */
+    if (machine->ram_size > maxphysaddr + 1) {
+        error_report("Address space limit 0x%"PRIx64" < 0x%"PRIx64
+                     " (max configured memory), phys-bits too low (%u)",
+                     maxphysaddr, machine->ram_size, cpu->phys_bits);
+        exit(EXIT_FAILURE);
+    }
+
     /*
      * Split single memory region and use aliases to address portions of it,
      * done for backwards compatibility with older qemus.
@@ -1845,6 +1857,38 @@ static bool pc_hotplug_allowed(MachineState *ms, DeviceState *dev, Error **errp)
     return true;
 }
 
+static bool pc_mem_hotplug_allowed(MachineState *ms,
+                                   MemoryRegion *mr, Error **errp)
+{
+    hwaddr maxphysaddr;
+    uint64_t dimm_size, size, ram_size, total_mem_size;
+    X86CPU *cpu = X86_CPU(first_cpu);
+
+    if (!mr) {
+        return true;
+    }
+
+    dimm_size = ms->device_memory->dimm_size;
+    size = memory_region_size(mr);
+    ram_size = (uint64_t) ms->ram_size;
+    total_mem_size = ram_size + dimm_size + size;
+
+    maxphysaddr = ((hwaddr)1 << cpu->phys_bits) - 1;
+
+    /*
+     * total memory after hotplug will exceed the maximum physical
+     * address limit of the processor. So hotplug cannot be allowed.
+     */
+    if ((total_mem_size > (uint64_t)maxphysaddr + 1) &&
+        (total_mem_size > ram_size + dimm_size)) {
+        error_setg(errp, "Address space limit 0x%"PRIx64" < 0x%"PRIx64
+                   " phys-bits too low (%u)",
+                   maxphysaddr, total_mem_size, cpu->phys_bits);
+        return false;
+    }
+    return true;
+}
+
 static void pc_machine_class_init(ObjectClass *oc, void *data)
 {
     MachineClass *mc = MACHINE_CLASS(oc);
@@ -1870,6 +1914,7 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
     assert(!mc->get_hotplug_handler);
     mc->get_hotplug_handler = pc_get_hotplug_handler;
     mc->hotplug_allowed = pc_hotplug_allowed;
+    mc->mem_hotplug_allowed = pc_mem_hotplug_allowed;
     mc->cpu_index_to_instance_props = x86_cpu_index_to_props;
     mc->get_default_cpu_node_id = x86_get_default_cpu_node_id;
     mc->possible_cpu_arch_ids = x86_possible_cpu_arch_ids;
diff --git a/hw/mem/memory-device.c b/hw/mem/memory-device.c
index 667d56bd29..825bc593ae 100644
--- a/hw/mem/memory-device.c
+++ b/hw/mem/memory-device.c
@@ -57,6 +57,7 @@ static void memory_device_check_addable(MachineState *ms, MemoryRegion *mr,
 {
     const uint64_t used_region_size = ms->device_memory->used_region_size;
     const uint64_t size = memory_region_size(mr);
+    MachineClass *mc = MACHINE_GET_CLASS(ms);
 
     /* we will need a new memory slot for kvm and vhost */
     if (kvm_enabled() && !kvm_has_free_slot(ms)) {
@@ -68,6 +69,11 @@ static void memory_device_check_addable(MachineState *ms, MemoryRegion *mr,
         return;
     }
 
+    if (mc->mem_hotplug_allowed &&
+        (!(mc->mem_hotplug_allowed(ms, mr, errp)))) {
+        return;
+    }
+
     /* will we exceed the total amount of memory specified */
     if (used_region_size + size < used_region_size ||
         used_region_size + size > ms->maxram_size - ms->ram_size) {
diff --git a/include/hw/boards.h b/include/hw/boards.h
index 3b541ffd24..84b199ee51 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -210,6 +210,13 @@ typedef struct {
  *    false is returned, an error must be set to show the reason of
  *    the rejection.  If the hook is not provided, all hotplug will be
  *    allowed.
+ * @mem_hotplug_allowed:
+ *    If the hook is provided, then it'll be called for each memory device
+ *    hotplug to check whether the mem device hotplug is allowed.  Return
+ *    true to grant allowance or false to reject the hotplug.  When
+ *    false is returned, an error must be set to show the reason of
+ *    the rejection.  If the hook is not provided, all mem hotplug will be
+ *    allowed.
  * @default_ram_id:
  *    Specifies inital RAM MemoryRegion name to be used for default backend
  *    creation if user explicitly hasn't specified backend with "memory-backend"
@@ -285,6 +292,8 @@ struct MachineClass {
                                            DeviceState *dev);
     bool (*hotplug_allowed)(MachineState *state, DeviceState *dev,
                             Error **errp);
+    bool (*mem_hotplug_allowed)(MachineState *state, MemoryRegion *mr,
+                                Error **errp);
     CpuInstanceProperties (*cpu_index_to_instance_props)(MachineState *machine,
                                                          unsigned cpu_index);
     const CPUArchIdList *(*possible_cpu_arch_ids)(MachineState *machine);
-- 
2.39.1



             reply	other threads:[~2023-09-08  9:53 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-09-08  9:50 Ani Sinha [this message]
2023-09-08 10:28 ` [PATCH] mem/x86: add processor address space check for VM memory David Hildenbrand
2023-09-08 14:12   ` Ani Sinha
2023-09-08 14:16     ` David Hildenbrand
2023-09-08 15:13       ` Ani Sinha
2023-09-08 16:02         ` David Hildenbrand
2023-09-08 16:04           ` David Hildenbrand
2023-09-12 10:41           ` Ani Sinha
2023-09-12 15:34             ` David Hildenbrand
2023-09-14  5:53               ` Ani Sinha
2023-09-14  8:37                 ` David Hildenbrand
2023-09-14 11:21                   ` Ani Sinha
2023-09-14 11:49                     ` David Hildenbrand
2023-09-15 10:38                       ` Ani Sinha
2023-09-18  9:33                         ` David Hildenbrand
2023-09-18 10:07                           ` Ani Sinha
2023-09-18 10:09                             ` David Hildenbrand
2023-09-18 10:11                               ` Ani Sinha
2023-09-18 10:14                                 ` Ani Sinha
2023-09-18 10:19                                 ` David Hildenbrand
2023-09-18 10:54                                   ` Ani Sinha
2023-09-18 10:58                                     ` David Hildenbrand
2023-09-18 11:00                                       ` Ani Sinha
2023-09-18 11:02                                         ` Ani Sinha
2023-09-18 11:02                                         ` David Hildenbrand
2023-09-18 11:04                                           ` Ani Sinha
2023-09-14 17:11                   ` Ani Sinha
2023-09-16  5:17                   ` Ani Sinha
2023-09-08 16:04         ` Philippe Mathieu-Daudé

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230908095024.270946-1-anisinha@redhat.com \
    --to=anisinha@redhat.com \
    --cc=david@redhat.com \
    --cc=eduardo@habkost.net \
    --cc=imammedo@redhat.com \
    --cc=marcel.apfelbaum@gmail.com \
    --cc=mst@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=philmd@linaro.org \
    --cc=qemu-devel@nongnu.org \
    --cc=richard.henderson@linaro.org \
    --cc=wangyanan55@huawei.com \
    --cc=xiaoguangrong.eric@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).