From fc276d92ae91bc7d48bda15996c70837c88f7d99 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Fri, 6 Apr 2018 22:03:43 +0000 Subject: Add a way to temporarily suspend and resume virtual CPUs. This is used as part of implementing run control in bhyve's debug server. The hypervisor now maintains a set of "debugged" CPUs. Attempting to run a debugged CPU will fail to execute any guest instructions and will instead report a VM_EXITCODE_DEBUG exit to the userland hypervisor. Virtual CPUs are placed into the debugged state via vm_suspend_cpu() (implemented via a new VM_SUSPEND_CPU ioctl). Virtual CPUs can be resumed via vm_resume_cpu() (VM_RESUME_CPU ioctl). The debug server suspends virtual CPUs when it wishes them to stop executing in the guest (for example, when a debugger attaches to the server). The debug server can choose to resume only a subset of CPUs (for example, when single stepping) or it can choose to resume all CPUs. The debug server must explicitly mark a CPU as resumed via vm_resume_cpu() before the virtual CPU will successfully execute any guest instructions. Reviewed by: avg, grehan Tested on: Intel (jhb), AMD (avg) Differential Revision: https://reviews.freebsd.org/D14466 --- lib/libvmmapi/vmmapi.c | 34 +++++++++++++++++++++++++++++++++- lib/libvmmapi/vmmapi.h | 3 +++ 2 files changed, 36 insertions(+), 1 deletion(-) (limited to 'lib/libvmmapi') diff --git a/lib/libvmmapi/vmmapi.c b/lib/libvmmapi/vmmapi.c index 292e749eaaa2..ecb21f0dcdc1 100644 --- a/lib/libvmmapi/vmmapi.c +++ b/lib/libvmmapi/vmmapi.c @@ -1373,6 +1373,13 @@ vm_suspended_cpus(struct vmctx *ctx, cpuset_t *cpus) return (vm_get_cpus(ctx, VM_SUSPENDED_CPUS, cpus)); } +int +vm_debug_cpus(struct vmctx *ctx, cpuset_t *cpus) +{ + + return (vm_get_cpus(ctx, VM_DEBUG_CPUS, cpus)); +} + int vm_activate_cpu(struct vmctx *ctx, int vcpu) { @@ -1385,6 +1392,30 @@ vm_activate_cpu(struct vmctx *ctx, int vcpu) return (error); } +int +vm_suspend_cpu(struct vmctx *ctx, int vcpu) +{ + struct vm_activate_cpu ac; + int error; + + bzero(&ac, sizeof(struct vm_activate_cpu)); + ac.vcpuid = vcpu; + error = ioctl(ctx->fd, VM_SUSPEND_CPU, &ac); + return (error); +} + +int +vm_resume_cpu(struct vmctx *ctx, int vcpu) +{ + struct vm_activate_cpu ac; + int error; + + bzero(&ac, sizeof(struct vm_activate_cpu)); + ac.vcpuid = vcpu; + error = ioctl(ctx->fd, VM_RESUME_CPU, &ac); + return (error); +} + int vm_get_intinfo(struct vmctx *ctx, int vcpu, uint64_t *info1, uint64_t *info2) { @@ -1501,7 +1532,8 @@ vm_get_ioctls(size_t *len) VM_SET_X2APIC_STATE, VM_GET_X2APIC_STATE, VM_GET_HPET_CAPABILITIES, VM_GET_GPA_PMAP, VM_GLA2GPA, VM_GLA2GPA_NOFAULT, - VM_ACTIVATE_CPU, VM_GET_CPUS, VM_SET_INTINFO, VM_GET_INTINFO, + VM_ACTIVATE_CPU, VM_GET_CPUS, VM_SUSPEND_CPU, VM_RESUME_CPU, + VM_SET_INTINFO, VM_GET_INTINFO, VM_RTC_WRITE, VM_RTC_READ, VM_RTC_SETTIME, VM_RTC_GETTIME, VM_RESTART_INSTRUCTION }; diff --git a/lib/libvmmapi/vmmapi.h b/lib/libvmmapi/vmmapi.h index e391d9131e86..da7267cba59d 100644 --- a/lib/libvmmapi/vmmapi.h +++ b/lib/libvmmapi/vmmapi.h @@ -216,7 +216,10 @@ int vcpu_reset(struct vmctx *ctx, int vcpu); int vm_active_cpus(struct vmctx *ctx, cpuset_t *cpus); int vm_suspended_cpus(struct vmctx *ctx, cpuset_t *cpus); +int vm_debug_cpus(struct vmctx *ctx, cpuset_t *cpus); int vm_activate_cpu(struct vmctx *ctx, int vcpu); +int vm_suspend_cpu(struct vmctx *ctx, int vcpu); +int vm_resume_cpu(struct vmctx *ctx, int vcpu); /* * FreeBSD specific APIs -- cgit v1.2.3