summaryrefslogtreecommitdiffstats
path: root/usr.sbin/bhyve
diff options
context:
space:
mode:
authorneel <neel@FreeBSD.org>2013-12-07 22:18:36 +0000
committerneel <neel@FreeBSD.org>2013-12-07 22:18:36 +0000
commit127d791c3eb087bbfd38ee604ebc3054a56f9ce9 (patch)
tree1189fddf5ff2f20e9c032e61874d82a5f227cf88 /usr.sbin/bhyve
parent76f5b95a8908222a3428a9e292f76cc2db20bc7d (diff)
downloadFreeBSD-src-127d791c3eb087bbfd38ee604ebc3054a56f9ce9.zip
FreeBSD-src-127d791c3eb087bbfd38ee604ebc3054a56f9ce9.tar.gz
If a vcpu disables its local apic and then executes a 'HLT' then spin down the
vcpu and destroy its thread context. Also modify the 'HLT' processing to ignore pending interrupts in the IRR if interrupts have been disabled by the guest. The interrupt cannot be injected into the guest in any case so resuming it is futile. With this change "halt" from a Linux guest works correctly. Reviewed by: grehan@ Tested by: Tycho Nightingale (tycho.nightingale@pluribusnetworks.com)
Diffstat (limited to 'usr.sbin/bhyve')
-rw-r--r--usr.sbin/bhyve/bhyverun.c32
1 files changed, 28 insertions, 4 deletions
diff --git a/usr.sbin/bhyve/bhyverun.c b/usr.sbin/bhyve/bhyverun.c
index 652f402..0ea2904 100644
--- a/usr.sbin/bhyve/bhyverun.c
+++ b/usr.sbin/bhyve/bhyverun.c
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
#include <sys/mman.h>
#include <sys/time.h>
+#include <machine/atomic.h>
#include <machine/segments.h>
#include <stdio.h>
@@ -85,8 +86,6 @@ static int pincpu = -1;
static int guest_vmexit_on_hlt, guest_vmexit_on_pause, disable_x2apic;
static int virtio_msix = 1;
-static int foundcpus;
-
static int strictio;
static int acpi;
@@ -210,8 +209,7 @@ fbsdrun_addcpu(struct vmctx *ctx, int vcpu, uint64_t rip)
exit(1);
}
- cpumask |= 1 << vcpu;
- foundcpus++;
+ atomic_set_int(&cpumask, 1 << vcpu);
/*
* Set up the vmexit struct to allow execution to start
@@ -229,6 +227,20 @@ fbsdrun_addcpu(struct vmctx *ctx, int vcpu, uint64_t rip)
}
static int
+fbsdrun_deletecpu(struct vmctx *ctx, int vcpu)
+{
+
+ if ((cpumask & (1 << vcpu)) == 0) {
+ fprintf(stderr, "addcpu: attempting to delete unknown cpu %d\n",
+ vcpu);
+ exit(1);
+ }
+
+ atomic_clear_int(&cpumask, 1 << vcpu);
+ return (cpumask == 0);
+}
+
+static int
vmexit_catch_reset(void)
{
stats.io_reset++;
@@ -327,6 +339,17 @@ vmexit_spinup_ap(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu)
}
static int
+vmexit_spindown_cpu(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu)
+{
+ int lastcpu;
+
+ lastcpu = fbsdrun_deletecpu(ctx, *pvcpu);
+ if (!lastcpu)
+ pthread_exit(NULL);
+ return (vmexit_catch_reset());
+}
+
+static int
vmexit_vmx(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
{
@@ -417,6 +440,7 @@ static vmexit_handler_t handler[VM_EXITCODE_MAX] = {
[VM_EXITCODE_MTRAP] = vmexit_mtrap,
[VM_EXITCODE_INST_EMUL] = vmexit_inst_emul,
[VM_EXITCODE_SPINUP_AP] = vmexit_spinup_ap,
+ [VM_EXITCODE_SPINDOWN_CPU] = vmexit_spindown_cpu,
};
static void
OpenPOWER on IntegriCloud