Issues implementing EPT

1

I'm having an issue implementing EPT in a hypervisor I'm developing. I'm receiving error no. 48 (EPT violation. An attempt to access memory with a guest-physical address was disallowed by the configuration of the EPT paging structures) with an EXIT_QUALIFICATION of 0x81 upon doing a VMLAUNCH. I've checked the page allocation logic and made sure GUEST_CR3 = HOST_CR3. I'm not sure why is this happening. I'm running on VMWare on a Linux host.

This is the allocation logic:

EPTP alloc_ept(int initial_pages_count){
    int i;
    EPTP eptp;
    EPT_PML4E *ept_pml4;
    EPT_PDPTE *ept_pdpt;
    EPT_PDE *ept_pd;
    EPT_PTE *ept_pt;
    eptp.value = 0;

    ept_pml4 = kzalloc(4096, GFP_KERNEL | GFP_NOWAIT);
    if(!ept_pml4)
        goto pml4err;
    ept_pdpt = kzalloc(4096, GFP_KERNEL | GFP_NOWAIT);
    if(!ept_pdpt)
        goto pdpterr;
    ept_pd = kzalloc(4096, GFP_KERNEL | GFP_NOWAIT);
    if(!ept_pd)
        goto pderr;
    ept_pt = kzalloc(4096, GFP_KERNEL | GFP_NOWAIT);
    if(!ept_pt)
        goto pterr;

    for(i = 0; i < initial_pages_count; i++){
        ept_pt[i].fields.phys_addr = virt_to_phys(kzalloc(4096, GFP_KERNEL | GFP_NOWAIT)) >> 12;
        ept_pt[i].fields.read_access = 1;
        ept_pt[i].fields.write_access = 1;
        ept_pt[i].fields.execute_access = 1;
        // Read CR0.bit30(CD) to determine cache disable and check if memtype=6 is supported:
        ept_pt[i].fields.ept_memtype = 0;
    }

    ept_pd[0].fields.phys_addr = virt_to_phys(ept_pt) >> 12;
    ept_pd[0].fields.read_access = 1;
    ept_pd[0].fields.write_access = 1;
    ept_pd[0].fields.execute_access = 1;

    ept_pdpt[0].fields.phys_addr = virt_to_phys(ept_pd) >> 12;
    ept_pdpt[0].fields.read_access = 1;
    ept_pdpt[0].fields.write_access = 1;
    ept_pdpt[0].fields.execute_access = 1;

    ept_pml4[0].fields.phys_addr = virt_to_phys(ept_pdpt) >> 12;
    ept_pml4[0].fields.read_access = 1;
    ept_pml4[0].fields.write_access = 1;
    ept_pml4[0].fields.execute_access = 1;

    eptp.fields.pml4_phys_addr = virt_to_phys(ept_pml4) >> 12;
    // Read CR0.bit30(CD) to determine cache disable and check if memtype=6 is supported:
    eptp.fields.memtype = 0;
    eptp.fields.page_walk = 3;
    // TODO: Read IA32_VMX_EPT_VPID_CAP - bit 21 if this is supported:
    eptp.fields.accessed_and_dirty_flags_enabled = 0;
    printk("EPTP PML4 PHYS ADDR: %08llx", eptp.fields.pml4_phys_addr);

    return eptp;

    pterr:
    kfree(ept_pd);
    pderr:
    kfree(ept_pdpt);
    pdpterr:
    kfree(ept_pml4);
    pml4err:
    panic("EPT ALLOC ERROR!");
}

static inline void VMLAUNCH(void){
    uint8_t err;
    __asm__ __volatile__(
        "vmlaunch; setna %[err]"
        : [err]"=rm"(err) 
        : : "cc", "memory"
    );
    dump_vmcs();
    printk(KERN_ERR "VMLAUNCH failure (err %lx)", vmcs_read(VM_INSTRUCTION_ERROR));
    BUG_ON(err);
}

static void setup_vm_code(vmstate *vms){
    int i;
        EPT_PML4E *pml = phys_to_virt(vms->eptp.fields.pml4_phys_addr << 12);
        EPT_PDPTE *pdpt = phys_to_virt(pml->fields.phys_addr << 12);
        EPT_PDE *pd = phys_to_virt(pdpt->fields.phys_addr << 12);
        EPT_PTE *pt = phys_to_virt(pd->fields.phys_addr << 12);

    vms->initial_rip = (unsigned long)phys_to_virt(pt[0].fields.phys_addr << 12);
    for(i = 0; i < 4096; i++){
        // hlt
        *(char*)(vms->initial_rip+i) = 0xf4;
    }
    printk(KERN_INFO "INITIAL_RIP: %016lx", vms->initial_rip);
    printk(KERN_INFO "INITIAL_RIP_PHYS: %016llx", virt_to_phys((unsigned long*)vms->initial_rip));
    // Stack grows down
    vms->initial_rsp = (unsigned long)phys_to_virt(pt[9].fields.phys_addr << 12) + 4095;
}

static void prepare_vmx_cpu(void){
    uint32_t vmcs_revid = 0;
    uint32_t hi = 0;
    vmstate *vms = per_cpu(cpu_vms, smp_processor_id());

    // Populate VMCS revision id in vmxon region
    rdmsr_safe(MSR_IA32_VMX_BASIC, &vmcs_revid, &hi);
    memcpy(vms->vmxon_region, &vmcs_revid, 4);
    memcpy(vms->vmcs_region, &vmcs_revid, 4);

    vms->eptp = alloc_ept(10);
    setup_vm_code(vms);

    vmx_enable();   
}

static void handle_vmexit(void){
    int exit_reason = vmcs_read32(VM_EXIT_REASON);
    int basic_exit_code = exit_reason & 0xffff;
    int exit_qualification = vmcs_read32(EXIT_QUALIFICATION);
    int vm_entry_failure = exit_reason & 0x80000000;
    dump_vmcs();
    panic("VMEXIT WITH CODE %d, VM ENTRY FAILURE: %s, QUAL: %d", basic_exit_code, vm_entry_failure ? "true" : "false", exit_qualification);
    VMRESUME();
    //TODO: switch error reasons
}

static void vmx_setup_vm_controls(void){
    // VM Execution Controls
    vmcs_write(PIN_BASED_VM_EXEC_CONTROL, adjust_msr_control(MSR_IA32_VMX_PINBASED_CTLS, 0));
    vmcs_write(CPU_BASED_VM_EXEC_CONTROL, adjust_msr_control(
        MSR_IA32_VMX_PROCBASED_CTLS, CPU_BASED_HLT_EXITING | CPU_BASED_ACTIVATE_SECONDARY_CONTROLS));
    vmcs_write(SECONDARY_VM_EXEC_CONTROL, adjust_msr_control(
        MSR_IA32_VMX_PROCBASED_CTLS2, CPU_BASED_CTL2_RDTSCP | CPU_BASED_CTL2_ENABLE_INVPCID | CPU_BASED_CTL2_ENABLE_VPID | CPU_BASED_CTL2_ENABLE_XSAVE_XRSTORS | CPU_BASED_CTL2_ENABLE_EPT
    ));

    //vmcs_write64(TSC_OFFSET, 0);  

    vmcs_write(CR0_READ_SHADOW, read_cr0());
    vmcs_write(CR4_READ_SHADOW, __read_cr4());
    vmcs_write(CR0_GUEST_HOST_MASK, ~0ul);
    vmcs_write(CR4_GUEST_HOST_MASK, ~0ul);

    // How many CR3_TARGET_VALUEs are considered without VM exit when MOV CR3, VAL
    vmcs_write(CR3_TARGET_COUNT, 0);

    // VM Entry & Exit Controls
    vmcs_write(VM_EXIT_CONTROLS, adjust_msr_control(MSR_IA32_VMX_EXIT_CTLS, VM_EXIT_IA32E_MODE | VM_EXIT_LOAD_IA32_EFER | VM_EXIT_HOST_ADDR_SPACE_SIZE));
    vmcs_write(VM_ENTRY_CONTROLS, adjust_msr_control(MSR_IA32_VMX_ENTRY_CTLS, VM_ENTRY_IA32E_MODE | VM_ENTRY_LOAD_IA32_EFER));
}

static void vmx_setup_initial_host_state(vmstate *vms){
    struct desc_ptr gdtptr, idt;

    vmcs_write(HOST_CR0, read_cr0());
    vmcs_write(HOST_CR3, __read_cr3());
    vmcs_write(HOST_CR4, __read_cr4());
    vmcs_write(HOST_RSP, (unsigned long)vms->vmm_handle_stack + vms->vmm_handle_stack_size - 1);
    vmcs_write(HOST_RIP, (unsigned long)handle_vmexit);

    /* An explanation of segment selectors: https://medium.com/hungys-blog/linux-kernel-memory-addressing-a0d304283af3 */
    // Segment Selectors
    vmcs_write(HOST_CS_SELECTOR, __KERNEL_CS);
    vmcs_write(HOST_DS_SELECTOR, __KERNEL_DS);
    vmcs_write(HOST_ES_SELECTOR, __KERNEL_DS);
    vmcs_write(HOST_SS_SELECTOR, __KERNEL_DS);
    vmcs_write(HOST_FS_SELECTOR, 0);
    vmcs_write(HOST_GS_SELECTOR, 0);
    vmcs_write(HOST_TR_SELECTOR, GDT_ENTRY_TSS*8);

    // Segment Base Adresses
    vmcs_write(HOST_FS_BASE, native_read_msr(MSR_FS_BASE));
    vmcs_write(HOST_GS_BASE, native_read_msr(MSR_GS_BASE));
    vmcs_write(HOST_TR_BASE, read_tr_base());
    native_store_gdt(&gdtptr);
    vmcs_write(HOST_GDTR_BASE, gdtptr.address);
    store_idt(&idt);
    vmcs_write(HOST_IDTR_BASE, idt.address);

    // MSRs
    vmcs_write(HOST_IA32_SYSENTER_CS, native_read_msr(MSR_IA32_SYSENTER_CS));
    vmcs_write(HOST_IA32_SYSENTER_ESP, native_read_msr(MSR_IA32_SYSENTER_ESP));
    vmcs_write(HOST_IA32_SYSENTER_EIP, native_read_msr(MSR_IA32_SYSENTER_EIP));
    vmcs_write64(HOST_IA32_EFER, native_read_msr(MSR_EFER));
}

static void RIPTEST(void) __attribute__((used));
static void RIPTEST(void){
    __asm__ __volatile__("hlt; hlt; hlt; hlt; hlt; hlt");
}

static void vmx_setup_initial_guest_state(vmstate *vms){
    vmcs_write(GUEST_CR0, read_cr0());
    vmcs_write(GUEST_CR3, __read_cr3());
    vmcs_write(GUEST_CR4, __read_cr4());
    vmcs_write(GUEST_DR7, 0);

    vmcs_write(GUEST_RIP, vms->initial_rip);
    //vmcs_write(GUEST_RIP, (unsigned long)RIPTEST);
    vmcs_write(GUEST_RSP, vms->initial_rsp);
    vmcs_write(GUEST_RFLAGS, 0x2); // Reserved flag

    // Setup selectors
    vmcs_write(GUEST_CS_SELECTOR, 0);
    vmcs_write(GUEST_SS_SELECTOR, 0);
    vmcs_write(GUEST_DS_SELECTOR, 0);
    vmcs_write(GUEST_ES_SELECTOR, 0);
    vmcs_write(GUEST_FS_SELECTOR, 0);
    vmcs_write(GUEST_GS_SELECTOR, 0);
    vmcs_write(GUEST_LDTR_SELECTOR, 0);
    vmcs_write(GUEST_TR_SELECTOR, 0);

    // Setup base addresses
    vmcs_write(GUEST_CS_BASE, 0);
    vmcs_write(GUEST_SS_BASE, 0);
    vmcs_write(GUEST_DS_BASE, 0);
    vmcs_write(GUEST_ES_BASE, 0);
    vmcs_write(GUEST_FS_BASE, native_read_msr(MSR_FS_BASE));
    vmcs_write(GUEST_GS_BASE, native_read_msr(MSR_GS_BASE));
    vmcs_write(GUEST_LDTR_BASE, 0);
    vmcs_write(GUEST_TR_BASE, 0);

    // Setup guest segment limits   
    vmcs_write(GUEST_CS_LIMIT, 0xFFFFFFFF);
    vmcs_write(GUEST_SS_LIMIT, 0xFFFFFFFF);
    vmcs_write(GUEST_DS_LIMIT, 0xFFFFFFFF);
    vmcs_write(GUEST_ES_LIMIT, 0xFFFFFFFF);
    vmcs_write(GUEST_FS_LIMIT, 0xFFFFFFFF);
    vmcs_write(GUEST_GS_LIMIT, 0xFFFFFFFF);
    vmcs_write(GUEST_LDTR_LIMIT, 0);
    vmcs_write(GUEST_TR_LIMIT, 0xFF);

    // Setup guest segment access rights
    // https://www.amd.com/system/files/TechDocs/24593.pdf#G10.910849
    vmcs_write(GUEST_CS_AR_BYTES, 0xA09B);
    vmcs_write(GUEST_SS_AR_BYTES, 0xA093);
    vmcs_write(GUEST_DS_AR_BYTES, 0xA093);
    vmcs_write(GUEST_ES_AR_BYTES, 0xA093);
    vmcs_write(GUEST_FS_AR_BYTES, 0xA093);
    vmcs_write(GUEST_GS_AR_BYTES, 0xA093);
    vmcs_write(GUEST_LDTR_AR_BYTES, 0x0082);
    vmcs_write(GUEST_TR_AR_BYTES, 0x008B);

    // Setup GDTR & IDTR
    vmcs_write(GUEST_GDTR_BASE, 0);
    vmcs_write(GUEST_IDTR_BASE, 0);
    vmcs_write(GUEST_GDTR_LIMIT, 0);
    vmcs_write(GUEST_IDTR_LIMIT, 0);

    vmcs_write(GUEST_IA32_EFER, native_read_msr(MSR_EFER));
    vmcs_write64(GUEST_IA32_DEBUGCTL, 0);

    // Setup sysenter primitives
    vmcs_write(GUEST_SYSENTER_CS, 0);
    vmcs_write(GUEST_SYSENTER_ESP, 0);
    vmcs_write(GUEST_SYSENTER_EIP, 0);
}

static void init_vmcs(vmstate *vms){
    VMPTRLD(vms->vmcs_physical);
    vmx_setup_vm_controls();
    vmx_setup_initial_guest_state(vms);
    vmx_setup_initial_host_state(vms);

    vmcs_write64(VMCS_LINK_POINTER, -1ull);

    //vmcs_write(EXCEPTION_BITMAP, 8192);

    vmcs_write64(EPT_POINTER, vms->eptp.value);
    //vmcs_write(VIRTUAL_PROCESSOR_ID, vms->vpid);
}

int vmx_launch(void){
    int cpu = smp_processor_id();
    vmstate *vms = per_cpu(cpu_vms, smp_processor_id());

    printk(KERN_INFO "Launching VM on CPU %d\n", cpu);
    init_vmcs(vms);
    VMLAUNCH();

    put_cpu();
    return 0;
}

int vmx_setup(void){
    int i = smp_processor_id();
    vmstate* vms;
    printk(KERN_INFO "NUM CPUS: %d\n", num_online_cpus());

    vms = create_vmstate();
    vms->vmxon_region = kmalloc(4096, GFP_KERNEL);
    vms->vmxon_physical = virt_to_phys(vms->vmxon_region);
    vms->vmcs_region = kzalloc(4096, GFP_KERNEL);
    vms->vmcs_physical = virt_to_phys(vms->vmcs_region);
    vms->vmm_handle_stack_size = 4096;
    vms->vmm_handle_stack = kmalloc(vms->vmm_handle_stack_size, GFP_KERNEL);
    vms->vpid = get_free_vpid();
    per_cpu(cpu_vms, i) = vms;


    prepare_vmx_cpu();
    printk(KERN_INFO "CPUS prepared!");

    vms = per_cpu(cpu_vms, i);
    if(vms->vmx_enabled == false) {
        printk(KERN_ALERT "Tearing down after VMXON failed!");
        vmx_teardown();
        return -1;
    }
    return 0;
}

static int __init hyper_init(void) {
    int err;

    get_cpu();
    printk(KERN_INFO "Hyper1 Init!\n");
    if(check_vmx_support()){
        device_cleanup();
        return -1;
    }
    if((err = setup_chrdev())){
        device_cleanup();
        return err;
    }
    if((err = vmx_setup())){
        device_cleanup();
        return err;
    }

    printk(KERN_INFO "Assigned major number %d\n", MAJOR(devt));
    vmx_launch();
    put_cpu();
    return 0;
}

VM log:

[  323.188232] Hyper1 Init!
[  323.189311] NUM CPUS: 2
[  323.192490] EPTP PML4 PHYS ADDR: 0007261e
[  323.192500] INITIAL_RIP: 18446615530478686208
[  323.194087] CPUS prepared!
[  323.195778] Assigned major number 240
[  323.198310] Launching VM on CPU 1
[  323.199330] vmwrite log: reg 4000 value 16
[  323.200639] vmwrite log: reg 4002 value ffffffff8401e1f2
[  323.202297] vmwrite log: reg 401e value a
[  323.203499] vmwrite log: reg 6004 value 80050033
[  323.204836] vmwrite log: reg 6006 value 626e0
[  323.206041] vmwrite log: reg 6000 value ffffffffffffffff
[  323.207529] vmwrite log: reg 6002 value ffffffffffffffff
[  323.209033] vmwrite log: reg 400a value 0
[  323.210121] vmwrite log: reg 400c value 236fff
[  323.211322] vmwrite log: reg 4012 value 93ff
[  323.212541] vmwrite log: reg 6800 value 80050033
[  323.213900] vmwrite log: reg 6802 value 7776e004
[  323.215150] vmwrite log: reg 6804 value 626e0
[  323.216457] vmwrite log: reg 681a value 0
[  323.217565] vmwrite log: reg 681e value ffff8b173262d000
[  323.219124] vmwrite log: reg 681c value ffff8b173260cfff
[  323.220656] vmwrite log: reg 6820 value 2
[  323.221746] vmwrite log: reg 802 value 0
[  323.222811] vmwrite log: reg 804 value 0
[  323.223938] vmwrite log: reg 806 value 0
[  323.225008] vmwrite log: reg 800 value 0
[  323.226082] vmwrite log: reg 808 value 0
[  323.227246] vmwrite log: reg 80a value 0
[  323.228437] vmwrite log: reg 80c value 0
[  323.229551] vmwrite log: reg 80e value 0
[  323.230626] vmwrite log: reg 6808 value 0
[  323.231753] vmwrite log: reg 680a value 0
[  323.232841] vmwrite log: reg 680c value 0
[  323.233925] vmwrite log: reg 6806 value 0
[  323.235037] vmwrite log: reg 680e value 7f624c519540
[  323.236473] vmwrite log: reg 6810 value ffff8b173bc40000
[  323.237903] vmwrite log: reg 6812 value 0
[  323.238988] vmwrite log: reg 6814 value 0
[  323.240129] vmwrite log: reg 4802 value ffffffff
[  323.241375] vmwrite log: reg 4804 value ffffffff
[  323.242619] vmwrite log: reg 4806 value ffffffff
[  323.243905] vmwrite log: reg 4800 value ffffffff
[  323.245150] vmwrite log: reg 4808 value ffffffff
[  323.246417] vmwrite log: reg 480a value ffffffff
[  323.247697] vmwrite log: reg 480c value 0
[  323.248784] vmwrite log: reg 480e value ff
[  323.249901] vmwrite log: reg 4816 value a09b
[  323.251053] vmwrite log: reg 4818 value a093
[  323.252243] vmwrite log: reg 481a value a093
[  323.253439] vmwrite log: reg 4814 value a093
[  323.254594] vmwrite log: reg 481c value a093
[  323.255822] vmwrite log: reg 481e value a093
[  323.256978] vmwrite log: reg 4820 value 82
[  323.258142] vmwrite log: reg 4822 value 8b
[  323.259238] vmwrite log: reg 6816 value 0
[  323.260350] vmwrite log: reg 6818 value 0
[  323.261421] vmwrite log: reg 4810 value 0
[  323.262489] vmwrite log: reg 4812 value 0
[  323.263762] vmwrite log: reg 2806 value d01
[  323.264960] vmwrite log: reg 2802 value 0
[  323.266068] vmwrite log: reg 482a value 0
[  323.267136] vmwrite log: reg 6824 value 0
[  323.268257] vmwrite log: reg 6826 value 0
[  323.269379] vmwrite log: reg 6c00 value 80050033
[  323.270601] vmwrite log: reg 6c02 value 7776e004
[  323.271879] vmwrite log: reg 6c04 value 626e0
[  323.273037] vmwrite log: reg 6c14 value ffff8b1732619fff
[  323.274435] vmwrite log: reg 6c16 value ffffffffc07154f0
[  323.275870] vmwrite log: reg c02 value 10
[  323.277134] vmwrite log: reg c06 value 18
[  323.278262] vmwrite log: reg c00 value 18
[  323.279443] vmwrite log: reg c04 value 18
[  323.280625] vmwrite log: reg c08 value 0
[  323.282006] vmwrite log: reg c0a value 0
[  323.283281] vmwrite log: reg c0c value 40
[  323.284409] vmwrite log: reg 6c06 value 7f624c519540
[  323.285794] vmwrite log: reg 6c08 value ffff8b173bc40000
[  323.287244] vmwrite log: reg 6c0a value 0
[  323.288367] vmwrite log: reg 6c0c value fffffe000002c000
[  323.289770] vmwrite log: reg 6c0e value fffffe0000000000
[  323.291169] vmwrite log: reg 4c00 value 10
[  323.292295] vmwrite log: reg 6c10 value fffffe000002d200
[  323.293696] vmwrite log: reg 6c12 value ffffffff860015f0
[  323.295124] vmwrite log: reg 2c02 value d01
[  323.296309] vmwrite log: reg 2800 value ffffffffffffffff
[  323.297711] vmwrite log: reg 201a value 7261e018
[  323.299105] *** Guest State ***
[  323.300022] CR0: actual=0x0000000080050033, shadow=0x0000000080050033, gh_mask=ffffffffffffffff
[  323.302373] CR4: actual=0x00000000000626e0, shadow=0x00000000000626e0, gh_mask=ffffffffffffffff
[  323.304697] CR3 = 0x000000007776e004
[  323.305687] PDPTR0 = 0x0000000000000000  PDPTR1 = 0x0000000000000000
[  323.307411] PDPTR2 = 0x0000000000000000  PDPTR3 = 0x0000000000000000
[  323.309117] RSP = 0xffff8b173260cfff  RIP = 0xffff8b173262d000
[  323.310683] RFLAGS=0x00010002         DR7 = 0x0000000000000400
[  323.312270] Sysenter RSP=0000000000000000 CS:RIP=0000:0000000000000000
[  323.314044] CS:   sel=0x0000, attr=0x0a09b, limit=0xffffffff, base=0x0000000000000000
[  323.316257] DS:   sel=0x0000, attr=0x0a093, limit=0xffffffff, base=0x0000000000000000
[  323.318371] SS:   sel=0x0000, attr=0x0a093, limit=0xffffffff, base=0x0000000000000000
[  323.320506] ES:   sel=0x0000, attr=0x0a093, limit=0xffffffff, base=0x0000000000000000
[  323.322580] FS:   sel=0x0000, attr=0x0a093, limit=0xffffffff, base=0x00007f624c519540
[  323.324678] GS:   sel=0x0000, attr=0x0a093, limit=0xffffffff, base=0xffff8b173bc40000
[  323.326774] GDTR:                           limit=0x00000000, base=0x0000000000000000
[  323.328880] LDTR: sel=0x0000, attr=0x00082, limit=0x00000000, base=0x0000000000000000
[  323.330982] IDTR:                           limit=0x00000000, base=0x0000000000000000
[  323.333073] TR:   sel=0x0000, attr=0x0008b, limit=0x000000ff, base=0x0000000000000000
[  323.335153] EFER =     0x0000000000000d01  PAT = 0x0000000000000000
[  323.337001] DebugCtl = 0x0000000000000000  DebugExceptions = 0x0000000000000000
[  323.338947] PerfGlobCtl = 0x0000000000000000
[  323.340114] vmread err: reg 2812 value 0
[  323.341171] BndCfgS = 0x0000000000000000
[  323.342235] Interruptibility = 00000000  ActivityState = 00000000
[  323.343874] vmread err: reg 810 value 0
[  323.344910] InterruptStatus = 0000
[  323.345840] *** Host State ***
[  323.346699] RIP = 0xffffffffc07154f0  RSP = 0xffff8b1732619fff
[  323.348287] CS=0010 SS=0018 DS=0018 ES=0018 FS=0000 GS=0000 TR=0040
[  323.349965] FSBase=00007f624c519540 GSBase=ffff8b173bc40000 TRBase=0000000000000000
[  323.352014] GDTBase=fffffe000002c000 IDTBase=fffffe0000000000
[  323.353586] CR0=0000000080050033 CR3=000000007776e004 CR4=00000000000626e0
[  323.355468] Sysenter RSP=fffffe000002d200 CS:RIP=0010:ffffffff860015f0
[  323.357231] EFER = 0x0000000000000d01  PAT = 0x0000000000000000
[  323.358815] PerfGlobCtl = 0x0000000000000000
[  323.359976] *** Control State ***
[  323.360877] PinBased=00000016 CPUBased=8401e1f2 SecondaryExec=0000000a
[  323.362632] EntryControls=000093ff ExitControls=00236fff
[  323.364073] ExceptionBitmap=00000000 PFECmask=00000000 PFECmatch=00000000
[  323.366003] VMEntry: intr_info=00000000 errcode=00000000 ilen=00000000
[  323.367768] VMExit: intr_info=00000000 errcode=00000000 ilen=00000003
[  323.369521]         reason=00000030 qualification=0000000000000081
[  323.371177] IDTVectoring: info=00000000 errcode=00000000
[  323.372614] TSC Offset = 0x0000000000000000
[  323.373742] vmread err: reg 810 value 810
[  323.374822] SVI|RVI = 08|10 TPR Threshold = 0x00
[  323.376079] vmread err: reg 2014 value 0
[  323.377276] APIC-access addr = 0x0000000000000000 virt-APIC addr = 0x0000000000000000
[  323.379498] vmread err: reg 2 value 0
[  323.380501] PostedIntrVec = 0x00
[  323.381383] EPT pointer = 0x000000007261e018
[  323.382534] Virtual processor ID = 0x0000
[  323.383629] Kernel panic - not syncing: VMEXIT WITH CODE 48, VM ENTRY FAILURE: false, QUAL: 129

Any help would be appreciated, thanks!

c
linux
linux-kernel
virtualization
hypervisor
asked on Stack Overflow Dec 25, 2019 by Paul • edited Dec 25, 2019 by Paul

1 Answer

1

It looks like it is only mapping 10 pages (40 KB) in the EPT, but GUEST CR3 is 7776e0000, which is not mapped.

If you want to only map a small amount of memory into the guest, then all the guest structures need to be located within that guest physical address range.

answered on Stack Overflow Dec 25, 2019 by prl • edited Dec 25, 2019 by prl

User contributions licensed under CC BY-SA 3.0