diff options
author | neel <neel@FreeBSD.org> | 2013-12-07 22:18:36 +0000 |
---|---|---|
committer | neel <neel@FreeBSD.org> | 2013-12-07 22:18:36 +0000 |
commit | 127d791c3eb087bbfd38ee604ebc3054a56f9ce9 (patch) | |
tree | 1189fddf5ff2f20e9c032e61874d82a5f227cf88 /usr.sbin/bhyve | |
parent | 76f5b95a8908222a3428a9e292f76cc2db20bc7d (diff) | |
download | FreeBSD-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.c | 32 |
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 |