diff options
Diffstat (limited to 'tools/ioemu/memory')
-rw-r--r-- | tools/ioemu/memory/Makefile | 12 | ||||
-rw-r--r-- | tools/ioemu/memory/memory.cc | 450 | ||||
-rw-r--r-- | tools/ioemu/memory/memory.h | 98 | ||||
-rw-r--r-- | tools/ioemu/memory/misc_mem.cc | 443 |
4 files changed, 1003 insertions, 0 deletions
diff --git a/tools/ioemu/memory/Makefile b/tools/ioemu/memory/Makefile new file mode 100644 index 0000000000..eb9be7da4b --- /dev/null +++ b/tools/ioemu/memory/Makefile @@ -0,0 +1,12 @@ +TOPDIR= .. +CXXFLAGS=-I. -I../include -I.. +OBJS= memory.o misc_mem.o + +all: libmemory.a + +libmemory.a: $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +include $(TOPDIR)/mk/helix.mk + +install:: all diff --git a/tools/ioemu/memory/memory.cc b/tools/ioemu/memory/memory.cc new file mode 100644 index 0000000000..7ee55f360f --- /dev/null +++ b/tools/ioemu/memory/memory.cc @@ -0,0 +1,450 @@ +///////////////////////////////////////////////////////////////////////// +// $Id: memory.cc,v 1.27 2003/03/02 23:59:12 cbothamy Exp $ +///////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2001 MandrakeSoft S.A. +// +// MandrakeSoft S.A. +// 43, rue d'Aboukir +// 75002 Paris - France +// http://www.linux-mandrake.com/ +// http://www.mandrakesoft.com/ +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + + + + + + +#include "bochs.h" +#define LOG_THIS BX_MEM_THIS + +#if BX_PROVIDE_CPU_MEMORY + + void BX_CPP_AttrRegparmN(3) +BX_MEM_C::writePhysicalPage(BX_CPU_C *cpu, Bit32u addr, unsigned len, void *data) +{ + Bit8u *data_ptr; + Bit32u a20addr; + + // Note: accesses should always be contained within a single page now. + +#if BX_IODEBUG_SUPPORT + bx_iodebug_c::mem_write(cpu, addr, len, data); +#endif + if (addr+len > this->dma_limit) + BX_PANIC(("address too large: %lx > %lx", addr+len, this->dma_limit)); + + a20addr = A20ADDR(addr); + BX_INSTR_PHY_WRITE(cpu->which_cpu(), a20addr, len); + +#if BX_DEBUGGER + // (mch) Check for physical write break points, TODO + // (bbd) Each breakpoint should have an associated CPU#, TODO + for (int i = 0; i < num_write_watchpoints; i++) + if (write_watchpoint[i] == a20addr) { + BX_CPU(0)->watchpoint = a20addr; + BX_CPU(0)->break_point = BREAK_POINT_WRITE; + break; + } +#endif + +#if BX_SupportICache + if (a20addr < BX_MEM_THIS len) + cpu->iCache.decWriteStamp(cpu, a20addr); +#endif + + if ( a20addr <= BX_MEM_THIS len ) { + // all of data is within limits of physical memory + if ( (a20addr & 0xfff80000) != 0x00080000 ) { + if (len == 4) { + WriteHostDWordToLittleEndian(&vector[a20addr], *(Bit32u*)data); + BX_DBG_DIRTY_PAGE(a20addr >> 12); + return; + } + if (len == 2) { + WriteHostWordToLittleEndian(&vector[a20addr], *(Bit16u*)data); + BX_DBG_DIRTY_PAGE(a20addr >> 12); + return; + } + if (len == 1) { + * ((Bit8u *) (&vector[a20addr])) = * (Bit8u *) data; + BX_DBG_DIRTY_PAGE(a20addr >> 12); + return; + } + // len == other, just fall thru to special cases handling + } + +#ifdef BX_LITTLE_ENDIAN + data_ptr = (Bit8u *) data; +#else // BX_BIG_ENDIAN + data_ptr = (Bit8u *) data + (len - 1); +#endif + +write_one: + if ( (a20addr & 0xfff80000) != 0x00080000 ) { + // addr *not* in range 00080000 .. 000FFFFF + vector[a20addr] = *data_ptr; + BX_DBG_DIRTY_PAGE(a20addr >> 12); +inc_one: + if (len == 1) return; + len--; + a20addr++; +#ifdef BX_LITTLE_ENDIAN + data_ptr++; +#else // BX_BIG_ENDIAN + data_ptr--; +#endif + goto write_one; + } + + // addr in range 00080000 .. 000FFFFF + + if (a20addr <= 0x0009ffff) { + // regular memory 80000 .. 9FFFF + vector[a20addr] = *data_ptr; + BX_DBG_DIRTY_PAGE(a20addr >> 12); + goto inc_one; + } + if (a20addr <= 0x000bffff) { + // VGA memory A0000 .. BFFFF + DEV_vga_mem_write(a20addr, *data_ptr); + BX_DBG_DIRTY_PAGE(a20addr >> 12); + BX_DBG_UCMEM_REPORT(a20addr, 1, BX_WRITE, *data_ptr); // obsolete + goto inc_one; + } + // adapter ROM C0000 .. DFFFF + // ROM BIOS memory E0000 .. FFFFF + // (ignore write) + //BX_INFO(("ROM lock %08x: len=%u", + // (unsigned) a20addr, (unsigned) len)); +#if BX_PCI_SUPPORT == 0 +#if BX_SHADOW_RAM + // Write it since its in shadow RAM + vector[a20addr] = *data_ptr; + BX_DBG_DIRTY_PAGE(a20addr >> 12); +#else + // ignore write to ROM +#endif +#else + // Write Based on 440fx Programming + if (bx_options.Oi440FXSupport->get () && + ((a20addr >= 0xC0000) && (a20addr <= 0xFFFFF))) { + switch (DEV_pci_wr_memtype(a20addr & 0xFC000)) { + case 0x1: // Writes to ShadowRAM +// BX_INFO(("Writing to ShadowRAM %08x, len %u ! ", (unsigned) a20addr, (unsigned) len)); + shadow[a20addr - 0xc0000] = *data_ptr; + BX_DBG_DIRTY_PAGE(a20addr >> 12); + goto inc_one; + + case 0x0: // Writes to ROM, Inhibit + BX_DEBUG(("Write to ROM ignored: address %08x, data %02x", (unsigned) a20addr, *data_ptr)); + goto inc_one; + default: + BX_PANIC(("writePhysicalPage: default case")); + goto inc_one; + } + } +#endif + goto inc_one; + } + + else { + // some or all of data is outside limits of physical memory + unsigned i; + +#ifdef BX_LITTLE_ENDIAN + data_ptr = (Bit8u *) data; +#else // BX_BIG_ENDIAN + data_ptr = (Bit8u *) data + (len - 1); +#endif + + +#if BX_SUPPORT_VBE + // Check VBE LFB support + + if ((a20addr >= VBE_DISPI_LFB_PHYSICAL_ADDRESS) && + (a20addr < (VBE_DISPI_LFB_PHYSICAL_ADDRESS + VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES))) + { + for (i = 0; i < len; i++) { + + //if (a20addr < BX_MEM_THIS len) { + //vector[a20addr] = *data_ptr; + //BX_DBG_DIRTY_PAGE(a20addr >> 12); + DEV_vga_mem_write(a20addr, *data_ptr); + // } + + // otherwise ignore byte, since it overruns memory + addr++; + a20addr = (addr); +#ifdef BX_LITTLE_ENDIAN + data_ptr++; +#else // BX_BIG_ENDIAN + data_ptr--; +#endif + } + return; + } + +#endif + + +#if BX_SUPPORT_APIC + bx_generic_apic_c *local_apic = &cpu->local_apic; + bx_generic_apic_c *ioapic = bx_devices.ioapic; + if (local_apic->is_selected (a20addr, len)) { + local_apic->write (a20addr, (Bit32u *)data, len); + return; + } else if (ioapic->is_selected (a20addr, len)) { + ioapic->write (a20addr, (Bit32u *)data, len); + return; + } + else +#endif + for (i = 0; i < len; i++) { + if (a20addr < BX_MEM_THIS len) { + vector[a20addr] = *data_ptr; + BX_DBG_DIRTY_PAGE(a20addr >> 12); + } + // otherwise ignore byte, since it overruns memory + addr++; + a20addr = (addr); +#ifdef BX_LITTLE_ENDIAN + data_ptr++; +#else // BX_BIG_ENDIAN + data_ptr--; +#endif + } + return; + } +} + + + void BX_CPP_AttrRegparmN(3) +BX_MEM_C::readPhysicalPage(BX_CPU_C *cpu, Bit32u addr, unsigned len, void *data) +{ + Bit8u *data_ptr; + Bit32u a20addr; + +#if BX_IODEBUG_SUPPORT + bx_iodebug_c::mem_read(cpu, addr, len, data); +#endif + + if (addr+len > this->dma_limit) + BX_PANIC(("address too large: %lx > %lx", addr+len, this->dma_limit)); + + a20addr = A20ADDR(addr); + BX_INSTR_PHY_READ(cpu->which_cpu(), a20addr, len); + +#if BX_DEBUGGER + // (mch) Check for physical read break points, TODO + // (bbd) Each breakpoint should have an associated CPU#, TODO + for (int i = 0; i < num_read_watchpoints; i++) + if (read_watchpoint[i] == a20addr) { + BX_CPU(0)->watchpoint = a20addr; + BX_CPU(0)->break_point = BREAK_POINT_READ; + break; + } +#endif + + if ( (a20addr + len) <= BX_MEM_THIS len ) { + // all of data is within limits of physical memory + if ( (a20addr & 0xfff80000) != 0x00080000 ) { + if (len == 4) { + ReadHostDWordFromLittleEndian(&vector[a20addr], * (Bit32u*) data); + return; + } + if (len == 2) { + ReadHostWordFromLittleEndian(&vector[a20addr], * (Bit16u*) data); + return; + } + if (len == 1) { + * (Bit8u *) data = * ((Bit8u *) (&vector[a20addr])); + return; + } + // len == 3 case can just fall thru to special cases handling + } + + +#ifdef BX_LITTLE_ENDIAN + data_ptr = (Bit8u *) data; +#else // BX_BIG_ENDIAN + data_ptr = (Bit8u *) data + (len - 1); +#endif + + + +read_one: + if ( (a20addr & 0xfff80000) != 0x00080000 ) { + // addr *not* in range 00080000 .. 000FFFFF + *data_ptr = vector[a20addr]; +inc_one: + if (len == 1) return; + len--; + a20addr++; +#ifdef BX_LITTLE_ENDIAN + data_ptr++; +#else // BX_BIG_ENDIAN + data_ptr--; +#endif + goto read_one; + } + + // addr in range 00080000 .. 000FFFFF +#if BX_PCI_SUPPORT == 0 + if ((a20addr <= 0x0009ffff) || (a20addr >= 0x000c0000) ) { + // regular memory 80000 .. 9FFFF, C0000 .. F0000 + *data_ptr = vector[a20addr]; + goto inc_one; + } + // VGA memory A0000 .. BFFFF + *data_ptr = DEV_vga_mem_read(a20addr); + BX_DBG_UCMEM_REPORT(a20addr, 1, BX_READ, *data_ptr); // obsolete + goto inc_one; +#else // #if BX_PCI_SUPPORT == 0 + if (a20addr <= 0x0009ffff) { + *data_ptr = vector[a20addr]; + goto inc_one; + } + if (a20addr <= 0x000BFFFF) { + // VGA memory A0000 .. BFFFF + *data_ptr = DEV_vga_mem_read(a20addr); + BX_DBG_UCMEM_REPORT(a20addr, 1, BX_READ, *data_ptr); + goto inc_one; + } + + // a20addr in C0000 .. FFFFF + if (!bx_options.Oi440FXSupport->get ()) { + *data_ptr = vector[a20addr]; + goto inc_one; + } + else { + switch (DEV_pci_rd_memtype(a20addr & 0xFC000)) { + case 0x1: // Read from ShadowRAM + *data_ptr = shadow[a20addr - 0xc0000]; + BX_INFO(("Reading from ShadowRAM %08x, Data %02x ", (unsigned) a20addr, *data_ptr)); + goto inc_one; + + case 0x0: // Read from ROM + *data_ptr = vector[a20addr]; + //BX_INFO(("Reading from ROM %08x, Data %02x ", (unsigned) a20addr, *data_ptr)); + goto inc_one; + default: + BX_PANIC(("::readPhysicalPage: default case")); + } + } + goto inc_one; +#endif // #if BX_PCI_SUPPORT == 0 + } + else { + // some or all of data is outside limits of physical memory + unsigned i; + +#ifdef BX_LITTLE_ENDIAN + data_ptr = (Bit8u *) data; +#else // BX_BIG_ENDIAN + data_ptr = (Bit8u *) data + (len - 1); +#endif + +#if BX_SUPPORT_VBE + // Check VBE LFB support + + if ((a20addr >= VBE_DISPI_LFB_PHYSICAL_ADDRESS) && + (a20addr < (VBE_DISPI_LFB_PHYSICAL_ADDRESS + VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES))) + { + for (i = 0; i < len; i++) { + + //if (a20addr < BX_MEM_THIS len) { + //vector[a20addr] = *data_ptr; + //BX_DBG_DIRTY_PAGE(a20addr >> 12); + *data_ptr = DEV_vga_mem_read(a20addr); + // } + + // otherwise ignore byte, since it overruns memory + addr++; + a20addr = (addr); +#ifdef BX_LITTLE_ENDIAN + data_ptr++; +#else // BX_BIG_ENDIAN + data_ptr--; +#endif + } + return; + } + +#endif + + +#if BX_SUPPORT_APIC + bx_generic_apic_c *local_apic = &cpu->local_apic; + bx_generic_apic_c *ioapic = bx_devices.ioapic; + if (local_apic->is_selected (addr, len)) { + local_apic->read (addr, data, len); + return; + } else if (ioapic->is_selected (addr, len)) { + ioapic->read (addr, data, len); + return; + } +#endif + for (i = 0; i < len; i++) { +#if BX_PCI_SUPPORT == 0 + if (a20addr < BX_MEM_THIS len) + *data_ptr = vector[a20addr]; + else + *data_ptr = 0xff; +#else // BX_PCI_SUPPORT == 0 + if (a20addr < BX_MEM_THIS len) { + if ((a20addr >= 0x000C0000) && (a20addr <= 0x000FFFFF)) { + if (!bx_options.Oi440FXSupport->get ()) + *data_ptr = vector[a20addr]; + else { + switch (DEV_pci_rd_memtype(a20addr & 0xFC000)) { + case 0x0: // Read from ROM + *data_ptr = vector[a20addr]; + //BX_INFO(("Reading from ROM %08x, Data %02x ", (unsigned) a20addr, *data_ptr)); + break; + + case 0x1: // Read from Shadow RAM + *data_ptr = shadow[a20addr - 0xc0000]; + BX_INFO(("Reading from ShadowRAM %08x, Data %02x ", (unsigned) a20addr, *data_ptr)); + break; + default: + BX_PANIC(("readPhysicalPage: default case")); + } // Switch + } + } + else { + *data_ptr = vector[a20addr]; + BX_INFO(("Reading from Norm %08x, Data %02x ", (unsigned) a20addr, *data_ptr)); + } + } + else + *data_ptr = 0xff; +#endif // BX_PCI_SUPPORT == 0 + addr++; + a20addr = (addr); +#ifdef BX_LITTLE_ENDIAN + data_ptr++; +#else // BX_BIG_ENDIAN + data_ptr--; +#endif + } + return; + } +} + +#endif // #if BX_PROVIDE_CPU_MEMORY diff --git a/tools/ioemu/memory/memory.h b/tools/ioemu/memory/memory.h new file mode 100644 index 0000000000..2af787b3c3 --- /dev/null +++ b/tools/ioemu/memory/memory.h @@ -0,0 +1,98 @@ +///////////////////////////////////////////////////////////////////////// +// $Id: memory.h,v 1.16 2003/08/05 13:19:35 cbothamy Exp $ +///////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2001 MandrakeSoft S.A. +// +// MandrakeSoft S.A. +// 43, rue d'Aboukir +// 75002 Paris - France +// http://www.linux-mandrake.com/ +// http://www.mandrakesoft.com/ +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + + +#define BX_USE_MEM_SMF 0 + +#if BX_USE_MEM_SMF +// if static member functions on, then there is only one memory +# define BX_MEM_SMF static +# define BX_MEM_THIS BX_MEM(0)-> +#else +# define BX_MEM_SMF +# define BX_MEM_THIS this-> +#endif + +// alignment of memory vector, must be a power of 2 +#define BX_MEM_VECTOR_ALIGN 4096 + +class BOCHSAPI BX_MEM_C : public logfunctions { + +public: + Bit8u *actual_vector; + Bit8u *vector; // aligned correctly + size_t len; + size_t dma_limit; + size_t megabytes; // (len in Megabytes) +#if BX_PCI_SUPPORT + Bit8u shadow[4*16*4096]; // 256k of memory +#endif +#if BX_DEBUGGER + unsigned char dbg_dirty_pages[(BX_MAX_DIRTY_PAGE_TABLE_MEGS * 1024 * 1024) / 4096]; + Bit32u dbg_count_dirty_pages () { + return (BX_MAX_DIRTY_PAGE_TABLE_MEGS * 1024 * 1024) / 4096; + } +#endif + unsigned long *page_array; /* for get_pfn_list() */ + + BX_MEM_C(void); + //BX_MEM_C(size_t memsize); + ~BX_MEM_C(void); + BX_MEM_SMF void alloc_vector_aligned (size_t bytes, size_t alignment) BX_CPP_AttrRegparmN(2); + BX_MEM_SMF void init_memory(int memsize); + BX_MEM_SMF void readPhysicalPage(BX_CPU_C *cpu, Bit32u addr, + unsigned len, void *data) BX_CPP_AttrRegparmN(3); + BX_MEM_SMF void writePhysicalPage(BX_CPU_C *cpu, Bit32u addr, + unsigned len, void *data) BX_CPP_AttrRegparmN(3); + BX_MEM_SMF void load_ROM(const char *path, Bit32u romaddress, Bit8u type); + BX_MEM_SMF Bit32u get_memory_in_k(void); +#if BX_PCI_SUPPORT + BX_MEM_SMF Bit8u* pci_fetch_ptr(Bit32u addr) BX_CPP_AttrRegparmN(1); +#endif + BX_MEM_SMF bx_bool dbg_fetch_mem(Bit32u addr, unsigned len, Bit8u *buf); + BX_MEM_SMF bx_bool dbg_set_mem(Bit32u addr, unsigned len, Bit8u *buf); + BX_MEM_SMF bx_bool dbg_crc32( + unsigned long (*f)(unsigned char *buf, int len), + Bit32u addr1, Bit32u addr2, Bit32u *crc); + BX_MEM_SMF Bit8u * getHostMemAddr(BX_CPU_C *cpu, Bit32u a20Addr, unsigned op) BX_CPP_AttrRegparmN(3); + }; + +#if BX_PROVIDE_CPU_MEMORY==1 + +#if BX_SMP_PROCESSORS==1 +BOCHSAPI extern BX_MEM_C bx_mem; +#else +BOCHSAPI extern BX_MEM_C *bx_mem_array[BX_ADDRESS_SPACES]; +#endif /* BX_SMP_PROCESSORS */ + +#endif /* BX_PROVIDE_CPU_MEMORY==1 */ + +#if BX_DEBUGGER +# define BX_DBG_DIRTY_PAGE(page) BX_MEM(0)->dbg_dirty_pages[page] = 1; +#else +# define BX_DBG_DIRTY_PAGE(page) +#endif diff --git a/tools/ioemu/memory/misc_mem.cc b/tools/ioemu/memory/misc_mem.cc new file mode 100644 index 0000000000..a69591dc1d --- /dev/null +++ b/tools/ioemu/memory/misc_mem.cc @@ -0,0 +1,443 @@ +///////////////////////////////////////////////////////////////////////// +// $Id: misc_mem.cc,v 1.41 2003/09/10 16:34:56 vruppert Exp $ +///////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2002 MandrakeSoft S.A. +// +// MandrakeSoft S.A. +// 43, rue d'Aboukir +// 75002 Paris - France +// http://www.linux-mandrake.com/ +// http://www.mandrakesoft.com/ +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + + + + + + +#include "bochs.h" +#ifdef BX_USE_VMX +extern "C" { +#include <sys/mman.h> +} +#endif + +#define LOG_THIS BX_MEM(0)-> + +#if BX_PROVIDE_CPU_MEMORY + Bit32u +BX_MEM_C::get_memory_in_k(void) +{ + return(BX_MEM_THIS megabytes * 1024); +} +#endif // #if BX_PROVIDE_CPU_MEMORY + + +#if BX_PROVIDE_CPU_MEMORY + // BX_MEM_C constructor +BX_MEM_C::BX_MEM_C(void) +{ + char mem[6]; + snprintf(mem, 6, "MEM%d", BX_SIM_ID); + put(mem); + settype(MEMLOG); + + vector = NULL; + actual_vector = NULL; + len = 0; + megabytes = 0; +} +#endif // #if BX_PROVIDE_CPU_MEMORY + + + +#if BX_PROVIDE_CPU_MEMORY +void BX_CPP_AttrRegparmN(2) +BX_MEM_C::alloc_vector_aligned (size_t bytes, size_t alignment) +{ + if (actual_vector != NULL) { + BX_INFO (("freeing existing memory vector")); + delete [] actual_vector; + actual_vector = NULL; + vector = NULL; + } + Bit64u test_mask = alignment - 1; + actual_vector = new Bit8u [bytes+test_mask]; + // round address forward to nearest multiple of alignment. Alignment + // MUST BE a power of two for this to work. + unsigned long masked = ((unsigned long)(actual_vector + test_mask)) & ~test_mask; + vector = (Bit8u *)masked; + // sanity check: no lost bits during pointer conversion + BX_ASSERT (sizeof(masked) >= sizeof(vector)); + // sanity check: after realignment, everything fits in allocated space + BX_ASSERT (vector+bytes <= actual_vector+bytes+test_mask); + BX_INFO (("allocated memory at %p. after alignment, vector=%p", + actual_vector, vector)); +} +#endif + +// We can't use this because alloc_vector_aligned uses BX_INFO, but the object does not yet exists +/* +#if BX_PROVIDE_CPU_MEMORY + // BX_MEM_C constructor + +BX_MEM_C::BX_MEM_C(size_t memsize) +{ + char mem[6]; + snprintf(mem, 6, "MEM%d", BX_SIM_ID); + put(mem); + settype(MEMLOG); + + vector = NULL; + actual_vector = NULL; + alloc_vector_aligned (memsize, BX_MEM_VECTOR_ALIGN); + len = memsize; + megabytes = len / (1024*1024); +} +#endif // #if BX_PROVIDE_CPU_MEMORY +*/ + + +#if BX_PROVIDE_CPU_MEMORY +// BX_MEM_C destructor +BX_MEM_C::~BX_MEM_C(void) +{ + if (this-> vector != NULL) { + delete [] actual_vector; + actual_vector = NULL; + vector = NULL; + } + else { + BX_DEBUG(("(%u) memory not freed as it wasn't allocated!", BX_SIM_ID)); + } +} +#endif // #if BX_PROVIDE_CPU_MEMORY + + +#if BX_PROVIDE_CPU_MEMORY + void +BX_MEM_C::init_memory(int memsize) +{ + BX_DEBUG(("Init $Id: misc_mem.cc,v 1.41 2003/09/10 16:34:56 vruppert Exp $")); + // you can pass 0 if memory has been allocated already through + // the constructor, or the desired size of memory if it hasn't + // BX_INFO(("%.2fMB", (float)(BX_MEM_THIS megabytes) )); + +#ifndef BX_USE_VMX + if (BX_MEM_THIS vector == NULL) { + // memory not already allocated, do now... + alloc_vector_aligned (memsize, BX_MEM_VECTOR_ALIGN); +#endif + BX_MEM_THIS len = memsize; + BX_MEM_THIS megabytes = memsize / (1024*1024); + BX_INFO(("%.2fMB", (float)(BX_MEM_THIS megabytes) )); +#ifndef BX_USE_VMX + } +#endif + +#if BX_DEBUGGER + if (megabytes > BX_MAX_DIRTY_PAGE_TABLE_MEGS) { + BX_INFO(("Error: memory larger than dirty page table can handle")); + BX_PANIC(("Error: increase BX_MAX_DIRTY_PAGE_TABLE_MEGS")); + } +#endif + + unsigned long nr_pages = megabytes * (1024 * 1024/getpagesize()); + + if ( (page_array = (unsigned long *) + malloc(nr_pages * sizeof(unsigned long))) == NULL) + { + BX_ERROR(("Could not allocate memory")); + return; + } + + if ( xc_get_pfn_list(xc_handle, domid, page_array, nr_pages) != nr_pages ) + { + BX_ERROR(("Could not get the page frame list")); + return; + } + +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1 << PAGE_SHIFT) + + if ((vector = (Bit8u *) xc_map_foreign_batch(xc_handle, domid, + PROT_READ|PROT_WRITE, + page_array, + nr_pages - 1)) == 0) { + BX_ERROR(("Could not map guest physical")); + return; + } + + BX_MEM_THIS dma_limit = (nr_pages - 1) << PAGE_SHIFT; + BX_INFO(("DMA limit: %lx", BX_MEM_THIS dma_limit)); + + shared_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, + PROT_READ|PROT_WRITE, + page_array[nr_pages - 1]); + + /* Initialize shared page */ + memset(shared_page, 0, PAGE_SIZE); +} +#endif // #if BX_PROVIDE_CPU_MEMORY + + +#if BX_PROVIDE_CPU_MEMORY + void + // Values for type : + // 0 : System Bios + // 1 : VGA Bios + // 2 : Optional ROM Bios +BX_MEM_C::load_ROM(const char *path, Bit32u romaddress, Bit8u type) +{ + struct stat stat_buf; + int fd, ret; + unsigned long size, offset; + + if (*path == '\0') { + if (type == 2) { + BX_PANIC(( "ROM: Optional BIOS image undefined.")); + } + else if (type == 1) { + BX_PANIC(( "ROM: VGA BIOS image undefined.")); + } + else { + BX_PANIC(( "ROM: System BIOS image undefined.")); + } + return; + } + // read in ROM BIOS image file + fd = open(path, O_RDONLY +#ifdef O_BINARY + | O_BINARY +#endif + ); + if (fd < 0) { + if (type < 2) { + BX_PANIC(( "ROM: couldn't open ROM image file '%s'.", path)); + } + else { + BX_ERROR(( "ROM: couldn't open ROM image file '%s'.", path)); + } + return; + } + ret = fstat(fd, &stat_buf); + if (ret) { + if (type < 2) { + BX_PANIC(( "ROM: couldn't stat ROM image file '%s'.", path)); + } + else { + BX_ERROR(( "ROM: couldn't stat ROM image file '%s'.", path)); + } + return; + } + + size = stat_buf.st_size; + + if ( (romaddress + size) > BX_MEM_THIS len ) { + BX_PANIC(( "ROM: ROM address range > physical memsize!")); + return; + } + + offset = 0; + while (size > 0) { + ret = read(fd, (bx_ptr_t) &BX_MEM_THIS vector[romaddress + offset], size); + if (ret <= 0) { + BX_PANIC(( "ROM: read failed on BIOS image: '%s'",path)); + } + size -= ret; + offset += ret; + } + close(fd); + BX_INFO(("rom at 0x%05x/%u ('%s')", + (unsigned) romaddress, + (unsigned) stat_buf.st_size, + path + )); +} +#endif // #if BX_PROVIDE_CPU_MEMORY + +#if BX_PCI_SUPPORT + Bit8u* BX_CPP_AttrRegparmN(1) +BX_MEM_C::pci_fetch_ptr(Bit32u addr) +{ + if (bx_options.Oi440FXSupport->get ()) { + switch (DEV_pci_rd_memtype (addr)) { + case 0x1: // Read from ShadowRAM + return (&BX_MEM_THIS shadow[addr - 0xc0000]); + + case 0x0: // Read from ROM + return (&BX_MEM_THIS vector[addr]); + default: + BX_PANIC(("pci_fetch_ptr(): default case")); + return(0); + } + } + else + return (&BX_MEM_THIS vector[addr]); +} +#endif + + +#if ( BX_DEBUGGER || BX_DISASM || BX_GDBSTUB) + bx_bool +BX_MEM_C::dbg_fetch_mem(Bit32u addr, unsigned len, Bit8u *buf) +{ + if ( (addr + len) > this->len ) { + BX_INFO(("dbg_fetch_mem out of range. 0x%x > 0x%x", + addr+len, this->len)); + return(0); // error, beyond limits of memory + } + for (; len>0; len--) { + if ( (addr & 0xfffe0000) == 0x000a0000 ) { + *buf = DEV_vga_mem_read(addr); + } + else { +#if BX_PCI_SUPPORT == 0 + *buf = vector[addr]; +#else + if ( bx_options.Oi440FXSupport->get () && + ((addr >= 0x000C0000) && (addr <= 0x000FFFFF)) ) { + switch (DEV_pci_rd_memtype (addr)) { + case 0x1: // Fetch from ShadowRAM + *buf = shadow[addr - 0xc0000]; +// BX_INFO(("Fetching from ShadowRAM %06x, len %u !", (unsigned)addr, (unsigned)len)); + break; + + case 0x0: // Fetch from ROM + *buf = vector[addr]; +// BX_INFO(("Fetching from ROM %06x, Data %02x ", (unsigned)addr, *buf)); + break; + default: + BX_PANIC(("dbg_fetch_mem: default case")); + } + } + else + *buf = vector[addr]; +#endif // #if BX_PCI_SUPPORT == 0 + } + buf++; + addr++; + } + return(1); +} +#endif + +#if BX_DEBUGGER || BX_GDBSTUB + bx_bool +BX_MEM_C::dbg_set_mem(Bit32u addr, unsigned len, Bit8u *buf) +{ + if ( (addr + len) > this->len ) { + return(0); // error, beyond limits of memory + } + for (; len>0; len--) { + if ( (addr & 0xfffe0000) == 0x000a0000 ) { + DEV_vga_mem_write(addr, *buf); + } + else + vector[addr] = *buf; + buf++; + addr++; + } + return(1); +} +#endif + + bx_bool +BX_MEM_C::dbg_crc32(unsigned long (*f)(unsigned char *buf, int len), + Bit32u addr1, Bit32u addr2, Bit32u *crc) +{ + unsigned len; + + *crc = 0; + if (addr1 > addr2) + return(0); + + if (addr2 >= this->len) { + return(0); // error, specified address past last phy mem addr + } + + len = 1 + addr2 - addr1; + *crc = f(vector + addr1, len); + + return(1); +} + + + Bit8u * BX_CPP_AttrRegparmN(3) +BX_MEM_C::getHostMemAddr(BX_CPU_C *cpu, Bit32u a20Addr, unsigned op) + // Return a host address corresponding to the guest physical memory + // address (with A20 already applied), given that the calling + // code will perform an 'op' operation. This address will be + // used for direct access to guest memory as an acceleration by + // a few instructions, like REP {MOV, INS, OUTS, etc}. + // Values of 'op' are { BX_READ, BX_WRITE, BX_RW }. + + // The other assumption is that the calling code _only_ accesses memory + // directly within the page that encompasses the address requested. +{ + if ( a20Addr >= BX_MEM_THIS len ) + return(NULL); // Error, requested addr is out of bounds. + if (op == BX_READ) { + if ( (a20Addr > 0x9ffff) && (a20Addr < 0xc0000) ) + return(NULL); // Vetoed! Mem mapped IO (VGA) +#if !BX_PCI_SUPPORT + return( (Bit8u *) & vector[a20Addr] ); +#else + else if ( (a20Addr < 0xa0000) || (a20Addr > 0xfffff) + || (!bx_options.Oi440FXSupport->get ()) ) + return( (Bit8u *) & vector[a20Addr] ); + else { + switch (DEV_pci_rd_memtype (a20Addr)) { + case 0x0: // Read from ROM + return ( (Bit8u *) & vector[a20Addr]); + case 0x1: // Read from ShadowRAM + return( (Bit8u *) & shadow[a20Addr - 0xc0000]); + default: + BX_PANIC(("getHostMemAddr(): default case")); + return(0); + } + } +#endif + } + else { // op == {BX_WRITE, BX_RW} + Bit8u *retAddr; + + if ( (a20Addr < 0xa0000) || (a20Addr > 0xfffff) ) { + retAddr = (Bit8u *) & vector[a20Addr]; + } +#if !BX_PCI_SUPPORT + else + return(NULL); // Vetoed! Mem mapped IO (VGA) and ROMs +#else + else if ( (a20Addr < 0xc0000) || (!bx_options.Oi440FXSupport->get ()) ) + return(NULL); // Vetoed! Mem mapped IO (VGA) and ROMs + else if (DEV_pci_wr_memtype (a20Addr) == 1) { + // Write to ShadowRAM + retAddr = (Bit8u *) & shadow[a20Addr - 0xc0000]; + } + else + return(NULL); // Vetoed! ROMs +#endif + +#if BX_SupportICache + cpu->iCache.decWriteStamp(cpu, a20Addr); +#endif + + return(retAddr); + } +} |