mirror of
https://gitlab.com/qemu-project/openbios.git
synced 2024-02-13 08:34:06 +08:00
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 <mark.cave-ayland@siriusit.co.uk> git-svn-id: svn://coreboot.org/openbios/trunk/openbios-devel@766 f158a5a8-5612-0410-a976-696ce0be7e32
This commit is contained in:
committed by
Mark Cave-Ayland
parent
0c2f6e929d
commit
ca0f9c5a03
@@ -394,11 +394,35 @@ mem_release( void )
|
|||||||
ofmem_release_phys(phys, size);
|
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");
|
DECLARE_NODE(memory, INSTALL_OPEN, 0, "/memory");
|
||||||
|
|
||||||
NODE_METHODS( memory ) = {
|
NODE_METHODS( memory ) = {
|
||||||
{ "claim", mem_claim },
|
{ "claim", mem_claim },
|
||||||
{ "release", mem_release },
|
{ "release", mem_release },
|
||||||
|
{ "SUNW,retain", mem_retain },
|
||||||
};
|
};
|
||||||
|
|
||||||
DECLARE_UNNAMED_NODE(mmu, INSTALL_OPEN, 0);
|
DECLARE_UNNAMED_NODE(mmu, INSTALL_OPEN, 0);
|
||||||
|
|||||||
@@ -26,21 +26,21 @@ static union {
|
|||||||
ofmem_t ofmem;
|
ofmem_t ofmem;
|
||||||
} s_ofmem_data;
|
} s_ofmem_data;
|
||||||
|
|
||||||
#define OFMEM (&s_ofmem_data.ofmem)
|
#define OFMEM (&s_ofmem_data.ofmem)
|
||||||
#define TOP_OF_RAM (s_ofmem_data.memory + MEMSIZE)
|
#define TOP_OF_RAM (s_ofmem_data.memory + MEMSIZE)
|
||||||
|
|
||||||
translation_t **g_ofmem_translations = &s_ofmem_data.ofmem.trans;
|
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)
|
static inline size_t ALIGN_SIZE(size_t x, size_t a)
|
||||||
{
|
{
|
||||||
return (x + a - 1) & ~(a-1);
|
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)
|
ofmem_t* ofmem_arch_get_private(void)
|
||||||
{
|
{
|
||||||
return OFMEM;
|
return OFMEM;
|
||||||
@@ -95,10 +95,27 @@ static int remap_page_range( ucell phys, ucell virt, ucell size, ucell mode )
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define RETAIN_OFMEM (TOP_OF_RAM - ALIGN_SIZE(sizeof(retain_t), 8))
|
||||||
|
#define RETAIN_MAGIC 0x1100220033004400
|
||||||
|
|
||||||
void ofmem_init( void )
|
void ofmem_init( void )
|
||||||
{
|
{
|
||||||
memset(&s_ofmem_data, 0, sizeof(s_ofmem_data));
|
retain_t *retained = (retain_t *)RETAIN_OFMEM;
|
||||||
s_ofmem_data.ofmem.ramsize = qemu_mem_size;
|
|
||||||
|
/* 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 */
|
/* inherit translations set up by entry.S */
|
||||||
ofmem_walk_boot_map(remap_page_range);
|
ofmem_walk_boot_map(remap_page_range);
|
||||||
|
|||||||
@@ -46,10 +46,17 @@ typedef struct {
|
|||||||
|
|
||||||
range_t *phys_range;
|
range_t *phys_range;
|
||||||
range_t *virt_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 */
|
translation_t *trans; /* this is really a translation_t */
|
||||||
} ofmem_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 */
|
/* TODO: temporary migration interface */
|
||||||
extern ofmem_t* ofmem_arch_get_private(void);
|
extern ofmem_t* ofmem_arch_get_private(void);
|
||||||
extern void* ofmem_arch_get_malloc_base(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_phys( ucell mphys, ucell size, ucell align );
|
||||||
extern ucell ofmem_claim_virt( ucell mvirt, 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_map( ucell phys, ucell virt, ucell size, ucell mode );
|
||||||
extern int ofmem_unmap( ucell virt, ucell size );
|
extern int ofmem_unmap( ucell virt, ucell size );
|
||||||
|
|
||||||
|
|||||||
@@ -449,6 +449,23 @@ ucell ofmem_claim_virt( ucell virt, ucell size, ucell align )
|
|||||||
get_ram_size(), ofmem_arch_get_virt_top(), 0 );
|
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 */
|
/* allocate both physical and virtual space and add a translation */
|
||||||
ucell ofmem_claim( ucell addr, ucell size, ucell align )
|
ucell ofmem_claim( ucell addr, ucell size, ucell align )
|
||||||
|
|||||||
Reference in New Issue
Block a user