From: Gleb Natapov <gleb@redhat.com>
To: Yang Zhang <yang.z.zhang@intel.com>
Cc: kvm@vger.kernel.org, mtosatti@redhat.com,
xiantao.zhang@intel.com, jun.nakajima@intel.com
Subject: Re: [PATCH v7 3/7] KVM: VMX: Check the posted interrupt capability
Date: Sun, 7 Apr 2013 17:14:08 +0300 [thread overview]
Message-ID: <20130407141408.GY17919@redhat.com> (raw)
In-Reply-To: <1364787155-3208-4-git-send-email-yang.z.zhang@intel.com>
On Mon, Apr 01, 2013 at 11:32:31AM +0800, Yang Zhang wrote:
> From: Yang Zhang <yang.z.zhang@Intel.com>
>
> Detect the posted interrupt feature. If it exists, then set it in vmcs_config.
>
> Signed-off-by: Yang Zhang <yang.z.zhang@Intel.com>
> ---
> arch/x86/include/asm/vmx.h | 4 ++
> arch/x86/kvm/vmx.c | 87 ++++++++++++++++++++++++++++++++++----------
> 2 files changed, 71 insertions(+), 20 deletions(-)
>
> diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h
> index fc1c313..6f07f19 100644
> --- a/arch/x86/include/asm/vmx.h
> +++ b/arch/x86/include/asm/vmx.h
> @@ -71,6 +71,7 @@
> #define PIN_BASED_NMI_EXITING 0x00000008
> #define PIN_BASED_VIRTUAL_NMIS 0x00000020
> #define PIN_BASED_VMX_PREEMPTION_TIMER 0x00000040
> +#define PIN_BASED_POSTED_INTR 0x00000080
>
> #define PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR 0x00000016
>
> @@ -102,6 +103,7 @@
> /* VMCS Encodings */
> enum vmcs_field {
> VIRTUAL_PROCESSOR_ID = 0x00000000,
> + POSTED_INTR_NV = 0x00000002,
> GUEST_ES_SELECTOR = 0x00000800,
> GUEST_CS_SELECTOR = 0x00000802,
> GUEST_SS_SELECTOR = 0x00000804,
> @@ -136,6 +138,8 @@ enum vmcs_field {
> VIRTUAL_APIC_PAGE_ADDR_HIGH = 0x00002013,
> APIC_ACCESS_ADDR = 0x00002014,
> APIC_ACCESS_ADDR_HIGH = 0x00002015,
> + POSTED_INTR_DESC_ADDR = 0x00002016,
> + POSTED_INTR_DESC_ADDR_HIGH = 0x00002017,
> EPT_POINTER = 0x0000201a,
> EPT_POINTER_HIGH = 0x0000201b,
> EOI_EXIT_BITMAP0 = 0x0000201c,
> diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
> index 7408d93..b2e95bc 100644
> --- a/arch/x86/kvm/vmx.c
> +++ b/arch/x86/kvm/vmx.c
> @@ -84,7 +84,8 @@ module_param(vmm_exclusive, bool, S_IRUGO);
> static bool __read_mostly fasteoi = 1;
> module_param(fasteoi, bool, S_IRUGO);
>
> -static bool __read_mostly enable_apicv_reg_vid;
> +static bool __read_mostly enable_apicv;
> +module_param(enable_apicv, bool, S_IRUGO);
>
> /*
> * If nested=1, nested virtualization is supported, i.e., guests may use
> @@ -366,6 +367,19 @@ struct nested_vmx {
> struct page *apic_access_page;
> };
>
> +#define POSTED_INTR_ON 0
> +/* Posted-Interrupt Descriptor */
> +struct pi_desc {
> + u32 pir[8]; /* Posted interrupt requested */
> + union {
> + struct {
> + u8 on:1,
Do you actually use the 'on' member of the bit field? As far as I can
tell the paths always access control with (set|clear)_bit(). And C does not
guaranty layout of the bit field, so on may not point to what you think
it points to.
> + rsvd:7;
> + } control;
> + u32 rsvd[8];
> + } u;
> +} __aligned(64);
> +
> struct vcpu_vmx {
> struct kvm_vcpu vcpu;
> unsigned long host_rsp;
> @@ -430,6 +444,9 @@ struct vcpu_vmx {
>
> bool rdtscp_enabled;
>
> + /* Posted interrupt descriptor */
> + struct pi_desc pi_desc;
> +
> /* Support for a guest hypervisor (nested VMX) */
> struct nested_vmx nested;
> };
> @@ -785,6 +802,18 @@ static inline bool cpu_has_vmx_virtual_intr_delivery(void)
> SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY;
> }
>
> +static inline bool cpu_has_vmx_posted_intr(void)
> +{
> + return vmcs_config.pin_based_exec_ctrl & PIN_BASED_POSTED_INTR;
> +}
> +
> +static inline bool cpu_has_vmx_apicv(void)
> +{
> + return cpu_has_vmx_apic_register_virt() &&
> + cpu_has_vmx_virtual_intr_delivery() &&
> + cpu_has_vmx_posted_intr();
> +}
> +
> static inline bool cpu_has_vmx_flexpriority(void)
> {
> return cpu_has_vmx_tpr_shadow() &&
> @@ -2552,12 +2581,6 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
> u32 _vmexit_control = 0;
> u32 _vmentry_control = 0;
>
> - min = PIN_BASED_EXT_INTR_MASK | PIN_BASED_NMI_EXITING;
> - opt = PIN_BASED_VIRTUAL_NMIS;
> - if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PINBASED_CTLS,
> - &_pin_based_exec_control) < 0)
> - return -EIO;
> -
> min = CPU_BASED_HLT_EXITING |
> #ifdef CONFIG_X86_64
> CPU_BASED_CR8_LOAD_EXITING |
> @@ -2634,6 +2657,17 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
> &_vmexit_control) < 0)
> return -EIO;
>
> + min = PIN_BASED_EXT_INTR_MASK | PIN_BASED_NMI_EXITING;
> + opt = PIN_BASED_VIRTUAL_NMIS | PIN_BASED_POSTED_INTR;
> + if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PINBASED_CTLS,
> + &_pin_based_exec_control) < 0)
> + return -EIO;
> +
> + if (!(_cpu_based_2nd_exec_control &
> + SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY) ||
> + !(_vmexit_control & VM_EXIT_ACK_INTR_ON_EXIT))
> + _pin_based_exec_control &= ~PIN_BASED_POSTED_INTR;
> +
> min = 0;
> opt = VM_ENTRY_LOAD_IA32_PAT;
> if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_ENTRY_CTLS,
> @@ -2812,11 +2846,10 @@ static __init int hardware_setup(void)
> if (!cpu_has_vmx_ple())
> ple_gap = 0;
>
> - if (!cpu_has_vmx_apic_register_virt() ||
> - !cpu_has_vmx_virtual_intr_delivery())
> - enable_apicv_reg_vid = 0;
> + if (!cpu_has_vmx_apicv())
> + enable_apicv = 0;
>
> - if (enable_apicv_reg_vid)
> + if (enable_apicv)
> kvm_x86_ops->update_cr8_intercept = NULL;
> else
> kvm_x86_ops->hwapic_irr_update = NULL;
> @@ -3875,6 +3908,11 @@ static void vmx_disable_intercept_msr_write_x2apic(u32 msr)
> msr, MSR_TYPE_W);
> }
>
> +static int vmx_vm_has_apicv(struct kvm *kvm)
> +{
> + return enable_apicv && irqchip_in_kernel(kvm);
> +}
> +
> /*
> * Set up the vmcs's constant host-state fields, i.e., host-state fields that
> * will not change in the lifetime of the guest.
> @@ -3935,6 +3973,15 @@ static void set_cr4_guest_host_mask(struct vcpu_vmx *vmx)
> vmcs_writel(CR4_GUEST_HOST_MASK, ~vmx->vcpu.arch.cr4_guest_owned_bits);
> }
>
> +static u32 vmx_pin_based_exec_ctrl(struct vcpu_vmx *vmx)
> +{
> + u32 pin_based_exec_ctrl = vmcs_config.pin_based_exec_ctrl;
> +
> + if (!vmx_vm_has_apicv(vmx->vcpu.kvm))
> + pin_based_exec_ctrl &= ~PIN_BASED_POSTED_INTR;
> + return pin_based_exec_ctrl;
> +}
> +
> static u32 vmx_exec_control(struct vcpu_vmx *vmx)
> {
> u32 exec_control = vmcs_config.cpu_based_exec_ctrl;
> @@ -3952,11 +3999,6 @@ static u32 vmx_exec_control(struct vcpu_vmx *vmx)
> return exec_control;
> }
>
> -static int vmx_vm_has_apicv(struct kvm *kvm)
> -{
> - return enable_apicv_reg_vid && irqchip_in_kernel(kvm);
> -}
> -
> static u32 vmx_secondary_exec_control(struct vcpu_vmx *vmx)
> {
> u32 exec_control = vmcs_config.cpu_based_2nd_exec_ctrl;
> @@ -4012,8 +4054,7 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
> vmcs_write64(VMCS_LINK_POINTER, -1ull); /* 22.3.1.5 */
>
> /* Control */
> - vmcs_write32(PIN_BASED_VM_EXEC_CONTROL,
> - vmcs_config.pin_based_exec_ctrl);
> + vmcs_write32(PIN_BASED_VM_EXEC_CONTROL, vmx_pin_based_exec_ctrl(vmx));
>
> vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, vmx_exec_control(vmx));
>
> @@ -4022,13 +4063,16 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
> vmx_secondary_exec_control(vmx));
> }
>
> - if (enable_apicv_reg_vid) {
> + if (vmx_vm_has_apicv(vmx->vcpu.kvm)) {
> vmcs_write64(EOI_EXIT_BITMAP0, 0);
> vmcs_write64(EOI_EXIT_BITMAP1, 0);
> vmcs_write64(EOI_EXIT_BITMAP2, 0);
> vmcs_write64(EOI_EXIT_BITMAP3, 0);
>
> vmcs_write16(GUEST_INTR_STATUS, 0);
> +
> + vmcs_write64(POSTED_INTR_NV, POSTED_INTR_VECTOR);
> + vmcs_write64(POSTED_INTR_DESC_ADDR, __pa((&vmx->pi_desc)));
> }
>
> if (ple_gap) {
> @@ -4170,6 +4214,9 @@ static void vmx_vcpu_reset(struct kvm_vcpu *vcpu)
> vmcs_write64(APIC_ACCESS_ADDR,
> page_to_phys(vmx->vcpu.kvm->arch.apic_access_page));
>
> + if (vmx_vm_has_apicv(vcpu->kvm))
> + memset(&vmx->pi_desc, 0, sizeof(struct pi_desc));
> +
> if (vmx->vpid != 0)
> vmcs_write16(VIRTUAL_PROCESSOR_ID, vmx->vpid);
>
> @@ -7809,7 +7856,7 @@ static int __init vmx_init(void)
> memcpy(vmx_msr_bitmap_longmode_x2apic,
> vmx_msr_bitmap_longmode, PAGE_SIZE);
>
> - if (enable_apicv_reg_vid) {
> + if (enable_apicv) {
> for (msr = 0x800; msr <= 0x8ff; msr++)
> vmx_disable_intercept_msr_read_x2apic(msr);
>
> --
> 1.7.1
--
Gleb.
next prev parent reply other threads:[~2013-04-07 14:14 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-04-01 3:32 [PATCH v7 0/7] KVM: VMX: Add Posted Interrupt supporting Yang Zhang
2013-04-01 3:32 ` [PATCH v7 1/7] KVM: VMX: Enable acknowledge interupt on vmexit Yang Zhang
2013-04-01 3:32 ` [PATCH v7 2/7] KVM: VMX: Register a new IPI for posted interrupt Yang Zhang
2013-04-01 3:32 ` [PATCH v7 3/7] KVM: VMX: Check the posted interrupt capability Yang Zhang
2013-04-07 14:14 ` Gleb Natapov [this message]
2013-04-08 2:57 ` Zhang, Yang Z
2013-04-01 3:32 ` [PATCH v7 4/7] KVM: Call common update function when ioapic entry changed Yang Zhang
2013-04-07 13:33 ` Gleb Natapov
2013-04-07 14:00 ` Zhang, Yang Z
2013-04-07 14:05 ` Gleb Natapov
2013-04-08 4:10 ` Zhang, Yang Z
2013-04-01 3:32 ` [PATCH v7 5/7] KVM: Set TMR when programming ioapic entry Yang Zhang
2013-04-07 14:10 ` Gleb Natapov
2013-04-01 3:32 ` [PATCH v7 6/7] KVM: VMX: Add the algorithm of deliver posted interrupt Yang Zhang
2013-04-07 14:55 ` Gleb Natapov
2013-04-08 5:38 ` Zhang, Yang Z
2013-04-01 3:32 ` [PATCH v7 7/7] KVM: VMX: Use posted interrupt to deliver virtual interrupt Yang Zhang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20130407141408.GY17919@redhat.com \
--to=gleb@redhat.com \
--cc=jun.nakajima@intel.com \
--cc=kvm@vger.kernel.org \
--cc=mtosatti@redhat.com \
--cc=xiantao.zhang@intel.com \
--cc=yang.z.zhang@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.