Deleted Added
full compact
bhyverun.c (253452) bhyverun.c (256062)
1/*-
2 * Copyright (c) 2011 NetApp, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 9 unchanged lines hidden (view full) ---

18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
1/*-
2 * Copyright (c) 2011 NetApp, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 9 unchanged lines hidden (view full) ---

18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: head/usr.sbin/bhyve/bhyverun.c 253452 2013-07-18 18:40:54Z grehan $
26 * $FreeBSD: head/usr.sbin/bhyve/bhyverun.c 256062 2013-10-04 23:29:07Z grehan $
27 */
28
29#include <sys/cdefs.h>
27 */
28
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD: head/usr.sbin/bhyve/bhyverun.c 253452 2013-07-18 18:40:54Z grehan $");
30__FBSDID("$FreeBSD: head/usr.sbin/bhyve/bhyverun.c 256062 2013-10-04 23:29:07Z grehan $");
31
32#include <sys/types.h>
33#include <sys/mman.h>
34#include <sys/time.h>
35
36#include <machine/segments.h>
37
38#include <stdio.h>
39#include <stdlib.h>
40#include <libgen.h>
41#include <unistd.h>
42#include <assert.h>
43#include <errno.h>
31
32#include <sys/types.h>
33#include <sys/mman.h>
34#include <sys/time.h>
35
36#include <machine/segments.h>
37
38#include <stdio.h>
39#include <stdlib.h>
40#include <libgen.h>
41#include <unistd.h>
42#include <assert.h>
43#include <errno.h>
44#include <signal.h>
45#include <pthread.h>
46#include <pthread_np.h>
47
48#include <machine/vmm.h>
49#include <vmmapi.h>
50
51#include "bhyverun.h"
52#include "acpi.h"
53#include "inout.h"
54#include "dbgport.h"
55#include "mem.h"
56#include "mevent.h"
57#include "mptbl.h"
58#include "pci_emul.h"
59#include "xmsr.h"
60#include "ioapic.h"
61#include "spinup_ap.h"
62#include "rtc.h"
63
44#include <pthread.h>
45#include <pthread_np.h>
46
47#include <machine/vmm.h>
48#include <vmmapi.h>
49
50#include "bhyverun.h"
51#include "acpi.h"
52#include "inout.h"
53#include "dbgport.h"
54#include "mem.h"
55#include "mevent.h"
56#include "mptbl.h"
57#include "pci_emul.h"
58#include "xmsr.h"
59#include "ioapic.h"
60#include "spinup_ap.h"
61#include "rtc.h"
62
64#define DEFAULT_GUEST_HZ 100
65#define DEFAULT_GUEST_TSLICE 200
66
67#define GUEST_NIO_PORT 0x488 /* guest upcalls via i/o port */
68
69#define VMEXIT_SWITCH 0 /* force vcpu switch in mux mode */
70#define VMEXIT_CONTINUE 1 /* continue from next instruction */
71#define VMEXIT_RESTART 2 /* restart current instruction */
72#define VMEXIT_ABORT 3 /* abort the vm run loop */
73#define VMEXIT_RESET 4 /* guest machine has reset */
74
75#define MB (1024UL * 1024)
76#define GB (1024UL * MB)
77
78typedef int (*vmexit_handler_t)(struct vmctx *, struct vm_exit *, int *vcpu);
79
63#define GUEST_NIO_PORT 0x488 /* guest upcalls via i/o port */
64
65#define VMEXIT_SWITCH 0 /* force vcpu switch in mux mode */
66#define VMEXIT_CONTINUE 1 /* continue from next instruction */
67#define VMEXIT_RESTART 2 /* restart current instruction */
68#define VMEXIT_ABORT 3 /* abort the vm run loop */
69#define VMEXIT_RESET 4 /* guest machine has reset */
70
71#define MB (1024UL * 1024)
72#define GB (1024UL * MB)
73
74typedef int (*vmexit_handler_t)(struct vmctx *, struct vm_exit *, int *vcpu);
75
80int guest_tslice = DEFAULT_GUEST_TSLICE;
81int guest_hz = DEFAULT_GUEST_HZ;
82char *vmname;
83
84int guest_ncpus;
85
86static int pincpu = -1;
76char *vmname;
77
78int guest_ncpus;
79
80static int pincpu = -1;
87static int guest_vcpu_mux;
88static int guest_vmexit_on_hlt, guest_vmexit_on_pause, disable_x2apic;
89
90static int foundcpus;
91
92static int strictio;
93
94static int acpi;
95
96static char *progname;
97static const int BSP = 0;
98
99static int cpumask;
100
101static void vm_loop(struct vmctx *ctx, int vcpu, uint64_t rip);
102
103struct vm_exit vmexit[VM_MAXCPU];
104
81static int guest_vmexit_on_hlt, guest_vmexit_on_pause, disable_x2apic;
82
83static int foundcpus;
84
85static int strictio;
86
87static int acpi;
88
89static char *progname;
90static const int BSP = 0;
91
92static int cpumask;
93
94static void vm_loop(struct vmctx *ctx, int vcpu, uint64_t rip);
95
96struct vm_exit vmexit[VM_MAXCPU];
97
105struct fbsdstats {
98struct bhyvestats {
106 uint64_t vmexit_bogus;
107 uint64_t vmexit_bogus_switch;
108 uint64_t vmexit_hlt;
109 uint64_t vmexit_pause;
110 uint64_t vmexit_mtrap;
111 uint64_t vmexit_paging;
112 uint64_t cpu_switch_rotate;
113 uint64_t cpu_switch_direct;

--- 6 unchanged lines hidden (view full) ---

120 int mt_vcpu;
121} mt_vmm_info[VM_MAXCPU];
122
123static void
124usage(int code)
125{
126
127 fprintf(stderr,
99 uint64_t vmexit_bogus;
100 uint64_t vmexit_bogus_switch;
101 uint64_t vmexit_hlt;
102 uint64_t vmexit_pause;
103 uint64_t vmexit_mtrap;
104 uint64_t vmexit_paging;
105 uint64_t cpu_switch_rotate;
106 uint64_t cpu_switch_direct;

--- 6 unchanged lines hidden (view full) ---

113 int mt_vcpu;
114} mt_vmm_info[VM_MAXCPU];
115
116static void
117usage(int code)
118{
119
120 fprintf(stderr,
128 "Usage: %s [-aehABHIP][-g <gdb port>][-z <hz>][-s <pci>]"
129 "[-S <pci>][-p pincpu][-n <pci>][-m lowmem][-M highmem]"
121 "Usage: %s [-aehAHIP][-g <gdb port>][-s <pci>][-S <pci>]"
122 "[-c vcpus][-p pincpu][-m mem]"
130 " <vmname>\n"
131 " -a: local apic is in XAPIC mode (default is X2APIC)\n"
132 " -A: create an ACPI table\n"
133 " -g: gdb port (default is %d and 0 means don't open)\n"
134 " -c: # cpus (default 1)\n"
135 " -p: pin vcpu 'n' to host cpu 'pincpu + n'\n"
123 " <vmname>\n"
124 " -a: local apic is in XAPIC mode (default is X2APIC)\n"
125 " -A: create an ACPI table\n"
126 " -g: gdb port (default is %d and 0 means don't open)\n"
127 " -c: # cpus (default 1)\n"
128 " -p: pin vcpu 'n' to host cpu 'pincpu + n'\n"
136 " -B: inject breakpoint exception on vm entry\n"
137 " -H: vmexit from the guest on hlt\n"
138 " -I: present an ioapic to the guest\n"
139 " -P: vmexit from the guest on pause\n"
140 " -e: exit on unhandled i/o access\n"
141 " -h: help\n"
129 " -H: vmexit from the guest on hlt\n"
130 " -I: present an ioapic to the guest\n"
131 " -P: vmexit from the guest on pause\n"
132 " -e: exit on unhandled i/o access\n"
133 " -h: help\n"
142 " -z: guest hz (default is %d)\n"
143 " -s: <slot,driver,configinfo> PCI slot config\n"
144 " -S: <slot,driver,configinfo> legacy PCI slot config\n"
134 " -s: <slot,driver,configinfo> PCI slot config\n"
135 " -S: <slot,driver,configinfo> legacy PCI slot config\n"
145 " -m: memory size in MB\n"
146 " -x: mux vcpus to 1 hcpu\n"
147 " -t: mux vcpu timeslice hz (default %d)\n",
148 progname, DEFAULT_GDB_PORT, DEFAULT_GUEST_HZ,
149 DEFAULT_GUEST_TSLICE);
136 " -m: memory size in MB\n",
137 progname, DEFAULT_GDB_PORT);
138
150 exit(code);
151}
152
153void *
154paddr_guest2host(struct vmctx *ctx, uintptr_t gaddr, size_t len)
155{
156
157 return (vm_map_gpa(ctx, gaddr, len));

--- 15 unchanged lines hidden (view full) ---

173
174int
175fbsdrun_vmexit_on_hlt(void)
176{
177
178 return (guest_vmexit_on_hlt);
179}
180
139 exit(code);
140}
141
142void *
143paddr_guest2host(struct vmctx *ctx, uintptr_t gaddr, size_t len)
144{
145
146 return (vm_map_gpa(ctx, gaddr, len));

--- 15 unchanged lines hidden (view full) ---

162
163int
164fbsdrun_vmexit_on_hlt(void)
165{
166
167 return (guest_vmexit_on_hlt);
168}
169
181int
182fbsdrun_muxed(void)
183{
184
185 return (guest_vcpu_mux);
186}
187
188static void *
189fbsdrun_start_thread(void *param)
190{
191 char tname[MAXCOMLEN + 1];
192 struct mt_vmm_info *mtp;
193 int vcpu;
194
195 mtp = param;

--- 25 unchanged lines hidden (view full) ---

221
222 /*
223 * Set up the vmexit struct to allow execution to start
224 * at the given RIP
225 */
226 vmexit[vcpu].rip = rip;
227 vmexit[vcpu].inst_length = 0;
228
170static void *
171fbsdrun_start_thread(void *param)
172{
173 char tname[MAXCOMLEN + 1];
174 struct mt_vmm_info *mtp;
175 int vcpu;
176
177 mtp = param;

--- 25 unchanged lines hidden (view full) ---

203
204 /*
205 * Set up the vmexit struct to allow execution to start
206 * at the given RIP
207 */
208 vmexit[vcpu].rip = rip;
209 vmexit[vcpu].inst_length = 0;
210
229 if (vcpu == BSP || !guest_vcpu_mux){
211 if (vcpu == BSP) {
230 mt_vmm_info[vcpu].mt_ctx = ctx;
231 mt_vmm_info[vcpu].mt_vcpu = vcpu;
232
233 error = pthread_create(&mt_vmm_info[vcpu].mt_thr, NULL,
234 fbsdrun_start_thread, &mt_vmm_info[vcpu]);
235 assert(error == 0);
236 }
237}

--- 21 unchanged lines hidden (view full) ---

259{
260 return (VMEXIT_ABORT);
261}
262
263static int
264vmexit_handle_notify(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu,
265 uint32_t eax)
266{
212 mt_vmm_info[vcpu].mt_ctx = ctx;
213 mt_vmm_info[vcpu].mt_vcpu = vcpu;
214
215 error = pthread_create(&mt_vmm_info[vcpu].mt_thr, NULL,
216 fbsdrun_start_thread, &mt_vmm_info[vcpu]);
217 assert(error == 0);
218 }
219}

--- 21 unchanged lines hidden (view full) ---

241{
242 return (VMEXIT_ABORT);
243}
244
245static int
246vmexit_handle_notify(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu,
247 uint32_t eax)
248{
267#if PG_DEBUG /* put all types of debug here */
268 if (eax == 0) {
269 pause_noswitch = 1;
270 } else if (eax == 1) {
271 pause_noswitch = 0;
272 } else {
273 pause_noswitch = 0;
274 if (eax == 5) {
275 vm_set_capability(ctx, *pvcpu, VM_CAP_MTRAP_EXIT, 1);
276 }
277 }
249#if BHYVE_DEBUG
250 /*
251 * put guest-driven debug here
252 */
278#endif
279 return (VMEXIT_CONTINUE);
280}
281
282static int
283vmexit_inout(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu)
284{
285 int error;

--- 46 unchanged lines hidden (view full) ---

332static int
333vmexit_wrmsr(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu)
334{
335 int newcpu;
336 int retval = VMEXIT_CONTINUE;
337
338 newcpu = emulate_wrmsr(ctx, *pvcpu, vme->u.msr.code,vme->u.msr.wval);
339
253#endif
254 return (VMEXIT_CONTINUE);
255}
256
257static int
258vmexit_inout(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu)
259{
260 int error;

--- 46 unchanged lines hidden (view full) ---

307static int
308vmexit_wrmsr(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu)
309{
310 int newcpu;
311 int retval = VMEXIT_CONTINUE;
312
313 newcpu = emulate_wrmsr(ctx, *pvcpu, vme->u.msr.code,vme->u.msr.wval);
314
340 if (guest_vcpu_mux && *pvcpu != newcpu) {
341 retval = VMEXIT_SWITCH;
342 *pvcpu = newcpu;
343 }
344
345 return (retval);
346}
347
348static int
349vmexit_spinup_ap(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu)
350{
351 int newcpu;
352 int retval = VMEXIT_CONTINUE;
353
354 newcpu = spinup_ap(ctx, *pvcpu,
355 vme->u.spinup_ap.vcpu, vme->u.spinup_ap.rip);
356
315 return (retval);
316}
317
318static int
319vmexit_spinup_ap(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu)
320{
321 int newcpu;
322 int retval = VMEXIT_CONTINUE;
323
324 newcpu = spinup_ap(ctx, *pvcpu,
325 vme->u.spinup_ap.vcpu, vme->u.spinup_ap.rip);
326
357 if (guest_vcpu_mux && *pvcpu != newcpu) {
358 retval = VMEXIT_SWITCH;
359 *pvcpu = newcpu;
360 }
361
362 return (retval);
363}
364
365static int
366vmexit_vmx(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
367{
368
369 fprintf(stderr, "vm exit[%d]\n", *pvcpu);
370 fprintf(stderr, "\treason\t\tVMX\n");
371 fprintf(stderr, "\trip\t\t0x%016lx\n", vmexit->rip);
372 fprintf(stderr, "\tinst_length\t%d\n", vmexit->inst_length);
373 fprintf(stderr, "\terror\t\t%d\n", vmexit->u.vmx.error);
374 fprintf(stderr, "\texit_reason\t%u\n", vmexit->u.vmx.exit_reason);
375 fprintf(stderr, "\tqualification\t0x%016lx\n",
376 vmexit->u.vmx.exit_qualification);
377
378 return (VMEXIT_ABORT);
379}
380
327 return (retval);
328}
329
330static int
331vmexit_vmx(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
332{
333
334 fprintf(stderr, "vm exit[%d]\n", *pvcpu);
335 fprintf(stderr, "\treason\t\tVMX\n");
336 fprintf(stderr, "\trip\t\t0x%016lx\n", vmexit->rip);
337 fprintf(stderr, "\tinst_length\t%d\n", vmexit->inst_length);
338 fprintf(stderr, "\terror\t\t%d\n", vmexit->u.vmx.error);
339 fprintf(stderr, "\texit_reason\t%u\n", vmexit->u.vmx.exit_reason);
340 fprintf(stderr, "\tqualification\t0x%016lx\n",
341 vmexit->u.vmx.exit_qualification);
342
343 return (VMEXIT_ABORT);
344}
345
381static int bogus_noswitch = 1;
382
383static int
384vmexit_bogus(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
385{
346static int
347vmexit_bogus(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
348{
349
386 stats.vmexit_bogus++;
387
350 stats.vmexit_bogus++;
351
388 if (!guest_vcpu_mux || guest_ncpus == 1 || bogus_noswitch) {
389 return (VMEXIT_RESTART);
390 } else {
391 stats.vmexit_bogus_switch++;
392 vmexit->inst_length = 0;
393 *pvcpu = -1;
394 return (VMEXIT_SWITCH);
395 }
352 return (VMEXIT_RESTART);
396}
397
398static int
399vmexit_hlt(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
400{
353}
354
355static int
356vmexit_hlt(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
357{
358
401 stats.vmexit_hlt++;
359 stats.vmexit_hlt++;
402 if (fbsdrun_muxed()) {
403 *pvcpu = -1;
404 return (VMEXIT_SWITCH);
405 } else {
406 /*
407 * Just continue execution with the next instruction. We use
408 * the HLT VM exit as a way to be friendly with the host
409 * scheduler.
410 */
411 return (VMEXIT_CONTINUE);
412 }
360
361 /*
362 * Just continue execution with the next instruction. We use
363 * the HLT VM exit as a way to be friendly with the host
364 * scheduler.
365 */
366 return (VMEXIT_CONTINUE);
413}
414
367}
368
415static int pause_noswitch;
416
417static int
418vmexit_pause(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
419{
369static int
370vmexit_pause(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
371{
372
420 stats.vmexit_pause++;
421
373 stats.vmexit_pause++;
374
422 if (fbsdrun_muxed() && !pause_noswitch) {
423 *pvcpu = -1;
424 return (VMEXIT_SWITCH);
425 } else {
426 return (VMEXIT_CONTINUE);
427 }
375 return (VMEXIT_CONTINUE);
428}
429
430static int
431vmexit_mtrap(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
432{
376}
377
378static int
379vmexit_mtrap(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
380{
381
433 stats.vmexit_mtrap++;
434
435 return (VMEXIT_RESTART);
436}
437
438static int
439vmexit_paging(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
440{

--- 14 unchanged lines hidden (view full) ---

455 }
456
457 return (VMEXIT_ABORT);
458 }
459
460 return (VMEXIT_CONTINUE);
461}
462
382 stats.vmexit_mtrap++;
383
384 return (VMEXIT_RESTART);
385}
386
387static int
388vmexit_paging(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
389{

--- 14 unchanged lines hidden (view full) ---

404 }
405
406 return (VMEXIT_ABORT);
407 }
408
409 return (VMEXIT_CONTINUE);
410}
411
463static void
464sigalrm(int sig)
465{
466 return;
467}
468
469static void
470setup_timeslice(void)
471{
472 struct sigaction sa;
473 struct itimerval itv;
474 int error;
475
476 /*
477 * Setup a realtime timer to generate a SIGALRM at a
478 * frequency of 'guest_tslice' ticks per second.
479 */
480 sigemptyset(&sa.sa_mask);
481 sa.sa_flags = 0;
482 sa.sa_handler = sigalrm;
483
484 error = sigaction(SIGALRM, &sa, NULL);
485 assert(error == 0);
486
487 itv.it_interval.tv_sec = 0;
488 itv.it_interval.tv_usec = 1000000 / guest_tslice;
489 itv.it_value.tv_sec = 0;
490 itv.it_value.tv_usec = 1000000 / guest_tslice;
491
492 error = setitimer(ITIMER_REAL, &itv, NULL);
493 assert(error == 0);
494}
495
496static vmexit_handler_t handler[VM_EXITCODE_MAX] = {
497 [VM_EXITCODE_INOUT] = vmexit_inout,
498 [VM_EXITCODE_VMX] = vmexit_vmx,
499 [VM_EXITCODE_BOGUS] = vmexit_bogus,
500 [VM_EXITCODE_RDMSR] = vmexit_rdmsr,
501 [VM_EXITCODE_WRMSR] = vmexit_wrmsr,
502 [VM_EXITCODE_MTRAP] = vmexit_mtrap,
503 [VM_EXITCODE_PAGING] = vmexit_paging,
504 [VM_EXITCODE_SPINUP_AP] = vmexit_spinup_ap,
505};
506
507static void
508vm_loop(struct vmctx *ctx, int vcpu, uint64_t rip)
509{
510 cpuset_t mask;
511 int error, rc, prevcpu;
512 enum vm_exitcode exitcode;
513
412static vmexit_handler_t handler[VM_EXITCODE_MAX] = {
413 [VM_EXITCODE_INOUT] = vmexit_inout,
414 [VM_EXITCODE_VMX] = vmexit_vmx,
415 [VM_EXITCODE_BOGUS] = vmexit_bogus,
416 [VM_EXITCODE_RDMSR] = vmexit_rdmsr,
417 [VM_EXITCODE_WRMSR] = vmexit_wrmsr,
418 [VM_EXITCODE_MTRAP] = vmexit_mtrap,
419 [VM_EXITCODE_PAGING] = vmexit_paging,
420 [VM_EXITCODE_SPINUP_AP] = vmexit_spinup_ap,
421};
422
423static void
424vm_loop(struct vmctx *ctx, int vcpu, uint64_t rip)
425{
426 cpuset_t mask;
427 int error, rc, prevcpu;
428 enum vm_exitcode exitcode;
429
514 if (guest_vcpu_mux)
515 setup_timeslice();
516
517 if (pincpu >= 0) {
518 CPU_ZERO(&mask);
519 CPU_SET(pincpu + vcpu, &mask);
520 error = pthread_setaffinity_np(pthread_self(),
521 sizeof(mask), &mask);
522 assert(error == 0);
523 }
524

--- 20 unchanged lines hidden (view full) ---

545 fprintf(stderr, "vm_loop: unexpected exitcode 0x%x\n",
546 exitcode);
547 exit(1);
548 }
549
550 rc = (*handler[exitcode])(ctx, &vmexit[vcpu], &vcpu);
551
552 switch (rc) {
430 if (pincpu >= 0) {
431 CPU_ZERO(&mask);
432 CPU_SET(pincpu + vcpu, &mask);
433 error = pthread_setaffinity_np(pthread_self(),
434 sizeof(mask), &mask);
435 assert(error == 0);
436 }
437

--- 20 unchanged lines hidden (view full) ---

458 fprintf(stderr, "vm_loop: unexpected exitcode 0x%x\n",
459 exitcode);
460 exit(1);
461 }
462
463 rc = (*handler[exitcode])(ctx, &vmexit[vcpu], &vcpu);
464
465 switch (rc) {
553 case VMEXIT_SWITCH:
554 assert(guest_vcpu_mux);
555 if (vcpu == -1) {
556 stats.cpu_switch_rotate++;
557 vcpu = fbsdrun_get_next_cpu(prevcpu);
558 } else {
559 stats.cpu_switch_direct++;
560 }
561 /* fall through */
562 case VMEXIT_CONTINUE:
563 rip = vmexit[vcpu].rip + vmexit[vcpu].inst_length;
564 break;
565 case VMEXIT_RESTART:
566 rip = vmexit[vcpu].rip;
567 break;
568 case VMEXIT_RESET:
569 exit(0);

--- 19 unchanged lines hidden (view full) ---

589 return (VM_MAXCPU);
590 else
591 return (1);
592}
593
594int
595main(int argc, char *argv[])
596{
466 case VMEXIT_CONTINUE:
467 rip = vmexit[vcpu].rip + vmexit[vcpu].inst_length;
468 break;
469 case VMEXIT_RESTART:
470 rip = vmexit[vcpu].rip;
471 break;
472 case VMEXIT_RESET:
473 exit(0);

--- 19 unchanged lines hidden (view full) ---

493 return (VM_MAXCPU);
494 else
495 return (1);
496}
497
498int
499main(int argc, char *argv[])
500{
597 int c, error, gdb_port, inject_bkpt, tmp, err, ioapic, bvmcons;
501 int c, error, gdb_port, tmp, err, ioapic, bvmcons;
598 int max_vcpus;
599 struct vmctx *ctx;
600 uint64_t rip;
601 size_t memsize;
602
603 bvmcons = 0;
502 int max_vcpus;
503 struct vmctx *ctx;
504 uint64_t rip;
505 size_t memsize;
506
507 bvmcons = 0;
604 inject_bkpt = 0;
605 progname = basename(argv[0]);
606 gdb_port = DEFAULT_GDB_PORT;
607 guest_ncpus = 1;
608 ioapic = 0;
609 memsize = 256 * MB;
610
508 progname = basename(argv[0]);
509 gdb_port = DEFAULT_GDB_PORT;
510 guest_ncpus = 1;
511 ioapic = 0;
512 memsize = 256 * MB;
513
611 while ((c = getopt(argc, argv, "abehABHIPxp:g:c:z:s:S:n:m:")) != -1) {
514 while ((c = getopt(argc, argv, "abehAHIPp:g:c:s:S:m:")) != -1) {
612 switch (c) {
613 case 'a':
614 disable_x2apic = 1;
615 break;
616 case 'A':
617 acpi = 1;
618 break;
619 case 'b':
620 bvmcons = 1;
621 break;
515 switch (c) {
516 case 'a':
517 disable_x2apic = 1;
518 break;
519 case 'A':
520 acpi = 1;
521 break;
522 case 'b':
523 bvmcons = 1;
524 break;
622 case 'B':
623 inject_bkpt = 1;
624 break;
625 case 'x':
626 guest_vcpu_mux = 1;
627 break;
628 case 'p':
629 pincpu = atoi(optarg);
630 break;
631 case 'c':
632 guest_ncpus = atoi(optarg);
633 break;
634 case 'g':
635 gdb_port = atoi(optarg);
636 break;
525 case 'p':
526 pincpu = atoi(optarg);
527 break;
528 case 'c':
529 guest_ncpus = atoi(optarg);
530 break;
531 case 'g':
532 gdb_port = atoi(optarg);
533 break;
637 case 'z':
638 guest_hz = atoi(optarg);
639 break;
640 case 't':
641 guest_tslice = atoi(optarg);
642 break;
643 case 's':
644 if (pci_parse_slot(optarg, 0) != 0)
645 exit(1);
646 else
647 break;
648 case 'S':
649 if (pci_parse_slot(optarg, 1) != 0)
650 exit(1);

--- 21 unchanged lines hidden (view full) ---

672 }
673 }
674 argc -= optind;
675 argv += optind;
676
677 if (argc != 1)
678 usage(1);
679
534 case 's':
535 if (pci_parse_slot(optarg, 0) != 0)
536 exit(1);
537 else
538 break;
539 case 'S':
540 if (pci_parse_slot(optarg, 1) != 0)
541 exit(1);

--- 21 unchanged lines hidden (view full) ---

563 }
564 }
565 argc -= optind;
566 argv += optind;
567
568 if (argc != 1)
569 usage(1);
570
680 /* No need to mux if guest is uni-processor */
681 if (guest_ncpus <= 1)
682 guest_vcpu_mux = 0;
683
684 /* vmexit on hlt if guest is muxed */
685 if (guest_vcpu_mux) {
686 guest_vmexit_on_hlt = 1;
687 guest_vmexit_on_pause = 1;
688 }
689
690 vmname = argv[0];
691
692 ctx = vm_open(vmname);
693 if (ctx == NULL) {
694 perror("vm_open");
695 exit(1);
696 }
697

--- 62 unchanged lines hidden (view full) ---

760 init_dbgport(gdb_port);
761
762 if (bvmcons)
763 init_bvmcons();
764
765 error = vm_get_register(ctx, BSP, VM_REG_GUEST_RIP, &rip);
766 assert(error == 0);
767
571 vmname = argv[0];
572
573 ctx = vm_open(vmname);
574 if (ctx == NULL) {
575 perror("vm_open");
576 exit(1);
577 }
578

--- 62 unchanged lines hidden (view full) ---

641 init_dbgport(gdb_port);
642
643 if (bvmcons)
644 init_bvmcons();
645
646 error = vm_get_register(ctx, BSP, VM_REG_GUEST_RIP, &rip);
647 assert(error == 0);
648
768 if (inject_bkpt) {
769 error = vm_inject_event(ctx, BSP, VM_HW_EXCEPTION, IDT_BP);
770 assert(error == 0);
771 }
772
773 /*
774 * build the guest tables, MP etc.
775 */
776 mptable_build(ctx, guest_ncpus, ioapic);
777
778 if (acpi) {
779 error = acpi_build(ctx, guest_ncpus, ioapic);
780 assert(error == 0);

--- 14 unchanged lines hidden ---
649 /*
650 * build the guest tables, MP etc.
651 */
652 mptable_build(ctx, guest_ncpus, ioapic);
653
654 if (acpi) {
655 error = acpi_build(ctx, guest_ncpus, ioapic);
656 assert(error == 0);

--- 14 unchanged lines hidden ---