[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


 


Rackspace

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