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:
parent
0aa4ce9b7d
commit
afd5e8ba88
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user