summaryrefslogtreecommitdiff
path: root/usr.sbin/vmd/vmm.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/vmd/vmm.c')
-rw-r--r--usr.sbin/vmd/vmm.c97
1 files changed, 80 insertions, 17 deletions
diff --git a/usr.sbin/vmd/vmm.c b/usr.sbin/vmd/vmm.c
index 1d0ef1613ee..3f1a3653e09 100644
--- a/usr.sbin/vmd/vmm.c
+++ b/usr.sbin/vmd/vmm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vmm.c,v 1.22 2016/03/13 02:37:29 mlarkin Exp $ */
+/* $OpenBSD: vmm.c,v 1.23 2016/03/13 13:11:47 stefan Exp $ */
/*
* Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org>
@@ -63,7 +63,6 @@
/*
* Emulated 8250 UART
- *
*/
#define COM1_DATA 0x3f8
#define COM1_IER 0x3f9
@@ -121,6 +120,7 @@ int run_vm(int *, int *, struct vm_create_params *, struct vcpu_init_state *);
void *vcpu_run_loop(void *);
int vcpu_exit(struct vm_run_params *);
int vcpu_reset(uint32_t, uint32_t, struct vcpu_init_state *);
+void create_memory_map(struct vm_create_params *);
int vmm_create_vm(struct vm_create_params *);
void init_emulated_hw(struct vm_create_params *, int *, int *);
void vcpu_exit_inout(struct vm_run_params *);
@@ -139,7 +139,8 @@ void vcpu_process_com_scr(union vm_exit *);
int vmm_dispatch_parent(int, struct privsep_proc *, struct imsg *);
void vmm_run(struct privsep *, struct privsep_proc *, void *);
-int con_fd, vm_id;
+int con_fd;
+struct vmd_vm *current_vm;
extern struct vmd *env;
@@ -470,7 +471,9 @@ start_vm(struct imsg *imsg, uint32_t *id)
setproctitle(vcp->vcp_name);
log_procinit(vcp->vcp_name);
+ create_memory_map(vcp);
ret = vmm_create_vm(vcp);
+ current_vm = vm;
/* send back the kernel-generated vm id (0 on error) */
close(fds[0]);
@@ -501,8 +504,7 @@ start_vm(struct imsg *imsg, uint32_t *id)
memcpy(&vis, &vcpu_init_flat32, sizeof(struct vcpu_init_state));
/* Load kernel image */
- ret = loadelf_main(vm->vm_kernel, vcp->vcp_id,
- vcp->vcp_memory_size, &vis);
+ ret = loadelf_main(vm->vm_kernel, vcp, &vis);
if (ret) {
errno = ret;
fatal("failed to load kernel - exiting");
@@ -642,6 +644,65 @@ start_client_vmd(void)
}
/*
+ * create_memory_map
+ *
+ * Sets up the guest physical memory ranges that the VM can access.
+ *
+ * Return values:
+ * nothing
+ */
+void
+create_memory_map(struct vm_create_params *vcp)
+{
+ size_t mem_mb;
+ uint64_t mem_bytes, len;
+
+ mem_mb = vcp->vcp_memranges[0].vmr_size;
+ vcp->vcp_nmemranges = 0;
+ if (mem_mb < 1 || mem_mb > VMM_MAX_VM_MEM_SIZE)
+ return;
+
+ mem_bytes = (uint64_t)mem_mb * 1024 * 1024;
+
+ /* First memory region: 0 - LOWMEM_KB (DOS low mem) */
+ vcp->vcp_memranges[0].vmr_gpa = 0x0;
+ vcp->vcp_memranges[0].vmr_size = LOWMEM_KB * 1024;
+ mem_bytes -= LOWMEM_KB * 1024;
+
+ /*
+ * Second memory region: LOWMEM_KB - 1MB.
+ * XXX Normally ROMs or parts of video RAM are mapped here.
+ * We have to add this region, because some systems
+ * unconditionally write to 0xb8000 (video RAM), and
+ * we need to make sure that vmm(4) permits accesses
+ * to it. So allocate guest memory for it.
+ */
+ len = 0x100000 - LOWMEM_KB * 1024;
+ vcp->vcp_memranges[1].vmr_gpa = LOWMEM_KB * 1024;
+ vcp->vcp_memranges[1].vmr_size = len;
+ mem_bytes -= len;
+
+ /* Make sure that we do not place physical memory into MMIO ranges. */
+ if (mem_bytes > VMM_PCI_MMIO_BAR_BASE - 0x100000)
+ len = VMM_PCI_MMIO_BAR_BASE - 0x100000;
+ else
+ len = mem_bytes;
+
+ /* Third memory region: 1MB - (1MB + len) */
+ vcp->vcp_memranges[2].vmr_gpa = 0x100000;
+ vcp->vcp_memranges[2].vmr_size = len;
+ mem_bytes -= len;
+
+ if (mem_bytes > 0) {
+ /* Fourth memory region for the remaining memory (if any) */
+ vcp->vcp_memranges[3].vmr_gpa = VMM_PCI_MMIO_BAR_END + 1;
+ vcp->vcp_memranges[3].vmr_size = mem_bytes;
+ vcp->vcp_nmemranges = 4;
+ } else
+ vcp->vcp_nmemranges = 3;
+}
+
+/*
* vmm_create_vm
*
* Requests vmm(4) to create a new VM using the supplied creation
@@ -663,7 +724,8 @@ vmm_create_vm(struct vm_create_params *vcp)
if (vcp->vcp_ncpus > VMM_MAX_VCPUS_PER_VM)
return (EINVAL);
- if (vcp->vcp_memory_size > VMM_MAX_VM_MEM_SIZE)
+ if (vcp->vcp_nmemranges == 0 ||
+ vcp->vcp_nmemranges > VMM_MAX_MEM_RANGES)
return (EINVAL);
if (vcp->vcp_ndisks > VMM_MAX_DISKS_PER_VM)
@@ -1492,10 +1554,11 @@ vcpu_exit(struct vm_run_params *vrp)
* Note - this function only handles GPAs < 4GB.
*/
int
-write_mem(uint32_t dst, void *buf, uint32_t len, int do_mask)
+write_mem(paddr_t dst, void *buf, size_t len, int do_mask)
{
char *p = buf;
- uint32_t gpa, n, left;
+ size_t n, left;
+ paddr_t gpa;
struct vm_writepage_params vwp;
/*
@@ -1516,11 +1579,11 @@ write_mem(uint32_t dst, void *buf, uint32_t len, int do_mask)
vwp.vwp_paddr = (paddr_t)gpa;
vwp.vwp_data = p;
- vwp.vwp_vm_id = vm_id;
+ vwp.vwp_vm_id = current_vm->vm_params.vcp_id;
vwp.vwp_len = n;
if (ioctl(env->vmd_fd, VMM_IOC_WRITEPAGE, &vwp) < 0) {
- log_warn("writepage ioctl failed @ 0x%x: "
- "dst = 0x%x, len = 0x%x", gpa, dst, len);
+ log_warn("writepage ioctl failed @ 0x%lx: "
+ "dst = 0x%lx, len = 0x%zx", gpa, dst, len);
return (errno);
}
@@ -1550,13 +1613,13 @@ write_mem(uint32_t dst, void *buf, uint32_t len, int do_mask)
* Note - this function only handles GPAs < 4GB.
*/
int
-read_mem(uint32_t src, void *buf, uint32_t len, int do_mask)
+read_mem(paddr_t src, void *buf, size_t len, int do_mask)
{
char *p = buf;
- uint32_t gpa, n, left;
+ size_t n, left;
+ paddr_t gpa;
struct vm_readpage_params vrp;
-
/*
* Mask kernel load addresses to avoid uint32_t -> uint64_t cast
* errors
@@ -1575,11 +1638,11 @@ read_mem(uint32_t src, void *buf, uint32_t len, int do_mask)
vrp.vrp_paddr = (paddr_t)gpa;
vrp.vrp_data = p;
- vrp.vrp_vm_id = vm_id;
+ vrp.vrp_vm_id = current_vm->vm_params.vcp_id;
vrp.vrp_len = n;
if (ioctl(env->vmd_fd, VMM_IOC_READPAGE, &vrp) < 0) {
- log_warn("readpage ioctl failed @ 0x%x: "
- "src = 0x%x, len = 0x%x", gpa, src, len);
+ log_warn("readpage ioctl failed @ 0x%lx: "
+ "src = 0x%lx, len = 0x%zx", gpa, src, len);
return (errno);
}