aboutsummaryrefslogtreecommitdiffstats
path: root/tools/ioemu/memory/misc_mem.cc
diff options
context:
space:
mode:
Diffstat (limited to 'tools/ioemu/memory/misc_mem.cc')
-rw-r--r--tools/ioemu/memory/misc_mem.cc443
1 files changed, 443 insertions, 0 deletions
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);
+ }
+}