Index: sys/dev/nvmm/nvmm.c =================================================================== RCS file: /cvsroot/src/sys/dev/nvmm/nvmm.c,v retrieving revision 1.33 diff -u -r1.33 nvmm.c --- sys/dev/nvmm/nvmm.c 1 Aug 2020 08:18:36 -0000 1.33 +++ sys/dev/nvmm/nvmm.c 5 Aug 2020 18:00:00 -0000 @@ -573,8 +573,7 @@ while (1) { /* Got a signal? Or pending resched? Leave. */ - if (__predict_false(nvmm_return_needed())) { - exit->reason = NVMM_VCPU_EXIT_NONE; + if (__predict_false(nvmm_return_needed(vcpu, exit))) { return 0; } @@ -619,6 +618,7 @@ out: nvmm_machine_put(mach); + vcpu->comm->immediate_exit = false; return error; } Index: sys/dev/nvmm/nvmm.h =================================================================== RCS file: /cvsroot/src/sys/dev/nvmm/nvmm.h,v retrieving revision 1.13 diff -u -r1.13 nvmm.h --- sys/dev/nvmm/nvmm.h 1 Aug 2020 08:18:36 -0000 1.13 +++ sys/dev/nvmm/nvmm.h 5 Aug 2020 18:00:00 -0000 @@ -48,7 +48,7 @@ #include #endif -#define NVMM_KERN_VERSION 1 +#define NVMM_KERN_VERSION 2 struct nvmm_capability { uint32_t version; @@ -81,6 +81,9 @@ /* Event. */ bool event_commit; struct nvmm_vcpu_event event; + + /* Race-free exit from nvmm_vcpu_run() without signals. */ + volatile bool immediate_exit; }; /* Index: sys/dev/nvmm/nvmm_internal.h =================================================================== RCS file: /cvsroot/src/sys/dev/nvmm/nvmm_internal.h,v retrieving revision 1.17 diff -u -r1.17 nvmm_internal.h --- sys/dev/nvmm/nvmm_internal.h 1 Aug 2020 08:18:36 -0000 1.17 +++ sys/dev/nvmm/nvmm_internal.h 5 Aug 2020 18:00:00 -0000 @@ -125,14 +125,24 @@ #endif static inline bool -nvmm_return_needed(void) +nvmm_return_needed(struct nvmm_cpu *vcpu, struct nvmm_vcpu_exit *exit) { + if (preempt_needed()) { + exit->reason = NVMM_VCPU_EXIT_NONE; return true; } if (curlwp->l_flag & LW_USERRET) { + exit->reason = NVMM_VCPU_EXIT_NONE; + return true; + } + if (vcpu->comm->immediate_exit) { + vcpu->comm->immediate_exit = false; + exit->reason = NVMM_VCPU_EXIT_STOPPED; + printf("%s() %s:%d\n", __func__, __FILE__, __LINE__); return true; } + return false; } Index: sys/dev/nvmm/x86/nvmm_x86.h =================================================================== RCS file: /cvsroot/src/sys/dev/nvmm/x86/nvmm_x86.h,v retrieving revision 1.18 diff -u -r1.18 nvmm_x86.h --- sys/dev/nvmm/x86/nvmm_x86.h 28 Oct 2019 08:30:49 -0000 1.18 +++ sys/dev/nvmm/x86/nvmm_x86.h 5 Aug 2020 18:00:00 -0000 @@ -75,6 +75,7 @@ /* Generic. */ #define NVMM_VCPU_EXIT_NONE 0x0000000000000000ULL +#define NVMM_VCPU_EXIT_STOPPED 0xFFFFFFFFFFFFFFFEULL #define NVMM_VCPU_EXIT_INVALID 0xFFFFFFFFFFFFFFFFULL /* x86: operations. */ #define NVMM_VCPU_EXIT_MEMORY 0x0000000000000001ULL Index: sys/dev/nvmm/x86/nvmm_x86_svm.c =================================================================== RCS file: /cvsroot/src/sys/dev/nvmm/x86/nvmm_x86_svm.c,v retrieving revision 1.65 diff -u -r1.65 nvmm_x86_svm.c --- sys/dev/nvmm/x86/nvmm_x86_svm.c 19 Jul 2020 06:56:09 -0000 1.65 +++ sys/dev/nvmm/x86/nvmm_x86_svm.c 5 Aug 2020 18:00:00 -0000 @@ -1472,7 +1472,7 @@ } /* If no reason to return to userland, keep rolling. */ - if (nvmm_return_needed()) { + if (nvmm_return_needed(vcpu, exit)) { break; } if (exit->reason != NVMM_VCPU_EXIT_NONE) { Index: sys/dev/nvmm/x86/nvmm_x86_vmx.c =================================================================== RCS file: /cvsroot/src/sys/dev/nvmm/x86/nvmm_x86_vmx.c,v retrieving revision 1.65 diff -u -r1.65 nvmm_x86_vmx.c --- sys/dev/nvmm/x86/nvmm_x86_vmx.c 19 Jul 2020 06:56:09 -0000 1.65 +++ sys/dev/nvmm/x86/nvmm_x86_vmx.c 5 Aug 2020 18:00:01 -0000 @@ -2195,7 +2195,7 @@ } /* If no reason to return to userland, keep rolling. */ - if (nvmm_return_needed()) { + if (nvmm_return_needed(vcpu, exit)) { break; } if (exit->reason != NVMM_VCPU_EXIT_NONE) { Index: lib/libnvmm/libnvmm.c =================================================================== RCS file: /cvsroot/src/lib/libnvmm/libnvmm.c,v retrieving revision 1.18 diff -u -r1.18 libnvmm.c --- lib/libnvmm/libnvmm.c 27 Oct 2019 20:17:36 -0000 1.18 +++ lib/libnvmm/libnvmm.c 5 Aug 2020 18:00:42 -0000 @@ -311,6 +311,7 @@ vcpu->cpuid = cpuid; vcpu->state = &comm->state; vcpu->event = &comm->event; + vcpu->immediate_exit = &comm->immediate_exit; vcpu->exit = malloc(sizeof(*vcpu->exit)); return 0; @@ -562,3 +563,12 @@ return 0; } + +int +nvmm_vcpu_stop(struct nvmm_vcpu *vcpu) +{ + + vcpu->immediate_exit = true; + + return 0; +} Index: lib/libnvmm/nvmm.h =================================================================== RCS file: /cvsroot/src/lib/libnvmm/nvmm.h,v retrieving revision 1.17 diff -u -r1.17 nvmm.h --- lib/libnvmm/nvmm.h 28 Oct 2019 08:30:49 -0000 1.17 +++ lib/libnvmm/nvmm.h 5 Aug 2020 18:00:42 -0000 @@ -38,7 +38,12 @@ #include #include -#define NVMM_USER_VERSION 1 +#define NVMM_USER_VERSION 2 + +/* + * Version 1 - Initial release in NetBSD 9.0. + * Version 2 - Added nvmm_vcpu::immediate_exit. + */ struct nvmm_io; struct nvmm_mem; @@ -60,6 +65,7 @@ struct nvmm_vcpu_state *state; struct nvmm_vcpu_event *event; struct nvmm_vcpu_exit *exit; + volatile bool immediate_exit; }; struct nvmm_io { @@ -124,4 +130,6 @@ int nvmm_vcpu_dump(struct nvmm_machine *, struct nvmm_vcpu *); +int nvmm_vcpu_stop(struct nvmm_vcpu *); + #endif /* _LIBNVMM_H_ */