diff options
-rw-r--r-- | lib/libvmmapi/vmmapi.c | 14 | ||||
-rw-r--r-- | lib/libvmmapi/vmmapi.h | 2 | ||||
-rw-r--r-- | sys/amd64/include/vmm.h | 2 | ||||
-rw-r--r-- | sys/amd64/vmm/intel/vmx.c | 48 | ||||
-rw-r--r-- | sys/amd64/vmm/vmm.c | 57 | ||||
-rw-r--r-- | sys/amd64/vmm/vmm_stat.c | 13 | ||||
-rw-r--r-- | sys/amd64/vmm/vmm_stat.h | 39 | ||||
-rw-r--r-- | usr.sbin/bhyve/pci_emul.c | 3 | ||||
-rw-r--r-- | usr.sbin/bhyve/rtc.c | 15 | ||||
-rw-r--r-- | usr.sbin/bhyve/smbiostbl.c | 9 | ||||
-rw-r--r-- | usr.sbin/bhyveload/bhyveload.c | 4 |
11 files changed, 146 insertions, 60 deletions
diff --git a/lib/libvmmapi/vmmapi.c b/lib/libvmmapi/vmmapi.c index 5ce3d8e..9fb2308 100644 --- a/lib/libvmmapi/vmmapi.c +++ b/lib/libvmmapi/vmmapi.c @@ -274,6 +274,20 @@ vm_map_gpa(struct vmctx *ctx, vm_paddr_t gaddr, size_t len) return (NULL); } +size_t +vm_get_lowmem_size(struct vmctx *ctx) +{ + + return (ctx->lowmem); +} + +size_t +vm_get_highmem_size(struct vmctx *ctx) +{ + + return (ctx->highmem); +} + int vm_set_desc(struct vmctx *ctx, int vcpu, int reg, uint64_t base, uint32_t limit, uint32_t access) diff --git a/lib/libvmmapi/vmmapi.h b/lib/libvmmapi/vmmapi.h index 4cc4290..067eaa0 100644 --- a/lib/libvmmapi/vmmapi.h +++ b/lib/libvmmapi/vmmapi.h @@ -60,6 +60,8 @@ int vm_get_gpa_pmap(struct vmctx *, uint64_t gpa, uint64_t *pte, int *num); uint32_t vm_get_lowmem_limit(struct vmctx *ctx); void vm_set_lowmem_limit(struct vmctx *ctx, uint32_t limit); void vm_set_memflags(struct vmctx *ctx, int flags); +size_t vm_get_lowmem_size(struct vmctx *ctx); +size_t vm_get_highmem_size(struct vmctx *ctx); int vm_set_desc(struct vmctx *ctx, int vcpu, int reg, uint64_t base, uint32_t limit, uint32_t access); int vm_get_desc(struct vmctx *ctx, int vcpu, int reg, diff --git a/sys/amd64/include/vmm.h b/sys/amd64/include/vmm.h index 00e1d96..86f696d 100644 --- a/sys/amd64/include/vmm.h +++ b/sys/amd64/include/vmm.h @@ -146,6 +146,8 @@ cpuset_t vm_active_cpus(struct vm *vm); cpuset_t vm_suspended_cpus(struct vm *vm); struct vm_exit *vm_exitinfo(struct vm *vm, int vcpuid); void vm_exit_suspended(struct vm *vm, int vcpuid, uint64_t rip); +void vm_exit_rendezvous(struct vm *vm, int vcpuid, uint64_t rip); +void vm_exit_astpending(struct vm *vm, int vcpuid, uint64_t rip); /* * Rendezvous all vcpus specified in 'dest' and execute 'func(arg)'. diff --git a/sys/amd64/vmm/intel/vmx.c b/sys/amd64/vmm/intel/vmx.c index 7390ccc..2cbb159 100644 --- a/sys/amd64/vmm/intel/vmx.c +++ b/sys/amd64/vmm/intel/vmx.c @@ -1327,9 +1327,13 @@ vmx_inject_interrupts(struct vmx *vmx, int vcpu, struct vlapic *vlapic) * have posted another one. If that is the case, set * the Interrupt Window Exiting execution control so * we can inject that one too. + * + * Also, interrupt window exiting allows us to inject any + * pending APIC vector that was preempted by the ExtINT + * as soon as possible. This applies both for the software + * emulated vlapic and the hardware assisted virtual APIC. */ - if (vm_extint_pending(vmx->vm, vcpu)) - vmx_set_int_window_exiting(vmx, vcpu); + vmx_set_int_window_exiting(vmx, vcpu); } VCPU_CTR1(vmx->vm, vcpu, "Injecting hwintr at vector %d", vector); @@ -2275,32 +2279,7 @@ vmx_exit_process(struct vmx *vmx, int vcpu, struct vm_exit *vmexit) return (handled); } -static __inline int -vmx_exit_astpending(struct vmx *vmx, int vcpu, struct vm_exit *vmexit) -{ - - vmexit->rip = vmcs_guest_rip(); - vmexit->inst_length = 0; - vmexit->exitcode = VM_EXITCODE_BOGUS; - vmx_astpending_trace(vmx, vcpu, vmexit->rip); - vmm_stat_incr(vmx->vm, vcpu, VMEXIT_ASTPENDING, 1); - - return (HANDLED); -} - -static __inline int -vmx_exit_rendezvous(struct vmx *vmx, int vcpu, struct vm_exit *vmexit) -{ - - vmexit->rip = vmcs_guest_rip(); - vmexit->inst_length = 0; - vmexit->exitcode = VM_EXITCODE_RENDEZVOUS; - vmm_stat_incr(vmx->vm, vcpu, VMEXIT_RENDEZVOUS, 1); - - return (UNHANDLED); -} - -static __inline int +static __inline void vmx_exit_inst_error(struct vmxctx *vmxctx, int rc, struct vm_exit *vmexit) { @@ -2324,8 +2303,6 @@ vmx_exit_inst_error(struct vmxctx *vmxctx, int rc, struct vm_exit *vmexit) default: panic("vm_exit_inst_error: vmx_enter_guest returned %d", rc); } - - return (UNHANDLED); } /* @@ -2398,6 +2375,8 @@ vmx_run(void *arg, int vcpu, register_t startrip, pmap_t pmap, vmcs_write(VMCS_GUEST_RIP, startrip); vmx_set_pcpu_defaults(vmx, vcpu, pmap); do { + handled = UNHANDLED; + /* * Interrupts are disabled from this point on until the * guest starts executing. This is done for the following @@ -2420,19 +2399,20 @@ vmx_run(void *arg, int vcpu, register_t startrip, pmap_t pmap, if (vcpu_suspended(suspend_cookie)) { enable_intr(); vm_exit_suspended(vmx->vm, vcpu, vmcs_guest_rip()); - handled = UNHANDLED; break; } if (vcpu_rendezvous_pending(rendezvous_cookie)) { enable_intr(); - handled = vmx_exit_rendezvous(vmx, vcpu, vmexit); + vm_exit_rendezvous(vmx->vm, vcpu, vmcs_guest_rip()); break; } if (curthread->td_flags & (TDF_ASTPENDING | TDF_NEEDRESCHED)) { enable_intr(); - handled = vmx_exit_astpending(vmx, vcpu, vmexit); + vm_exit_astpending(vmx->vm, vcpu, vmcs_guest_rip()); + vmx_astpending_trace(vmx, vcpu, vmexit->rip); + handled = HANDLED; break; } @@ -2452,7 +2432,7 @@ vmx_run(void *arg, int vcpu, register_t startrip, pmap_t pmap, handled = vmx_exit_process(vmx, vcpu, vmexit); } else { enable_intr(); - handled = vmx_exit_inst_error(vmxctx, rc, vmexit); + vmx_exit_inst_error(vmxctx, rc, vmexit); } launched = 1; vmx_exit_trace(vmx, vcpu, rip, exit_reason, handled); diff --git a/sys/amd64/vmm/vmm.c b/sys/amd64/vmm/vmm.c index 435ba39..c2a9fd1 100644 --- a/sys/amd64/vmm/vmm.c +++ b/sys/amd64/vmm/vmm.c @@ -1331,6 +1331,32 @@ vm_exit_suspended(struct vm *vm, int vcpuid, uint64_t rip) vmexit->u.suspended.how = vm->suspend; } +void +vm_exit_rendezvous(struct vm *vm, int vcpuid, uint64_t rip) +{ + struct vm_exit *vmexit; + + KASSERT(vm->rendezvous_func != NULL, ("rendezvous not in progress")); + + vmexit = vm_exitinfo(vm, vcpuid); + vmexit->rip = rip; + vmexit->inst_length = 0; + vmexit->exitcode = VM_EXITCODE_RENDEZVOUS; + vmm_stat_incr(vm, vcpuid, VMEXIT_RENDEZVOUS, 1); +} + +void +vm_exit_astpending(struct vm *vm, int vcpuid, uint64_t rip) +{ + struct vm_exit *vmexit; + + vmexit = vm_exitinfo(vm, vcpuid); + vmexit->rip = rip; + vmexit->inst_length = 0; + vmexit->exitcode = VM_EXITCODE_BOGUS; + vmm_stat_incr(vm, vcpuid, VMEXIT_ASTPENDING, 1); +} + int vm_run(struct vm *vm, struct vm_run *vmrun) { @@ -1966,3 +1992,34 @@ vm_segment_name(int seg) ("%s: invalid segment encoding %d", __func__, seg)); return (seg_names[seg]); } + + +/* + * Return the amount of in-use and wired memory for the VM. Since + * these are global stats, only return the values with for vCPU 0 + */ +VMM_STAT_DECLARE(VMM_MEM_RESIDENT); +VMM_STAT_DECLARE(VMM_MEM_WIRED); + +static void +vm_get_rescnt(struct vm *vm, int vcpu, struct vmm_stat_type *stat) +{ + + if (vcpu == 0) { + vmm_stat_set(vm, vcpu, VMM_MEM_RESIDENT, + PAGE_SIZE * vmspace_resident_count(vm->vmspace)); + } +} + +static void +vm_get_wiredcnt(struct vm *vm, int vcpu, struct vmm_stat_type *stat) +{ + + if (vcpu == 0) { + vmm_stat_set(vm, vcpu, VMM_MEM_WIRED, + PAGE_SIZE * pmap_wired_count(vmspace_pmap(vm->vmspace))); + } +} + +VMM_STAT_FUNC(VMM_MEM_RESIDENT, "Resident memory", vm_get_rescnt); +VMM_STAT_FUNC(VMM_MEM_WIRED, "Wired memory", vm_get_wiredcnt); diff --git a/sys/amd64/vmm/vmm_stat.c b/sys/amd64/vmm/vmm_stat.c index ef9f411..9ecf9af 100644 --- a/sys/amd64/vmm/vmm_stat.c +++ b/sys/amd64/vmm/vmm_stat.c @@ -83,12 +83,21 @@ vmm_stat_register(void *arg) int vmm_stat_copy(struct vm *vm, int vcpu, int *num_stats, uint64_t *buf) { - int i; + struct vmm_stat_type *vst; uint64_t *stats; + int i; if (vcpu < 0 || vcpu >= VM_MAXCPU) return (EINVAL); - + + /* Let stats functions update their counters */ + for (i = 0; i < vst_num_types; i++) { + vst = vsttab[i]; + if (vst->func != NULL) + (*vst->func)(vm, vcpu, vst); + } + + /* Copy over the stats */ stats = vcpu_stats(vm, vcpu); for (i = 0; i < vst_num_elems; i++) buf[i] = stats[i]; diff --git a/sys/amd64/vmm/vmm_stat.h b/sys/amd64/vmm/vmm_stat.h index 6e98965..1640ba3 100644 --- a/sys/amd64/vmm/vmm_stat.h +++ b/sys/amd64/vmm/vmm_stat.h @@ -42,21 +42,29 @@ enum vmm_stat_scope { VMM_STAT_SCOPE_AMD, /* AMD SVM specific statistic */ }; +struct vmm_stat_type; +typedef void (*vmm_stat_func_t)(struct vm *vm, int vcpu, + struct vmm_stat_type *stat); + struct vmm_stat_type { int index; /* position in the stats buffer */ int nelems; /* standalone or array */ const char *desc; /* description of statistic */ + vmm_stat_func_t func; enum vmm_stat_scope scope; }; void vmm_stat_register(void *arg); -#define VMM_STAT_DEFINE(type, nelems, desc, scope) \ +#define VMM_STAT_FDEFINE(type, nelems, desc, func, scope) \ struct vmm_stat_type type[1] = { \ - { -1, nelems, desc, scope } \ + { -1, nelems, desc, func, scope } \ }; \ SYSINIT(type##_stat, SI_SUB_KLD, SI_ORDER_ANY, vmm_stat_register, type) +#define VMM_STAT_DEFINE(type, nelems, desc, scope) \ + VMM_STAT_FDEFINE(type, nelems, desc, NULL, scope) + #define VMM_STAT_DECLARE(type) \ extern struct vmm_stat_type type[1] @@ -67,6 +75,9 @@ void vmm_stat_register(void *arg); #define VMM_STAT_AMD(type, desc) \ VMM_STAT_DEFINE(type, 1, desc, VMM_STAT_SCOPE_AMD) +#define VMM_STAT_FUNC(type, desc, func) \ + VMM_STAT_FDEFINE(type, 1, desc, func, VMM_STAT_SCOPE_ANY) + #define VMM_STAT_ARRAY(type, nelems, desc) \ VMM_STAT_DEFINE(type, nelems, desc, VMM_STAT_SCOPE_ANY) @@ -93,9 +104,22 @@ vmm_stat_array_incr(struct vm *vm, int vcpu, struct vmm_stat_type *vst, stats[vst->index + statidx] += x; #endif } - static void __inline +vmm_stat_array_set(struct vm *vm, int vcpu, struct vmm_stat_type *vst, + int statidx, uint64_t val) +{ +#ifdef VMM_KEEP_STATS + uint64_t *stats; + + stats = vcpu_stats(vm, vcpu); + + if (vst->index >= 0 && statidx < vst->nelems) + stats[vst->index + statidx] = val; +#endif +} + +static void __inline vmm_stat_incr(struct vm *vm, int vcpu, struct vmm_stat_type *vst, uint64_t x) { @@ -104,6 +128,15 @@ vmm_stat_incr(struct vm *vm, int vcpu, struct vmm_stat_type *vst, uint64_t x) #endif } +static void __inline +vmm_stat_set(struct vm *vm, int vcpu, struct vmm_stat_type *vst, uint64_t val) +{ + +#ifdef VMM_KEEP_STATS + vmm_stat_array_set(vm, vcpu, vst, 0, val); +#endif +} + VMM_STAT_DECLARE(VCPU_MIGRATIONS); VMM_STAT_DECLARE(VMEXIT_COUNT); VMM_STAT_DECLARE(VMEXIT_EXTINT); diff --git a/usr.sbin/bhyve/pci_emul.c b/usr.sbin/bhyve/pci_emul.c index a2c47ec..458ba76 100644 --- a/usr.sbin/bhyve/pci_emul.c +++ b/usr.sbin/bhyve/pci_emul.c @@ -1118,8 +1118,7 @@ init_pci(struct vmctx *ctx) * Accesses to memory addresses that are not allocated to system * memory or PCI devices return 0xff's. */ - error = vm_get_memory_seg(ctx, 0, &lowmem, NULL); - assert(error == 0); + lowmem = vm_get_lowmem_size(ctx); memset(&pci_mem_hole, 0, sizeof(struct mem_range)); pci_mem_hole.name = "PCI hole"; diff --git a/usr.sbin/bhyve/rtc.c b/usr.sbin/bhyve/rtc.c index 1187747..b3631fc 100644 --- a/usr.sbin/bhyve/rtc.c +++ b/usr.sbin/bhyve/rtc.c @@ -343,19 +343,14 @@ rtc_init(struct vmctx *ctx) * 0x34/0x35 - 64KB chunks above 16MB, below 4GB * 0x5b/0x5c/0x5d - 64KB chunks above 4GB */ - err = vm_get_memory_seg(ctx, 0, &lomem, NULL); - assert(err == 0); - - lomem = (lomem - m_16MB) / m_64KB; + lomem = (vm_get_lowmem_size(ctx) - m_16MB) / m_64KB; rtc_nvram[nvoff(RTC_LMEM_LSB)] = lomem; rtc_nvram[nvoff(RTC_LMEM_MSB)] = lomem >> 8; - if (vm_get_memory_seg(ctx, m_4GB, &himem, NULL) == 0) { - himem /= m_64KB; - rtc_nvram[nvoff(RTC_HMEM_LSB)] = himem; - rtc_nvram[nvoff(RTC_HMEM_SB)] = himem >> 8; - rtc_nvram[nvoff(RTC_HMEM_MSB)] = himem >> 16; - } + himem = vm_get_highmem_size(ctx) / m_64KB; + rtc_nvram[nvoff(RTC_HMEM_LSB)] = himem; + rtc_nvram[nvoff(RTC_HMEM_SB)] = himem >> 8; + rtc_nvram[nvoff(RTC_HMEM_MSB)] = himem >> 16; } INOUT_PORT(rtc, IO_RTC, IOPORT_F_INOUT, rtc_addr_handler); diff --git a/usr.sbin/bhyve/smbiostbl.c b/usr.sbin/bhyve/smbiostbl.c index 9d1cfb3..d560f02 100644 --- a/usr.sbin/bhyve/smbiostbl.c +++ b/usr.sbin/bhyve/smbiostbl.c @@ -779,13 +779,8 @@ smbios_build(struct vmctx *ctx) int i; int err; - err = vm_get_memory_seg(ctx, 0, &guest_lomem, NULL); - if (err != 0) - return (err); - - err = vm_get_memory_seg(ctx, 4*GB, &guest_himem, NULL); - if (err != 0) - return (err); + guest_lomem = vm_get_lowmem_size(ctx); + guest_himem = vm_get_highmem_size(ctx); startaddr = paddr_guest2host(ctx, SMBIOS_BASE, SMBIOS_MAX_LENGTH); if (startaddr == NULL) { diff --git a/usr.sbin/bhyveload/bhyveload.c b/usr.sbin/bhyveload/bhyveload.c index 4442496..ff6b269 100644 --- a/usr.sbin/bhyveload/bhyveload.c +++ b/usr.sbin/bhyveload/bhyveload.c @@ -505,8 +505,8 @@ static void cb_getmem(void *arg, uint64_t *ret_lowmem, uint64_t *ret_highmem) { - vm_get_memory_seg(ctx, 0, ret_lowmem, NULL); - vm_get_memory_seg(ctx, 4 * GB, ret_highmem, NULL); + *ret_lowmem = vm_get_lowmem_size(ctx); + *ret_highmem = vm_get_highmem_size(ctx); } struct env { |