From ca0f9c5a0335c72aa5e77e51918e16cd505cc335 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Sun, 2 May 2010 19:26:29 +0000 Subject: [PATCH] Commit partial implementation of SUNW,retain for SPARC64 based upon the existing physical allocation routines. I've been unable to finish the code and test retention after a restart since the OpenBIOS words reset and reset-all don't seem to work at the moment. However, it enables OpenSolaris boot to get further in the meantime. Signed-off-by: Mark Cave-Ayland git-svn-id: svn://coreboot.org/openbios/trunk/openbios-devel@766 f158a5a8-5612-0410-a976-696ce0be7e32 --- arch/sparc64/lib.c | 24 ++++++++++++++++++++++++ arch/sparc64/ofmem_sparc64.c | 35 ++++++++++++++++++++++++++--------- include/libopenbios/ofmem.h | 9 +++++++++ libopenbios/ofmem_common.c | 17 +++++++++++++++++ 4 files changed, 76 insertions(+), 9 deletions(-) diff --git a/arch/sparc64/lib.c b/arch/sparc64/lib.c index 6a8a6ea..9f94a6a 100644 --- a/arch/sparc64/lib.c +++ b/arch/sparc64/lib.c @@ -394,11 +394,35 @@ mem_release( void ) ofmem_release_phys(phys, size); } +/* ( name-cstr phys size align --- phys ) */ +static void +mem_retain ( void ) +{ + ucell phys=-1UL, size, align; + + align = POP(); + size = POP(); + if (!align) { + phys = POP(); + phys <<= 32; + phys |= POP(); + } + + /* Currently do nothing with the name */ + POP(); + + phys = ofmem_retain(phys, size, align); + + PUSH(phys & 0xffffffffUL); + PUSH(phys >> 32); +} + DECLARE_NODE(memory, INSTALL_OPEN, 0, "/memory"); NODE_METHODS( memory ) = { { "claim", mem_claim }, { "release", mem_release }, + { "SUNW,retain", mem_retain }, }; DECLARE_UNNAMED_NODE(mmu, INSTALL_OPEN, 0); diff --git a/arch/sparc64/ofmem_sparc64.c b/arch/sparc64/ofmem_sparc64.c index ad8fe46..fb2b96b 100644 --- a/arch/sparc64/ofmem_sparc64.c +++ b/arch/sparc64/ofmem_sparc64.c @@ -26,21 +26,21 @@ static union { ofmem_t ofmem; } s_ofmem_data; -#define OFMEM (&s_ofmem_data.ofmem) -#define TOP_OF_RAM (s_ofmem_data.memory + MEMSIZE) +#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; -static ucell get_heap_top( void ) -{ - return (ucell)TOP_OF_RAM; -} - 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 - ALIGN_SIZE(sizeof(retain_t), 8)); +} + ofmem_t* ofmem_arch_get_private(void) { return OFMEM; @@ -95,10 +95,27 @@ static int remap_page_range( ucell phys, ucell virt, ucell size, ucell mode ) return 0; } +#define RETAIN_OFMEM (TOP_OF_RAM - ALIGN_SIZE(sizeof(retain_t), 8)) +#define RETAIN_MAGIC 0x1100220033004400 + void ofmem_init( void ) { - memset(&s_ofmem_data, 0, sizeof(s_ofmem_data)); - s_ofmem_data.ofmem.ramsize = qemu_mem_size; + retain_t *retained = (retain_t *)RETAIN_OFMEM; + + /* Clear all memory except any retained areas */ + if (!retained->magic == RETAIN_MAGIC) { + memset(&s_ofmem_data, 0, sizeof(s_ofmem_data)); + s_ofmem_data.ofmem.ramsize = qemu_mem_size; + + retained->magic = RETAIN_MAGIC; + } else { + /* TODO: walk retain_phys_range and add entries to phys_range to prevent + them being reused */ + OFMEM_TRACE("ofmem_init has detected retained magic but currently not implemented"); + + memset(&s_ofmem_data, 0, sizeof(s_ofmem_data)); + s_ofmem_data.ofmem.ramsize = qemu_mem_size; + } /* inherit translations set up by entry.S */ ofmem_walk_boot_map(remap_page_range); diff --git a/include/libopenbios/ofmem.h b/include/libopenbios/ofmem.h index 314edf9..924dc16 100644 --- a/include/libopenbios/ofmem.h +++ b/include/libopenbios/ofmem.h @@ -46,10 +46,17 @@ typedef struct { range_t *phys_range; range_t *virt_range; + range_t *retain_phys_range; /* physical memory that should survive a warm reset */ translation_t *trans; /* this is really a translation_t */ } ofmem_t; +/* structure for retained data at the top of the heap */ +typedef struct { + ucell magic; + range_t *retain_phys_range; +} retain_t; + /* TODO: temporary migration interface */ extern ofmem_t* ofmem_arch_get_private(void); extern void* ofmem_arch_get_malloc_base(void); @@ -86,6 +93,8 @@ extern ucell ofmem_claim( ucell addr, ucell size, ucell align ); extern ucell ofmem_claim_phys( ucell 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 int ofmem_map( ucell phys, ucell virt, ucell size, ucell mode ); extern int ofmem_unmap( ucell virt, ucell size ); diff --git a/libopenbios/ofmem_common.c b/libopenbios/ofmem_common.c index 8f10118..940b82b 100644 --- a/libopenbios/ofmem_common.c +++ b/libopenbios/ofmem_common.c @@ -449,6 +449,23 @@ ucell ofmem_claim_virt( ucell virt, ucell size, ucell align ) get_ram_size(), ofmem_arch_get_virt_top(), 0 ); } +/* if align != 0, phys is ignored. Returns -1 on error */ +ucell ofmem_retain( ucell phys, ucell size, ucell align ) +{ + ofmem_t *ofmem = ofmem_arch_get_private(); + ucell retain_phys; + + OFMEM_TRACE("ofmem_retain phys=" FMT_ucellx " size=" FMT_ucellx + " align=" FMT_ucellx "\n", + phys, size, align); + + retain_phys = ofmem_claim_phys_( phys, size, align, 0, get_ram_size(), 0 ); + + /* Also add to the retain_phys_range list */ + add_entry( phys, size, &ofmem->retain_phys_range ); + + return retain_phys; +} /* allocate both physical and virtual space and add a translation */ ucell ofmem_claim( ucell addr, ucell size, ucell align )