- rewrite of the PCI memory management code for the expansion ROM and BIOS area

- store memory type array in the memory object to avoid calling the pci plugin
    frequently. The pci code calls a memory method to change the memory type in
    case the PAM registers are modified.
  - removed now obsolete code and minor cleanups
This commit is contained in:
Volker Ruppert 2012-01-19 18:32:11 +00:00
parent 12afed23a1
commit ed669adfd1
7 changed files with 125 additions and 179 deletions

View File

@ -295,9 +295,6 @@ public:
STUBFUNC(pci, pci_set_base_io);
return 0;
}
virtual Bit8u rd_memType(Bit32u addr) { return 0; }
virtual Bit8u wr_memType(Bit32u addr) { return 0; }
};
class BOCHSAPI bx_pci2isa_stub_c : public bx_devmodel_c, public bx_pci_device_stub_c {

View File

@ -91,8 +91,6 @@ void bx_pci_bridge_c::init(void)
for (i=0x0CFC; i<=0x0CFF; i++) {
DEV_register_ioread_handler(this, read_handler, i, "i440FX", 7);
}
for (i=0x0CFC; i<=0x0CFF; i++) {
DEV_register_iowrite_handler(this, write_handler, i, "i440FX", 7);
}
@ -276,12 +274,14 @@ Bit32u bx_pci_bridge_c::pci_read_handler(Bit8u address, unsigned io_len)
// pci configuration space write callback handler
void bx_pci_bridge_c::pci_write_handler(Bit8u address, Bit32u value, unsigned io_len)
{
Bit8u value8;
Bit8u value8, oldval;
unsigned area;
if ((address >= 0x10) && (address < 0x34))
return;
for (unsigned i=0; i<io_len; i++) {
value8 = (value >> (i*8)) & 0xFF;
oldval = BX_PCI_THIS pci_conf[address+i];
switch (address+i) {
case 0x04:
BX_PCI_THIS pci_conf[address+i] = (value8 & 0x40) | 0x06;
@ -296,9 +296,23 @@ void bx_pci_bridge_c::pci_write_handler(Bit8u address, Bit32u value, unsigned io
case 0x5D:
case 0x5E:
case 0x5F:
BX_INFO(("440FX PMC write to PAM register %x (TLB Flush)", address+i));
BX_PCI_THIS pci_conf[address+i] = value8;
bx_pc_system.MemoryMappingChanged();
if (value != oldval) {
BX_PCI_THIS pci_conf[address+i] = value8;
if ((address+i) == 0x59) {
area = BX_MEM_AREA_F0000;
DEV_mem_set_memory_type(area, 0, (value >> 4) & 0x1);
DEV_mem_set_memory_type(area, 1, (value >> 5) & 0x1);
} else {
area = ((address+i) - 0x5a) << 1;
DEV_mem_set_memory_type(area, 0, (value >> 0) & 0x1);
DEV_mem_set_memory_type(area, 1, (value >> 1) & 0x1);
area++;
DEV_mem_set_memory_type(area, 0, (value >> 4) & 0x1);
DEV_mem_set_memory_type(area, 1, (value >> 5) & 0x1);
}
BX_INFO(("440FX PMC write to PAM register %x (TLB Flush)", address+i));
bx_pc_system.MemoryMappingChanged();
}
break;
case 0x72:
smram_control(value); // SMRAM conrol register
@ -366,94 +380,6 @@ void bx_pci_bridge_c::smram_control(Bit8u value8)
BX_PCI_THIS pci_conf[0x72] = value8;
}
Bit8u bx_pci_bridge_c::rd_memType(Bit32u addr)
{
switch ((addr & 0xFC000) >> 12) {
case 0xC0:
return (BX_PCI_THIS pci_conf[0x5A] & 0x1);
case 0xC4:
return ((BX_PCI_THIS pci_conf[0x5A] >> 4) & 0x1);
case 0xC8:
return (BX_PCI_THIS pci_conf[0x5B] & 0x1);
case 0xCC:
return ((BX_PCI_THIS pci_conf[0x5B] >> 4) & 0x1);
case 0xD0:
return (BX_PCI_THIS pci_conf[0x5C] & 0x1);
case 0xD4:
return ((BX_PCI_THIS pci_conf[0x5C] >> 4) & 0x1);
case 0xD8:
return (BX_PCI_THIS pci_conf[0x5D] & 0x1);
case 0xDC:
return ((BX_PCI_THIS pci_conf[0x5D] >> 4) & 0x1);
case 0xE0:
return (BX_PCI_THIS pci_conf[0x5E] & 0x1);
case 0xE4:
return ((BX_PCI_THIS pci_conf[0x5E] >> 4) & 0x1);
case 0xE8:
return (BX_PCI_THIS pci_conf[0x5F] & 0x1);
case 0xEC:
return ((BX_PCI_THIS pci_conf[0x5F] >> 4) & 0x1);
case 0xF0:
case 0xF4:
case 0xF8:
case 0xFC:
return ((BX_PCI_THIS pci_conf[0x59] >> 4) & 0x1);
default:
BX_PANIC(("rd_memType () Error: Memory Type not known !"));
break;
}
return(0); // keep compiler happy
}
Bit8u bx_pci_bridge_c::wr_memType(Bit32u addr)
{
switch ((addr & 0xFC000) >> 12) {
case 0xC0:
return ((BX_PCI_THIS pci_conf[0x5A] >> 1) & 0x1);
case 0xC4:
return ((BX_PCI_THIS pci_conf[0x5A] >> 5) & 0x1);
case 0xC8:
return ((BX_PCI_THIS pci_conf[0x5B] >> 1) & 0x1);
case 0xCC:
return ((BX_PCI_THIS pci_conf[0x5B] >> 5) & 0x1);
case 0xD0:
return ((BX_PCI_THIS pci_conf[0x5C] >> 1) & 0x1);
case 0xD4:
return ((BX_PCI_THIS pci_conf[0x5C] >> 5) & 0x1);
case 0xD8:
return ((BX_PCI_THIS pci_conf[0x5D] >> 1) & 0x1);
case 0xDC:
return ((BX_PCI_THIS pci_conf[0x5D] >> 5) & 0x1);
case 0xE0:
return ((BX_PCI_THIS pci_conf[0x5E] >> 1) & 0x1);
case 0xE4:
return ((BX_PCI_THIS pci_conf[0x5E] >> 5) & 0x1);
case 0xE8:
return ((BX_PCI_THIS pci_conf[0x5F] >> 1) & 0x1);
case 0xEC:
return ((BX_PCI_THIS pci_conf[0x5F] >> 5) & 0x1);
case 0xF0:
case 0xF4:
case 0xF8:
case 0xFC:
return ((BX_PCI_THIS pci_conf[0x59] >> 5) & 0x1);
default:
BX_PANIC(("wr_memType () Error: Memory Type not known !"));
break;
}
return(0); // keep compiler happy
}
void bx_pci_bridge_c::debug_dump()
{
int i;

View File

@ -59,8 +59,6 @@ public:
bx_write_handler_t f2, Bit32u *addr,
Bit8u *pci_conf, unsigned size,
const Bit8u *iomask, const char *name);
virtual Bit8u rd_memType(Bit32u addr);
virtual Bit8u wr_memType(Bit32u addr);
virtual Bit32u pci_read_handler(Bit8u address, unsigned io_len);
virtual void pci_write_handler(Bit8u address, Bit32u value, unsigned io_len);

View File

@ -155,20 +155,16 @@ mem_write:
// ignore write to ROM
#else
// Write Based on 440fx Programming
if (BX_MEM_THIS pci_enabled && ((a20addr & 0xfffc0000) == 0x000c0000))
{
switch (DEV_pci_wr_memtype((Bit32u) a20addr)) {
case 0x1: // Writes to ShadowRAM
BX_DEBUG(("Writing to ShadowRAM: address 0x" FMT_PHY_ADDRX ", data %02x", a20addr, *data_ptr));
*(BX_MEM_THIS get_vector(a20addr)) = *data_ptr;
break;
case 0x0: // Writes to ROM, Inhibit
BX_DEBUG(("Write to ROM ignored: address 0x" FMT_PHY_ADDRX ", data %02x", a20addr, *data_ptr));
break;
default:
BX_PANIC(("writePhysicalPage: default case"));
if (BX_MEM_THIS pci_enabled && ((a20addr & 0xfffc0000) == 0x000c0000)) {
unsigned area = (unsigned)(a20addr >> 14) & 0x0f;
if (area > BX_MEM_AREA_F0000) area = BX_MEM_AREA_F0000;
if (BX_MEM_THIS memory_type[area][1] == 1) {
// Writes to ShadowRAM
BX_DEBUG(("Writing to ShadowRAM: address 0x" FMT_PHY_ADDRX ", data %02x", a20addr, *data_ptr));
*(BX_MEM_THIS get_vector(a20addr)) = *data_ptr;
} else {
// Writes to ROM, Inhibit
BX_DEBUG(("Write to ROM ignored: address 0x" FMT_PHY_ADDRX ", data %02x", a20addr, *data_ptr));
}
}
#endif
@ -290,23 +286,20 @@ mem_read:
}
#if BX_SUPPORT_PCI
if (BX_MEM_THIS pci_enabled && ((a20addr & 0xfffc0000) == 0x000c0000))
{
switch (DEV_pci_rd_memtype((Bit32u) a20addr)) {
case 0x0: // Read from ROM
if ((a20addr & 0xfffe0000) == 0x000e0000) {
// last 128K of BIOS ROM mapped to 0xE0000-0xFFFFF
*data_ptr = BX_MEM_THIS rom[BIOS_MAP_LAST128K(a20addr)];
}
else {
*data_ptr = BX_MEM_THIS rom[(a20addr & EXROM_MASK) + BIOSROMSZ];
}
break;
case 0x1: // Read from ShadowRAM
*data_ptr = *(BX_MEM_THIS get_vector(a20addr));
break;
default:
BX_PANIC(("readPhysicalPage: default case"));
if (BX_MEM_THIS pci_enabled && ((a20addr & 0xfffc0000) == 0x000c0000)) {
unsigned area = (unsigned)(a20addr >> 14) & 0x0f;
if (area > BX_MEM_AREA_F0000) area = BX_MEM_AREA_F0000;
if (BX_MEM_THIS memory_type[area][0] == 0) {
// Read from ROM
if ((a20addr & 0xfffe0000) == 0x000e0000) {
// last 128K of BIOS ROM mapped to 0xE0000-0xFFFFF
*data_ptr = BX_MEM_THIS rom[BIOS_MAP_LAST128K(a20addr)];
} else {
*data_ptr = BX_MEM_THIS rom[(a20addr & EXROM_MASK) + BIOSROMSZ];
}
} else {
// Read from ShadowRAM
*data_ptr = *(BX_MEM_THIS get_vector(a20addr));
}
}
else

View File

@ -44,6 +44,22 @@ class BX_CPU_C;
#define BIOS_MAP_LAST128K(addr) (((addr) | 0xfff00000) & BIOS_MASK)
enum memory_area_t {
BX_MEM_AREA_C0000 = 0,
BX_MEM_AREA_C4000,
BX_MEM_AREA_C8000,
BX_MEM_AREA_CC000,
BX_MEM_AREA_D0000,
BX_MEM_AREA_D4000,
BX_MEM_AREA_D8000,
BX_MEM_AREA_DC000,
BX_MEM_AREA_E0000,
BX_MEM_AREA_E4000,
BX_MEM_AREA_E8000,
BX_MEM_AREA_EC000,
BX_MEM_AREA_F0000
};
typedef bx_bool (*memory_handler_t)(bx_phy_address addr, unsigned len, void *data, void *param);
// return a pointer to 4K region containing <addr> or NULL if direct access is not allowed
// same format as getHostMemAddr method
@ -77,6 +93,7 @@ private:
Bit8u *rom; // 512k BIOS rom space + 128k expansion rom space
Bit8u *bogus; // 4k for unexisting memory
bx_bool rom_present[65];
bx_bool memory_type[13][2];
Bit32u used_blocks;
#if BX_LARGE_RAMFILE
@ -99,6 +116,8 @@ public:
BX_MEM_SMF void disable_smram(void);
BX_MEM_SMF bx_bool is_smram_accessible(void);
BX_MEM_SMF void set_memory_type(memory_area_t area, bx_bool rw, bx_bool dram);
BX_MEM_SMF Bit8u* getHostMemAddr(BX_CPU_C *cpu, bx_phy_address addr, unsigned rw);
// Note: accesses should always be contained within a single page

View File

@ -38,15 +38,21 @@ Bit8u* const BX_MEM_C::swapped_out = ((Bit8u*)NULL - sizeof(Bit8u));
BX_MEM_C::BX_MEM_C()
{
put("MEM0");
int i;
put("memory", "MEM0");
vector = NULL;
actual_vector = NULL;
blocks = NULL;
len = 0;
used_blocks = 0;
for (int i = 0; i < 65; i++)
for (i = 0; i < 65; i++)
rom_present[i] = 0;
for (i = 0; i <= BX_MEM_AREA_F0000; i++) {
memory_type[i][0] = 0;
memory_type[i][1] = 0;
}
memory_handlers = NULL;
@ -292,6 +298,8 @@ void memory_param_restore_handler(void *devptr, bx_param_c *param, Bit64s val)
void BX_MEM_C::register_state()
{
char param_name[15];
bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "memory", "Memory State", 6);
Bit32u num_blocks = BX_MEM_THIS len / BX_MEM_BLOCK_LEN;
#if BX_LARGE_RAMFILE
@ -306,12 +314,18 @@ void BX_MEM_C::register_state()
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);
}
bx_list_c *memtype = new bx_list_c(list, "memtype", 26);
for (int i = 0; i <= BX_MEM_AREA_F0000; i++) {
sprintf(param_name, "%d_r", i);
new bx_shadow_bool_c(memtype, param_name, &BX_MEM_THIS memory_type[i][0]);
sprintf(param_name, "%d_w", i);
new bx_shadow_bool_c(memtype, param_name, &BX_MEM_THIS memory_type[i][1]);
}
}
void BX_MEM_C::cleanup_memory()
@ -545,23 +559,20 @@ bx_bool BX_MEM_C::dbg_fetch_mem(BX_CPU_C *cpu, bx_phy_address addr, unsigned len
*buf = DEV_vga_mem_read(addr);
}
#if BX_SUPPORT_PCI
else if (BX_MEM_THIS pci_enabled && (addr >= 0x000c0000 && addr < 0x00100000))
{
switch (DEV_pci_rd_memtype ((Bit32u) addr)) {
case 0x0: // Read from ROM
if ((addr & 0xfffe0000) == 0x000e0000) {
// last 128K of BIOS ROM mapped to 0xE0000-0xFFFFF
*buf = BX_MEM_THIS rom[BIOS_MAP_LAST128K(addr)];
}
else {
*buf = BX_MEM_THIS rom[(addr & EXROM_MASK) + BIOSROMSZ];
}
break;
case 0x1: // Read from ShadowRAM
*buf = *(BX_MEM_THIS get_vector(addr));
break;
default:
BX_PANIC(("dbg_fetch_mem: default case"));
else if (BX_MEM_THIS pci_enabled && (addr >= 0x000c0000 && addr < 0x00100000)) {
unsigned area = (unsigned)(addr >> 14) & 0x0f;
if (area > BX_MEM_AREA_F0000) area = BX_MEM_AREA_F0000;
if (BX_MEM_THIS memory_type[area][0] == 0) {
// Read from ROM
if ((addr & 0xfffe0000) == 0x000e0000) {
// last 128K of BIOS ROM mapped to 0xE0000-0xFFFFF
*buf = BX_MEM_THIS rom[BIOS_MAP_LAST128K(addr)];
} else {
*buf = BX_MEM_THIS rom[(addr & EXROM_MASK) + BIOSROMSZ];
}
} else {
// Read from ShadowRAM
*buf = *(BX_MEM_THIS get_vector(addr));
}
}
#endif // #if BX_SUPPORT_PCI
@ -616,16 +627,14 @@ bx_bool BX_MEM_C::dbg_set_mem(bx_phy_address addr, unsigned len, Bit8u *buf)
DEV_vga_mem_write(addr, *buf);
}
#if BX_SUPPORT_PCI
else if (BX_MEM_THIS pci_enabled && (addr >= 0x000c0000 && addr < 0x00100000))
{
switch (DEV_pci_wr_memtype (addr)) {
case 0x0: // Ignore write to ROM
break;
case 0x1: // Write to ShadowRAM
*(BX_MEM_THIS get_vector(addr)) = *buf;
break;
default:
BX_PANIC(("dbg_fetch_mem: default case"));
else if (BX_MEM_THIS pci_enabled && (addr >= 0x000c0000 && addr < 0x00100000)) {
unsigned area = (unsigned)(addr >> 14) & 0x0f;
if (area > BX_MEM_AREA_F0000) area = BX_MEM_AREA_F0000;
if (BX_MEM_THIS memory_type[area][1] == 1) {
// Write to ShadowRAM
*(BX_MEM_THIS get_vector(addr)) = *buf;
} else {
// Ignore write to ROM
}
}
#endif // #if BX_SUPPORT_PCI
@ -729,23 +738,20 @@ Bit8u *BX_MEM_C::getHostMemAddr(BX_CPU_C *cpu, bx_phy_address addr, unsigned rw)
if ((a20addr >= 0x000a0000 && a20addr < 0x000c0000))
return(NULL); // Vetoed! Mem mapped IO (VGA)
#if BX_SUPPORT_PCI
else if (BX_MEM_THIS pci_enabled && (a20addr >= 0x000c0000 && a20addr < 0x00100000))
{
switch (DEV_pci_rd_memtype ((Bit32u) a20addr)) {
case 0x0: // Read from ROM
if ((a20addr & 0xfffe0000) == 0x000e0000) {
// last 128K of BIOS ROM mapped to 0xE0000-0xFFFFF
return (Bit8u *) &BX_MEM_THIS rom[BIOS_MAP_LAST128K(a20addr)];
}
else {
return (Bit8u *) &BX_MEM_THIS rom[(a20addr & EXROM_MASK) + BIOSROMSZ];
}
break;
case 0x1: // Read from ShadowRAM
return BX_MEM_THIS get_vector(a20addr);
default:
BX_PANIC(("getHostMemAddr(): default case"));
return(NULL);
else if (BX_MEM_THIS pci_enabled && (a20addr >= 0x000c0000 && a20addr < 0x00100000)) {
unsigned area = (unsigned)(a20addr >> 14) & 0x0f;
if (area > BX_MEM_AREA_F0000) area = BX_MEM_AREA_F0000;
if (BX_MEM_THIS memory_type[area][0] == 0) {
// Read from ROM
if ((a20addr & 0xfffe0000) == 0x000e0000) {
// last 128K of BIOS ROM mapped to 0xE0000-0xFFFFF
return (Bit8u *) &BX_MEM_THIS rom[BIOS_MAP_LAST128K(a20addr)];
} else {
return (Bit8u *) &BX_MEM_THIS rom[(a20addr & EXROM_MASK) + BIOSROMSZ];
}
} else {
// Read from ShadowRAM
return BX_MEM_THIS get_vector(a20addr);
}
}
#endif
@ -884,6 +890,13 @@ bx_bool BX_MEM_C::is_smram_accessible(void)
(BX_MEM_THIS smram_enable || !BX_MEM_THIS smram_restricted);
}
void BX_MEM_C::set_memory_type(memory_area_t area, bx_bool rw, bx_bool dram)
{
if (area <= BX_MEM_AREA_F0000) {
BX_MEM_THIS memory_type[area][rw] = dram;
}
}
#if BX_SUPPORT_MONITOR_MWAIT
//

View File

@ -235,8 +235,6 @@ extern "C" {
(bx_devices.pluginPciBridge->pci_set_base_mem(a,b,c,d,e,f))
#define DEV_pci_set_base_io(a,b,c,d,e,f,g,h) \
(bx_devices.pluginPciBridge->pci_set_base_io(a,b,c,d,e,f,g,h))
#define DEV_pci_rd_memtype(addr) bx_devices.pluginPciBridge->rd_memType(addr)
#define DEV_pci_wr_memtype(addr) bx_devices.pluginPciBridge->wr_memType(addr)
#define DEV_pci_debug_dump() bx_devices.pluginPciBridge->debug_dump()
#define DEV_ide_bmdma_present() bx_devices.pluginPciIdeController->bmdma_present()
#define DEV_ide_bmdma_set_irq(a) bx_devices.pluginPciIdeController->bmdma_set_irq(a)
@ -255,6 +253,8 @@ extern "C" {
bx_devices.mem->registerMemoryHandlers(param,rh,wh,b,e)
#define DEV_unregister_memory_handlers(param,b,e) \
bx_devices.mem->unregisterMemoryHandlers(param,b,e)
#define DEV_mem_set_memory_type(a,b,c) \
bx_devices.mem->set_memory_type((memory_area_t)a,b,c)
///////// USB device macros
#define DEV_usb_init_device(a,b,c,d) (usbdev_type)bx_devices.pluginUsbDevCtl->init_device(a,b,(void**)c,d)