Based on Mark's previous work, let ofmem handle addresses wider than one cell. This is based on the assumption that sizeof(phys_addr_t) >= sizeof(ucell). Affected are in particular sparc32 (36 bits) and ppc64 (64 bits).
As a consequence, some range_t related code shared with virtual/effective addresses needed to be migrated, too. Since both address types are unsigned this should be okay.
v4: * Coding style fixes and comments, as suggested by Mark.
v3: * Rebased: Prefer FMT_plx for trace output. * Convert some more places to phys_addr_t to avoid breakage on ppc64. * Add helpers ofmem_arch_{get_physaddr_cellsize,encode_physaddr}(), requested by Mark.
v2: * Use FMT_physaddr_t in ofmem trace code. (by Mark)
Cc: Mark Cave-Ayland mark.cave-ayland@siriusit.co.uk Signed-off-by: Andreas Färber andreas.faerber@web.de --- arch/ppc/qemu/ofmem.c | 51 +++++++++++++++++++-------- arch/sparc64/lib.c | 21 +++++++---- arch/sparc64/ofmem_sparc64.c | 15 +++++++- include/libopenbios/ofmem.h | 22 ++++++----- libopenbios/ofmem_common.c | 77 +++++++++++++++++++++++++----------------- 5 files changed, 120 insertions(+), 66 deletions(-)
diff --git a/arch/ppc/qemu/ofmem.c b/arch/ppc/qemu/ofmem.c index c62e42c..2892d54 100644 --- a/arch/ppc/qemu/ofmem.c +++ b/arch/ppc/qemu/ofmem.c @@ -120,7 +120,7 @@ void ofmem_arch_unmap_pages(ucell virt, ucell size) /* kill page mappings in provided range */ }
-void ofmem_arch_early_map_pages(ucell phys, ucell virt, ucell size, ucell mode) +void ofmem_arch_early_map_pages(phys_addr_t phys, ucell virt, ucell size, ucell mode) { /* none yet */ } @@ -131,10 +131,29 @@ retain_t *ofmem_arch_get_retained(void) return NULL; }
+int ofmem_arch_get_physaddr_cellsize(void) +{ +#ifdef CONFIG_PPC64 + return 2; +#else + return 1; +#endif +} + +int ofmem_arch_encode_physaddr(ucell *p, phys_addr_t value) +{ + int n = 0; +#ifdef CONFIG_PPC64 + p[n++] = value >> 32; +#endif + p[n++] = value; + return n; +} + /* Return size of a single MMU package translation property entry in cells */ int ofmem_arch_get_translation_entry_size(void) { - return 4; + return 3 + ofmem_arch_get_physaddr_cellsize(); }
/* Generate translation property entry for PPC. @@ -149,10 +168,12 @@ int ofmem_arch_get_translation_entry_size(void) */ void ofmem_arch_create_translation_entry(ucell *transentry, translation_t *t) { - transentry[0] = t->virt; - transentry[1] = t->size; - transentry[2] = t->phys; - transentry[3] = t->mode; + int i = 0; + + transentry[i++] = t->virt; + transentry[i++] = t->size; + i += ofmem_arch_encode_physaddr(&transentry[i], t->phys); + transentry[i++] = t->mode; }
/************************************************************************/ @@ -182,7 +203,7 @@ realloc(void *ptr, size_t size) /* misc */ /************************************************************************/
-ucell ofmem_arch_default_translation_mode(ucell phys) +ucell ofmem_arch_default_translation_mode(phys_addr_t phys) { /* XXX: Guard bit not set as it should! */ if (phys < IO_BASE) @@ -195,10 +216,10 @@ ucell ofmem_arch_default_translation_mode(ucell phys) /* page fault handler */ /************************************************************************/
-static ucell +static phys_addr_t ea_to_phys(ucell ea, ucell *mode) { - ucell phys; + phys_addr_t phys;
if (ea >= OF_CODE_START) { /* ROM into RAM */ @@ -221,7 +242,7 @@ ea_to_phys(ucell ea, ucell *mode) }
static void -hash_page_64(ucell ea, ucell phys, ucell mode) +hash_page_64(ucell ea, phys_addr_t phys, ucell mode) { static int next_grab_slot = 0; uint64_t vsid_mask, page_mask, pgidx, hash; @@ -270,7 +291,7 @@ hash_page_64(ucell ea, ucell phys, ucell mode) .h = 0, .v = 1,
- .rpn = (phys & ~0xfff) >> 12, + .rpn = (phys & ~0xfffUL) >> 12, .r = mode & (1 << 8) ? 1 : 0, .c = mode & (1 << 7) ? 1 : 0, .w = mode & (1 << 6) ? 1 : 0, @@ -287,7 +308,7 @@ hash_page_64(ucell ea, ucell phys, ucell mode) }
static void -hash_page_32(ucell ea, ucell phys, ucell mode) +hash_page_32(ucell ea, phys_addr_t phys, ucell mode) { #ifndef __powerpc64__ static int next_grab_slot = 0; @@ -341,7 +362,7 @@ static int is_ppc64(void) }
/* XXX Remove these ugly constructs when legacy 64-bit support is dropped. */ -static void hash_page(unsigned long ea, unsigned long phys, ucell mode) +static void hash_page(unsigned long ea, phys_addr_t phys, ucell mode) { if (is_ppc64()) hash_page_64(ea, phys, mode); @@ -354,7 +375,7 @@ dsi_exception(void) { unsigned long dar, dsisr; ucell mode; - ucell phys; + phys_addr_t phys;
asm volatile("mfdar %0" : "=r" (dar) : ); asm volatile("mfdsisr %0" : "=r" (dsisr) : ); @@ -368,7 +389,7 @@ isi_exception(void) { unsigned long nip, srr1; ucell mode; - ucell phys; + phys_addr_t phys;
asm volatile("mfsrr0 %0" : "=r" (nip) : ); asm volatile("mfsrr1 %0" : "=r" (srr1) : ); diff --git a/arch/sparc64/lib.c b/arch/sparc64/lib.c index 03dc754..1a48649 100644 --- a/arch/sparc64/lib.c +++ b/arch/sparc64/lib.c @@ -120,7 +120,8 @@ void ofmem_walk_boot_map(translation_entry_cb cb) static void mmu_translate(void) { - ucell virt, phys, mode; + ucell virt, mode; + phys_addr_t phys;
virt = POP();
@@ -352,7 +353,7 @@ itlb_miss_handler(void) }
static void -map_pages(unsigned long phys, unsigned long virt, +map_pages(phys_addr_t phys, unsigned long virt, unsigned long size, unsigned long mode) { unsigned long tte_data, currsize; @@ -393,7 +394,7 @@ map_pages(unsigned long phys, unsigned long virt, } }
-void ofmem_map_pages(ucell phys, ucell virt, ucell size, ucell mode) +void ofmem_map_pages(phys_addr_t phys, ucell virt, ucell size, ucell mode) { return map_pages(phys, virt, size, mode); } @@ -405,7 +406,8 @@ void ofmem_map_pages(ucell phys, ucell virt, ucell size, ucell mode) static void mmu_map(void) { - ucell virt, size, mode, phys; + ucell virt, size, mode; + phys_addr_t phys;
mode = POP(); size = POP(); @@ -453,7 +455,7 @@ void ofmem_arch_unmap_pages(ucell virt, ucell size) unmap_pages(virt, size); }
-void ofmem_arch_early_map_pages(ucell phys, ucell virt, ucell size, ucell mode) +void ofmem_arch_early_map_pages(phys_addr_t phys, ucell virt, ucell size, ucell mode) { if (mode & SPITFIRE_TTE_LOCKED) { // install locked tlb entries now @@ -514,7 +516,8 @@ mmu_release(void) static void mem_claim( void ) { - ucell phys=-1UL, size, align; + ucell size, align; + phys_addr_t phys=-1UL;
align = POP(); size = POP(); @@ -534,7 +537,8 @@ mem_claim( void ) static void mem_release( void ) { - ucell phys, size; + phys_addr_t phys; + ucell size;
size = POP(); phys = POP(); @@ -548,7 +552,8 @@ mem_release( void ) static void mem_retain ( void ) { - ucell phys=-1UL, size, align; + ucell size, align; + phys_addr_t phys=-1UL;
align = POP(); size = POP(); diff --git a/arch/sparc64/ofmem_sparc64.c b/arch/sparc64/ofmem_sparc64.c index 7c05c40..4d13038 100644 --- a/arch/sparc64/ofmem_sparc64.c +++ b/arch/sparc64/ofmem_sparc64.c @@ -95,7 +95,18 @@ void ofmem_arch_create_translation_entry(ucell *transentry, translation_t *t) /* misc */ /************************************************************************/
-ucell ofmem_arch_default_translation_mode( ucell phys ) +int ofmem_arch_get_physaddr_cellsize(void) +{ + return 1; +} + +int ofmem_arch_encode_physaddr(ucell *p, phys_addr_t value) +{ + p[0] = value; + return 1; +} + +ucell ofmem_arch_default_translation_mode( phys_addr_t phys ) { /* Writable, cacheable */ /* not privileged and not locked */ @@ -109,7 +120,7 @@ ucell ofmem_arch_default_translation_mode( ucell phys ) /* init / cleanup */ /************************************************************************/
-static int remap_page_range( ucell phys, ucell virt, ucell size, ucell mode ) +static int remap_page_range( phys_addr_t phys, ucell virt, ucell size, ucell mode ) { ofmem_claim_phys(phys, size, 0); ofmem_claim_virt(virt, size, 0); diff --git a/include/libopenbios/ofmem.h b/include/libopenbios/ofmem.h index 74f1efd..6472008 100644 --- a/include/libopenbios/ofmem.h +++ b/include/libopenbios/ofmem.h @@ -26,7 +26,7 @@ typedef struct alloc_desc {
typedef struct mem_range { struct mem_range *next; - ucell start; + phys_addr_t start; /* sizeof(phys) >= sizeof(virt), e.g SPARC32 */ ucell size; } range_t;
@@ -34,7 +34,7 @@ typedef struct trans { struct trans *next; ucell virt; /* chain is sorted by virt */ ucell size; - ucell phys; + phys_addr_t phys; ucell mode; } translation_t;
@@ -63,14 +63,16 @@ 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 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); 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( ucell phys ); -extern void ofmem_arch_early_map_pages(ucell phys, ucell virt, ucell size, +extern ucell ofmem_arch_default_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); /* sparc64 uses this method */ -extern int ofmem_map_page_range( ucell phys, ucell virt, ucell size, +extern int ofmem_map_page_range( phys_addr_t phys, ucell virt, ucell size, ucell mode );
/* malloc interface */ @@ -93,18 +95,18 @@ extern void ofmem_init( void ); extern void ofmem_register( phandle_t ph_memory, phandle_t ph_mmu );
extern ucell ofmem_claim( ucell addr, ucell size, ucell align ); -extern ucell ofmem_claim_phys( ucell mphys, 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_retain( ucell phys, ucell size, ucell align ); +extern phys_addr_t ofmem_retain( phys_addr_t phys, ucell size, ucell align );
-extern int ofmem_map( ucell phys, ucell virt, ucell size, ucell mode ); +extern int ofmem_map( phys_addr_t phys, ucell virt, ucell size, ucell mode ); extern int ofmem_unmap( ucell virt, ucell size );
extern void ofmem_release( ucell virt, ucell size ); -extern void ofmem_release_phys( ucell phys, ucell size ); +extern void ofmem_release_phys( phys_addr_t phys, ucell size ); extern void ofmem_release_virt( ucell virt, ucell size ); -extern ucell ofmem_translate( ucell virt, ucell *ret_mode ); +extern phys_addr_t ofmem_translate( ucell virt, ucell *ret_mode );
#ifdef CONFIG_PPC #define PAGE_SHIFT 12 diff --git a/libopenbios/ofmem_common.c b/libopenbios/ofmem_common.c index 64695b6..20a4cba 100644 --- a/libopenbios/ofmem_common.c +++ b/libopenbios/ofmem_common.c @@ -49,7 +49,7 @@ print_range( range_t *r, char *str ) { printk("--- Range %s ---\n", str ); for( ; r; r=r->next ) - printk("%08lx - %08lx\n", r->start, r->start + r->size -1 ); + printk(FMT_plx " - " FMT_plx "\n", r->start, r->start + r->size - 1); printk("\n"); }
@@ -72,7 +72,7 @@ print_trans( void )
printk("--- Translations ---\n"); for( ; t; t=t->next ) - printk("%08lx -> %08lx [size %lx]\n", t->virt, t->phys, t->size ); + printk("%08lx -> " FMT_plx " [size %lx]\n", t->virt, t->phys, t->size); printk("\n"); } #endif @@ -246,8 +246,8 @@ static void ofmem_update_memory_available( phandle_t ph, range_t *range, { range_t *r; int ncells, prop_used, prop_size; - - ucell start, size, *prop; + phys_addr_t start; + ucell size, *prop;
if (s_phandle_memory == 0) return; @@ -256,8 +256,10 @@ static void ofmem_update_memory_available( phandle_t ph, range_t *range, for( r = range, ncells = 0; r ; r=r->next, ncells++ ) { }
- /* inverse of phys_range list could take 2 more cells for the tail */ - prop_used = (ncells+1) * sizeof(ucell) * 2; + /* inverse of phys_range list could take 2 or more additional cells for the tail + For /memory, physical addresses may be wider than one ucell. */ + prop_used = (ncells + 1) * sizeof(ucell) * + (((ph == s_phandle_memory) ? ofmem_arch_get_physaddr_cellsize() : 1) + 1);
if (prop_used > *mem_prop_size) {
@@ -291,7 +293,13 @@ static void ofmem_update_memory_available( phandle_t ph, range_t *range,
size = r->start - start; if (size) { - prop[ncells++] = start; + if (ph == s_phandle_memory) { + /* physical address for /memory */ + ncells += ofmem_arch_encode_physaddr(&prop[ncells], start); + } else { + /* virtual address for MMU */ + prop[ncells++] = start; + } prop[ncells++] = size; } start = r->start + r->size; @@ -299,7 +307,13 @@ static void ofmem_update_memory_available( phandle_t ph, range_t *range,
/* tail */ if (start < top_address) { - prop[ncells++] = start; + if (ph == s_phandle_memory) { + /* physical address for /memory */ + ncells += ofmem_arch_encode_physaddr(&prop[ncells], start); + } else { + /* virtual address for MMU */ + prop[ncells++] = start; + } prop[ncells++] = top_address - start; }
@@ -323,7 +337,7 @@ static void ofmem_update_translations( void ) /* client interface */ /************************************************************************/
-static int is_free( ucell ea, ucell size, range_t *r ) +static int is_free( phys_addr_t ea, ucell size, range_t *r ) { if( size == 0 ) return 1; @@ -336,7 +350,7 @@ static int is_free( ucell ea, ucell size, range_t *r ) return 1; }
-static void add_entry_( ucell ea, ucell size, range_t **r ) +static void add_entry_( phys_addr_t ea, ucell size, range_t **r ) { range_t *nr;
@@ -350,7 +364,7 @@ static void add_entry_( ucell ea, ucell size, range_t **r ) *r = nr; }
-static int add_entry( ucell ea, ucell size, range_t **r ) +static int add_entry( phys_addr_t ea, ucell size, range_t **r ) { if( !is_free( ea, size, *r ) ) { OFMEM_TRACE("add_entry: range not free!\n"); @@ -380,7 +394,7 @@ static void join_ranges( range_t **rr ) } }
-static void fill_range( ucell ea, ucell size, range_t **rr ) +static void fill_range( phys_addr_t ea, ucell size, range_t **rr ) { add_entry_( ea, size, rr ); join_ranges( rr ); @@ -388,9 +402,9 @@ static void fill_range( ucell ea, ucell size, range_t **rr ) #endif
static ucell find_area( ucell align, ucell size, range_t *r, - ucell min, ucell max, int reverse ) + phys_addr_t min, phys_addr_t max, int reverse ) { - ucell base = min; + phys_addr_t base = min; range_t *r2;
if( (align & (align-1)) ) { @@ -438,7 +452,7 @@ static ucell find_area( ucell align, ucell size, range_t *r, return -1; }
-static ucell ofmem_claim_phys_( ucell phys, ucell size, ucell align, +static phys_addr_t ofmem_claim_phys_( phys_addr_t phys, ucell size, ucell align, ucell min, ucell max, int reverse ) { ofmem_t *ofmem = ofmem_arch_get_private(); @@ -463,9 +477,9 @@ static ucell ofmem_claim_phys_( ucell phys, ucell size, ucell align, }
/* if align != 0, phys is ignored. Returns -1 on error */ -ucell ofmem_claim_phys( ucell phys, ucell size, ucell align ) +phys_addr_t ofmem_claim_phys( phys_addr_t phys, ucell size, ucell align ) { - OFMEM_TRACE("ofmem_claim phys=" FMT_ucellx " size=" FMT_ucellx + OFMEM_TRACE("ofmem_claim phys=" FMT_plx " size=" FMT_ucellx " align=" FMT_ucellx "\n", phys, size, align);
@@ -506,12 +520,12 @@ ucell ofmem_claim_virt( ucell virt, ucell size, ucell align ) }
/* if align != 0, phys is ignored. Returns -1 on error */ -ucell ofmem_retain( ucell phys, ucell size, ucell align ) +phys_addr_t ofmem_retain( phys_addr_t phys, ucell size, ucell align ) { retain_t *retained = ofmem_arch_get_retained(); - ucell retain_phys; + phys_addr_t retain_phys;
- OFMEM_TRACE("ofmem_retain phys=" FMT_ucellx " size=" FMT_ucellx + OFMEM_TRACE("ofmem_retain phys=" FMT_plx " size=" FMT_ucellx " align=" FMT_ucellx "\n", phys, size, align);
@@ -530,7 +544,8 @@ ucell ofmem_retain( ucell phys, ucell size, ucell align ) ucell ofmem_claim( ucell addr, ucell size, ucell align ) { ofmem_t *ofmem = ofmem_arch_get_private(); - ucell virt, phys; + ucell virt; + phys_addr_t phys; ucell offs = addr & 0xfff;
OFMEM_TRACE("ofmem_claim " FMT_ucellx " " FMT_ucellx " " FMT_ucellx "\n", addr, size, align ); @@ -595,13 +610,13 @@ static void split_trans( ucell virt ) } }
-int ofmem_map_page_range( ucell phys, ucell virt, ucell size, ucell mode ) +int ofmem_map_page_range( phys_addr_t phys, ucell virt, ucell size, ucell mode ) { ofmem_t *ofmem = ofmem_arch_get_private(); translation_t *t, **tt;
OFMEM_TRACE("ofmem_map_page_range " FMT_ucellx - " -> " FMT_ucellx " " FMT_ucellx " mode " FMT_ucellx "\n", + " -> " FMT_plx " " FMT_ucellx " mode " FMT_ucellx "\n", virt, phys, size, mode );
split_trans( virt ); @@ -677,7 +692,7 @@ static int unmap_page_range( ucell virt, ucell size ) *plinkentry = t->next;
OFMEM_TRACE("unmap_page_range found " - FMT_ucellx " -> " FMT_ucellx " " FMT_ucellx + FMT_ucellx " -> " FMT_plx " " FMT_ucellx " mode " FMT_ucellx "\n", t->virt, t->phys, t->size, t->mode );
@@ -693,7 +708,7 @@ static int unmap_page_range( ucell virt, ucell size ) return 0; }
-int ofmem_map( ucell phys, ucell virt, ucell size, ucell mode ) +int ofmem_map( phys_addr_t phys, ucell virt, ucell size, ucell mode ) { /* printk("+ofmem_map: %08lX --> %08lX (size %08lX, mode 0x%02X)\n", virt, phys, size, mode ); */ @@ -701,7 +716,7 @@ int ofmem_map( ucell phys, ucell virt, ucell size, ucell mode ) if( (phys & 0xfff) || (virt & 0xfff) || (size & 0xfff) ) {
OFMEM_TRACE("ofmem_map: Bad parameters (" - FMT_ucellX " " FMT_ucellX " " FMT_ucellX ")\n", + FMT_plx " " FMT_ucellX " " FMT_ucellX ")\n", phys, virt, size );
phys &= ~0xfff; @@ -751,7 +766,7 @@ int ofmem_unmap( ucell virt, ucell size ) }
/* virtual -> physical. */ -ucell ofmem_translate( ucell virt, ucell *mode ) +phys_addr_t ofmem_translate( ucell virt, ucell *mode ) { ofmem_t *ofmem = ofmem_arch_get_private(); translation_t *t; @@ -776,9 +791,9 @@ static void remove_range( ucell ea, ucell size, range_t **r ) }
/* release memory allocated by ofmem_claim_phys */ -void ofmem_release_phys( ucell phys, ucell size ) +void ofmem_release_phys( phys_addr_t phys, ucell size ) { - OFMEM_TRACE("ofmem_release_phys addr=" FMT_ucellx " size=" FMT_ucellx "\n", + OFMEM_TRACE("ofmem_release_phys addr=" FMT_plx " size=" FMT_ucellx "\n", phys, size);
ofmem_t *ofmem = ofmem_arch_get_private(); @@ -802,8 +817,8 @@ void ofmem_release( ucell virt, ucell size ) __func__, virt, size);
ucell mode; - ucell phys = ofmem_translate(virt, &mode); - if (phys == (ucell)-1) { + phys_addr_t phys = ofmem_translate(virt, &mode); + if (phys == (phys_addr_t)-1) { OFMEM_TRACE("%s: no mapping\n", __func__); return; }