ia64/xen-unstable

changeset 9689:f6e8c269f6af

[IA64] Add support for discontiguous physical memory.

Signed-off-by: Kouya Shimura <kouya@jp.fujitsu.com>
author awilliam@xenbuild.aw
date Mon Apr 17 08:46:04 2006 -0600 (2006-04-17)
parents 042b695ffc69
children bdb08c9ef3d1
files xen/arch/ia64/linux-xen/efi.c xen/arch/ia64/linux-xen/head.S xen/arch/ia64/vmx/vmx_ivt.S xen/arch/ia64/xen/dom0_ops.c xen/arch/ia64/xen/domain.c xen/arch/ia64/xen/ivt.S xen/arch/ia64/xen/xenmem.c xen/include/asm-ia64/config.h xen/include/asm-ia64/xenpage.h xen/include/asm-ia64/xensystem.h
line diff
     1.1 --- a/xen/arch/ia64/linux-xen/efi.c	Fri Apr 14 14:24:09 2006 -0600
     1.2 +++ b/xen/arch/ia64/linux-xen/efi.c	Mon Apr 17 08:46:04 2006 -0600
     1.3 @@ -42,7 +42,7 @@ extern unsigned long long memparse (char
     1.4  struct efi efi;
     1.5  EXPORT_SYMBOL(efi);
     1.6  static efi_runtime_services_t *runtime;
     1.7 -#ifdef XEN
     1.8 +#if defined(XEN) && !defined(CONFIG_VIRTUAL_FRAME_TABLE)
     1.9  // this is a temporary hack to avoid CONFIG_VIRTUAL_MEM_MAP
    1.10  static unsigned long mem_limit = ~0UL, max_addr = 0x100000000;
    1.11  #else
     2.1 --- a/xen/arch/ia64/linux-xen/head.S	Fri Apr 14 14:24:09 2006 -0600
     2.2 +++ b/xen/arch/ia64/linux-xen/head.S	Mon Apr 17 08:46:04 2006 -0600
     2.3 @@ -182,6 +182,12 @@ empty_zero_page:
     2.4  swapper_pg_dir:
     2.5  	.skip PAGE_SIZE
     2.6  
     2.7 +#if defined(XEN) && defined(CONFIG_VIRTUAL_FRAME_TABLE)
     2.8 +	.global frametable_pg_dir
     2.9 +frametable_pg_dir:
    2.10 +	.skip PAGE_SIZE
    2.11 +#endif
    2.12 +
    2.13  	.rodata
    2.14  halt_msg:
    2.15  	stringz "Halting kernel\n"
     3.1 --- a/xen/arch/ia64/vmx/vmx_ivt.S	Fri Apr 14 14:24:09 2006 -0600
     3.2 +++ b/xen/arch/ia64/vmx/vmx_ivt.S	Mon Apr 17 08:46:04 2006 -0600
     3.3 @@ -305,6 +305,12 @@ ENTRY(vmx_alt_dtlb_miss)
     3.4  vmx_alt_dtlb_miss_1:
     3.5  	mov r16=cr.ifa		// get address that caused the TLB miss
     3.6      ;;
     3.7 +#ifdef CONFIG_VIRTUAL_FRAME_TABLE
     3.8 +	// Test for the address of virtual frame_table
     3.9 +	shr r22=r16,56;;
    3.10 +	cmp.eq p8,p0=((VIRT_FRAME_TABLE_ADDR>>56)&0xff)-0x100,r22
    3.11 +(p8)	br.cond.sptk frametable_miss ;;
    3.12 +#endif
    3.13      tbit.z p6,p7=r16,63
    3.14  (p6)br.spnt vmx_fault_4
    3.15      ;;
     4.1 --- a/xen/arch/ia64/xen/dom0_ops.c	Fri Apr 14 14:24:09 2006 -0600
     4.2 +++ b/xen/arch/ia64/xen/dom0_ops.c	Mon Apr 17 08:46:04 2006 -0600
     4.3 @@ -42,7 +42,7 @@ long arch_do_dom0_op(dom0_op_t *op, GUES
     4.4               unlikely((d = find_domain_by_id(dom)) == NULL) )
     4.5              break;
     4.6  
     4.7 -        page = &frame_table[mfn];
     4.8 +        page = mfn_to_page(mfn);
     4.9  
    4.10          if ( likely(get_page(page, d)) )
    4.11          {
    4.12 @@ -110,7 +110,7 @@ long arch_do_dom0_op(dom0_op_t *op, GUES
    4.13                  if ( unlikely(mfn >= max_page) )
    4.14                      goto e2_err;
    4.15  
    4.16 -                page = &frame_table[mfn];
    4.17 +                page = mfn_to_page(mfn);
    4.18    
    4.19                  if ( likely(get_page(page, d)) )
    4.20                  {
     5.1 --- a/xen/arch/ia64/xen/domain.c	Fri Apr 14 14:24:09 2006 -0600
     5.2 +++ b/xen/arch/ia64/xen/domain.c	Mon Apr 17 08:46:04 2006 -0600
     5.3 @@ -1033,7 +1033,7 @@ int construct_dom0(struct domain *d,
     5.4  	      mfn < (alloc_end>>PAGE_SHIFT); 
     5.5  	      mfn++ )
     5.6  	{
     5.7 -            page = &frame_table[mfn];
     5.8 +            page = mfn_to_page(mfn);
     5.9              page_set_owner(page, d);
    5.10              page->u.inuse.type_info = 0;
    5.11              page->count_info        = PGC_allocated | 1;
     6.1 --- a/xen/arch/ia64/xen/ivt.S	Fri Apr 14 14:24:09 2006 -0600
     6.2 +++ b/xen/arch/ia64/xen/ivt.S	Mon Apr 17 08:46:04 2006 -0600
     6.3 @@ -529,6 +529,12 @@ late_alt_dtlb_miss:
     6.4  (p8)	br.cond.spnt page_fault
     6.5  #ifdef XEN
     6.6  	;;
     6.7 +#ifdef CONFIG_VIRTUAL_FRAME_TABLE
     6.8 +	// Test for the address of virtual frame_table
     6.9 +	shr r22=r16,56;;
    6.10 +	cmp.eq p8,p0=((VIRT_FRAME_TABLE_ADDR>>56)&0xff)-0x100,r22
    6.11 +(p8)	br.cond.sptk frametable_miss ;;
    6.12 +#endif
    6.13  	// Test for Xen address, if not handle via page_fault
    6.14  	// note that 0xf000 (cached) and 0xe800 (uncached) addresses
    6.15  	// should be OK.
    6.16 @@ -550,6 +556,65 @@ 1:
    6.17  	mov pr=r31,-1
    6.18  	rfi
    6.19  END(alt_dtlb_miss)
    6.20 +#ifdef CONFIG_VIRTUAL_FRAME_TABLE	
    6.21 +GLOBAL_ENTRY(frametable_miss)
    6.22 +	rsm psr.dt		// switch to using physical data addressing
    6.23 +	movl r24=(frametable_pg_dir-PAGE_OFFSET)	// r24=__pa(frametable_pg_dir)
    6.24 +	;;
    6.25 +	srlz.d
    6.26 +	extr.u r17=r16,PGDIR_SHIFT,(PAGE_SHIFT-3)
    6.27 +	;;
    6.28 +	shladd r24=r17,3,r24	// r24=&pgd[pgd_offset(addr)]
    6.29 +	;;
    6.30 +	ld8 r24=[r24]		// r24=pgd[pgd_offset(addr)]
    6.31 +	extr.u r18=r16,PMD_SHIFT,(PAGE_SHIFT-3)	// r18=pmd_offset
    6.32 +	;;
    6.33 +	cmp.eq p6,p7=0,r24	// pgd present?
    6.34 +	shladd r24=r18,3,r24	// r24=&pmd[pmd_offset(addr)]
    6.35 +	;;
    6.36 +(p7)	ld8 r24=[r24]		// r24=pmd[pmd_offset(addr)]
    6.37 +	extr.u r19=r16,PAGE_SHIFT,(PAGE_SHIFT-3)// r19=pte_offset
    6.38 +(p6)	br.spnt.few frametable_fault
    6.39 +	;;
    6.40 +	cmp.eq p6,p7=0,r24	// pmd present?
    6.41 +	shladd r24=r19,3,r24	// r24=&pte[pte_offset(addr)]
    6.42 +	;;
    6.43 +(p7)	ld8 r24=[r24]		// r24=pte[pte_offset(addr)]
    6.44 +	mov r25=0x700|(_PAGE_SIZE_16K<<2) // key=7
    6.45 +(p6)	br.spnt.few frametable_fault
    6.46 +	;;
    6.47 +	mov cr.itir=r25
    6.48 +	ssm psr.dt		// switch to using virtual data addressing
    6.49 +	tbit.z p6,p7=r24,_PAGE_P_BIT	// pte present? 
    6.50 +	;;
    6.51 +(p7)	itc.d r24		// install updated PTE
    6.52 +(p6)	br.spnt.few frametable_fault	// page present bit cleared?
    6.53 +	;;
    6.54 +	mov pr=r31,-1		// restore predicate registers
    6.55 +	rfi
    6.56 +END(frametable_miss)
    6.57 +ENTRY(frametable_fault)
    6.58 +	ssm psr.dt		// switch to using virtual data addressing
    6.59 +	mov r18=cr.iip
    6.60 +	movl r19=ia64_frametable_probe
    6.61 +	;;
    6.62 +	cmp.eq p6,p7=r18,r19	// is faulting addrress ia64_frametable_probe?
    6.63 +	mov r8=0		// assumes that 'probe.r' uses r8
    6.64 +	dep r21=-1,r21,IA64_PSR_RI_BIT+1,1 // return to next instrucition in bundle 2
    6.65 +	;;
    6.66 +(p6)	mov cr.ipsr=r21
    6.67 +	mov r19=4		// FAULT(4)
    6.68 +(p7)	br.spnt.few dispatch_to_fault_handler
    6.69 +	;;
    6.70 +	mov pr=r31,-1
    6.71 +	rfi
    6.72 +END(frametable_fault)
    6.73 +GLOBAL_ENTRY(ia64_frametable_probe)
    6.74 +	probe.r	r8=r32,0	// destination register must be r8
    6.75 +	nop.f 0x0
    6.76 +	br.ret.sptk.many b0	// this instruction must be in bundle 2
    6.77 +END(ia64_frametable_probe)
    6.78 +#endif /* CONFIG_VIRTUAL_FRAME_TABLE */
    6.79  
    6.80  	.org ia64_ivt+0x1400
    6.81  /////////////////////////////////////////////////////////////////////////////////////////
     7.1 --- a/xen/arch/ia64/xen/xenmem.c	Fri Apr 14 14:24:09 2006 -0600
     7.2 +++ b/xen/arch/ia64/xen/xenmem.c	Mon Apr 17 08:46:04 2006 -0600
     7.3 @@ -13,29 +13,42 @@
     7.4  #include <asm/pgtable.h>
     7.5  #include <xen/mm.h>
     7.6  
     7.7 -struct page_info *frame_table;
     7.8 -unsigned long frame_table_size;
     7.9 -unsigned long max_page;
    7.10 +#ifdef CONFIG_VIRTUAL_FRAME_TABLE
    7.11 +#include <linux/efi.h>
    7.12 +#include <asm/pgalloc.h>
    7.13  
    7.14 -struct page_info *mem_map;
    7.15 -#define MAX_DMA_ADDRESS ~0UL	// FIXME???
    7.16 +extern pgd_t frametable_pg_dir[];
    7.17  
    7.18 -#ifdef CONFIG_VIRTUAL_MEM_MAP
    7.19 -static unsigned long num_dma_physpages;
    7.20 +#define frametable_pgd_offset(addr) \
    7.21 +	(frametable_pg_dir + (((addr) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1)))
    7.22 +
    7.23 +static unsigned long table_size;
    7.24 +static int opt_contig_mem = 0;
    7.25 +boolean_param("contig_mem", opt_contig_mem);
    7.26 +#else
    7.27 +#define opt_contig_mem 1
    7.28  #endif
    7.29  
    7.30 +struct page_info *frame_table;
    7.31 +unsigned long max_page;
    7.32 +
    7.33  /*
    7.34   * Set up the page tables.
    7.35   */
    7.36  unsigned long *mpt_table;
    7.37 -unsigned long mpt_table_size;
    7.38  
    7.39  void
    7.40  paging_init (void)
    7.41  {
    7.42  	unsigned int mpt_order;
    7.43 +	unsigned long mpt_table_size;
    7.44  	unsigned long i;
    7.45  
    7.46 +	if (!opt_contig_mem) {
    7.47 +		/* mpt_table is already allocated at this point. */
    7.48 +		return;
    7.49 +	}
    7.50 +
    7.51  	/* Create machine to physical mapping table
    7.52  	 * NOTE: similar to frame table, later we may need virtually
    7.53  	 * mapped mpt table if large hole exists. Also MAX_ORDER needs
    7.54 @@ -57,14 +70,165 @@ paging_init (void)
    7.55  	}
    7.56  }
    7.57  
    7.58 +#ifdef CONFIG_VIRTUAL_FRAME_TABLE
    7.59 +
    7.60 +static inline void *
    7.61 +alloc_dir_page(void)
    7.62 +{
    7.63 +	unsigned long mfn = alloc_boot_pages(1, 1);
    7.64 +	unsigned long dir;
    7.65 +	if (!mfn)
    7.66 +		panic("Not enough memory for virtual frame table!\n");
    7.67 +	++table_size;
    7.68 +	dir = mfn << PAGE_SHIFT;
    7.69 +	memset(__va(dir), 0, PAGE_SIZE);
    7.70 +	return (void *)dir;
    7.71 +}
    7.72 +
    7.73 +static inline unsigned long
    7.74 +alloc_table_page(unsigned long fill)
    7.75 +{
    7.76 +	unsigned long mfn = alloc_boot_pages(1, 1);
    7.77 +	unsigned long *table;
    7.78 +	unsigned long i;
    7.79 +	if (!mfn)
    7.80 +		panic("Not enough memory for virtual frame table!\n");
    7.81 +	++table_size;
    7.82 +	table = (unsigned long *)__va((mfn << PAGE_SHIFT));
    7.83 +	for (i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++)
    7.84 +	    table[i] = fill;
    7.85 +	return mfn;
    7.86 +}
    7.87 +
    7.88 +int
    7.89 +create_frametable_page_table (u64 start, u64 end, void *arg)
    7.90 +{
    7.91 +	unsigned long address, start_page, end_page;
    7.92 +	struct page_info *map_start, *map_end;
    7.93 +	pgd_t *pgd;
    7.94 +	pud_t *pud;
    7.95 +	pmd_t *pmd;
    7.96 +	pte_t *pte;
    7.97 +
    7.98 +	map_start = frame_table + (__pa(start) >> PAGE_SHIFT);
    7.99 +	map_end   = frame_table + (__pa(end) >> PAGE_SHIFT);
   7.100 +
   7.101 +	start_page = (unsigned long) map_start & PAGE_MASK;
   7.102 +	end_page = PAGE_ALIGN((unsigned long) map_end);
   7.103 +
   7.104 +	for (address = start_page; address < end_page; address += PAGE_SIZE) {
   7.105 +		pgd = frametable_pgd_offset(address);
   7.106 +		if (pgd_none(*pgd))
   7.107 +			pgd_populate(NULL, pgd, alloc_dir_page());
   7.108 +		pud = pud_offset(pgd, address);
   7.109 +
   7.110 +		if (pud_none(*pud))
   7.111 +			pud_populate(NULL, pud, alloc_dir_page());
   7.112 +		pmd = pmd_offset(pud, address);
   7.113 +
   7.114 +		if (pmd_none(*pmd))
   7.115 +			pmd_populate_kernel(NULL, pmd, alloc_dir_page());
   7.116 +		pte = pte_offset_kernel(pmd, address);
   7.117 +
   7.118 +		if (pte_none(*pte))
   7.119 +			set_pte(pte, pfn_pte(alloc_table_page(0), PAGE_KERNEL));
   7.120 +	}
   7.121 +	return 0;
   7.122 +}
   7.123 +
   7.124 +int
   7.125 +create_mpttable_page_table (u64 start, u64 end, void *arg)
   7.126 +{
   7.127 +	unsigned long address, start_page, end_page;
   7.128 +	unsigned long *map_start, *map_end;
   7.129 +	pgd_t *pgd;
   7.130 +	pud_t *pud;
   7.131 +	pmd_t *pmd;
   7.132 +	pte_t *pte;
   7.133 +
   7.134 +	map_start = mpt_table + (__pa(start) >> PAGE_SHIFT);
   7.135 +	map_end   = mpt_table + (__pa(end) >> PAGE_SHIFT);
   7.136 +
   7.137 +	start_page = (unsigned long) map_start & PAGE_MASK;
   7.138 +	end_page = PAGE_ALIGN((unsigned long) map_end);
   7.139 +
   7.140 +	for (address = start_page; address < end_page; address += PAGE_SIZE) {
   7.141 +		pgd = frametable_pgd_offset(address);
   7.142 +		if (pgd_none(*pgd))
   7.143 +			pgd_populate(NULL, pgd, alloc_dir_page());
   7.144 +		pud = pud_offset(pgd, address);
   7.145 +
   7.146 +		if (pud_none(*pud))
   7.147 +			pud_populate(NULL, pud, alloc_dir_page());
   7.148 +		pmd = pmd_offset(pud, address);
   7.149 +
   7.150 +		if (pmd_none(*pmd))
   7.151 +			pmd_populate_kernel(NULL, pmd, alloc_dir_page());
   7.152 +		pte = pte_offset_kernel(pmd, address);
   7.153 +
   7.154 +		if (pte_none(*pte))
   7.155 +			set_pte(pte, pfn_pte(alloc_table_page(INVALID_M2P_ENTRY), PAGE_KERNEL));
   7.156 +	}
   7.157 +	return 0;
   7.158 +}
   7.159 +
   7.160 +void init_virtual_frametable(void)
   7.161 +{
   7.162 +	/* Allocate virtual frame_table */
   7.163 +	frame_table = (struct page_info *) VIRT_FRAME_TABLE_ADDR;
   7.164 +	table_size = 0;
   7.165 +	efi_memmap_walk(create_frametable_page_table, NULL);
   7.166 +
   7.167 +	printk("size of virtual frame_table: %lukB\n",
   7.168 +	       ((table_size << PAGE_SHIFT) >> 10));
   7.169 +
   7.170 +	/* Allocate virtual mpt_table */
   7.171 +	table_size = 0;
   7.172 +	mpt_table = (unsigned long *)VIRT_FRAME_TABLE_END - max_page;
   7.173 +	efi_memmap_walk(create_mpttable_page_table, NULL);
   7.174 +
   7.175 +	printk("virtual machine to physical table: %p size: %lukB\n"
   7.176 +	       "max_page: 0x%lx\n",
   7.177 +	       mpt_table, ((table_size << PAGE_SHIFT) >> 10), max_page);
   7.178 +}
   7.179 +
   7.180 +int
   7.181 +ia64_mfn_valid (unsigned long pfn)
   7.182 +{
   7.183 +	extern long ia64_frametable_probe(unsigned long);
   7.184 +	struct page_info *pg;
   7.185 +	int valid;
   7.186 +
   7.187 +	if (opt_contig_mem)
   7.188 +		return 1;
   7.189 +	pg = mfn_to_page(pfn);
   7.190 +	valid = ia64_frametable_probe((unsigned long)pg);
   7.191 +	/* more check the whole struct of page_info */
   7.192 +	if (valid)
   7.193 +		valid = ia64_frametable_probe((unsigned long)(pg+1)-1);
   7.194 +	return valid;
   7.195 +}
   7.196 +
   7.197 +EXPORT_SYMBOL(ia64_mfn_valid);
   7.198 +
   7.199 +#endif /* CONFIG_VIRTUAL_FRAME_TABLE */
   7.200 +
   7.201  /* FIXME: postpone support to machines with big holes between physical memorys.
   7.202   * Current hack allows only efi memdesc upto 4G place. (See efi.c)
   7.203   */
   7.204 -#ifndef CONFIG_VIRTUAL_MEM_MAP
   7.205  #define FT_ALIGN_SIZE	(16UL << 20)
   7.206  void __init init_frametable(void)
   7.207  {
   7.208  	unsigned long pfn;
   7.209 +	unsigned long frame_table_size;
   7.210 +
   7.211 +#ifdef CONFIG_VIRTUAL_FRAME_TABLE
   7.212 +	if (!opt_contig_mem) {
   7.213 +		init_virtual_frametable();
   7.214 +		return;
   7.215 +	}
   7.216 +#endif
   7.217 +
   7.218  	frame_table_size = max_page * sizeof(struct page_info);
   7.219  	frame_table_size = (frame_table_size + PAGE_SIZE - 1) & PAGE_MASK;
   7.220  
   7.221 @@ -80,4 +244,3 @@ void __init init_frametable(void)
   7.222  	printk("size of frame_table: %lukB\n",
   7.223  		frame_table_size >> 10);
   7.224  }
   7.225 -#endif
     8.1 --- a/xen/include/asm-ia64/config.h	Fri Apr 14 14:24:09 2006 -0600
     8.2 +++ b/xen/include/asm-ia64/config.h	Mon Apr 17 08:46:04 2006 -0600
     8.3 @@ -18,6 +18,9 @@
     8.4  #define	CONFIG_IA64_PAGE_SIZE_16KB	// 4KB doesn't work?!?
     8.5  #define	CONFIG_IA64_GRANULE_16MB
     8.6  
     8.7 +// this needs to be on to run on system with large memory hole
     8.8 +#define	CONFIG_VIRTUAL_FRAME_TABLE
     8.9 +
    8.10  #define CONFIG_EFI_PCDP
    8.11  #define CONFIG_SERIAL_SGI_L1_CONSOLE
    8.12  
    8.13 @@ -262,10 +265,6 @@ extern int ht_per_core;
    8.14  #undef CONFIG_X86_IO_APIC
    8.15  #undef CONFIG_X86_L1_CACHE_SHIFT
    8.16  
    8.17 -// this needs to be on to run on hp zx1 with more than 4GB
    8.18 -// it is hacked around for now though
    8.19 -//#define	CONFIG_VIRTUAL_MEM_MAP
    8.20 -
    8.21  //#ifndef CONFIG_IA64_HP_SIM
    8.22  // looks like this is hard to turn off for Xen
    8.23  #define CONFIG_ACPI 1
     9.1 --- a/xen/include/asm-ia64/xenpage.h	Fri Apr 14 14:24:09 2006 -0600
     9.2 +++ b/xen/include/asm-ia64/xenpage.h	Mon Apr 17 08:46:04 2006 -0600
     9.3 @@ -8,7 +8,15 @@
     9.4  #undef mfn_valid
     9.5  #undef page_to_mfn
     9.6  #undef mfn_to_page
     9.7 +#ifdef CONFIG_VIRTUAL_FRAME_TABLE
     9.8 +#undef ia64_mfn_valid
     9.9 +#ifndef __ASSEMBLY__
    9.10 +extern int ia64_mfn_valid (unsigned long pfn);
    9.11 +#endif
    9.12 +# define mfn_valid(_pfn)	(((_pfn) < max_page) && ia64_mfn_valid(_pfn))
    9.13 +#else
    9.14  # define mfn_valid(_pfn)	((_pfn) < max_page)
    9.15 +#endif
    9.16  # define page_to_mfn(_page)	((unsigned long) ((_page) - frame_table))
    9.17  # define mfn_to_page(_pfn)	(frame_table + (_pfn))
    9.18  
    10.1 --- a/xen/include/asm-ia64/xensystem.h	Fri Apr 14 14:24:09 2006 -0600
    10.2 +++ b/xen/include/asm-ia64/xensystem.h	Mon Apr 17 08:46:04 2006 -0600
    10.3 @@ -27,6 +27,10 @@
    10.4  #define PERCPU_ADDR		 (SHAREDINFO_ADDR - PERCPU_PAGE_SIZE)
    10.5  #define XSI_OFS 		 (SHARED_ARCHINFO_ADDR - SHAREDINFO_ADDR)
    10.6  #define VHPT_ADDR		 0xf200000000000000
    10.7 +#ifdef CONFIG_VIRTUAL_FRAME_TABLE
    10.8 +#define VIRT_FRAME_TABLE_ADDR	 0xf300000000000000
    10.9 +#define VIRT_FRAME_TABLE_END	 0xf400000000000000
   10.10 +#endif
   10.11  #define XEN_END_ADDR		 0xf400000000000000
   10.12  
   10.13  #ifndef __ASSEMBLY__