summaryrefslogtreecommitdiff
path: root/usr.sbin/vmd
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/vmd')
-rw-r--r--usr.sbin/vmd/loadfile.h7
-rw-r--r--usr.sbin/vmd/loadfile_elf.c175
-rw-r--r--usr.sbin/vmd/parse.y10
-rw-r--r--usr.sbin/vmd/virtio.c43
-rw-r--r--usr.sbin/vmd/vmd.h6
-rw-r--r--usr.sbin/vmd/vmm.c97
6 files changed, 217 insertions, 121 deletions
diff --git a/usr.sbin/vmd/loadfile.h b/usr.sbin/vmd/loadfile.h
index 92155921b95..4b473425550 100644
--- a/usr.sbin/vmd/loadfile.h
+++ b/usr.sbin/vmd/loadfile.h
@@ -1,5 +1,5 @@
/* $NetBSD: loadfile.h,v 1.1 1999/04/28 09:08:50 christos Exp $ */
-/* $OpenBSD: loadfile.h,v 1.2 2015/12/17 09:29:28 mlarkin Exp $ */
+/* $OpenBSD: loadfile.h,v 1.3 2016/03/13 13:11:47 stefan Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -63,6 +63,9 @@
#define COUNT_RANDOM 0x4000
#define COUNT_ALL 0x7f00
-int loadelf_main(int, int, int, struct vcpu_init_state *);
+#define LOWMEM_KB 636
+
+int loadelf_main(int, struct vm_create_params *,
+ struct vcpu_init_state *);
#include <machine/loadfile_machdep.h>
diff --git a/usr.sbin/vmd/loadfile_elf.c b/usr.sbin/vmd/loadfile_elf.c
index 069677d3059..2c51e199c03 100644
--- a/usr.sbin/vmd/loadfile_elf.c
+++ b/usr.sbin/vmd/loadfile_elf.c
@@ -1,5 +1,5 @@
/* $NetBSD: loadfile.c,v 1.10 2000/12/03 02:53:04 tsutsui Exp $ */
-/* $OpenBSD: loadfile_elf.c,v 1.10 2016/03/04 15:34:14 stefan Exp $ */
+/* $OpenBSD: loadfile_elf.c,v 1.11 2016/03/13 13:11:47 stefan Exp $ */
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
@@ -108,8 +108,6 @@
#define GDT_PAGE 0x10000
#define STACK_PAGE 0xF000
-#define LOWMEM_KB 636
-
union {
Elf32_Ehdr elf32;
Elf64_Ehdr elf64;
@@ -119,12 +117,13 @@ static void setsegment(struct mem_segment_descriptor *, uint32_t,
size_t, int, int, int, int);
static int elf32_exec(int, Elf32_Ehdr *, u_long *, int);
static int elf64_exec(int, Elf64_Ehdr *, u_long *, int);
-static void push_bootargs(int);
-static size_t push_stack(int, uint32_t);
+static size_t create_bios_memmap(struct vm_create_params *, bios_memmap_t *);
+static uint32_t push_bootargs(bios_memmap_t *, size_t);
+static size_t push_stack(uint32_t, uint32_t);
static void push_gdt(void);
-static size_t mread(int, uint32_t, size_t);
-static void marc4random_buf(uint32_t, int);
-static void mbzero(uint32_t, int);
+static size_t mread(int, paddr_t, size_t);
+static void marc4random_buf(paddr_t, int);
+static void mbzero(paddr_t, int);
static void mbcopy(char *, char *, int);
extern char *__progname;
@@ -198,15 +197,12 @@ push_gdt(void)
/*
* loadelf_main
*
- * Loads an ELF kernel to it's defined load address in the guest VM whose
- * ID is provided in 'vm_id_in'. The kernel is loaded to its defined start
- * point as set in the ELF header.
+ * Loads an ELF kernel to it's defined load address in the guest VM.
+ * The kernel is loaded to its defined start point as set in the ELF header.
*
* Parameters:
* fd: file descriptor of a kernel file to load
- * vm_id_in: ID of the VM to load the kernel into
- * mem_sz: memory size in MB assigned to the guest (passed through to
- * push_bootargs)
+ * vcp: the VM create parameters, holding the exact memory map
* (out) vis: register state to set on init for this kernel
*
* Return values:
@@ -214,13 +210,13 @@ push_gdt(void)
* various error codes returned from read(2) or loadelf functions
*/
int
-loadelf_main(int fd, int vm_id_in, int mem_sz, struct vcpu_init_state *vis)
+loadelf_main(int fd, struct vm_create_params *vcp, struct vcpu_init_state *vis)
{
int r;
- size_t stacksize;
+ uint32_t bootargsz;
+ size_t n, stacksize;
u_long marks[MARK_MAX];
-
- vm_id = vm_id_in;
+ bios_memmap_t memmap[VMM_MAX_MEM_RANGES + 1];
if ((r = read(fd, &hdr, sizeof(hdr))) != sizeof(hdr))
return 1;
@@ -237,9 +233,10 @@ loadelf_main(int fd, int vm_id_in, int mem_sz, struct vcpu_init_state *vis)
if (r)
return (r);
- push_bootargs(mem_sz);
push_gdt();
- stacksize = push_stack(mem_sz, marks[MARK_END]);
+ n = create_bios_memmap(vcp, memmap);
+ bootargsz = push_bootargs(memmap, n);
+ stacksize = push_stack(bootargsz, marks[MARK_END]);
vis->vis_rip = (uint64_t)marks[MARK_ENTRY];
vis->vis_rsp = (uint64_t)(STACK_PAGE + PAGE_SIZE) - stacksize;
@@ -249,6 +246,58 @@ loadelf_main(int fd, int vm_id_in, int mem_sz, struct vcpu_init_state *vis)
}
/*
+ * create_bios_memmap
+ *
+ * Construct a memory map as returned by the BIOS INT 0x15, e820 routine.
+ *
+ * Parameters:
+ * vcp: the VM create parameters, containing the memory map passed to vmm(4)
+ * memmap (out): the BIOS memory map
+ *
+ * Return values:
+ * Number of bios_memmap_t entries, including the terminating nul-entry.
+ */
+static size_t
+create_bios_memmap(struct vm_create_params *vcp, bios_memmap_t *memmap)
+{
+ size_t i, n = 0, sz;
+ paddr_t gpa;
+ struct vm_mem_range *vmr;
+
+ for (i = 0; i < vcp->vcp_nmemranges; i++) {
+ vmr = &vcp->vcp_memranges[i];
+ gpa = vmr->vmr_gpa;
+ sz = vmr->vmr_size;
+
+ /*
+ * Make sure that we do not mark the ROM/video RAM area in the
+ * low memory as physcal memory available to the kernel.
+ */
+ if (gpa < 0x100000 && gpa + sz > LOWMEM_KB * 1024) {
+ if (gpa >= LOWMEM_KB * 1024)
+ sz = 0;
+ else
+ sz = LOWMEM_KB * 1024 - gpa;
+ }
+
+ if (sz != 0) {
+ memmap[n].addr = gpa;
+ memmap[n].size = sz;
+ memmap[n].type = 0x1; /* Type 1 : Normal memory */
+ n++;
+ }
+ }
+
+ /* Null mem map entry to denote the end of the ranges */
+ memmap[n].addr = 0x0;
+ memmap[n].size = 0x0;
+ memmap[n].type = 0x0;
+ n++;
+
+ return (n);
+}
+
+/*
* push_bootargs
*
* Creates the boot arguments page in the guest address space.
@@ -257,40 +306,25 @@ loadelf_main(int fd, int vm_id_in, int mem_sz, struct vcpu_init_state *vis)
* into the guest phys RAM space at address BOOTARGS_PAGE.
*
* Parameters:
- * mem_sz: guest memory size in MB
+ * memmap: the BIOS memory map
+ * n: number of entries in memmap
*
* Return values:
- * nothing
+ * The size of the bootargs
*/
-static void
-push_bootargs(int mem_sz)
+static uint32_t
+push_bootargs(bios_memmap_t *memmap, size_t n)
{
- size_t sz;
- bios_memmap_t memmap[3];
+ uint32_t memmap_sz, consdev_sz, i;
bios_consdev_t consdev;
uint32_t ba[1024];
- /* First memory region: 0 - LOWMEM_KB (DOS low mem) */
- memmap[0].addr = 0x0;
- memmap[0].size = LOWMEM_KB * 1024;
- memmap[0].type = 0x1; /* Type 1 : Normal memory */
-
- /* Second memory region: 1MB - n, reserve top 1MB */
- memmap[1].addr = 0x100000;
- memmap[1].size = (mem_sz - 1) * 1024 * 1024;
- memmap[1].type = 0x1; /* Type 1 : Normal memory */
-
- /* Null mem map entry to denote the end of the ranges */
- memmap[2].addr = 0x0;
- memmap[2].size = 0x0;
- memmap[2].type = 0x0;
-
- sz = 3 * sizeof(int) + 3 * sizeof(bios_memmap_t);
+ memmap_sz = 3 * sizeof(int) + n * sizeof(bios_memmap_t);
ba[0] = 0x0; /* memory map */
- ba[1] = sz;
- ba[2] = sz; /* next */
- memcpy(&ba[3], &memmap, 3 * sizeof(bios_memmap_t));
- sz = sz / sizeof(int);
+ ba[1] = memmap_sz;
+ ba[2] = memmap_sz; /* next */
+ memcpy(&ba[3], memmap, n * sizeof(bios_memmap_t));
+ i = memmap_sz / sizeof(int);
/* Serial console device, COM1 @ 0x3f8 */
consdev.consdev = makedev(8, 0); /* com1 @ 0x3f8 */
@@ -298,12 +332,15 @@ push_bootargs(int mem_sz)
consdev.consaddr = 0x3f8;
consdev.consfreq = 0;
- ba[sz] = 0x5; /* consdev */
- ba[sz + 1] = (int)sizeof(bios_consdev_t) + 3 * sizeof(int);
- ba[sz + 2] = (int)sizeof(bios_consdev_t) + 3 * sizeof(int);
- memcpy(&ba[sz + 3], &consdev, sizeof(bios_consdev_t));
+ consdev_sz = 3 * sizeof(int) + sizeof(bios_consdev_t);
+ ba[i] = 0x5; /* consdev */
+ ba[i + 1] = consdev_sz;
+ ba[i + 2] = consdev_sz;
+ memcpy(&ba[i + 3], &consdev, sizeof(bios_consdev_t));
write_mem(BOOTARGS_PAGE, ba, PAGE_SIZE, 1);
+
+ return (memmap_sz + consdev_sz);
}
/*
@@ -319,20 +356,20 @@ push_bootargs(int mem_sz)
* Stack Layout: (TOS == Top Of Stack)
* TOS location of boot arguments page
* TOS - 0x4 size of the content in the boot arguments page
- * TOS - 0x8 size of low memory in KB
- * TOS - 0xc size of high memory in KB
+ * TOS - 0x8 size of low memory (biosbasemem: kernel uses BIOS map only if 0)
+ * TOS - 0xc size of high memory (biosextmem, not used by kernel at all)
* TOS - 0x10 kernel 'end' symbol value
* TOS - 0x14 version of bootarg API
*
* Parameters:
- * mem_sz: size of guest VM memory, in MB
+ * bootargsz: size of boot arguments
* end: kernel 'end' symbol value
*
* Return values:
* size of the stack
*/
static size_t
-push_stack(int mem_sz, uint32_t end)
+push_stack(uint32_t bootargsz, uint32_t end)
{
uint32_t stack[1024];
uint16_t loc;
@@ -341,11 +378,9 @@ push_stack(int mem_sz, uint32_t end)
loc = 1024;
stack[--loc] = BOOTARGS_PAGE;
- stack[--loc] = 3 * sizeof(bios_memmap_t) +
- sizeof(bios_consdev_t) +
- 6 * sizeof(int);
- stack[--loc] = LOWMEM_KB;
- stack[--loc] = mem_sz * 1024 - LOWMEM_KB;
+ stack[--loc] = bootargsz;
+ stack[--loc] = 0; /* biosbasemem */
+ stack[--loc] = 0; /* biosextmem */
stack[--loc] = end;
stack[--loc] = 0x0e;
stack[--loc] = MAKEBOOTDEV(0x4, 0, 0, 0, 0); /* bootdev: sd0a */
@@ -360,8 +395,7 @@ push_stack(int mem_sz, uint32_t end)
* mread
*
* Reads 'sz' bytes from the file whose descriptor is provided in 'fd'
- * into the guest address space at paddr 'addr'. Note that the guest
- * paddr is limited to 32 bit (4GB).
+ * into the guest address space at paddr 'addr'.
*
* Parameters:
* fd: file descriptor of the kernel image file to read from.
@@ -372,7 +406,7 @@ push_stack(int mem_sz, uint32_t end)
* returns 'sz' if successful, or 0 otherwise.
*/
static size_t
-mread(int fd, uint32_t addr, size_t sz)
+mread(int fd, paddr_t addr, size_t sz)
{
int ct;
size_t i, rd, osz;
@@ -433,7 +467,7 @@ mread(int fd, uint32_t addr, size_t sz)
* marc4random_buf
*
* load 'sz' bytes of random data into the guest address space at paddr
- * 'addr'. Note that the guest paddr is limited to 32 bit (4GB).
+ * 'addr'.
*
* Parameters:
* addr: guest paddr_t to load random bytes into
@@ -443,7 +477,7 @@ mread(int fd, uint32_t addr, size_t sz)
* nothing
*/
static void
-marc4random_buf(uint32_t addr, int sz)
+marc4random_buf(paddr_t addr, int sz)
{
int i, ct;
char buf[PAGE_SIZE];
@@ -483,7 +517,7 @@ marc4random_buf(uint32_t addr, int sz)
* mbzero
*
* load 'sz' bytes of zeros into the guest address space at paddr
- * 'addr'. Note that the guest paddr is limited to 32 bit (4GB)
+ * 'addr'.
*
* Parameters:
* addr: guest paddr_t to zero
@@ -493,7 +527,7 @@ marc4random_buf(uint32_t addr, int sz)
* nothing
*/
static void
-mbzero(uint32_t addr, int sz)
+mbzero(paddr_t addr, int sz)
{
int i, ct;
char buf[PAGE_SIZE];
@@ -528,7 +562,6 @@ mbzero(uint32_t addr, int sz)
* mbcopy
*
* copies 'sz' bytes from guest paddr 'src' to guest paddr 'dst'.
- * Both 'src' and 'dst' are limited to 32 bit (4GB)
*
* Parameters:
* src: source guest paddr_t to copy from
@@ -632,7 +665,7 @@ elf64_exec(int fd, Elf64_Ehdr *elf, u_long *marks, int flags)
free(phdr);
return 1;
}
- if (mread(fd, (uint32_t)(phdr[i].p_paddr -
+ if (mread(fd, (phdr[i].p_paddr -
0xffffffff80000000ULL), phdr[i].p_filesz) !=
phdr[i].p_filesz) {
free(phdr);
@@ -654,7 +687,7 @@ elf64_exec(int fd, Elf64_Ehdr *elf, u_long *marks, int flags)
/* Zero out BSS. */
if (IS_BSS(phdr[i]) && (flags & LOAD_BSS)) {
- mbzero((uint32_t)(phdr[i].p_paddr -
+ mbzero((phdr[i].p_paddr -
0xffffffff80000000 + phdr[i].p_filesz),
phdr[i].p_memsz - phdr[i].p_filesz);
}
@@ -725,7 +758,7 @@ elf64_exec(int fd, Elf64_Ehdr *elf, u_long *marks, int flags)
free(shp);
return 1;
}
- if (mread(fd, (uint32_t)maxp,
+ if (mread(fd, maxp,
shp[i].sh_size) != shp[i].sh_size) {
free(shstr);
free(shp);
@@ -946,7 +979,7 @@ elf32_exec(int fd, Elf32_Ehdr *elf, u_long *marks, int flags)
free(shp);
return 1;
}
- if (mread(fd, (uint32_t)maxp,
+ if (mread(fd, maxp,
shp[i].sh_size) != shp[i].sh_size) {
free(shstr);
free(shp);
diff --git a/usr.sbin/vmd/parse.y b/usr.sbin/vmd/parse.y
index c69eaf167ac..23cea73bb32 100644
--- a/usr.sbin/vmd/parse.y
+++ b/usr.sbin/vmd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.5 2015/12/07 13:30:06 reyk Exp $ */
+/* $OpenBSD: parse.y,v 1.6 2016/03/13 13:11:47 stefan Exp $ */
/*
* Copyright (c) 2007-2015 Reyk Floeter <reyk@openbsd.org>
@@ -218,7 +218,7 @@ vm_opts : disable {
}
| MEMORY NUMBER {
ssize_t res;
- if (vcp.vcp_memory_size != 0) {
+ if (vcp.vcp_memranges[0].vmr_size != 0) {
yyerror("memory specified more than once");
YYERROR;
}
@@ -226,11 +226,11 @@ vm_opts : disable {
yyerror("failed to parse size: %lld", $2);
YYERROR;
}
- vcp.vcp_memory_size = (size_t)res;
+ vcp.vcp_memranges[0].vmr_size = (size_t)res;
}
| MEMORY STRING {
ssize_t res;
- if (vcp.vcp_memory_size != 0) {
+ if (vcp.vcp_memranges[0].vmr_size != 0) {
yyerror("argument specified more than once");
free($2);
YYERROR;
@@ -240,7 +240,7 @@ vm_opts : disable {
free($2);
YYERROR;
}
- vcp.vcp_memory_size = (size_t)res;
+ vcp.vcp_memranges[0].vmr_size = (size_t)res;
}
;
diff --git a/usr.sbin/vmd/virtio.c b/usr.sbin/vmd/virtio.c
index 56de8244f96..43a19777980 100644
--- a/usr.sbin/vmd/virtio.c
+++ b/usr.sbin/vmd/virtio.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: virtio.c,v 1.9 2016/02/07 10:17:19 jsg Exp $ */
+/* $OpenBSD: virtio.c,v 1.10 2016/03/13 13:11:47 stefan Exp $ */
/*
* Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org>
@@ -172,7 +172,7 @@ viornd_notifyq(void)
memset(buf, 0, vr_sz);
- if (read_mem((uint32_t)q_gpa, buf, vr_sz, 0)) {
+ if (read_mem(q_gpa, buf, vr_sz, 0)) {
free(buf);
return (0);
}
@@ -188,7 +188,7 @@ viornd_notifyq(void)
if (rnd_data != NULL) {
arc4random_buf(rnd_data, desc[avail->ring[avail->idx]].len);
- if (write_mem((uint32_t)(desc[avail->ring[avail->idx]].addr),
+ if (write_mem(desc[avail->ring[avail->idx]].addr,
rnd_data, desc[avail->ring[avail->idx]].len, 0)) {
log_warnx("viornd: can't write random data @ "
"0x%llx",
@@ -384,8 +384,8 @@ vioblk_notifyq(struct vioblk_dev *dev)
memset(vr, 0, vr_sz);
- if (read_mem((uint32_t)q_gpa, vr, vr_sz, 0)) {
- log_warnx("error reading gpa 0x%x", (uint32_t)q_gpa);
+ if (read_mem(q_gpa, vr, vr_sz, 0)) {
+ log_warnx("error reading gpa 0x%llx", q_gpa);
free(vr);
return (0);
}
@@ -417,7 +417,7 @@ vioblk_notifyq(struct vioblk_dev *dev)
}
/* Read command from descriptor ring */
- if (read_mem((uint32_t)cmd_desc->addr, &cmd, cmd_desc->len, 0)) {
+ if (read_mem(cmd_desc->addr, &cmd, cmd_desc->len, 0)) {
log_warnx("vioblk: command read_mem error @ 0x%llx",
cmd_desc->addr);
free(vr);
@@ -453,7 +453,7 @@ vioblk_notifyq(struct vioblk_dev *dev)
return (0);
}
- if (write_mem((uint32_t)secdata_desc->addr, secdata,
+ if (write_mem(secdata_desc->addr, secdata,
secdata_desc->len, 0)) {
log_warnx("can't write sector "
"data to gpa @ 0x%llx",
@@ -476,8 +476,7 @@ vioblk_notifyq(struct vioblk_dev *dev)
ds_desc = secdata_desc;
ds = VIRTIO_BLK_S_OK;
- if (write_mem((uint32_t)ds_desc->addr,
- &ds, ds_desc->len, 0)) {
+ if (write_mem(ds_desc->addr, &ds, ds_desc->len, 0)) {
log_warnx("can't write device status data @ "
"0x%llx", ds_desc->addr);
dump_descriptor_chain(desc, cmd_desc_idx);
@@ -520,7 +519,7 @@ vioblk_notifyq(struct vioblk_dev *dev)
secbias = 0;
do {
- if (read_mem((uint32_t)secdata_desc->addr, secdata,
+ if (read_mem(secdata_desc->addr, secdata,
secdata_desc->len, 0)) {
log_warnx("wr vioblk: can't read "
"sector data @ 0x%llx",
@@ -552,8 +551,7 @@ vioblk_notifyq(struct vioblk_dev *dev)
ds_desc = secdata_desc;
ds = VIRTIO_BLK_S_OK;
- if (write_mem((uint32_t)ds_desc->addr,
- &ds, ds_desc->len, 0)) {
+ if (write_mem(ds_desc->addr, &ds, ds_desc->len, 0)) {
log_warnx("wr vioblk: can't write device status "
"data @ 0x%llx", ds_desc->addr);
dump_descriptor_chain(desc, cmd_desc_idx);
@@ -578,8 +576,7 @@ vioblk_notifyq(struct vioblk_dev *dev)
ds_desc = &desc[ds_desc_idx];
ds = VIRTIO_BLK_S_OK;
- if (write_mem((uint32_t)ds_desc->addr,
- &ds, ds_desc->len, 0)) {
+ if (write_mem(ds_desc->addr, &ds, ds_desc->len, 0)) {
log_warnx("fl vioblk: can't write device status "
"data @ 0x%llx", ds_desc->addr);
dump_descriptor_chain(desc, cmd_desc_idx);
@@ -807,8 +804,8 @@ vionet_enq_rx(struct vionet_dev *dev, char *pkt, ssize_t sz, int *spc)
memset(vr, 0, vr_sz);
- if (read_mem((uint32_t)q_gpa, vr, vr_sz, 0)) {
- log_warnx("rx enq: error reading gpa 0x%x", (uint32_t)q_gpa);
+ if (read_mem(q_gpa, vr, vr_sz, 0)) {
+ log_warnx("rx enq: error reading gpa 0x%llx", q_gpa);
free(vr);
return (0);
}
@@ -843,7 +840,7 @@ vionet_enq_rx(struct vionet_dev *dev, char *pkt, ssize_t sz, int *spc)
}
/* Write packet to descriptor ring */
- if (write_mem((uint32_t)pkt_desc->addr, pkt, sz, 0)) {
+ if (write_mem(pkt_desc->addr, pkt, sz, 0)) {
log_warnx("vionet: rx enq packet write_mem error @ "
"0x%llx", pkt_desc->addr);
free(vr);
@@ -933,8 +930,8 @@ vionet_notify_rx(struct vionet_dev *dev)
memset(vr, 0, vr_sz);
- if (read_mem((uint32_t)q_gpa, vr, vr_sz, 0)) {
- log_warnx("error reading gpa 0x%x", (uint32_t)q_gpa);
+ if (read_mem(q_gpa, vr, vr_sz, 0)) {
+ log_warnx("error reading gpa 0x%llx", q_gpa);
free(vr);
return;
}
@@ -994,8 +991,8 @@ vionet_notifyq(struct vionet_dev *dev)
memset(vr, 0, vr_sz);
- if (read_mem((uint32_t)q_gpa, vr, vr_sz, 0)) {
- log_warnx("error reading gpa 0x%x", (uint32_t)q_gpa);
+ if (read_mem(q_gpa, vr, vr_sz, 0)) {
+ log_warnx("error reading gpa 0x%llx", q_gpa);
goto out;
}
@@ -1055,7 +1052,7 @@ vionet_notifyq(struct vionet_dev *dev)
}
/* Read packet from descriptor ring */
- if (read_mem((uint32_t)pkt_desc->addr, pkt + ofs,
+ if (read_mem(pkt_desc->addr, pkt + ofs,
pkt_desc->len, 0)) {
log_warnx("vionet: packet read_mem error "
"@ 0x%llx", pkt_desc->addr);
@@ -1075,7 +1072,7 @@ vionet_notifyq(struct vionet_dev *dev)
}
/* Read packet from descriptor ring */
- if (read_mem((uint32_t)pkt_desc->addr, pkt + ofs,
+ if (read_mem(pkt_desc->addr, pkt + ofs,
pkt_desc->len, 0)) {
log_warnx("vionet: packet read_mem error @ "
"0x%llx", pkt_desc->addr);
diff --git a/usr.sbin/vmd/vmd.h b/usr.sbin/vmd/vmd.h
index 97a2ebdbba1..2d52ac87a44 100644
--- a/usr.sbin/vmd/vmd.h
+++ b/usr.sbin/vmd/vmd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: vmd.h,v 1.18 2016/01/16 08:55:40 stefan Exp $ */
+/* $OpenBSD: vmd.h,v 1.19 2016/03/13 13:11:47 stefan Exp $ */
/*
* Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org>
@@ -114,8 +114,8 @@ char *get_string(uint8_t *, size_t);
/* vmm.c */
pid_t vmm(struct privsep *, struct privsep_proc *);
-int write_mem(uint32_t dst, void *buf, uint32_t, int);
-int read_mem(uint32_t dst, void *buf, uint32_t, int);
+int write_mem(paddr_t, void *buf, size_t, int);
+int read_mem(paddr_t, void *buf, size_t, int);
int opentap(void);
/* control.c */
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);
}