/* * Allocate guest system memory. This memory is backed by swap and returns * zero-filled pages on-demand. The memory object is identified by 'ident'. * * System memory cannot be unmapped from the guest's address space once * it is mapped. */ int vm_alloc_sysmem(struct vmctx *ctx, int ident, size_t size); /* * Allocate guest device memory. This memory is backed by swap and returns * zero-filled pages on-demand. The memory is identified by 'ident'. * * If 'devname' is not NULL then a device called /dev/vmm//devname * will be created. This device node supports mmap(2). * * Device memory may be unmapped at any time from the guest address space. */ int vm_alloc_devmem(struct vmctx *ctx, int ident, size_t size, const char *devname); /* * Map the memory object called 'ident' into the guest address space at * [gpa, gpa + len). The mapping begins at 'offset' in the underlying * memory object. */ int vm_map_gpa(struct vmctx *ctx, int ident, uint64_t gpa, size_t mapsize, size_t offset, int flags); /* * Unmap the mapping in the guest address space that starts at 'gpa'. * * Mappings backed by system memory object cannot be unmapped. */ int vm_unmap_gpa(struct vmctx *ctx, uint64_t gpa); /* 'flags' parameter of 'vm_map_gpa()' */ #define GPA_PROT_READ 0x01 #define GPA_PROT_WRITE 0x02 #define GPA_PROT_EXEC 0x04 #define GPA_MMIO 0x08 #define GPA_WIRED 0x10 #define GPA_PROT_ALL (GPA_PROT_READ | GPA_PROT_WRITE | GPA_PROT_EXEC) #define GPA_PROT_RW (GPA_PROT_READ | GPA_PROT_WRITE) /* * Identifiers for guest memory objects. These identifiers are opaque to * vmm.ko and solely used to identify the memory object in vm_map_gpa(). */ enum { LOWMEM, HIGHMEM, BOOTROM, VIDEOMEM, }; /* * guest system memory: * 0 - 640KB * 1MB - lomem_limit * 4GB - himem_limit * All memory segments are visible to pci passthru devices. */ vm_alloc_sysmem(ctx, LOWMEM, lomemsz); vm_map_gpa(ctx, LOWMEM, 0, 640KB, 0, GPA_PROT_ALL | GPA_PPT_VISIBLE); vm_map_gpa(ctx, LOWMEM, 1MB, lomemsz - 1MB, 1MB, GPA_PROT_ALL|GPA_PPT_VISIBLE); vm_alloc_sysmem(ctx, HIGHMEM, himemsz); vm_map_gpa(ctx, HIGHMEM, 4GB, himemsz, 0, GPA_PROT_ALL | GPA_PPT_VISIBLE); /* * guest firmware: * - map the entire firmware image below 4GB * - map the top 128KB of the firmware image below 1MB */ rom_prot = GPA_PROT_READ | GPA_PROT_EXEC; vm_alloc_sysmem(ctx, BOOTROM, romsize); vm_map_gpa(ctx, BOOTROM, 4GB - romsize, romsize, 0, rom_prot); vm_map_gpa(ctx, BOOTROM, 1MB - 128KB, 128KB, romsize - 128KB, rom_prot); /* * guest vga memory: * - map the entire video memory at 'vgabar' * - map the first 128KB in the legacy VGA mapping * Wire the video memory buffer to avoid nested page faults when the screen * is being updated. */ vm_alloc_devmem(ctx, VIDEOMEM, vidmemsz, "framebuffer"); vm_map_gpa(ctx, VIDEOMEM, 0xA0000, 128KB, 0, GPA_PROT_RW | GPA_WIRED); vm_map_gpa(ctx, VIDEOMEM, vgabar, vidmemsz, 0, GPA_PROT_RW | GPA_WIRED); vm_unmap_gpa(ctx, VIDEOMEM, vgabar); vm_map_gpa(ctx, VIDEOMEM, vgabar2, vidmemsz, 0, GPA_PROT_RW | GPA_WIRED); /dev/vmm/vmname: mmap of this device only maps guest regions that correspond to system memory (e.g., LOMEM, HIGHMEM, BOOTROM). Specifically it will not map regions of guest address space that are backed by VIDEOMEM or other device memory. This should not be surprising given that other emulated BARs and MMIO devices in the PCI hole are also ignored by the mmap, for e.g., LAPIC, HPET. /dev/vmm/vmname/framebuffer: Opened by the device emulation in bhyve(8) to convert the framebuffer contents into a VNC-compatible bitmap. TODO: vm_cleanup(bool destroy) { /* Remove all mappings from the guest's vmspace */ foreach gpa vm_map_remove(vmspace, gpa, gpa + len); /* Remove all objects associated with the guest vmspace */ if (destroy) { foreach memobj vm_object_deallocate(memobj); } } VGA device emulation needs a callback when the framebuffer address is modified by the guest. In response to this it will do a vm_unmap_gpa() or vm_map_gpa(). A new callback type needs to be added to 'struct pci_devemu' and it needs to be triggered from 'modify_bar_registration()' in pci_emul.c. Get rid of 'struct vm_memory_segment' or at least limit it to ppt.c. Deprecate IOCNUM_MAP_MEMORY and IOCNUM_GET_MEMORY_SEG.