Gleb Natapov wrote on 2013-01-17: > On Wed, Jan 16, 2013 at 06:21:11PM +0800, Yang Zhang wrote: >> From: Yang Zhang <yang.z.zhang@xxxxxxxxx> >> @@ -6103,6 +6206,53 @@ static void update_cr8_intercept(struct kvm_vcpu > *vcpu, int tpr, int irr) >> vmcs_write32(TPR_THRESHOLD, irr); >> } >> +static void vmx_set_virtual_x2apic_mode(struct kvm_vcpu *vcpu, bool >> set) +{ + u32 exec_control, sec_exec_control; + int msr; + struct >> vcpu_vmx *vmx = to_vmx(vcpu); + + /* There is not point to enable >> virtualize x2apic without enable + * apicv*/ + if >> (!cpu_has_vmx_virtualize_x2apic_mode() || !enable_apicv_reg) + return; >> + + if (set) { + exec_control = >> vmcs_read32(CPU_BASED_VM_EXEC_CONTROL); + /* virtualize x2apic mode >> relies on tpr shadow */ + if (!(exec_control & CPU_BASED_TPR_SHADOW)) >> + return; + } + + sec_exec_control = >> vmcs_read32(SECONDARY_VM_EXEC_CONTROL); + + if (set) { >> + sec_exec_control &= ~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES; >> + sec_exec_control |= SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE; + } else >> { + sec_exec_control &= ~SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE; + if >> (vm_need_virtualize_apic_accesses(vmx->vcpu.kvm)) + sec_exec_control >> |= + SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES; + } >> + vmcs_write32(SECONDARY_VM_EXEC_CONTROL, sec_exec_control); + + if >> (set) { + for (msr = 0x800; msr <= 0x8ff; msr++) >> + vmx_intercept_for_msr_read_x2apic(msr, false); + + /* According >> SDM, in x2apic mode, the whole id reg is used. + * But in KVM, it >> only use the highest eight bits. Need to + * intercept it */ >> + vmx_intercept_for_msr_read_x2apic(0x802, true); + /* TMCCT */ >> + vmx_intercept_for_msr_read_x2apic(0x839, true); + /* TPR */ >> + vmx_intercept_for_msr_write_x2apic(0x808, false); + } > Do it during vmx init, not here. Here you only need to call > vmx_set_msr_bitmap(). Sure. It is more reasonable. >> + vmx_set_msr_bitmap(vcpu); >> +} >> + >> static void vmx_complete_atomic_exit(struct vcpu_vmx *vmx) { u32 >> exit_intr_info; @@ -7366,6 +7516,7 @@ static struct kvm_x86_ops >> vmx_x86_ops = { .enable_nmi_window = enable_nmi_window, >> .enable_irq_window = enable_irq_window, .update_cr8_intercept = >> update_cr8_intercept, >> + .set_virtual_x2apic_mode = vmx_set_virtual_x2apic_mode, >> >> .set_tss_addr = vmx_set_tss_addr, .get_tdp_level = get_ept_level, @@ >> -7419,11 +7570,19 @@ static int __init vmx_init(void) if >> (!vmx_msr_bitmap_legacy) goto out1; >> + vmx_msr_bitmap_legacy_x2apic = >> + (unsigned long *)__get_free_page(GFP_KERNEL); >> + if (!vmx_msr_bitmap_legacy_x2apic) >> + goto out2; >> >> vmx_msr_bitmap_longmode = (unsigned long >> *)__get_free_page(GFP_KERNEL); if (!vmx_msr_bitmap_longmode) >> - goto out2; >> + goto out3; >> >> + vmx_msr_bitmap_longmode_x2apic = >> + (unsigned long *)__get_free_page(GFP_KERNEL); >> + if (!vmx_msr_bitmap_longmode_x2apic) >> + goto out4; >> >> /* * Allow direct access to the PC debug port (it is often used for >> I/O @@ -7456,6 +7615,11 @@ static int __init vmx_init(void) >> vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_ESP, false); >> vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_EIP, false); >> + memcpy(vmx_msr_bitmap_legacy_x2apic, >> + vmx_msr_bitmap_legacy, PAGE_SIZE); >> + memcpy(vmx_msr_bitmap_longmode_x2apic, >> + vmx_msr_bitmap_longmode, PAGE_SIZE); >> + >> if (enable_ept) { >> kvm_mmu_set_mask_ptes(0ull, >> (enable_ept_ad_bits) ? VMX_EPT_ACCESS_BIT : 0ull, >> @@ -7468,8 +7632,10 @@ static int __init vmx_init(void) >> >> return 0; >> -out3: >> +out4: >> free_page((unsigned long)vmx_msr_bitmap_longmode); >> +out3: >> + free_page((unsigned long)vmx_msr_bitmap_legacy_x2apic); >> out2: >> free_page((unsigned long)vmx_msr_bitmap_legacy); >> out1: >> @@ -7481,6 +7647,8 @@ out: >> >> static void __exit vmx_exit(void) >> { >> + free_page((unsigned long)vmx_msr_bitmap_legacy_x2apic); >> + free_page((unsigned long)vmx_msr_bitmap_longmode_x2apic); >> free_page((unsigned long)vmx_msr_bitmap_legacy); >> free_page((unsigned long)vmx_msr_bitmap_longmode); >> free_page((unsigned long)vmx_io_bitmap_b); >> -- >> 1.7.1 > > -- > Gleb. Best regards, Yang -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html