diff --git a/sys/amd64/include/vmm.h b/sys/amd64/include/vmm.h --- a/sys/amd64/include/vmm.h +++ b/sys/amd64/include/vmm.h @@ -243,7 +243,8 @@ int vm_mmap_memseg(struct vm *vm, vm_paddr_t gpa, int segid, vm_ooffset_t off, size_t len, int prot, int flags); int vm_munmap_memseg(struct vm *vm, vm_paddr_t gpa, size_t len); -int vm_alloc_memseg(struct vm *vm, int ident, size_t len, bool sysmem); +int vm_alloc_memseg(struct vm *vm, int ident, size_t len, int host_domain, + bool sysmem); void vm_free_memseg(struct vm *vm, int ident); int vm_map_mmio(struct vm *vm, vm_paddr_t gpa, size_t len, vm_paddr_t hpa); int vm_unmap_mmio(struct vm *vm, vm_paddr_t gpa, size_t len); diff --git a/sys/amd64/include/vmm_dev.h b/sys/amd64/include/vmm_dev.h --- a/sys/amd64/include/vmm_dev.h +++ b/sys/amd64/include/vmm_dev.h @@ -51,11 +51,30 @@ vm_paddr_t gpa; size_t len; }; - +/* Maximum number of NUMA domains in a guest. */ +#define VM_MAXMEMDOM 8 +#define VM_MAXSYSMEM VM_MAXMEMDOM + +/* + * Identifiers for memory segments. + * Each guest NUMA domain is represented by a single system + * memory segment from [VM_SYSMEM, VM_MAXSYSMEM). + * The remaining identifiers can be used to create devmem segments. + */ +enum { + VM_SYSMEM, + VM_BOOTROM = VM_MAXSYSMEM, + VM_FRAMEBUFFER, + VM_PCIROM, + VM_MEMSEG_END +}; +/* Passing this value to vm_alloc_memseg ... */ +#define VM_MEMSEG_ANYDOMAIN (-1) #define VM_MEMSEG_NAME(m) ((m)->name[0] != '\0' ? (m)->name : NULL) struct vm_memseg { int segid; size_t len; + int host_domain; char name[VM_MAX_SUFFIXLEN + 1]; }; diff --git a/sys/amd64/vmm/vmm.c b/sys/amd64/vmm/vmm.c --- a/sys/amd64/vmm/vmm.c +++ b/sys/amd64/vmm/vmm.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -135,7 +136,7 @@ bool sysmem; struct vm_object *object; }; -#define VM_MAX_MEMSEGS 4 +#define VM_MAX_MEMSEGS VM_MEMSEG_END struct mem_map { vm_paddr_t gpa; @@ -145,7 +146,7 @@ int prot; int flags; }; -#define VM_MAX_MEMMAPS 8 +#define VM_MAX_MEMMAPS (VM_MAX_MEMSEGS * 2) /* * Initialization: @@ -806,7 +807,8 @@ } int -vm_alloc_memseg(struct vm *vm, int ident, size_t len, bool sysmem) +vm_alloc_memseg(struct vm *vm, int ident, size_t len, int host_domain, + bool sysmem) { struct mem_seg *seg; vm_object_t obj; @@ -818,6 +820,9 @@ if (len == 0 || (len & PAGE_MASK)) return (EINVAL); + if (host_domain != VM_MEMSEG_ANYDOMAIN && + (host_domain < 0 || host_domain >= vm_ndomains)) + return (EINVAL); seg = &vm->mem_segs[ident]; if (seg->object != NULL) { @@ -833,6 +838,10 @@ seg->len = len; seg->object = obj; + if (host_domain == VM_MEMSEG_ANYDOMAIN) + seg->object->domain.dr_policy = DOMAINSET_IL(); + else + seg->object->domain.dr_policy = DOMAINSET_PREF(host_domain); seg->sysmem = sysmem; return (0); } diff --git a/sys/amd64/vmm/vmm_dev.c b/sys/amd64/vmm/vmm_dev.c --- a/sys/amd64/vmm/vmm_dev.c +++ b/sys/amd64/vmm/vmm_dev.c @@ -356,7 +356,8 @@ goto done; } - error = vm_alloc_memseg(sc->vm, mseg->segid, mseg->len, sysmem); + error = vm_alloc_memseg(sc->vm, mseg->segid, mseg->len, + mseg->host_domain, sysmem); if (error) goto done;