# HG changeset patch # User yamahata@xxxxxxxxxxxxx # Date 1155119075 -32400 # Node ID dc37e8c2b96afe282d95a7263fb64ede040b28df # Parent 5e2fec53ecc5c62acb0e2b083464b527d77b9bcf p2m exposure. linux side part. This patch introduce compile time option XEN_IA64_EXPOSE_P2M to enable this feature and boot option xen_ia64_p2m_expose to disable the functionality. PATCHNAME: fix_p2m_exposure_linux_side Signed-off-by: Isaku Yamahata diff -r 5e2fec53ecc5 -r dc37e8c2b96a linux-2.6-xen-sparse/arch/ia64/Kconfig --- a/linux-2.6-xen-sparse/arch/ia64/Kconfig Wed Aug 09 19:23:11 2006 +0900 +++ b/linux-2.6-xen-sparse/arch/ia64/Kconfig Wed Aug 09 19:24:35 2006 +0900 @@ -63,6 +63,13 @@ config XEN_IA64_VDSO_PARAVIRT default y help vDSO paravirtualization + +config XEN_IA64_EXPOSE_P2M + bool + depends on XEN + default y + help + expose p2m from xen config SCHED_NO_NO_OMIT_FRAME_POINTER bool diff -r 5e2fec53ecc5 -r dc37e8c2b96a linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c --- a/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c Wed Aug 09 19:23:11 2006 +0900 +++ b/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c Wed Aug 09 19:24:35 2006 +0900 @@ -503,6 +503,12 @@ out: privcmd_resource_min, privcmd_resource_max, (privcmd_resource_max - privcmd_resource_min) >> 20); BUG_ON(privcmd_resource_min >= privcmd_resource_max); + + // XXX this should be somewhere appropriate +#ifdef CONFIG_XEN_IA64_EXPOSE_P2M + (void)p2m_expose_init(); +#endif + return 0; } late_initcall(xen_ia64_privcmd_init); @@ -808,3 +814,141 @@ time_resume(void) /* Just trigger a tick. */ ia64_cpu_local_tick(); } + +/////////////////////////////////////////////////////////////////////////// +// expose p2m table +#ifdef CONFIG_XEN_IA64_EXPOSE_P2M +#include + +int p2m_initialized __read_mostly = 0; + +unsigned long p2m_min_low_pfn __read_mostly; +unsigned long p2m_max_low_pfn __read_mostly; +unsigned long p2m_convert_min_pfn __read_mostly; +unsigned long p2m_convert_max_pfn __read_mostly; + +static struct resource p2m_resource; +static unsigned long p2m_assign_start_pfn __read_mostly; +static unsigned long p2m_assign_end_pfn __read_mostly; +volatile const pte_t* p2m_pte; + +#define GRNULE_PFN PTRS_PER_PTE +static unsigned long p2m_granule_pfn __read_mostly = GRNULE_PFN; + +#define ROUNDDOWN(x, y) ((x) & ~((y) - 1)) +#define ROUNDUP(x, y) (((x) + (y) - 1) & ~((y) - 1)) + +#define P2M_PREFIX "Xen p2m: " + +static int xen_ia64_p2m_expose = 1; +module_param(xen_ia64_p2m_expose, int, 0); +MODULE_DESCRIPTION("enable/disable xen/ia64 p2m exposure optimization"); + +int +p2m_expose_init(void) +{ + unsigned long size; + int error; + + if (!xen_ia64_p2m_expose) + return -ENOSYS; + if (p2m_initialized) + return 0; + +#ifdef CONFIG_DISCONTIGMEM + p2m_min_low_pfn = min_low_pfn; + p2m_max_low_pfn = max_low_pfn; +#else + p2m_min_low_pfn = 0; + p2m_max_low_pfn = max_pfn; +#endif + + BUG_ON(p2m_granule_pfn & (p2m_granule_pfn - 1)); + p2m_convert_min_pfn = ROUNDDOWN(p2m_min_low_pfn, p2m_granule_pfn); + p2m_convert_max_pfn = ROUNDUP(p2m_max_low_pfn, p2m_granule_pfn); + size = (p2m_convert_max_pfn - p2m_convert_min_pfn) << PAGE_SHIFT; + + // use privcmd region + p2m_resource.name = "Xen p2m table"; + error = allocate_resource(&iomem_resource, &p2m_resource, size, + privcmd_resource_min, privcmd_resource_max, + max(privcmd_resource_align, + p2m_granule_pfn << PAGE_SHIFT), + NULL, NULL); + if (error) { + printk(KERN_ERR P2M_PREFIX + "can't allocate region for p2m exposure " + "[0x%016lx, 0x%016lx]\n", + p2m_convert_min_pfn, p2m_convert_max_pfn); + return error; + } + + p2m_assign_start_pfn = p2m_resource.start >> PAGE_SHIFT; + p2m_assign_end_pfn = p2m_resource.end >> PAGE_SHIFT; + + error = HYPERVISOR_expose_p2m(p2m_convert_min_pfn, + p2m_assign_start_pfn, + size, p2m_granule_pfn); + if (error) { + printk(KERN_ERR P2M_PREFIX "failed expose p2m hypercall\n"); + printk(KERN_ERR P2M_PREFIX "conv 0x%016lx assign 0x%016lx " + "size 0x%016lx granule 0x%016lx\n", + p2m_convert_min_pfn, p2m_assign_start_pfn, + size, p2m_granule_pfn);; + release_resource(&p2m_resource); + return error; + } + p2m_pte = (volatile const pte_t*)pfn_to_kaddr(p2m_assign_start_pfn); + + smp_mb(); + p2m_initialized = 1; + printk(P2M_PREFIX "assign p2m table of [0x%016lx, 0x%016lx]\n", + p2m_convert_min_pfn << PAGE_SHIFT, + p2m_convert_max_pfn << PAGE_SHIFT); + printk(P2M_PREFIX "to [0x%016lx, 0x%016lx]\n", + p2m_assign_start_pfn << PAGE_SHIFT, + p2m_assign_end_pfn << PAGE_SHIFT); + return 0; +} + +#ifdef notyet +void +p2m_expose_cleanup(void) +{ + BUG_ON(!p2m_initialized); + release_resrouce(&p2m_resource); +} +#endif + +//XXX inlinize? +unsigned long +p2m_phystomach(unsigned long gpfn) +{ + volatile const pte_t* pte; + unsigned long mfn; + unsigned long pteval; + + if (!p2m_initialized || + gpfn < p2m_min_low_pfn || gpfn > p2m_max_low_pfn + /* || !pfn_valid(gpfn) */) + return INVALID_MFN; + pte = p2m_pte + (gpfn - p2m_convert_min_pfn); + + mfn = INVALID_MFN; + if (likely(__get_user(pteval, (unsigned long __user *)pte) == 0) && + likely(pte_present(__pte(pteval))) && + likely(pte_pfn(__pte(pteval)) != (INVALID_MFN >> PAGE_SHIFT))) + mfn = (pteval & _PFN_MASK) >> PAGE_SHIFT; + + return mfn; +} + +EXPORT_SYMBOL(p2m_initialized); +EXPORT_SYMBOL(p2m_min_low_pfn); +EXPORT_SYMBOL(p2m_max_low_pfn); +EXPORT_SYMBOL(p2m_convert_min_pfn); +EXPORT_SYMBOL(p2m_convert_max_pfn); +EXPORT_SYMBOL(p2m_pte); +EXPORT_SYMBOL(p2m_expose_init); +EXPORT_SYMBOL(p2m_phystomach); +#endif diff -r 5e2fec53ecc5 -r dc37e8c2b96a linux-2.6-xen-sparse/include/asm-ia64/hypercall.h --- a/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h Wed Aug 09 19:23:11 2006 +0900 +++ b/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h Wed Aug 09 19:24:35 2006 +0900 @@ -490,6 +490,33 @@ HYPERVISOR_add_physmap(unsigned long gpf return ret; } +#ifdef CONFIG_XEN_IA64_EXPOSE_P2M +static inline unsigned long +__HYPERVISOR_expose_p2m(unsigned long conv_start_gpfn, + unsigned long assign_start_gpfn, + unsigned long expose_size, unsigned long granule_pfn) +{ + return _hypercall_imm4(unsigned long, ia64_dom0vp_op, + IA64_DOM0VP_expose_p2m, + conv_start_gpfn, assign_start_gpfn, + expose_size, granule_pfn); +} + +static inline unsigned long +HYPERVISOR_expose_p2m(unsigned long conv_start_gpfn, + unsigned long assign_start_gpfn, + unsigned long expose_size, unsigned long granule_pfn) +{ + unsigned long ret = 0; + if (is_running_on_xen()) { + ret = __HYPERVISOR_expose_p2m(conv_start_gpfn, + assign_start_gpfn, + expose_size, granule_pfn); + } + return ret; +} +#endif + // for balloon driver #define HYPERVISOR_update_va_mapping(va, new_val, flags) (0) diff -r 5e2fec53ecc5 -r dc37e8c2b96a linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h --- a/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h Wed Aug 09 19:23:11 2006 +0900 +++ b/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h Wed Aug 09 19:24:35 2006 +0900 @@ -168,6 +168,17 @@ xen_destroy_contiguous_region(unsigned l __xen_destroy_contiguous_region(vstart, order); } +#ifdef CONFIG_XEN_IA64_EXPOSE_P2M +extern int p2m_initialized; +extern unsigned long p2m_min_low_pfn; +extern unsigned long p2m_max_low_pfn; +extern unsigned long p2m_convert_min_pfn; +extern unsigned long p2m_convert_max_pfn; +extern volatile const pte_t* p2m_pte; +int p2m_expose_init(void); +unsigned long p2m_phystomach(unsigned long gpfn); +#endif + // for netfront.c, netback.c #define MULTI_UVMFLAGS_INDEX 0 //XXX any value diff -r 5e2fec53ecc5 -r dc37e8c2b96a linux-2.6-xen-sparse/include/asm-ia64/page.h --- a/linux-2.6-xen-sparse/include/asm-ia64/page.h Wed Aug 09 19:23:11 2006 +0900 +++ b/linux-2.6-xen-sparse/include/asm-ia64/page.h Wed Aug 09 19:24:35 2006 +0900 @@ -271,6 +271,13 @@ pfn_to_mfn_for_dma(unsigned long pfn) pfn_to_mfn_for_dma(unsigned long pfn) { unsigned long mfn; +#ifdef CONFIG_XEN_IA64_EXPOSE_P2M + // avoid include hell. + extern int p2m_initialized; + unsigned long p2m_phystomach(unsigned long gpfn); + if (p2m_initialized) + return p2m_phystomach(pfn); +#endif mfn = HYPERVISOR_phystomach(pfn); BUG_ON(mfn == 0); // XXX BUG_ON(mfn == INVALID_P2M_ENTRY); // XXX