From: Paul Durrant <paul.durrant@citrix.com> To: xen-devel@lists.xenproject.org Cc: Wei Liu <wei.liu2@citrix.com>, Stefano Stabellini <stefano.stabellini@eu.citrix.com>, Andrew Cooper <andrew.cooper3@citrix.com>, Ian Jackson <ian.jackson@eu.citrix.com>, Paul Durrant <paul.durrant@citrix.com>, Jan Beulich <jbeulich@suse.com>, Keir Fraser <keir@xen.org> Subject: [PATCH v5 2/2] x86/hvm/viridian: Enable APIC assist enlightenment Date: Thu, 17 Mar 2016 12:13:52 +0000 [thread overview] Message-ID: <1458216832-18378-3-git-send-email-paul.durrant@citrix.com> (raw) In-Reply-To: <1458216832-18378-1-git-send-email-paul.durrant@citrix.com> This patch adds code to enable the APIC assist enlightenment which, under certain conditions, means that the guest can avoid an EOI of the local APIC and thereby avoid a VMEXIT. Use of the enlightenment by the hypervisor is under control of the toolstack, and is added to the default set. Signed-off-by: Paul Durrant <paul.durrant@citrix.com> Cc: Ian Jackson <ian.jackson@eu.citrix.com> Cc: Stefano Stabellini <stefano.stabellini@eu.citrix.com> Cc: Wei Liu <wei.liu2@citrix.com> Cc: Keir Fraser <keir@xen.org> Cc: Jan Beulich <jbeulich@suse.com> Cc: Andrew Cooper <andrew.cooper3@citrix.com> --- v4: - Re-worded xl.cfg text and added missing LIBXL_HAVE_ definition v3: - Re-instated read-modify-write for forwards compatibility - Fix a coding style issue v2: - Removed some code duplication and unnecessary read-modify-write operations on the APIC assist word. - Stated in the xl.cfg text that the enlightenment has no effect if posted interrupts are in use. - Added the enlightenment to the default set. --- docs/man/xl.cfg.pod.5 | 12 +++++++- tools/libxl/libxl.h | 6 ++++ tools/libxl/libxl_dom.c | 4 +++ tools/libxl/libxl_types.idl | 1 + xen/arch/x86/hvm/viridian.c | 59 ++++++++++++++++++++++++++++++++++---- xen/arch/x86/hvm/vlapic.c | 58 +++++++++++++++++++++++++++++++++---- xen/include/asm-x86/hvm/viridian.h | 5 ++++ xen/include/public/hvm/params.h | 7 ++++- 8 files changed, 139 insertions(+), 13 deletions(-) diff --git a/docs/man/xl.cfg.pod.5 b/docs/man/xl.cfg.pod.5 index 56b1117..abf638c 100644 --- a/docs/man/xl.cfg.pod.5 +++ b/docs/man/xl.cfg.pod.5 @@ -1484,10 +1484,20 @@ This set incorporates use of hypercalls for remote TLB flushing. This enlightenment may improve performance of Windows guests running on hosts with higher levels of (physical) CPU contention. +=item B<apic_assist> + +This set incorporates use of the APIC assist page to avoid EOI of +the local APIC. +This enlightenment may improve performance of guests that make use of +per-vcpu event channel upcall vectors. +Note that this enlightenment will have no effect if the guest is +using APICv posted interrupts. + =item B<defaults> This is a special value that enables the default set of groups, which -is currently the B<base>, B<freq> and B<time_ref_count> groups. +is currently the B<base>, B<freq>, B<time_ref_count> and B<apic_assist> +groups. =item B<all> diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h index f9e3ef5..055a7b4 100644 --- a/tools/libxl/libxl.h +++ b/tools/libxl/libxl.h @@ -218,6 +218,12 @@ #define LIBXL_HAVE_SOFT_RESET 1 /* + * LIBXL_HAVE_APIC_ASSIST indicates that the 'apic_assist' value + * is present in the viridian enlightenment enumeration. + */ +#define LIBXL_HAVE_APIC_ASSIST 1 + +/* * libxl ABI compatibility * * The only guarantee which libxl makes regarding ABI compatibility diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c index b825b98..09d3bca 100644 --- a/tools/libxl/libxl_dom.c +++ b/tools/libxl/libxl_dom.c @@ -211,6 +211,7 @@ static int hvm_set_viridian_features(libxl__gc *gc, uint32_t domid, libxl_bitmap_set(&enlightenments, LIBXL_VIRIDIAN_ENLIGHTENMENT_BASE); libxl_bitmap_set(&enlightenments, LIBXL_VIRIDIAN_ENLIGHTENMENT_FREQ); libxl_bitmap_set(&enlightenments, LIBXL_VIRIDIAN_ENLIGHTENMENT_TIME_REF_COUNT); + libxl_bitmap_set(&enlightenments, LIBXL_VIRIDIAN_ENLIGHTENMENT_APIC_ASSIST); } libxl_for_each_set_bit(v, info->u.hvm.viridian_enable) { @@ -253,6 +254,9 @@ static int hvm_set_viridian_features(libxl__gc *gc, uint32_t domid, if (libxl_bitmap_test(&enlightenments, LIBXL_VIRIDIAN_ENLIGHTENMENT_HCALL_REMOTE_TLB_FLUSH)) mask |= HVMPV_hcall_remote_tlb_flush; + if (libxl_bitmap_test(&enlightenments, LIBXL_VIRIDIAN_ENLIGHTENMENT_APIC_ASSIST)) + mask |= HVMPV_apic_assist; + if (mask != 0 && xc_hvm_param_set(CTX->xch, domid, diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl index 632c009..e3be957 100644 --- a/tools/libxl/libxl_types.idl +++ b/tools/libxl/libxl_types.idl @@ -221,6 +221,7 @@ libxl_viridian_enlightenment = Enumeration("viridian_enlightenment", [ (2, "time_ref_count"), (3, "reference_tsc"), (4, "hcall_remote_tlb_flush"), + (5, "apic_assist"), ]) libxl_hdtype = Enumeration("hdtype", [ diff --git a/xen/arch/x86/hvm/viridian.c b/xen/arch/x86/hvm/viridian.c index abbca3c..0f548ce 100644 --- a/xen/arch/x86/hvm/viridian.c +++ b/xen/arch/x86/hvm/viridian.c @@ -227,11 +227,6 @@ static void initialize_apic_assist(struct vcpu *v) void *va; /* - * We don't yet make use of the APIC assist page but by setting - * the CPUID3A_MSR_APIC_ACCESS bit in CPUID leaf 40000003 we are duty - * bound to support the MSR. We therefore do just enough to keep windows - * happy. - * * See section 13.3.4.1 of the specification for details of this * enlightenment. */ @@ -255,6 +250,7 @@ static void initialize_apic_assist(struct vcpu *v) *(uint32_t *)va = 0; v->arch.hvm_vcpu.viridian.apic_assist.va = va; + v->arch.hvm_vcpu.viridian.apic_assist.vector = -1; return; fail: @@ -262,6 +258,59 @@ static void initialize_apic_assist(struct vcpu *v) page ? page_to_mfn(page) : INVALID_MFN); } +static uint32_t *get_apic_assist_word(struct vcpu *v) +{ + if ( !(viridian_feature_mask(v->domain) & HVMPV_apic_assist) ) + return NULL; + + return v->arch.hvm_vcpu.viridian.apic_assist.va; +} + +void viridian_start_apic_assist(struct vcpu *v, int vector) +{ + uint32_t *va = get_apic_assist_word(v); + + if ( !va ) + return; + + /* + * If there is already an assist pending then something has gone + * wrong and the VM will most likely hang so force a crash now + * to make the problem clear. + */ + if ( v->arch.hvm_vcpu.viridian.apic_assist.vector >= 0 ) + domain_crash(v->domain); + + v->arch.hvm_vcpu.viridian.apic_assist.vector = vector; + *va |= 1u; +} + +bool_t viridian_complete_apic_assist(struct vcpu *v, int *vector) +{ + uint32_t *va = get_apic_assist_word(v); + + if ( !va ) + return 0; + + if ( *va & 1u ) + return 0; /* Interrupt not yet processed by the guest */ + + *vector = v->arch.hvm_vcpu.viridian.apic_assist.vector; + v->arch.hvm_vcpu.viridian.apic_assist.vector = -1; + return 1; +} + +void viridian_abort_apic_assist(struct vcpu *v) +{ + uint32_t *va = get_apic_assist_word(v); + + if ( !va ) + return; + + *va &= ~1u; + v->arch.hvm_vcpu.viridian.apic_assist.vector = -1; +} + static void teardown_apic_assist(struct vcpu *v) { void *va = v->arch.hvm_vcpu.viridian.apic_assist.va; diff --git a/xen/arch/x86/hvm/vlapic.c b/xen/arch/x86/hvm/vlapic.c index 01a8430..aac4263 100644 --- a/xen/arch/x86/hvm/vlapic.c +++ b/xen/arch/x86/hvm/vlapic.c @@ -38,6 +38,7 @@ #include <asm/hvm/support.h> #include <asm/hvm/vmx/vmx.h> #include <asm/hvm/nestedhvm.h> +#include <asm/hvm/viridian.h> #include <public/hvm/ioreq.h> #include <public/hvm/params.h> @@ -95,6 +96,18 @@ static int vlapic_find_highest_vector(const void *bitmap) return (fls(word[word_offset*4]) - 1) + (word_offset * 32); } +static int vlapic_find_lowest_vector(const void *bitmap) +{ + const uint32_t *word = bitmap; + unsigned int word_offset; + + /* Work forwards through the bitmap (first 32-bit word in every four). */ + for ( word_offset = 0; word_offset < NR_VECTORS / 32; word_offset++) + if ( word[word_offset * 4] ) + return (ffs(word[word_offset * 4]) - 1) + (word_offset * 32); + + return -1; +} /* * IRR-specific bitmap update & search routines. @@ -1157,7 +1170,7 @@ int vlapic_virtual_intr_delivery_enabled(void) int vlapic_has_pending_irq(struct vcpu *v) { struct vlapic *vlapic = vcpu_vlapic(v); - int irr, isr; + int irr, vector, isr; if ( !vlapic_enabled(vlapic) ) return -1; @@ -1170,10 +1183,27 @@ int vlapic_has_pending_irq(struct vcpu *v) !nestedhvm_vcpu_in_guestmode(v) ) return irr; + /* + * If APIC assist was used then there may have been no EOI so + * we need to clear the requisite bit from the ISR here, before + * comparing with the IRR. + */ + if ( viridian_complete_apic_assist(v, &vector) && + vector != -1 ) + vlapic_clear_vector(vector, &vlapic->regs->data[APIC_ISR]); + isr = vlapic_find_highest_isr(vlapic); isr = (isr != -1) ? isr : 0; if ( (isr & 0xf0) >= (irr & 0xf0) ) + { + /* + * There's already a higher priority vector pending so + * we need to abort any previous APIC assist to ensure there + * is an EOI. + */ + viridian_abort_apic_assist(v); return -1; + } return irr; } @@ -1181,13 +1211,29 @@ int vlapic_has_pending_irq(struct vcpu *v) int vlapic_ack_pending_irq(struct vcpu *v, int vector, bool_t force_ack) { struct vlapic *vlapic = vcpu_vlapic(v); + int isr; - if ( force_ack || !vlapic_virtual_intr_delivery_enabled() ) - { - vlapic_set_vector(vector, &vlapic->regs->data[APIC_ISR]); - vlapic_clear_irr(vector, vlapic); - } + if ( !force_ack && + vlapic_virtual_intr_delivery_enabled() ) + return 1; + + if ( vlapic_test_vector(vector, &vlapic->regs->data[APIC_TMR]) ) + goto done; + + isr = vlapic_find_lowest_vector(&vlapic->regs->data[APIC_ISR]); + if ( isr >= 0 && isr < vector ) + goto done; + + /* + * This vector is edge triggered and there are no lower priority + * vectors pending, so we can use APIC assist to avoid exiting + * for EOI. + */ + viridian_start_apic_assist(v, vector); +done: + vlapic_set_vector(vector, &vlapic->regs->data[APIC_ISR]); + vlapic_clear_irr(vector, vlapic); return 1; } diff --git a/xen/include/asm-x86/hvm/viridian.h b/xen/include/asm-x86/hvm/viridian.h index 19ecc06..336e547 100644 --- a/xen/include/asm-x86/hvm/viridian.h +++ b/xen/include/asm-x86/hvm/viridian.h @@ -24,6 +24,7 @@ struct viridian_vcpu struct { union viridian_apic_assist msr; void *va; + int vector; } apic_assist; }; @@ -122,6 +123,10 @@ void viridian_time_ref_count_thaw(struct domain *d); void viridian_vcpu_deinit(struct vcpu *v); +void viridian_start_apic_assist(struct vcpu *v, int vector); +bool_t viridian_complete_apic_assist(struct vcpu *v, int *vector); +void viridian_abort_apic_assist(struct vcpu *v); + #endif /* __ASM_X86_HVM_VIRIDIAN_H__ */ /* diff --git a/xen/include/public/hvm/params.h b/xen/include/public/hvm/params.h index 73d4718..e69c72c 100644 --- a/xen/include/public/hvm/params.h +++ b/xen/include/public/hvm/params.h @@ -115,12 +115,17 @@ #define _HVMPV_hcall_remote_tlb_flush 4 #define HVMPV_hcall_remote_tlb_flush (1 << _HVMPV_hcall_remote_tlb_flush) +/* Use APIC assist */ +#define _HVMPV_apic_assist 5 +#define HVMPV_apic_assist (1 << _HVMPV_apic_assist) + #define HVMPV_feature_mask \ (HVMPV_base_freq | \ HVMPV_no_freq | \ HVMPV_time_ref_count | \ HVMPV_reference_tsc | \ - HVMPV_hcall_remote_tlb_flush) + HVMPV_hcall_remote_tlb_flush | \ + HVMPV_apic_assist) #endif -- 2.1.4 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel
next prev parent reply other threads:[~2016-03-17 12:24 UTC|newest] Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top 2016-03-17 12:13 [PATCH v4 0/2] x86/hvm/viridian: APIC assist Paul Durrant 2016-03-17 12:13 ` [PATCH v5 1/2] x86/hvm/viridian: keep APIC assist page mapped Paul Durrant 2016-03-17 12:13 ` Paul Durrant [this message] 2016-03-17 16:43 ` [PATCH v5 2/2] x86/hvm/viridian: Enable APIC assist enlightenment Jan Beulich 2016-03-18 10:06 ` Paul Durrant 2016-03-18 10:24 ` Jan Beulich 2016-03-18 10:30 ` Paul Durrant 2016-03-18 10:58 ` Ian Jackson
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=1458216832-18378-3-git-send-email-paul.durrant@citrix.com \ --to=paul.durrant@citrix.com \ --cc=andrew.cooper3@citrix.com \ --cc=ian.jackson@eu.citrix.com \ --cc=jbeulich@suse.com \ --cc=keir@xen.org \ --cc=stefano.stabellini@eu.citrix.com \ --cc=wei.liu2@citrix.com \ --cc=xen-devel@lists.xenproject.org \ --subject='Re: [PATCH v5 2/2] x86/hvm/viridian: Enable APIC assist enlightenment' \ /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
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).