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