[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [IA64] Add support for discontiguous physical memory.
# HG changeset patch # User awilliam@xxxxxxxxxxx # Node ID f6e8c269f6afbfd7ea98b419e876e175803ea8e6 # Parent 042b695ffc691f63179684129854bc2e9612b8f7 [IA64] Add support for discontiguous physical memory. Signed-off-by: Kouya Shimura <kouya@xxxxxxxxxxxxxx> diff -r 042b695ffc69 -r f6e8c269f6af xen/arch/ia64/linux-xen/efi.c --- a/xen/arch/ia64/linux-xen/efi.c Fri Apr 14 14:24:09 2006 -0600 +++ b/xen/arch/ia64/linux-xen/efi.c Mon Apr 17 08:46:04 2006 -0600 @@ -42,7 +42,7 @@ struct efi efi; struct efi efi; EXPORT_SYMBOL(efi); static efi_runtime_services_t *runtime; -#ifdef XEN +#if defined(XEN) && !defined(CONFIG_VIRTUAL_FRAME_TABLE) // this is a temporary hack to avoid CONFIG_VIRTUAL_MEM_MAP static unsigned long mem_limit = ~0UL, max_addr = 0x100000000; #else diff -r 042b695ffc69 -r f6e8c269f6af xen/arch/ia64/linux-xen/head.S --- a/xen/arch/ia64/linux-xen/head.S Fri Apr 14 14:24:09 2006 -0600 +++ b/xen/arch/ia64/linux-xen/head.S Mon Apr 17 08:46:04 2006 -0600 @@ -181,6 +181,12 @@ empty_zero_page: .global swapper_pg_dir swapper_pg_dir: .skip PAGE_SIZE + +#if defined(XEN) && defined(CONFIG_VIRTUAL_FRAME_TABLE) + .global frametable_pg_dir +frametable_pg_dir: + .skip PAGE_SIZE +#endif .rodata halt_msg: diff -r 042b695ffc69 -r f6e8c269f6af xen/arch/ia64/vmx/vmx_ivt.S --- a/xen/arch/ia64/vmx/vmx_ivt.S Fri Apr 14 14:24:09 2006 -0600 +++ b/xen/arch/ia64/vmx/vmx_ivt.S Mon Apr 17 08:46:04 2006 -0600 @@ -305,6 +305,12 @@ vmx_alt_dtlb_miss_1: vmx_alt_dtlb_miss_1: mov r16=cr.ifa // get address that caused the TLB miss ;; +#ifdef CONFIG_VIRTUAL_FRAME_TABLE + // Test for the address of virtual frame_table + shr r22=r16,56;; + cmp.eq p8,p0=((VIRT_FRAME_TABLE_ADDR>>56)&0xff)-0x100,r22 +(p8) br.cond.sptk frametable_miss ;; +#endif tbit.z p6,p7=r16,63 (p6)br.spnt vmx_fault_4 ;; diff -r 042b695ffc69 -r f6e8c269f6af xen/arch/ia64/xen/dom0_ops.c --- a/xen/arch/ia64/xen/dom0_ops.c Fri Apr 14 14:24:09 2006 -0600 +++ b/xen/arch/ia64/xen/dom0_ops.c Mon Apr 17 08:46:04 2006 -0600 @@ -42,7 +42,7 @@ long arch_do_dom0_op(dom0_op_t *op, GUES unlikely((d = find_domain_by_id(dom)) == NULL) ) break; - page = &frame_table[mfn]; + page = mfn_to_page(mfn); if ( likely(get_page(page, d)) ) { @@ -110,7 +110,7 @@ long arch_do_dom0_op(dom0_op_t *op, GUES if ( unlikely(mfn >= max_page) ) goto e2_err; - page = &frame_table[mfn]; + page = mfn_to_page(mfn); if ( likely(get_page(page, d)) ) { diff -r 042b695ffc69 -r f6e8c269f6af xen/arch/ia64/xen/domain.c --- a/xen/arch/ia64/xen/domain.c Fri Apr 14 14:24:09 2006 -0600 +++ b/xen/arch/ia64/xen/domain.c Mon Apr 17 08:46:04 2006 -0600 @@ -1033,7 +1033,7 @@ int construct_dom0(struct domain *d, mfn < (alloc_end>>PAGE_SHIFT); mfn++ ) { - page = &frame_table[mfn]; + page = mfn_to_page(mfn); page_set_owner(page, d); page->u.inuse.type_info = 0; page->count_info = PGC_allocated | 1; diff -r 042b695ffc69 -r f6e8c269f6af xen/arch/ia64/xen/ivt.S --- a/xen/arch/ia64/xen/ivt.S Fri Apr 14 14:24:09 2006 -0600 +++ b/xen/arch/ia64/xen/ivt.S Mon Apr 17 08:46:04 2006 -0600 @@ -529,6 +529,12 @@ late_alt_dtlb_miss: (p8) br.cond.spnt page_fault #ifdef XEN ;; +#ifdef CONFIG_VIRTUAL_FRAME_TABLE + // Test for the address of virtual frame_table + shr r22=r16,56;; + cmp.eq p8,p0=((VIRT_FRAME_TABLE_ADDR>>56)&0xff)-0x100,r22 +(p8) br.cond.sptk frametable_miss ;; +#endif // Test for Xen address, if not handle via page_fault // note that 0xf000 (cached) and 0xe800 (uncached) addresses // should be OK. @@ -550,6 +556,65 @@ 1: mov pr=r31,-1 rfi END(alt_dtlb_miss) +#ifdef CONFIG_VIRTUAL_FRAME_TABLE +GLOBAL_ENTRY(frametable_miss) + rsm psr.dt // switch to using physical data addressing + movl r24=(frametable_pg_dir-PAGE_OFFSET) // r24=__pa(frametable_pg_dir) + ;; + srlz.d + extr.u r17=r16,PGDIR_SHIFT,(PAGE_SHIFT-3) + ;; + shladd r24=r17,3,r24 // r24=&pgd[pgd_offset(addr)] + ;; + ld8 r24=[r24] // r24=pgd[pgd_offset(addr)] + extr.u r18=r16,PMD_SHIFT,(PAGE_SHIFT-3) // r18=pmd_offset + ;; + cmp.eq p6,p7=0,r24 // pgd present? + shladd r24=r18,3,r24 // r24=&pmd[pmd_offset(addr)] + ;; +(p7) ld8 r24=[r24] // r24=pmd[pmd_offset(addr)] + extr.u r19=r16,PAGE_SHIFT,(PAGE_SHIFT-3)// r19=pte_offset +(p6) br.spnt.few frametable_fault + ;; + cmp.eq p6,p7=0,r24 // pmd present? + shladd r24=r19,3,r24 // r24=&pte[pte_offset(addr)] + ;; +(p7) ld8 r24=[r24] // r24=pte[pte_offset(addr)] + mov r25=0x700|(_PAGE_SIZE_16K<<2) // key=7 +(p6) br.spnt.few frametable_fault + ;; + mov cr.itir=r25 + ssm psr.dt // switch to using virtual data addressing + tbit.z p6,p7=r24,_PAGE_P_BIT // pte present? + ;; +(p7) itc.d r24 // install updated PTE +(p6) br.spnt.few frametable_fault // page present bit cleared? + ;; + mov pr=r31,-1 // restore predicate registers + rfi +END(frametable_miss) +ENTRY(frametable_fault) + ssm psr.dt // switch to using virtual data addressing + mov r18=cr.iip + movl r19=ia64_frametable_probe + ;; + cmp.eq p6,p7=r18,r19 // is faulting addrress ia64_frametable_probe? + mov r8=0 // assumes that 'probe.r' uses r8 + dep r21=-1,r21,IA64_PSR_RI_BIT+1,1 // return to next instrucition in bundle 2 + ;; +(p6) mov cr.ipsr=r21 + mov r19=4 // FAULT(4) +(p7) br.spnt.few dispatch_to_fault_handler + ;; + mov pr=r31,-1 + rfi +END(frametable_fault) +GLOBAL_ENTRY(ia64_frametable_probe) + probe.r r8=r32,0 // destination register must be r8 + nop.f 0x0 + br.ret.sptk.many b0 // this instruction must be in bundle 2 +END(ia64_frametable_probe) +#endif /* CONFIG_VIRTUAL_FRAME_TABLE */ .org ia64_ivt+0x1400 ///////////////////////////////////////////////////////////////////////////////////////// diff -r 042b695ffc69 -r f6e8c269f6af xen/arch/ia64/xen/xenmem.c --- a/xen/arch/ia64/xen/xenmem.c Fri Apr 14 14:24:09 2006 -0600 +++ b/xen/arch/ia64/xen/xenmem.c Mon Apr 17 08:46:04 2006 -0600 @@ -13,28 +13,41 @@ #include <asm/pgtable.h> #include <xen/mm.h> +#ifdef CONFIG_VIRTUAL_FRAME_TABLE +#include <linux/efi.h> +#include <asm/pgalloc.h> + +extern pgd_t frametable_pg_dir[]; + +#define frametable_pgd_offset(addr) \ + (frametable_pg_dir + (((addr) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))) + +static unsigned long table_size; +static int opt_contig_mem = 0; +boolean_param("contig_mem", opt_contig_mem); +#else +#define opt_contig_mem 1 +#endif + struct page_info *frame_table; -unsigned long frame_table_size; unsigned long max_page; - -struct page_info *mem_map; -#define MAX_DMA_ADDRESS ~0UL // FIXME??? - -#ifdef CONFIG_VIRTUAL_MEM_MAP -static unsigned long num_dma_physpages; -#endif /* * Set up the page tables. */ unsigned long *mpt_table; -unsigned long mpt_table_size; void paging_init (void) { unsigned int mpt_order; + unsigned long mpt_table_size; unsigned long i; + + if (!opt_contig_mem) { + /* mpt_table is already allocated at this point. */ + return; + } /* Create machine to physical mapping table * NOTE: similar to frame table, later we may need virtually @@ -57,14 +70,165 @@ paging_init (void) } } +#ifdef CONFIG_VIRTUAL_FRAME_TABLE + +static inline void * +alloc_dir_page(void) +{ + unsigned long mfn = alloc_boot_pages(1, 1); + unsigned long dir; + if (!mfn) + panic("Not enough memory for virtual frame table!\n"); + ++table_size; + dir = mfn << PAGE_SHIFT; + memset(__va(dir), 0, PAGE_SIZE); + return (void *)dir; +} + +static inline unsigned long +alloc_table_page(unsigned long fill) +{ + unsigned long mfn = alloc_boot_pages(1, 1); + unsigned long *table; + unsigned long i; + if (!mfn) + panic("Not enough memory for virtual frame table!\n"); + ++table_size; + table = (unsigned long *)__va((mfn << PAGE_SHIFT)); + for (i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) + table[i] = fill; + return mfn; +} + +int +create_frametable_page_table (u64 start, u64 end, void *arg) +{ + unsigned long address, start_page, end_page; + struct page_info *map_start, *map_end; + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + pte_t *pte; + + map_start = frame_table + (__pa(start) >> PAGE_SHIFT); + map_end = frame_table + (__pa(end) >> PAGE_SHIFT); + + start_page = (unsigned long) map_start & PAGE_MASK; + end_page = PAGE_ALIGN((unsigned long) map_end); + + for (address = start_page; address < end_page; address += PAGE_SIZE) { + pgd = frametable_pgd_offset(address); + if (pgd_none(*pgd)) + pgd_populate(NULL, pgd, alloc_dir_page()); + pud = pud_offset(pgd, address); + + if (pud_none(*pud)) + pud_populate(NULL, pud, alloc_dir_page()); + pmd = pmd_offset(pud, address); + + if (pmd_none(*pmd)) + pmd_populate_kernel(NULL, pmd, alloc_dir_page()); + pte = pte_offset_kernel(pmd, address); + + if (pte_none(*pte)) + set_pte(pte, pfn_pte(alloc_table_page(0), PAGE_KERNEL)); + } + return 0; +} + +int +create_mpttable_page_table (u64 start, u64 end, void *arg) +{ + unsigned long address, start_page, end_page; + unsigned long *map_start, *map_end; + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + pte_t *pte; + + map_start = mpt_table + (__pa(start) >> PAGE_SHIFT); + map_end = mpt_table + (__pa(end) >> PAGE_SHIFT); + + start_page = (unsigned long) map_start & PAGE_MASK; + end_page = PAGE_ALIGN((unsigned long) map_end); + + for (address = start_page; address < end_page; address += PAGE_SIZE) { + pgd = frametable_pgd_offset(address); + if (pgd_none(*pgd)) + pgd_populate(NULL, pgd, alloc_dir_page()); + pud = pud_offset(pgd, address); + + if (pud_none(*pud)) + pud_populate(NULL, pud, alloc_dir_page()); + pmd = pmd_offset(pud, address); + + if (pmd_none(*pmd)) + pmd_populate_kernel(NULL, pmd, alloc_dir_page()); + pte = pte_offset_kernel(pmd, address); + + if (pte_none(*pte)) + set_pte(pte, pfn_pte(alloc_table_page(INVALID_M2P_ENTRY), PAGE_KERNEL)); + } + return 0; +} + +void init_virtual_frametable(void) +{ + /* Allocate virtual frame_table */ + frame_table = (struct page_info *) VIRT_FRAME_TABLE_ADDR; + table_size = 0; + efi_memmap_walk(create_frametable_page_table, NULL); + + printk("size of virtual frame_table: %lukB\n", + ((table_size << PAGE_SHIFT) >> 10)); + + /* Allocate virtual mpt_table */ + table_size = 0; + mpt_table = (unsigned long *)VIRT_FRAME_TABLE_END - max_page; + efi_memmap_walk(create_mpttable_page_table, NULL); + + printk("virtual machine to physical table: %p size: %lukB\n" + "max_page: 0x%lx\n", + mpt_table, ((table_size << PAGE_SHIFT) >> 10), max_page); +} + +int +ia64_mfn_valid (unsigned long pfn) +{ + extern long ia64_frametable_probe(unsigned long); + struct page_info *pg; + int valid; + + if (opt_contig_mem) + return 1; + pg = mfn_to_page(pfn); + valid = ia64_frametable_probe((unsigned long)pg); + /* more check the whole struct of page_info */ + if (valid) + valid = ia64_frametable_probe((unsigned long)(pg+1)-1); + return valid; +} + +EXPORT_SYMBOL(ia64_mfn_valid); + +#endif /* CONFIG_VIRTUAL_FRAME_TABLE */ + /* FIXME: postpone support to machines with big holes between physical memorys. * Current hack allows only efi memdesc upto 4G place. (See efi.c) */ -#ifndef CONFIG_VIRTUAL_MEM_MAP #define FT_ALIGN_SIZE (16UL << 20) void __init init_frametable(void) { unsigned long pfn; + unsigned long frame_table_size; + +#ifdef CONFIG_VIRTUAL_FRAME_TABLE + if (!opt_contig_mem) { + init_virtual_frametable(); + return; + } +#endif + frame_table_size = max_page * sizeof(struct page_info); frame_table_size = (frame_table_size + PAGE_SIZE - 1) & PAGE_MASK; @@ -80,4 +244,3 @@ void __init init_frametable(void) printk("size of frame_table: %lukB\n", frame_table_size >> 10); } -#endif diff -r 042b695ffc69 -r f6e8c269f6af xen/include/asm-ia64/config.h --- a/xen/include/asm-ia64/config.h Fri Apr 14 14:24:09 2006 -0600 +++ b/xen/include/asm-ia64/config.h Mon Apr 17 08:46:04 2006 -0600 @@ -17,6 +17,9 @@ // needed by include/asm-ia64/page.h #define CONFIG_IA64_PAGE_SIZE_16KB // 4KB doesn't work?!? #define CONFIG_IA64_GRANULE_16MB + +// this needs to be on to run on system with large memory hole +#define CONFIG_VIRTUAL_FRAME_TABLE #define CONFIG_EFI_PCDP #define CONFIG_SERIAL_SGI_L1_CONSOLE @@ -262,10 +265,6 @@ extern int ht_per_core; #undef CONFIG_X86_IO_APIC #undef CONFIG_X86_L1_CACHE_SHIFT -// this needs to be on to run on hp zx1 with more than 4GB -// it is hacked around for now though -//#define CONFIG_VIRTUAL_MEM_MAP - //#ifndef CONFIG_IA64_HP_SIM // looks like this is hard to turn off for Xen #define CONFIG_ACPI 1 diff -r 042b695ffc69 -r f6e8c269f6af xen/include/asm-ia64/xenpage.h --- a/xen/include/asm-ia64/xenpage.h Fri Apr 14 14:24:09 2006 -0600 +++ b/xen/include/asm-ia64/xenpage.h Mon Apr 17 08:46:04 2006 -0600 @@ -8,7 +8,15 @@ #undef mfn_valid #undef page_to_mfn #undef mfn_to_page +#ifdef CONFIG_VIRTUAL_FRAME_TABLE +#undef ia64_mfn_valid +#ifndef __ASSEMBLY__ +extern int ia64_mfn_valid (unsigned long pfn); +#endif +# define mfn_valid(_pfn) (((_pfn) < max_page) && ia64_mfn_valid(_pfn)) +#else # define mfn_valid(_pfn) ((_pfn) < max_page) +#endif # define page_to_mfn(_page) ((unsigned long) ((_page) - frame_table)) # define mfn_to_page(_pfn) (frame_table + (_pfn)) diff -r 042b695ffc69 -r f6e8c269f6af xen/include/asm-ia64/xensystem.h --- a/xen/include/asm-ia64/xensystem.h Fri Apr 14 14:24:09 2006 -0600 +++ b/xen/include/asm-ia64/xensystem.h Mon Apr 17 08:46:04 2006 -0600 @@ -27,6 +27,10 @@ #define PERCPU_ADDR (SHAREDINFO_ADDR - PERCPU_PAGE_SIZE) #define XSI_OFS (SHARED_ARCHINFO_ADDR - SHAREDINFO_ADDR) #define VHPT_ADDR 0xf200000000000000 +#ifdef CONFIG_VIRTUAL_FRAME_TABLE +#define VIRT_FRAME_TABLE_ADDR 0xf300000000000000 +#define VIRT_FRAME_TABLE_END 0xf400000000000000 +#endif #define XEN_END_ADDR 0xf400000000000000 #ifndef __ASSEMBLY__ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |