ia64/xen-unstable
changeset 11727:d1d9f3f6ca09
[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@valinux.co.jp>
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@valinux.co.jp>
author | awilliam@xenbuild.aw |
---|---|
date | Wed Oct 04 22:12:29 2006 -0600 (2006-10-04) |
parents | 0bb486157ff5 |
children | c1a8785f0eb1 |
files | linux-2.6-xen-sparse/arch/ia64/Kconfig linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c linux-2.6-xen-sparse/include/asm-ia64/hypercall.h linux-2.6-xen-sparse/include/asm-ia64/maddr.h |
line diff
1.1 --- a/linux-2.6-xen-sparse/arch/ia64/Kconfig Wed Oct 04 22:12:25 2006 -0600 1.2 +++ b/linux-2.6-xen-sparse/arch/ia64/Kconfig Wed Oct 04 22:12:29 2006 -0600 1.3 @@ -64,6 +64,20 @@ config XEN_IA64_VDSO_PARAVIRT 1.4 help 1.5 vDSO paravirtualization 1.6 1.7 +config XEN_IA64_EXPOSE_P2M 1.8 + bool "Xen/IA64 exposure p2m table" 1.9 + depends on XEN 1.10 + default y 1.11 + help 1.12 + expose p2m from xen 1.13 + 1.14 +config XEN_IA64_EXPOSE_P2M_USE_DTR 1.15 + bool "Xen/IA64 map p2m table with dtr" 1.16 + depends on XEN_IA64_EXPOSE_P2M 1.17 + default y 1.18 + help 1.19 + use dtr to map the exposed p2m table 1.20 + 1.21 config SCHED_NO_NO_OMIT_FRAME_POINTER 1.22 bool 1.23 default y
2.1 --- a/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c Wed Oct 04 22:12:25 2006 -0600 2.2 +++ b/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c Wed Oct 04 22:12:29 2006 -0600 2.3 @@ -40,6 +40,8 @@ EXPORT_SYMBOL(xen_start_info); 2.4 int running_on_xen; 2.5 EXPORT_SYMBOL(running_on_xen); 2.6 2.7 +static int p2m_expose_init(void); 2.8 + 2.9 //XXX same as i386, x86_64 contiguous_bitmap_set(), contiguous_bitmap_clear() 2.10 // move those to lib/contiguous_bitmap? 2.11 //XXX discontigmem/sparsemem 2.12 @@ -448,6 +450,10 @@ out: 2.13 privcmd_resource_min, privcmd_resource_max, 2.14 (privcmd_resource_max - privcmd_resource_min) >> 20); 2.15 BUG_ON(privcmd_resource_min >= privcmd_resource_max); 2.16 + 2.17 + // XXX this should be somewhere appropriate 2.18 + (void)p2m_expose_init(); 2.19 + 2.20 return 0; 2.21 } 2.22 late_initcall(xen_ia64_privcmd_init); 2.23 @@ -753,3 +759,276 @@ time_resume(void) 2.24 /* Just trigger a tick. */ 2.25 ia64_cpu_local_tick(); 2.26 } 2.27 + 2.28 +/////////////////////////////////////////////////////////////////////////// 2.29 +// expose p2m table 2.30 +#ifdef CONFIG_XEN_IA64_EXPOSE_P2M 2.31 +#include <linux/cpu.h> 2.32 +#include <asm/uaccess.h> 2.33 + 2.34 +int p2m_initialized __read_mostly = 0; 2.35 + 2.36 +unsigned long p2m_min_low_pfn __read_mostly; 2.37 +unsigned long p2m_max_low_pfn __read_mostly; 2.38 +unsigned long p2m_convert_min_pfn __read_mostly; 2.39 +unsigned long p2m_convert_max_pfn __read_mostly; 2.40 + 2.41 +static struct resource p2m_resource = { 2.42 + .name = "Xen p2m table", 2.43 + .flags = IORESOURCE_MEM, 2.44 +}; 2.45 +static unsigned long p2m_assign_start_pfn __read_mostly; 2.46 +static unsigned long p2m_assign_end_pfn __read_mostly; 2.47 +volatile const pte_t* p2m_pte __read_mostly; 2.48 + 2.49 +#define GRNULE_PFN PTRS_PER_PTE 2.50 +static unsigned long p2m_granule_pfn __read_mostly = GRNULE_PFN; 2.51 + 2.52 +#define ROUNDDOWN(x, y) ((x) & ~((y) - 1)) 2.53 +#define ROUNDUP(x, y) (((x) + (y) - 1) & ~((y) - 1)) 2.54 + 2.55 +#define P2M_PREFIX "Xen p2m: " 2.56 + 2.57 +static int xen_ia64_p2m_expose __read_mostly = 1; 2.58 +module_param(xen_ia64_p2m_expose, int, 0); 2.59 +MODULE_PARM_DESC(xen_ia64_p2m_expose, 2.60 + "enable/disable xen/ia64 p2m exposure optimization\n"); 2.61 + 2.62 +#ifdef CONFIG_XEN_IA64_EXPOSE_P2M_USE_DTR 2.63 +static int xen_ia64_p2m_expose_use_dtr __read_mostly = 1; 2.64 +module_param(xen_ia64_p2m_expose_use_dtr, int, 0); 2.65 +MODULE_PARM_DESC(xen_ia64_p2m_expose_use_dtr, 2.66 + "use/unuse dtr to map exposed p2m table\n"); 2.67 + 2.68 +static const int p2m_page_shifts[] = { 2.69 + _PAGE_SIZE_4K, 2.70 + _PAGE_SIZE_8K, 2.71 + _PAGE_SIZE_16K, 2.72 + _PAGE_SIZE_64K, 2.73 + _PAGE_SIZE_256K, 2.74 + _PAGE_SIZE_1M, 2.75 + _PAGE_SIZE_4M, 2.76 + _PAGE_SIZE_16M, 2.77 + _PAGE_SIZE_64M, 2.78 + _PAGE_SIZE_256M, 2.79 +}; 2.80 + 2.81 +struct p2m_itr_arg { 2.82 + unsigned long vaddr; 2.83 + unsigned long pteval; 2.84 + unsigned long log_page_size; 2.85 +}; 2.86 +static struct p2m_itr_arg p2m_itr_arg __read_mostly; 2.87 + 2.88 +// This should be in asm-ia64/kregs.h 2.89 +#define IA64_TR_P2M_TABLE 3 2.90 + 2.91 +static void 2.92 +p2m_itr(void* info) 2.93 +{ 2.94 + struct p2m_itr_arg* arg = (struct p2m_itr_arg*)info; 2.95 + ia64_itr(0x2, IA64_TR_P2M_TABLE, 2.96 + arg->vaddr, arg->pteval, arg->log_page_size); 2.97 + ia64_srlz_d(); 2.98 +} 2.99 + 2.100 +static int 2.101 +p2m_expose_dtr_call(struct notifier_block *self, 2.102 + unsigned long event, void* ptr) 2.103 +{ 2.104 + unsigned int cpu = (unsigned int)(long)ptr; 2.105 + if (event != CPU_ONLINE) 2.106 + return 0; 2.107 + if (!(p2m_initialized && xen_ia64_p2m_expose_use_dtr)) 2.108 + smp_call_function_single(cpu, &p2m_itr, &p2m_itr_arg, 1, 1); 2.109 + return 0; 2.110 +} 2.111 + 2.112 +static struct notifier_block p2m_expose_dtr_hotplug_notifier = { 2.113 + .notifier_call = p2m_expose_dtr_call, 2.114 + .next = NULL, 2.115 + .priority = 0 2.116 +}; 2.117 +#endif 2.118 + 2.119 +static int 2.120 +p2m_expose_init(void) 2.121 +{ 2.122 + unsigned long num_pfn; 2.123 + unsigned long size = 0; 2.124 + unsigned long p2m_size = 0; 2.125 + unsigned long align = ~0UL; 2.126 + int error = 0; 2.127 +#ifdef CONFIG_XEN_IA64_EXPOSE_P2M_USE_DTR 2.128 + int i; 2.129 + unsigned long page_size; 2.130 + unsigned long log_page_size = 0; 2.131 +#endif 2.132 + 2.133 + if (!xen_ia64_p2m_expose) 2.134 + return -ENOSYS; 2.135 + if (p2m_initialized) 2.136 + return 0; 2.137 + 2.138 +#ifdef CONFIG_XEN_IA64_EXPOSE_P2M_USE_DTR 2.139 + error = register_cpu_notifier(&p2m_expose_dtr_hotplug_notifier); 2.140 + if (error < 0) 2.141 + return error; 2.142 +#endif 2.143 + 2.144 + lock_cpu_hotplug(); 2.145 + if (p2m_initialized) 2.146 + goto out; 2.147 + 2.148 +#ifdef CONFIG_DISCONTIGMEM 2.149 + p2m_min_low_pfn = min_low_pfn; 2.150 + p2m_max_low_pfn = max_low_pfn; 2.151 +#else 2.152 + p2m_min_low_pfn = 0; 2.153 + p2m_max_low_pfn = max_pfn; 2.154 +#endif 2.155 + 2.156 +#ifdef CONFIG_XEN_IA64_EXPOSE_P2M_USE_DTR 2.157 + if (xen_ia64_p2m_expose_use_dtr) { 2.158 + unsigned long granule_pfn = 0; 2.159 + p2m_size = p2m_max_low_pfn - p2m_min_low_pfn; 2.160 + for (i = 0; 2.161 + i < sizeof(p2m_page_shifts)/sizeof(p2m_page_shifts[0]); 2.162 + i++) { 2.163 + log_page_size = p2m_page_shifts[i]; 2.164 + page_size = 1UL << log_page_size; 2.165 + if (page_size < p2m_size) 2.166 + continue; 2.167 + 2.168 + granule_pfn = max(page_size >> PAGE_SHIFT, 2.169 + p2m_granule_pfn); 2.170 + p2m_convert_min_pfn = ROUNDDOWN(p2m_min_low_pfn, 2.171 + granule_pfn); 2.172 + p2m_convert_max_pfn = ROUNDUP(p2m_max_low_pfn, 2.173 + granule_pfn); 2.174 + num_pfn = p2m_convert_max_pfn - p2m_convert_min_pfn; 2.175 + size = num_pfn << PAGE_SHIFT; 2.176 + p2m_size = num_pfn / PTRS_PER_PTE; 2.177 + p2m_size = ROUNDUP(p2m_size, granule_pfn << PAGE_SHIFT); 2.178 + if (p2m_size == page_size) 2.179 + break; 2.180 + } 2.181 + if (p2m_size != page_size) { 2.182 + printk(KERN_ERR "p2m_size != page_size\n"); 2.183 + error = -EINVAL; 2.184 + goto out; 2.185 + } 2.186 + align = max(privcmd_resource_align, granule_pfn << PAGE_SHIFT); 2.187 + } else 2.188 +#endif 2.189 + { 2.190 + BUG_ON(p2m_granule_pfn & (p2m_granule_pfn - 1)); 2.191 + p2m_convert_min_pfn = ROUNDDOWN(p2m_min_low_pfn, 2.192 + p2m_granule_pfn); 2.193 + p2m_convert_max_pfn = ROUNDUP(p2m_max_low_pfn, p2m_granule_pfn); 2.194 + num_pfn = p2m_convert_max_pfn - p2m_convert_min_pfn; 2.195 + size = num_pfn << PAGE_SHIFT; 2.196 + p2m_size = num_pfn / PTRS_PER_PTE; 2.197 + p2m_size = ROUNDUP(p2m_size, p2m_granule_pfn << PAGE_SHIFT); 2.198 + align = max(privcmd_resource_align, 2.199 + p2m_granule_pfn << PAGE_SHIFT); 2.200 + } 2.201 + 2.202 + // use privcmd region 2.203 + error = allocate_resource(&iomem_resource, &p2m_resource, p2m_size, 2.204 + privcmd_resource_min, privcmd_resource_max, 2.205 + align, NULL, NULL); 2.206 + if (error) { 2.207 + printk(KERN_ERR P2M_PREFIX 2.208 + "can't allocate region for p2m exposure " 2.209 + "[0x%016lx, 0x%016lx) 0x%016lx\n", 2.210 + p2m_convert_min_pfn, p2m_convert_max_pfn, p2m_size); 2.211 + goto out; 2.212 + } 2.213 + 2.214 + p2m_assign_start_pfn = p2m_resource.start >> PAGE_SHIFT; 2.215 + p2m_assign_end_pfn = p2m_resource.end >> PAGE_SHIFT; 2.216 + 2.217 + error = HYPERVISOR_expose_p2m(p2m_convert_min_pfn, 2.218 + p2m_assign_start_pfn, 2.219 + size, p2m_granule_pfn); 2.220 + if (error) { 2.221 + printk(KERN_ERR P2M_PREFIX "failed expose p2m hypercall %d\n", 2.222 + error); 2.223 + printk(KERN_ERR P2M_PREFIX "conv 0x%016lx assign 0x%016lx " 2.224 + "size 0x%016lx granule 0x%016lx\n", 2.225 + p2m_convert_min_pfn, p2m_assign_start_pfn, 2.226 + size, p2m_granule_pfn);; 2.227 + release_resource(&p2m_resource); 2.228 + goto out; 2.229 + } 2.230 + p2m_pte = (volatile const pte_t*)pfn_to_kaddr(p2m_assign_start_pfn); 2.231 +#ifdef CONFIG_XEN_IA64_EXPOSE_P2M_USE_DTR 2.232 + if (xen_ia64_p2m_expose_use_dtr) { 2.233 + p2m_itr_arg.vaddr = (unsigned long)__va(p2m_assign_start_pfn 2.234 + << PAGE_SHIFT); 2.235 + p2m_itr_arg.pteval = pte_val(pfn_pte(p2m_assign_start_pfn, 2.236 + PAGE_KERNEL)); 2.237 + p2m_itr_arg.log_page_size = log_page_size; 2.238 + smp_mb(); 2.239 + smp_call_function(&p2m_itr, &p2m_itr_arg, 1, 1); 2.240 + p2m_itr(&p2m_itr_arg); 2.241 + } 2.242 +#endif 2.243 + smp_mb(); 2.244 + p2m_initialized = 1; 2.245 + printk(P2M_PREFIX "assign p2m table of [0x%016lx, 0x%016lx)\n", 2.246 + p2m_convert_min_pfn << PAGE_SHIFT, 2.247 + p2m_convert_max_pfn << PAGE_SHIFT); 2.248 + printk(P2M_PREFIX "to [0x%016lx, 0x%016lx) (%ld KBytes)\n", 2.249 + p2m_assign_start_pfn << PAGE_SHIFT, 2.250 + p2m_assign_end_pfn << PAGE_SHIFT, 2.251 + p2m_size / 1024); 2.252 +out: 2.253 + unlock_cpu_hotplug(); 2.254 + return error; 2.255 +} 2.256 + 2.257 +#ifdef notyet 2.258 +void 2.259 +p2m_expose_cleanup(void) 2.260 +{ 2.261 + BUG_ON(!p2m_initialized); 2.262 +#ifdef CONFIG_XEN_IA64_EXPOSE_P2M_USE_DTR 2.263 + unregister_cpu_notifier(&p2m_expose_dtr_hotplug_notifier); 2.264 +#endif 2.265 + release_resource(&p2m_resource); 2.266 +} 2.267 +#endif 2.268 + 2.269 +//XXX inlinize? 2.270 +unsigned long 2.271 +p2m_phystomach(unsigned long gpfn) 2.272 +{ 2.273 + volatile const pte_t* pte; 2.274 + unsigned long mfn; 2.275 + unsigned long pteval; 2.276 + 2.277 + if (!p2m_initialized || 2.278 + gpfn < p2m_min_low_pfn || gpfn > p2m_max_low_pfn 2.279 + /* || !pfn_valid(gpfn) */) 2.280 + return INVALID_MFN; 2.281 + pte = p2m_pte + (gpfn - p2m_convert_min_pfn); 2.282 + 2.283 + mfn = INVALID_MFN; 2.284 + if (likely(__get_user(pteval, (unsigned long __user *)pte) == 0 && 2.285 + pte_present(__pte(pteval)) && 2.286 + pte_pfn(__pte(pteval)) != (INVALID_MFN >> PAGE_SHIFT))) 2.287 + mfn = (pteval & _PFN_MASK) >> PAGE_SHIFT; 2.288 + 2.289 + return mfn; 2.290 +} 2.291 + 2.292 +EXPORT_SYMBOL_GPL(p2m_initialized); 2.293 +EXPORT_SYMBOL_GPL(p2m_min_low_pfn); 2.294 +EXPORT_SYMBOL_GPL(p2m_max_low_pfn); 2.295 +EXPORT_SYMBOL_GPL(p2m_convert_min_pfn); 2.296 +EXPORT_SYMBOL_GPL(p2m_convert_max_pfn); 2.297 +EXPORT_SYMBOL_GPL(p2m_pte); 2.298 +EXPORT_SYMBOL_GPL(p2m_phystomach); 2.299 +#endif
3.1 --- a/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h Wed Oct 04 22:12:25 2006 -0600 3.2 +++ b/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h Wed Oct 04 22:12:29 2006 -0600 3.3 @@ -378,6 +378,18 @@ HYPERVISOR_add_physmap(unsigned long gpf 3.4 return ret; 3.5 } 3.6 3.7 +#ifdef CONFIG_XEN_IA64_EXPOSE_P2M 3.8 +static inline unsigned long 3.9 +HYPERVISOR_expose_p2m(unsigned long conv_start_gpfn, 3.10 + unsigned long assign_start_gpfn, 3.11 + unsigned long expose_size, unsigned long granule_pfn) 3.12 +{ 3.13 + return _hypercall5(unsigned long, ia64_dom0vp_op, 3.14 + IA64_DOM0VP_expose_p2m, conv_start_gpfn, 3.15 + assign_start_gpfn, expose_size, granule_pfn); 3.16 +} 3.17 +#endif 3.18 + 3.19 // for balloon driver 3.20 #define HYPERVISOR_update_va_mapping(va, new_val, flags) (0) 3.21
4.1 --- a/linux-2.6-xen-sparse/include/asm-ia64/maddr.h Wed Oct 04 22:12:25 2006 -0600 4.2 +++ b/linux-2.6-xen-sparse/include/asm-ia64/maddr.h Wed Oct 04 22:12:29 2006 -0600 4.3 @@ -10,11 +10,26 @@ 4.4 4.5 #define INVALID_P2M_ENTRY (~0UL) 4.6 4.7 +#ifdef CONFIG_XEN_IA64_EXPOSE_P2M 4.8 +extern int p2m_initialized; 4.9 +extern unsigned long p2m_min_low_pfn; 4.10 +extern unsigned long p2m_max_low_pfn; 4.11 +extern unsigned long p2m_convert_min_pfn; 4.12 +extern unsigned long p2m_convert_max_pfn; 4.13 +extern volatile const pte_t* p2m_pte; 4.14 +unsigned long p2m_phystomach(unsigned long gpfn); 4.15 +#else 4.16 +#define p2m_initialized (0) 4.17 +#define p2m_phystomach(gpfn) INVALID_MFN 4.18 +#endif 4.19 + 4.20 /* XXX xen page size != page size */ 4.21 static inline unsigned long 4.22 pfn_to_mfn_for_dma(unsigned long pfn) 4.23 { 4.24 unsigned long mfn; 4.25 + if (p2m_initialized) 4.26 + return p2m_phystomach(pfn); 4.27 mfn = HYPERVISOR_phystomach(pfn); 4.28 BUG_ON(mfn == 0); // XXX 4.29 BUG_ON(mfn == INVALID_P2M_ENTRY); // XXX