Simplify the meaning of return values from the inout handlers. After this

change 0 means success and non-zero means failure.

This also helps to eliminate VMEXIT_POWEROFF and VMEXIT_RESET as return values
from VM-exit handlers.

CR:		D480
Reviewed by:	grehan, jhb
This commit is contained in:
Neel Natu 2014-07-25 20:18:35 +00:00
parent 0aa4ce9b7d
commit afd5e8ba88
6 changed files with 42 additions and 56 deletions

View File

@ -31,6 +31,10 @@ __FBSDID("$FreeBSD$");
#include <machine/vmm.h>
#include <vmmapi.h>
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include "inout.h"
@ -48,29 +52,30 @@ atkbdc_data_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
uint32_t *eax, void *arg)
{
if (bytes != 1)
return (INOUT_ERROR);
return (-1);
*eax = 0;
return (INOUT_OK);
return (0);
}
static int
atkbdc_sts_ctl_handler(struct vmctx *ctx, int vcpu, int in, int port,
int bytes, uint32_t *eax, void *arg)
{
int retval;
int error, retval;
if (bytes != 1)
return (INOUT_ERROR);
return (-1);
retval = INOUT_OK;
retval = 0;
if (in) {
*eax = KBD_SYS_FLAG; /* system passed POST */
} else {
switch (*eax) {
case KBDC_RESET: /* Pulse "reset" line. */
retval = INOUT_RESET;
error = vm_suspend(ctx, VM_SUSPEND_RESET);
assert(error == 0 || errno == EALREADY);
break;
}
}

View File

@ -107,8 +107,6 @@ struct bhyvestats {
uint64_t vmexit_inst_emul;
uint64_t cpu_switch_rotate;
uint64_t cpu_switch_direct;
int io_reset;
int io_poweroff;
} stats;
struct mt_vmm_info {
@ -331,27 +329,18 @@ vmexit_inout(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu)
}
error = emulate_inout(ctx, vcpu, vme, strictio);
if (error == INOUT_OK && in && !string) {
if (!error && in && !string) {
error = vm_set_register(ctx, vcpu, VM_REG_GUEST_RAX,
vme->u.inout.eax);
assert(error == 0);
}
switch (error) {
case INOUT_OK:
return (VMEXIT_CONTINUE);
case INOUT_RESTART:
return (VMEXIT_RESTART);
case INOUT_RESET:
stats.io_reset++;
return (VMEXIT_RESET);
case INOUT_POWEROFF:
stats.io_poweroff++;
return (VMEXIT_POWEROFF);
default:
fprintf(stderr, "Unhandled %s%c 0x%04x\n",
in ? "in" : "out",
bytes == 1 ? 'b' : (bytes == 2 ? 'w' : 'l'), port);
if (error) {
fprintf(stderr, "Unhandled %s%c 0x%04x\n", in ? "in" : "out",
bytes == 1 ? 'b' : (bytes == 2 ? 'w' : 'l'), port);
return (VMEXIT_ABORT);
} else {
return (VMEXIT_CONTINUE);
}
}
@ -581,7 +570,6 @@ vm_loop(struct vmctx *ctx, int vcpu, uint64_t rip)
{
int error, rc, prevcpu;
enum vm_exitcode exitcode;
enum vm_suspend_how how;
cpuset_t active_cpus;
if (vcpumap[vcpu] != NULL) {
@ -616,16 +604,6 @@ vm_loop(struct vmctx *ctx, int vcpu, uint64_t rip)
case VMEXIT_RESTART:
rip = vmexit[vcpu].rip;
break;
case VMEXIT_RESET:
case VMEXIT_POWEROFF:
if (rc == VMEXIT_RESET)
how = VM_SUSPEND_RESET;
else
how = VM_SUSPEND_POWEROFF;
error = vm_suspend(ctx, how);
assert(error == 0 || errno == EALREADY);
rip = vmexit[vcpu].rip + vmexit[vcpu].inst_length;
break;
case VMEXIT_ABORT:
abort();
default:

View File

@ -38,8 +38,6 @@
#define VMEXIT_CONTINUE 1 /* continue from next instruction */
#define VMEXIT_RESTART 2 /* restart current instruction */
#define VMEXIT_ABORT 3 /* abort the vm run loop */
#define VMEXIT_RESET 4 /* guest machine has reset */
#define VMEXIT_POWEROFF 5 /* guest machine has powered off */
struct vmctx;
extern int guest_ncpus;

View File

@ -154,27 +154,28 @@ emulate_inout(struct vmctx *ctx, int vcpu, struct vm_exit *vmexit, int strict)
/* Limit number of back-to-back in/out emulations to 16 */
iterations = MIN(count, 16);
while (iterations > 0) {
assert(retval == 0);
if (vie_calculate_gla(vis->paging.cpu_mode,
vis->seg_name, &vis->seg_desc, index, bytes,
addrsize, prot, &gla)) {
vm_inject_gp(ctx, vcpu);
retval = INOUT_RESTART;
break;
}
error = vm_copy_setup(ctx, vcpu, &vis->paging, gla,
bytes, prot, iov, nitems(iov));
assert(error == 0 || error == 1 || error == -1);
if (error) {
retval = (error == 1) ? INOUT_RESTART :
INOUT_ERROR;
if (error == -1) {
retval = -1; /* Unrecoverable error */
break;
} else if (error == 1) {
retval = 0; /* Resume guest to handle fault */
break;
}
if (vie_alignment_check(vis->paging.cpl, bytes,
vis->cr0, vis->rflags, gla)) {
vm_inject_ac(ctx, vcpu, 0);
return (INOUT_RESTART);
break;
}
val = 0;
@ -213,8 +214,8 @@ emulate_inout(struct vmctx *ctx, int vcpu, struct vm_exit *vmexit, int strict)
}
/* Restart the instruction if more iterations remain */
if (retval == INOUT_OK && count != 0)
retval = INOUT_RESTART;
if (retval == 0 && count != 0)
vmexit->inst_length = 0;
} else {
if (!in) {
val = vmexit->u.inout.eax & vie_size2mask(bytes);

View File

@ -34,13 +34,9 @@
struct vmctx;
struct vm_exit;
/* Handler return values. */
#define INOUT_ERROR -1
#define INOUT_OK 0
#define INOUT_RESTART 1
#define INOUT_RESET 2
#define INOUT_POWEROFF 3
/*
* inout emulation handlers return 0 on success and -1 on failure.
*/
typedef int (*inout_func_t)(struct vmctx *ctx, int vcpu, int in, int port,
int bytes, uint32_t *eax, void *arg);

View File

@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
#include <machine/vmm.h>
#include <assert.h>
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <vmmapi.h>
@ -56,6 +57,8 @@ static int
reset_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
uint32_t *eax, void *arg)
{
int error;
static uint8_t reset_control;
if (bytes != 1)
@ -66,8 +69,10 @@ reset_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
reset_control = *eax;
/* Treat hard and soft resets the same. */
if (reset_control & 0x4)
return (INOUT_RESET);
if (reset_control & 0x4) {
error = vm_suspend(ctx, VM_SUSPEND_RESET);
assert(error == 0 || errno == EALREADY);
}
}
return (0);
}
@ -224,6 +229,7 @@ static int
pm1_control_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
uint32_t *eax, void *arg)
{
int error;
if (bytes != 2)
return (-1);
@ -243,8 +249,10 @@ pm1_control_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
* says that '5' should be stored in SLP_TYP for S5.
*/
if (*eax & PM1_SLP_EN) {
if ((pm1_control & PM1_SLP_TYP) >> 10 == 5)
return (INOUT_POWEROFF);
if ((pm1_control & PM1_SLP_TYP) >> 10 == 5) {
error = vm_suspend(ctx, VM_SUSPEND_POWEROFF);
assert(error == 0 || errno == EALREADY);
}
}
}
return (0);