This patchset converts SPARC32 and its associated devices over from its own private memory routines over to using the OFMEM API as used by PPC and SPARC64.
v1: Initial patchset.
Mark Cave-Ayland (13): Change the SPARC32 build system so that OFMEM is now included within SPARC32 builds. Reduce memory of the Forth machine to 16k. Alter the SPARC32 entry.S file to allow extra space for the page tables to handle OpenBIOS images up to 2MB. Switch SPARC32 page tables over to use OFMEM's ofmem_posix_memalign() rather than its internal posix_memalign() function. Switch IOMMU posix_memalign() calls over to ofmem_posix_memalign(), and then remove the private SPARC32 posix_memalign() implementation since it is no longer required. Add ofmem_init() function to openbios.c taking into account that unlike SPARC64, OFMEM needs to be setup *before* the MMU so that the page table allocation routines can use it. Switch SPARC32 over to use OFMEM's malloc()/free() internally rather than using it's own implementation. Remove the existing map_page() function and instead install a transitional API using map_pages() which is almost identical to the OFMEM API. Introduce ofmem_arch_io_translation_mode() to allow an OFMEM arch to specify different MMU modes for I/O memory mapped regions. Implement ofmem_map_io() within OFMEM as a function to map I/O memory (similar to SPARC32's private map_io() function). Switch all SPARC32 devices over from the private map_io() function over to OFMEM's ofmem_map_io() function. Switch remaining SPARC32 code over to OFMEM. Fix the FMT_cell and FMT_ucell definitions for SPARC32.
mcayland (3): Alter ofmem_posix_memalign() so that the resulting pointer is aligned for both physical and virtual addresses. Introduce ofmem_arch_get_phys_top() for specifying the top of physical memory in OFMEM. Change OFMEM to allocate memory from the top of RAM downwards.
openbios-devel/arch/ppc/qemu/ofmem.c | 23 ++ openbios-devel/arch/sparc32/build.xml | 1 + openbios-devel/arch/sparc32/console.c | 4 +- openbios-devel/arch/sparc32/entry.S | 52 +++- openbios-devel/arch/sparc32/ldscript | 3 +- openbios-devel/arch/sparc32/lib.c | 306 +++++---------------- openbios-devel/arch/sparc32/ofmem_sparc32.c | 149 ++++++++++ openbios-devel/arch/sparc32/openbios.c | 6 +- openbios-devel/arch/sparc64/ofmem_sparc64.c | 26 ++- openbios-devel/config/examples/sparc32_config.xml | 2 + openbios-devel/drivers/escc.c | 4 +- openbios-devel/drivers/esp.c | 4 +- openbios-devel/drivers/fw_cfg.c | 2 +- openbios-devel/drivers/iommu.c | 12 +- openbios-devel/drivers/obio.c | 10 +- openbios-devel/drivers/sbus.c | 2 +- openbios-devel/include/arch/sparc32/types.h | 4 +- openbios-devel/include/libc/stdlib.h | 1 - openbios-devel/include/libopenbios/ofmem.h | 15 +- openbios-devel/libopenbios/ofmem_common.c | 73 +++++- 20 files changed, 402 insertions(+), 297 deletions(-) create mode 100644 openbios-devel/arch/sparc32/ofmem_sparc32.c
From: mcayland mcayland@f158a5a8-5612-0410-a976-696ce0be7e32
Some uses of ofmem_posix_memalign() need to ensure that the alignment requirement is for physical as well as virtual addresses, e.g. for MMU page tables.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@siriusit.co.uk
git-svn-id: svn://openbios.org/openbios/trunk@994 f158a5a8-5612-0410-a976-696ce0be7e32 --- openbios-devel/libopenbios/ofmem_common.c | 11 ++++++++--- 1 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/openbios-devel/libopenbios/ofmem_common.c b/openbios-devel/libopenbios/ofmem_common.c index 8a24a7f..48b0b17 100644 --- a/openbios-devel/libopenbios/ofmem_common.c +++ b/openbios-devel/libopenbios/ofmem_common.c @@ -33,9 +33,9 @@ static inline size_t align_size(size_t x, size_t a) return (x + a - 1) & ~(a - 1); }
-static inline void * align_ptr(uintptr_t x, size_t a) +static inline phys_addr_t align_ptr(uintptr_t x, size_t a) { - return (void *)((x + a - 1) & ~(a - 1)); + return (x + a - 1) & ~(a - 1); }
static ucell get_ram_size( void ) @@ -92,6 +92,7 @@ int ofmem_posix_memalign( void **memptr, size_t alignment, size_t size ) alloc_desc_t *d, **pp; void *ret; ucell top; + phys_addr_t pa;
if( !size ) return ENOMEM; @@ -117,7 +118,11 @@ int ofmem_posix_memalign( void **memptr, size_t alignment, size_t size )
top = ofmem_arch_get_heap_top();
- ret = align_ptr((uintptr_t)ofmem->next_malloc + sizeof(alloc_desc_t), alignment); + /* Alignment should be on physical not virtual address */ + pa = va2pa((uintptr_t)ofmem->next_malloc + sizeof(alloc_desc_t)); + pa = align_ptr(pa, alignment); + ret = (void *)pa2va(pa); + if( pointer2cell(ret) + size > top ) { printk("out of malloc memory (%x)!\n", size ); return ENOMEM;
From: mcayland mcayland@f158a5a8-5612-0410-a976-696ce0be7e32
At the same time, teach OFMEM to make use of it when calculating the /memory available property.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@siriusit.co.uk
git-svn-id: svn://openbios.org/openbios/trunk@995 f158a5a8-5612-0410-a976-696ce0be7e32 --- openbios-devel/arch/ppc/qemu/ofmem.c | 7 +++++++ openbios-devel/arch/sparc64/ofmem_sparc64.c | 7 +++++++ openbios-devel/include/libopenbios/ofmem.h | 1 + openbios-devel/libopenbios/ofmem_common.c | 8 ++++---- 4 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/openbios-devel/arch/ppc/qemu/ofmem.c b/openbios-devel/arch/ppc/qemu/ofmem.c index e41d47d..c0143a4 100644 --- a/openbios-devel/arch/ppc/qemu/ofmem.c +++ b/openbios-devel/arch/ppc/qemu/ofmem.c @@ -115,6 +115,13 @@ ucell ofmem_arch_get_virt_top(void) return IO_BASE; }
+phys_addr_t ofmem_arch_get_phys_top(void) +{ + ofmem_t *ofmem = ofmem_arch_get_private(); + + return ofmem->ramsize; +} + void ofmem_arch_unmap_pages(ucell virt, ucell size) { /* kill page mappings in provided range */ diff --git a/openbios-devel/arch/sparc64/ofmem_sparc64.c b/openbios-devel/arch/sparc64/ofmem_sparc64.c index 4d13038..0ec8632 100644 --- a/openbios-devel/arch/sparc64/ofmem_sparc64.c +++ b/openbios-devel/arch/sparc64/ofmem_sparc64.c @@ -63,6 +63,13 @@ ucell ofmem_arch_get_virt_top(void) return (ucell)TOP_OF_RAM; }
+phys_addr_t ofmem_arch_get_phys_top(void) +{ + ofmem_t *ofmem = ofmem_arch_get_private(); + + return ofmem->ramsize; +} + retain_t *ofmem_arch_get_retained(void) { /* Retained area is at the top of physical RAM */ diff --git a/openbios-devel/include/libopenbios/ofmem.h b/openbios-devel/include/libopenbios/ofmem.h index ebb4dba..54868e2 100644 --- a/openbios-devel/include/libopenbios/ofmem.h +++ b/openbios-devel/include/libopenbios/ofmem.h @@ -62,6 +62,7 @@ extern ofmem_t* ofmem_arch_get_private(void); extern void* ofmem_arch_get_malloc_base(void); extern ucell ofmem_arch_get_heap_top(void); extern ucell ofmem_arch_get_virt_top(void); +extern phys_addr_t ofmem_arch_get_phys_top(void); extern retain_t* ofmem_arch_get_retained(void); extern int ofmem_arch_get_physaddr_cellsize(void); extern int ofmem_arch_encode_physaddr(ucell *p, phys_addr_t value); diff --git a/openbios-devel/libopenbios/ofmem_common.c b/openbios-devel/libopenbios/ofmem_common.c index 48b0b17..e93b938 100644 --- a/openbios-devel/libopenbios/ofmem_common.c +++ b/openbios-devel/libopenbios/ofmem_common.c @@ -354,7 +354,7 @@ static void ofmem_update_translations( void ) ofmem_t *ofmem = ofmem_arch_get_private();
ofmem_update_memory_available(s_phandle_memory, ofmem->phys_range, - &phys_range_prop, &phys_range_prop_size, &phys_range_prop_used, get_ram_size()); + &phys_range_prop, &phys_range_prop_size, &phys_range_prop_used, ofmem_arch_get_phys_top()); ofmem_update_memory_available(s_phandle_mmu, ofmem->virt_range, &virt_range_prop, &virt_range_prop_size, &virt_range_prop_used, -1ULL); ofmem_update_mmu_translations(); @@ -481,7 +481,7 @@ static ucell find_area( ucell align, ucell size, range_t *r, }
static phys_addr_t ofmem_claim_phys_( phys_addr_t phys, ucell size, ucell align, - ucell min, ucell max, int reverse ) + phys_addr_t min, phys_addr_t max, int reverse ) { ofmem_t *ofmem = ofmem_arch_get_private(); if( !align ) { @@ -511,7 +511,7 @@ phys_addr_t ofmem_claim_phys( phys_addr_t phys, ucell size, ucell align ) " align=" FMT_ucellx "\n", phys, size, align);
- return ofmem_claim_phys_( phys, size, align, 0, get_ram_size(), 0 ); + return ofmem_claim_phys_( phys, size, align, 0, ofmem_arch_get_phys_top(), 0 ); }
static ucell ofmem_claim_virt_( ucell virt, ucell size, ucell align, @@ -591,7 +591,7 @@ ucell ofmem_claim( ucell addr, ucell size, ucell align ) } else { if( align < 0x1000 ) align = 0x1000; - phys = ofmem_claim_phys_( addr, size, align, 0, get_ram_size(), 1 /* reverse */ ); + phys = ofmem_claim_phys_( addr, size, align, 0, ofmem_arch_get_phys_top(), 1 /* reverse */ ); virt = ofmem_claim_virt_( addr, size, align, 0, get_ram_size(), 1 /* reverse */ ); if( phys == -1 || virt == -1 ) { OFMEM_TRACE("ofmem_claim failed\n");
From: mcayland mcayland@f158a5a8-5612-0410-a976-696ce0be7e32
At the moment OFMEM allocates memory from the bottom of RAM upwards, however many loaders/kernels initialise themselves in lower memory areas which can cause them to be overwritten by subsequent memory allocations. Mimic the existing SPARC32 behaviour by allocating physical and virtual memory from the top of RAM downwards.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@siriusit.co.uk
git-svn-id: svn://openbios.org/openbios/trunk@996 f158a5a8-5612-0410-a976-696ce0be7e32 --- openbios-devel/libopenbios/ofmem_common.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/openbios-devel/libopenbios/ofmem_common.c b/openbios-devel/libopenbios/ofmem_common.c index e93b938..34caa2f 100644 --- a/openbios-devel/libopenbios/ofmem_common.c +++ b/openbios-devel/libopenbios/ofmem_common.c @@ -511,7 +511,7 @@ phys_addr_t ofmem_claim_phys( phys_addr_t phys, ucell size, ucell align ) " align=" FMT_ucellx "\n", phys, size, align);
- return ofmem_claim_phys_( phys, size, align, 0, ofmem_arch_get_phys_top(), 0 ); + return ofmem_claim_phys_( phys, size, align, 0, ofmem_arch_get_phys_top(), 1 ); }
static ucell ofmem_claim_virt_( ucell virt, ucell size, ucell align, @@ -544,7 +544,7 @@ ucell ofmem_claim_virt( ucell virt, ucell size, ucell align )
/* printk("+ ofmem_claim virt %08lx %lx %ld\n", virt, size, align ); */ return ofmem_claim_virt_( virt, size, align, - get_ram_size(), ofmem_arch_get_virt_top(), 0 ); + get_ram_size(), ofmem_arch_get_virt_top(), 1 ); }
/* if align != 0, phys is ignored. Returns -1 on error */
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@siriusit.co.uk --- openbios-devel/arch/sparc32/build.xml | 1 + openbios-devel/arch/sparc32/lib.c | 10 ++ openbios-devel/arch/sparc32/ofmem_sparc32.c | 135 +++++++++++++++++++++ openbios-devel/config/examples/sparc32_config.xml | 2 + 4 files changed, 148 insertions(+), 0 deletions(-) create mode 100644 openbios-devel/arch/sparc32/ofmem_sparc32.c
diff --git a/openbios-devel/arch/sparc32/build.xml b/openbios-devel/arch/sparc32/build.xml index 222dfb7..4db875f 100644 --- a/openbios-devel/arch/sparc32/build.xml +++ b/openbios-devel/arch/sparc32/build.xml @@ -15,6 +15,7 @@ <object source="udiv.S"/> <object source="linux_load.c"/> <object source="sys_info.c"/> + <object source="ofmem_sparc32.c"/> <object source="romvec.c"/> <object source="call-romvec.S"/> <object source="entry.S"/> diff --git a/openbios-devel/arch/sparc32/lib.c b/openbios-devel/arch/sparc32/lib.c index a30729f..10599ce 100644 --- a/openbios-devel/arch/sparc32/lib.c +++ b/openbios-devel/arch/sparc32/lib.c @@ -497,6 +497,16 @@ void obp_dumb_munmap(__attribute__((unused)) char *va, DPRINTF("obp_dumb_munmap: virta 0x%x, sz %d\n", (unsigned int)va, size); }
+void ofmem_arch_unmap_pages(ucell virt, ucell size) +{ + /* Currently do nothing */ +} + +void ofmem_arch_early_map_pages(phys_addr_t phys, ucell virt, ucell size, ucell mode) +{ + /* Currently do nothing */ +} + char *obp_dumb_memalloc(char *va, unsigned int size) { size = (size + 7) & ~7; diff --git a/openbios-devel/arch/sparc32/ofmem_sparc32.c b/openbios-devel/arch/sparc32/ofmem_sparc32.c new file mode 100644 index 0000000..2e6f7b5 --- /dev/null +++ b/openbios-devel/arch/sparc32/ofmem_sparc32.c @@ -0,0 +1,135 @@ +/* + * <ofmem_sparc32.c> + * + * OF Memory manager + * + * Copyright (C) 1999-2004 Samuel Rydh (samuel@ibrium.se) + * Copyright (C) 2004 Stefan Reinauer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libc/string.h" +#include "ofmem_sparc32.h" +#include "asm/asi.h" +#include "pgtsrmmu.h" + +#define OF_MALLOC_BASE ((char*)OFMEM + ALIGN_SIZE(sizeof(ofmem_t), 8)) + +/* Temporarily very small */ +#define MEMSIZE (1 * 1024) +static union { + char memory[MEMSIZE]; + ofmem_t ofmem; +} s_ofmem_data; + +#define OFMEM (&s_ofmem_data.ofmem) +#define TOP_OF_RAM (s_ofmem_data.memory + MEMSIZE) + +translation_t **g_ofmem_translations = &s_ofmem_data.ofmem.trans; + +extern uint32_t qemu_mem_size; + +static inline size_t ALIGN_SIZE(size_t x, size_t a) +{ + return (x + a - 1) & ~(a-1); +} + +static ucell get_heap_top( void ) +{ + return (ucell)TOP_OF_RAM; +} + +ofmem_t* ofmem_arch_get_private(void) +{ + return OFMEM; +} + +void* ofmem_arch_get_malloc_base(void) +{ + return OF_MALLOC_BASE; +} + +ucell ofmem_arch_get_heap_top(void) +{ + return get_heap_top(); +} + +ucell ofmem_arch_get_virt_top(void) +{ + return (ucell)TOP_OF_RAM; +} + +phys_addr_t ofmem_arch_get_phys_top(void) +{ + ofmem_t *ofmem = ofmem_arch_get_private(); + + return (uintptr_t)ofmem->ramsize - 0x1000000; +} + +retain_t *ofmem_arch_get_retained(void) +{ + /* Not used */ + return 0; +} + +int ofmem_arch_get_physaddr_cellsize(void) +{ + return 2; +} + +int ofmem_arch_encode_physaddr(ucell *p, phys_addr_t value) +{ + int n = 0; + + p[n++] = value >> 32; + p[n++] = value; + + return n; +} + +int ofmem_arch_get_translation_entry_size(void) +{ + /* Return size of a single MMU package translation property entry in cells */ + return 3; +} + +void ofmem_arch_create_translation_entry(ucell *transentry, translation_t *t) +{ + /* Generate translation property entry for SPARC. While there is no + formal documentation for this, both Linux kernel and OpenSolaris sources + expect a translation property entry to have the following layout: + + virtual address + length + mode + */ + + transentry[0] = t->virt; + transentry[1] = t->size; + transentry[2] = t->mode; +} + +/************************************************************************/ +/* misc */ +/************************************************************************/ + +ucell ofmem_arch_default_translation_mode( phys_addr_t phys ) +{ + return SRMMU_REF | SRMMU_CACHE | SRMMU_PRIV; +} + +/************************************************************************/ +/* init / cleanup */ +/************************************************************************/ + +void ofmem_init( void ) +{ + memset(&s_ofmem_data, 0, sizeof(s_ofmem_data)); + s_ofmem_data.ofmem.ramsize = qemu_mem_size; +} diff --git a/openbios-devel/config/examples/sparc32_config.xml b/openbios-devel/config/examples/sparc32_config.xml index 233bacb..ba4b7d7 100644 --- a/openbios-devel/config/examples/sparc32_config.xml +++ b/openbios-devel/config/examples/sparc32_config.xml @@ -26,6 +26,8 @@ <option name="CONFIG_DEBLOCKER" type="boolean" value="true"/> <option name="CONFIG_FONT_8X8" type="boolean" value="true"/> <option name="CONFIG_FONT_8X16" type="boolean" value="false"/> + <option name="CONFIG_OFMEM" type="boolean" value="true"/> + <option name="CONFIG_OFMEM_MALLOC_ALIGN" type="integer" value="8"/> <option name="CONFIG_LOADER_AOUT" type="boolean" value="true"/> <option name="CONFIG_LOADER_BOOTINFO" type="boolean" value="false"/> <option name="CONFIG_LOADER_ELF" type="boolean" value="true"/>
Since this memory is only being used by alloc-mem and free-mem then the majority of memory allocations will not actually be taken from this pool but from the C malloc()/free() implementations instead.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@siriusit.co.uk --- openbios-devel/arch/sparc32/ldscript | 4 ++-- openbios-devel/arch/sparc32/openbios.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/openbios-devel/arch/sparc32/ldscript b/openbios-devel/arch/sparc32/ldscript index a95ef68..da94a56 100644 --- a/openbios-devel/arch/sparc32/ldscript +++ b/openbios-devel/arch/sparc32/ldscript @@ -12,8 +12,8 @@ BASE_ADDR = 0xffd00000;
/* 16KB stack */ STACK_SIZE = 16384; -/* 256k general alloc + 256k Forth dictionary + 128k Forth memory */ -VMEM_SIZE = (256 + 256 + 128) * 1024; +/* 256k general alloc + 256k Forth dictionary + 16k Forth memory */ +VMEM_SIZE = (256 + 256 + 16) * 1024; IOMEM_SIZE = 256 * 1024 + 768 * 1024;
SECTIONS diff --git a/openbios-devel/arch/sparc32/openbios.c b/openbios-devel/arch/sparc32/openbios.c index 1c86752..1419468 100644 --- a/openbios-devel/arch/sparc32/openbios.c +++ b/openbios-devel/arch/sparc32/openbios.c @@ -26,7 +26,7 @@ #define NO_QEMU_PROTOS #include "arch/common/fw_cfg.h"
-#define MEMORY_SIZE (128*1024) /* 16K ram for hosted system */ +#define MEMORY_SIZE (16*1024) /* 16K ram for hosted system */ #define DICTIONARY_SIZE (256*1024) /* 256K for the dictionary */ #define UUID_FMT "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" #define FW_CFG_SUN4M_DEPTH (FW_CFG_ARCH_LOCAL + 0x00)
Currently the page tables only allow enough space for a 1.5MB image; however during testing/development it was useful to temporarily allow larger images for debugging. Note that if larger ROM sizes are required for testing, it is necessary to patch qemu to raise the hardcoded limit there too.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@siriusit.co.uk --- openbios-devel/arch/sparc32/entry.S | 52 ++++++++++++++++++++++++----------- 1 files changed, 36 insertions(+), 16 deletions(-)
diff --git a/openbios-devel/arch/sparc32/entry.S b/openbios-devel/arch/sparc32/entry.S index 3a4ce4e..9f5356c 100644 --- a/openbios-devel/arch/sparc32/entry.S +++ b/openbios-devel/arch/sparc32/entry.S @@ -38,15 +38,15 @@ * * Top +-------------------------+ * | SMP CPU table | - * | s + 0xf00 ... 0xf0f | - * | s + 0xf0c valid | - * | s + 0xf08 entry | - * | s + 0xf04 ctxtbl | - * | s + 0xf00 ctx | + * | s + 0x1f00 ... 0x1f0f | + * | s + 0x1f0c valid | + * | s + 0x1f08 entry | + * | s + 0x1f04 ctxtbl | + * | s + 0x1f00 ctx | * +-------------------------+ * | Bootstrap | - * | MMU L3 tables 5 * 0x100 | - * | s + 0xa00 ... 0xeff | + * | MMU L3 tables 8 * 0x100 | + * | s + 0xa00 ... 0x11ff | * +-------------------------+ * | Bootstrap | * | MMU L2 tables 2 * 0x100 | @@ -123,11 +123,12 @@ entry:
! Start of private memory in %g6 - set 0x1000, %g3 + set 0x2000, %g3 sub %g1, %g3, %g6
! Calculate SMP table location - add %g6, 0xf0c, %g2 ! valid? + set 0x1f0c, %g2 + add %g6, %g2, %g2 ! valid? lda [%g2] ASI_M_BYPASS, %g7 sta %g0, [%g2] ASI_M_BYPASS
@@ -168,17 +169,20 @@ entry:
load_ctx: ! SMP init, jump to user specified address - add %g6, 0xf04, %g5 ! ctxtbl + set 0x1f04, %g5 + add %g6, %g5, %g5 ! ctxtbl lda [%g5] ASI_M_BYPASS, %g2 sta %g0, [%g5] ASI_M_BYPASS set AC_M_CTPR, %g1 sta %g2, [%g1] ASI_M_MMUREGS ! set ctx table ptr - add %g6, 0xf00, %g5 ! ctx + set 0x1f00, %g5 + add %g6, %g5, %g5 ! ctx lda [%g5] ASI_M_BYPASS, %g2 sta %g0, [%g5] ASI_M_BYPASS set AC_M_CXR, %g1 sta %g2, [%g1] ASI_M_MMUREGS ! set context - add %g6, 0xf08, %g5 ! entry + set 0x1f08, %g5 + add %g6, %g5, %g5 ! entry lda [%g5] ASI_M_BYPASS, %g2 sta %g0, [%g5] ASI_M_BYPASS set 1, %g1 @@ -217,7 +221,7 @@ first_cpu: /* Create temporary page tables and map the ROM area to end of RAM. This will be done properly in iommu.c later. */ ! Calculate start of page tables etc. to %g6 - set 0x1000, %g4 + set 0x2000, %g4 sub %g1, %g4, %g6 ! start of private memory
mov %g6, %g2 ! ctx table at s+0x0 @@ -273,7 +277,22 @@ first_cpu: srl %g3, 0x4, %g3 or %g3, 0x1, %g3 sta %g3, [%g2] ASI_M_BYPASS - add %g2, 0xa00-0x9e0, %g2 ! s+0xa00 + add %g2, 4, %g2 ! s+0x9e4 + add %g2, 0xf00 - 0x9e4, %g3 ! 6th l3 table for rom at s+0xf00 + srl %g3, 0x4, %g3 + or %g3, 0x1, %g3 + sta %g3, [%g2] ASI_M_BYPASS + add %g2, 4, %g2 ! s+0x9e8 + add %g2, 0x1000 - 0x9e8, %g3 ! 7th l3 table for rom at s+0x1000 + srl %g3, 0x4, %g3 + or %g3, 0x1, %g3 + sta %g3, [%g2] ASI_M_BYPASS + add %g2, 4, %g2 ! s+0x9ec + add %g2, 0x1100 - 0x9ec, %g3 ! 8th l3 table for rom at s+0x1100 + srl %g3, 0x4, %g3 + or %g3, 0x1, %g3 + sta %g3, [%g2] ASI_M_BYPASS + add %g2, 0xa00-0x9ec, %g2 ! s+0xa00
/* Use end of ram for code, rodata, data, and bss sections. SunOS wants to write to trap table... */ @@ -282,6 +301,7 @@ first_cpu: sub %g6, %g4, %g6 sub %g1, %g6, %g3 set 0x1000, %g5 + sub %g3, %g5, %g3 sub %g3, %g5, %g3 ! start of ROM copy mov %g3, %g7 ! save in %g7 srl %g6, 12, %g6 ! # of all pages @@ -311,7 +331,7 @@ first_cpu: bl 1b add %g4, 0x4, %g4
- set 0x1000, %g3 + set 0x2000, %g3 sub %g6, %g3, %g7 ! ctx table at s+0x0 set AC_M_CTPR, %g2 srl %g7, 4, %g7 @@ -360,7 +380,7 @@ highmem: set _start, %o2 sub %o0, %o2, %o0 sub %g6, %o0, %o0 - set 0x1000, %o1 + set 0x2000, %o1 sub %o0, %o1, %o0 ! start of ROM copy sub %o2, %o0, %o0 ! start of ROM copy set va_shift, %g1
This requires a corresponding increase in the memory allocated to OFMEM in order to store the page tables.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@siriusit.co.uk --- openbios-devel/arch/sparc32/lib.c | 8 ++++---- openbios-devel/arch/sparc32/ofmem_sparc32.c | 3 +-- 2 files changed, 5 insertions(+), 6 deletions(-)
diff --git a/openbios-devel/arch/sparc32/lib.c b/openbios-devel/arch/sparc32/lib.c index 10599ce..788d6f5 100644 --- a/openbios-devel/arch/sparc32/lib.c +++ b/openbios-devel/arch/sparc32/lib.c @@ -273,7 +273,7 @@ find_pte(unsigned long va, int alloc) 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), + ret = ofmem_posix_memalign(&p, SRMMU_PTRS_PER_PMD * sizeof(int), SRMMU_PTRS_PER_PMD * sizeof(int)); if (ret != 0) return ret; @@ -290,7 +290,7 @@ find_pte(unsigned long va, int alloc) 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 *), + ret = ofmem_posix_memalign(&p, SRMMU_PTRS_PER_PTE * sizeof(void *), SRMMU_PTRS_PER_PTE * sizeof(void *)); if (ret != 0) return ret; @@ -602,9 +602,9 @@ init_mmu_swift(void) mem_init(&cmem, (char *) &_vmem, (char *)&_evmem); mem_init(&cio, (char *)&_end, (char *)&_iomem);
- posix_memalign((void *)&context_table, NCTX_SWIFT * sizeof(int), + ofmem_posix_memalign((void *)&context_table, NCTX_SWIFT * sizeof(int), NCTX_SWIFT * sizeof(int)); - posix_memalign((void *)&l1, 256 * sizeof(int), 256 * sizeof(int)); + ofmem_posix_memalign((void *)&l1, 256 * sizeof(int), 256 * sizeof(int));
context_table[0] = (((unsigned long)va2pa((unsigned long)l1)) >> 4) | SRMMU_ET_PTD; diff --git a/openbios-devel/arch/sparc32/ofmem_sparc32.c b/openbios-devel/arch/sparc32/ofmem_sparc32.c index 2e6f7b5..6484be9 100644 --- a/openbios-devel/arch/sparc32/ofmem_sparc32.c +++ b/openbios-devel/arch/sparc32/ofmem_sparc32.c @@ -21,8 +21,7 @@
#define OF_MALLOC_BASE ((char*)OFMEM + ALIGN_SIZE(sizeof(ofmem_t), 8))
-/* Temporarily very small */ -#define MEMSIZE (1 * 1024) +#define MEMSIZE (256 * 1024) static union { char memory[MEMSIZE]; ofmem_t ofmem;
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@siriusit.co.uk --- openbios-devel/arch/sparc32/lib.c | 15 --------------- openbios-devel/drivers/iommu.c | 4 ++-- openbios-devel/include/libc/stdlib.h | 1 - 3 files changed, 2 insertions(+), 18 deletions(-)
diff --git a/openbios-devel/arch/sparc32/lib.c b/openbios-devel/arch/sparc32/lib.c index 788d6f5..a5ad8ca 100644 --- a/openbios-devel/arch/sparc32/lib.c +++ b/openbios-devel/arch/sparc32/lib.c @@ -216,21 +216,6 @@ realloc( void *ptr, size_t size ) 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. */ diff --git a/openbios-devel/drivers/iommu.c b/openbios-devel/drivers/iommu.c index 019f8b7..716d01e 100644 --- a/openbios-devel/drivers/iommu.c +++ b/openbios-devel/drivers/iommu.c @@ -53,7 +53,7 @@ dvma_alloc(int size, unsigned int *pphys) int ret;
npages = (size + (PAGE_SIZE-1)) / PAGE_SIZE; - ret = posix_memalign(&va, npages * PAGE_SIZE, PAGE_SIZE); + ret = ofmem_posix_memalign(&va, npages * PAGE_SIZE, PAGE_SIZE); if (ret != 0) return NULL;
@@ -132,7 +132,7 @@ iommu_init(struct iommu *t, uint64_t base) /* Allocate IOMMU page table */ /* Tremendous alignment causes great waste... */ ptsize = (vasize / PAGE_SIZE) * sizeof(int); - ret = posix_memalign((void *)&ptab, ptsize, ptsize); + ret = ofmem_posix_memalign((void *)&ptab, ptsize, ptsize); if (ret != 0) { DPRINTF("Cannot allocate IOMMU table [0x%x]\n", ptsize); for (;;) { } diff --git a/openbios-devel/include/libc/stdlib.h b/openbios-devel/include/libc/stdlib.h index 4059db2..ef08838 100644 --- a/openbios-devel/include/libc/stdlib.h +++ b/openbios-devel/include/libc/stdlib.h @@ -19,7 +19,6 @@ 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*));
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@siriusit.co.uk --- openbios-devel/arch/sparc32/openbios.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/openbios-devel/arch/sparc32/openbios.c b/openbios-devel/arch/sparc32/openbios.c index 1419468..c940a5f 100644 --- a/openbios-devel/arch/sparc32/openbios.c +++ b/openbios-devel/arch/sparc32/openbios.c @@ -25,6 +25,7 @@ #include "packages/video.h" #define NO_QEMU_PROTOS #include "arch/common/fw_cfg.h" +#include "libopenbios/ofmem.h"
#define MEMORY_SIZE (16*1024) /* 16K ram for hosted system */ #define DICTIONARY_SIZE (256*1024) /* 256K for the dictionary */ @@ -946,6 +947,9 @@ int openbios(void) if (!hwdef) for(;;); // Internal inconsistency, hang
+ /* Make sure we setup OFMEM before the MMU as we need malloc() to setup page tables */ + ofmem_init(); + #ifdef CONFIG_DRIVER_SBUS init_mmu_swift(); #endif
Also juggle the memory to take into account that the allocations are coming from OFMEM, and remove posix_memalign2() since it is no longer required.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@siriusit.co.uk --- openbios-devel/arch/sparc32/ldscript | 3 +- openbios-devel/arch/sparc32/lib.c | 124 +++------------------------ openbios-devel/arch/sparc32/ofmem_sparc32.c | 2 +- 3 files changed, 13 insertions(+), 116 deletions(-)
diff --git a/openbios-devel/arch/sparc32/ldscript b/openbios-devel/arch/sparc32/ldscript index da94a56..32c9445 100644 --- a/openbios-devel/arch/sparc32/ldscript +++ b/openbios-devel/arch/sparc32/ldscript @@ -12,8 +12,7 @@ BASE_ADDR = 0xffd00000;
/* 16KB stack */ STACK_SIZE = 16384; -/* 256k general alloc + 256k Forth dictionary + 16k Forth memory */ -VMEM_SIZE = (256 + 256 + 16) * 1024; +VMEM_SIZE = 128 * 1024; IOMEM_SIZE = 256 * 1024 + 768 * 1024;
SECTIONS diff --git a/openbios-devel/arch/sparc32/lib.c b/openbios-devel/arch/sparc32/lib.c index a5ad8ca..010b7b6 100644 --- a/openbios-devel/arch/sparc32/lib.c +++ b/openbios-devel/arch/sparc32/lib.c @@ -75,18 +75,6 @@ struct linux_mlist_v0 *ptphys; struct linux_mlist_v0 *ptmap; struct linux_mlist_v0 *ptavail;
-static struct { - char *next_malloc; - int left; - alloc_desc_t *mfree; /* list of free malloc blocks */ - - range_t *phys_range; - range_t *virt_range; - - translation_t *trans; /* this is really a translation_t */ -} ofmem; -#define ALLOC_BLOCK (64 * 1024) - /* Private functions for mapping between physical/virtual addresses */ phys_addr_t va2pa(unsigned long va) @@ -108,112 +96,22 @@ pa2va(phys_addr_t pa) return pa; }
-// XXX should be posix_memalign -static int -posix_memalign2(void **memptr, size_t alignment, size_t size) -{ - alloc_desc_t *d, **pp; - char *ret; - - if( !size ) - return -1; - - size = (size + (alignment - 1)) & ~(alignment - 1); - size += sizeof(alloc_desc_t); - - /* look in the freelist */ - for( pp=&ofmem.mfree; *pp && (**pp).size < size; pp = &(**pp).next ) - ; - - /* waste at most 4K by taking an entry from the freelist */ - if( *pp && (**pp).size < size + 0x1000 ) { - ret = (char*)*pp + sizeof(alloc_desc_t); - memset( ret, 0, (**pp).size - sizeof(alloc_desc_t) ); - *pp = (**pp).next; - *memptr = ret; - return 0; - } - - if( !ofmem.next_malloc || ofmem.left < size) { - unsigned long alloc_size = ALLOC_BLOCK; - if (size > ALLOC_BLOCK) - alloc_size = size; - // Recover possible leftover - if ((size_t)ofmem.left > sizeof(alloc_desc_t) + 4) { - alloc_desc_t *d_leftover; - - d_leftover = (alloc_desc_t*)ofmem.next_malloc; - d_leftover->size = ofmem.left - sizeof(alloc_desc_t); - free((void *)((unsigned long)d_leftover + - sizeof(alloc_desc_t))); - } - - 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 -1; - } - d = (alloc_desc_t*) ofmem.next_malloc; - ofmem.next_malloc += size; - ofmem.left -= size; - - d->next = NULL; - d->size = size; - - ret = (char*)d + sizeof(alloc_desc_t); - memset( ret, 0, size - sizeof(alloc_desc_t) ); - *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) +void * +malloc(int size) { - alloc_desc_t **pp, *d; - - /* it is legal to free NULL pointers (size zero allocations) */ - if( !ptr ) - return; - - d = (alloc_desc_t*)((unsigned long)ptr - sizeof(alloc_desc_t)); - d->next = ofmem.mfree; - - /* insert in the (sorted) freelist */ - for( pp=&ofmem.mfree; *pp && (**pp).size < d->size ; pp = &(**pp).next ) - ; - d->next = *pp; - *pp = d; + return ofmem_malloc(size); } - + void * realloc( void *ptr, size_t size ) { - alloc_desc_t *d = (alloc_desc_t*)((unsigned long)ptr - sizeof(alloc_desc_t)); - char *p; - - if( !ptr ) - return malloc( size ); - if( !size ) { - free( ptr ); - return NULL; - } - p = malloc( size ); - memcpy( p, ptr, MIN(d->size - sizeof(alloc_desc_t),size) ); - free( ptr ); - return p; + return ofmem_realloc(ptr, size); +} + +void +free(void *ptr) +{ + ofmem_free(ptr); }
/* diff --git a/openbios-devel/arch/sparc32/ofmem_sparc32.c b/openbios-devel/arch/sparc32/ofmem_sparc32.c index 6484be9..8c21f9b 100644 --- a/openbios-devel/arch/sparc32/ofmem_sparc32.c +++ b/openbios-devel/arch/sparc32/ofmem_sparc32.c @@ -21,7 +21,7 @@
#define OF_MALLOC_BASE ((char*)OFMEM + ALIGN_SIZE(sizeof(ofmem_t), 8))
-#define MEMSIZE (256 * 1024) +#define MEMSIZE (512 * 1024) static union { char memory[MEMSIZE]; ofmem_t ofmem;
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@siriusit.co.uk --- openbios-devel/arch/sparc32/lib.c | 77 +++++++++++--------------- openbios-devel/arch/sparc32/ofmem_sparc32.c | 2 +- openbios-devel/drivers/iommu.c | 6 +-- openbios-devel/include/libopenbios/ofmem.h | 2 +- 4 files changed, 36 insertions(+), 51 deletions(-)
diff --git a/openbios-devel/arch/sparc32/lib.c b/openbios-devel/arch/sparc32/lib.c index 010b7b6..d5faab3 100644 --- a/openbios-devel/arch/sparc32/lib.c +++ b/openbios-devel/arch/sparc32/lib.c @@ -190,49 +190,41 @@ find_pte(unsigned long va, int alloc) return pa2va(pa); }
-/* - * Create a memory mapping from va to epa. - */ -int -map_page(unsigned long va, uint64_t epa, int type) +void +map_pages(phys_addr_t phys, unsigned long virt, + unsigned long size, unsigned long mode) { + unsigned long npages, off; uint32_t pte; unsigned long pa;
- pa = find_pte(va, 1); + DPRINTF("map_pages: va 0x%lx, pa 0x%llx, size 0x%lx\n", virt, phys, size);
- 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); + off = phys & (PAGE_SIZE - 1); + npages = (off + (size - 1) + (PAGE_SIZE - 1)) / PAGE_SIZE; + phys &= ~(uint64_t)(PAGE_SIZE - 1);
- return 0; -} + while (npages-- != 0) { + pa = find_pte(virt, 1);
-static void map_pages(unsigned long va, uint64_t pa, int type, - unsigned long size) -{ - unsigned long npages, off; + pte = SRMMU_ET_PTE | ((phys & PAGE_MASK) >> 4);
- DPRINTF("map_pages: va 0x%lx, pa 0x%llx, size 0x%lx\n", va, pa, size); + if (mode) { /* 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 */ + }
- off = pa & (PAGE_SIZE - 1); - npages = (off + (size - 1) + (PAGE_SIZE - 1)) / PAGE_SIZE; - pa &= ~(uint64_t)(PAGE_SIZE - 1); + *(uint32_t *)pa = pte;
- while (npages-- != 0) { - map_page(va, pa, type); - va += PAGE_SIZE; - pa += PAGE_SIZE; + virt += PAGE_SIZE; + phys += PAGE_SIZE; } } + /* * Create an I/O mapping to pa[size]. * Returns va of the mapping or 0 if unsuccessful. @@ -252,7 +244,7 @@ map_io(uint64_t pa, int size) if (va == 0) return NULL;
- map_pages(va, pa, 1, npages * PAGE_SIZE); + map_pages(pa, va, npages * PAGE_SIZE, 1); return (void *)(va + off); }
@@ -312,7 +304,7 @@ ob_map_pages(void) pa <<= 32; pa |= POP() & 0xffffffff;
- map_pages(va, pa, 0, size); + map_pages(pa, va, size, 0); DPRINTF("map-page: va 0x%lx pa 0x%llx size 0x%x\n", va, pa, size); }
@@ -370,7 +362,7 @@ char *obp_dumb_mmap(char *va, int which_io, unsigned int pa, { uint64_t mpa = ((uint64_t)which_io << 32) | (uint64_t)pa;
- map_pages((unsigned long)va, mpa, 0, size); + map_pages(mpa, (unsigned long)va, size, 0); return va; }
@@ -410,7 +402,7 @@ char *obp_dumb_memalloc(char *va, unsigned int size) DPRINTF("obp_dumb_memalloc req null -> 0x%p\n", va); }
- map_pages((unsigned long)va, totavail[0].num_bytes, 0, size); + map_pages(totavail[0].num_bytes, (unsigned long)va, size, 0);
update_memory_properties();
@@ -481,7 +473,8 @@ init_mmu_swift(void) { unsigned int addr, i; unsigned long pa, va; - + int size; + mem_init(&cmem, (char *) &_vmem, (char *)&_evmem); mem_init(&cio, (char *)&_end, (char *)&_iomem);
@@ -501,16 +494,12 @@ init_mmu_swift(void)
// 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); - } + size = (unsigned long)&_end - (unsigned long)&_start; + pa = va2pa(va); + map_pages(pa, va, size, 0);
// 1:1 mapping for RAM - pa = va = 0; - for (; va < LOWMEMSZ; va += PAGE_SIZE, pa += PAGE_SIZE) { - map_page(va, pa, 0); - } + map_pages(0, 0, LOWMEMSZ, 0);
/* * Flush cache diff --git a/openbios-devel/arch/sparc32/ofmem_sparc32.c b/openbios-devel/arch/sparc32/ofmem_sparc32.c index 8c21f9b..030d62d 100644 --- a/openbios-devel/arch/sparc32/ofmem_sparc32.c +++ b/openbios-devel/arch/sparc32/ofmem_sparc32.c @@ -15,7 +15,7 @@ #include "config.h" #include "libopenbios/bindings.h" #include "libc/string.h" -#include "ofmem_sparc32.h" +#include "libopenbios/ofmem.h" #include "asm/asi.h" #include "pgtsrmmu.h"
diff --git a/openbios-devel/drivers/iommu.c b/openbios-devel/drivers/iommu.c index 716d01e..bf3c887 100644 --- a/openbios-devel/drivers/iommu.c +++ b/openbios-devel/drivers/iommu.c @@ -68,11 +68,7 @@ dvma_alloc(int size, unsigned int *pphys) */ mva = (unsigned int) va; mpa = (unsigned int) pa; - for (i = 0; i < npages; i++) { - map_page(mva, mpa, 1); - mva += PAGE_SIZE; - mpa += PAGE_SIZE; - } + map_pages(mpa, mva, npages * PAGE_SIZE, 1);
/* * Map into IOMMU page table. diff --git a/openbios-devel/include/libopenbios/ofmem.h b/openbios-devel/include/libopenbios/ofmem.h index 54868e2..2766a95 100644 --- a/openbios-devel/include/libopenbios/ofmem.h +++ b/openbios-devel/include/libopenbios/ofmem.h @@ -129,7 +129,7 @@ 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_pages(phys_addr_t phys, unsigned long virt, unsigned long size, unsigned long mode); void *map_io(uint64_t pa, int size); #endif
Once this is in place, we can switch SPARC32's map_pages() over to use the MMU mode directly to bring it in line with the existing OFMEM API.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@siriusit.co.uk --- openbios-devel/arch/ppc/qemu/ofmem.c | 4 ++++ openbios-devel/arch/sparc32/lib.c | 22 +++++++--------------- openbios-devel/arch/sparc32/ofmem_sparc32.c | 5 +++++ openbios-devel/arch/sparc64/ofmem_sparc64.c | 7 +++++-- openbios-devel/drivers/iommu.c | 2 +- openbios-devel/include/libopenbios/ofmem.h | 1 + 6 files changed, 23 insertions(+), 18 deletions(-)
diff --git a/openbios-devel/arch/ppc/qemu/ofmem.c b/openbios-devel/arch/ppc/qemu/ofmem.c index c0143a4..80fad75 100644 --- a/openbios-devel/arch/ppc/qemu/ofmem.c +++ b/openbios-devel/arch/ppc/qemu/ofmem.c @@ -239,6 +239,10 @@ ucell ofmem_arch_default_translation_mode(phys_addr_t phys) return 0x6a; /* WIm GxPp, I/O */ }
+ucell ofmem_arch_io_translation_mode(phys_addr_t phys) +{ + return 0x6a; /* WIm GxPp, I/O */ +}
/************************************************************************/ /* page fault handler */ diff --git a/openbios-devel/arch/sparc32/lib.c b/openbios-devel/arch/sparc32/lib.c index d5faab3..6847b36 100644 --- a/openbios-devel/arch/sparc32/lib.c +++ b/openbios-devel/arch/sparc32/lib.c @@ -208,15 +208,7 @@ map_pages(phys_addr_t phys, unsigned long virt, pa = find_pte(virt, 1);
pte = SRMMU_ET_PTE | ((phys & PAGE_MASK) >> 4); - - if (mode) { /* 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 */ - } + pte |= mode;
*(uint32_t *)pa = pte;
@@ -244,7 +236,7 @@ map_io(uint64_t pa, int size) if (va == 0) return NULL;
- map_pages(pa, va, npages * PAGE_SIZE, 1); + map_pages(pa, va, npages * PAGE_SIZE, ofmem_arch_io_translation_mode(pa)); return (void *)(va + off); }
@@ -304,7 +296,7 @@ ob_map_pages(void) pa <<= 32; pa |= POP() & 0xffffffff;
- map_pages(pa, va, size, 0); + map_pages(pa, va, size, ofmem_arch_default_translation_mode(pa)); DPRINTF("map-page: va 0x%lx pa 0x%llx size 0x%x\n", va, pa, size); }
@@ -362,7 +354,7 @@ char *obp_dumb_mmap(char *va, int which_io, unsigned int pa, { uint64_t mpa = ((uint64_t)which_io << 32) | (uint64_t)pa;
- map_pages(mpa, (unsigned long)va, size, 0); + map_pages(mpa, (unsigned long)va, size, ofmem_arch_default_translation_mode(mpa)); return va; }
@@ -402,7 +394,7 @@ char *obp_dumb_memalloc(char *va, unsigned int size) DPRINTF("obp_dumb_memalloc req null -> 0x%p\n", va); }
- map_pages(totavail[0].num_bytes, (unsigned long)va, size, 0); + map_pages(totavail[0].num_bytes, (unsigned long)va, size, ofmem_arch_default_translation_mode(totavail[0].num_bytes));
update_memory_properties();
@@ -496,10 +488,10 @@ init_mmu_swift(void) va = (unsigned long)&_start; size = (unsigned long)&_end - (unsigned long)&_start; pa = va2pa(va); - map_pages(pa, va, size, 0); + map_pages(pa, va, size, ofmem_arch_default_translation_mode(pa));
// 1:1 mapping for RAM - map_pages(0, 0, LOWMEMSZ, 0); + map_pages(0, 0, LOWMEMSZ, ofmem_arch_default_translation_mode(0));
/* * Flush cache diff --git a/openbios-devel/arch/sparc32/ofmem_sparc32.c b/openbios-devel/arch/sparc32/ofmem_sparc32.c index 030d62d..bd6f69b 100644 --- a/openbios-devel/arch/sparc32/ofmem_sparc32.c +++ b/openbios-devel/arch/sparc32/ofmem_sparc32.c @@ -123,6 +123,11 @@ ucell ofmem_arch_default_translation_mode( phys_addr_t phys ) return SRMMU_REF | SRMMU_CACHE | SRMMU_PRIV; }
+ucell ofmem_arch_io_translation_mode( phys_addr_t phys ) +{ + return SRMMU_REF | SRMMU_PRIV; +} + /************************************************************************/ /* init / cleanup */ /************************************************************************/ diff --git a/openbios-devel/arch/sparc64/ofmem_sparc64.c b/openbios-devel/arch/sparc64/ofmem_sparc64.c index 0ec8632..6a4fb5e 100644 --- a/openbios-devel/arch/sparc64/ofmem_sparc64.c +++ b/openbios-devel/arch/sparc64/ofmem_sparc64.c @@ -120,8 +120,11 @@ ucell ofmem_arch_default_translation_mode( phys_addr_t phys ) return SPITFIRE_TTE_CP | SPITFIRE_TTE_CV | SPITFIRE_TTE_WRITABLE; }
- - +ucell ofmem_arch_io_translation_mode( phys_addr_t phys ) +{ + /* Writable, not privileged and not locked */ + return SPITFIRE_TTE_CV | SPITFIRE_TTE_WRITABLE; +}
/************************************************************************/ /* init / cleanup */ diff --git a/openbios-devel/drivers/iommu.c b/openbios-devel/drivers/iommu.c index bf3c887..6af5b33 100644 --- a/openbios-devel/drivers/iommu.c +++ b/openbios-devel/drivers/iommu.c @@ -68,7 +68,7 @@ dvma_alloc(int size, unsigned int *pphys) */ mva = (unsigned int) va; mpa = (unsigned int) pa; - map_pages(mpa, mva, npages * PAGE_SIZE, 1); + map_pages(mpa, mva, npages * PAGE_SIZE, ofmem_arch_io_translation_mode(mpa));
/* * Map into IOMMU page table. diff --git a/openbios-devel/include/libopenbios/ofmem.h b/openbios-devel/include/libopenbios/ofmem.h index 2766a95..e350dec 100644 --- a/openbios-devel/include/libopenbios/ofmem.h +++ b/openbios-devel/include/libopenbios/ofmem.h @@ -69,6 +69,7 @@ extern int ofmem_arch_encode_physaddr(ucell *p, phys_addr_t value); extern int ofmem_arch_get_translation_entry_size(void); extern void ofmem_arch_create_translation_entry(ucell *transentry, translation_t *t); extern ucell ofmem_arch_default_translation_mode( phys_addr_t phys ); +extern ucell ofmem_arch_io_translation_mode( phys_addr_t phys ); extern void ofmem_arch_early_map_pages(phys_addr_t phys, ucell virt, ucell size, ucell mode); extern void ofmem_arch_unmap_pages(ucell virt, ucell size);
As a consequence we need to maintain a separate I/O range within OFMEM, and add management functions similar to those that exist for the virtual and physical ranges. At the same time, we introduce a couple of new OFMEM arch functions called ofmem_arch_get_iomem_base() and ofmem_arch_get_iomem_top() to control the range of allocatable I/O memory which is again similar to the existing method used for the virtual and physical ranges.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@siriusit.co.uk --- openbios-devel/arch/ppc/qemu/ofmem.c | 12 ++++++ openbios-devel/arch/sparc32/ofmem_sparc32.c | 10 +++++ openbios-devel/arch/sparc64/ofmem_sparc64.c | 12 ++++++ openbios-devel/include/libopenbios/ofmem.h | 11 ++++-- openbios-devel/libopenbios/ofmem_common.c | 52 +++++++++++++++++++++++++++ 5 files changed, 94 insertions(+), 3 deletions(-)
diff --git a/openbios-devel/arch/ppc/qemu/ofmem.c b/openbios-devel/arch/ppc/qemu/ofmem.c index 80fad75..4c6825e 100644 --- a/openbios-devel/arch/ppc/qemu/ofmem.c +++ b/openbios-devel/arch/ppc/qemu/ofmem.c @@ -132,6 +132,18 @@ void ofmem_arch_early_map_pages(phys_addr_t phys, ucell virt, ucell size, ucell /* none yet */ }
+ucell ofmem_arch_get_iomem_base(void) +{ + /* Currently unused */ + return 0; +} + +ucell ofmem_arch_get_iomem_top(void) +{ + /* Currently unused */ + return 0; +} + retain_t *ofmem_arch_get_retained(void) { /* not implemented */ diff --git a/openbios-devel/arch/sparc32/ofmem_sparc32.c b/openbios-devel/arch/sparc32/ofmem_sparc32.c index bd6f69b..83f22b5 100644 --- a/openbios-devel/arch/sparc32/ofmem_sparc32.c +++ b/openbios-devel/arch/sparc32/ofmem_sparc32.c @@ -71,6 +71,16 @@ phys_addr_t ofmem_arch_get_phys_top(void) return (uintptr_t)ofmem->ramsize - 0x1000000; }
+ucell ofmem_arch_get_iomem_base(void) +{ + return pointer2cell(&_end); +} + +ucell ofmem_arch_get_iomem_top(void) +{ + return pointer2cell(&_iomem); +} + retain_t *ofmem_arch_get_retained(void) { /* Not used */ diff --git a/openbios-devel/arch/sparc64/ofmem_sparc64.c b/openbios-devel/arch/sparc64/ofmem_sparc64.c index 6a4fb5e..1655978 100644 --- a/openbios-devel/arch/sparc64/ofmem_sparc64.c +++ b/openbios-devel/arch/sparc64/ofmem_sparc64.c @@ -70,6 +70,18 @@ phys_addr_t ofmem_arch_get_phys_top(void) return ofmem->ramsize; }
+ucell ofmem_arch_get_iomem_base(void) +{ + /* Currently unused */ + return 0; +} + +ucell ofmem_arch_get_iomem_top(void) +{ + /* Currently unused */ + return 0; +} + retain_t *ofmem_arch_get_retained(void) { /* Retained area is at the top of physical RAM */ diff --git a/openbios-devel/include/libopenbios/ofmem.h b/openbios-devel/include/libopenbios/ofmem.h index e350dec..fa37146 100644 --- a/openbios-devel/include/libopenbios/ofmem.h +++ b/openbios-devel/include/libopenbios/ofmem.h @@ -46,7 +46,8 @@ typedef struct {
range_t *phys_range; range_t *virt_range; - + range_t *io_range; + translation_t *trans; /* this is really a translation_t */ } ofmem_t;
@@ -63,6 +64,8 @@ extern void* ofmem_arch_get_malloc_base(void); extern ucell ofmem_arch_get_heap_top(void); extern ucell ofmem_arch_get_virt_top(void); extern phys_addr_t ofmem_arch_get_phys_top(void); +extern ucell ofmem_arch_get_iomem_base(void); +extern ucell ofmem_arch_get_iomem_top(void); extern retain_t* ofmem_arch_get_retained(void); extern int ofmem_arch_get_physaddr_cellsize(void); extern int ofmem_arch_encode_physaddr(ucell *p, phys_addr_t value); @@ -104,25 +107,27 @@ extern void ofmem_register( phandle_t ph_memory, phandle_t ph_mmu ); extern ucell ofmem_claim( ucell addr, ucell size, ucell align ); extern phys_addr_t ofmem_claim_phys( phys_addr_t mphys, ucell size, ucell align ); extern ucell ofmem_claim_virt( ucell mvirt, ucell size, ucell align ); +extern ucell ofmem_claim_io( ucell virt, ucell size, ucell align );
extern phys_addr_t ofmem_retain( phys_addr_t phys, ucell size, ucell align );
extern int ofmem_map( phys_addr_t phys, ucell virt, ucell size, ucell mode ); extern int ofmem_unmap( ucell virt, ucell size ); +extern ucell ofmem_map_io( phys_addr_t phys, ucell size );
extern void ofmem_release( ucell virt, ucell size ); extern void ofmem_release_phys( phys_addr_t phys, ucell size ); extern void ofmem_release_virt( ucell virt, ucell size ); extern phys_addr_t ofmem_translate( ucell virt, ucell *ret_mode );
-#ifdef CONFIG_PPC +/* Currently the same for all architectures */ #define PAGE_SHIFT 12
+#ifdef CONFIG_PPC unsigned long get_ram_top( void ); unsigned long get_ram_bottom( void );
#elif defined(CONFIG_SPARC32) -#define PAGE_SHIFT 12
/* arch/sparc32/lib.c */ struct mem; diff --git a/openbios-devel/libopenbios/ofmem_common.c b/openbios-devel/libopenbios/ofmem_common.c index 34caa2f..f1394af 100644 --- a/openbios-devel/libopenbios/ofmem_common.c +++ b/openbios-devel/libopenbios/ofmem_common.c @@ -547,6 +547,35 @@ ucell ofmem_claim_virt( ucell virt, ucell size, ucell align ) get_ram_size(), ofmem_arch_get_virt_top(), 1 ); }
+static ucell ofmem_claim_io_( ucell virt, ucell size, ucell align, + ucell min, ucell max, int reverse ) +{ + ofmem_t *ofmem = ofmem_arch_get_private(); + if( !align ) { + if( !is_free( virt, size, ofmem->io_range ) ) { + OFMEM_TRACE("Non-free I/O memory claimed!\n"); + return -1; + } + add_entry( virt, size, &ofmem->io_range ); + return virt; + } + + virt = find_area( align, size, ofmem->io_range, min, max, reverse ); + if( virt == -1 ) { + printk("ofmem_claim_io - out of space (failed request for " FMT_ucellx " bytes)\n", size); + return -1; + } + add_entry( virt, size, &ofmem->io_range ); + return virt; +} + +ucell ofmem_claim_io( ucell virt, ucell size, ucell align ) +{ + /* Claim a section of memory from the I/O range */ + return ofmem_claim_io_( virt, size, align, + ofmem_arch_get_iomem_base(), ofmem_arch_get_iomem_top(), 0 ); +} + /* if align != 0, phys is ignored. Returns -1 on error */ phys_addr_t ofmem_retain( phys_addr_t phys, ucell size, ucell align ) { @@ -793,6 +822,29 @@ int ofmem_unmap( ucell virt, ucell size ) return 0; }
+ucell ofmem_map_io( phys_addr_t phys, ucell size ) +{ + /* Claim virtual memory from the I/O range and map the page-aligned + physical address phys to it, returning the newly allocated + virtual address */ + ucell virt, mode; + phys_addr_t off; + int npages; + + off = phys & (PAGE_SIZE - 1); + npages = (off + size - 1) / PAGE_SIZE + 1; + phys &= ~(PAGE_SIZE - 1); + + virt = ofmem_claim_io(-1, npages * PAGE_SIZE, PAGE_SIZE); + + mode = ofmem_arch_io_translation_mode(off); + + ofmem_map_page_range(phys, virt, npages * PAGE_SIZE, mode); + ofmem_arch_early_map_pages(phys, virt, npages * PAGE_SIZE, mode); + + return (virt + off); +} + /* virtual -> physical. */ phys_addr_t ofmem_translate( ucell virt, ucell *mode ) {
The old map_io() function can now be removed. Also fill in ofmem_arch_early_map_pages() on SPARC32 which is required for ofmem_map_io() to work correctly.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@siriusit.co.uk --- openbios-devel/arch/sparc32/console.c | 4 ++-- openbios-devel/arch/sparc32/lib.c | 25 +------------------------ openbios-devel/drivers/escc.c | 4 ++-- openbios-devel/drivers/esp.c | 4 ++-- openbios-devel/drivers/fw_cfg.c | 2 +- openbios-devel/drivers/iommu.c | 2 +- openbios-devel/drivers/obio.c | 10 +++++----- openbios-devel/drivers/sbus.c | 2 +- openbios-devel/include/libopenbios/ofmem.h | 1 - 9 files changed, 15 insertions(+), 39 deletions(-)
diff --git a/openbios-devel/arch/sparc32/console.c b/openbios-devel/arch/sparc32/console.c index 52e4827..2bcdf02 100644 --- a/openbios-devel/arch/sparc32/console.c +++ b/openbios-devel/arch/sparc32/console.c @@ -46,8 +46,8 @@ static void video_cls(void)
void tcx_init(uint64_t base) { - vmem = map_io(base + VMEM_BASE, VMEM_SIZE); - dac = map_io(base + DAC_BASE, DAC_SIZE); + vmem = (unsigned char *)ofmem_map_io(base + VMEM_BASE, VMEM_SIZE); + dac = (uint32_t *)ofmem_map_io(base + DAC_BASE, DAC_SIZE);
console_init(); } diff --git a/openbios-devel/arch/sparc32/lib.c b/openbios-devel/arch/sparc32/lib.c index 6847b36..74ac5e7 100644 --- a/openbios-devel/arch/sparc32/lib.c +++ b/openbios-devel/arch/sparc32/lib.c @@ -218,29 +218,6 @@ map_pages(phys_addr_t phys, unsigned long virt, }
/* - * 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(pa, va, npages * PAGE_SIZE, ofmem_arch_io_translation_mode(pa)); - return (void *)(va + off); -} - -/* * D5.3 pgmap@ ( va -- pte ) */ static void @@ -371,7 +348,7 @@ void ofmem_arch_unmap_pages(ucell virt, ucell size)
void ofmem_arch_early_map_pages(phys_addr_t phys, ucell virt, ucell size, ucell mode) { - /* Currently do nothing */ + map_pages(phys, virt, size, mode); }
char *obp_dumb_memalloc(char *va, unsigned int size) diff --git a/openbios-devel/drivers/escc.c b/openbios-devel/drivers/escc.c index e22d245..ef431b2 100644 --- a/openbios-devel/drivers/escc.c +++ b/openbios-devel/drivers/escc.c @@ -105,7 +105,7 @@ static void uart_init_line(volatile unsigned char *port, unsigned long baud) int uart_init(phys_addr_t port, unsigned long speed) { #ifdef CONFIG_DRIVER_ESCC_SUN - serial_dev = map_io(port & ~7ULL, ZS_REGS); + serial_dev = (unsigned char *)ofmem_map_io(port & ~7ULL, ZS_REGS); serial_dev += port & 7ULL; #else serial_dev = (unsigned char *)(uintptr_t)port; @@ -213,7 +213,7 @@ static volatile unsigned char *kbd_dev;
void kbd_init(phys_addr_t base) { - kbd_dev = map_io(base, 2 * 4); + kbd_dev = (unsigned char *)ofmem_map_io(base, 2 * 4); kbd_dev += 4; }
diff --git a/openbios-devel/drivers/esp.c b/openbios-devel/drivers/esp.c index 869421d..f268b6a 100644 --- a/openbios-devel/drivers/esp.c +++ b/openbios-devel/drivers/esp.c @@ -311,7 +311,7 @@ static int espdma_init(unsigned int slot, uint64_t base, unsigned long offset, struct esp_dma *espdma) { - espdma->regs = (void *)map_io(base + (uint64_t)offset, 0x10); + espdma->regs = (void *)ofmem_map_io(base + (uint64_t)offset, 0x10);
if (espdma->regs == NULL) { DPRINTF("espdma_init: cannot map registers\n"); @@ -445,7 +445,7 @@ ob_esp_init(unsigned int slot, uint64_t base, unsigned long espoffset, return -1; } /* Get the IO region */ - esp->ll = (void *)map_io(base + (uint64_t)espoffset, + esp->ll = (void *)ofmem_map_io(base + (uint64_t)espoffset, sizeof(struct esp_regs)); if (esp->ll == NULL) { DPRINTF("Can't map ESP registers\n"); diff --git a/openbios-devel/drivers/fw_cfg.c b/openbios-devel/drivers/fw_cfg.c index 0da2e72..4027570 100644 --- a/openbios-devel/drivers/fw_cfg.c +++ b/openbios-devel/drivers/fw_cfg.c @@ -65,7 +65,7 @@ void fw_cfg_init(void) { #if defined(CONFIG_SPARC32) - fw_cfg_cmd = (void *)map_io(CONFIG_FW_CFG_ADDR, 2); + fw_cfg_cmd = (void *)ofmem_map_io(CONFIG_FW_CFG_ADDR, 2); fw_cfg_data = (uint8_t *)fw_cfg_cmd + 2; #elif defined(CONFIG_SPARC64) // Nothing for the port version diff --git a/openbios-devel/drivers/iommu.c b/openbios-devel/drivers/iommu.c index 6af5b33..7d34f81 100644 --- a/openbios-devel/drivers/iommu.c +++ b/openbios-devel/drivers/iommu.c @@ -103,7 +103,7 @@ iommu_init(struct iommu *t, uint64_t base) int ret; unsigned long vasize;
- regs = map_io(base, IOMMU_REGS); + regs = (struct iommu_regs *)ofmem_map_io(base, IOMMU_REGS); if (regs == NULL) { DPRINTF("Cannot map IOMMU\n"); for (;;) { } diff --git a/openbios-devel/drivers/obio.c b/openbios-devel/drivers/obio.c index 38c5f8d..359c6c2 100644 --- a/openbios-devel/drivers/obio.c +++ b/openbios-devel/drivers/obio.c @@ -71,7 +71,7 @@ map_reg(uint64_t base, uint64_t offset, unsigned long size, int map, if (map) { unsigned long addr;
- addr = (unsigned long)map_io(base + offset, size); + addr = (unsigned long)ofmem_map_io(base + offset, size);
PUSH(addr); fword("encode-int"); @@ -251,7 +251,7 @@ ob_aux2_reset_init(uint64_t base, uint64_t offset, int intr) power_reg = (void *)ob_reg(base, offset, AUXIO2_REGS, 1);
// Not in device tree - reset_reg = map_io(base + (uint64_t)SLAVIO_RESET, RESET_REGS); + reset_reg = (unsigned int *)ofmem_map_io(base + (uint64_t)SLAVIO_RESET, RESET_REGS);
bind_func("sparc32-reset-all", sparc32_reset_all); push_str("' sparc32-reset-all to reset-all"); @@ -297,7 +297,7 @@ ob_counter_init(uint64_t base, unsigned long offset) fword("property");
- counter_regs = map_io(base + (uint64_t)offset, sizeof(*counter_regs)); + counter_regs = (struct sun4m_timer_regs *)ofmem_map_io(base + (uint64_t)offset, sizeof(*counter_regs)); counter_regs->cfg = 0xffffffff; counter_regs->l10_timer_limit = (((1000000/100) + 1) << 10); counter_regs->cpu_timers[0].l14_timer_limit = 0; @@ -352,7 +352,7 @@ ob_interrupt_init(uint64_t base, unsigned long offset) push_str("reg"); fword("property");
- intregs = map_io(base | (uint64_t)offset, sizeof(*intregs)); + intregs = (struct sun4m_intregs *)ofmem_map_io(base | (uint64_t)offset, sizeof(*intregs)); intregs->clear = ~SUN4M_INT_MASKALL; intregs->cpu_intregs[0].clear = ~0x17fff;
@@ -403,7 +403,7 @@ static void ob_smp_init(unsigned long mem_size) { // See arch/sparc32/entry.S for memory layout - smp_header = (struct smp_cfg *)map_io((uint64_t)(mem_size - 0x100), + smp_header = (struct smp_cfg *)ofmem_map_io((uint64_t)(mem_size - 0x100), sizeof(struct smp_cfg)); }
diff --git a/openbios-devel/drivers/sbus.c b/openbios-devel/drivers/sbus.c index cba1050..f4a6d66 100644 --- a/openbios-devel/drivers/sbus.c +++ b/openbios-devel/drivers/sbus.c @@ -49,7 +49,7 @@ ob_sbus_node_init(uint64_t base) push_str("reg"); fword("property");
- regs = map_io(base, SBUS_REGS); + regs = (void *)ofmem_map_io(base, SBUS_REGS); PUSH((unsigned long)regs); fword("encode-int"); push_str("address"); diff --git a/openbios-devel/include/libopenbios/ofmem.h b/openbios-devel/include/libopenbios/ofmem.h index fa37146..4588a5e 100644 --- a/openbios-devel/include/libopenbios/ofmem.h +++ b/openbios-devel/include/libopenbios/ofmem.h @@ -136,7 +136,6 @@ extern struct mem cdvmem; void mem_init(struct mem *t, char *begin, char *limit); void *mem_alloc(struct mem *t, int size, int align); void map_pages(phys_addr_t phys, unsigned long virt, unsigned long size, unsigned long mode); -void *map_io(uint64_t pa, int size); #endif
#ifdef PAGE_SHIFT
This patch removes the SPARC32-specific map_pages() function from the IOMMU driver, plus switches obp_dumb_memalloc() over to use OFMEM. OFMEM property generation is enabled for the /memory and /virtual-memory nodes, and any remaining traces of the old memory variables are removed.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@siriusit.co.uk --- openbios-devel/arch/sparc32/lib.c | 69 +++++++++------------------ openbios-devel/drivers/iommu.c | 2 +- openbios-devel/include/libopenbios/ofmem.h | 1 - 3 files changed, 24 insertions(+), 48 deletions(-)
diff --git a/openbios-devel/arch/sparc32/lib.c b/openbios-devel/arch/sparc32/lib.c index 74ac5e7..6b51f1c 100644 --- a/openbios-devel/arch/sparc32/lib.c +++ b/openbios-devel/arch/sparc32/lib.c @@ -53,8 +53,6 @@ struct mem { 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; @@ -190,7 +188,7 @@ find_pte(unsigned long va, int alloc) return pa2va(pa); }
-void +static void map_pages(phys_addr_t phys, unsigned long virt, unsigned long size, unsigned long mode) { @@ -353,29 +351,19 @@ void ofmem_arch_early_map_pages(phys_addr_t phys, ucell virt, ucell size, ucell
char *obp_dumb_memalloc(char *va, unsigned int size) { - size = (size + 7) & ~7; - // XXX should use normal memory alloc - totavail[0].num_bytes -= size; - DPRINTF("obp_dumb_memalloc va 0x%p size %x at 0x%x\n", va, size, - totavail[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 *)(totmap[0].start_adr - size); - totmap[0].start_adr -= size; - totmap[0].num_bytes += size; - DPRINTF("obp_dumb_memalloc req null -> 0x%p\n", va); - } + phys_addr_t phys; + ucell virt; + + /* Claim physical memory */ + phys = ofmem_claim_phys(-1, size, CONFIG_OFMEM_MALLOC_ALIGN); + + /* Claim virtual memory */ + virt = ofmem_claim_virt(pointer2cell(va), size, 0);
- map_pages(totavail[0].num_bytes, (unsigned long)va, size, ofmem_arch_default_translation_mode(totavail[0].num_bytes)); + /* Map the memory */ + ofmem_map(phys, virt, size, ofmem_arch_default_translation_mode(phys));
- update_memory_properties(); - - return va; + return cell2pointer(virt); }
void obp_dumb_memfree(__attribute__((unused))char *va, @@ -387,6 +375,9 @@ void obp_dumb_memfree(__attribute__((unused))char *va, void ob_init_mmu(void) { + ucell *reg; + ofmem_t *ofmem; + init_romvec_mem();
/* Find the phandles for the /memory and /virtual-memory nodes */ @@ -400,30 +391,19 @@ ob_init_mmu(void) POP(); s_phandle_mmu = POP();
- /* Setup /memory:reg (totphys) property */ - push_str("/memory"); - fword("find-device"); - PUSH(pointer2cell(mem_reg)); - PUSH(3 * sizeof(ucell)); - push_str("reg"); - PUSH_ph(s_phandle_memory); - fword("encode-property"); + ofmem_register(s_phandle_memory, s_phandle_mmu);
- /* Setup /virtual-memory:avail (totmap) property */ - push_str("/virtual-memory"); - fword("find-device"); - PUSH(pointer2cell(virt_avail)); - PUSH(3 * sizeof(ucell)); - push_str("available"); - PUSH_ph(s_phandle_mmu); - fword("encode-property"); + /* Setup /memory:reg (totphys) property */ + ofmem = ofmem_arch_get_private(); + reg = malloc(3 * sizeof(ucell)); + ofmem_arch_encode_physaddr(reg, 0); /* physical base */ + reg[2] = (ucell)ofmem_arch_get_phys_top(); /* size */
- /* Setup /memory:avail (totavail) property */ push_str("/memory"); fword("find-device"); - PUSH(pointer2cell(mem_avail)); + PUSH(pointer2cell(reg)); PUSH(3 * sizeof(ucell)); - push_str("available"); + push_str("reg"); PUSH_ph(s_phandle_memory); fword("encode-property");
@@ -443,9 +423,6 @@ init_mmu_swift(void) unsigned int addr, i; unsigned long pa, va; int size; - - mem_init(&cmem, (char *) &_vmem, (char *)&_evmem); - mem_init(&cio, (char *)&_end, (char *)&_iomem);
ofmem_posix_memalign((void *)&context_table, NCTX_SWIFT * sizeof(int), NCTX_SWIFT * sizeof(int)); diff --git a/openbios-devel/drivers/iommu.c b/openbios-devel/drivers/iommu.c index 7d34f81..28f3b57 100644 --- a/openbios-devel/drivers/iommu.c +++ b/openbios-devel/drivers/iommu.c @@ -68,7 +68,7 @@ dvma_alloc(int size, unsigned int *pphys) */ mva = (unsigned int) va; mpa = (unsigned int) pa; - map_pages(mpa, mva, npages * PAGE_SIZE, ofmem_arch_io_translation_mode(mpa)); + ofmem_arch_early_map_pages(mpa, mva, npages * PAGE_SIZE, ofmem_arch_io_translation_mode(mpa));
/* * Map into IOMMU page table. diff --git a/openbios-devel/include/libopenbios/ofmem.h b/openbios-devel/include/libopenbios/ofmem.h index 4588a5e..5d7bfeb 100644 --- a/openbios-devel/include/libopenbios/ofmem.h +++ b/openbios-devel/include/libopenbios/ofmem.h @@ -135,7 +135,6 @@ extern struct mem cdvmem;
void mem_init(struct mem *t, char *begin, char *limit); void *mem_alloc(struct mem *t, int size, int align); -void map_pages(phys_addr_t phys, unsigned long virt, unsigned long size, unsigned long mode); #endif
#ifdef PAGE_SHIFT
This is required to enable a build with CONFIG_DEBUG_OFMEM set to true to complete successfully.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@siriusit.co.uk --- openbios-devel/include/arch/sparc32/types.h | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/openbios-devel/include/arch/sparc32/types.h b/openbios-devel/include/arch/sparc32/types.h index 444d648..e4f0f0d 100644 --- a/openbios-devel/include/arch/sparc32/types.h +++ b/openbios-devel/include/arch/sparc32/types.h @@ -46,8 +46,8 @@ typedef uint32_t ucell; typedef long long dcell; typedef unsigned long long ducell;
-#define FMT_cell "%ld" -#define FMT_ucell "%lu" +#define FMT_cell "%d" +#define FMT_ucell "%u" #define FMT_ucellx "%08x" #define FMT_ucellX "%08X"
On Thu, Dec 30, 2010 at 6:07 PM, Mark Cave-Ayland mark.cave-ayland@siriusit.co.uk wrote:
This patchset converts SPARC32 and its associated devices over from its own private memory routines over to using the OFMEM API as used by PPC and SPARC64.
Based on quick tests this seems almost OK, except NetBSD 5.0.1 CD boot fails: Jumping to entry point 00004000 for type 00000005... switching to new context:
NetBSD/sparc Secondary Boot, Revision 1.15 (builds@b8.netbsd.org, Thu Jul 30 00:08:01 UTC 2009)
Booting netbsd 1724008Unhandled Exception 0x00000009 PC = 0x00394dac NPC = 0x00394db0 Stopping execution
HEAD: Jumping to entry point 00004000 for type 00000005... switching to new context:
NetBSD/sparc Secondary Boot, Revision 1.15 (builds@b8.netbsd.org, Thu Jul 30 00:08:01 UTC 2009)
Booting netbsd 1724008+846700+210280=0x2b7208 OBP version 3, revision 2.25 (plugin rev 2) Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The NetBSD Foundation, Inc. All rights reserved. Copyright (c) 1982, 1986, 1989, 1991, 1993 The Regents of the University of California. All rights reserved.
NetBSD 5.0.1 (INSTALL) #0: Thu Jul 30 00:20:16 UTC 2009 builds@b8.netbsd.org:/home/builds/ab/netbsd-5-0-1-RELEASE/sparc/200907292356Z-obj/home/builds/ab/netbsd-5-0-1-RELEASE/src/sys/arch/sparc/compile/INSTALL total memory = 127 MB avail memory = 121 MB etc...
On 30/12/10 19:03, Blue Swirl wrote:
Based on quick tests this seems almost OK, except NetBSD 5.0.1 CD boot fails: Jumping to entry point 00004000 for type 00000005... switching to new context:
NetBSD/sparc Secondary Boot, Revision 1.15 (builds@b8.netbsd.org, Thu Jul 30 00:08:01 UTC 2009)
Booting netbsd 1724008Unhandled Exception 0x00000009 PC = 0x00394dac NPC = 0x00394db0 Stopping execution
Ah got it - it's a bug in the OFMEM freelist code whereby it doesn't honour the physical alignment if the space is reallocated from the freelist. The attached patch seems to fix the problem for me - can you confirm at your end?
Would you like me to re-spin the entire patchset based on previous comments to the list for more testing, or do you think it's close to commit?
ATB,
Mark.
On Thu, Dec 30, 2010 at 8:17 PM, Mark Cave-Ayland mark.cave-ayland@siriusit.co.uk wrote:
On 30/12/10 19:03, Blue Swirl wrote:
Based on quick tests this seems almost OK, except NetBSD 5.0.1 CD boot fails: Jumping to entry point 00004000 for type 00000005... switching to new context:
NetBSD/sparc Secondary Boot, Revision 1.15 (builds@b8.netbsd.org, Thu Jul 30 00:08:01 UTC 2009)
Booting netbsd 1724008Unhandled Exception 0x00000009 PC = 0x00394dac NPC = 0x00394db0 Stopping execution
Ah got it - it's a bug in the OFMEM freelist code whereby it doesn't honour the physical alignment if the space is reallocated from the freelist. The attached patch seems to fix the problem for me - can you confirm at your end?
Yes, now it works. Please merge it with 1/16.
Would you like me to re-spin the entire patchset based on previous comments to the list for more testing, or do you think it's close to commit?
As you wish. BTW, git am complained about trailing whitespace, but I didn't check why.
On 30/12/10 21:00, Blue Swirl wrote:
Ah got it - it's a bug in the OFMEM freelist code whereby it doesn't honour the physical alignment if the space is reallocated from the freelist. The attached patch seems to fix the problem for me - can you confirm at your end?
Yes, now it works. Please merge it with 1/16.
Excellent! :) However 1/16 was one of the "extra" patches that got picked up and so it has already been committed. I'll commit the fix as a separate patch and then rebase.
Would you like me to re-spin the entire patchset based on previous comments to the list for more testing, or do you think it's close to commit?
As you wish. BTW, git am complained about trailing whitespace, but I didn't check why.
I think on the basis of the above, I'll post a final rebased version to the list just to be safe.
ATB,
Mark.