> ...not sure the reset bits are right
They are incorrect. I have corrected the values. Thanks for noticing.
I tested against a old binary by mistake, sorry.
I also updated vcpu_exit's comment to include EAGAIN. It was already
a existing return value before this patch, at the SVM_VMEXIT_SHUTDOWN
case.
> and from my quick checking I think we need to implement reads of the
> register. At least linux reads before it writes and I'm not sure the
> consequence yet of not emulating that correctly.
Linux just masks the read before writing back. It works as it as,
because currently it simply reads 0xff.
However, I see no benefit from reading this register. Not implementing
might affect guests who probe 0xcf9 for presence, but I do not know of
any that do that.
Thanks for the feedback.
diff --git usr.sbin/vmd/x86_vm.c usr.sbin/vmd/x86_vm.c
index 1b5ade90f9b..2d2da13da92 100644
--- usr.sbin/vmd/x86_vm.c
+++ usr.sbin/vmd/x86_vm.c
@@ -45,6 +45,10 @@ typedef uint8_t (*io_fn_t)(struct vm_run_params *);
#define LOWMEM_KB 576
#define MAX_PORTS 65536
+#define RST_CNT 0xcf9
+#define RST_CNT_SYS_RST 0x02
+#define RST_CNT_RST_CPU 0x04
+#define RST_CNT_RESET (RST_CNT_SYS_RST | RST_CNT_RST_CPU)
io_fn_t ioports_map[MAX_PORTS];
@@ -52,7 +56,7 @@ int translate_gva(struct vm_exit*, uint64_t, uint64_t *, int);
static int loadfile_bios(gzFile, off_t, struct vcpu_reg_state *);
static int vcpu_exit_eptviolation(struct vm_run_params *);
-static void vcpu_exit_inout(struct vm_run_params *);
+static int vcpu_exit_inout(struct vm_run_params *);
extern struct vmd_vm *current_vm;
extern int con_fd;
@@ -449,12 +453,16 @@ unpause_vm_md(struct vmd_vm *vm)
* Parameters:
* vrp: vcpu run parameters containing guest state for this exit
*/
-void
+int
vcpu_exit_inout(struct vm_run_params *vrp)
{
struct vm_exit *vei = vrp->vrp_exit;
uint8_t intr = 0xFF;
+ if (vei->vei.vei_dir == VEI_DIR_OUT &&
+ vei->vei.vei_port == RST_CNT &&
+ (vei->vei.vei_data & RST_CNT_RESET) == RST_CNT_RESET)
+ return (EAGAIN);
if (vei->vei.vei_rep || vei->vei.vei_string) {
#ifdef MMIO_DEBUG
log_info("%s: %s%s%s %d-byte, enc=%d, data=0x%08x, port=0x%04x",
@@ -483,6 +491,7 @@ vcpu_exit_inout(struct vm_run_params *vrp)
if (intr != 0xFF)
vcpu_assert_irq(vrp->vrp_vm_id, vrp->vrp_vcpu_id, intr);
+ return (0);
}
/*
@@ -503,12 +512,14 @@ vcpu_exit_inout(struct vm_run_params *vrp)
* Return values:
* 0: the exit was handled successfully
* 1: an error occurred (eg, unknown exit reason passed in 'vrp')
+ * EAGAIN: the vm should be reset
*/
int
vcpu_exit(struct vm_run_params *vrp)
{
int ret;
+ ret = 0;
switch (vrp->vrp_exit_reason) {
case VMX_EXIT_INT_WINDOW:
case SVM_VMEXIT_VINTR:
@@ -528,12 +539,10 @@ vcpu_exit(struct vm_run_params *vrp)
case SVM_VMEXIT_NPF:
case VMX_EXIT_EPT_VIOLATION:
ret = vcpu_exit_eptviolation(vrp);
- if (ret)
- return (ret);
break;
case VMX_EXIT_IO:
case SVM_VMEXIT_IOIO:
- vcpu_exit_inout(vrp);
+ ret = vcpu_exit_inout(vrp);
break;
case VMX_EXIT_HLT:
case SVM_VMEXIT_HLT:
@@ -547,7 +556,7 @@ vcpu_exit(struct vm_run_params *vrp)
log_debug("unknown exit reason 0x%x", vrp->vrp_exit_reason);
}
- return (0);
+ return (ret);
}
/*
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.