Index: bhyvectl.c =================================================================== --- bhyvectl.c (revision 268701) +++ bhyvectl.c (working copy) @@ -34,7 +34,10 @@ #include #include #include +#include +#include + #include #include #include @@ -195,12 +198,17 @@ " [--force-reset]\n" " [--force-poweroff]\n" " [--get-active-cpus]\n" + " [--read-gla1=]\n" + " [--read-gla2=]\n" + " [--read-gla4=]\n" + " [--read-gla8=]\n" " [--get-suspended-cpus]\n", progname); exit(1); } static int get_stats, getcap, setcap, capval, get_gpa_pmap; +static int read_gla1, read_gla2, read_gla4, read_gla8; static int inject_nmi, assert_lapic_lvt; static int force_reset, force_poweroff; static const char *capname; @@ -391,6 +399,10 @@ UNASSIGN_PPTDEV, GET_GPA_PMAP, ASSERT_LAPIC_LVT, + READ_GLA1, + READ_GLA2, + READ_GLA4, + READ_GLA8, }; static void @@ -412,12 +424,115 @@ printf("\n"); } +static int +cpu_mode(struct vmctx *ctx, int vcpu, enum vm_cpu_mode *mode) +{ + uint64_t base, efer, cr0; + uint32_t limit, access; + int error; + + error = vm_get_register(ctx, vcpu, VM_REG_GUEST_EFER, &efer); + if (error) + return (error); + + error = vm_get_register(ctx, vcpu, VM_REG_GUEST_CR0, &cr0); + if (error) + return (error); + + error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_CS, &base, &limit, &access); + if (error) + return (error); + + if (efer & EFER_LMA) { + if (access & 0x2000) + *mode = CPU_MODE_64BIT; + else + *mode = CPU_MODE_COMPATIBILITY; + } else if (cr0 & CR0_PE) { + *mode = CPU_MODE_PROTECTED; + } else { + *mode = CPU_MODE_REAL; + } + return (0); +} + +static int +paging_mode(struct vmctx *ctx, int vcpu, enum vm_paging_mode *mode) +{ + uint64_t cr0, cr4, efer; + int error; + + error = vm_get_register(ctx, vcpu, VM_REG_GUEST_EFER, &efer); + if (error) + return (error); + + error = vm_get_register(ctx, vcpu, VM_REG_GUEST_CR0, &cr0); + if (error) + return (error); + + error = vm_get_register(ctx, vcpu, VM_REG_GUEST_CR4, &cr4); + if (error) + return (error); + + if (!(cr0 & CR0_PG)) + *mode = PAGING_MODE_FLAT; + if (!(cr4 & CR4_PAE)) + *mode = PAGING_MODE_32; + if (efer & EFER_LME) + *mode = PAGING_MODE_64; + else + *mode = PAGING_MODE_PAE; + + return (0); +} + +static int +read_gla(struct vmctx *ctx, int vcpu, uint64_t gla, int bytes, void *vp) +{ + struct vm_guest_paging paging; + struct iovec iov[1]; + int error; + + assert(bytes == 1 || bytes == 2 || bytes == 4 || bytes == 8); + + bzero(&paging, sizeof(struct vm_guest_paging)); + error = vm_get_register(ctx, vcpu, VM_REG_GUEST_CR3, &paging.cr3); + if (error) + return (error); + + error = cpu_mode(ctx, vcpu, &paging.cpu_mode); + if (error) + return (error); + + error = paging_mode(ctx, vcpu, &paging.paging_mode); + if (error) + return (error); + + paging.cpl = 0; /* Ignore U/S bit in paging entries */ + + error = vm_gla2gpa(ctx, vcpu, &paging, gla, bytes, PROT_READ, + iov, nitems(iov)); + if (error) + return (error); + + vm_copyin(ctx, vcpu, iov, vp, bytes); + return (0); +} + +static union { + uint8_t byte; + uint16_t word; + uint32_t dword; + uint64_t qword; +} glabytes; + int main(int argc, char *argv[]) { char *vmname; int error, ch, vcpu, ptenum; vm_paddr_t gpa, gpa_pmap; + uint64_t gla1_addr, gla2_addr, gla4_addr, gla8_addr; size_t len; struct vm_exit vmexit; uint64_t ctl, eptp, bm, addr, u64, pteval[4], *pte; @@ -463,6 +578,10 @@ { "unassign-pptdev", REQ_ARG, 0, UNASSIGN_PPTDEV }, { "setcap", REQ_ARG, 0, SET_CAP }, { "get-gpa-pmap", REQ_ARG, 0, GET_GPA_PMAP }, + { "read-gla1", REQ_ARG, 0, READ_GLA1 }, + { "read-gla2", REQ_ARG, 0, READ_GLA2 }, + { "read-gla4", REQ_ARG, 0, READ_GLA4 }, + { "read-gla8", REQ_ARG, 0, READ_GLA8 }, { "assert-lapic-lvt", REQ_ARG, 0, ASSERT_LAPIC_LVT }, { "getcap", NO_ARG, &getcap, 1 }, { "get-stats", NO_ARG, &get_stats, 1 }, @@ -714,6 +833,22 @@ gpa_pmap = strtoul(optarg, NULL, 0); get_gpa_pmap = 1; break; + case READ_GLA1: + gla1_addr = strtoul(optarg, NULL, 0); + read_gla1 = 1; + break; + case READ_GLA2: + gla2_addr = strtoul(optarg, NULL, 0); + read_gla2 = 1; + break; + case READ_GLA4: + gla4_addr = strtoul(optarg, NULL, 0); + read_gla4 = 1; + break; + case READ_GLA8: + gla8_addr = strtoul(optarg, NULL, 0); + read_gla8 = 1; + break; case CAPNAME: capname = optarg; break; @@ -747,7 +882,7 @@ } if (!error && memsize) - error = vm_setup_memory(ctx, memsize, VM_MMAP_NONE); + error = vm_setup_memory(ctx, memsize, VM_MMAP_ALL); if (!error && set_efer) error = vm_set_register(ctx, vcpu, VM_REG_GUEST_EFER, efer); @@ -1528,6 +1663,32 @@ } } + if (!error && read_gla1) { + error = read_gla(ctx, vcpu, gla1_addr, 1, &glabytes); + if (!error) + printf("0x%016lx: 0x%02x\n", gla1_addr, glabytes.byte); + } + + if (!error && read_gla2) { + error = read_gla(ctx, vcpu, gla2_addr, 2, &glabytes); + if (!error) + printf("0x%016lx: 0x%04x\n", gla2_addr, glabytes.word); + } + + if (!error && read_gla4) { + error = read_gla(ctx, vcpu, gla4_addr, 4, &glabytes); + if (!error) + printf("0x%016lx: 0x%08x\n", gla4_addr, glabytes.dword); + } + + if (!error && read_gla8) { + error = read_gla(ctx, vcpu, gla8_addr, 8, &glabytes); + if (!error) { + printf("0x%016lx: 0x%016lx\n", gla8_addr, + glabytes.qword); + } + } + if (!error && (getcap || get_all)) { int captype, val, getcaptype;