svn commit: r219626 - projects/altix/sys/boot/ia64/common

Marcel Moolenaar marcel at FreeBSD.org
Sun Mar 13 22:04:20 UTC 2011


Author: marcel
Date: Sun Mar 13 22:04:19 2011
New Revision: 219626
URL: http://svn.freebsd.org/changeset/base/219626

Log:
  o   Make sure the page table has a size that is mappable. Certain page
      sizes are not supported.
  o   Map the PBVM page table.
  o   Map the PBVM using the largest possible power of 2 that is less than
      the amount of PBVM used and round down to a valid page size. Note
      that the current kernel is between 8MB and 16MB in size, which would
      mean that 8MB would be the typical size of the mapping, if only 8MB
      wasn't an invalid page size. In practice, we end up mapping the first
      4MB of PBVM in most cases.

Modified:
  projects/altix/sys/boot/ia64/common/copy.c
  projects/altix/sys/boot/ia64/common/exec.c

Modified: projects/altix/sys/boot/ia64/common/copy.c
==============================================================================
--- projects/altix/sys/boot/ia64/common/copy.c	Sun Mar 13 21:51:47 2011	(r219625)
+++ projects/altix/sys/boot/ia64/common/copy.c	Sun Mar 13 22:04:19 2011	(r219626)
@@ -43,6 +43,8 @@ pgtbl_extend(u_int idx)
 	u_int pot;
 
 	pgtblsz = (idx + 1) << 3;
+
+	/* The minimum size is 4KB. */
 	if (pgtblsz < 4096)
 		pgtblsz = 4096;
 
@@ -52,6 +54,14 @@ pgtbl_extend(u_int idx)
 		pgtblsz = pgtblsz | (pgtblsz >> pot);
 	pgtblsz++;
 
+	/* The maximum size is 1MB. */
+	if (pgtblsz > 1048576)
+		return (ENOMEM);
+
+	/* Make sure the size is a valid (mappable) page size. */
+	if (pgtblsz == 32*1024 || pgtblsz == 128*1024 || pgtblsz == 512*1024)
+		pgtblsz <<= 1;
+
 	/* Allocate naturally aligned memory. */
 	pgtbl = (void *)ia64_platform_alloc(0, pgtblsz);
 	if (pgtbl == NULL)

Modified: projects/altix/sys/boot/ia64/common/exec.c
==============================================================================
--- projects/altix/sys/boot/ia64/common/exec.c	Sun Mar 13 21:51:47 2011	(r219625)
+++ projects/altix/sys/boot/ia64/common/exec.c	Sun Mar 13 22:04:19 2011	(r219626)
@@ -85,9 +85,52 @@ enter_kernel(uint64_t start, struct boot
 }
 
 static void
-mmu_setup_legacy(uint64_t entry)
+mmu_wire(vm_offset_t va, vm_paddr_t pa, u_int sz, u_int acc)
 {
+	static u_int iidx = 0, didx = 0;
 	pt_entry_t pte;
+	u_int shft;
+
+	/* Round up to the smallest possible page size. */
+	if (sz < 4096)
+		sz = 4096;
+	/* Determine the exponent (base 2). */
+	shft = 0;
+	while (sz > 1) {
+		shft++;
+		sz >>= 1;
+	}
+	/* Truncate to the largest possible page size (256MB). */
+	if (shft > 28)
+		shft = 28;
+	/* Round down to a valid (mappable) page size. */
+	if (shft > 14 && (shft & 1) != 0)
+		shft--;
+
+	pte = PTE_PRESENT | PTE_MA_WB | PTE_ACCESSED | PTE_DIRTY |
+	    PTE_PL_KERN | (acc & PTE_AR_MASK) | (pa & PTE_PPN_MASK);
+
+	__asm __volatile("mov cr.ifa=%0" :: "r"(va));
+	__asm __volatile("mov cr.itir=%0" :: "r"(shft << 2));
+	__asm __volatile("srlz.d;;");
+	__asm __volatile("ptr.d %0,%1" :: "r"(va), "r"(shft << 2));
+	__asm __volatile("srlz.d;;");
+	__asm __volatile("itr.d dtr[%0]=%1" :: "r"(didx), "r"(pte));
+	__asm __volatile("srlz.d;;");
+	didx++;
+
+	if (acc == PTE_AR_RWX) {
+		__asm __volatile("ptr.i %0,%1;;" :: "r"(va), "r"(shft << 2));
+		__asm __volatile("srlz.i;;");
+		__asm __volatile("itr.i itr[%0]=%1;;" :: "r"(iidx), "r"(pte));
+		__asm __volatile("srlz.i;;");
+		iidx++;
+	}
+}
+
+static void
+mmu_setup_legacy(uint64_t entry)
+{
 
 	/*
 	 * Region 6 is direct mapped UC and region 7 is direct mapped
@@ -99,53 +142,28 @@ mmu_setup_legacy(uint64_t entry)
 	ia64_set_rr(IA64_RR_BASE(7), (7 << 8) | (28 << 2));
 	__asm __volatile("srlz.i;;");
 
-	pte = PTE_PRESENT | PTE_MA_WB | PTE_ACCESSED | PTE_DIRTY |
-	    PTE_PL_KERN | PTE_AR_RWX | PTE_ED;
-	pte |= IA64_RR_MASK(entry) & PTE_PPN_MASK;
-
-	__asm __volatile("mov cr.ifa=%0" :: "r"(entry));
-	__asm __volatile("mov cr.itir=%0" :: "r"(28 << 2));
-	__asm __volatile("ptr.i %0,%1" :: "r"(entry), "r"(28<<2));
-	__asm __volatile("ptr.d %0,%1" :: "r"(entry), "r"(28<<2));
-	__asm __volatile("srlz.i;;");
-	__asm __volatile("itr.i itr[%0]=%1;;" :: "r"(0), "r"(pte));
-	__asm __volatile("srlz.i;;");
-	__asm __volatile("itr.d dtr[%0]=%1;;" :: "r"(0), "r"(pte));
-	__asm __volatile("srlz.i;;");
+	mmu_wire(entry, IA64_RR_MASK(entry), 1UL << 28, PTE_AR_RWX);
 }
 
 static void
-mmu_setup_paged(void)
+mmu_setup_paged(vm_offset_t pbvm_top)
 {
-	pt_entry_t pte;
 	u_int sz;
 
-	ia64_set_rr(IA64_RR_BASE(4), (4 << 8) | (IA64_PBVM_PAGE_SHIFT << 2));
+	ia64_set_rr(IA64_RR_BASE(IA64_PBVM_RR),
+	    (IA64_PBVM_RR << 8) | (IA64_PBVM_PAGE_SHIFT << 2));
 	__asm __volatile("srlz.i;;");
 
-	/*
-	 * Wire the PBVM page table.
-	 */
-
-	pte = PTE_PRESENT | PTE_MA_WB | PTE_ACCESSED | PTE_DIRTY |
-	    PTE_PL_KERN | PTE_AR_RWX | PTE_ED;
-	pte |= ia64_pgtbl[0] & PTE_PPN_MASK;
-
-	/*
-	 * Size of the translation. This should be the largest power of 2
-	 * smaller than the LVM in use.
-	 */
-	sz = 24;
-
-	__asm __volatile("mov cr.ifa=%0" :: "r"(IA64_PBVM_BASE));
-	__asm __volatile("mov cr.itir=%0" :: "r"(sz << 2));
-	__asm __volatile("ptr.i %0,%1" :: "r"(IA64_PBVM_BASE), "r"(sz << 2));
-	__asm __volatile("ptr.d %0,%1" :: "r"(IA64_PBVM_BASE), "r"(sz << 2));
-	__asm __volatile("srlz.i;;");
-	__asm __volatile("itr.i itr[%0]=%1;;" :: "r"(0), "r"(pte));
-	__asm __volatile("srlz.i;;");
-	__asm __volatile("itr.d dtr[%0]=%1;;" :: "r"(0), "r"(pte));
-	__asm __volatile("srlz.i;;");
+	/* Wire the PBVM page table. */
+	mmu_wire(IA64_PBVM_PGTBL, (uintptr_t)ia64_pgtbl, ia64_pgtblsz,
+	    PTE_AR_RW);
+
+	/* Wire as much of the PBVM we can. This must be a power of 2. */
+	pbvm_top = (pbvm_top + IA64_PBVM_PAGE_MASK) & ~IA64_PBVM_PAGE_MASK;
+	sz = pbvm_top - IA64_PBVM_BASE;
+	while (sz & (sz - 1))
+		sz -= IA64_PBVM_PAGE_SIZE;
+	mmu_wire(IA64_PBVM_BASE, ia64_pgtbl[0], sz, PTE_AR_RWX);
 }
 
 static int
@@ -177,7 +195,7 @@ elf64_exec(struct preloaded_file *fp)
 	if (IS_LEGACY_KERNEL())
 		mmu_setup_legacy(hdr->e_entry);
 	else
-		mmu_setup_paged();
+		mmu_setup_paged((uintptr_t)(bi + 1));
 
 	enter_kernel(hdr->e_entry, bi);
 	/* NOTREACHED */


More information about the svn-src-projects mailing list