mirror of
https://gitlab.com/qemu-project/openbios.git
synced 2024-02-13 08:34:06 +08:00
Move the retained magic block to the top of physical RAM and implement code that should do the right thing. Probably needs more
testing though. Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@siriusit.co.uk> git-svn-id: svn://coreboot.org/openbios/trunk/openbios-devel@771 f158a5a8-5612-0410-a976-696ce0be7e32
This commit is contained in:
committed by
Mark Cave-Ayland
parent
1f2d742bad
commit
389529217e
@@ -135,6 +135,12 @@ void ofmem_arch_early_map_pages(ucell phys, ucell virt, ucell size, ucell mode)
|
|||||||
/* none yet */
|
/* none yet */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
retain_t *ofmem_arch_get_retained(void)
|
||||||
|
{
|
||||||
|
/* not implemented */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/* OF private allocations */
|
/* OF private allocations */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ static union {
|
|||||||
|
|
||||||
translation_t **g_ofmem_translations = &s_ofmem_data.ofmem.trans;
|
translation_t **g_ofmem_translations = &s_ofmem_data.ofmem.trans;
|
||||||
|
|
||||||
|
extern uint64_t qemu_mem_size;
|
||||||
|
|
||||||
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);
|
||||||
@@ -61,6 +63,12 @@ ucell ofmem_arch_get_virt_top(void)
|
|||||||
return (ucell)TOP_OF_RAM;
|
return (ucell)TOP_OF_RAM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
retain_t *ofmem_arch_get_retained(void)
|
||||||
|
{
|
||||||
|
/* Retained area is at the top of physical RAM */
|
||||||
|
return (retain_t *)(qemu_mem_size - sizeof(retain_t));
|
||||||
|
}
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/* misc */
|
/* misc */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
@@ -79,8 +87,6 @@ ucell ofmem_arch_default_translation_mode( ucell phys )
|
|||||||
/* init / cleanup */
|
/* init / cleanup */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
extern uint64_t qemu_mem_size;
|
|
||||||
|
|
||||||
static int remap_page_range( ucell phys, ucell virt, ucell size, ucell mode )
|
static int remap_page_range( ucell phys, ucell virt, ucell size, ucell mode )
|
||||||
{
|
{
|
||||||
ofmem_claim_phys(phys, size, 0);
|
ofmem_claim_phys(phys, size, 0);
|
||||||
@@ -95,32 +101,37 @@ 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
|
#define RETAIN_MAGIC 0x1100220033004400
|
||||||
|
|
||||||
void ofmem_init( void )
|
void ofmem_init( void )
|
||||||
{
|
{
|
||||||
retain_t *retained = (retain_t *)RETAIN_OFMEM;
|
retain_t *retained = ofmem_arch_get_retained();
|
||||||
|
int i;
|
||||||
|
|
||||||
/* Clear all memory except any retained areas */
|
memset(&s_ofmem_data, 0, sizeof(s_ofmem_data));
|
||||||
if (!(retained->magic == RETAIN_MAGIC)) {
|
s_ofmem_data.ofmem.ramsize = qemu_mem_size;
|
||||||
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);
|
||||||
|
|
||||||
/* Map the memory */
|
/* Map the memory */
|
||||||
ofmem_map_page_range(0, 0, qemu_mem_size, 0x36);
|
ofmem_map_page_range(0, 0, qemu_mem_size, 0x36);
|
||||||
}
|
|
||||||
|
|
||||||
|
if (!(retained->magic == RETAIN_MAGIC)) {
|
||||||
|
OFMEM_TRACE("ofmem_init: no retained magic found, creating\n");
|
||||||
|
retained->magic = RETAIN_MAGIC;
|
||||||
|
retained->numentries = 0;
|
||||||
|
} else {
|
||||||
|
OFMEM_TRACE("ofmem_init: retained magic found, total %lld mappings\n", retained->numentries);
|
||||||
|
|
||||||
|
/* Mark physical addresses as used so they are not reallocated */
|
||||||
|
for (i = 0; i < retained->numentries; i++) {
|
||||||
|
ofmem_claim_phys(retained->retain_phys_range[i].start,
|
||||||
|
retained->retain_phys_range[i].size, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset retained area for next reset */
|
||||||
|
retained->magic = RETAIN_MAGIC;
|
||||||
|
retained->numentries = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -46,28 +46,29 @@ 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 */
|
/* structure for retained data */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ucell magic;
|
ucell magic;
|
||||||
range_t *retain_phys_range;
|
ucell numentries;
|
||||||
|
range_t retain_phys_range[8]; /* physical memory that should survive a warm reset */
|
||||||
} retain_t;
|
} 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);
|
||||||
extern ucell ofmem_arch_get_heap_top(void);
|
extern ucell ofmem_arch_get_heap_top(void);
|
||||||
extern ucell ofmem_arch_get_virt_top(void);
|
extern ucell ofmem_arch_get_virt_top(void);
|
||||||
extern ucell ofmem_arch_default_translation_mode( ucell phys );
|
extern retain_t* ofmem_arch_get_retained(void);
|
||||||
extern void ofmem_arch_early_map_pages(ucell phys, ucell virt, ucell size,
|
extern ucell ofmem_arch_default_translation_mode( ucell phys );
|
||||||
|
extern void ofmem_arch_early_map_pages(ucell phys, ucell virt, ucell size,
|
||||||
ucell mode);
|
ucell mode);
|
||||||
extern void ofmem_arch_unmap_pages(ucell virt, ucell size);
|
extern void ofmem_arch_unmap_pages(ucell virt, ucell size);
|
||||||
/* sparc64 uses this method */
|
/* sparc64 uses this method */
|
||||||
extern int ofmem_map_page_range( ucell phys, ucell virt, ucell size,
|
extern int ofmem_map_page_range( ucell phys, ucell virt, ucell size,
|
||||||
ucell mode );
|
ucell mode );
|
||||||
|
|
||||||
/* malloc interface */
|
/* malloc interface */
|
||||||
|
|||||||
@@ -452,7 +452,7 @@ ucell ofmem_claim_virt( ucell virt, ucell size, ucell align )
|
|||||||
/* if align != 0, phys is ignored. Returns -1 on error */
|
/* if align != 0, phys is ignored. Returns -1 on error */
|
||||||
ucell ofmem_retain( ucell phys, ucell size, ucell align )
|
ucell ofmem_retain( ucell phys, ucell size, ucell align )
|
||||||
{
|
{
|
||||||
ofmem_t *ofmem = ofmem_arch_get_private();
|
retain_t *retained = ofmem_arch_get_retained();
|
||||||
ucell retain_phys;
|
ucell retain_phys;
|
||||||
|
|
||||||
OFMEM_TRACE("ofmem_retain phys=" FMT_ucellx " size=" FMT_ucellx
|
OFMEM_TRACE("ofmem_retain phys=" FMT_ucellx " size=" FMT_ucellx
|
||||||
@@ -461,8 +461,11 @@ ucell ofmem_retain( ucell phys, ucell size, ucell align )
|
|||||||
|
|
||||||
retain_phys = ofmem_claim_phys_( phys, size, align, 0, get_ram_size(), 0 );
|
retain_phys = ofmem_claim_phys_( phys, size, align, 0, get_ram_size(), 0 );
|
||||||
|
|
||||||
/* Also add to the retain_phys_range list */
|
/* Add to the retain_phys_range list */
|
||||||
add_entry( phys, size, &ofmem->retain_phys_range );
|
retained->retain_phys_range[retained->numentries].next = NULL;
|
||||||
|
retained->retain_phys_range[retained->numentries].start = retain_phys;
|
||||||
|
retained->retain_phys_range[retained->numentries].size = size;
|
||||||
|
retained->numentries++;
|
||||||
|
|
||||||
return retain_phys;
|
return retain_phys;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user