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>
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