Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/bhyvectl/amd64/bhyvectl_machdep.c
| Show All 25 Lines | |||||
| * SUCH DAMAGE. | * SUCH DAMAGE. | ||||
| */ | */ | ||||
| #include <sys/types.h> | #include <sys/types.h> | ||||
| #include <sys/mman.h> | #include <sys/mman.h> | ||||
| #include <machine/cpufunc.h> | #include <machine/cpufunc.h> | ||||
| #include <machine/specialreg.h> | #include <machine/specialreg.h> | ||||
| #include <machine/vmm.h> | |||||
| #include <err.h> | #include <err.h> | ||||
| #include <fcntl.h> | #include <fcntl.h> | ||||
| #include <getopt.h> | #include <getopt.h> | ||||
| #include <stdbool.h> | #include <stdbool.h> | ||||
| #include <stdio.h> | #include <stdio.h> | ||||
| #include <stdlib.h> | #include <stdlib.h> | ||||
| #include <string.h> | #include <string.h> | ||||
| #include <time.h> | #include <time.h> | ||||
| #include <unistd.h> | #include <unistd.h> | ||||
| #include <ctype.h> | |||||
| #include <vmmapi.h> | #include <vmmapi.h> | ||||
| #include "amd/vmcb.h" | #include "amd/vmcb.h" | ||||
| #include "intel/vmcs.h" | #include "intel/vmcs.h" | ||||
| #include "bhyvectl.h" | #include "bhyvectl.h" | ||||
| enum { | enum { | ||||
| Show All 36 Lines | |||||
| static int get_rtc_nvram, set_rtc_nvram; | static int get_rtc_nvram, set_rtc_nvram; | ||||
| static int rtc_nvram_offset; | static int rtc_nvram_offset; | ||||
| static uint8_t rtc_nvram_value; | static uint8_t rtc_nvram_value; | ||||
| static time_t rtc_secs; | static time_t rtc_secs; | ||||
| static int get_gpa_pmap; | static int get_gpa_pmap; | ||||
| static vm_paddr_t gpa_pmap; | static vm_paddr_t gpa_pmap; | ||||
| static int inject_nmi, assert_lapic_lvt = -1; | static int inject_nmi, assert_lapic_lvt = -1; | ||||
| static int get_intinfo; | static int get_intinfo; | ||||
| static int get_cpuid_cfg; | |||||
| static int set_cr0, get_cr0, set_cr2, get_cr2, set_cr3, get_cr3; | static int set_cr0, get_cr0, set_cr2, get_cr2, set_cr3, get_cr3; | ||||
| static int set_cr4, get_cr4; | static int set_cr4, get_cr4; | ||||
| static uint64_t set_cr0_val, set_cr2_val, set_cr3_val, set_cr4_val; | static uint64_t set_cr0_val, set_cr2_val, set_cr3_val, set_cr4_val; | ||||
| static int set_efer, get_efer; | static int set_efer, get_efer; | ||||
| static uint64_t set_efer_val; | static uint64_t set_efer_val; | ||||
| static int set_dr0, get_dr0; | static int set_dr0, get_dr0; | ||||
| static int set_dr1, get_dr1; | static int set_dr1, get_dr1; | ||||
| static int set_dr2, get_dr2; | static int set_dr2, get_dr2; | ||||
| ▲ Show 20 Lines • Show All 169 Lines • ▼ Show 20 Lines | if (info & VM_INTINFO_VALID) { | ||||
| if (info & VM_INTINFO_DEL_ERRCODE) | if (info & VM_INTINFO_DEL_ERRCODE) | ||||
| printf(" errcode %#x", (u_int)(info >> 32)); | printf(" errcode %#x", (u_int)(info >> 32)); | ||||
| } else { | } else { | ||||
| printf("n/a"); | printf("n/a"); | ||||
| } | } | ||||
| printf("\n"); | printf("\n"); | ||||
| } | } | ||||
| static void | |||||
| print_cpuid_cfg(struct vm_vcpu_cpuid_config *vvcc) | |||||
| { | |||||
| printf("CPUID configuration for vcpu %d: flags = 0x%x, nent = %d\n", | |||||
| vvcc->vvcc_vcpuid, vvcc->vvcc_flags, vvcc->vvcc_nent); | |||||
| if (vvcc->vvcc_nent == 0) | |||||
| return; | |||||
| printf("%10s,%5s %10s %10s %10s %10s %16s\n", | |||||
| "Function", "Index", "EAX", "EBX", "ECX", "EDX", "ASCII"); | |||||
| for (uint32_t i = 0; i != vvcc->vvcc_nent; i++) { | |||||
| struct vcpu_cpuid_entry *vce = | |||||
| &((struct vcpu_cpuid_entry *)vvcc->vvcc_entries)[i]; | |||||
| char *regs = (char *)&vce->vce_eax; | |||||
| printf("0x%.8x", vce->vce_function); | |||||
| if ((vce->vce_flags & VCE_FLAG_MATCH_INDEX) != 0) | |||||
| printf(",0x%.3x: ", vce->vce_index); | |||||
| else | |||||
| printf(": "); | |||||
| printf("0x%.8x,0x%.8x,0x%.8x,0x%.8x ", | |||||
| vce->vce_eax, vce->vce_ebx, vce->vce_ecx, vce->vce_edx); | |||||
| for (int j = 0; j != 16; j++) | |||||
| printf("%c", isprint(regs[j]) ? regs[j] : '.'); | |||||
| printf("\n"); | |||||
| } | |||||
| } | |||||
| /* AMD 6th generation and Intel compatible MSRs */ | /* AMD 6th generation and Intel compatible MSRs */ | ||||
| #define MSR_AMD6TH_START 0xC0000000 | #define MSR_AMD6TH_START 0xC0000000 | ||||
| #define MSR_AMD6TH_END 0xC0001FFF | #define MSR_AMD6TH_END 0xC0001FFF | ||||
| /* AMD 7th and 8th generation compatible MSRs */ | /* AMD 7th and 8th generation compatible MSRs */ | ||||
| #define MSR_AMD7TH_START 0xC0010000 | #define MSR_AMD7TH_START 0xC0010000 | ||||
| #define MSR_AMD7TH_END 0xC0011FFF | #define MSR_AMD7TH_END 0xC0011FFF | ||||
| static const char * | static const char * | ||||
| ▲ Show 20 Lines • Show All 923 Lines • ▼ Show 20 Lines | const struct option common_opts[] = { | ||||
| { "get-msr-bitmap", NO_ARG, &get_msr_bitmap, 1 }, | { "get-msr-bitmap", NO_ARG, &get_msr_bitmap, 1 }, | ||||
| { "get-msr-bitmap-address", NO_ARG, &get_msr_bitmap_address, 1}, | { "get-msr-bitmap-address", NO_ARG, &get_msr_bitmap_address, 1}, | ||||
| { "get-guest-pat", NO_ARG, &get_guest_pat, 1 }, | { "get-guest-pat", NO_ARG, &get_guest_pat, 1 }, | ||||
| { "get-guest-sysenter", NO_ARG, &get_guest_sysenter, 1 }, | { "get-guest-sysenter", NO_ARG, &get_guest_sysenter, 1 }, | ||||
| { "get-exit-reason", NO_ARG, &get_exit_reason, 1 }, | { "get-exit-reason", NO_ARG, &get_exit_reason, 1 }, | ||||
| { "get-x2apic-state", NO_ARG, &get_x2apic_state, 1 }, | { "get-x2apic-state", NO_ARG, &get_x2apic_state, 1 }, | ||||
| { "inject-nmi", NO_ARG, &inject_nmi, 1 }, | { "inject-nmi", NO_ARG, &inject_nmi, 1 }, | ||||
| { "get-intinfo", NO_ARG, &get_intinfo, 1 }, | { "get-intinfo", NO_ARG, &get_intinfo, 1 }, | ||||
| { "get-cpuid-cfg", NO_ARG, &get_cpuid_cfg, 1 }, | |||||
| }; | }; | ||||
| const struct option intel_opts[] = { | const struct option intel_opts[] = { | ||||
| { "get-vmcs-pinbased-ctls", | { "get-vmcs-pinbased-ctls", | ||||
| NO_ARG, &get_pinbased_ctls, 1 }, | NO_ARG, &get_pinbased_ctls, 1 }, | ||||
| { "get-vmcs-procbased-ctls", | { "get-vmcs-procbased-ctls", | ||||
| NO_ARG, &get_procbased_ctls, 1 }, | NO_ARG, &get_procbased_ctls, 1 }, | ||||
| { "get-vmcs-procbased-ctls2", | { "get-vmcs-procbased-ctls2", | ||||
| NO_ARG, &get_procbased_ctls2, 1 }, | NO_ARG, &get_procbased_ctls2, 1 }, | ||||
| ▲ Show 20 Lines • Show All 650 Lines • ▼ Show 20 Lines | if (!error && (get_rtc_time || get_all)) { | ||||
| } | } | ||||
| } | } | ||||
| if (!error && (get_intinfo || get_all)) { | if (!error && (get_intinfo || get_all)) { | ||||
| error = vm_get_intinfo(vcpu, &info[0], &info[1]); | error = vm_get_intinfo(vcpu, &info[0], &info[1]); | ||||
| if (!error) { | if (!error) { | ||||
| print_intinfo("pending", info[0]); | print_intinfo("pending", info[0]); | ||||
| print_intinfo("current", info[1]); | print_intinfo("current", info[1]); | ||||
| } | |||||
| } | |||||
| if (!error && (get_cpuid_cfg || get_all)) { | |||||
| struct vm_vcpu_cpuid_config vvcc = { | |||||
| .vvcc_vcpuid = 0, /* filled in by the ioctl code */ | |||||
markj: Where exactly does it get filled in? This looks like it always queries vcpu 0, ignoring the… | |||||
rosenfeld_grumpf.hope-2000.orgAuthorUnsubmitted Done Inline ActionsThis is done in vcpu_ioctl() in vmmapi.c, called by vm_get_cpuid() in vmmapi_machdep.c: int
vcpu_ioctl(struct vcpu *vcpu, u_long cmd, void *arg)
{
/*
* XXX: fragile, handle with care
* Assumes that the first field of the ioctl data
* is the vcpuid.
*/
*(int *)arg = vcpu->vcpuid;
return (ioctl(vcpu->ctx->fd, cmd, arg));
}rosenfeld_grumpf.hope-2000.org: This is done in vcpu_ioctl() in vmmapi.c, called by vm_get_cpuid() in vmmapi_machdep.c:
```… | |||||
markjUnsubmitted Not Done Inline ActionsRight, I forgot about that bit of magic. (I'd rather initialize vvcc_vcpuid = -1 in that case.) markj: Right, I forgot about that bit of magic. (I'd rather initialize vvcc_vcpuid = -1 in that case.) | |||||
| .vvcc_flags = 0, | |||||
| .vvcc_nent = 0, | |||||
| .vvcc_entries = NULL | |||||
| }; | |||||
| size_t entries_sz; | |||||
| /* | |||||
| * Get the flags and the number of configured CPUID entries, | |||||
| * and allocate a buffer for the entries if necessary. | |||||
| */ | |||||
| error = vm_get_cpuid(vcpu, &vvcc); | |||||
| if (error == 0 && vvcc.vvcc_nent != 0) { | |||||
| entries_sz = vvcc.vvcc_nent * | |||||
| sizeof (struct vcpu_cpuid_entry); | |||||
| vvcc.vvcc_entries = malloc(entries_sz); | |||||
| } | |||||
| /* | |||||
| * If there are CPUID entries, call vm_get_cpuid() again | |||||
| * to get them. | |||||
| */ | |||||
| if (error == 0 && vvcc.vvcc_entries != NULL) { | |||||
| bzero(vvcc.vvcc_entries, entries_sz); | |||||
| error = vm_get_cpuid(vcpu, &vvcc); | |||||
| } | |||||
| if (error == 0) { | |||||
| print_cpuid_cfg(&vvcc); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
Where exactly does it get filled in? This looks like it always queries vcpu 0, ignoring the --cpu parameter.