Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 12 Jun 2014 15:20:59 +0000 (UTC)
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r267399 - in stable/10: lib/libvmmapi sys/amd64/include sys/amd64/vmm sys/amd64/vmm/intel sys/boot/common sys/boot/userboot/userboot usr.sbin/bhyveload
Message-ID:  <201406121520.s5CFKxvA099459@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhb
Date: Thu Jun 12 15:20:59 2014
New Revision: 267399
URL: http://svnweb.freebsd.org/changeset/base/267399

Log:
  MFC 261504:
  Add support for FreeBSD/i386 guests under bhyve.

Added:
  stable/10/sys/boot/userboot/userboot/biossmap.c
     - copied unchanged from r261504, head/sys/boot/userboot/userboot/biossmap.c
Modified:
  stable/10/lib/libvmmapi/vmmapi.h
  stable/10/lib/libvmmapi/vmmapi_freebsd.c
  stable/10/sys/amd64/include/vmm.h
  stable/10/sys/amd64/include/vmm_instruction_emul.h
  stable/10/sys/amd64/vmm/intel/vmx.c
  stable/10/sys/amd64/vmm/vmm.c
  stable/10/sys/amd64/vmm/vmm_instruction_emul.c
  stable/10/sys/boot/common/load_elf32.c
  stable/10/sys/boot/common/load_elf32_obj.c
  stable/10/sys/boot/userboot/userboot/Makefile
  stable/10/sys/boot/userboot/userboot/bootinfo32.c
  stable/10/sys/boot/userboot/userboot/bootinfo64.c
  stable/10/sys/boot/userboot/userboot/elf32_freebsd.c
  stable/10/sys/boot/userboot/userboot/libuserboot.h
  stable/10/usr.sbin/bhyveload/bhyveload.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/lib/libvmmapi/vmmapi.h
==============================================================================
--- stable/10/lib/libvmmapi/vmmapi.h	Thu Jun 12 14:20:58 2014	(r267398)
+++ stable/10/lib/libvmmapi/vmmapi.h	Thu Jun 12 15:20:59 2014	(r267399)
@@ -111,5 +111,8 @@ int	vcpu_reset(struct vmctx *ctx, int vc
 int	vm_setup_freebsd_registers(struct vmctx *ctx, int vcpu,
 				uint64_t rip, uint64_t cr3, uint64_t gdtbase,
 				uint64_t rsp);
+int	vm_setup_freebsd_registers_i386(struct vmctx *vmctx, int vcpu,
+					uint32_t eip, uint32_t gdtbase,
+					uint32_t esp);
 void	vm_setup_freebsd_gdt(uint64_t *gdtr);
 #endif	/* _VMMAPI_H_ */

Modified: stable/10/lib/libvmmapi/vmmapi_freebsd.c
==============================================================================
--- stable/10/lib/libvmmapi/vmmapi_freebsd.c	Thu Jun 12 14:20:58 2014	(r267398)
+++ stable/10/lib/libvmmapi/vmmapi_freebsd.c	Thu Jun 12 15:20:59 2014	(r267399)
@@ -35,14 +35,176 @@ __FBSDID("$FreeBSD$");
 #include <machine/segments.h>
 #include <machine/vmm.h>
 
+#include <errno.h>
+#include <string.h>
+
 #include "vmmapi.h"
 
+#define	I386_TSS_SIZE		104
+
+#define	DESC_PRESENT		0x00000080
+#define	DESC_LONGMODE		0x00002000
+#define	DESC_DEF32		0x00004000
+#define	DESC_GRAN		0x00008000
 #define	DESC_UNUSABLE		0x00010000
 
 #define	GUEST_NULL_SEL		0
 #define	GUEST_CODE_SEL		1
 #define	GUEST_DATA_SEL		2
-#define	GUEST_GDTR_LIMIT	(3 * 8 - 1)
+#define	GUEST_TSS_SEL		3
+#define	GUEST_GDTR_LIMIT64	(3 * 8 - 1)
+
+static struct segment_descriptor i386_gdt[] = {
+	{},						/* NULL */
+	{ .sd_lolimit = 0xffff, .sd_type = SDT_MEMER,	/* CODE */
+	  .sd_p = 1, .sd_hilimit = 0xf, .sd_def32 = 1, .sd_gran = 1 }, 
+	{ .sd_lolimit = 0xffff, .sd_type = SDT_MEMRW,	/* DATA */
+	  .sd_p = 1, .sd_hilimit = 0xf, .sd_def32 = 1, .sd_gran = 1 },
+	{ .sd_lolimit = I386_TSS_SIZE - 1,		/* TSS */
+	  .sd_type = SDT_SYS386TSS, .sd_p = 1 }
+};
+
+/*
+ * Setup the 'vcpu' register set such that it will begin execution at
+ * 'eip' in flat mode.
+ */
+int
+vm_setup_freebsd_registers_i386(struct vmctx *vmctx, int vcpu, uint32_t eip,
+				uint32_t gdtbase, uint32_t esp)
+{
+	uint64_t cr0, rflags, desc_base;
+	uint32_t desc_access, desc_limit, tssbase;
+	uint16_t gsel;
+	struct segment_descriptor *gdt;
+	int error, tmp;
+
+	/* A 32-bit guest requires unrestricted mode. */	
+	error = vm_get_capability(vmctx, vcpu, VM_CAP_UNRESTRICTED_GUEST, &tmp);
+	if (error)
+		goto done;
+	error = vm_set_capability(vmctx, vcpu, VM_CAP_UNRESTRICTED_GUEST, 1);
+	if (error)
+		goto done;
+
+	cr0 = CR0_PE | CR0_NE;
+	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CR0, cr0)) != 0)
+		goto done;
+
+	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CR4, 0)) != 0)
+		goto done;
+
+	/*
+	 * Forcing EFER to 0 causes bhyve to clear the "IA-32e guest
+	 * mode" entry control.
+	 */
+	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_EFER, 0)))
+		goto done;
+
+	gdt = vm_map_gpa(vmctx, gdtbase, 0x1000);
+	if (gdt == NULL)
+		return (EFAULT);
+	memcpy(gdt, i386_gdt, sizeof(i386_gdt));
+	desc_base = gdtbase;
+	desc_limit = sizeof(i386_gdt) - 1;
+	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_GDTR,
+			    desc_base, desc_limit, 0);
+	if (error != 0)
+		goto done;
+
+	/* Place the TSS one page above the GDT. */
+	tssbase = gdtbase + 0x1000;
+	gdt[3].sd_lobase = tssbase;	
+
+	rflags = 0x2;
+	error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RFLAGS, rflags);
+	if (error)
+		goto done;
+
+	desc_base = 0;
+	desc_limit = 0xffffffff;
+	desc_access = DESC_GRAN | DESC_DEF32 | DESC_PRESENT | SDT_MEMERA;
+	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_CS,
+			    desc_base, desc_limit, desc_access);
+
+	desc_access = DESC_GRAN | DESC_DEF32 | DESC_PRESENT | SDT_MEMRWA;
+	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_DS,
+			    desc_base, desc_limit, desc_access);
+	if (error)
+		goto done;
+
+	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_ES,
+			    desc_base, desc_limit, desc_access);
+	if (error)
+		goto done;
+
+	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_FS,
+			    desc_base, desc_limit, desc_access);
+	if (error)
+		goto done;
+
+	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_GS,
+			    desc_base, desc_limit, desc_access);
+	if (error)
+		goto done;
+
+	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_SS,
+			    desc_base, desc_limit, desc_access);
+	if (error)
+		goto done;
+
+	desc_base = tssbase;
+	desc_limit = I386_TSS_SIZE - 1;
+	desc_access = DESC_PRESENT | SDT_SYS386BSY;
+	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_TR,
+			    desc_base, desc_limit, desc_access);
+	if (error)
+		goto done;
+
+	
+	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_LDTR, 0, 0,
+			    DESC_UNUSABLE);
+	if (error)
+		goto done;
+
+	gsel = GSEL(GUEST_CODE_SEL, SEL_KPL);
+	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CS, gsel)) != 0)
+		goto done;
+	
+	gsel = GSEL(GUEST_DATA_SEL, SEL_KPL);
+	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_DS, gsel)) != 0)
+		goto done;
+	
+	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_ES, gsel)) != 0)
+		goto done;
+
+	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_FS, gsel)) != 0)
+		goto done;
+	
+	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_GS, gsel)) != 0)
+		goto done;
+	
+	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_SS, gsel)) != 0)
+		goto done;
+
+	gsel = GSEL(GUEST_TSS_SEL, SEL_KPL);
+	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_TR, gsel)) != 0)
+		goto done;
+
+	/* LDTR is pointing to the null selector */
+	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_LDTR, 0)) != 0)
+		goto done;
+
+	/* entry point */
+	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RIP, eip)) != 0)
+		goto done;
+
+	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RSP, esp)) != 0)
+		goto done;
+
+	error = 0;
+done:
+	return (error);
+}
 
 void     
 vm_setup_freebsd_gdt(uint64_t *gdtr)
@@ -168,7 +330,7 @@ vm_setup_freebsd_registers(struct vmctx 
 		goto done;
 
 	desc_base = gdtbase;
-	desc_limit = GUEST_GDTR_LIMIT;
+	desc_limit = GUEST_GDTR_LIMIT64;
 	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_GDTR,
 			    desc_base, desc_limit, 0);
 	if (error != 0)

Modified: stable/10/sys/amd64/include/vmm.h
==============================================================================
--- stable/10/sys/amd64/include/vmm.h	Thu Jun 12 14:20:58 2014	(r267398)
+++ stable/10/sys/amd64/include/vmm.h	Thu Jun 12 15:20:59 2014	(r267399)
@@ -323,6 +323,8 @@ struct vm_exit {
 			uint64_t	gpa;
 			uint64_t	gla;
 			uint64_t	cr3;
+			enum vie_cpu_mode cpu_mode;
+			enum vie_paging_mode paging_mode;
 			struct vie	vie;
 		} inst_emul;
 		/*

Modified: stable/10/sys/amd64/include/vmm_instruction_emul.h
==============================================================================
--- stable/10/sys/amd64/include/vmm_instruction_emul.h	Thu Jun 12 14:20:58 2014	(r267398)
+++ stable/10/sys/amd64/include/vmm_instruction_emul.h	Thu Jun 12 15:20:59 2014	(r267399)
@@ -29,6 +29,18 @@
 #ifndef	_VMM_INSTRUCTION_EMUL_H_
 #define	_VMM_INSTRUCTION_EMUL_H_
 
+enum vie_cpu_mode {
+	CPU_MODE_COMPATIBILITY,		/* IA-32E mode (CS.L = 0) */
+	CPU_MODE_64BIT,			/* IA-32E mode (CS.L = 1) */
+};
+
+enum vie_paging_mode {
+	PAGING_MODE_FLAT,
+	PAGING_MODE_32,
+	PAGING_MODE_PAE,
+	PAGING_MODE_64,
+};
+
 /*
  * The data structures 'vie' and 'vie_op' are meant to be opaque to the
  * consumers of instruction decoding. The only reason why their contents
@@ -107,7 +119,7 @@ int vmm_emulate_instruction(void *vm, in
  */
 int vmm_fetch_instruction(struct vm *vm, int cpuid,
 			  uint64_t rip, int inst_length, uint64_t cr3,
-			  struct vie *vie);
+			  enum vie_paging_mode paging_mode, struct vie *vie);
 
 void vie_init(struct vie *vie);
 
@@ -123,8 +135,8 @@ void vie_init(struct vie *vie);
  * in VIE_INVALID_GLA instead.
  */
 #define	VIE_INVALID_GLA		(1UL << 63)	/* a non-canonical address */
-int vmm_decode_instruction(struct vm *vm, int cpuid,
-			   uint64_t gla, struct vie *vie);
+int vmm_decode_instruction(struct vm *vm, int cpuid, uint64_t gla,
+			   enum vie_cpu_mode cpu_mode, struct vie *vie);
 #endif	/* _KERNEL */
 
 #endif	/* _VMM_INSTRUCTION_EMUL_H_ */

Modified: stable/10/sys/amd64/vmm/intel/vmx.c
==============================================================================
--- stable/10/sys/amd64/vmm/intel/vmx.c	Thu Jun 12 14:20:58 2014	(r267398)
+++ stable/10/sys/amd64/vmm/intel/vmx.c	Thu Jun 12 15:20:59 2014	(r267399)
@@ -1337,6 +1337,30 @@ vmx_emulate_cr_access(struct vmx *vmx, i
 	return (HANDLED);
 }
 
+static enum vie_cpu_mode
+vmx_cpu_mode(void)
+{
+
+	if (vmcs_read(VMCS_GUEST_IA32_EFER) & EFER_LMA)
+		return (CPU_MODE_64BIT);
+	else
+		return (CPU_MODE_COMPATIBILITY);
+}
+
+static enum vie_paging_mode
+vmx_paging_mode(void)
+{
+
+	if (!(vmcs_read(VMCS_GUEST_CR0) & CR0_PG))
+		return (PAGING_MODE_FLAT);
+	if (!(vmcs_read(VMCS_GUEST_CR4) & CR4_PAE))
+		return (PAGING_MODE_32);
+	if (vmcs_read(VMCS_GUEST_IA32_EFER) & EFER_LME)
+		return (PAGING_MODE_64);
+	else
+		return (PAGING_MODE_PAE);
+}
+
 static int
 ept_fault_type(uint64_t ept_qual)
 {
@@ -1496,6 +1520,8 @@ vmx_handle_apic_access(struct vmx *vmx, 
 		vmexit->u.inst_emul.gpa = DEFAULT_APIC_BASE + offset;
 		vmexit->u.inst_emul.gla = VIE_INVALID_GLA;
 		vmexit->u.inst_emul.cr3 = vmcs_guest_cr3();
+		vmexit->u.inst_emul.cpu_mode = vmx_cpu_mode();
+		vmexit->u.inst_emul.paging_mode = vmx_paging_mode();
 	}
 
 	/*
@@ -1714,6 +1740,8 @@ vmx_exit_process(struct vmx *vmx, int vc
 			vmexit->u.inst_emul.gpa = gpa;
 			vmexit->u.inst_emul.gla = vmcs_gla();
 			vmexit->u.inst_emul.cr3 = vmcs_guest_cr3();
+			vmexit->u.inst_emul.cpu_mode = vmx_cpu_mode();
+			vmexit->u.inst_emul.paging_mode = vmx_paging_mode();
 			vmm_stat_incr(vmx->vm, vcpu, VMEXIT_INST_EMUL, 1);
 		}
 		/*

Modified: stable/10/sys/amd64/vmm/vmm.c
==============================================================================
--- stable/10/sys/amd64/vmm/vmm.c	Thu Jun 12 14:20:58 2014	(r267398)
+++ stable/10/sys/amd64/vmm/vmm.c	Thu Jun 12 15:20:59 2014	(r267399)
@@ -1082,6 +1082,8 @@ vm_handle_inst_emul(struct vm *vm, int v
 	struct vm_exit *vme;
 	int error, inst_length;
 	uint64_t rip, gla, gpa, cr3;
+	enum vie_cpu_mode cpu_mode;
+	enum vie_paging_mode paging_mode;
 	mem_region_read_t mread;
 	mem_region_write_t mwrite;
 
@@ -1094,15 +1096,18 @@ vm_handle_inst_emul(struct vm *vm, int v
 	gla = vme->u.inst_emul.gla;
 	gpa = vme->u.inst_emul.gpa;
 	cr3 = vme->u.inst_emul.cr3;
+	cpu_mode = vme->u.inst_emul.cpu_mode;
+	paging_mode = vme->u.inst_emul.paging_mode;
 	vie = &vme->u.inst_emul.vie;
 
 	vie_init(vie);
 
 	/* Fetch, decode and emulate the faulting instruction */
-	if (vmm_fetch_instruction(vm, vcpuid, rip, inst_length, cr3, vie) != 0)
+	if (vmm_fetch_instruction(vm, vcpuid, rip, inst_length, cr3,
+	    paging_mode, vie) != 0)
 		return (EFAULT);
 
-	if (vmm_decode_instruction(vm, vcpuid, gla, vie) != 0)
+	if (vmm_decode_instruction(vm, vcpuid, gla, cpu_mode, vie) != 0)
 		return (EFAULT);
 
 	/* return to userland unless this is an in-kernel emulated device */

Modified: stable/10/sys/amd64/vmm/vmm_instruction_emul.c
==============================================================================
--- stable/10/sys/amd64/vmm/vmm_instruction_emul.c	Thu Jun 12 14:20:58 2014	(r267398)
+++ stable/10/sys/amd64/vmm/vmm_instruction_emul.c	Thu Jun 12 15:20:59 2014	(r267399)
@@ -49,11 +49,6 @@ __FBSDID("$FreeBSD$");
 #include <vmmapi.h>
 #endif	/* _KERNEL */
 
-enum cpu_mode {
-	CPU_MODE_COMPATIBILITY,		/* IA-32E mode (CS.L = 0) */
-	CPU_MODE_64BIT,			/* IA-32E mode (CS.L = 1) */
-};
-
 /* struct vie_op.op_type */
 enum {
 	VIE_OP_TYPE_NONE = 0,
@@ -578,16 +573,76 @@ vie_init(struct vie *vie)
 
 static int
 gla2gpa(struct vm *vm, uint64_t gla, uint64_t ptpphys,
-	uint64_t *gpa, uint64_t *gpaend)
+	uint64_t *gpa, enum vie_paging_mode paging_mode)
 {
 	int nlevels, ptpshift, ptpindex;
 	uint64_t *ptpbase, pte, pgsize;
+	uint32_t *ptpbase32, pte32;
 	void *cookie;
 
-	/*
-	 * XXX assumes 64-bit guest with 4 page walk levels
-	 */
-	nlevels = 4;
+	if (paging_mode == PAGING_MODE_FLAT) {
+		*gpa = gla;
+		return (0);
+	}
+
+	if (paging_mode == PAGING_MODE_32) {
+		nlevels = 2;
+		while (--nlevels >= 0) {
+			/* Zero out the lower 12 bits. */
+			ptpphys &= ~0xfff;
+
+			ptpbase32 = vm_gpa_hold(vm, ptpphys, PAGE_SIZE,
+						VM_PROT_READ, &cookie);
+			
+			if (ptpbase32 == NULL)
+				goto error;
+
+			ptpshift = PAGE_SHIFT + nlevels * 10;
+			ptpindex = (gla >> ptpshift) & 0x3FF;
+			pgsize = 1UL << ptpshift;
+
+			pte32 = ptpbase32[ptpindex];
+
+			vm_gpa_release(cookie);
+
+			if ((pte32 & PG_V) == 0)
+				goto error;
+
+			if (pte32 & PG_PS)
+				break;
+
+			ptpphys = pte32;
+		}
+
+		/* Zero out the lower 'ptpshift' bits */
+		pte32 >>= ptpshift; pte32 <<= ptpshift;
+		*gpa = pte32 | (gla & (pgsize - 1));
+		return (0);
+	}
+
+	if (paging_mode == PAGING_MODE_PAE) {
+		/* Zero out the lower 5 bits and the upper 12 bits */
+		ptpphys >>= 5; ptpphys <<= 17; ptpphys >>= 12;
+
+		ptpbase = vm_gpa_hold(vm, ptpphys, sizeof(*ptpbase) * 4,
+				      VM_PROT_READ, &cookie);
+		if (ptpbase == NULL)
+			goto error;
+
+		ptpindex = (gla >> 30) & 0x3;
+
+		pte = ptpbase[ptpindex];
+
+		vm_gpa_release(cookie);
+
+		if ((pte & PG_V) == 0)
+			goto error;
+
+		ptpphys = pte;
+
+		nlevels = 2;
+	} else
+		nlevels = 4;
 	while (--nlevels >= 0) {
 		/* Zero out the lower 12 bits and the upper 12 bits */
 		ptpphys >>= 12; ptpphys <<= 24; ptpphys >>= 12;
@@ -621,7 +676,6 @@ gla2gpa(struct vm *vm, uint64_t gla, uin
 	/* Zero out the lower 'ptpshift' bits and the upper 12 bits */
 	pte >>= ptpshift; pte <<= (ptpshift + 12); pte >>= 12;
 	*gpa = pte | (gla & (pgsize - 1));
-	*gpaend = pte + pgsize;
 	return (0);
 
 error:
@@ -630,10 +684,11 @@ error:
 
 int
 vmm_fetch_instruction(struct vm *vm, int cpuid, uint64_t rip, int inst_length,
-		      uint64_t cr3, struct vie *vie)
+		      uint64_t cr3, enum vie_paging_mode paging_mode,
+		      struct vie *vie)
 {
 	int n, err, prot;
-	uint64_t gpa, gpaend, off;
+	uint64_t gpa, off;
 	void *hpa, *cookie;
 
 	/*
@@ -646,7 +701,7 @@ vmm_fetch_instruction(struct vm *vm, int
 
 	/* Copy the instruction into 'vie' */
 	while (vie->num_valid < inst_length) {
-		err = gla2gpa(vm, rip, cr3, &gpa, &gpaend);
+		err = gla2gpa(vm, rip, cr3, &gpa, paging_mode);
 		if (err)
 			break;
 
@@ -749,15 +804,9 @@ decode_opcode(struct vie *vie)
 }
 
 static int
-decode_modrm(struct vie *vie)
+decode_modrm(struct vie *vie, enum vie_cpu_mode cpu_mode)
 {
 	uint8_t x;
-	enum cpu_mode cpu_mode;
-
-	/*
-	 * XXX assuming that guest is in IA-32E 64-bit mode
-	 */
-	cpu_mode = CPU_MODE_64BIT;
 
 	if (vie_peek(vie, &x))
 		return (-1);
@@ -1034,16 +1083,19 @@ verify_gla(struct vm *vm, int cpuid, uin
 }
 
 int
-vmm_decode_instruction(struct vm *vm, int cpuid, uint64_t gla, struct vie *vie)
+vmm_decode_instruction(struct vm *vm, int cpuid, uint64_t gla,
+		       enum vie_cpu_mode cpu_mode, struct vie *vie)
 {
 
-	if (decode_rex(vie))
-		return (-1);
+	if (cpu_mode == CPU_MODE_64BIT) {
+		if (decode_rex(vie))
+			return (-1);
+	}
 
 	if (decode_opcode(vie))
 		return (-1);
 
-	if (decode_modrm(vie))
+	if (decode_modrm(vie, cpu_mode))
 		return (-1);
 
 	if (decode_sib(vie))

Modified: stable/10/sys/boot/common/load_elf32.c
==============================================================================
--- stable/10/sys/boot/common/load_elf32.c	Thu Jun 12 14:20:58 2014	(r267398)
+++ stable/10/sys/boot/common/load_elf32.c	Thu Jun 12 15:20:59 2014	(r267399)
@@ -2,5 +2,6 @@
 __FBSDID("$FreeBSD$");
 
 #define __ELF_WORD_SIZE 32
+#define	_MACHINE_ELF_WANT_32BIT
 
 #include "load_elf.c"

Modified: stable/10/sys/boot/common/load_elf32_obj.c
==============================================================================
--- stable/10/sys/boot/common/load_elf32_obj.c	Thu Jun 12 14:20:58 2014	(r267398)
+++ stable/10/sys/boot/common/load_elf32_obj.c	Thu Jun 12 15:20:59 2014	(r267399)
@@ -2,5 +2,6 @@
 __FBSDID("$FreeBSD$");
 
 #define __ELF_WORD_SIZE 32
+#define	_MACHINE_ELF_WANT_32BIT
 
 #include "load_elf_obj.c"

Modified: stable/10/sys/boot/userboot/userboot/Makefile
==============================================================================
--- stable/10/sys/boot/userboot/userboot/Makefile	Thu Jun 12 14:20:58 2014	(r267398)
+++ stable/10/sys/boot/userboot/userboot/Makefile	Thu Jun 12 15:20:59 2014	(r267399)
@@ -11,6 +11,7 @@ STRIP=
 LIBDIR=		/boot
 
 SRCS=		autoload.c
+SRCS+=		biossmap.c
 SRCS+=		bootinfo.c
 SRCS+=		bootinfo32.c
 SRCS+=		bootinfo64.c

Copied: stable/10/sys/boot/userboot/userboot/biossmap.c (from r261504, head/sys/boot/userboot/userboot/biossmap.c)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ stable/10/sys/boot/userboot/userboot/biossmap.c	Thu Jun 12 15:20:59 2014	(r267399, copy of r261504, head/sys/boot/userboot/userboot/biossmap.c)
@@ -0,0 +1,74 @@
+/*-
+ * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stand.h>
+#include <sys/param.h>
+#include <sys/reboot.h>
+#include <sys/linker.h>
+#include <machine/pc/bios.h>
+#include <machine/metadata.h>
+
+#include "bootstrap.h"
+#include "libuserboot.h"
+
+#define GB (1024UL * 1024 * 1024)
+
+void
+bios_addsmapdata(struct preloaded_file *kfp)
+{
+	uint64_t lowmem, highmem;
+	int smapnum, len;
+	struct bios_smap smap[3], *sm;
+
+	CALLBACK(getmem, &lowmem, &highmem);
+
+	sm = &smap[0];
+
+	sm->base = 0;				/* base memory */
+	sm->length = 640 * 1024;
+	sm->type = SMAP_TYPE_MEMORY;
+	sm++;
+
+	sm->base = 0x100000;			/* extended memory */
+	sm->length = lowmem - 0x100000;
+	sm->type = SMAP_TYPE_MEMORY;
+	sm++;
+
+	smapnum = 2;
+
+        if (highmem != 0) {
+                sm->base = 4 * GB;
+                sm->length = highmem;
+                sm->type = SMAP_TYPE_MEMORY;
+		smapnum++;
+        }
+
+        len = smapnum * sizeof(struct bios_smap);
+        file_addmetadata(kfp, MODINFOMD_SMAP, len, &smap[0]);
+}

Modified: stable/10/sys/boot/userboot/userboot/bootinfo32.c
==============================================================================
--- stable/10/sys/boot/userboot/userboot/bootinfo32.c	Thu Jun 12 14:20:58 2014	(r267398)
+++ stable/10/sys/boot/userboot/userboot/bootinfo32.c	Thu Jun 12 15:20:59 2014	(r267399)
@@ -66,7 +66,7 @@ static struct bootinfo  bi;
     COPY32(strlen(s) + 1, a, c);		\
     if (c)					\
         CALLBACK(copyin, s, a, strlen(s) + 1);  \
-    a += roundup(strlen(s) + 1, sizeof(u_long));\
+    a += roundup(strlen(s) + 1, sizeof(uint32_t));\
 }
 
 #define MOD_NAME(a, s, c)	MOD_STR(MODINFO_NAME, a, s, c)
@@ -78,7 +78,7 @@ static struct bootinfo  bi;
     COPY32(sizeof(s), a, c);			\
     if (c)					\
         CALLBACK(copyin, &s, a, sizeof(s));	\
-    a += roundup(sizeof(s), sizeof(u_long));	\
+    a += roundup(sizeof(s), sizeof(uint32_t));	\
 }
 
 #define MOD_ADDR(a, s, c)	MOD_VAR(MODINFO_ADDR, a, s, c)
@@ -89,7 +89,7 @@ static struct bootinfo  bi;
     COPY32(mm->md_size, a, c);			\
     if (c)					\
         CALLBACK(copyin, mm->md_data, a, mm->md_size);    \
-    a += roundup(mm->md_size, sizeof(u_long));\
+    a += roundup(mm->md_size, sizeof(uint32_t));\
 }
 
 #define MOD_END(a, c) {				\
@@ -146,6 +146,7 @@ bi_load32(char *args, int *howtop, int *
     int				bootdevnr, howto;
     char			*kernelname;
     const char			*kernelpath;
+    uint64_t			lowmem, highmem;
 
     howto = bi_getboothowto(args);
 
@@ -198,9 +199,7 @@ bi_load32(char *args, int *howtop, int *
     file_addmetadata(kfp, MODINFOMD_HOWTO, sizeof howto, &howto);
     file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp);
     file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof kernend, &kernend);
-#if 0
     bios_addsmapdata(kfp);
-#endif
 
     /* Figure out the size and location of the metadata */
     *modulep = addr;
@@ -237,11 +236,10 @@ bi_load32(char *args, int *howtop, int *
         bi.bi_bios_geom[i] = bd_getbigeom(i);
 #endif
     bi.bi_size = sizeof(bi);
+    CALLBACK(getmem, &lowmem, &highmem);
     bi.bi_memsizes_valid = 1;
-#if 0
-    bi.bi_basemem = bios_basemem / 1024;
-    bi.bi_extmem = bios_extmem / 1024;
-#endif
+    bi.bi_basemem = 640;
+    bi.bi_extmem = (lowmem - 0x100000) / 1024;
     bi.bi_envp = envp;
     bi.bi_modulep = *modulep;
     bi.bi_kernend = kernend;
@@ -251,7 +249,7 @@ bi_load32(char *args, int *howtop, int *
     /*
      * Copy the legacy bootinfo and kernel name to the guest at 0x2000
      */
-    bi.bi_kernelname = (char *) (0x2000 + sizeof(bi));
+    bi.bi_kernelname = 0x2000 + sizeof(bi);
     CALLBACK(copyin, &bi, 0x2000, sizeof(bi));
     CALLBACK(copyin, kernelname, 0x2000 + sizeof(bi), strlen(kernelname) + 1);
 

Modified: stable/10/sys/boot/userboot/userboot/bootinfo64.c
==============================================================================
--- stable/10/sys/boot/userboot/userboot/bootinfo64.c	Thu Jun 12 14:20:58 2014	(r267398)
+++ stable/10/sys/boot/userboot/userboot/bootinfo64.c	Thu Jun 12 15:20:59 2014	(r267399)
@@ -169,53 +169,6 @@ bi_checkcpu(void)
 #endif
 }
 
-struct smap {
-        uint64_t       base;
-        uint64_t       length;
-        uint32_t       type;
-} __packed;
-
-/* From FreeBSD <machine/pc/bios.h> */
-#define SMAP_TYPE_MEMORY	1
-
-#define GB (1024UL * 1024 * 1024)
-
-#define MODINFOMD_SMAP          0x1001
-
-static void
-bios_addsmapdata(struct preloaded_file *kfp)
-{
-	uint64_t lowmem, highmem;
-	int smapnum, len;
-	struct smap smap[3], *sm;
-
-	CALLBACK(getmem, &lowmem, &highmem);
-
-	sm = &smap[0];
-
-	sm->base = 0;				/* base memory */
-	sm->length = 640 * 1024;
-	sm->type = SMAP_TYPE_MEMORY;
-	sm++;
-
-	sm->base = 0x100000;			/* extended memory */
-	sm->length = lowmem - 0x100000;
-	sm->type = SMAP_TYPE_MEMORY;
-	sm++;
-
-	smapnum = 2;
-
-        if (highmem != 0) {
-                sm->base = 4 * GB;
-                sm->length = highmem;
-                sm->type = SMAP_TYPE_MEMORY;
-		smapnum++;
-        }
-
-        len = smapnum * sizeof (struct smap);
-        file_addmetadata(kfp, MODINFOMD_SMAP, len, &smap[0]);
-}
-
 /*
  * Load the information expected by an amd64 kernel.
  *

Modified: stable/10/sys/boot/userboot/userboot/elf32_freebsd.c
==============================================================================
--- stable/10/sys/boot/userboot/userboot/elf32_freebsd.c	Thu Jun 12 14:20:58 2014	(r267398)
+++ stable/10/sys/boot/userboot/userboot/elf32_freebsd.c	Thu Jun 12 15:20:59 2014	(r267399)
@@ -45,6 +45,9 @@ static int	elf32_obj_exec(struct preload
 struct file_format i386_elf = { elf32_loadfile, elf32_exec };
 struct file_format i386_elf_obj = { elf32_obj_loadfile, elf32_obj_exec };
 
+#define	GUEST_STACK	0x1000		/* Initial stack base */
+#define	GUEST_GDT	0x3000		/* Address of initial GDT */
+
 /*
  * There is an ELF kernel and one or more ELF modules loaded.  
  * We wish to start executing the kernel image, so make such 
@@ -57,7 +60,7 @@ elf32_exec(struct preloaded_file *fp)
 	Elf_Ehdr 		*ehdr;
 	vm_offset_t		entry, bootinfop, modulep, kernend;
 	int			boothowto, err, bootdev;
-	uint32_t		stack[1024];
+	uint32_t		stack[1024], *sp;
 
 
 	if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL)
@@ -78,16 +81,27 @@ elf32_exec(struct preloaded_file *fp)
 	/*
 	 * Build a scratch stack at physical 0x1000
 	 */
-	stack[0] = boothowto;
-	stack[1] = bootdev;
-	stack[2] = 0;
-	stack[3] = 0;
-	stack[4] = 0;
-	stack[5] = bootinfop;
-	stack[6] = modulep;
-	stack[7] = kernend;
-	CALLBACK(copyin, stack, 0x1000, sizeof(stack));
-	CALLBACK(setreg, 4, 0x1000);
+	memset(stack, 0, sizeof(stack));
+	sp = (uint32_t *)((char *)stack + sizeof(stack));
+	*--sp = kernend;
+	*--sp = modulep;
+	*--sp = bootinfop;
+	*--sp = 0;
+	*--sp = 0;
+	*--sp = 0;
+	*--sp = bootdev;
+	*--sp = boothowto;
+
+	/*
+	 * Fake return address to mimic "new" boot blocks.  For more
+	 * details see recover_bootinfo in locore.S.
+	 */
+	*--sp = 0xbeefface;
+	CALLBACK(copyin, stack, GUEST_STACK, sizeof(stack));
+	CALLBACK(setreg, 4, (char *)sp - (char *)stack + GUEST_STACK);
+
+	CALLBACK(setgdt, GUEST_GDT, 8 * 4 - 1);
+
         CALLBACK(exec, entry);
 
 	panic("exec returned");

Modified: stable/10/sys/boot/userboot/userboot/libuserboot.h
==============================================================================
--- stable/10/sys/boot/userboot/userboot/libuserboot.h	Thu Jun 12 14:20:58 2014	(r267398)
+++ stable/10/sys/boot/userboot/userboot/libuserboot.h	Thu Jun 12 15:20:59 2014	(r267399)
@@ -65,3 +65,4 @@ vm_offset_t	bi_copyenv(vm_offset_t addr)
 int	bi_load32(char *args, int *howtop, int *bootdevp, vm_offset_t *bip,
     vm_offset_t *modulep, vm_offset_t *kernend);
 int	bi_load64(char *args, vm_offset_t *modulep, vm_offset_t *kernend);
+void	bios_addsmapdata(struct preloaded_file *kfp);

Modified: stable/10/usr.sbin/bhyveload/bhyveload.c
==============================================================================
--- stable/10/usr.sbin/bhyveload/bhyveload.c	Thu Jun 12 14:20:58 2014	(r267398)
+++ stable/10/usr.sbin/bhyveload/bhyveload.c	Thu Jun 12 15:20:59 2014	(r267399)
@@ -465,7 +465,12 @@ cb_exec(void *arg, uint64_t rip)
 {
 	int error;
 
-	error = vm_setup_freebsd_registers(ctx, BSP, rip, cr3, gdtbase, rsp);
+	if (cr3 == 0)
+		error = vm_setup_freebsd_registers_i386(ctx, BSP, rip, gdtbase,
+		    rsp);
+	else
+		error = vm_setup_freebsd_registers(ctx, BSP, rip, cr3, gdtbase,
+		    rsp);
 	if (error) {
 		perror("vm_setup_freebsd_registers");
 		cb_exit(NULL, USERBOOT_EXIT_QUIT);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201406121520.s5CFKxvA099459>