Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 7 Jul 2012 05:17:43 +0000 (UTC)
From:      Marcel Moolenaar <marcel@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r238190 - in head/sys/ia64: ia64 include
Message-ID:  <201207070517.q675HhIX015900@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: marcel
Date: Sat Jul  7 05:17:43 2012
New Revision: 238190
URL: http://svn.freebsd.org/changeset/base/238190

Log:
  Implement ia64_physmem_alloc() and use it consistently to get memory
  before VM has been initialized. This includes:
  1.  Replacing pmap_steal_memory(),
  2.  Replace the handcrafted logic to allocate a naturally aligned VHPT,
  3.  Properly allocate the DPCPU for the BSP.
  
  Ad 3: Appending the DPCPU to kernend worked as long as we wouldn't
        cross into the next PBVM page. If we were to cross into the next
        page, then there wouldn't be a PTE entry on the page table for it
        and we would end up with a MCA following a page fault. As such,
        this commit fixes MCAs occasionally seen.

Modified:
  head/sys/ia64/ia64/machdep.c
  head/sys/ia64/ia64/physmem.c
  head/sys/ia64/ia64/pmap.c
  head/sys/ia64/include/md_var.h

Modified: head/sys/ia64/ia64/machdep.c
==============================================================================
--- head/sys/ia64/ia64/machdep.c	Sat Jul  7 05:02:39 2012	(r238189)
+++ head/sys/ia64/ia64/machdep.c	Sat Jul  7 05:17:43 2012	(r238190)
@@ -675,7 +675,6 @@ ia64_init(void)
 	struct efi_md *md;
 	pt_entry_t *pbvm_pgtbl_ent, *pbvm_pgtbl_lim;
 	char *p;
-	vm_offset_t kernend;
 	vm_size_t mdlen;
 	int metadata_missing;
 
@@ -773,20 +772,6 @@ ia64_init(void)
 		bootverbose = 1;
 
 	/*
-	 * Find the end of the kernel.
-	 */
-#ifdef DDB
-	ksym_start = bootinfo->bi_symtab;
-	ksym_end = bootinfo->bi_esymtab;
-	kernend = (vm_offset_t)round_page(ksym_end);
-#else
-	kernend = (vm_offset_t)round_page(_end);
-#endif
-	/* But if the bootstrap tells us otherwise, believe it! */
-	if (bootinfo->bi_kernend)
-		kernend = round_page(bootinfo->bi_kernend);
-
-	/*
 	 * Wire things up so we can call the firmware.
 	 */
 	map_pal_code();
@@ -805,9 +790,8 @@ ia64_init(void)
 	pcpup = &pcpu0;
 	ia64_set_k4((u_int64_t)pcpup);
 	pcpu_init(pcpup, 0, sizeof(pcpu0));
-	dpcpu_init((void *)kernend, 0);
+	dpcpu_init(ia64_physmem_alloc(DPCPU_SIZE, PAGE_SIZE), 0);
 	PCPU_SET(md.lid, ia64_get_lid());
-	kernend += DPCPU_SIZE;
 	PCPU_SET(curthread, &thread0);
 
 	/*
@@ -838,14 +822,15 @@ ia64_init(void)
 	/*
 	 * Initialize error message buffer (at end of core).
 	 */
-	msgbufp = (struct msgbuf *)pmap_steal_memory(msgbufsize);
+	msgbufp = ia64_physmem_alloc(msgbufsize, PAGE_SIZE);
 	msgbufinit(msgbufp, msgbufsize);
 
 	proc_linkup0(&proc0, &thread0);
 	/*
 	 * Init mapping for kernel stack for proc 0
 	 */
-	thread0.td_kstack = pmap_steal_memory(KSTACK_PAGES * PAGE_SIZE);
+	p = ia64_physmem_alloc(KSTACK_PAGES * PAGE_SIZE, PAGE_SIZE);
+	thread0.td_kstack = (uintptr_t)p;
 	thread0.td_kstack_pages = KSTACK_PAGES;
 
 	mutex_init();
@@ -871,6 +856,11 @@ ia64_init(void)
 	/*
 	 * Initialize debuggers, and break into them if appropriate.
 	 */
+#ifdef DDB
+	ksym_start = bootinfo->bi_symtab;
+	ksym_end = bootinfo->bi_esymtab;
+#endif
+
 	kdb_init();
 
 #ifdef KDB

Modified: head/sys/ia64/ia64/physmem.c
==============================================================================
--- head/sys/ia64/ia64/physmem.c	Sat Jul  7 05:02:39 2012	(r238189)
+++ head/sys/ia64/ia64/physmem.c	Sat Jul  7 05:17:43 2012	(r238190)
@@ -187,9 +187,72 @@ ia64_physmem_track(vm_paddr_t base, vm_s
 	return (0);
 }
 
-vm_paddr_t
+void *
 ia64_physmem_alloc(vm_size_t len, vm_size_t align)
 {
+	vm_paddr_t base, lim, pa;
+	void *ptr;
+	u_int idx;
 
-	return (0);
+	if (phys_avail_segs == 0)
+		return (NULL);
+
+	len = round_page(len);
+
+	/*
+	 * Try and allocate with least effort.
+	 */
+	idx = phys_avail_segs * 2;
+	while (idx > 0) {
+		idx -= 2;
+		base = phys_avail[idx];
+		lim = phys_avail[idx + 1];
+
+		if (lim - base < len)
+			continue;
+
+		/* First try from the end. */
+		pa = lim - len;
+		if ((pa & (align - 1)) == 0) {
+			if (pa == base)
+				ia64_physmem_remove(idx);
+			else
+				phys_avail[idx + 1] = pa;
+			goto gotit;
+		}
+
+		/* Try from the start next. */
+		pa = base;
+		if ((pa & (align - 1)) == 0) {
+			if (pa + len == lim)
+				ia64_physmem_remove(idx);
+			else
+				phys_avail[idx] += len;
+			goto gotit;
+		}
+	}
+
+	/*
+	 * Find a good segment and split it up.
+	 */
+	idx = phys_avail_segs * 2;
+	while (idx > 0) {
+		idx -= 2;
+		base = phys_avail[idx];
+		lim = phys_avail[idx + 1];
+
+		pa = (base + align - 1) & ~(align - 1);
+		if (pa + len <= lim) {
+			ia64_physmem_delete(pa, len);
+			goto gotit;
+		}
+	}
+
+	/* Out of luck. */
+	return (NULL);
+
+ gotit:
+	ptr = (void *)IA64_PHYS_TO_RR7(pa);
+	bzero(ptr, len);
+	return (ptr);
 }

Modified: head/sys/ia64/ia64/pmap.c
==============================================================================
--- head/sys/ia64/ia64/pmap.c	Sat Jul  7 05:02:39 2012	(r238189)
+++ head/sys/ia64/ia64/pmap.c	Sat Jul  7 05:17:43 2012	(r238190)
@@ -243,36 +243,6 @@ static int	pmap_remove_vhpt(vm_offset_t 
 static boolean_t pmap_try_insert_pv_entry(pmap_t pmap, vm_offset_t va,
 		    vm_page_t m);
 
-vm_offset_t
-pmap_steal_memory(vm_size_t size)
-{
-	vm_size_t bank_size;
-	vm_offset_t pa, va;
-
-	size = round_page(size);
-
-	bank_size = phys_avail[1] - phys_avail[0];
-	while (size > bank_size) {
-		int i;
-		for (i = 0; phys_avail[i+2]; i+= 2) {
-			phys_avail[i] = phys_avail[i+2];
-			phys_avail[i+1] = phys_avail[i+3];
-		}
-		phys_avail[i] = 0;
-		phys_avail[i+1] = 0;
-		if (!phys_avail[0])
-			panic("pmap_steal_memory: out of memory");
-		bank_size = phys_avail[1] - phys_avail[0];
-	}
-
-	pa = phys_avail[0];
-	phys_avail[0] += size;
-
-	va = IA64_PHYS_TO_RR7(pa);
-	bzero((caddr_t) va, size);
-	return va;
-}
-
 static void
 pmap_initialize_vhpt(vm_offset_t vhpt)
 {
@@ -318,7 +288,7 @@ pmap_bootstrap()
 	struct ia64_pal_result res;
 	vm_offset_t base;
 	size_t size;
-	int i, j, count, ridbits;
+	int i, ridbits;
 
 	/*
 	 * Query the PAL Code to find the loop parameters for the
@@ -380,7 +350,7 @@ pmap_bootstrap()
 
 	pmap_ridmax = (1 << ridbits);
 	pmap_ridmapsz = pmap_ridmax / 64;
-	pmap_ridmap = (uint64_t *)pmap_steal_memory(pmap_ridmax / 8);
+	pmap_ridmap = ia64_physmem_alloc(pmap_ridmax / 8, PAGE_SIZE);
 	pmap_ridmap[0] |= 0xff;
 	pmap_rididx = 0;
 	pmap_ridcount = 8;
@@ -389,14 +359,10 @@ pmap_bootstrap()
 	/*
 	 * Allocate some memory for initial kernel 'page tables'.
 	 */
-	ia64_kptdir = (void *)pmap_steal_memory(PAGE_SIZE);
+	ia64_kptdir = ia64_physmem_alloc(PAGE_SIZE, PAGE_SIZE);
 	nkpt = 0;
 	kernel_vm_end = VM_MIN_KERNEL_ADDRESS;
 
-	for (i = 0; phys_avail[i+2]; i+= 2)
-		;
-	count = i+2;
-
 	/*
 	 * Determine a valid (mappable) VHPT size.
 	 */
@@ -410,35 +376,18 @@ pmap_bootstrap()
 	if (pmap_vhpt_log2size & 1)
 		pmap_vhpt_log2size--;
 
-	base = 0;
 	size = 1UL << pmap_vhpt_log2size;
-	for (i = 0; i < count; i += 2) {
-		base = (phys_avail[i] + size - 1) & ~(size - 1);
-		if (base + size <= phys_avail[i+1])
-			break;
-	}
-	if (!phys_avail[i])
+	base = (uintptr_t)ia64_physmem_alloc(size, size);
+	if (base == 0)
 		panic("Unable to allocate VHPT");
 
-	if (base != phys_avail[i]) {
-		/* Split this region. */
-		for (j = count; j > i; j -= 2) {
-			phys_avail[j] = phys_avail[j-2];
-			phys_avail[j+1] = phys_avail[j-2+1];
-		}
-		phys_avail[i+1] = base;
-		phys_avail[i+2] = base + size;
-	} else
-		phys_avail[i] = base + size;
-
-	base = IA64_PHYS_TO_RR7(base);
 	PCPU_SET(md.vhpt, base);
 	if (bootverbose)
 		printf("VHPT: address=%#lx, size=%#lx\n", base, size);
 
 	pmap_vhpt_nbuckets = size / sizeof(struct ia64_lpte);
-	pmap_vhpt_bucket = (void *)pmap_steal_memory(pmap_vhpt_nbuckets *
-	    sizeof(struct ia64_bucket));
+	pmap_vhpt_bucket = ia64_physmem_alloc(pmap_vhpt_nbuckets *
+	    sizeof(struct ia64_bucket), PAGE_SIZE);
 	for (i = 0; i < pmap_vhpt_nbuckets; i++) {
 		/* Stolen memory is zeroed. */
 		mtx_init(&pmap_vhpt_bucket[i].mutex, "VHPT bucket lock", NULL,

Modified: head/sys/ia64/include/md_var.h
==============================================================================
--- head/sys/ia64/include/md_var.h	Sat Jul  7 05:02:39 2012	(r238189)
+++ head/sys/ia64/include/md_var.h	Sat Jul  7 05:17:43 2012	(r238190)
@@ -93,7 +93,7 @@ int	ia64_highfp_save_ipi(void);
 struct ia64_init_return ia64_init(void);
 u_int	ia64_itc_freq(void);
 int	ia64_physmem_add(vm_paddr_t, vm_size_t);
-vm_paddr_t ia64_physmem_alloc(vm_size_t, vm_size_t);
+void	*ia64_physmem_alloc(vm_size_t, vm_size_t);
 int	ia64_physmem_delete(vm_paddr_t, vm_size_t);
 int	ia64_physmem_fini(void);
 int	ia64_physmem_init(void);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201207070517.q675HhIX015900>