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