svn commit: r264648 - in head: sys/amd64/vmm sys/amd64/vmm/io usr.sbin/bhyve

Tycho Nightingale tychon at FreeBSD.org
Fri Apr 18 15:22:58 UTC 2014


Author: tychon
Date: Fri Apr 18 15:22:56 2014
New Revision: 264648
URL: http://svnweb.freebsd.org/changeset/base/264648

Log:
  Respect the destination operand size of the 'Input from Port' instruction.
  
  Approved by:	grehan (co-mentor)

Modified:
  head/sys/amd64/vmm/io/vatpic.c
  head/sys/amd64/vmm/io/vatpic.h
  head/sys/amd64/vmm/io/vatpit.c
  head/sys/amd64/vmm/io/vatpit.h
  head/sys/amd64/vmm/vmm_ioport.c
  head/sys/amd64/vmm/vmm_ioport.h
  head/usr.sbin/bhyve/inout.c

Modified: head/sys/amd64/vmm/io/vatpic.c
==============================================================================
--- head/sys/amd64/vmm/io/vatpic.c	Fri Apr 18 14:59:39 2014	(r264647)
+++ head/sys/amd64/vmm/io/vatpic.c	Fri Apr 18 15:22:56 2014	(r264648)
@@ -517,7 +517,8 @@ vatpic_intr_accepted(struct vm *vm, int 
 }
 
 static int
-vatpic_read(struct vatpic *vatpic, struct atpic *atpic, struct vm_exit *vmexit)
+vatpic_read(struct vatpic *vatpic, struct atpic *atpic, bool in, int port,
+	    int bytes, uint32_t *eax)
 {
 	VATPIC_LOCK(vatpic);
 
@@ -526,16 +527,16 @@ vatpic_read(struct vatpic *vatpic, struc
 		VATPIC_UNLOCK(vatpic);
 		return (-1);
 	} else {
-		if (vmexit->u.inout.port & ICU_IMR_OFFSET) {
+		if (port & ICU_IMR_OFFSET) {
 			/* read interrrupt mask register */
-			vmexit->u.inout.eax = atpic->mask;
+			*eax = atpic->mask;
 		} else {
 			if (atpic->rd_cmd_reg == OCW3_RIS) {
 				/* read interrupt service register */
-				vmexit->u.inout.eax = atpic->service;
+				*eax = atpic->service;
 			} else {
 				/* read interrupt request register */
-				vmexit->u.inout.eax = atpic->request;
+				*eax = atpic->request;
 			}
 		}
 	}
@@ -547,17 +548,17 @@ vatpic_read(struct vatpic *vatpic, struc
 }
 
 static int
-vatpic_write(struct vatpic *vatpic, struct atpic *atpic,
-    struct vm_exit *vmexit)
+vatpic_write(struct vatpic *vatpic, struct atpic *atpic, bool in, int port,
+    int bytes, uint32_t *eax)
 {
 	int error;
 	uint8_t val;
 
-	val = vmexit->u.inout.eax;
+	val = *eax;
 
 	VATPIC_LOCK(vatpic);
 
-	if (vmexit->u.inout.port & ICU_IMR_OFFSET) {
+	if (port & ICU_IMR_OFFSET) {
 		if (atpic->ready) {
 			error = vatpic_ocw1(vatpic, atpic, val);
 		} else {
@@ -594,7 +595,8 @@ vatpic_write(struct vatpic *vatpic, stru
 }
 
 int
-vatpic_master_handler(void *vm, int vcpuid, struct vm_exit *vmexit)
+vatpic_master_handler(void *vm, int vcpuid, bool in, int port, int bytes,
+    uint32_t *eax)
 {
 	struct vatpic *vatpic;
 	struct atpic *atpic;
@@ -602,18 +604,19 @@ vatpic_master_handler(void *vm, int vcpu
 	vatpic = vm_atpic(vm);
 	atpic = &vatpic->atpic[0];
 
-	if (vmexit->u.inout.bytes != 1)
+	if (bytes != 1)
 		return (-1);
  
-	if (vmexit->u.inout.in) {
-		return (vatpic_read(vatpic, atpic, vmexit));
+	if (in) {
+		return (vatpic_read(vatpic, atpic, in, port, bytes, eax));
 	}
  
-	return (vatpic_write(vatpic, atpic, vmexit));
+	return (vatpic_write(vatpic, atpic, in, port, bytes, eax));
 }
 
 int
-vatpic_slave_handler(void *vm, int vcpuid, struct vm_exit *vmexit)
+vatpic_slave_handler(void *vm, int vcpuid, bool in, int port, int bytes,
+    uint32_t *eax)
 {
 	struct vatpic *vatpic;
 	struct atpic *atpic;
@@ -621,35 +624,36 @@ vatpic_slave_handler(void *vm, int vcpui
 	vatpic = vm_atpic(vm);
 	atpic = &vatpic->atpic[1];
 
-	if (vmexit->u.inout.bytes != 1)
+	if (bytes != 1)
 		return (-1);
 
-	if (vmexit->u.inout.in) {
-		return (vatpic_read(vatpic, atpic, vmexit));
+	if (in) {
+		return (vatpic_read(vatpic, atpic, in, port, bytes, eax));
 	}
 
-	return (vatpic_write(vatpic, atpic, vmexit));
+	return (vatpic_write(vatpic, atpic, in, port, bytes, eax));
 }
 
 int
-vatpic_elc_handler(void *vm, int vcpuid, struct vm_exit *vmexit)
+vatpic_elc_handler(void *vm, int vcpuid, bool in, int port, int bytes,
+    uint32_t *eax)
 {
 	struct vatpic *vatpic;
 	bool is_master;
 
 	vatpic = vm_atpic(vm);
-	is_master = (vmexit->u.inout.port == IO_ELCR1);
+	is_master = (port == IO_ELCR1);
 
-	if (vmexit->u.inout.bytes != 1)
+	if (bytes != 1)
 		return (-1);
 
 	VATPIC_LOCK(vatpic);
 
-	if (vmexit->u.inout.in) {
+	if (in) {
 		if (is_master)
-			vmexit->u.inout.eax = vatpic->elc[0];
+			*eax = vatpic->elc[0];
 		else
-			vmexit->u.inout.eax = vatpic->elc[1];
+			*eax = vatpic->elc[1];
 	} else {
 		/*
 		 * For the master PIC the cascade channel (IRQ2), the
@@ -662,9 +666,9 @@ vatpic_elc_handler(void *vm, int vcpuid,
 		 * be programmed for level mode.
 		 */
 		if (is_master)
-			vatpic->elc[0] = (vmexit->u.inout.eax & 0xf8);
+			vatpic->elc[0] = (*eax & 0xf8);
 		else
-			vatpic->elc[1] = (vmexit->u.inout.eax & 0xde);
+			vatpic->elc[1] = (*eax & 0xde);
 	}
 
 	VATPIC_UNLOCK(vatpic);

Modified: head/sys/amd64/vmm/io/vatpic.h
==============================================================================
--- head/sys/amd64/vmm/io/vatpic.h	Fri Apr 18 14:59:39 2014	(r264647)
+++ head/sys/amd64/vmm/io/vatpic.h	Fri Apr 18 15:22:56 2014	(r264648)
@@ -39,9 +39,12 @@
 struct vatpic *vatpic_init(struct vm *vm);
 void vatpic_cleanup(struct vatpic *vatpic);
 
-int vatpic_master_handler(void *vm, int vcpuid, struct vm_exit *vmexit);
-int vatpic_slave_handler(void *vm, int vcpuid, struct vm_exit *vmexit);
-int vatpic_elc_handler(void *vm, int vcpuid, struct vm_exit *vmexit);
+int vatpic_master_handler(void *vm, int vcpuid, bool in, int port, int bytes,
+    uint32_t *eax);
+int vatpic_slave_handler(void *vm, int vcpuid, bool in, int port, int bytes,
+    uint32_t *eax);
+int vatpic_elc_handler(void *vm, int vcpuid, bool in, int port, int bytes,
+    uint32_t *eax);
 
 int vatpic_assert_irq(struct vm *vm, int irq);
 int vatpic_deassert_irq(struct vm *vm, int irq);

Modified: head/sys/amd64/vmm/io/vatpit.c
==============================================================================
--- head/sys/amd64/vmm/io/vatpit.c	Fri Apr 18 14:59:39 2014	(r264647)
+++ head/sys/amd64/vmm/io/vatpit.c	Fri Apr 18 15:22:56 2014	(r264648)
@@ -253,24 +253,23 @@ vatpit_update_mode(struct vatpit *vatpit
 }
 
 int
-vatpit_handler(void *vm, int vcpuid, struct vm_exit *vmexit)
+vatpit_handler(void *vm, int vcpuid, bool in, int port, int bytes,
+    uint32_t *eax)
 {
 	struct vatpit *vatpit;
 	struct channel *c;
-	int port;
 	uint8_t val;
 	int error;
 
 	vatpit = vm_atpit(vm);
 
-	if (vmexit->u.inout.bytes != 1)
+	if (bytes != 1)
 		return (-1);
 
-	val = vmexit->u.inout.eax;
-	port = vmexit->u.inout.port;
+	val = *eax;
 
 	if (port == TIMER_MODE) {
-		if (vmexit->u.inout.in) {
+		if (in) {
 			VM_CTR0(vatpit->vm, "vatpit attempt to read mode");
 			return (-1);
 		}
@@ -283,12 +282,12 @@ vatpit_handler(void *vm, int vcpuid, str
 	}
 
 	/* counter ports */
-	KASSERT(port >= TIMER_CNTR0 && vmexit->u.inout.port <= TIMER_CNTR2,
+	KASSERT(port >= TIMER_CNTR0 && port <= TIMER_CNTR2,
 	    ("invalid port 0x%x", port));
 	c = &vatpit->channel[port - TIMER_CNTR0];
 
 	VATPIT_LOCK(vatpit);
-	if (vmexit->u.inout.in) {
+	if (in) {
 		/*
 		 * The spec says that once the output latch is completely
 		 * read it should revert to "following" the counter. Use
@@ -303,12 +302,12 @@ vatpit_handler(void *vm, int vcpuid, str
 			if (c->frbyte)
 				tmp >>= 8;
 			tmp &= 0xff;
-			vmexit->u.inout.eax = tmp;
+			*eax = tmp;
 			c->frbyte ^= 1;
 		}  else
-			vmexit->u.inout.eax = c->ol[--c->olbyte];
+			*eax = c->ol[--c->olbyte];
 	} else {
-		c->cr[c->crbyte++] = vmexit->u.inout.eax;
+		c->cr[c->crbyte++] = *eax;
 		if (c->crbyte == 2) {
 			c->frbyte = 0;
 			c->crbyte = 0;
@@ -329,18 +328,19 @@ vatpit_handler(void *vm, int vcpuid, str
 }
 
 int
-vatpit_nmisc_handler(void *vm, int vcpuid, struct vm_exit *vmexit)
+vatpit_nmisc_handler(void *vm, int vcpuid, bool in, int port, int bytes,
+    uint32_t *eax)
 {
 	struct vatpit *vatpit;
 
 	vatpit = vm_atpit(vm);
 
-	if (vmexit->u.inout.in) {
+	if (in) {
 			VATPIT_LOCK(vatpit);
 			if (vatpit_get_out(vatpit, 2))
-				vmexit->u.inout.eax = TMR2_OUT_STS;
+				*eax = TMR2_OUT_STS;
 			else
-				vmexit->u.inout.eax = 0;
+				*eax = 0;
 
 			VATPIT_UNLOCK(vatpit);
 	}

Modified: head/sys/amd64/vmm/io/vatpit.h
==============================================================================
--- head/sys/amd64/vmm/io/vatpit.h	Fri Apr 18 14:59:39 2014	(r264647)
+++ head/sys/amd64/vmm/io/vatpit.h	Fri Apr 18 15:22:56 2014	(r264648)
@@ -37,7 +37,9 @@
 struct vatpit *vatpit_init(struct vm *vm);
 void vatpit_cleanup(struct vatpit *vatpit);
 
-int vatpit_handler(void *vm, int vcpuid, struct vm_exit *vmexit);
-int vatpit_nmisc_handler(void *vm, int vcpuid, struct vm_exit *vmexit);
+int vatpit_handler(void *vm, int vcpuid, bool in, int port, int bytes,
+    uint32_t *eax);
+int vatpit_nmisc_handler(void *vm, int vcpuid, bool in, int port, int bytes,
+    uint32_t *eax);
 
 #endif	/* _VATPIT_H_ */

Modified: head/sys/amd64/vmm/vmm_ioport.c
==============================================================================
--- head/sys/amd64/vmm/vmm_ioport.c	Fri Apr 18 14:59:39 2014	(r264647)
+++ head/sys/amd64/vmm/vmm_ioport.c	Fri Apr 18 15:22:56 2014	(r264648)
@@ -59,6 +59,8 @@ int
 emulate_ioport(struct vm *vm, int vcpuid, struct vm_exit *vmexit)
 {
 	ioport_handler_func_t handler;
+	uint32_t mask, val;
+	int error;
 
 	if (vmexit->u.inout.port >= MAX_IOPORTS)
 		return (-1);
@@ -67,5 +69,39 @@ emulate_ioport(struct vm *vm, int vcpuid
 	if (handler == NULL)
 		return (-1);
 
-	return ((*handler)(vm, vcpuid, vmexit));
+	if (!vmexit->u.inout.in) {
+		switch (vmexit->u.inout.bytes) {
+		case 1:
+			mask = 0xff;
+			break;
+		case 2:
+			mask = 0xffff;
+			break;
+		default:
+			mask = 0xffffffff;
+			break;
+		}
+		val = vmexit->u.inout.eax & mask;
+	}
+
+	error = (*handler)(vm, vcpuid, vmexit->u.inout.in,
+	    vmexit->u.inout.port, vmexit->u.inout.bytes, &val);
+
+	if (!error && vmexit->u.inout.in) {
+		switch (vmexit->u.inout.bytes) {
+		case 1:
+			mask = 0xff;
+			break;
+		case 2:
+			mask = 0xffff;
+			break;
+		default:
+			mask = 0xffffffff;
+			break;
+		}
+		vmexit->u.inout.eax &= ~mask;
+		vmexit->u.inout.eax |= val & mask;
+	}
+
+	return (error);
 }

Modified: head/sys/amd64/vmm/vmm_ioport.h
==============================================================================
--- head/sys/amd64/vmm/vmm_ioport.h	Fri Apr 18 14:59:39 2014	(r264647)
+++ head/sys/amd64/vmm/vmm_ioport.h	Fri Apr 18 15:22:56 2014	(r264648)
@@ -30,7 +30,7 @@
 #define	_VMM_IOPORT_H_
 
 typedef int (*ioport_handler_func_t)(void *vm, int vcpuid,
-    struct vm_exit *vmexit);
+    bool in, int port, int bytes, uint32_t *val);
 
 int emulate_ioport(struct vm *vm, int vcpuid, struct vm_exit *vmexit);
 

Modified: head/usr.sbin/bhyve/inout.c
==============================================================================
--- head/usr.sbin/bhyve/inout.c	Fri Apr 18 14:59:39 2014	(r264647)
+++ head/usr.sbin/bhyve/inout.c	Fri Apr 18 15:22:56 2014	(r264648)
@@ -95,9 +95,10 @@ emulate_inout(struct vmctx *ctx, int vcp
 	      uint32_t *eax, int strict)
 {
 	int flags;
-	uint32_t mask;
+	uint32_t mask, val;
 	inout_func_t handler;
 	void *arg;
+	int error;
 
 	assert(port < MAX_IOPORTS);
 
@@ -118,16 +119,34 @@ emulate_inout(struct vmctx *ctx, int vcp
 			mask = 0xffffffff;
 			break;
 		}
-		*eax = *eax & mask;
+		val = *eax & mask;
 	}
 
 	flags = inout_handlers[port].flags;
 	arg = inout_handlers[port].arg;
 
 	if ((in && (flags & IOPORT_F_IN)) || (!in && (flags & IOPORT_F_OUT)))
-		return ((*handler)(ctx, vcpu, in, port, bytes, eax, arg));
+		error = (*handler)(ctx, vcpu, in, port, bytes, &val, arg);
 	else
-		return (-1);
+		error = -1;
+
+	if (!error && in) {
+		switch (bytes) {
+		case 1:
+			mask = 0xff;
+			break;
+		case 2:
+			mask = 0xffff;
+			break;
+		default:
+			mask = 0xffffffff;
+			break;
+		}
+		*eax &= ~mask;
+		*eax |= val & mask;
+	}
+
+	return (error);
 }
 
 void


More information about the svn-src-all mailing list