[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] x86: highmem handling assistance hypercalls
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1225114175 0 # Node ID 4413d53a8320809e93142ed599a81e1bfe5ae900 # Parent 9bbb54fd9181644d2bdd3c7f93c2cba1dac1b719 x86: highmem handling assistance hypercalls While looking at the origin of very frequently executed hypercalls I realized that the high page accessor functions in Linux would be good candidates to handle in the hypervisor - clearing or copying to/from a high page is a pretty frequent operation (provided there's enough memory in the domain). While prior to the first submission I only measured kernel builds (where the results are not hinting at a meaningful improvement), I now found time to do a more specific analysis: page clearing is being improved by about 20%, page copying doesn't seem to significantly benefit (though that may be an effect of the simplistic copy_page() implementation Xen currently uses) - nevertheless I would think that if one function is supported by the hypervisor, then the other should also be. Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx> --- xen/arch/x86/mm.c | 83 ++++++++++++++++++++++++++++++++++++++++ xen/arch/x86/x86_64/compat/mm.c | 5 ++ xen/common/kernel.c | 3 - xen/include/public/features.h | 3 + xen/include/public/xen.h | 14 ++++++ 5 files changed, 106 insertions(+), 2 deletions(-) diff -r 9bbb54fd9181 -r 4413d53a8320 xen/arch/x86/mm.c --- a/xen/arch/x86/mm.c Mon Oct 27 13:27:33 2008 +0000 +++ b/xen/arch/x86/mm.c Mon Oct 27 13:29:35 2008 +0000 @@ -2431,6 +2431,29 @@ static inline cpumask_t vcpumask_to_pcpu return pmask; } +#ifdef __i386__ +static inline void *fixmap_domain_page(unsigned long mfn) +{ + unsigned int cpu = smp_processor_id(); + void *ptr = (void *)fix_to_virt(FIX_PAE_HIGHMEM_0 + cpu); + + l1e_write(fix_pae_highmem_pl1e - cpu, + l1e_from_pfn(mfn, __PAGE_HYPERVISOR)); + flush_tlb_one_local(ptr); + return ptr; +} +static inline void fixunmap_domain_page(const void *ptr) +{ + unsigned int cpu = virt_to_fix((unsigned long)ptr) - FIX_PAE_HIGHMEM_0; + + l1e_write(fix_pae_highmem_pl1e - cpu, l1e_empty()); + this_cpu(make_cr3_timestamp) = this_cpu(tlbflush_time); +} +#else +#define fixmap_domain_page(mfn) mfn_to_virt(mfn) +#define fixunmap_domain_page(ptr) ((void)(ptr)) +#endif + int do_mmuext_op( XEN_GUEST_HANDLE(mmuext_op_t) uops, unsigned int count, @@ -2697,6 +2720,66 @@ int do_mmuext_op( if ( ents != 0 ) this_cpu(percpu_mm_info).deferred_ops |= DOP_RELOAD_LDT; } + break; + } + + case MMUEXT_CLEAR_PAGE: + { + unsigned char *ptr; + + okay = !get_page_and_type_from_pagenr(mfn, PGT_writable_page, + FOREIGNDOM, 0); + if ( unlikely(!okay) ) + { + MEM_LOG("Error while clearing mfn %lx", mfn); + break; + } + + /* A page is dirtied when it's being cleared. */ + paging_mark_dirty(d, mfn); + + ptr = fixmap_domain_page(mfn); + clear_page(ptr); + fixunmap_domain_page(ptr); + + put_page_and_type(page); + break; + } + + case MMUEXT_COPY_PAGE: + { + const unsigned char *src; + unsigned char *dst; + unsigned long src_mfn; + + src_mfn = gmfn_to_mfn(FOREIGNDOM, op.arg2.src_mfn); + okay = get_page_from_pagenr(src_mfn, FOREIGNDOM); + if ( unlikely(!okay) ) + { + MEM_LOG("Error while copying from mfn %lx", src_mfn); + break; + } + + okay = !get_page_and_type_from_pagenr(mfn, PGT_writable_page, + FOREIGNDOM, 0); + if ( unlikely(!okay) ) + { + put_page(mfn_to_page(src_mfn)); + MEM_LOG("Error while copying to mfn %lx", mfn); + break; + } + + /* A page is dirtied when it's being copied to. */ + paging_mark_dirty(d, mfn); + + src = map_domain_page(src_mfn); + dst = fixmap_domain_page(mfn); + copy_page(dst, src); + fixunmap_domain_page(dst); + unmap_domain_page(src); + + put_page_and_type(page); + put_page(mfn_to_page(src_mfn)); break; } diff -r 9bbb54fd9181 -r 4413d53a8320 xen/arch/x86/x86_64/compat/mm.c --- a/xen/arch/x86/x86_64/compat/mm.c Mon Oct 27 13:27:33 2008 +0000 +++ b/xen/arch/x86/x86_64/compat/mm.c Mon Oct 27 13:29:35 2008 +0000 @@ -231,6 +231,8 @@ int compat_mmuext_op(XEN_GUEST_HANDLE(mm case MMUEXT_PIN_L4_TABLE: case MMUEXT_UNPIN_TABLE: case MMUEXT_NEW_BASEPTR: + case MMUEXT_CLEAR_PAGE: + case MMUEXT_COPY_PAGE: arg1 = XLAT_mmuext_op_arg1_mfn; break; default: @@ -257,6 +259,9 @@ int compat_mmuext_op(XEN_GUEST_HANDLE(mm case MMUEXT_TLB_FLUSH_MULTI: case MMUEXT_INVLPG_MULTI: arg2 = XLAT_mmuext_op_arg2_vcpumask; + break; + case MMUEXT_COPY_PAGE: + arg2 = XLAT_mmuext_op_arg2_src_mfn; break; default: arg2 = -1; diff -r 9bbb54fd9181 -r 4413d53a8320 xen/common/kernel.c --- a/xen/common/kernel.c Mon Oct 27 13:27:33 2008 +0000 +++ b/xen/common/kernel.c Mon Oct 27 13:29:35 2008 +0000 @@ -221,7 +221,8 @@ DO(xen_version)(int cmd, XEN_GUEST_HANDL fi.submap |= 1U << XENFEAT_supervisor_mode_kernel; #ifdef CONFIG_X86 if ( !is_hvm_vcpu(current) ) - fi.submap |= 1U << XENFEAT_mmu_pt_update_preserve_ad; + fi.submap |= (1U << XENFEAT_mmu_pt_update_preserve_ad) | + (1U << XENFEAT_highmem_assist); #endif break; default: diff -r 9bbb54fd9181 -r 4413d53a8320 xen/include/public/features.h --- a/xen/include/public/features.h Mon Oct 27 13:27:33 2008 +0000 +++ b/xen/include/public/features.h Mon Oct 27 13:29:35 2008 +0000 @@ -59,6 +59,9 @@ /* x86: Does this Xen host support the MMU_PT_UPDATE_PRESERVE_AD hypercall? */ #define XENFEAT_mmu_pt_update_preserve_ad 5 +/* x86: Does this Xen host support the MMU_{CLEAR,COPY}_PAGE hypercall? */ +#define XENFEAT_highmem_assist 6 + #define XENFEAT_NR_SUBMAPS 1 #endif /* __XEN_PUBLIC_FEATURES_H__ */ diff -r 9bbb54fd9181 -r 4413d53a8320 xen/include/public/xen.h --- a/xen/include/public/xen.h Mon Oct 27 13:27:33 2008 +0000 +++ b/xen/include/public/xen.h Mon Oct 27 13:29:35 2008 +0000 @@ -231,6 +231,13 @@ DEFINE_XEN_GUEST_HANDLE(xen_pfn_t); * cmd: MMUEXT_SET_LDT * linear_addr: Linear address of LDT base (NB. must be page-aligned). * nr_ents: Number of entries in LDT. + * + * cmd: MMUEXT_CLEAR_PAGE + * mfn: Machine frame number to be cleared. + * + * cmd: MMUEXT_COPY_PAGE + * mfn: Machine frame number of the destination page. + * src_mfn: Machine frame number of the source page. */ #define MMUEXT_PIN_L1_TABLE 0 #define MMUEXT_PIN_L2_TABLE 1 @@ -247,12 +254,15 @@ DEFINE_XEN_GUEST_HANDLE(xen_pfn_t); #define MMUEXT_FLUSH_CACHE 12 #define MMUEXT_SET_LDT 13 #define MMUEXT_NEW_USER_BASEPTR 15 +#define MMUEXT_CLEAR_PAGE 16 +#define MMUEXT_COPY_PAGE 17 #ifndef __ASSEMBLY__ struct mmuext_op { unsigned int cmd; union { - /* [UN]PIN_TABLE, NEW_BASEPTR, NEW_USER_BASEPTR */ + /* [UN]PIN_TABLE, NEW_BASEPTR, NEW_USER_BASEPTR + * CLEAR_PAGE, COPY_PAGE */ xen_pfn_t mfn; /* INVLPG_LOCAL, INVLPG_ALL, SET_LDT */ unsigned long linear_addr; @@ -266,6 +276,8 @@ struct mmuext_op { #else void *vcpumask; #endif + /* COPY_PAGE */ + xen_pfn_t src_mfn; } arg2; }; typedef struct mmuext_op mmuext_op_t; _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |