[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] [IA64] p2m exposure. linux side part.



# HG changeset patch
# User awilliam@xxxxxxxxxxx
# Node ID d1d9f3f6ca09e109261a2dacc6b75fe87d162b53
# Parent  0bb486157ff5886c1593146169a17e91280f53e9
[IA64] 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.
This patch also introduce XEN_IA64_EXPOSE_P2M_USE_DTR to map p2m table
with dtr and boot option xen_ia64_p2m_expose_use_dtr to disable it.

Signed-off-by: Isaku Yamahata <yamahata@xxxxxxxxxxxxx>
---
 linux-2.6-xen-sparse/arch/ia64/Kconfig            |   14 +
 linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c   |  279 ++++++++++++++++++++++
 linux-2.6-xen-sparse/include/asm-ia64/hypercall.h |   12 
 linux-2.6-xen-sparse/include/asm-ia64/maddr.h     |   15 +
 4 files changed, 320 insertions(+)

diff -r 0bb486157ff5 -r d1d9f3f6ca09 linux-2.6-xen-sparse/arch/ia64/Kconfig
--- a/linux-2.6-xen-sparse/arch/ia64/Kconfig    Wed Oct 04 22:12:25 2006 -0600
+++ b/linux-2.6-xen-sparse/arch/ia64/Kconfig    Wed Oct 04 22:12:29 2006 -0600
@@ -63,6 +63,20 @@ config XEN_IA64_VDSO_PARAVIRT
        default y
        help
          vDSO paravirtualization
+
+config XEN_IA64_EXPOSE_P2M
+       bool "Xen/IA64 exposure p2m table"
+       depends on XEN
+       default y
+       help
+         expose p2m from xen
+
+config XEN_IA64_EXPOSE_P2M_USE_DTR
+       bool "Xen/IA64 map p2m table with dtr"
+       depends on XEN_IA64_EXPOSE_P2M
+       default y
+       help
+         use dtr to map the exposed p2m table
 
 config SCHED_NO_NO_OMIT_FRAME_POINTER
        bool
diff -r 0bb486157ff5 -r d1d9f3f6ca09 
linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c
--- a/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c   Wed Oct 04 22:12:25 
2006 -0600
+++ b/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c   Wed Oct 04 22:12:29 
2006 -0600
@@ -39,6 +39,8 @@ EXPORT_SYMBOL(xen_start_info);
 
 int running_on_xen;
 EXPORT_SYMBOL(running_on_xen);
+
+static int p2m_expose_init(void);
 
 //XXX same as i386, x86_64 contiguous_bitmap_set(), contiguous_bitmap_clear()
 // move those to lib/contiguous_bitmap?
@@ -448,6 +450,10 @@ 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
+       (void)p2m_expose_init();
+
        return 0;
 }
 late_initcall(xen_ia64_privcmd_init);
@@ -753,3 +759,276 @@ time_resume(void)
        /* Just trigger a tick.  */
        ia64_cpu_local_tick();
 }
+
+///////////////////////////////////////////////////////////////////////////
+// expose p2m table
+#ifdef CONFIG_XEN_IA64_EXPOSE_P2M
+#include <linux/cpu.h>
+#include <asm/uaccess.h>
+
+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 = {
+       .name    = "Xen p2m table",
+       .flags   = IORESOURCE_MEM,
+};
+static unsigned long p2m_assign_start_pfn __read_mostly;
+static unsigned long p2m_assign_end_pfn __read_mostly;
+volatile const pte_t* p2m_pte __read_mostly;
+
+#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 __read_mostly = 1;
+module_param(xen_ia64_p2m_expose, int, 0);
+MODULE_PARM_DESC(xen_ia64_p2m_expose,
+                 "enable/disable xen/ia64 p2m exposure optimization\n");
+
+#ifdef CONFIG_XEN_IA64_EXPOSE_P2M_USE_DTR
+static int xen_ia64_p2m_expose_use_dtr __read_mostly = 1;
+module_param(xen_ia64_p2m_expose_use_dtr, int, 0);
+MODULE_PARM_DESC(xen_ia64_p2m_expose_use_dtr,
+                 "use/unuse dtr to map exposed p2m table\n");
+
+static const int p2m_page_shifts[] = {
+       _PAGE_SIZE_4K,
+       _PAGE_SIZE_8K,
+       _PAGE_SIZE_16K,
+       _PAGE_SIZE_64K,
+       _PAGE_SIZE_256K,
+       _PAGE_SIZE_1M,
+       _PAGE_SIZE_4M,
+       _PAGE_SIZE_16M,
+       _PAGE_SIZE_64M,
+       _PAGE_SIZE_256M,
+};
+
+struct p2m_itr_arg {
+       unsigned long vaddr;
+       unsigned long pteval;
+       unsigned long log_page_size;
+};
+static struct p2m_itr_arg p2m_itr_arg __read_mostly;
+
+// This should be in asm-ia64/kregs.h
+#define IA64_TR_P2M_TABLE      3
+
+static void
+p2m_itr(void* info)
+{
+       struct p2m_itr_arg* arg = (struct p2m_itr_arg*)info;
+       ia64_itr(0x2, IA64_TR_P2M_TABLE,
+                arg->vaddr, arg->pteval, arg->log_page_size);
+       ia64_srlz_d();
+}
+
+static int
+p2m_expose_dtr_call(struct notifier_block *self,
+                    unsigned long event, void* ptr)
+{
+       unsigned int cpu = (unsigned int)(long)ptr;
+       if (event != CPU_ONLINE)
+               return 0;
+       if (!(p2m_initialized && xen_ia64_p2m_expose_use_dtr))
+               smp_call_function_single(cpu, &p2m_itr, &p2m_itr_arg, 1, 1);
+       return 0;
+}
+
+static struct notifier_block p2m_expose_dtr_hotplug_notifier = {
+       .notifier_call = p2m_expose_dtr_call,
+       .next          = NULL,
+       .priority      = 0
+};
+#endif
+
+static int
+p2m_expose_init(void)
+{
+       unsigned long num_pfn;
+       unsigned long size = 0;
+       unsigned long p2m_size = 0;
+       unsigned long align = ~0UL;
+       int error = 0;
+#ifdef CONFIG_XEN_IA64_EXPOSE_P2M_USE_DTR
+       int i;
+       unsigned long page_size;
+       unsigned long log_page_size = 0;
+#endif
+
+       if (!xen_ia64_p2m_expose)
+               return -ENOSYS;
+       if (p2m_initialized)
+               return 0;
+
+#ifdef CONFIG_XEN_IA64_EXPOSE_P2M_USE_DTR
+       error = register_cpu_notifier(&p2m_expose_dtr_hotplug_notifier);
+       if (error < 0)
+               return error;
+#endif
+
+       lock_cpu_hotplug();
+       if (p2m_initialized)
+               goto out;
+
+#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
+
+#ifdef CONFIG_XEN_IA64_EXPOSE_P2M_USE_DTR
+       if (xen_ia64_p2m_expose_use_dtr) {
+               unsigned long granule_pfn = 0;
+               p2m_size = p2m_max_low_pfn - p2m_min_low_pfn;
+               for (i = 0;
+                    i < sizeof(p2m_page_shifts)/sizeof(p2m_page_shifts[0]);
+                    i++) {
+                       log_page_size = p2m_page_shifts[i];
+                       page_size = 1UL << log_page_size;
+                       if (page_size < p2m_size)
+                               continue;
+
+                       granule_pfn = max(page_size >> PAGE_SHIFT,
+                                         p2m_granule_pfn);
+                       p2m_convert_min_pfn = ROUNDDOWN(p2m_min_low_pfn,
+                                                       granule_pfn);
+                       p2m_convert_max_pfn = ROUNDUP(p2m_max_low_pfn,
+                                                     granule_pfn);
+                       num_pfn = p2m_convert_max_pfn - p2m_convert_min_pfn;
+                       size = num_pfn << PAGE_SHIFT;
+                       p2m_size = num_pfn / PTRS_PER_PTE;
+                       p2m_size = ROUNDUP(p2m_size, granule_pfn << PAGE_SHIFT);
+                       if (p2m_size == page_size)
+                               break;
+               }
+               if (p2m_size != page_size) {
+                       printk(KERN_ERR "p2m_size != page_size\n");
+                       error = -EINVAL;
+                       goto out;
+               }
+               align = max(privcmd_resource_align, granule_pfn << PAGE_SHIFT);
+       } else
+#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);
+               num_pfn = p2m_convert_max_pfn - p2m_convert_min_pfn;
+               size = num_pfn << PAGE_SHIFT;
+               p2m_size = num_pfn / PTRS_PER_PTE;
+               p2m_size = ROUNDUP(p2m_size, p2m_granule_pfn << PAGE_SHIFT);
+               align = max(privcmd_resource_align,
+                           p2m_granule_pfn << PAGE_SHIFT);
+       }
+       
+       // use privcmd region
+       error = allocate_resource(&iomem_resource, &p2m_resource, p2m_size,
+                                 privcmd_resource_min, privcmd_resource_max,
+                                 align, NULL, NULL);
+       if (error) {
+               printk(KERN_ERR P2M_PREFIX
+                      "can't allocate region for p2m exposure "
+                      "[0x%016lx, 0x%016lx) 0x%016lx\n",
+                      p2m_convert_min_pfn, p2m_convert_max_pfn, p2m_size);
+               goto out;
+       }
+
+       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 %d\n",
+                      error);
+               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);
+               goto out;
+       }
+       p2m_pte = (volatile const pte_t*)pfn_to_kaddr(p2m_assign_start_pfn);
+#ifdef CONFIG_XEN_IA64_EXPOSE_P2M_USE_DTR
+       if (xen_ia64_p2m_expose_use_dtr) {
+               p2m_itr_arg.vaddr = (unsigned long)__va(p2m_assign_start_pfn
+                                                       << PAGE_SHIFT);
+               p2m_itr_arg.pteval = pte_val(pfn_pte(p2m_assign_start_pfn,
+                                                    PAGE_KERNEL));
+               p2m_itr_arg.log_page_size = log_page_size;
+               smp_mb();
+               smp_call_function(&p2m_itr, &p2m_itr_arg, 1, 1);
+               p2m_itr(&p2m_itr_arg);
+       }
+#endif 
+       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) (%ld KBytes)\n",
+              p2m_assign_start_pfn << PAGE_SHIFT,
+              p2m_assign_end_pfn << PAGE_SHIFT,
+              p2m_size / 1024);
+out:
+       unlock_cpu_hotplug();
+       return error;
+}
+
+#ifdef notyet
+void
+p2m_expose_cleanup(void)
+{
+       BUG_ON(!p2m_initialized);
+#ifdef CONFIG_XEN_IA64_EXPOSE_P2M_USE_DTR
+       unregister_cpu_notifier(&p2m_expose_dtr_hotplug_notifier);
+#endif
+       release_resource(&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 &&
+                  pte_present(__pte(pteval)) &&
+                  pte_pfn(__pte(pteval)) != (INVALID_MFN >> PAGE_SHIFT)))
+               mfn = (pteval & _PFN_MASK) >> PAGE_SHIFT;
+
+       return mfn;
+}
+
+EXPORT_SYMBOL_GPL(p2m_initialized);
+EXPORT_SYMBOL_GPL(p2m_min_low_pfn);
+EXPORT_SYMBOL_GPL(p2m_max_low_pfn);
+EXPORT_SYMBOL_GPL(p2m_convert_min_pfn);
+EXPORT_SYMBOL_GPL(p2m_convert_max_pfn);
+EXPORT_SYMBOL_GPL(p2m_pte);
+EXPORT_SYMBOL_GPL(p2m_phystomach);
+#endif
diff -r 0bb486157ff5 -r d1d9f3f6ca09 
linux-2.6-xen-sparse/include/asm-ia64/hypercall.h
--- a/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h Wed Oct 04 22:12:25 
2006 -0600
+++ b/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h Wed Oct 04 22:12:29 
2006 -0600
@@ -377,6 +377,18 @@ 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 _hypercall5(unsigned long, ia64_dom0vp_op,
+                          IA64_DOM0VP_expose_p2m, conv_start_gpfn,
+                          assign_start_gpfn, expose_size, granule_pfn);
+}
+#endif
 
 // for balloon driver
 #define HYPERVISOR_update_va_mapping(va, new_val, flags) (0)
diff -r 0bb486157ff5 -r d1d9f3f6ca09 
linux-2.6-xen-sparse/include/asm-ia64/maddr.h
--- a/linux-2.6-xen-sparse/include/asm-ia64/maddr.h     Wed Oct 04 22:12:25 
2006 -0600
+++ b/linux-2.6-xen-sparse/include/asm-ia64/maddr.h     Wed Oct 04 22:12:29 
2006 -0600
@@ -10,11 +10,26 @@
 
 #define INVALID_P2M_ENTRY       (~0UL)
 
+#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;
+unsigned long p2m_phystomach(unsigned long gpfn);
+#else
+#define p2m_initialized                (0)
+#define p2m_phystomach(gpfn)   INVALID_MFN
+#endif
+
 /* XXX xen page size != page size */
 static inline unsigned long
 pfn_to_mfn_for_dma(unsigned long pfn)
 {
        unsigned long mfn;
+       if (p2m_initialized)
+               return p2m_phystomach(pfn);
        mfn = HYPERVISOR_phystomach(pfn);
        BUG_ON(mfn == 0); // XXX
        BUG_ON(mfn == INVALID_P2M_ENTRY); // XXX

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.