[OpenBIOS] r344 - in openbios-devel: arch/sparc32 drivers include include/libc include/openbios include/sparc32

svn at openbios.org svn at openbios.org
Sat Jan 3 14:45:02 CET 2009


Author: blueswirl
Date: 2009-01-03 14:45:02 +0100 (Sat, 03 Jan 2009)
New Revision: 344

Added:
   openbios-devel/arch/sparc32/pgtsrmmu.h
Removed:
   openbios-devel/drivers/pgtsrmmu.h
Modified:
   openbios-devel/arch/sparc32/boot.c
   openbios-devel/arch/sparc32/boot.h
   openbios-devel/arch/sparc32/console.c
   openbios-devel/arch/sparc32/lib.c
   openbios-devel/arch/sparc32/openbios.c
   openbios-devel/arch/sparc32/romvec.c
   openbios-devel/drivers/esp.c
   openbios-devel/drivers/iommu.c
   openbios-devel/drivers/iommu.h
   openbios-devel/drivers/obio.c
   openbios-devel/drivers/obio.h
   openbios-devel/drivers/sbus.c
   openbios-devel/include/libc/stdlib.h
   openbios-devel/include/ofmem.h
   openbios-devel/include/openbios/drivers.h
   openbios-devel/include/sparc32/io.h
Log:
Clean up Sparc32 memory management

Concentrate memory and MMU management (lib.c malloc, romvec opb_, iommu,
OF /memory) to lib.c.



Modified: openbios-devel/arch/sparc32/boot.c
===================================================================
--- openbios-devel/arch/sparc32/boot.c	2009-01-02 14:53:33 UTC (rev 343)
+++ openbios-devel/arch/sparc32/boot.c	2009-01-03 13:45:02 UTC (rev 344)
@@ -99,7 +99,7 @@
             obp_arg.argv[1] = param;
         }
 
-        romvec = init_openprom(qemu_mem_size);
+        romvec = init_openprom();
 
         if (kernel_size) {
             int (*entry)(const void *romvec_ptr, int p2, int p3, int p4, int p5);

Modified: openbios-devel/arch/sparc32/boot.h
===================================================================
--- openbios-devel/arch/sparc32/boot.h	2009-01-02 14:53:33 UTC (rev 343)
+++ openbios-devel/arch/sparc32/boot.h	2009-01-03 13:45:02 UTC (rev 344)
@@ -24,7 +24,7 @@
 unsigned int start_elf(unsigned long entry_point, unsigned long param);
 
 // romvec.c
-void *init_openprom(unsigned long memsize);
+void *init_openprom(void);
 
 // boot.c
 extern struct sys_info sys_info;
@@ -39,3 +39,19 @@
 
 // openbios.c
 extern int qemu_machine_type;
+
+// arch/sparc32/lib.c
+struct linux_mlist_v0;
+extern struct linux_mlist_v0 *ptphys;
+extern struct linux_mlist_v0 *ptmap;
+extern struct linux_mlist_v0 *ptavail;
+
+void ob_init_mmu(void);
+void init_mmu_swift(void);
+char *obp_dumb_mmap(char *va, int which_io, unsigned int pa,
+                    unsigned int size);
+void obp_dumb_munmap(__attribute__((unused)) char *va,
+                     __attribute__((unused)) unsigned int size);
+char *obp_dumb_memalloc(char *va, unsigned int size);
+void obp_dumb_memfree(__attribute__((unused))char *va,
+                      __attribute__((unused))unsigned sz);

Modified: openbios-devel/arch/sparc32/console.c
===================================================================
--- openbios-devel/arch/sparc32/console.c	2009-01-02 14:53:33 UTC (rev 343)
+++ openbios-devel/arch/sparc32/console.c	2009-01-03 13:45:02 UTC (rev 344)
@@ -10,6 +10,7 @@
 #include "openbios/drivers.h"
 #include "openbios.h"
 #include "video_subr.h"
+#include "ofmem.h"
 
 #ifdef CONFIG_DEBUG_CONSOLE
 

Modified: openbios-devel/arch/sparc32/lib.c
===================================================================
--- openbios-devel/arch/sparc32/lib.c	2009-01-02 14:53:33 UTC (rev 343)
+++ openbios-devel/arch/sparc32/lib.c	2009-01-03 13:45:02 UTC (rev 344)
@@ -7,13 +7,25 @@
  * the copyright and warranty status of this work.
  */
 
-#include "openbios/config.h"
-#include "asm/types.h"
-#include <stdarg.h>
-#include "libc/stdlib.h"
 #include "libc/vsprintf.h"
-#include "openbios/kernel.h"
+#include "openbios/bindings.h"
+#include "ofmem.h"
+#include "asm/asi.h"
+#include "pgtsrmmu.h"
+#include "openprom.h"
+#include "sys_info.h"
+#include "boot.h"
 
+#define NCTX_SWIFT  0x100
+#define LOWMEMSZ 32 * 1024 * 1024
+
+#ifdef CONFIG_DEBUG_MEM
+#define DPRINTF(fmt, args...)                   \
+    do { printk(fmt , ##args); } while (0)
+#else
+#define DPRINTF(fmt, args...)
+#endif
+
 /* Format a string and print it on the screen, just like the libc
  * function printf.
  */
@@ -32,6 +44,30 @@
 	return i;
 }
 
+/*
+ * Allocatable memory chunk.
+ */
+struct mem {
+    char *start, *uplim;
+    char *curp;
+};
+
+static struct mem cmem;         /* Current memory, virtual */
+static struct mem cio;          /* Current I/O space */
+struct mem cdvmem;              /* Current device virtual memory space */
+
+unsigned int va_shift;
+static unsigned long *context_table;
+static unsigned long *l1;
+
+static struct linux_mlist_v0 totphys[1];
+static struct linux_mlist_v0 totmap[1];
+static struct linux_mlist_v0 totavail[1];
+
+struct linux_mlist_v0 *ptphys;
+struct linux_mlist_v0 *ptmap;
+struct linux_mlist_v0 *ptavail;
+
 typedef struct alloc_desc {
 	struct alloc_desc 	*next;
 	int			size;			/* size (including) this struct */
@@ -63,16 +99,17 @@
 } ofmem;
 #define ALLOC_BLOCK (64 * 1024)
 
-void *malloc(int size)
+// XXX should be posix_memalign
+static int
+posix_memalign2(void **memptr, size_t alignment, size_t size)
 {
 	alloc_desc_t *d, **pp;
 	char *ret;
-        extern struct mem cmem;
 
 	if( !size )
-		return NULL;
+                return -1;
 
-        size = (size + 7) & ~7;
+        size = (size + (alignment - 1)) & ~(alignment - 1);
 	size += sizeof(alloc_desc_t);
 
 	/* look in the freelist */
@@ -84,7 +121,8 @@
 		ret = (char*)*pp + sizeof(alloc_desc_t);
 		memset( ret, 0, (**pp).size - sizeof(alloc_desc_t) );
 		*pp = (**pp).next;
-		return ret;
+                *memptr = ret;
+                return 0;
 	}
 
 	if( !ofmem.next_malloc || ofmem.left < size) {
@@ -101,13 +139,13 @@
                                   sizeof(alloc_desc_t)));
                 }
 
-                ofmem.next_malloc = mem_alloc(&cmem, alloc_size, 4);
+                ofmem.next_malloc = mem_alloc(&cmem, alloc_size, 8);
                 ofmem.left = alloc_size;
         }
 
 	if( ofmem.left < size) {
 		printk("out of malloc memory (%x)!\n", size );
-		return NULL;
+                return -1;
 	}
 	d = (alloc_desc_t*) ofmem.next_malloc;
 	ofmem.next_malloc += size;
@@ -118,9 +156,21 @@
 
 	ret = (char*)d + sizeof(alloc_desc_t);
 	memset( ret, 0, size - sizeof(alloc_desc_t) );
-	return ret;
+        *memptr = ret;
+        return 0;
 }
 
+void *malloc(int size)
+{
+    int ret;
+    void *mem;
+
+    ret = posix_memalign2(&mem, 8, size);
+    if (ret != 0)
+        return NULL;
+    return mem;
+}
+
 void free(void *ptr)
 {
 	alloc_desc_t **pp, *d;
@@ -156,3 +206,406 @@
 	free( ptr );
 	return p;
 }
+
+// XXX should be removed
+int
+posix_memalign(void **memptr, size_t alignment, size_t size)
+{
+    void *block;
+
+    block = mem_alloc(&cmem, size, alignment);
+
+    if (!block)
+        return -1;
+
+    *memptr = block;
+    return 0;
+}
+
+/*
+ * Allocate memory. This is reusable.
+ */
+void
+mem_init(struct mem *t, char *begin, char *limit)
+{
+    t->start = begin;
+    t->uplim = limit;
+    t->curp = begin;
+}
+
+void *
+mem_alloc(struct mem *t, int size, int align)
+{
+    char *p;
+    unsigned long pa;
+
+    // The alignment restrictions refer to physical, not virtual
+    // addresses
+    pa = va2pa((unsigned long)t->curp) + (align - 1);
+    pa &= ~(align - 1);
+    p = (char *)pa2va(pa);
+
+    if ((unsigned long)p >= (unsigned long)t->uplim ||
+        (unsigned long)p + size > (unsigned long)t->uplim)
+        return NULL;
+    t->curp = p + size;
+
+    return p;
+}
+
+static unsigned long
+find_pte(unsigned long va, int alloc)
+{
+    uint32_t pte;
+    void *p;
+    unsigned long pa;
+    int ret;
+
+    pte = l1[(va >> SRMMU_PGDIR_SHIFT) & (SRMMU_PTRS_PER_PGD - 1)];
+    if ((pte & SRMMU_ET_MASK) == SRMMU_ET_INVALID) {
+        if (alloc) {
+            ret = posix_memalign(&p, SRMMU_PTRS_PER_PMD * sizeof(int),
+                                 SRMMU_PTRS_PER_PMD * sizeof(int));
+            if (ret != 0)
+                return ret;
+            pte = SRMMU_ET_PTD | ((va2pa((unsigned long)p)) >> 4);
+            l1[(va >> SRMMU_PGDIR_SHIFT) & (SRMMU_PTRS_PER_PGD - 1)] = pte;
+            /* barrier() */
+        } else {
+            return -1;
+        }
+    }
+
+    pa = (pte & 0xFFFFFFF0) << 4;
+    pa += ((va >> SRMMU_PMD_SHIFT) & (SRMMU_PTRS_PER_PMD - 1)) << 2;
+    pte = *(uint32_t *)pa2va(pa);
+    if ((pte & SRMMU_ET_MASK) == SRMMU_ET_INVALID) {
+        if (alloc) {
+            ret = posix_memalign(&p, SRMMU_PTRS_PER_PTE * sizeof(void *),
+                                 SRMMU_PTRS_PER_PTE * sizeof(void *));
+            if (ret != 0)
+                return ret;
+            pte = SRMMU_ET_PTD | ((va2pa((unsigned int)p)) >> 4);
+            *(uint32_t *)pa2va(pa) = pte;
+        } else {
+            return -2;
+        }
+    }
+
+    pa = (pte & 0xFFFFFFF0) << 4;
+    pa += ((va >> PAGE_SHIFT) & (SRMMU_PTRS_PER_PTE - 1)) << 2;
+
+    return pa2va(pa);
+}
+
+/*
+ * Create a memory mapping from va to epa.
+ */
+int
+map_page(unsigned long va, uint64_t epa, int type)
+{
+    uint32_t pte;
+    unsigned long pa;
+
+    pa = find_pte(va, 1);
+
+    pte = SRMMU_ET_PTE | ((epa & PAGE_MASK) >> 4);
+    if (type) {         /* I/O */
+        pte |= SRMMU_REF;
+        /* SRMMU cannot make Supervisor-only, but not exectutable */
+        pte |= SRMMU_PRIV;
+    } else {            /* memory */
+        pte |= SRMMU_REF | SRMMU_CACHE;
+        pte |= SRMMU_PRIV; /* Supervisor only access */
+    }
+    *(uint32_t *)pa = pte;
+    DPRINTF("map_page: va 0x%lx pa 0x%llx pte 0x%x\n", va, epa, pte);
+
+    return 0;
+}
+
+static void map_pages(unsigned long va, uint64_t pa, int type,
+                      unsigned long size)
+{
+    unsigned long npages, off;
+
+    DPRINTF("map_pages: va 0x%lx, pa 0x%llx, size 0x%lx\n", va, pa, size);
+
+    off = pa & (PAGE_SIZE - 1);
+    npages = (off + (size - 1) + (PAGE_SIZE - 1)) / PAGE_SIZE;
+    pa &= ~(uint64_t)(PAGE_SIZE - 1);
+
+    while (npages-- != 0) {
+        map_page(va, pa, type);
+        va += PAGE_SIZE;
+        pa += PAGE_SIZE;
+    }
+}
+/*
+ * Create an I/O mapping to pa[size].
+ * Returns va of the mapping or 0 if unsuccessful.
+ */
+void *
+map_io(uint64_t pa, int size)
+{
+    unsigned long va;
+    unsigned int npages;
+    unsigned int off;
+
+    off = pa & (PAGE_SIZE - 1);
+    npages = (off + size - 1) / PAGE_SIZE + 1;
+    pa &= ~(PAGE_SIZE - 1);
+
+    va = (unsigned long)mem_alloc(&cio, npages * PAGE_SIZE, PAGE_SIZE);
+    if (va == 0)
+        return NULL;
+
+    map_pages(va, pa, 1, npages * PAGE_SIZE);
+    return (void *)(va + off);
+}
+
+/*
+ * D5.3 pgmap@ ( va -- pte )
+ */
+static void
+pgmap_fetch(void)
+{
+    uint32_t pte;
+    unsigned long va, pa;
+
+    va = POP();
+
+    pa = find_pte(va, 0);
+    if (pa == 1 || pa == 2)
+        goto error;
+    pte = *(uint32_t *)pa;
+    DPRINTF("pgmap@: va 0x%lx pa 0x%lx pte 0x%x\n", va, pa, pte);
+
+    PUSH(pte);
+    return;
+ error:
+    PUSH(0);
+}
+
+/*
+ * D5.3 pgmap! ( pte va -- )
+ */
+static void
+pgmap_store(void)
+{
+    uint32_t pte;
+    unsigned long va, pa;
+
+    va = POP();
+    pte = POP();
+
+    pa = find_pte(va, 1);
+    *(uint32_t *)pa = pte;
+    DPRINTF("pgmap!: va 0x%lx pa 0x%lx pte 0x%x\n", va, pa, pte);
+}
+
+/*
+ * D5.3 map-pages ( pa space va size -- )
+ */
+static void
+ob_map_pages(void)
+{
+    unsigned long va;
+    int size;
+    uint64_t pa;
+
+    size = POP();
+    va = POP();
+    pa = POP();
+    pa <<= 32;
+    pa |= POP() & 0xffffffff;
+
+    map_pages(va, pa, 0, size);
+    DPRINTF("map-page: va 0x%lx pa 0x%llx size 0x%x\n", va, pa, size);
+}
+
+static void
+init_romvec_mem(void)
+{
+    ptphys = totphys;
+    ptmap = totmap;
+    ptavail = totavail;
+
+    /*
+     * Form memory descriptors.
+     */
+    totphys[0].theres_more = NULL;
+    totphys[0].start_adr = (char *) 0;
+    totphys[0].num_bytes = qemu_mem_size;
+
+    totavail[0].theres_more = NULL;
+    totavail[0].start_adr = (char *) 0;
+    totavail[0].num_bytes = va2pa((int)&_start) - PAGE_SIZE;
+
+    totmap[0].theres_more = NULL;
+    totmap[0].start_adr = &_start;
+    totmap[0].num_bytes = (unsigned long) &_iomem -
+        (unsigned long) &_start + PAGE_SIZE;
+}
+
+char *obp_dumb_mmap(char *va, int which_io, unsigned int pa,
+                    unsigned int size)
+{
+    uint64_t mpa = ((uint64_t)which_io << 32) | (uint64_t)pa;
+
+    map_pages((unsigned long)va, mpa, 0, size);
+    return va;
+}
+
+void obp_dumb_munmap(__attribute__((unused)) char *va,
+                     __attribute__((unused)) unsigned int size)
+{
+    DPRINTF("obp_dumb_munmap: virta 0x%x, sz %d\n", (unsigned int)va, size);
+}
+
+char *obp_dumb_memalloc(char *va, unsigned int size)
+{
+    static unsigned int next_free_address = 0xFFEDA000;
+
+    size = (size + 7) & ~7;
+    // XXX should use normal memory alloc
+    totmap[0].num_bytes -= size;
+    DPRINTF("obp_dumb_memalloc va 0x%p size %x at 0x%x\n", va, size,
+            totmap[0].num_bytes);
+
+    // If va is null, the allocator is supposed to pick a "suitable" address.
+    // (See OpenSolaric prom_alloc.c)  There's not any real guidance as
+    // to what might be "suitable".  So we mimic the behavior of a Sun boot
+    // ROM.
+
+    if (va == NULL) {
+        // XXX should register virtual memory allocation
+        va = (char *)(next_free_address - size);
+        next_free_address -= size;
+        DPRINTF("obp_dumb_memalloc req null -> 0x%p\n", va);
+    }
+
+    map_pages((unsigned long)va, totmap[0].num_bytes, 0, size);
+
+    return va;
+}
+
+void obp_dumb_memfree(__attribute__((unused))char *va,
+                             __attribute__((unused))unsigned sz)
+{
+    DPRINTF("obp_dumb_memfree 0x%p (size %d)\n", va, sz);
+}
+
+void
+ob_init_mmu(void)
+{
+    push_str("/memory");
+    fword("find-device");
+
+    PUSH(0);
+    fword("encode-int");
+    PUSH(0);
+    fword("encode-int");
+    fword("encode+");
+    PUSH(qemu_mem_size);
+    fword("encode-int");
+    fword("encode+");
+    push_str("reg");
+    fword("property");
+
+    PUSH(0);
+    fword("encode-int");
+    PUSH(0);
+    fword("encode-int");
+    fword("encode+");
+    PUSH(va2pa((unsigned long)&_start) - PAGE_SIZE);
+    fword("encode-int");
+    fword("encode+");
+    push_str("available");
+    fword("property");
+
+    push_str("/virtual-memory");
+    fword("find-device");
+
+    PUSH(0);
+    fword("encode-int");
+    PUSH(0);
+    fword("encode-int");
+    fword("encode+");
+    PUSH((unsigned long)&_start - PAGE_SIZE);
+    fword("encode-int");
+    fword("encode+");
+
+    PUSH(0);
+    fword("encode-int");
+    fword("encode+");
+    PUSH(va2pa((unsigned long)&_iomem));
+    fword("encode-int");
+    fword("encode+");
+    PUSH(-va2pa((unsigned long)&_iomem));
+    fword("encode-int");
+    fword("encode+");
+    push_str("available");
+    fword("property");
+
+    PUSH(0);
+    fword("active-package!");
+    bind_func("pgmap@", pgmap_fetch);
+    bind_func("pgmap!", pgmap_store);
+    bind_func("map-pages", ob_map_pages);
+
+    init_romvec_mem();
+}
+
+/*
+ * Switch page tables.
+ */
+void
+init_mmu_swift(void)
+{
+    unsigned int addr, i;
+    unsigned long pa, va;
+
+    mem_init(&cmem, (char *) &_vmem, (char *)&_evmem);
+    mem_init(&cio, (char *)&_end, (char *)&_iomem);
+
+    posix_memalign((void *)&context_table, NCTX_SWIFT * sizeof(int),
+                   NCTX_SWIFT * sizeof(int));
+    posix_memalign((void *)&l1, 256 * sizeof(int), 256 * sizeof(int));
+
+    context_table[0] = (((unsigned long)va2pa((unsigned long)l1)) >> 4) |
+        SRMMU_ET_PTD;
+
+    for (i = 1; i < NCTX_SWIFT; i++) {
+        context_table[i] = SRMMU_ET_INVALID;
+    }
+    for (i = 0; i < 256; i += 4) {
+        l1[i] = SRMMU_ET_INVALID;
+    }
+
+    // text, rodata, data, and bss mapped to end of RAM
+    va = (unsigned long)&_start;
+    for (; va < (unsigned long)&_end; va += PAGE_SIZE) {
+        pa = va2pa(va);
+        map_page(va, pa, 0);
+    }
+
+    // 1:1 mapping for RAM
+    pa = va = 0;
+    for (; va < LOWMEMSZ; va += PAGE_SIZE, pa += PAGE_SIZE) {
+        map_page(va, pa, 0);
+    }
+
+    /*
+     * Flush cache
+     */
+    for (addr = 0; addr < 0x2000; addr += 0x10) {
+        __asm__ __volatile__ ("sta %%g0, [%0] %1\n\t" : :
+                              "r" (addr), "i" (ASI_M_DATAC_TAG));
+        __asm__ __volatile__ ("sta %%g0, [%0] %1\n\t" : :
+                              "r" (addr<<1), "i" (ASI_M_TXTC_TAG));
+    }
+    srmmu_set_context(0);
+    srmmu_set_ctable_ptr(va2pa((unsigned long)context_table));
+    srmmu_flush_whole_tlb();
+}

Modified: openbios-devel/arch/sparc32/openbios.c
===================================================================
--- openbios-devel/arch/sparc32/openbios.c	2009-01-02 14:53:33 UTC (rev 343)
+++ openbios-devel/arch/sparc32/openbios.c	2009-01-03 13:45:02 UTC (rev 344)
@@ -111,10 +111,9 @@
 static void
 arch_init( void )
 {
-	void setup_timers(void);
-
 	modules_init();
-        ob_init_mmu(hwdef->iommu_base);
+        ob_init_mmu();
+        ob_init_iommu(hwdef->iommu_base);
 #ifdef CONFIG_DRIVER_OBIO
 	ob_obio_init(hwdef->slavio_base, hwdef->fd_offset,
                      hwdef->counter_offset, hwdef->intr_offset,
@@ -146,9 +145,8 @@
         if (!hwdef)
             for(;;); // Internal inconsistency, hang
 
-        mem_init(&cmem, (char *) &_vmem, (char *)&_evmem);
 #ifdef CONFIG_DRIVER_SBUS
-        init_mmu_swift(hwdef->iommu_base);
+        init_mmu_swift();
 #endif
 #ifdef CONFIG_DEBUG_CONSOLE
 #ifdef CONFIG_DEBUG_CONSOLE_SERIAL

Copied: openbios-devel/arch/sparc32/pgtsrmmu.h (from rev 343, openbios-devel/drivers/pgtsrmmu.h)
===================================================================
--- openbios-devel/arch/sparc32/pgtsrmmu.h	                        (rev 0)
+++ openbios-devel/arch/sparc32/pgtsrmmu.h	2009-01-03 13:45:02 UTC (rev 344)
@@ -0,0 +1,230 @@
+/*
+ * Taken from kernel for decoupling from <asm/page.h>. --zaitcev
+ *
+ * $Id: pgtsrmmu.h,v 1.2 1999/04/19 01:04:31 zaitcev Exp $
+ * pgtsrmmu.h:  SRMMU page table defines and code.
+ *
+ * Copyright (C) 1995 David S. Miller (davem at caip.rutgers.edu)
+ */
+
+#ifndef _PGTSRMMU_H
+#define _PGTSRMMU_H
+
+/* Replacement for <asm/page.h> */
+#define PAGE_SHIFT   12
+#define PAGE_SIZE    (1 << PAGE_SHIFT)
+#define PAGE_MASK    (~(PAGE_SIZE-1))
+#define PAGE_ALIGN(addr)  (((addr)+PAGE_SIZE-1)&PAGE_MASK)
+/* */
+
+/* PMD_SHIFT determines the size of the area a second-level page table can map */
+#define SRMMU_PMD_SHIFT         18
+#define SRMMU_PMD_SIZE          (1UL << SRMMU_PMD_SHIFT)
+#define SRMMU_PMD_MASK          (~(SRMMU_PMD_SIZE-1))
+#define SRMMU_PMD_ALIGN(addr)   (((addr)+SRMMU_PMD_SIZE-1)&SRMMU_PMD_MASK)
+
+/* PGDIR_SHIFT determines what a third-level page table entry can map */
+#define SRMMU_PGDIR_SHIFT       24
+#define SRMMU_PGDIR_SIZE        (1UL << SRMMU_PGDIR_SHIFT)
+#define SRMMU_PGDIR_MASK        (~(SRMMU_PGDIR_SIZE-1))
+#define SRMMU_PGDIR_ALIGN(addr) (((addr)+SRMMU_PGDIR_SIZE-1)&SRMMU_PGDIR_MASK)
+
+#define SRMMU_PTRS_PER_PTE      64
+#define SRMMU_PTRS_PER_PMD      64
+#define SRMMU_PTRS_PER_PGD      256
+
+#define SRMMU_PTE_TABLE_SIZE    0x100 /* 64 entries, 4 bytes a piece */
+#define SRMMU_PMD_TABLE_SIZE    0x100 /* 64 entries, 4 bytes a piece */
+#define SRMMU_PGD_TABLE_SIZE    0x400 /* 256 entries, 4 bytes a piece */
+
+#define SRMMU_VMALLOC_START   (0xfe300000)
+#define SRMMU_VMALLOC_END     ~0x0UL
+
+/* Definition of the values in the ET field of PTD's and PTE's */
+#define SRMMU_ET_MASK         0x3
+#define SRMMU_ET_INVALID      0x0
+#define SRMMU_ET_PTD          0x1
+#define SRMMU_ET_PTE          0x2
+#define SRMMU_ET_REPTE        0x3 /* AIEEE, SuperSparc II reverse endian page! */
+
+/* Physical page extraction from PTP's and PTE's. */
+#define SRMMU_CTX_PMASK    0xfffffff0
+#define SRMMU_PTD_PMASK    0xfffffff0
+#define SRMMU_PTE_PMASK    0xffffff00
+
+/* The pte non-page bits.  Some notes:
+ * 1) cache, dirty, valid, and ref are frobbable
+ *    for both supervisor and user pages.
+ * 2) exec and write will only give the desired effect
+ *    on user pages
+ * 3) use priv and priv_readonly for changing the
+ *    characteristics of supervisor ptes
+ */
+#define SRMMU_CACHE        0x80
+#define SRMMU_DIRTY        0x40
+#define SRMMU_REF          0x20
+#define SRMMU_EXEC         0x08
+#define SRMMU_WRITE        0x04
+#define SRMMU_VALID        0x02 /* SRMMU_ET_PTE */
+#define SRMMU_PRIV         0x1c
+#define SRMMU_PRIV_RDONLY  0x18
+
+#define SRMMU_CHG_MASK    (0xffffff00 | SRMMU_REF | SRMMU_DIRTY)
+
+/* SRMMU Register addresses in ASI 0x4.  These are valid for all
+ * current SRMMU implementations that exist.
+ */
+#define SRMMU_CTRL_REG           0x00000000
+#define SRMMU_CTXTBL_PTR         0x00000100
+#define SRMMU_CTX_REG            0x00000200
+#define SRMMU_FAULT_STATUS       0x00000300
+#define SRMMU_FAULT_ADDR         0x00000400
+
+#ifndef __ASSEMBLY__
+
+/* Accessing the MMU control register. */
+static __inline__ unsigned int srmmu_get_mmureg(void)
+{
+        unsigned int retval;
+	__asm__ __volatile__("lda [%%g0] %1, %0\n\t" :
+			     "=r" (retval) :
+			     "i" (ASI_M_MMUREGS));
+	return retval;
+}
+
+static __inline__ void srmmu_set_mmureg(unsigned long regval)
+{
+	__asm__ __volatile__("sta %0, [%%g0] %1\n\t" : :
+			     "r" (regval), "i" (ASI_M_MMUREGS) : "memory");
+
+}
+
+static __inline__ void srmmu_set_ctable_ptr(unsigned long paddr)
+{
+	paddr = ((paddr >> 4) & SRMMU_CTX_PMASK);
+	__asm__ __volatile__("sta %0, [%1] %2\n\t" : :
+			     "r" (paddr), "r" (SRMMU_CTXTBL_PTR),
+			     "i" (ASI_M_MMUREGS) :
+			     "memory");
+}
+
+static __inline__ unsigned long srmmu_get_ctable_ptr(void)
+{
+	unsigned int retval;
+
+	__asm__ __volatile__("lda [%1] %2, %0\n\t" :
+			     "=r" (retval) :
+			     "r" (SRMMU_CTXTBL_PTR),
+			     "i" (ASI_M_MMUREGS));
+	return (retval & SRMMU_CTX_PMASK) << 4;
+}
+
+static __inline__ void srmmu_set_context(int context)
+{
+	__asm__ __volatile__("sta %0, [%1] %2\n\t" : :
+			     "r" (context), "r" (SRMMU_CTX_REG),
+			     "i" (ASI_M_MMUREGS) : "memory");
+}
+
+static __inline__ int srmmu_get_context(void)
+{
+	register int retval;
+	__asm__ __volatile__("lda [%1] %2, %0\n\t" :
+			     "=r" (retval) :
+			     "r" (SRMMU_CTX_REG),
+			     "i" (ASI_M_MMUREGS));
+	return retval;
+}
+
+static __inline__ unsigned int srmmu_get_fstatus(void)
+{
+	unsigned int retval;
+
+	__asm__ __volatile__("lda [%1] %2, %0\n\t" :
+			     "=r" (retval) :
+			     "r" (SRMMU_FAULT_STATUS), "i" (ASI_M_MMUREGS));
+	return retval;
+}
+
+static __inline__ unsigned int srmmu_get_faddr(void)
+{
+	unsigned int retval;
+
+	__asm__ __volatile__("lda [%1] %2, %0\n\t" :
+			     "=r" (retval) :
+			     "r" (SRMMU_FAULT_ADDR), "i" (ASI_M_MMUREGS));
+	return retval;
+}
+
+/* This is guaranteed on all SRMMU's. */
+static __inline__ void srmmu_flush_whole_tlb(void)
+{
+	__asm__ __volatile__("sta %%g0, [%0] %1\n\t": :
+			     "r" (0x400),        /* Flush entire TLB!! */
+			     "i" (ASI_M_FLUSH_PROBE) : "memory");
+
+}
+
+/* These flush types are not available on all chips... */
+static __inline__ void srmmu_flush_tlb_ctx(void)
+{
+	__asm__ __volatile__("sta %%g0, [%0] %1\n\t": :
+			     "r" (0x300),        /* Flush TLB ctx.. */
+			     "i" (ASI_M_FLUSH_PROBE) : "memory");
+
+}
+
+static __inline__ void srmmu_flush_tlb_region(unsigned long addr)
+{
+	addr &= SRMMU_PGDIR_MASK;
+	__asm__ __volatile__("sta %%g0, [%0] %1\n\t": :
+			     "r" (addr | 0x200), /* Flush TLB region.. */
+			     "i" (ASI_M_FLUSH_PROBE) : "memory");
+
+}
+
+
+static __inline__ void srmmu_flush_tlb_segment(unsigned long addr)
+{
+	addr &= SRMMU_PMD_MASK;
+	__asm__ __volatile__("sta %%g0, [%0] %1\n\t": :
+			     "r" (addr | 0x100), /* Flush TLB segment.. */
+			     "i" (ASI_M_FLUSH_PROBE) : "memory");
+
+}
+
+static __inline__ void srmmu_flush_tlb_page(unsigned long page)
+{
+	page &= PAGE_MASK;
+	__asm__ __volatile__("sta %%g0, [%0] %1\n\t": :
+			     "r" (page),        /* Flush TLB page.. */
+			     "i" (ASI_M_FLUSH_PROBE) : "memory");
+
+}
+
+static __inline__ unsigned long srmmu_hwprobe(unsigned long vaddr)
+{
+	unsigned long retval;
+
+	vaddr &= PAGE_MASK;
+	__asm__ __volatile__("lda [%1] %2, %0\n\t" :
+			     "=r" (retval) :
+			     "r" (vaddr | 0x400), "i" (ASI_M_FLUSH_PROBE));
+
+	return retval;
+}
+
+static __inline__ int
+srmmu_get_pte (unsigned long addr)
+{
+	register unsigned long entry;
+
+	__asm__ __volatile__("\n\tlda [%1] %2,%0\n\t" :
+				"=r" (entry):
+				"r" ((addr & 0xfffff000) | 0x400), "i" (ASI_M_FLUSH_PROBE));
+	return entry;
+}
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* !(_SPARC_PGTSRMMU_H) */

Modified: openbios-devel/arch/sparc32/romvec.c
===================================================================
--- openbios-devel/arch/sparc32/romvec.c	2009-01-02 14:53:33 UTC (rev 343)
+++ openbios-devel/arch/sparc32/romvec.c	2009-01-03 13:45:02 UTC (rev 344)
@@ -8,14 +8,9 @@
  */
 
 #include "openprom.h"
-#include "asm/io.h"
-#include "asm/types.h"
-#include "libc/vsprintf.h"
 #include "openbios/config.h"
 #include "openbios/bindings.h"
 #include "openbios/drivers.h"
-#include "openbios/kernel.h"
-#include "openbios/sysinclude.h"
 #include "sys_info.h"
 #include "boot.h"
 
@@ -26,15 +21,6 @@
 #define DPRINTF(fmt, args...)
 #endif
 
-#define PAGE_SIZE 4096
-
-static struct linux_mlist_v0 totphys[1];
-static struct linux_mlist_v0 totmap[1];
-static struct linux_mlist_v0 totavail[1];
-
-static struct linux_mlist_v0 *ptphys;
-static struct linux_mlist_v0 *ptmap;
-static struct linux_mlist_v0 *ptavail;
 char obp_stdin, obp_stdout;
 static int obp_fd_stdin, obp_fd_stdout;
 const char *obp_stdin_path, *obp_stdout_path;
@@ -321,37 +307,6 @@
     return ret;
 }
 
-static char *obp_dumb_mmap(char *va, int which_io, unsigned int pa,
-                           unsigned int size)
-{
-    unsigned int npages;
-    unsigned int off;
-    unsigned int mva;
-    uint64_t mpa = ((uint64_t)which_io << 32) | (uint64_t)pa;
-
-    DPRINTF("obp_dumb_mmap: virta 0x%x, paddr 0x%llx, sz %d\n",
-            (unsigned int)va, mpa, size);
-
-    off = pa & (PAGE_SIZE-1);
-    npages = (off + (size - 1) + (PAGE_SIZE-1)) / PAGE_SIZE;
-    mpa &= ~(uint64_t)(PAGE_SIZE - 1);
-
-    mva = (unsigned int) va;
-    while (npages-- != 0) {
-        map_page(mva, mpa, 1);
-        mva += PAGE_SIZE;
-        mpa += (uint64_t)PAGE_SIZE;
-    }
-
-    return va;
-}
-
-static void obp_dumb_munmap(__attribute__((unused)) char *va,
-			    __attribute__((unused)) unsigned int size)
-{
-    DPRINTF("obp_dumb_munmap: virta 0x%x, sz %d\n", (unsigned int)va, size);
-}
-
 static int obp_devread(int dev_desc, char *buf, int nbytes)
 {
     int ret;
@@ -413,37 +368,6 @@
     return ret;
 }
 
-static void obp_dumb_memfree(__attribute__((unused))char *va,
-                             __attribute__((unused))unsigned sz)
-{
-    DPRINTF("obp_dumb_memfree 0x%x(%d)\n", va, sz);
-}
-
-static char * obp_dumb_memalloc(char *va, unsigned int size)
-{
-    static unsigned int next_free_address = 0xFFEDA000;
-
-    size = (size + 7) & ~7;
-    totmap[0].num_bytes -= size;
-    DPRINTF("obp_dumb_memalloc req 0x%x of %d at 0x%x\n", va, size,
-            totmap[0].num_bytes);
-
-    // If va is null, the allocator is supposed to pick a "suitable" address.
-    // (See OpenSolaric prom_alloc.c)  There's not any real guidance as
-    // to what might be "suitable".  So we mimic the behavior of a Sun boot
-    // ROM.
-
-    if (va == NULL) {
-        va = (char *)(next_free_address - size);
-        next_free_address -= size;
-        DPRINTF("obp_dumb_memalloc req null -> 0x%x\n", va);
-    }
-
-    obp_dumb_mmap(va, 0, totmap[0].num_bytes, size);
-
-    return va;
-}
-
 static int obp_cpustart(__attribute__((unused))unsigned int whichcpu,
                         __attribute__((unused))int ctxtbl_ptr,
                         __attribute__((unused))int thiscontext,
@@ -501,27 +425,8 @@
 }
 
 void *
-init_openprom(unsigned long memsize)
+init_openprom(void)
 {
-    ptphys = totphys;
-    ptmap = totmap;
-    ptavail = totavail;
-
-    /*
-     * Form memory descriptors.
-     */
-    totphys[0].theres_more = NULL;
-    totphys[0].start_adr = (char *) 0;
-    totphys[0].num_bytes = memsize;
-
-    totavail[0].theres_more = NULL;
-    totavail[0].start_adr = (char *) 0;
-    totavail[0].num_bytes = va2pa((int)&_start) - PAGE_SIZE;
-
-    totmap[0].theres_more = NULL;
-    totmap[0].start_adr = &_start;
-    totmap[0].num_bytes = (unsigned long) &_iomem - (unsigned long) &_start + PAGE_SIZE;
-
     // Linux wants a R/W romvec table
     romvec0.pv_magic_cookie = LINUX_OPPROM_MAGIC;
     romvec0.pv_romvers = 3;

Modified: openbios-devel/drivers/esp.c
===================================================================
--- openbios-devel/drivers/esp.c	2009-01-02 14:53:33 UTC (rev 343)
+++ openbios-devel/drivers/esp.c	2009-01-03 13:45:02 UTC (rev 344)
@@ -24,6 +24,7 @@
 #include "scsi.h"
 #include "asm/dma.h"
 #include "esp.h"
+#include "ofmem.h"
 
 #define BUFSIZE         4096
 

Modified: openbios-devel/drivers/iommu.c
===================================================================
--- openbios-devel/drivers/iommu.c	2009-01-02 14:53:33 UTC (rev 343)
+++ openbios-devel/drivers/iommu.c	2009-01-03 13:45:02 UTC (rev 344)
@@ -6,25 +6,10 @@
  **/
 #include "openbios/config.h"
 #include "openbios/bindings.h"
-#include "openbios/kernel.h"
-#include "libc/byteorder.h"
-#include "libc/vsprintf.h"
-#include "libc/string.h"
-
 #include "openbios/drivers.h"
-#include "asm/asi.h"
-#include "asm/crs.h"
-#include "asm/io.h"
-#include "pgtsrmmu.h"
 #include "iommu.h"
+#include "ofmem.h"
 
-#define IOMMU_REGS  0x300
-#define NCTX_SWIFT  0x100
-
-#define IOPERM        (IOPTE_CACHE | IOPTE_WRITE | IOPTE_VALID)
-#define MKIOPTE(phys) (((((phys)>>4) & IOPTE_PAGE) | IOPERM) & ~IOPTE_WAZ)
-#define LOWMEMSZ 32 * 1024 * 1024
-
 #ifdef CONFIG_DEBUG_IOMMU
 #define DPRINTF(fmt, args...)                   \
     do { printk(fmt , ##args); } while (0)
@@ -33,37 +18,16 @@
 #endif
 
 /*
- * Allocatable memory chunk.
- */
-struct mem {
-    char *start, *uplim;
-    char *curp;
-};
-
-struct mem cmem;                /* Current memory, virtual */
-static struct mem cio;          /* Current I/O space */
-
-unsigned int va_shift;
-
-static unsigned long *context_table;
-static unsigned long *l1;
-
-/*
  * IOMMU parameters
  */
 struct iommu {
     struct iommu_regs *regs;
     unsigned int *page_table;
     unsigned long plow;     /* Base bus address */
-    unsigned long vasize;   /* Size of VA region that we manage */
-    struct mem bmap;
 };
 
 static struct iommu ciommu;
-static struct iommu_regs *regs;
 
-static void iommu_init(struct iommu *t, uint64_t base);
-
 static void
 iommu_invalidate(struct iommu_regs *iregs)
 {
@@ -71,352 +35,6 @@
 }
 
 /*
- * Allocate memory. This is reusable.
- */
-void
-mem_init(struct mem *t, char *begin, char *limit)
-{
-    t->start = begin;
-    t->uplim = limit;
-    t->curp = begin;
-}
-
-void *
-mem_alloc(struct mem *t, int size, int align)
-{
-    char *p;
-    unsigned long pa;
-
-    // The alignment restrictions refer to physical, not virtual
-    // addresses
-    pa = va2pa((unsigned long)t->curp) + (align - 1);
-    pa &= ~(align - 1);
-    p = (char *)pa2va(pa);
-
-    if ((unsigned long)p >= (unsigned long)t->uplim ||
-        (unsigned long)p + size > (unsigned long)t->uplim)
-        return NULL;
-    t->curp = p + size;
-
-    return p;
-}
-
-void *
-mem_zalloc(struct mem *t, int size, int align)
-{
-    char *p;
-
-    if ((p = mem_alloc(t, size, align)) != NULL)
-        memset(p, 0, size);
-
-    return p;
-}
-
-static unsigned long
-find_pte(unsigned long va, int alloc)
-{
-    uint32_t pte;
-    void *p;
-    unsigned long pa;
-
-    pte = l1[(va >> SRMMU_PGDIR_SHIFT) & (SRMMU_PTRS_PER_PGD - 1)];
-    if ((pte & SRMMU_ET_MASK) == SRMMU_ET_INVALID) {
-        if (alloc) {
-            p = mem_zalloc(&cmem, SRMMU_PTRS_PER_PMD * sizeof(int),
-                           SRMMU_PTRS_PER_PMD * sizeof(int));
-            if (p == NULL)
-                return -1;
-            pte = SRMMU_ET_PTD | ((va2pa((unsigned long)p)) >> 4);
-            l1[(va >> SRMMU_PGDIR_SHIFT) & (SRMMU_PTRS_PER_PGD - 1)] = pte;
-            /* barrier() */
-        } else {
-            return -1;
-        }
-    }
-
-    pa = (pte & 0xFFFFFFF0) << 4;
-    pa += ((va >> SRMMU_PMD_SHIFT) & (SRMMU_PTRS_PER_PMD - 1)) << 2;
-    pte = *(uint32_t *)pa2va(pa);
-    if ((pte & SRMMU_ET_MASK) == SRMMU_ET_INVALID) {
-        if (alloc) {
-            p = mem_zalloc(&cmem, SRMMU_PTRS_PER_PTE * sizeof(void *),
-                           SRMMU_PTRS_PER_PTE * sizeof(void *));
-            if (p == NULL)
-                return -2;
-            pte = SRMMU_ET_PTD | ((va2pa((unsigned int)p)) >> 4);
-            *(uint32_t *)pa2va(pa) = pte;
-        } else {
-            return -2;
-        }
-    }
-
-    pa = (pte & 0xFFFFFFF0) << 4;
-    pa += ((va >> PAGE_SHIFT) & (SRMMU_PTRS_PER_PTE - 1)) << 2;
-
-    return pa2va(pa);
-}
-
-/*
- * Create a memory mapping from va to epa.
- */
-int
-map_page(unsigned long va, uint64_t epa, int type)
-{
-    uint32_t pte;
-    unsigned long pa;
-
-    pa = find_pte(va, 1);
-
-    pte = SRMMU_ET_PTE | ((epa & PAGE_MASK) >> 4);
-    if (type) {		/* I/O */
-        pte |= SRMMU_REF;
-        /* SRMMU cannot make Supervisor-only, but not exectutable */
-        pte |= SRMMU_PRIV;
-    } else {		/* memory */
-        pte |= SRMMU_REF | SRMMU_CACHE;
-        pte |= SRMMU_PRIV; /* Supervisor only access */
-    }
-    *(uint32_t *)pa = pte;
-    DPRINTF("map_page: va 0x%lx pa 0x%llx pte 0x%x\n", va, epa, pte);
-
-    return 0;
-}
-
-/*
- * Create an I/O mapping to pa[size].
- * Returns va of the mapping or 0 if unsuccessful.
- */
-void *
-map_io(uint64_t pa, int size)
-{
-    void *va;
-    unsigned int npages;
-    unsigned int off;
-    unsigned int mva;
-
-    off = pa & (PAGE_SIZE - 1);
-    npages = (off + size - 1) / PAGE_SIZE + 1;
-    pa &= ~(PAGE_SIZE - 1);
-
-    va = mem_alloc(&cio, npages * PAGE_SIZE, PAGE_SIZE);
-    if (va == NULL)
-        return va;
-
-    mva = (unsigned int) va;
-    DPRINTF("map_io: va 0x%p pa 0x%llx off 0x%x npages %d\n", va, pa, off, npages); /* P3 */
-    while (npages-- != 0) {
-        map_page(mva, pa, 1);
-        mva += PAGE_SIZE;
-        pa += PAGE_SIZE;
-    }
-
-    return (void *)((unsigned int)va + off);
-}
-
-/*
- * D5.3 pgmap@ ( va -- pte )
- */
-static void
-pgmap_fetch(void)
-{
-    uint32_t pte;
-    unsigned long va, pa;
-
-    va = POP();
-
-    pa = find_pte(va, 0);
-    if (pa == 1 || pa == 2)
-        goto error;
-    pte = *(uint32_t *)pa;
-    DPRINTF("pgmap@: va 0x%lx pa 0x%lx pte 0x%x\n", va, pa, pte);
-
-    PUSH(pte);
-    return;
- error:
-    PUSH(0);
-}
-
-/*
- * D5.3 pgmap! ( pte va -- )
- */
-static void
-pgmap_store(void)
-{
-    uint32_t pte;
-    unsigned long va, pa;
-
-    va = POP();
-    pte = POP();
-
-    pa = find_pte(va, 1);
-    *(uint32_t *)pa = pte;
-    DPRINTF("pgmap!: va 0x%lx pa 0x%lx pte 0x%x\n", va, pa, pte);
-}
-
-/*
- * D5.3 map-pages ( pa space va size -- )
- */
-static void
-map_pages(void)
-{
-    unsigned long va;
-    int size;
-    uint64_t pa;
-
-    size = POP();
-    va = POP();
-    pa = POP();
-    pa <<= 32;
-    pa |= POP() & 0xffffffff;
-
-    for (; size > 0; size -= PAGE_SIZE, pa += PAGE_SIZE, va += PAGE_SIZE)
-        map_page(va, pa, 1);
-    DPRINTF("map-page: va 0x%lx pa 0x%lx size 0x%x\n", va, pa, size);
-}
-
-
-void
-ob_init_mmu(uint64_t base)
-{
-    extern unsigned int qemu_mem_size;
-
-    push_str("/memory");
-    fword("find-device");
-
-    PUSH(0);
-    fword("encode-int");
-    PUSH(0);
-    fword("encode-int");
-    fword("encode+");
-    PUSH(qemu_mem_size);
-    fword("encode-int");
-    fword("encode+");
-    push_str("reg");
-    fword("property");
-
-    PUSH(0);
-    fword("encode-int");
-    PUSH(0);
-    fword("encode-int");
-    fword("encode+");
-    PUSH(va2pa((unsigned long)&_start) - PAGE_SIZE);
-    fword("encode-int");
-    fword("encode+");
-    push_str("available");
-    fword("property");
-
-    push_str("/virtual-memory");
-    fword("find-device");
-
-    PUSH(base >> 32);
-    fword("encode-int");
-    PUSH(base & 0xffffffff);
-    fword("encode-int");
-    fword("encode+");
-    PUSH(IOMMU_REGS);
-    fword("encode-int");
-    fword("encode+");
-    push_str("reg");
-    fword("property");
-
-    PUSH(0);
-    fword("encode-int");
-    PUSH(0);
-    fword("encode-int");
-    fword("encode+");
-    PUSH((unsigned long)&_start - PAGE_SIZE);
-    fword("encode-int");
-    fword("encode+");
-
-    PUSH(0);
-    fword("encode-int");
-    fword("encode+");
-    PUSH(va2pa((unsigned long)&_iomem));
-    fword("encode-int");
-    fword("encode+");
-    PUSH(-va2pa((unsigned long)&_iomem));
-    fword("encode-int");
-    fword("encode+");
-    push_str("available");
-    fword("property");
-
-    push_str("/iommu");
-    fword("find-device");
-    PUSH((unsigned long)regs);
-    fword("encode-int");
-    push_str("address");
-    fword("property");
-
-    PUSH(base >> 32);
-    fword("encode-int");
-    PUSH(base & 0xffffffff);
-    fword("encode-int");
-    fword("encode+");
-    PUSH(IOMMU_REGS);
-    fword("encode-int");
-    fword("encode+");
-    push_str("reg");
-    fword("property");
-
-    PUSH(0);
-    fword("active-package!");
-    bind_func("pgmap@", pgmap_fetch);
-    bind_func("pgmap!", pgmap_store);
-    bind_func("map-pages", map_pages);
-}
-
-
-/*
- * Switch page tables.
- */
-void
-init_mmu_swift(uint64_t base)
-{
-    unsigned int addr, i;
-    unsigned long pa, va;
-
-    mem_init(&cio, (char *)&_end, (char *)&_iomem);
-
-    context_table = mem_zalloc(&cmem, NCTX_SWIFT * sizeof(int), NCTX_SWIFT * sizeof(int));
-    l1 = mem_zalloc(&cmem, 256 * sizeof(int), 256 * sizeof(int));
-
-    context_table[0] = (((unsigned long)va2pa((unsigned long)l1)) >> 4) | SRMMU_ET_PTD;
-
-    for (i = 1; i < NCTX_SWIFT; i++) {
-        context_table[i] = SRMMU_ET_INVALID;
-    }
-    for (i = 0; i < 256; i += 4) {
-        l1[i] = SRMMU_ET_INVALID;
-    }
-
-    // text, rodata, data, and bss mapped to end of RAM
-    va = (unsigned long)&_start;
-    for (; va < (unsigned long)&_end; va += PAGE_SIZE) {
-        pa = va2pa(va);
-        map_page(va, pa, 0);
-    }
-
-    // 1:1 mapping for RAM
-    pa = va = 0;
-    for (; va < LOWMEMSZ; va += PAGE_SIZE, pa += PAGE_SIZE) {
-        map_page(va, pa, 0);
-    }
-
-    /*
-     * Flush cache
-     */
-    for (addr = 0; addr < 0x2000; addr += 0x10) {
-        __asm__ __volatile__ ("sta %%g0, [%0] %1\n\t" : :
-                              "r" (addr), "i" (ASI_M_DATAC_TAG));
-        __asm__ __volatile__ ("sta %%g0, [%0] %1\n\t" : :
-                              "r" (addr<<1), "i" (ASI_M_TXTC_TAG));
-    }
-    srmmu_set_context(0);
-    srmmu_set_ctable_ptr(va2pa((unsigned long)context_table));
-    srmmu_flush_whole_tlb();
-    iommu_init(&ciommu, base);
-}
-/*
  * XXX This is a problematic interface. We alloc _memory_ which is uncached.
  * So if we ever reuse allocations somebody is going to get uncached pages.
  * Returned address is always aligned by page.
@@ -432,13 +50,14 @@
     unsigned int i;
     unsigned int *iopte;
     struct iommu *t = &ciommu;
+    int ret;
 
     npages = (size + (PAGE_SIZE-1)) / PAGE_SIZE;
-    va = mem_alloc(&cmem, npages * PAGE_SIZE, PAGE_SIZE);
-    if (va == NULL)
+    ret = posix_memalign(&va, npages * PAGE_SIZE, PAGE_SIZE);
+    if (ret != 0)
         return NULL;
 
-    ba = (unsigned int)mem_alloc(&t->bmap, npages * PAGE_SIZE, PAGE_SIZE);
+    ba = (unsigned int)mem_alloc(&cdvmem, npages * PAGE_SIZE, PAGE_SIZE);
     if (ba == 0)
         return NULL;
 
@@ -475,13 +94,16 @@
  * This looks like initialization of CPU MMU but
  * the routine is higher in food chain.
  */
-static void
+static struct iommu_regs *
 iommu_init(struct iommu *t, uint64_t base)
 {
     unsigned int *ptab;
     int ptsize;
     unsigned int impl, vers;
     unsigned int tmp;
+    struct iommu_regs *regs;
+    int ret;
+    unsigned long vasize;
 
     regs = map_io(base, IOMMU_REGS);
     if (regs == NULL) {
@@ -497,15 +119,17 @@
 
     tmp |= (IOMMU_RNGE_32MB | IOMMU_CTRL_ENAB);
     t->plow = 0xfe000000;		/* End - 32 MB */
-    t->vasize = 0x2000000;		/* 32 MB */
+    /* Size of VA region that we manage */
+    vasize = 0x2000000; /* 32 MB */
 
     regs->control = tmp;
     iommu_invalidate(regs);
 
     /* Allocate IOMMU page table */
-    /* Thremendous alignment causes great waste... */
-    ptsize = (t->vasize/PAGE_SIZE) *  sizeof(int);
-    if ((ptab = mem_zalloc(&cmem, ptsize, ptsize)) == NULL) {
+    /* Tremendous alignment causes great waste... */
+    ptsize = (vasize / PAGE_SIZE) * sizeof(int);
+    ret = posix_memalign((void *)&ptab, ptsize, ptsize);
+    if (ret != 0) {
         DPRINTF("Cannot allocate IOMMU table [0x%x]\n", ptsize);
         for (;;) { }
     }
@@ -520,5 +144,46 @@
     DPRINTF("IOMMU: impl %d vers %d page table at 0x%p (pa 0x%x) of size %d bytes\n",
             impl, vers, t->page_table, tmp, ptsize);
 
-    mem_init(&t->bmap, (char*)t->plow, (char *)0xfffff000);
+    mem_init(&cdvmem, (char*)t->plow, (char *)0xfffff000);
+    return regs;
 }
+
+void
+ob_init_iommu(uint64_t base)
+{
+    struct iommu_regs *regs;
+
+    regs = iommu_init(&ciommu, base);
+
+    push_str("/virtual-memory");
+    fword("find-device");
+
+    PUSH(base >> 32);
+    fword("encode-int");
+    PUSH(base & 0xffffffff);
+    fword("encode-int");
+    fword("encode+");
+    PUSH(IOMMU_REGS);
+    fword("encode-int");
+    fword("encode+");
+    push_str("reg");
+    fword("property");
+
+    push_str("/iommu");
+    fword("find-device");
+    PUSH((unsigned long)regs);
+    fword("encode-int");
+    push_str("address");
+    fword("property");
+
+    PUSH(base >> 32);
+    fword("encode-int");
+    PUSH(base & 0xffffffff);
+    fword("encode-int");
+    fword("encode+");
+    PUSH(IOMMU_REGS);
+    fword("encode-int");
+    fword("encode+");
+    push_str("reg");
+    fword("property");
+}

Modified: openbios-devel/drivers/iommu.h
===================================================================
--- openbios-devel/drivers/iommu.h	2009-01-02 14:53:33 UTC (rev 343)
+++ openbios-devel/drivers/iommu.h	2009-01-03 13:45:02 UTC (rev 344)
@@ -95,3 +95,8 @@
 #define IOPTE_WRITE         0x00000004 /* Writeable */
 #define IOPTE_VALID         0x00000002 /* IOPTE is valid */
 #define IOPTE_WAZ           0x00000001 /* Write as zeros */
+
+#define IOPERM        (IOPTE_CACHE | IOPTE_WRITE | IOPTE_VALID)
+#define MKIOPTE(phys) (((((phys)>>4) & IOPTE_PAGE) | IOPERM) & ~IOPTE_WAZ)
+
+#define IOMMU_REGS  0x300

Modified: openbios-devel/drivers/obio.c
===================================================================
--- openbios-devel/drivers/obio.c	2009-01-02 14:53:33 UTC (rev 343)
+++ openbios-devel/drivers/obio.c	2009-01-03 13:45:02 UTC (rev 344)
@@ -18,6 +18,7 @@
 
 #include "openbios/drivers.h"
 #include "openbios/nvram.h"
+#include "ofmem.h"
 #include "obio.h"
 #define cpu_to_be16(x) __cpu_to_be16(x)
 #include "openbios/firmware_abi.h"

Modified: openbios-devel/drivers/obio.h
===================================================================
--- openbios-devel/drivers/obio.h	2009-01-02 14:53:33 UTC (rev 343)
+++ openbios-devel/drivers/obio.h	2009-01-03 13:45:02 UTC (rev 344)
@@ -36,7 +36,6 @@
 #define SLAVIO_SIZE      0x01000000
 
 #define SUN4M_NCPUS      16
-#define PAGE_SIZE        4096
 
 #define CFG_ADDR         0xd00000510ULL
 #define CFG_SIZE         3

Deleted: openbios-devel/drivers/pgtsrmmu.h
===================================================================
--- openbios-devel/drivers/pgtsrmmu.h	2009-01-02 14:53:33 UTC (rev 343)
+++ openbios-devel/drivers/pgtsrmmu.h	2009-01-03 13:45:02 UTC (rev 344)
@@ -1,230 +0,0 @@
-/*
- * Taken from kernel for decoupling from <asm/page.h>. --zaitcev
- *
- * $Id: pgtsrmmu.h,v 1.2 1999/04/19 01:04:31 zaitcev Exp $
- * pgtsrmmu.h:  SRMMU page table defines and code.
- *
- * Copyright (C) 1995 David S. Miller (davem at caip.rutgers.edu)
- */
-
-#ifndef _PGTSRMMU_H
-#define _PGTSRMMU_H
-
-/* Replacement for <asm/page.h> */
-#define PAGE_SHIFT   12
-#define PAGE_SIZE    (1 << PAGE_SHIFT)
-#define PAGE_MASK    (~(PAGE_SIZE-1))
-#define PAGE_ALIGN(addr)  (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-/* */
-
-/* PMD_SHIFT determines the size of the area a second-level page table can map */
-#define SRMMU_PMD_SHIFT         18
-#define SRMMU_PMD_SIZE          (1UL << SRMMU_PMD_SHIFT)
-#define SRMMU_PMD_MASK          (~(SRMMU_PMD_SIZE-1))
-#define SRMMU_PMD_ALIGN(addr)   (((addr)+SRMMU_PMD_SIZE-1)&SRMMU_PMD_MASK)
-
-/* PGDIR_SHIFT determines what a third-level page table entry can map */
-#define SRMMU_PGDIR_SHIFT       24
-#define SRMMU_PGDIR_SIZE        (1UL << SRMMU_PGDIR_SHIFT)
-#define SRMMU_PGDIR_MASK        (~(SRMMU_PGDIR_SIZE-1))
-#define SRMMU_PGDIR_ALIGN(addr) (((addr)+SRMMU_PGDIR_SIZE-1)&SRMMU_PGDIR_MASK)
-
-#define SRMMU_PTRS_PER_PTE      64
-#define SRMMU_PTRS_PER_PMD      64
-#define SRMMU_PTRS_PER_PGD      256
-
-#define SRMMU_PTE_TABLE_SIZE    0x100 /* 64 entries, 4 bytes a piece */
-#define SRMMU_PMD_TABLE_SIZE    0x100 /* 64 entries, 4 bytes a piece */
-#define SRMMU_PGD_TABLE_SIZE    0x400 /* 256 entries, 4 bytes a piece */
-
-#define SRMMU_VMALLOC_START   (0xfe300000)
-#define SRMMU_VMALLOC_END     ~0x0UL
-
-/* Definition of the values in the ET field of PTD's and PTE's */
-#define SRMMU_ET_MASK         0x3
-#define SRMMU_ET_INVALID      0x0
-#define SRMMU_ET_PTD          0x1
-#define SRMMU_ET_PTE          0x2
-#define SRMMU_ET_REPTE        0x3 /* AIEEE, SuperSparc II reverse endian page! */
-
-/* Physical page extraction from PTP's and PTE's. */
-#define SRMMU_CTX_PMASK    0xfffffff0
-#define SRMMU_PTD_PMASK    0xfffffff0
-#define SRMMU_PTE_PMASK    0xffffff00
-
-/* The pte non-page bits.  Some notes:
- * 1) cache, dirty, valid, and ref are frobbable
- *    for both supervisor and user pages.
- * 2) exec and write will only give the desired effect
- *    on user pages
- * 3) use priv and priv_readonly for changing the
- *    characteristics of supervisor ptes
- */
-#define SRMMU_CACHE        0x80
-#define SRMMU_DIRTY        0x40
-#define SRMMU_REF          0x20
-#define SRMMU_EXEC         0x08
-#define SRMMU_WRITE        0x04
-#define SRMMU_VALID        0x02 /* SRMMU_ET_PTE */
-#define SRMMU_PRIV         0x1c
-#define SRMMU_PRIV_RDONLY  0x18
-
-#define SRMMU_CHG_MASK    (0xffffff00 | SRMMU_REF | SRMMU_DIRTY)
-
-/* SRMMU Register addresses in ASI 0x4.  These are valid for all
- * current SRMMU implementations that exist.
- */
-#define SRMMU_CTRL_REG           0x00000000
-#define SRMMU_CTXTBL_PTR         0x00000100
-#define SRMMU_CTX_REG            0x00000200
-#define SRMMU_FAULT_STATUS       0x00000300
-#define SRMMU_FAULT_ADDR         0x00000400
-
-#ifndef __ASSEMBLY__
-
-/* Accessing the MMU control register. */
-static __inline__ unsigned int srmmu_get_mmureg(void)
-{
-        unsigned int retval;
-	__asm__ __volatile__("lda [%%g0] %1, %0\n\t" :
-			     "=r" (retval) :
-			     "i" (ASI_M_MMUREGS));
-	return retval;
-}
-
-static __inline__ void srmmu_set_mmureg(unsigned long regval)
-{
-	__asm__ __volatile__("sta %0, [%%g0] %1\n\t" : :
-			     "r" (regval), "i" (ASI_M_MMUREGS) : "memory");
-
-}
-
-static __inline__ void srmmu_set_ctable_ptr(unsigned long paddr)
-{
-	paddr = ((paddr >> 4) & SRMMU_CTX_PMASK);
-	__asm__ __volatile__("sta %0, [%1] %2\n\t" : :
-			     "r" (paddr), "r" (SRMMU_CTXTBL_PTR),
-			     "i" (ASI_M_MMUREGS) :
-			     "memory");
-}
-
-static __inline__ unsigned long srmmu_get_ctable_ptr(void)
-{
-	unsigned int retval;
-
-	__asm__ __volatile__("lda [%1] %2, %0\n\t" :
-			     "=r" (retval) :
-			     "r" (SRMMU_CTXTBL_PTR),
-			     "i" (ASI_M_MMUREGS));
-	return (retval & SRMMU_CTX_PMASK) << 4;
-}
-
-static __inline__ void srmmu_set_context(int context)
-{
-	__asm__ __volatile__("sta %0, [%1] %2\n\t" : :
-			     "r" (context), "r" (SRMMU_CTX_REG),
-			     "i" (ASI_M_MMUREGS) : "memory");
-}
-
-static __inline__ int srmmu_get_context(void)
-{
-	register int retval;
-	__asm__ __volatile__("lda [%1] %2, %0\n\t" :
-			     "=r" (retval) :
-			     "r" (SRMMU_CTX_REG),
-			     "i" (ASI_M_MMUREGS));
-	return retval;
-}
-
-static __inline__ unsigned int srmmu_get_fstatus(void)
-{
-	unsigned int retval;
-
-	__asm__ __volatile__("lda [%1] %2, %0\n\t" :
-			     "=r" (retval) :
-			     "r" (SRMMU_FAULT_STATUS), "i" (ASI_M_MMUREGS));
-	return retval;
-}
-
-static __inline__ unsigned int srmmu_get_faddr(void)
-{
-	unsigned int retval;
-
-	__asm__ __volatile__("lda [%1] %2, %0\n\t" :
-			     "=r" (retval) :
-			     "r" (SRMMU_FAULT_ADDR), "i" (ASI_M_MMUREGS));
-	return retval;
-}
-
-/* This is guaranteed on all SRMMU's. */
-static __inline__ void srmmu_flush_whole_tlb(void)
-{
-	__asm__ __volatile__("sta %%g0, [%0] %1\n\t": :
-			     "r" (0x400),        /* Flush entire TLB!! */
-			     "i" (ASI_M_FLUSH_PROBE) : "memory");
-
-}
-
-/* These flush types are not available on all chips... */
-static __inline__ void srmmu_flush_tlb_ctx(void)
-{
-	__asm__ __volatile__("sta %%g0, [%0] %1\n\t": :
-			     "r" (0x300),        /* Flush TLB ctx.. */
-			     "i" (ASI_M_FLUSH_PROBE) : "memory");
-
-}
-
-static __inline__ void srmmu_flush_tlb_region(unsigned long addr)
-{
-	addr &= SRMMU_PGDIR_MASK;
-	__asm__ __volatile__("sta %%g0, [%0] %1\n\t": :
-			     "r" (addr | 0x200), /* Flush TLB region.. */
-			     "i" (ASI_M_FLUSH_PROBE) : "memory");
-
-}
-
-
-static __inline__ void srmmu_flush_tlb_segment(unsigned long addr)
-{
-	addr &= SRMMU_PMD_MASK;
-	__asm__ __volatile__("sta %%g0, [%0] %1\n\t": :
-			     "r" (addr | 0x100), /* Flush TLB segment.. */
-			     "i" (ASI_M_FLUSH_PROBE) : "memory");
-
-}
-
-static __inline__ void srmmu_flush_tlb_page(unsigned long page)
-{
-	page &= PAGE_MASK;
-	__asm__ __volatile__("sta %%g0, [%0] %1\n\t": :
-			     "r" (page),        /* Flush TLB page.. */
-			     "i" (ASI_M_FLUSH_PROBE) : "memory");
-
-}
-
-static __inline__ unsigned long srmmu_hwprobe(unsigned long vaddr)
-{
-	unsigned long retval;
-
-	vaddr &= PAGE_MASK;
-	__asm__ __volatile__("lda [%1] %2, %0\n\t" :
-			     "=r" (retval) :
-			     "r" (vaddr | 0x400), "i" (ASI_M_FLUSH_PROBE));
-
-	return retval;
-}
-
-static __inline__ int
-srmmu_get_pte (unsigned long addr)
-{
-	register unsigned long entry;
-
-	__asm__ __volatile__("\n\tlda [%1] %2,%0\n\t" :
-				"=r" (entry):
-				"r" ((addr & 0xfffff000) | 0x400), "i" (ASI_M_FLUSH_PROBE));
-	return entry;
-}
-
-#endif /* !(__ASSEMBLY__) */
-
-#endif /* !(_SPARC_PGTSRMMU_H) */

Modified: openbios-devel/drivers/sbus.c
===================================================================
--- openbios-devel/drivers/sbus.c	2009-01-02 14:53:33 UTC (rev 343)
+++ openbios-devel/drivers/sbus.c	2009-01-03 13:45:02 UTC (rev 344)
@@ -15,8 +15,8 @@
 #include "openbios/kernel.h"
 #include "libc/byteorder.h"
 #include "libc/vsprintf.h"
-
 #include "openbios/drivers.h"
+#include "ofmem.h"
 
 #define SBUS_REGS        0x28
 #define SBUS_SLOTS       16

Modified: openbios-devel/include/libc/stdlib.h
===================================================================
--- openbios-devel/include/libc/stdlib.h	2009-01-02 14:53:33 UTC (rev 343)
+++ openbios-devel/include/libc/stdlib.h	2009-01-03 13:45:02 UTC (rev 344)
@@ -19,6 +19,7 @@
 extern void	*malloc( int size );
 extern void	free( void *ptr );
 extern void	*realloc( void *ptr, size_t size );
+extern int      posix_memalign(void **memptr, size_t alignment, size_t size);
 
 /* should perhaps go somewhere else... */
 extern void	qsort( void *base, size_t nmemb, size_t size, int (*compar)(const void*, const void*));

Modified: openbios-devel/include/ofmem.h
===================================================================
--- openbios-devel/include/ofmem.h	2009-01-02 14:53:33 UTC (rev 343)
+++ openbios-devel/include/ofmem.h	2009-01-03 13:45:02 UTC (rev 344)
@@ -37,6 +37,20 @@
 void isi_exception( void );
 void setup_mmu( ulong ramsize );
 void ofmem_register( phandle_t ph );
+#elif defined(CONFIG_SPARC32)
+#define PAGE_SHIFT   12
+#define PAGE_SIZE    (1 << PAGE_SHIFT)
+#define PAGE_MASK    (~(PAGE_SIZE - 1))
+#define PAGE_ALIGN(addr)  (((addr) + PAGE_SIZE - 1) & PAGE_MASK)
+
+/* arch/sparc32/lib.c */
+struct mem;
+extern struct mem cdvmem;
+
+void mem_init(struct mem *t, char *begin, char *limit);
+void *mem_alloc(struct mem *t, int size, int align);
+int map_page(unsigned long va, uint64_t epa, int type);
+void *map_io(uint64_t pa, int size);
 #endif
 
 #endif   /* _H_OFMEM */

Modified: openbios-devel/include/openbios/drivers.h
===================================================================
--- openbios-devel/include/openbios/drivers.h	2009-01-02 14:53:33 UTC (rev 343)
+++ openbios-devel/include/openbios/drivers.h	2009-01-03 13:45:02 UTC (rev 344)
@@ -54,7 +54,8 @@
 int uart_init(uint64_t port, unsigned long speed);
 
 /* drivers/iommu.c */
-extern struct mem cmem;
+void ob_init_iommu(uint64_t base);
+void *dvma_alloc(int size, unsigned int *pphys);
 
 /* drivers/sbus.c */
 extern uint16_t graphic_depth;

Modified: openbios-devel/include/sparc32/io.h
===================================================================
--- openbios-devel/include/sparc32/io.h	2009-01-02 14:53:33 UTC (rev 343)
+++ openbios-devel/include/sparc32/io.h	2009-01-03 13:45:02 UTC (rev 344)
@@ -31,17 +31,6 @@
 #define phys_to_virt(phys) ((void *) ((unsigned long) (phys)))
 #define virt_to_phys(virt) ((unsigned long) (virt))
 
-struct mem;
-
-void mem_init(struct mem *t, char *begin, char *limit);
-void *mem_alloc(struct mem *t, int size, int align);
-void *mem_zalloc(struct mem *t, int size, int align);
-int map_page(unsigned long va, uint64_t epa, int type);
-void *map_io(uint64_t pa, int size);
-void ob_init_mmu(uint64_t base);
-void init_mmu_swift(uint64_t base);
-void *dvma_alloc(int size, unsigned int *pphys);
-
 #ifndef BOOTSTRAP
 
 #ifndef _IO_BASE




More information about the OpenBIOS mailing list