diff --git a/tools/xentrace/formats b/tools/xentrace/formats index 5d7b72a..d44f2fa 100644 --- a/tools/xentrace/formats +++ b/tools/xentrace/formats @@ -42,8 +42,8 @@ 0x00081401 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) nVMENTRY 0x00081402 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) nVMEXIT [ exitcode = 0x%(1)08x, rIP = 0x%(2)08x ] 0x00081502 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) nVMEXIT [ exitcode = 0x%(1)08x, rIP = 0x%(3)08x%(2)08x ] -0x00082001 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) PF_XEN [ errorcode = 0x%(2)02x, virt = 0x%(1)08x ] -0x00082101 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) PF_XEN [ errorcode = 0x%(3)02x, virt = 0x%(2)08x%(1)08x ] +0x00082401 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) nL1 [ errorcode = 0x%(2)02x, virt = 0x%(1)08x ] +0x00082501 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) nL1 [ errorcode = 0x%(3)02x, virt = 0x%(2)08x%(1)08x ] 0x00082002 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) PF_INJECT [ errorcode = 0x%(1)02x, virt = 0x%(2)08x ] 0x00082102 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) PF_INJECT [ errorcode = 0x%(1)02x, virt = 0x%(3)08x%(2)08x ] 0x00082003 CPU%(cpu)d %(tsc)d (+%(reltsc)8d) INJ_EXC [ vector = 0x%(1)02x, errorcode = 0x%(2)04x ] diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c index 5bc3c74..964ef01 100644 --- a/xen/arch/x86/hvm/vmx/vmcs.c +++ b/xen/arch/x86/hvm/vmx/vmcs.c @@ -1825,6 +1825,12 @@ void vmcs_dump_vcpu(struct vcpu *v) SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY ) printk("InterruptStatus = %04x\n", vmr16(GUEST_INTR_STATUS)); + if ( cpu_has_vmx_tpr_shadow ) + printk("VIRTUAL_APIC_PAGE_ADDR = 0x%016lx TPR threshold = 0x%016lx\n", + vmr(VIRTUAL_APIC_PAGE_ADDR), vmr(TPR_THRESHOLD)); + if ( cpu_has_vmx_virtualize_apic_accesses ) + printk("APIC_ACCESS_ADDR = 0x%016lx\n", + vmr(APIC_ACCESS_ADDR)); printk("*** Host State ***\n"); printk("RIP = 0x%016lx (%ps) RSP = 0x%016lx\n", vmr(HOST_RIP), (void *)vmr(HOST_RIP), vmr(HOST_RSP)); diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index 04dde83..565af29 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -2970,6 +2970,7 @@ void vmx_vmexit_handler(struct cpu_user_regs *regs) unsigned long exit_qualification, exit_reason, idtv_info, intr_info = 0; unsigned int vector = 0; struct vcpu *v = current; + bool_t vcpu_guestmode; __vmread(GUEST_RIP, ®s->rip); __vmread(GUEST_RSP, ®s->rsp); @@ -2986,12 +2987,17 @@ void vmx_vmexit_handler(struct cpu_user_regs *regs) __vmread(VM_EXIT_REASON, &exit_reason); + if ( nestedhvm_enabled(v->domain) && nestedhvm_vcpu_in_guestmode(v) ) + vcpu_guestmode = 1; + if ( hvm_long_mode_enabled(v) ) - HVMTRACE_ND(VMEXIT64, 0, 1/*cycles*/, 3, exit_reason, + HVMTRACE_ND(VMEXIT64, vcpu_guestmode ? TRC_HVM_NESTEDFLAG : 0, + 1/*cycles*/, 3, exit_reason, (uint32_t)regs->eip, (uint32_t)((uint64_t)regs->eip >> 32), 0, 0, 0); else - HVMTRACE_ND(VMEXIT, 0, 1/*cycles*/, 2, exit_reason, + HVMTRACE_ND(VMEXIT, vcpu_guestmode ? TRC_HVM_NESTEDFLAG : 0, + 1/*cycles*/, 2, exit_reason, (uint32_t)regs->eip, 0, 0, 0, 0); @@ -3069,7 +3075,19 @@ void vmx_vmexit_handler(struct cpu_user_regs *regs) { paging_update_nestedmode(v); if ( nvmx_n2_vmexit_handler(regs, exit_reason) ) + { + if ( hvm_long_mode_enabled(v) ) + HVMTRACE_ND(PF_XEN64, TRC_HVM_NESTEDFLAG , + 1/*cycles*/, 3, exit_reason, + (uint32_t)regs->eip, (uint32_t)((uint64_t)regs->eip >> 32), + 0, 0, 0); + else + HVMTRACE_ND(PF_XEN, TRC_HVM_NESTEDFLAG, + 1/*cycles*/, 2, exit_reason, + (uint32_t)regs->eip, + 0, 0, 0, 0); goto out; + } } if ( unlikely(exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY) ) diff --git a/xen/arch/x86/hvm/vmx/vvmx.c b/xen/arch/x86/hvm/vmx/vvmx.c index 271ec70..974e89f 100644 --- a/xen/arch/x86/hvm/vmx/vvmx.c +++ b/xen/arch/x86/hvm/vmx/vvmx.c @@ -101,7 +101,14 @@ int nvmx_vcpu_initialise(struct vcpu *v) set_bit(IO_BITMAP_B, vw); set_bit(VMCS_HIGH(IO_BITMAP_B), vw); + set_bit(VIRTUAL_APIC_PAGE_ADDR, vw); + + unmap_domain_page(vw); + + vw = __map_domain_page(vmread_bitmap); + set_bit(VIRTUAL_APIC_PAGE_ADDR, vw); unmap_domain_page(vw); + } nvmx->ept.enabled = 0; @@ -692,12 +699,40 @@ static void nvmx_update_virtual_apic_address(struct vcpu *v) p2m_type_t p2mt; unsigned long vapic_gpfn; struct page_info *vapic_pg; + u32 sec_ctrl = __n2_secondary_exec_control(v); + + vapic_gpfn = __get_vvmcs(nvcpu->nv_vvmcx, VIRTUAL_APIC_PAGE_ADDR); - vapic_gpfn = __get_vvmcs(nvcpu->nv_vvmcx, VIRTUAL_APIC_PAGE_ADDR) >> PAGE_SHIFT; - vapic_pg = get_page_from_gfn(v->domain, vapic_gpfn, &p2mt, P2M_ALLOC); - ASSERT(vapic_pg && !p2m_is_paging(p2mt)); - __vmwrite(VIRTUAL_APIC_PAGE_ADDR, page_to_maddr(vapic_pg)); - put_page(vapic_pg); + vapic_pg = get_page_from_gfn(v->domain, vapic_gpfn >> PAGE_SHIFT, &p2mt, P2M_ALLOC); + if ( !vapic_pg ) + { + unsigned int i; + printk("%s: vCPU%d 0x%lx(vAPIC) 0x%lx(APIC), 0x%lx(TPR) ctrl=%x sec=%x %s%s%s%s\n", + __func__,v->vcpu_id, + vapic_gpfn, + __get_vvmcs(nvcpu->nv_vvmcx, APIC_ACCESS_ADDR), + __get_vvmcs(nvcpu->nv_vvmcx, TPR_THRESHOLD), + ctrl, sec_ctrl, + sec_ctrl & SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES ? "APIC" : "", + sec_ctrl & SECONDARY_EXEC_APIC_REGISTER_VIRT ? "APIC virt" : "", + sec_ctrl & SECONDARY_EXEC_ENABLE_VMCS_SHADOWING ? "VMCS shadow" : "", + sec_ctrl & SECONDARY_EXEC_ENABLE_VIRT_EXCEPTIONS ? "v excpt" : ""); + for (i = 0; i < 3; i++) + printk("%s: %s = 0x%lx updated %ld.\n", __func__, + i == 0 ? "TPR threshold" : + (i == 1 ? "Virtual APIC" : + (i == 2 ? "APIC address" : "" )), + nvcpu->debug[i], nvcpu->debug_cnt[i]); + + printk("HOST_RIP=0x%lx HOST_RSP=0x%lx\n", __get_vvmcs(nvcpu->nv_vvmcx, HOST_RIP), + __get_vvmcs(nvcpu->nv_vvmcx, HOST_RSP)); + __vmwrite(VIRTUAL_APIC_PAGE_ADDR, vapic_gpfn); + } else { + ASSERT(vapic_pg); + ASSERT(vapic_pg && !p2m_is_paging(p2mt)); + __vmwrite(VIRTUAL_APIC_PAGE_ADDR, page_to_maddr(vapic_pg)); + put_page(vapic_pg); + } } else __vmwrite(VIRTUAL_APIC_PAGE_ADDR, 0); @@ -1729,12 +1764,17 @@ int nvmx_handle_vmread(struct cpu_user_regs *regs) struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v); u64 value = 0; int rc; + unsigned long operand; rc = decode_vmx_inst(regs, &decode, NULL, 0); if ( rc != X86EMUL_OKAY ) return rc; - value = __get_vvmcs(nvcpu->nv_vvmcx, reg_read(regs, decode.reg2)); + operand = reg_read(regs, decode.reg2); + value = __get_vvmcs(nvcpu->nv_vvmcx, operand); + + if ( operand == VIRTUAL_APIC_PAGE_ADDR ) + printk("%s: val=%lx\n", __func__, value); switch ( decode.type ) { case VMX_INST_MEMREG_TYPE_MEMORY: @@ -1756,29 +1796,62 @@ int nvmx_handle_vmwrite(struct cpu_user_regs *regs) struct vcpu *v = current; struct vmx_inst_decoded decode; struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v); - unsigned long operand; + unsigned long operand, val; u64 vmcs_encoding; bool_t okay = 1; + char *msg = NULL; if ( decode_vmx_inst(regs, &decode, &operand, 0) != X86EMUL_OKAY ) return X86EMUL_EXCEPTION; vmcs_encoding = reg_read(regs, decode.reg2); + val = __get_vvmcs(nvcpu->nv_vvmcx, vmcs_encoding); __set_vvmcs(nvcpu->nv_vvmcx, vmcs_encoding, operand); switch ( vmcs_encoding & ~VMCS_HIGH(0) ) { case IO_BITMAP_A: okay = _map_io_bitmap(v, IO_BITMAP_A); + msg="IO_BITMAP_A"; break; case IO_BITMAP_B: okay = _map_io_bitmap(v, IO_BITMAP_B); + msg="IO_BITMAP_B"; break; case MSR_BITMAP: + msg="MSR_BITMAP"; okay = _map_msr_bitmap(v); break; + case TPR_THRESHOLD: + msg="TPR_THRESHOLD"; + nvcpu->debug[0] = operand; + nvcpu->debug_cnt[0] ++; + okay = 1; + break; + case VIRTUAL_APIC_PAGE_ADDR: + msg="VIRTUAL_APIC_PAGE_ADDR"; + nvcpu->debug[1] = operand; + nvcpu->debug_cnt[1] ++; + okay = 1; + break; + case APIC_ACCESS_ADDR: + msg="APIC_ACCESS_ADDR"; + nvcpu->debug[2] = operand; + nvcpu->debug_cnt[1] ++; + okay = 1; + break; + case VM_EXIT_MSR_LOAD_ADDR: + msg="VM_EXIT_MSR_LOAD_ADDR"; + break; + case VIRTUAL_PROCESSOR_ID: + msg="VIRTUAL_PROCESSOR_ID"; + default: + okay = 1; + break; } + printk("%s %d: %s(%lx)[%lx=%lx]\n", __func__, v->vcpu_id, + msg ? msg : "",vmcs_encoding, val, operand); vmreturn(regs, okay ? VMSUCCEED : VMFAIL_VALID); diff --git a/xen/include/asm-x86/hvm/vcpu.h b/xen/include/asm-x86/hvm/vcpu.h index 152d9f3..b69a584 100644 --- a/xen/include/asm-x86/hvm/vcpu.h +++ b/xen/include/asm-x86/hvm/vcpu.h @@ -130,6 +130,9 @@ struct nestedvcpu { /* L2's control-resgister, just as the L2 sees them. */ unsigned long guest_cr[5]; + + unsigned long debug[3]; /* 0 - TPR, 1 - VIRTUAL APIC, 2 - APIC_ADDR */ + unsigned long debug_cnt[3]; /* 0 - TPR, 1 - VIRTUAL APIC, 2 - APIC_ADDR */ }; #define vcpu_nestedhvm(v) ((v)->arch.hvm_vcpu.nvcpu)