Wed Aug 26 16:28:17 2020 UTC ()
nvmm: misc improvements

 - use mach->ncpus to get the number of vcpus, now that we have it
 - don't forget to decrement mach->ncpus when a machine gets killed
 - add more __predict_false()


(maxv)
diff -r1.35 -r1.36 src/sys/dev/nvmm/nvmm.c

cvs diff -r1.35 -r1.36 src/sys/dev/nvmm/nvmm.c (expand / switch to unified diff)

--- src/sys/dev/nvmm/nvmm.c 2020/08/18 17:04:37 1.35
+++ src/sys/dev/nvmm/nvmm.c 2020/08/26 16:28:17 1.36
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: nvmm.c,v 1.35 2020/08/18 17:04:37 maxv Exp $ */ 1/* $NetBSD: nvmm.c,v 1.36 2020/08/26 16:28:17 maxv Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2018-2020 The NetBSD Foundation, Inc. 4 * Copyright (c) 2018-2020 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Maxime Villard. 8 * by Maxime Villard.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -20,27 +20,27 @@ @@ -20,27 +20,27 @@
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32#include <sys/cdefs.h> 32#include <sys/cdefs.h>
33__KERNEL_RCSID(0, "$NetBSD: nvmm.c,v 1.35 2020/08/18 17:04:37 maxv Exp $"); 33__KERNEL_RCSID(0, "$NetBSD: nvmm.c,v 1.36 2020/08/26 16:28:17 maxv Exp $");
34 34
35#include <sys/param.h> 35#include <sys/param.h>
36#include <sys/systm.h> 36#include <sys/systm.h>
37#include <sys/kernel.h> 37#include <sys/kernel.h>
38 38
39#include <sys/cpu.h> 39#include <sys/cpu.h>
40#include <sys/conf.h> 40#include <sys/conf.h>
41#include <sys/kmem.h> 41#include <sys/kmem.h>
42#include <sys/module.h> 42#include <sys/module.h>
43#include <sys/proc.h> 43#include <sys/proc.h>
44#include <sys/mman.h> 44#include <sys/mman.h>
45#include <sys/file.h> 45#include <sys/file.h>
46#include <sys/filedesc.h> 46#include <sys/filedesc.h>
@@ -102,37 +102,37 @@ nvmm_machine_free(struct nvmm_machine *m @@ -102,37 +102,37 @@ nvmm_machine_free(struct nvmm_machine *m
102 KASSERT(rw_write_held(&mach->lock)); 102 KASSERT(rw_write_held(&mach->lock));
103 KASSERT(mach->present); 103 KASSERT(mach->present);
104 mach->present = false; 104 mach->present = false;
105 atomic_dec_uint(&nmachines); 105 atomic_dec_uint(&nmachines);
106} 106}
107 107
108static int 108static int
109nvmm_machine_get(struct nvmm_owner *owner, nvmm_machid_t machid, 109nvmm_machine_get(struct nvmm_owner *owner, nvmm_machid_t machid,
110 struct nvmm_machine **ret, bool writer) 110 struct nvmm_machine **ret, bool writer)
111{ 111{
112 struct nvmm_machine *mach; 112 struct nvmm_machine *mach;
113 krw_t op = writer ? RW_WRITER : RW_READER; 113 krw_t op = writer ? RW_WRITER : RW_READER;
114 114
115 if (machid >= NVMM_MAX_MACHINES) { 115 if (__predict_false(machid >= NVMM_MAX_MACHINES)) {
116 return EINVAL; 116 return EINVAL;
117 } 117 }
118 mach = &machines[machid]; 118 mach = &machines[machid];
119 119
120 rw_enter(&mach->lock, op); 120 rw_enter(&mach->lock, op);
121 if (!mach->present) { 121 if (__predict_false(!mach->present)) {
122 rw_exit(&mach->lock); 122 rw_exit(&mach->lock);
123 return ENOENT; 123 return ENOENT;
124 } 124 }
125 if (owner != &root_owner && mach->owner != owner) { 125 if (__predict_false(mach->owner != owner && owner != &root_owner)) {
126 rw_exit(&mach->lock); 126 rw_exit(&mach->lock);
127 return EPERM; 127 return EPERM;
128 } 128 }
129 *ret = mach; 129 *ret = mach;
130 130
131 return 0; 131 return 0;
132} 132}
133 133
134static void 134static void
135nvmm_machine_put(struct nvmm_machine *mach) 135nvmm_machine_put(struct nvmm_machine *mach)
136{ 136{
137 rw_exit(&mach->lock); 137 rw_exit(&mach->lock);
138} 138}
@@ -169,33 +169,33 @@ nvmm_vcpu_free(struct nvmm_machine *mach @@ -169,33 +169,33 @@ nvmm_vcpu_free(struct nvmm_machine *mach
169 KASSERT(mutex_owned(&vcpu->lock)); 169 KASSERT(mutex_owned(&vcpu->lock));
170 vcpu->present = false; 170 vcpu->present = false;
171 if (vcpu->comm != NULL) { 171 if (vcpu->comm != NULL) {
172 uvm_deallocate(kernel_map, (vaddr_t)vcpu->comm, PAGE_SIZE); 172 uvm_deallocate(kernel_map, (vaddr_t)vcpu->comm, PAGE_SIZE);
173 } 173 }
174} 174}
175 175
176static int 176static int
177nvmm_vcpu_get(struct nvmm_machine *mach, nvmm_cpuid_t cpuid, 177nvmm_vcpu_get(struct nvmm_machine *mach, nvmm_cpuid_t cpuid,
178 struct nvmm_cpu **ret) 178 struct nvmm_cpu **ret)
179{ 179{
180 struct nvmm_cpu *vcpu; 180 struct nvmm_cpu *vcpu;
181 181
182 if (cpuid >= NVMM_MAX_VCPUS) { 182 if (__predict_false(cpuid >= NVMM_MAX_VCPUS)) {
183 return EINVAL; 183 return EINVAL;
184 } 184 }
185 vcpu = &mach->cpus[cpuid]; 185 vcpu = &mach->cpus[cpuid];
186 186
187 mutex_enter(&vcpu->lock); 187 mutex_enter(&vcpu->lock);
188 if (!vcpu->present) { 188 if (__predict_false(!vcpu->present)) {
189 mutex_exit(&vcpu->lock); 189 mutex_exit(&vcpu->lock);
190 return ENOENT; 190 return ENOENT;
191 } 191 }
192 *ret = vcpu; 192 *ret = vcpu;
193 193
194 return 0; 194 return 0;
195} 195}
196 196
197static void 197static void
198nvmm_vcpu_put(struct nvmm_cpu *vcpu) 198nvmm_vcpu_put(struct nvmm_cpu *vcpu)
199{ 199{
200 mutex_exit(&vcpu->lock); 200 mutex_exit(&vcpu->lock);
201} 201}
@@ -217,26 +217,27 @@ nvmm_kill_machines(struct nvmm_owner *ow @@ -217,26 +217,27 @@ nvmm_kill_machines(struct nvmm_owner *ow
217 if (!mach->present || mach->owner != owner) { 217 if (!mach->present || mach->owner != owner) {
218 rw_exit(&mach->lock); 218 rw_exit(&mach->lock);
219 continue; 219 continue;
220 } 220 }
221 221
222 /* Kill it. */ 222 /* Kill it. */
223 for (j = 0; j < NVMM_MAX_VCPUS; j++) { 223 for (j = 0; j < NVMM_MAX_VCPUS; j++) {
224 error = nvmm_vcpu_get(mach, j, &vcpu); 224 error = nvmm_vcpu_get(mach, j, &vcpu);
225 if (error) 225 if (error)
226 continue; 226 continue;
227 (*nvmm_impl->vcpu_destroy)(mach, vcpu); 227 (*nvmm_impl->vcpu_destroy)(mach, vcpu);
228 nvmm_vcpu_free(mach, vcpu); 228 nvmm_vcpu_free(mach, vcpu);
229 nvmm_vcpu_put(vcpu); 229 nvmm_vcpu_put(vcpu);
 230 atomic_dec_uint(&mach->ncpus);
230 } 231 }
231 (*nvmm_impl->machine_destroy)(mach); 232 (*nvmm_impl->machine_destroy)(mach);
232 uvmspace_free(mach->vm); 233 uvmspace_free(mach->vm);
233 234
234 /* Drop the kernel UOBJ refs. */ 235 /* Drop the kernel UOBJ refs. */
235 for (j = 0; j < NVMM_MAX_HMAPPINGS; j++) { 236 for (j = 0; j < NVMM_MAX_HMAPPINGS; j++) {
236 if (!mach->hmap[j].present) 237 if (!mach->hmap[j].present)
237 continue; 238 continue;
238 uao_detach(mach->hmap[j].uobj); 239 uao_detach(mach->hmap[j].uobj);
239 } 240 }
240 241
241 nvmm_machine_free(mach); 242 nvmm_machine_free(mach);
242 243
@@ -304,26 +305,27 @@ nvmm_machine_destroy(struct nvmm_owner * @@ -304,26 +305,27 @@ nvmm_machine_destroy(struct nvmm_owner *
304 305
305 error = nvmm_machine_get(owner, args->machid, &mach, true); 306 error = nvmm_machine_get(owner, args->machid, &mach, true);
306 if (error) 307 if (error)
307 return error; 308 return error;
308 309
309 for (i = 0; i < NVMM_MAX_VCPUS; i++) { 310 for (i = 0; i < NVMM_MAX_VCPUS; i++) {
310 error = nvmm_vcpu_get(mach, i, &vcpu); 311 error = nvmm_vcpu_get(mach, i, &vcpu);
311 if (error) 312 if (error)
312 continue; 313 continue;
313 314
314 (*nvmm_impl->vcpu_destroy)(mach, vcpu); 315 (*nvmm_impl->vcpu_destroy)(mach, vcpu);
315 nvmm_vcpu_free(mach, vcpu); 316 nvmm_vcpu_free(mach, vcpu);
316 nvmm_vcpu_put(vcpu); 317 nvmm_vcpu_put(vcpu);
 318 atomic_dec_uint(&mach->ncpus);
317 } 319 }
318 320
319 (*nvmm_impl->machine_destroy)(mach); 321 (*nvmm_impl->machine_destroy)(mach);
320 322
321 /* Free the machine vmspace. */ 323 /* Free the machine vmspace. */
322 uvmspace_free(mach->vm); 324 uvmspace_free(mach->vm);
323 325
324 /* Drop the kernel UOBJ refs. */ 326 /* Drop the kernel UOBJ refs. */
325 for (i = 0; i < NVMM_MAX_HMAPPINGS; i++) { 327 for (i = 0; i < NVMM_MAX_HMAPPINGS; i++) {
326 if (!mach->hmap[i].present) 328 if (!mach->hmap[i].present)
327 continue; 329 continue;
328 uao_detach(mach->hmap[i].uobj); 330 uao_detach(mach->hmap[i].uobj);
329 } 331 }
@@ -404,53 +406,51 @@ nvmm_vcpu_create(struct nvmm_owner *owne @@ -404,53 +406,51 @@ nvmm_vcpu_create(struct nvmm_owner *owne
404 nvmm_vcpu_put(vcpu); 406 nvmm_vcpu_put(vcpu);
405 goto out; 407 goto out;
406 } 408 }
407 memset(vcpu->comm, 0, PAGE_SIZE); 409 memset(vcpu->comm, 0, PAGE_SIZE);
408 410
409 error = (*nvmm_impl->vcpu_create)(mach, vcpu); 411 error = (*nvmm_impl->vcpu_create)(mach, vcpu);
410 if (error) { 412 if (error) {
411 nvmm_vcpu_free(mach, vcpu); 413 nvmm_vcpu_free(mach, vcpu);
412 nvmm_vcpu_put(vcpu); 414 nvmm_vcpu_put(vcpu);
413 goto out; 415 goto out;
414 } 416 }
415 417
416 nvmm_vcpu_put(vcpu); 418 nvmm_vcpu_put(vcpu);
417 
418 atomic_inc_uint(&mach->ncpus); 419 atomic_inc_uint(&mach->ncpus);
419 420
420out: 421out:
421 nvmm_machine_put(mach); 422 nvmm_machine_put(mach);
422 return error; 423 return error;
423} 424}
424 425
425static int 426static int
426nvmm_vcpu_destroy(struct nvmm_owner *owner, struct nvmm_ioc_vcpu_destroy *args) 427nvmm_vcpu_destroy(struct nvmm_owner *owner, struct nvmm_ioc_vcpu_destroy *args)
427{ 428{
428 struct nvmm_machine *mach; 429 struct nvmm_machine *mach;
429 struct nvmm_cpu *vcpu; 430 struct nvmm_cpu *vcpu;
430 int error; 431 int error;
431 432
432 error = nvmm_machine_get(owner, args->machid, &mach, false); 433 error = nvmm_machine_get(owner, args->machid, &mach, false);
433 if (error) 434 if (error)
434 return error; 435 return error;
435 436
436 error = nvmm_vcpu_get(mach, args->cpuid, &vcpu); 437 error = nvmm_vcpu_get(mach, args->cpuid, &vcpu);
437 if (error) 438 if (error)
438 goto out; 439 goto out;
439 440
440 (*nvmm_impl->vcpu_destroy)(mach, vcpu); 441 (*nvmm_impl->vcpu_destroy)(mach, vcpu);
441 nvmm_vcpu_free(mach, vcpu); 442 nvmm_vcpu_free(mach, vcpu);
442 nvmm_vcpu_put(vcpu); 443 nvmm_vcpu_put(vcpu);
443 
444 atomic_dec_uint(&mach->ncpus); 444 atomic_dec_uint(&mach->ncpus);
445 445
446out: 446out:
447 nvmm_machine_put(mach); 447 nvmm_machine_put(mach);
448 return error; 448 return error;
449} 449}
450 450
451static int 451static int
452nvmm_vcpu_configure(struct nvmm_owner *owner, 452nvmm_vcpu_configure(struct nvmm_owner *owner,
453 struct nvmm_ioc_vcpu_configure *args) 453 struct nvmm_ioc_vcpu_configure *args)
454{ 454{
455 struct nvmm_machine *mach; 455 struct nvmm_machine *mach;
456 struct nvmm_cpu *vcpu; 456 struct nvmm_cpu *vcpu;
@@ -897,48 +897,40 @@ nvmm_gpa_unmap(struct nvmm_owner *owner, @@ -897,48 +897,40 @@ nvmm_gpa_unmap(struct nvmm_owner *owner,
897 897
898out: 898out:
899 nvmm_machine_put(mach); 899 nvmm_machine_put(mach);
900 return error; 900 return error;
901} 901}
902 902
903/* -------------------------------------------------------------------------- */ 903/* -------------------------------------------------------------------------- */
904 904
905static int 905static int
906nvmm_ctl_mach_info(struct nvmm_owner *owner, struct nvmm_ioc_ctl *args) 906nvmm_ctl_mach_info(struct nvmm_owner *owner, struct nvmm_ioc_ctl *args)
907{ 907{
908 struct nvmm_ctl_mach_info ctl; 908 struct nvmm_ctl_mach_info ctl;
909 struct nvmm_machine *mach; 909 struct nvmm_machine *mach;
910 struct nvmm_cpu *vcpu; 
911 int error; 910 int error;
912 size_t i; 911 size_t i;
913 912
914 if (args->size != sizeof(ctl)) 913 if (args->size != sizeof(ctl))
915 return EINVAL; 914 return EINVAL;
916 error = copyin(args->data, &ctl, sizeof(ctl)); 915 error = copyin(args->data, &ctl, sizeof(ctl));
917 if (error) 916 if (error)
918 return error; 917 return error;
919 918
920 error = nvmm_machine_get(owner, ctl.machid, &mach, true); 919 error = nvmm_machine_get(owner, ctl.machid, &mach, true);
921 if (error) 920 if (error)
922 return error; 921 return error;
923 922
924 ctl.nvcpus = 0; 923 ctl.nvcpus = mach->ncpus;
925 for (i = 0; i < NVMM_MAX_VCPUS; i++) { 
926 error = nvmm_vcpu_get(mach, i, &vcpu); 
927 if (error) 
928 continue; 
929 ctl.nvcpus++; 
930 nvmm_vcpu_put(vcpu); 
931 } 
932 924
933 ctl.nram = 0; 925 ctl.nram = 0;
934 for (i = 0; i < NVMM_MAX_HMAPPINGS; i++) { 926 for (i = 0; i < NVMM_MAX_HMAPPINGS; i++) {
935 if (!mach->hmap[i].present) 927 if (!mach->hmap[i].present)
936 continue; 928 continue;
937 ctl.nram += mach->hmap[i].size; 929 ctl.nram += mach->hmap[i].size;
938 } 930 }
939 931
940 ctl.pid = mach->owner->pid; 932 ctl.pid = mach->owner->pid;
941 ctl.time = mach->time; 933 ctl.time = mach->time;
942 934
943 nvmm_machine_put(mach); 935 nvmm_machine_put(mach);
944 936