@@ -61,8 +61,6 @@ static void e820_setup(struct kvm *kvm)
size = guest_flat_to_host(kvm, E820_MAP_SIZE);
mem_map = guest_flat_to_host(kvm, E820_MAP_START);
- *size = E820_MEM_AREAS;
-
mem_map[i++] = (struct e820_entry) {
.addr = REAL_MODE_IVT_BEGIN,
.size = EBDA_START - REAL_MODE_IVT_BEGIN,
@@ -78,13 +76,28 @@ static void e820_setup(struct kvm *kvm)
.size = MB_BIOS_END - MB_BIOS_BEGIN,
.type = E820_MEM_RESERVED,
};
- mem_map[i++] = (struct e820_entry) {
- .addr = BZ_KERNEL_START,
- .size = kvm->ram_size - BZ_KERNEL_START,
- .type = E820_MEM_USABLE,
- };
+ if (kvm->ram_size < KVM_32BIT_GAP_START) {
+ mem_map[i++] = (struct e820_entry) {
+ .addr = BZ_KERNEL_START,
+ .size = kvm->ram_size - BZ_KERNEL_START,
+ .type = E820_MEM_USABLE,
+ };
+ } else {
+ mem_map[i++] = (struct e820_entry) {
+ .addr = BZ_KERNEL_START,
+ .size = KVM_32BIT_GAP_START - BZ_KERNEL_START,
+ .type = E820_MEM_USABLE,
+ };
+ mem_map[i++] = (struct e820_entry) {
+ .addr = 0x100000000ULL,
+ .size = kvm->ram_size - KVM_32BIT_GAP_START,
+ .type = E820_MEM_USABLE,
+ };
+ }
BUILD_BUG_ON(i > E820_MEM_AREAS);
+
+ *size = i;
}
/**
@@ -8,7 +8,7 @@
#define E820_MEM_USABLE 1
#define E820_MEM_RESERVED 2
-#define E820_MEM_AREAS 4
+#define E820_MEM_AREAS 5
struct e820_entry {
u64 addr; /* start of memory segment */
@@ -8,6 +8,8 @@
#include <time.h>
#define KVM_NR_CPUS (255)
+#define KVM_32BIT_GAP_SIZE (512 << 20)
+#define KVM_32BIT_GAP_START (((u64)1 << 32) - KVM_32BIT_GAP_SIZE)
struct kvm {
int sys_fd; /* For system ioctls(), i.e. /dev/kvm */
@@ -153,23 +153,33 @@ static bool kvm__cpu_supports_vm(void)
return regs.ecx & (1 << feature);
}
-void kvm__init_ram(struct kvm *self)
+static void kvm_register_mem_slot(struct kvm *kvm, u32 slot, u64 guest_phys, u64 size, u64 userspace_addr)
{
struct kvm_userspace_memory_region mem;
int ret;
mem = (struct kvm_userspace_memory_region) {
- .slot = 0,
- .guest_phys_addr = 0x0UL,
- .memory_size = self->ram_size,
- .userspace_addr = (unsigned long) self->ram_start,
+ .slot = slot,
+ .guest_phys_addr = guest_phys,
+ .memory_size = size,
+ .userspace_addr = userspace_addr,
};
- ret = ioctl(self->vm_fd, KVM_SET_USER_MEMORY_REGION, &mem);
+ ret = ioctl(kvm->vm_fd, KVM_SET_USER_MEMORY_REGION, &mem);
if (ret < 0)
die_perror("KVM_SET_USER_MEMORY_REGION ioctl");
}
+void kvm__init_ram(struct kvm *self)
+{
+ if (self->ram_size < KVM_32BIT_GAP_START) {
+ kvm_register_mem_slot(self, 0, 0, self->ram_size, (u64)self->ram_start);
+ } else {
+ kvm_register_mem_slot(self, 0, 0, KVM_32BIT_GAP_START, (u64)self->ram_start);
+ kvm_register_mem_slot(self, 1, 0x100000000ULL, self->ram_size - KVM_32BIT_GAP_START, (u64)self->ram_start + 0x100000000ULL);
+ }
+}
+
int kvm__max_cpus(struct kvm *self)
{
int ret;
@@ -225,7 +235,13 @@ struct kvm *kvm__init(const char *kvm_dev, unsigned long ram_size)
self->ram_size = ram_size;
- self->ram_start = mmap(NULL, ram_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0);
+ if (self->ram_size < KVM_32BIT_GAP_START) {
+ self->ram_start = mmap(NULL, ram_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0);
+ } else {
+ self->ram_start = mmap(NULL, ram_size + KVM_32BIT_GAP_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0);
+ if (self->ram_start != MAP_FAILED)
+ mprotect(self->ram_start + KVM_32BIT_GAP_START, KVM_32BIT_GAP_SIZE, PROT_NONE);
+ }
if (self->ram_start == MAP_FAILED)
die("out of memory");
e820 is expected to leave a memory gap within the low 32 bits of RAM space. From the documentation of e820_setup_gap(): /* * Search for the biggest gap in the low 32 bits of the e820 * memory space. We pass this space to PCI to assign MMIO resources * for hotplug or unconfigured devices in. * Hopefully the BIOS let enough space left. */ Not leaving such gap causes errors and hangs during the boot process. This patch adds a memory gap between 0xe0000000 and 0x100000000 when using more than 0xe0000000 bytes for guest RAM. This patch updates the e820 table, slot allocations used for KVM_SET_USER_MEMORY_REGION. Changes in V2: - Allocate RAM with the gap to avoid altering the translation code. - New patch description. Signed-off-by: Sasha Levin <levinsasha928@gmail.com> --- tools/kvm/bios.c | 27 ++++++++++++++++++++------- tools/kvm/include/kvm/e820.h | 2 +- tools/kvm/include/kvm/kvm.h | 2 ++ tools/kvm/kvm.c | 30 +++++++++++++++++++++++------- 4 files changed, 46 insertions(+), 15 deletions(-)