allow to emulate more guest RAM that host could allocate, it is fine until guest tries to access all the allocated memory

This commit is contained in:
Stanislav Shwartsman 2009-10-16 17:10:36 +00:00
parent 140d2d1508
commit 92aecadb18
3 changed files with 128 additions and 25 deletions

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: main.cc,v 1.405 2009-08-22 19:30:23 sshwarts Exp $
// $Id: main.cc,v 1.406 2009-10-16 17:10:36 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2002 MandrakeSoft S.A.
@ -1055,7 +1055,7 @@ void bx_init_hardware()
bx_param_num_c *bxp_memsize = SIM->get_param_num(BXPN_MEM_SIZE);
Bit32u memSize = bxp_memsize->get() * 1024*1024;
BX_MEM(0)->init_memory(memSize);
BX_MEM(0)->init_memory(memSize, memSize);
// First load the BIOS and VGABIOS
BX_MEM(0)->load_ROM(SIM->get_param_string(BXPN_ROM_PATH)->getptr(),

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: memory.h,v 1.62 2009-10-15 21:39:40 sshwarts Exp $
// $Id: memory.h,v 1.63 2009-10-16 17:10:36 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -75,18 +75,20 @@ private:
unsigned n_monitors;
#endif
Bit64u len; // could be > 4G in future
Bit64u len, allocated; // could be > 4G
Bit8u *actual_vector;
Bit8u *vector; // aligned correctly
Bit8u **blocks;
Bit8u *rom; // 512k BIOS rom space + 128k expansion rom space
Bit8u *bogus; // 4k for unexisting memory
unsigned used_blocks;
public:
BX_MEM_C();
~BX_MEM_C();
BX_MEM_SMF Bit8u* get_vector(bx_phy_address addr);
BX_MEM_SMF void init_memory(Bit32u memsize);
BX_MEM_SMF void init_memory(Bit64u guest, Bit64u host);
BX_MEM_SMF void cleanup_memory(void);
BX_MEM_SMF void enable_smram(bx_bool enable, bx_bool restricted);
BX_MEM_SMF void disable_smram(void);
@ -110,6 +112,7 @@ public:
BX_MEM_SMF bx_bool unregisterMemoryHandlers(memory_handler_t read_handler, memory_handler_t write_handler,
bx_phy_address begin_addr, bx_phy_address end_addr);
BX_MEM_SMF Bit64u get_memory_len(void);
BX_MEM_SMF void allocate_block(Bit32u index);
#if BX_SUPPORT_MONITOR_MWAIT
BX_MEM_SMF void set_monitor(unsigned cpu);
@ -118,15 +121,30 @@ public:
BX_MEM_SMF void check_monitor(bx_phy_address addr, unsigned len);
#endif
BX_MEM_SMF void register_state(void);
void register_state(void);
friend Bit64s memory_param_save_handler(void *devptr, bx_param_c *param, Bit64s val);
friend Bit64s memory_param_restore_handler(void *devptr, bx_param_c *param, Bit64s val);
};
BOCHSAPI extern BX_MEM_C bx_mem;
// must be power of two
#define BX_MEM_BLOCK_LEN (2*1024*1024) /* 2M blocks */
/*
BX_CPP_INLINE Bit8u* BX_MEM_C::get_vector(bx_phy_address addr)
{
return (BX_MEM_THIS vector + addr);
}
*/
BX_CPP_INLINE Bit8u* BX_MEM_C::get_vector(bx_phy_address addr)
{
Bit32u block = addr / BX_MEM_BLOCK_LEN;
if (! BX_MEM_THIS blocks[block]) allocate_block(block);
return BX_MEM_THIS blocks[block] + (Bit32u)(addr & (BX_MEM_BLOCK_LEN-1));
}
BX_CPP_INLINE Bit64u BX_MEM_C::get_memory_len(void)
{

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: misc_mem.cc,v 1.133 2009-10-15 21:39:40 sshwarts Exp $
// $Id: misc_mem.cc,v 1.134 2009-10-16 17:10:36 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2002 MandrakeSoft S.A.
@ -43,7 +43,9 @@ BX_MEM_C::BX_MEM_C()
vector = NULL;
actual_vector = NULL;
blocks = NULL;
len = 0;
used_blocks = 0;
memory_handlers = NULL;
}
@ -68,40 +70,66 @@ BX_MEM_C::~BX_MEM_C()
cleanup_memory();
}
void BX_MEM_C::init_memory(Bit32u memsize)
void BX_MEM_C::init_memory(Bit64u guest, Bit64u host)
{
unsigned idx;
BX_DEBUG(("Init $Id: misc_mem.cc,v 1.133 2009-10-15 21:39:40 sshwarts Exp $"));
BX_DEBUG(("Init $Id: misc_mem.cc,v 1.134 2009-10-16 17:10:36 sshwarts Exp $"));
// accept only memory size which is multiply of 1M
BX_ASSERT((host & 0xfffff) == 0);
BX_ASSERT((guest & 0xfffff) == 0);
if (BX_MEM_THIS actual_vector != NULL) {
BX_INFO (("freeing existing memory vector"));
BX_INFO(("freeing existing memory vector"));
delete [] BX_MEM_THIS actual_vector;
BX_MEM_THIS actual_vector = NULL;
BX_MEM_THIS vector = NULL;
BX_MEM_THIS blocks = NULL;
}
BX_MEM_THIS vector = ::alloc_vector_aligned(&BX_MEM_THIS actual_vector, memsize + BIOSROMSZ + EXROMSIZE + 4096, BX_MEM_VECTOR_ALIGN);
BX_INFO (("allocated memory at %p. after alignment, vector=%p",
BX_MEM_THIS vector = ::alloc_vector_aligned(&BX_MEM_THIS actual_vector, host + BIOSROMSZ + EXROMSIZE + 4096, BX_MEM_VECTOR_ALIGN);
BX_INFO(("allocated memory at %p. after alignment, vector=%p",
BX_MEM_THIS actual_vector, BX_MEM_THIS vector));
BX_MEM_THIS len = memsize;
BX_MEM_THIS memory_handlers = new struct memory_handler_struct *[BX_MEM_HANDLERS];
BX_MEM_THIS rom = &BX_MEM_THIS vector[memsize];
BX_MEM_THIS bogus = &BX_MEM_THIS vector[memsize + BIOSROMSZ + EXROMSIZE];
BX_MEM_THIS len = guest;
BX_MEM_THIS allocated = host;
BX_MEM_THIS rom = &BX_MEM_THIS vector[host];
BX_MEM_THIS bogus = &BX_MEM_THIS vector[host + BIOSROMSZ + EXROMSIZE];
memset(BX_MEM_THIS rom, 0xff, BIOSROMSZ + EXROMSIZE + 4096);
for (idx = 0; idx < BX_MEM_HANDLERS; idx++)
BX_MEM_THIS memory_handlers[idx] = NULL;
for (idx = 0; idx < 65; idx++)
BX_MEM_THIS rom_present[idx] = 0;
// block must be large enough to fit num_blocks in 32-bit
BX_ASSERT((BX_MEM_THIS len / BX_MEM_BLOCK_LEN) <= 0xffffffff);
Bit32u num_blocks = BX_MEM_THIS len / BX_MEM_BLOCK_LEN;
BX_INFO(("%.2fMB", (float)(BX_MEM_THIS len / (1024.0*1024.0))));
BX_INFO(("mem block size = 0x%08x, blocks=%u", BX_MEM_BLOCK_LEN, num_blocks));
BX_MEM_THIS blocks = new Bit8u* [num_blocks];
if (0) {
// all guest memory is allocated, just map it
for (idx = 0; idx < num_blocks; idx++) {
BX_MEM_THIS blocks[idx] = BX_MEM_THIS vector + (idx * BX_MEM_BLOCK_LEN);
}
BX_MEM_THIS used_blocks = num_blocks;
}
else {
// host cannot allocate all requested guest memory
for (idx = 0; idx < num_blocks; idx++) {
BX_MEM_THIS blocks[idx] = NULL;
}
BX_MEM_THIS used_blocks = 0;
}
BX_MEM_THIS memory_handlers = new struct memory_handler_struct *[BX_MEM_HANDLERS];
for (idx = 0; idx < BX_MEM_HANDLERS; idx++)
BX_MEM_THIS memory_handlers[idx] = NULL;
BX_MEM_THIS pci_enabled = SIM->get_param_bool(BXPN_I440FX_SUPPORT)->get();
BX_MEM_THIS smram_available = 0;
BX_MEM_THIS smram_enable = 0;
BX_MEM_THIS smram_restricted = 0;
// accept only memory size which is multiply of 1M
BX_ASSERT((BX_MEM_THIS len & 0xfffff) == 0);
BX_INFO(("%.2fMB", (float)(BX_MEM_THIS len / (1024.0*1024.0))));
#if BX_SUPPORT_MONITOR_MWAIT
BX_MEM_THIS monitor_active = new bx_bool[BX_SMP_PROCESSORS];
for (int i=0; i<BX_SMP_PROCESSORS;i++) {
@ -110,14 +138,71 @@ void BX_MEM_C::init_memory(Bit32u memsize)
BX_MEM_THIS n_monitors = 0;
#endif
register_state();
BX_MEM_THIS register_state();
}
void BX_MEM_C::allocate_block(Bit32u block)
{
Bit32u num_blocks = BX_MEM_THIS len / BX_MEM_BLOCK_LEN;
if (BX_MEM_THIS used_blocks >= num_blocks) {
BX_PANIC(("FATAL ERROR: all available memory is already allocated !"));
}
else {
BX_MEM_THIS blocks[block] = BX_MEM_THIS vector + (BX_MEM_THIS used_blocks * BX_MEM_BLOCK_LEN);
BX_MEM_THIS used_blocks++;
}
}
Bit64s memory_param_save_handler(void *devptr, bx_param_c *param, Bit64s val)
{
const char *pname = param->get_name();
if (! strncmp(pname, "blk", 3)) {
Bit32u blk_index = atoi(pname + 3);
if (! BX_MEM(0)->blocks[blk_index]) {
return -1;
}
else {
val = (Bit32u) (BX_MEM(0)->blocks[blk_index] - BX_MEM(0)->vector);
if (val & (BX_MEM_BLOCK_LEN-1)) return -2;
return val / BX_MEM_BLOCK_LEN;
}
}
return -1;
}
Bit64s memory_param_restore_handler(void *devptr, bx_param_c *param, Bit64s val)
{
const char *pname = param->get_name();
if (! strncmp(pname, "blk", 3)) {
Bit32u blk_index = atoi(pname + 3);
if(val < 0)
BX_MEM(0)->blocks[blk_index] = NULL;
else
BX_MEM(0)->blocks[blk_index] = BX_MEM(0)->vector + val * BX_MEM_BLOCK_LEN;
}
return -1;
}
void BX_MEM_C::register_state()
{
bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "memory", "Memory State", 3);
new bx_shadow_data_c(list, "ram", BX_MEM_THIS vector, BX_MEM_THIS len);
bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "memory", "Memory State", 6);
new bx_shadow_data_c(list, "ram", BX_MEM_THIS vector, BX_MEM_THIS allocated);
BXRS_DEC_PARAM_FIELD(list, len, BX_MEM_THIS len);
BXRS_DEC_PARAM_FIELD(list, allocated, BX_MEM_THIS allocated);
BXRS_DEC_PARAM_FIELD(list, used_blocks, BX_MEM_THIS used_blocks);
Bit32u num_blocks = BX_MEM_THIS len / BX_MEM_BLOCK_LEN;
bx_list_c *mapping = new bx_list_c(list, "mapping", num_blocks);
for (Bit32u blk=0; blk < num_blocks; blk++) {
char param_name[15];
sprintf(param_name, "blk%d", blk);
bx_param_num_c *param = new bx_param_num_c(mapping, param_name, "", "", 0, BX_MAX_BIT32U, 0);
param->set_base(BASE_DEC);
param->set_sr_handlers(this, memory_param_save_handler, memory_param_restore_handler);
}
#if BX_SUPPORT_MONITOR_MWAIT
bx_list_c *monitors = new bx_list_c(list, "monitors", BX_SMP_PROCESSORS+1);
BXRS_PARAM_BOOL(monitors, n_monitors, BX_MEM_THIS n_monitors);