Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 27 Sep 2012 00:27:58 +0000 (UTC)
From:      Neel Natu <neel@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r240978 - in projects/bhyve/sys/amd64/vmm: . intel
Message-ID:  <201209270027.q8R0RwpD019625@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: neel
Date: Thu Sep 27 00:27:58 2012
New Revision: 240978
URL: http://svn.freebsd.org/changeset/base/240978

Log:
  Intel VT-x provides the length of the instruction at the time of the nested
  page table fault. Use this when fetching the instruction bytes from the guest
  memory.
  
  Also modify the lapic_mmio() API so that a decoded instruction is fed into it
  instead of having it fetch the instruction bytes from the guest. This is
  useful for hardware assists like SVM that provide the faulting instruction
  as part of the vmexit.

Modified:
  projects/bhyve/sys/amd64/vmm/intel/vmx.c
  projects/bhyve/sys/amd64/vmm/vmm_instruction_emul.c
  projects/bhyve/sys/amd64/vmm/vmm_instruction_emul.h
  projects/bhyve/sys/amd64/vmm/vmm_lapic.c
  projects/bhyve/sys/amd64/vmm/vmm_lapic.h

Modified: projects/bhyve/sys/amd64/vmm/intel/vmx.c
==============================================================================
--- projects/bhyve/sys/amd64/vmm/intel/vmx.c	Wed Sep 26 23:07:00 2012	(r240977)
+++ projects/bhyve/sys/amd64/vmm/intel/vmx.c	Thu Sep 27 00:27:58 2012	(r240978)
@@ -1146,9 +1146,11 @@ vmx_emulate_cr_access(struct vmx *vmx, i
 
 static int
 vmx_lapic_fault(struct vm *vm, int cpu,
-		uint64_t gpa, uint64_t rip, uint64_t cr3, uint64_t ept_qual)
+		uint64_t gpa, uint64_t rip, int inst_length,
+		uint64_t cr3, uint64_t ept_qual)
 {
 	int read, write, handled;
+	struct vie vie;
 
 	/*
 	 * For this to be a legitimate access to the local apic:
@@ -1180,7 +1182,14 @@ vmx_lapic_fault(struct vm *vm, int cpu,
 		return (UNHANDLED);
 	}
 
-	handled = lapic_mmio(vm, cpu, gpa - DEFAULT_APIC_BASE, read, rip, cr3);
+	/* Fetch, decode and emulate the faulting instruction */
+	if (vmm_fetch_instruction(vm, rip, inst_length, cr3, &vie) != 0)
+		return (UNHANDLED);
+
+	if (vmm_decode_instruction(&vie) != 0)
+		return (UNHANDLED);
+
+	handled = lapic_mmio(vm, cpu, gpa - DEFAULT_APIC_BASE, read, &vie);
 
 	return (handled);
 }
@@ -1275,7 +1284,8 @@ vmx_exit_process(struct vmx *vmx, int vc
 		gpa = vmcs_gpa();
 		cr3 = vmcs_guest_cr3();
 		handled = vmx_lapic_fault(vmx->vm, vcpu,
-					  gpa, vmexit->rip, cr3, qual);
+					  gpa, vmexit->rip, vmexit->inst_length,
+					  cr3, qual);
 		if (!handled) {
 			vmexit->exitcode = VM_EXITCODE_PAGING;
 			vmexit->u.paging.cr3 = cr3;

Modified: projects/bhyve/sys/amd64/vmm/vmm_instruction_emul.c
==============================================================================
--- projects/bhyve/sys/amd64/vmm/vmm_instruction_emul.c	Wed Sep 26 23:07:00 2012	(r240977)
+++ projects/bhyve/sys/amd64/vmm/vmm_instruction_emul.c	Thu Sep 27 00:27:58 2012	(r240978)
@@ -128,9 +128,9 @@ error:
 	return (-1);
 }
 
-void
-vmm_fetch_instruction(struct vm *vm, uint64_t rip, uint64_t cr3,
-		      struct vie *vie)
+int
+vmm_fetch_instruction(struct vm *vm, uint64_t rip, int inst_length,
+		      uint64_t cr3, struct vie *vie)
 {
 	int n, err;
 	uint64_t hpa, gpa, gpaend;
@@ -139,17 +139,18 @@ vmm_fetch_instruction(struct vm *vm, uin
 	 * XXX cache previously fetched instructions using 'rip' as the tag
 	 */
 
+	if (inst_length > VIE_INST_SIZE)
+		panic("vmm_fetch_instruction: invalid length %d", inst_length);
+
 	vie_init(vie);
 
-	/*
-	 * Copy up to 15 bytes of the instruction stream into 'vie'
-	 */
-	while (vie->num_valid < VIE_INST_SIZE) {
+	/* Copy the instruction into 'vie' */
+	while (vie->num_valid < inst_length) {
 		err = gla2gpa(vm, rip, cr3, &gpa, &gpaend);
 		if (err)
 			break;
 
-		n = min(VIE_INST_SIZE - vie->num_valid, gpaend - gpa);
+		n = min(inst_length - vie->num_valid, gpaend - gpa);
 
 		hpa = vm_gpa2hpa(vm, gpa, n);
 		if (hpa == -1)
@@ -160,6 +161,11 @@ vmm_fetch_instruction(struct vm *vm, uin
 		rip += n;
 		vie->num_valid += n;
 	}
+
+	if (vie->num_valid == inst_length)
+		return (0);
+	else
+		return (-1);
 }
 
 static int

Modified: projects/bhyve/sys/amd64/vmm/vmm_instruction_emul.h
==============================================================================
--- projects/bhyve/sys/amd64/vmm/vmm_instruction_emul.h	Wed Sep 26 23:07:00 2012	(r240977)
+++ projects/bhyve/sys/amd64/vmm/vmm_instruction_emul.h	Thu Sep 27 00:27:58 2012	(r240978)
@@ -83,8 +83,8 @@ struct vie {
 
 struct vm;
 
-void	vmm_fetch_instruction(struct vm *vm, uint64_t rip, uint64_t cr3,
-			      struct vie *vie);
+int	vmm_fetch_instruction(struct vm *vm, uint64_t rip, int inst_length,
+			      uint64_t cr3, struct vie *vie);
 
 int	vmm_decode_instruction(struct vie *vie);
 

Modified: projects/bhyve/sys/amd64/vmm/vmm_lapic.c
==============================================================================
--- projects/bhyve/sys/amd64/vmm/vmm_lapic.c	Wed Sep 26 23:07:00 2012	(r240977)
+++ projects/bhyve/sys/amd64/vmm/vmm_lapic.c	Thu Sep 27 00:27:58 2012	(r240978)
@@ -177,25 +177,18 @@ lapic_wrmsr(struct vm *vm, int cpu, u_in
 }
 
 int
-lapic_mmio(struct vm *vm, int cpu, u_int offset, int read,
-	   uint64_t rip, uint64_t cr3)
+lapic_mmio(struct vm *vm, int cpu, u_int offset, int read, struct vie *vie)
 {
 	int handled, error;
 	uint64_t val;
-	struct vie vie;
 	struct vlapic *vlapic;
 
 	const int UNHANDLED = 0;
 
 	vlapic = vm_lapic(vm, cpu);
 
-	vmm_fetch_instruction(vm, rip, cr3, &vie);
-
-	if (vmm_decode_instruction(&vie) != 0)
-		return (UNHANDLED);
-
 	/* Only 32-bit accesses to local apic */
-	if (vie.op_size != VIE_OP_SIZE_32BIT)
+	if (vie->op_size != VIE_OP_SIZE_32BIT)
 		return (UNHANDLED);
 
 	/*
@@ -207,35 +200,35 @@ lapic_mmio(struct vm *vm, int cpu, u_int
 	 * This is a limitation of the vm_set_register() API
 	 * and can be fixed if necessary.
 	 */
-	if (vie.operand_register == VM_REG_GUEST_RSP)
+	if (vie->operand_register == VM_REG_GUEST_RSP)
 		return (UNHANDLED);
 
 	if (read) {
-		if ((vie.opcode_flags & VIE_F_TO_REG) == 0)
+		if ((vie->opcode_flags & VIE_F_TO_REG) == 0)
 			return (UNHANDLED);
 
-		if (vie.operand_register >= VM_REG_LAST)
+		if (vie->operand_register >= VM_REG_LAST)
 			return (UNHANDLED);
 
 		handled = lapic_read(vlapic, offset, &val);
 		if (handled) {
-			error = vm_set_register(vm, cpu, vie.operand_register,
+			error = vm_set_register(vm, cpu, vie->operand_register,
 						val);
 			if (error)
 				panic("lapic_mmio: error %d setting gpr %d",
-				      error, vie.operand_register);
+				      error, vie->operand_register);
 		}
 	} else {
-		if ((vie.opcode_flags & VIE_F_FROM_REG) &&
-		    (vie.operand_register < VM_REG_LAST)) {
-			error = vm_get_register(vm, cpu, vie.operand_register,
+		if ((vie->opcode_flags & VIE_F_FROM_REG) &&
+		    (vie->operand_register < VM_REG_LAST)) {
+			error = vm_get_register(vm, cpu, vie->operand_register,
 						&val);
 			if (error) {
 				panic("lapic_mmio: error %d getting gpr %d",
-				      error, vie.operand_register);
+				      error, vie->operand_register);
 			}
-		} else if (vie.opcode_flags & VIE_F_FROM_IMM) {
-			val = vie.immediate;
+		} else if (vie->opcode_flags & VIE_F_FROM_IMM) {
+			val = vie->immediate;
 		} else {
 			return (UNHANDLED);
 		}

Modified: projects/bhyve/sys/amd64/vmm/vmm_lapic.h
==============================================================================
--- projects/bhyve/sys/amd64/vmm/vmm_lapic.h	Wed Sep 26 23:07:00 2012	(r240977)
+++ projects/bhyve/sys/amd64/vmm/vmm_lapic.h	Thu Sep 27 00:27:58 2012	(r240978)
@@ -30,13 +30,13 @@
 #define	_VMM_LAPIC_H_
 
 struct vm;
+struct vie;
 
 boolean_t lapic_msr(u_int num);
 int	lapic_rdmsr(struct vm *vm, int cpu, u_int msr, uint64_t *rval);
 int	lapic_wrmsr(struct vm *vm, int cpu, u_int msr, uint64_t wval);
 
-int	lapic_mmio(struct vm *vm, int cpu, u_int offset, int read,
-		   uint64_t rip, uint64_t cr3);
+int	lapic_mmio(struct vm *vm, int cpu, u_int offset, int rd, struct vie *);
 
 void	lapic_timer_tick(struct vm *vm, int cpu);
 



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