vmd(8): fix vmctl -b option for i386 kernels.
authormlarkin <mlarkin@openbsd.org>
Tue, 17 Jul 2018 13:47:06 +0000 (13:47 +0000)
committermlarkin <mlarkin@openbsd.org>
Tue, 17 Jul 2018 13:47:06 +0000 (13:47 +0000)
ok pd@

usr.sbin/vmd/loadfile_elf.c
usr.sbin/vmd/vm.c

index 586e491..295852e 100644 (file)
@@ -1,5 +1,5 @@
 /* $NetBSD: loadfile.c,v 1.10 2000/12/03 02:53:04 tsutsui Exp $ */
-/* $OpenBSD: loadfile_elf.c,v 1.29 2017/11/29 02:46:10 mlarkin Exp $ */
+/* $OpenBSD: loadfile_elf.c,v 1.30 2018/07/17 13:47:06 mlarkin Exp $ */
 
 /*-
  * Copyright (c) 1997 The NetBSD Foundation, Inc.
 #include <machine/vmmvar.h>
 #include <machine/biosvar.h>
 #include <machine/segments.h>
+#include <machine/specialreg.h>
 #include <machine/pte.h>
 
 #include "loadfile.h"
@@ -124,7 +125,8 @@ 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, uint32_t, uint32_t);
 static void push_gdt(void);
-static void push_pt(void);
+static void push_pt_32(void);
+static void push_pt_64(void);
 static void marc4random_buf(paddr_t, int);
 static void mbzero(paddr_t, int);
 static void mbcopy(void *, paddr_t, int);
@@ -217,16 +219,35 @@ push_gdt(void)
 }
 
 /*
- * push_pt
+ * push_pt_32
  *
  * Create an identity-mapped page directory hierarchy mapping the first
- * 1GB of physical memory. This is used during bootstrapping VMs on
+ * 4GB of physical memory. This is used during bootstrapping i386 VMs on
  * CPUs without unrestricted guest capability.
  */
 static void
-push_pt(void)
+push_pt_32(void)
 {
-       uint64_t ptes[NPTE_PG], i;
+       uint32_t ptes[1024], i;
+
+       memset(ptes, 0, sizeof(ptes));
+       for (i = 0 ; i < 1024; i++) {
+               ptes[i] = PG_V | PG_RW | PG_u | PG_PS | ((4096 * 1024) * i);
+       }
+       write_mem(PML3_PAGE, ptes, PAGE_SIZE);
+}
+
+/*
+ * push_pt_64
+ *
+ * Create an identity-mapped page directory hierarchy mapping the first
+ * 1GB of physical memory. This is used during bootstrapping 64 bit VMs on
+ * CPUs without unrestricted guest capability.
+ */
+static void
+push_pt_64(void)
+{
+       uint64_t ptes[512], i;
 
        /* PDPDE0 - first 1GB */
        memset(ptes, 0, sizeof(ptes));
@@ -240,7 +261,7 @@ push_pt(void)
 
        /* First 1GB (in 2MB pages) */
        memset(ptes, 0, sizeof(ptes));
-       for (i = 0 ; i < NPTE_PG; i++) {
+       for (i = 0 ; i < 512; i++) {
                ptes[i] = PG_V | PG_RW | PG_u | PG_PS | ((2048 * 1024) * i);
        }
        write_mem(PML2_PAGE, ptes, PAGE_SIZE);
@@ -267,7 +288,7 @@ int
 loadfile_elf(FILE *fp, struct vm_create_params *vcp,
     struct vcpu_reg_state *vrs, uint32_t bootdev, uint32_t howto)
 {
-       int r;
+       int r, is_i386 = 0;
        uint32_t bootargsz;
        size_t n, stacksize;
        u_long marks[MARK_MAX];
@@ -280,6 +301,7 @@ loadfile_elf(FILE *fp, struct vm_create_params *vcp,
        if (memcmp(hdr.elf32.e_ident, ELFMAG, SELFMAG) == 0 &&
            hdr.elf32.e_ident[EI_CLASS] == ELFCLASS32) {
                r = elf32_exec(fp, &hdr.elf32, marks, LOAD_ALL);
+               is_i386 = 1;
        } else if (memcmp(hdr.elf64.e_ident, ELFMAG, SELFMAG) == 0 &&
            hdr.elf64.e_ident[EI_CLASS] == ELFCLASS64) {
                r = elf64_exec(fp, &hdr.elf64, marks, LOAD_ALL);
@@ -290,7 +312,17 @@ loadfile_elf(FILE *fp, struct vm_create_params *vcp,
                return (r);
 
        push_gdt();
-       push_pt();
+
+       if (is_i386) {
+               push_pt_32();
+               /* Reconfigure the default flat-64 register set for 32 bit */
+               vrs->vrs_crs[VCPU_REGS_CR3] = PML3_PAGE;
+               vrs->vrs_crs[VCPU_REGS_CR4] = CR4_PSE;
+               vrs->vrs_msrs[VCPU_REGS_EFER] = 0ULL;
+       }
+       else
+               push_pt_64();
+
        n = create_bios_memmap(vcp, memmap);
        bootargsz = push_bootargs(memmap, n);
        stacksize = push_stack(bootargsz, marks[MARK_END], bootdev, howto);
index 67252e5..046b2be 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: vm.c,v 1.37 2018/07/12 10:15:44 mlarkin Exp $ */
+/*     $OpenBSD: vm.c,v 1.38 2018/07/17 13:47:06 mlarkin Exp $ */
 
 /*
  * Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org>
@@ -110,7 +110,7 @@ uint8_t vcpu_done[VMM_MAX_VCPUS_PER_VM];
 
 /*
  * Represents a standard register set for an OS to be booted
- * as a flat 32 bit address space, before paging is enabled.
+ * as a flat 64 bit address space.
  *
  * NOT set here are:
  *  RIP
@@ -123,7 +123,7 @@ uint8_t vcpu_done[VMM_MAX_VCPUS_PER_VM];
  * Note - CR3 and various bits in CR0 may be overridden by vmm(4) based on
  *        features of the CPU in use.
  */
-static const struct vcpu_reg_state vcpu_init_flat32 = {
+static const struct vcpu_reg_state vcpu_init_flat64 = {
 #ifdef __i386__
        .vrs_gprs[VCPU_REGS_EFLAGS] = 0x2,
        .vrs_gprs[VCPU_REGS_EIP] = 0x0,
@@ -136,7 +136,7 @@ static const struct vcpu_reg_state vcpu_init_flat32 = {
        .vrs_crs[VCPU_REGS_CR0] = CR0_CD | CR0_NW | CR0_ET | CR0_PE | CR0_PG,
        .vrs_crs[VCPU_REGS_CR3] = PML4_PAGE,
        .vrs_crs[VCPU_REGS_CR4] = CR4_PAE | CR4_PSE,
-       .vrs_crs[VCPU_REGS_PDPTE0] = PML3_PAGE | PG_V,
+       .vrs_crs[VCPU_REGS_PDPTE0] = 0ULL,
        .vrs_crs[VCPU_REGS_PDPTE1] = 0ULL,
        .vrs_crs[VCPU_REGS_PDPTE2] = 0ULL,
        .vrs_crs[VCPU_REGS_PDPTE3] = 0ULL,
@@ -319,10 +319,10 @@ start_vm(struct vmd_vm *vm, int fd)
                vrs = vrp.vrwp_regs;
        } else {
                /*
-                * Set up default "flat 32 bit" register state - RIP,
+                * Set up default "flat 64 bit" register state - RIP,
                 * RSP, and GDT info will be set in bootloader
                 */
-               memcpy(&vrs, &vcpu_init_flat32, sizeof(vrs));
+               memcpy(&vrs, &vcpu_init_flat64, sizeof(vrs));
 
                /* Find and open kernel image */
                if ((fp = vmboot_open(vm->vm_kernel,