dm: add support of high MMIO mapping

1G PCI hole is added just after 4G address which is used as the
PCI high MMIO address space. Guest high memory is mapped from 5G
address for both EPT and device model user space address. Guest
e820 table and API vm_map_gpa are updated accordingly.

Tracked-On: #2577
Signed-off-by: Jian Jun Chen <jian.jun.chen@intel.com>
Reviewed-by: Jason Chen CJ <jason.cj.chen@intel.com>
Acked-by: Yu Wang <yu1.wang@intel.com>
This commit is contained in:
Jian Jun Chen 2019-02-25 16:28:14 +08:00 committed by wenlingz
parent 32925c10bd
commit 29b1ebcd43
9 changed files with 34 additions and 26 deletions

View File

@ -652,14 +652,7 @@ int hugetlb_setup_memory(struct vmctx *ctx)
ctx->highmem =
ALIGN_DOWN(ctx->highmem, hugetlb_priv[HUGETLB_LV1].pg_size);
/*
* High BIOS resides right below 4GB.
* Therefore, at least 4GB of memory space is needed.
*/
if (ctx->biosmem > 0 || ctx->highmem > 0)
total_size = 4 * GB + ctx->highmem;
else
total_size = ctx->lowmem;
total_size = ctx->highmem_gpa_base + ctx->highmem;
/* check & set hugetlb level memory size for lowmem/biosmem/highmem */
lowmem = ctx->lowmem;
@ -735,7 +728,8 @@ int hugetlb_setup_memory(struct vmctx *ctx)
}
/* mmap highmem */
if (mmap_hugetlbfs(ctx, 4 * GB, get_highmem_param, adj_highmem_param) < 0) {
if (mmap_hugetlbfs(ctx, ctx->highmem_gpa_base,
get_highmem_param, adj_highmem_param) < 0) {
perror("highmem mmap failed");
goto err;
}
@ -772,8 +766,9 @@ int hugetlb_setup_memory(struct vmctx *ctx)
/* map ept for highmem */
if (ctx->highmem > 0) {
if (vm_map_memseg_vma(ctx, ctx->highmem, 4 * GB,
(uint64_t)(ctx->baseaddr + 4 * GB), PROT_ALL) < 0)
if (vm_map_memseg_vma(ctx, ctx->highmem, ctx->highmem_gpa_base,
(uint64_t)(ctx->baseaddr + ctx->highmem_gpa_base),
PROT_ALL) < 0)
goto err;
}

View File

@ -522,7 +522,7 @@ static struct smbios_template_entry smbios_template[] = {
{ NULL, NULL, NULL }
};
static uint64_t guest_lomem, guest_himem;
static uint64_t guest_lomem, guest_himem, guest_highmem_base;
static uint16_t type16_handle;
static int
@ -709,7 +709,7 @@ smbios_type19_initializer(struct smbios_structure *template_entry,
curaddr, endaddr, n, size);
type19 = (struct smbios_table_type19 *)curaddr;
type19->arrayhand = type16_handle;
type19->xsaddr = 4*GB;
type19->xsaddr = guest_highmem_base;
type19->xeaddr = guest_himem;
}
@ -767,6 +767,7 @@ smbios_build(struct vmctx *ctx)
guest_lomem = vm_get_lowmem_size(ctx);
guest_himem = vm_get_highmem_size(ctx);
guest_highmem_base = ctx->highmem_gpa_base;
startaddr = paddr_guest2host(ctx, SMBIOS_BASE, SMBIOS_MAX_LENGTH);
if (startaddr == NULL) {

View File

@ -33,6 +33,7 @@
#include "vmmapi.h"
#include "sw_load.h"
#include "dm.h"
#include "pci_core.h"
int with_bootargs;
static char bootargs[STR_LEN];
@ -56,7 +57,8 @@ static char bootargs[STR_LEN];
* 3: lowmem - bff_fffff (reserved) 0xc00_00000-lowmem
* 4: 0xc00_00000 - dff_fffff PCI hole 512MB
* 5: 0xe00_00000 - fff_fffff (reserved) 512MB
* 6: 1_000_00000 - highmem RAM highmem-4G
* 6: 1_000_00000 - 1_400_00000 PCI hole 1G
* 7: 1_400_00000 - highmem RAM highmem-5G
*/
const struct e820_entry e820_default_entries[NUM_E820_ENTRIES] = {
{ /* 0 to mptable/smbios/acpi */
@ -89,8 +91,14 @@ const struct e820_entry e820_default_entries[NUM_E820_ENTRIES] = {
.type = E820_TYPE_RESERVED
},
{ /* 4G to 5G */
.baseaddr = PCI_EMUL_MEMBASE64,
.length = PCI_EMUL_MEMLIMIT64 - PCI_EMUL_MEMBASE64,
.type = E820_TYPE_RESERVED
},
{
.baseaddr = 0x100000000,
.baseaddr = PCI_EMUL_MEMLIMIT64,
.length = 0x000100000,
.type = E820_TYPE_RESERVED
},

View File

@ -45,6 +45,7 @@
#include "mevent.h"
#include "dm.h"
#include "pci_core.h"
#define MAP_NOCORE 0
#define MAP_ALIGNED_SUPER 0
@ -129,6 +130,7 @@ vm_create(const char *name, uint64_t req_buf)
ctx->fd = devfd;
ctx->lowmem_limit = 2 * GB;
ctx->highmem_gpa_base = PCI_EMUL_MEMLIMIT64;
ctx->name = (char *)(ctx + 1);
strncpy(ctx->name, name, strnlen(name, PATH_MAX) + 1);
@ -327,7 +329,8 @@ vm_unsetup_memory(struct vmctx *ctx)
*/
bzero((void *)ctx->baseaddr, ctx->lowmem);
if (ctx->highmem > 0) {
bzero((void *)(ctx->baseaddr + 4 * GB), ctx->highmem);
bzero((void *)(ctx->baseaddr + ctx->highmem_gpa_base),
ctx->highmem);
}
hugetlb_unsetup_memory(ctx);
@ -351,10 +354,10 @@ vm_map_gpa(struct vmctx *ctx, vm_paddr_t gaddr, size_t len)
}
if (ctx->highmem > 0) {
if (gaddr >= 4*GB) {
if (gaddr < 4*GB + ctx->highmem &&
if (gaddr >= ctx->highmem_gpa_base) {
if (gaddr < ctx->highmem_gpa_base + ctx->highmem &&
len <= ctx->highmem &&
gaddr + len <= 4*GB + ctx->highmem)
gaddr + len <= ctx->highmem_gpa_base + ctx->highmem)
return (ctx->baseaddr + gaddr);
}
}

View File

@ -97,9 +97,6 @@ SYSRES_MEM(PCI_EMUL_ECFG_BASE, PCI_EMUL_ECFG_SIZE);
#define PCI_EMUL_MEMLIMIT32 PCI_EMUL_ECFG_BASE
#define PCI_EMUL_MEMBASE64 0x100000000UL
#define PCI_EMUL_MEMLIMIT64 0x140000000UL
static struct pci_vdev_ops *pci_emul_finddev(char *name);
static void pci_lintr_route(struct pci_vdev *dev);
static void pci_lintr_update(struct pci_vdev *dev);

View File

@ -523,10 +523,10 @@ vhost_set_mem_table(struct vhost_dev *vdev)
}
if (ctx->highmem > 0) {
mem->regions[nregions].guest_phys_addr = 4*GB;
mem->regions[nregions].guest_phys_addr = ctx->highmem_gpa_base;
mem->regions[nregions].memory_size = ctx->highmem;
mem->regions[nregions].userspace_addr =
(uintptr_t)(ctx->baseaddr + 4*GB);
(uintptr_t)(ctx->baseaddr + ctx->highmem_gpa_base);
DPRINTF("[%d][0x%llx -> 0x%llx, 0x%llx]\n",
nregions,
mem->regions[nregions].guest_phys_addr,

View File

@ -38,6 +38,9 @@
#define PCI_BARMAX PCIR_MAX_BAR_0 /* BAR registers in a Type 0 header */
#define PCI_BDF(b, d, f) (((b & 0xFF) << 8) | ((d & 0x1F) << 3) | ((f & 0x7)))
#define PCI_EMUL_MEMBASE64 0x100000000UL
#define PCI_EMUL_MEMLIMIT64 0x140000000UL
struct vmctx;
struct pci_vdev;
struct memory_region;

View File

@ -38,9 +38,9 @@
#define E820_TYPE_ACPI_NVS 4 /* EFI 10 */
#define E820_TYPE_UNUSABLE 5 /* EFI 8 */
#define NUM_E820_ENTRIES 6
#define NUM_E820_ENTRIES 7
#define LOWRAM_E820_ENTRIES 2
#define HIGHRAM_E820_ENTRIES 5
#define HIGHRAM_E820_ENTRIES 6
/* Defines a single entry in an E820 memory map. */
struct e820_entry {

View File

@ -52,6 +52,7 @@ struct vmctx {
int vmid;
int ioreq_client;
uint32_t lowmem_limit;
uint64_t highmem_gpa_base;
size_t lowmem;
size_t biosmem;
size_t highmem;