diff --git a/bochs/memory/Makefile.in b/bochs/memory/Makefile.in index ec6bb7d24..603af4984 100644 --- a/bochs/memory/Makefile.in +++ b/bochs/memory/Makefile.in @@ -40,7 +40,7 @@ RANLIB = @RANLIB@ BX_INCDIRS = -I.. -I$(srcdir)/.. -I../@INSTRUMENT_DIR@ -I$(srcdir)/../@INSTRUMENT_DIR@ BX_OBJS = \ - memory.o misc_mem.o + memory.o memory_stub.o misc_mem.o BX_INCLUDES = ../bochs.h ../config.h @@ -79,6 +79,15 @@ memory.o: memory.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../cpu/access.h ../iodev/iodev.h ../plugin.h ../extplugin.h \ ../param_names.h ../pc_system.h ../memory/memory-bochs.h \ ../gui/siminterface.h ../gui/paramtree.h ../gui/gui.h +memory_stub.o: memory_stub.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ + ../logio.h ../misc/bswap.h ../pc_system.h ../param_names.h ../cpu/cpu.h \ + ../bx_debug/debug.h ../config.h ../osdep.h ../cpu/decoder/decoder.h \ + ../cpu/decoder/features.h ../instrument/stubs/instrument.h ../cpu/i387.h \ + ../cpu/fpu/softfloat.h ../cpu/fpu/tag_w.h ../cpu/fpu/status_w.h \ + ../cpu/fpu/control_w.h ../cpu/crregs.h ../cpu/descriptor.h \ + ../cpu/decoder/instr.h ../cpu/lazy_flags.h ../cpu/tlb.h ../cpu/icache.h \ + ../cpu/apic.h ../cpu/xmm.h ../cpu/vmx.h ../cpu/svm.h ../cpu/cpuid.h \ + ../cpu/access.h ../memory/memory-bochs.h misc_mem.o: misc_mem.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../logio.h \ ../misc/bswap.h ../param_names.h ../cpu/cpu.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../cpu/decoder/decoder.h \ diff --git a/bochs/memory/memory-bochs.h b/bochs/memory/memory-bochs.h index 7a518a1c6..68d0cdafc 100644 --- a/bochs/memory/memory-bochs.h +++ b/bochs/memory/memory-bochs.h @@ -2,7 +2,7 @@ // $Id$ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2001-2021 The Bochs Project +// Copyright (C) 2001-2023 The Bochs Project // // I/O memory handlers API Copyright (C) 2003 by Frank Cornelis // @@ -42,6 +42,73 @@ const Bit32u EXROMSIZE = (0x20000); // ROMs 0xc0000-0xdffff (area 0xe0000-0xf const Bit32u BIOS_MASK = BIOSROMSZ-1; const Bit32u EXROM_MASK = EXROMSIZE-1; +class BOCHSAPI BX_MEMORY_STUB_C : public logfunctions { +protected: + Bit64u len, allocated; // could be > 4G + Bit32u block_size; // individual block size, must be power of 2 + 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 + + Bit32u used_blocks; +#if BX_LARGE_RAMFILE + static Bit8u * const swapped_out; // NULL; // (NULL - sizeof(Bit8u)); + Bit32u next_swapout_idx; + FILE *overflow_file; + + BX_MEM_SMF void read_block(Bit32u block); +#endif + +public: + BX_MEMORY_STUB_C(); + virtual ~BX_MEMORY_STUB_C(); + + BX_MEM_SMF void init_memory(Bit64u guest, Bit64u host, Bit32u block_size); + BX_MEM_SMF void cleanup_memory(void); + BX_MEM_SMF Bit8u* get_vector(bx_phy_address addr); + + 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 + BX_MEM_SMF void readPhysicalPage(BX_CPU_C *cpu, bx_phy_address addr, + unsigned len, void *data); + BX_MEM_SMF void writePhysicalPage(BX_CPU_C *cpu, bx_phy_address addr, + unsigned len, void *data); + + BX_MEM_SMF bool dbg_fetch_mem(BX_CPU_C *cpu, bx_phy_address addr, unsigned len, Bit8u *buf); +#if (BX_DEBUGGER || BX_GDBSTUB) + BX_MEM_SMF bool dbg_set_mem(BX_CPU_C *cpu, bx_phy_address addr, unsigned len, Bit8u *buf); + BX_MEM_SMF bool dbg_crc32(bx_phy_address addr1, bx_phy_address addr2, Bit32u *crc); +#endif + + BX_MEM_SMF Bit64u get_memory_len(void); + BX_MEM_SMF void allocate_block(Bit32u index); + BX_MEM_SMF Bit8u* alloc_vector_aligned(Bit64u bytes, Bit64u alignment); + +#if BX_SUPPORT_MONITOR_MWAIT + BX_MEM_SMF bool is_monitor(bx_phy_address begin_addr, unsigned len); + BX_MEM_SMF void check_monitor(bx_phy_address addr, unsigned len); +#endif +}; + +typedef bool (*memory_handler_t)(bx_phy_address addr, unsigned len, void *data, void *param); +// return a pointer to 4K region containing or NULL if direct access is not allowed +// same format as getHostMemAddr method +typedef Bit8u* (*memory_direct_access_handler_t)(bx_phy_address addr, unsigned rw, void *param); + +struct memory_handler_struct { + struct memory_handler_struct *next; + void *param; + bx_phy_address begin; + bx_phy_address end; + Bit16u bitmap; + memory_handler_t read_handler; + memory_handler_t write_handler; + memory_direct_access_handler_t da_handler; +}; + #define BIOS_MAP_LAST128K(addr) (((addr) | 0xfff00000) & BIOS_MASK) #define BIOS_ROM_LOWER 0x01 @@ -64,38 +131,16 @@ enum memory_area_t { BX_MEM_AREA_F0000 }; -typedef bool (*memory_handler_t)(bx_phy_address addr, unsigned len, void *data, void *param); -// return a pointer to 4K region containing or NULL if direct access is not allowed -// same format as getHostMemAddr method -typedef Bit8u* (*memory_direct_access_handler_t)(bx_phy_address addr, unsigned rw, void *param); - -struct memory_handler_struct { - struct memory_handler_struct *next; - void *param; - bx_phy_address begin; - bx_phy_address end; - Bit16u bitmap; - memory_handler_t read_handler; - memory_handler_t write_handler; - memory_direct_access_handler_t da_handler; -}; - -class BOCHSAPI BX_MEM_C : public logfunctions { +class BOCHSAPI BX_MEM_C : public BX_MEMORY_STUB_C { private: struct memory_handler_struct **memory_handlers; bool pci_enabled; bool bios_write_enabled; + bool smram_available; bool smram_enable; bool smram_restricted; - Bit64u len, allocated; // could be > 4G - Bit32u block_size; // individual block size, must be power of 2 - 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 bool rom_present[65]; bool memory_type[13][2]; Bit32u bios_rom_addr; @@ -104,28 +149,19 @@ private: Bit8u flash_status; Bit8u flash_wsm_state; - Bit32u used_blocks; -#if BX_LARGE_RAMFILE - static Bit8u * const swapped_out; // NULL; // (NULL - sizeof(Bit8u)); - Bit32u next_swapout_idx; - FILE *overflow_file; - - BX_MEM_SMF void read_block(Bit32u block); -#endif BX_MEM_SMF Bit8u flash_read(Bit32u addr); BX_MEM_SMF void flash_write(Bit32u addr, Bit8u data); public: BX_MEM_C(); - ~BX_MEM_C(); + virtual ~BX_MEM_C(); BX_MEM_SMF void init_memory(Bit64u guest, Bit64u host, Bit32u block_size); BX_MEM_SMF void cleanup_memory(void); - BX_MEM_SMF Bit8u* get_vector(bx_phy_address addr); BX_MEM_SMF void enable_smram(bool enable, bool restricted); BX_MEM_SMF void disable_smram(void); - BX_MEM_SMF bool is_smram_accessible(void); + BX_MEM_SMF bool is_smram_accessible(void); BX_MEM_SMF void set_bios_write(bool enabled); BX_MEM_SMF void set_bios_rom_access(Bit8u region, bool enabled); @@ -148,7 +184,6 @@ public: BX_MEM_SMF bool dbg_fetch_mem(BX_CPU_C *cpu, bx_phy_address addr, unsigned len, Bit8u *buf); #if (BX_DEBUGGER || BX_GDBSTUB) BX_MEM_SMF bool dbg_set_mem(BX_CPU_C *cpu, bx_phy_address addr, unsigned len, Bit8u *buf); - BX_MEM_SMF bool dbg_crc32(bx_phy_address addr1, bx_phy_address addr2, Bit32u *crc); #endif BX_MEM_SMF bool registerMemoryHandlers(void *param, memory_handler_t read_handler, @@ -162,34 +197,15 @@ public: } BX_MEM_SMF bool unregisterMemoryHandlers(void *param, 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); - BX_MEM_SMF Bit8u* alloc_vector_aligned(Bit64u bytes, Bit64u alignment); - -#if BX_SUPPORT_MONITOR_MWAIT - BX_MEM_SMF bool is_monitor(bx_phy_address begin_addr, unsigned len); - BX_MEM_SMF void check_monitor(bx_phy_address addr, unsigned len); -#endif - void register_state(void); +#if BX_LARGE_RAMFILE friend void ramfile_save_handler(void *devptr, FILE *fp); +#endif friend Bit64s memory_param_save_handler(void *devptr, bx_param_c *param); friend void memory_param_restore_handler(void *devptr, bx_param_c *param, Bit64s val); }; BOCHSAPI extern BX_MEM_C bx_mem; -/* -BX_CPP_INLINE Bit8u* BX_MEM_C::get_vector(bx_phy_address addr) -{ - return (BX_MEM_THIS vector + addr); -} -*/ - -BX_CPP_INLINE Bit64u BX_MEM_C::get_memory_len(void) -{ - return (BX_MEM_THIS len); -} - #endif diff --git a/bochs/memory/memory.cc b/bochs/memory/memory.cc index 047034937..685430cc2 100644 --- a/bochs/memory/memory.cc +++ b/bochs/memory/memory.cc @@ -89,27 +89,8 @@ mem_write: // all of data is within limits of physical memory if (a20addr < 0x000a0000 || a20addr >= 0x00100000) { - if (len == 8) { - pageWriteStampTable.decWriteStamp(a20addr, 8); - WriteHostQWordToLittleEndian((Bit64u*) BX_MEM_THIS get_vector(a20addr), *(Bit64u*)data); - return; - } - if (len == 4) { - pageWriteStampTable.decWriteStamp(a20addr, 4); - WriteHostDWordToLittleEndian((Bit32u*) BX_MEM_THIS get_vector(a20addr), *(Bit32u*)data); - return; - } - if (len == 2) { - pageWriteStampTable.decWriteStamp(a20addr, 2); - WriteHostWordToLittleEndian((Bit16u*) BX_MEM_THIS get_vector(a20addr), *(Bit16u*)data); - return; - } - if (len == 1) { - pageWriteStampTable.decWriteStamp(a20addr, 1); - * (BX_MEM_THIS get_vector(a20addr)) = * (Bit8u *) data; - return; - } - // len == other, just fall thru to special cases handling + BX_MEMORY_STUB_C::writePhysicalPage(cpu, addr, len, data); + return; } #ifdef BX_LITTLE_ENDIAN @@ -118,44 +99,10 @@ mem_write: data_ptr = (Bit8u *) data + (len - 1); #endif - if (a20addr < 0x000a0000 || a20addr >= 0x00100000) - { - // addr *not* in range 000A0000 .. 000FFFFF - while(1) { - // Write in chunks of 8 bytes if we can - if ((len & 7) == 0) { - pageWriteStampTable.decWriteStamp(a20addr, 8); - WriteHostQWordToLittleEndian((Bit64u*) BX_MEM_THIS get_vector(a20addr), *(Bit64u*)data_ptr); - len -= 8; - a20addr += 8; - #ifdef BX_LITTLE_ENDIAN - data_ptr += 8; - #else - data_ptr -= 8; - #endif - - if (len == 0) return; - } else { - pageWriteStampTable.decWriteStamp(a20addr, 1); - *(BX_MEM_THIS get_vector(a20addr)) = *data_ptr; - if (len == 1) return; - len--; - a20addr++; - #ifdef BX_LITTLE_ENDIAN - data_ptr++; - #else // BX_BIG_ENDIAN - data_ptr--; - #endif - } - } - } - pageWriteStampTable.decWriteStamp(a20addr); // addr must be in range 000A0000 .. 000FFFFF - for(unsigned i=0; i= 0x00100000) { - if (len == 8) { - * (Bit64u*) data = ReadHostQWordFromLittleEndian((Bit64u*) BX_MEM_THIS get_vector(a20addr)); - return; - } - if (len == 4) { - * (Bit32u*) data = ReadHostDWordFromLittleEndian((Bit32u*) BX_MEM_THIS get_vector(a20addr)); - return; - } - if (len == 2) { - * (Bit16u*) data = ReadHostWordFromLittleEndian((Bit16u*) BX_MEM_THIS get_vector(a20addr)); - return; - } - if (len == 1) { - * (Bit8u *) data = * (BX_MEM_THIS get_vector(a20addr)); - return; - } - // len == other case can just fall thru to special cases handling + BX_MEMORY_STUB_C::readPhysicalPage(cpu, addr, len, data); + return; } #ifdef BX_LITTLE_ENDIAN @@ -298,38 +230,7 @@ mem_read: data_ptr = (Bit8u *) data + (len - 1); #endif - if (a20addr < 0x000a0000 || a20addr >= 0x00100000) - { - // addr *not* in range 000A0000 .. 000FFFFF - while(1) { - // Read in chunks of 8 bytes if we can - if ((len & 7) == 0) { - *((Bit64u*)data_ptr) = ReadHostQWordFromLittleEndian((Bit64u*) BX_MEM_THIS get_vector(a20addr)); - len -= 8; - a20addr += 8; - #ifdef BX_LITTLE_ENDIAN - data_ptr += 8; - #else - data_ptr -= 8; - #endif - - if (len == 0) return; - } else { - *data_ptr = *(BX_MEM_THIS get_vector(a20addr)); - if (len == 1) return; - len--; - a20addr++; - #ifdef BX_LITTLE_ENDIAN - data_ptr++; - #else // BX_BIG_ENDIAN - data_ptr--; - #endif - } - } - } - // addr must be in range 000A0000 .. 000FFFFF - for (unsigned i=0; i + +// block size must be power of two +BX_CPP_INLINE bool is_power_of_2(Bit64u x) +{ + return (x & (x - 1)) == 0; +} + +// alignment of memory vector, must be a power of 2 +#define BX_MEM_VECTOR_ALIGN 4096 + +#if BX_LARGE_RAMFILE +Bit8u* const BX_MEMORY_STUB_C::swapped_out = ((Bit8u*)NULL - sizeof(Bit8u)); +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////// +// MEMORY_STUB class implements RAM vector only + +BX_MEMORY_STUB_C::BX_MEMORY_STUB_C() +{ + put("memory", "MEM0"); + + vector = NULL; + actual_vector = NULL; + blocks = NULL; + rom = NULL; + bogus = NULL; + len = 0; + used_blocks = 0; + allocated = 0; + +#if BX_LARGE_RAMFILE + next_swapout_idx = 0; + overflow_file = NULL; +#endif +} + +BX_MEMORY_STUB_C::~BX_MEMORY_STUB_C() +{ +#if BX_LARGE_RAMFILE + if (overflow_file) + fclose(BX_MEM_THIS overflow_file); +#endif + + cleanup_memory(); +} + +Bit64u BX_MEMORY_STUB_C::get_memory_len(void) +{ + return (BX_MEM_THIS len); +} + +Bit8u* BX_MEMORY_STUB_C::alloc_vector_aligned(Bit64u bytes, Bit64u alignment) +{ + Bit64u test_mask = alignment - 1; + BX_MEM_THIS actual_vector = new Bit8u [(Bit32u)(bytes + test_mask)]; + if (BX_MEM_THIS actual_vector == 0) { + BX_PANIC(("alloc_vector_aligned: unable to allocate host RAM !")); + return 0; + } + // round address forward to nearest multiple of alignment. Alignment + // MUST BE a power of two for this to work. + Bit64u masked = ((Bit64u)(BX_MEM_THIS actual_vector + test_mask)) & ~test_mask; + Bit8u *vector = (Bit8u *) masked; + // sanity check: no lost bits during pointer conversion + assert(sizeof(masked) >= sizeof(vector)); + // sanity check: after realignment, everything fits in allocated space + assert(vector+bytes <= BX_MEM_THIS actual_vector+bytes+test_mask); + return vector; +} + +void BX_MEMORY_STUB_C::init_memory(Bit64u guest, Bit64u host, Bit32u block_size) +{ + // accept only memory size which is multiply of 1M + BX_ASSERT((host & 0xfffff) == 0); + BX_ASSERT((guest & 0xfffff) == 0); + + if (! is_power_of_2(block_size)) { + BX_PANIC(("Block size %d is not power of two !", block_size)); + } + + if (BX_MEM_THIS actual_vector != NULL) { + 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(host + BIOSROMSZ + EXROMSIZE + 4096, BX_MEM_VECTOR_ALIGN); + BX_INFO(("allocated memory at %p. after alignment, vector=%p, block_size = %dK", + BX_MEM_THIS actual_vector, BX_MEM_THIS vector, block_size/1024)); + + 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); + + BX_MEM_THIS block_size = block_size; + // block must be large enough to fit num_blocks in 32-bit + BX_ASSERT((BX_MEM_THIS len / BX_MEM_THIS block_size) <= 0xffffffff); + + Bit32u num_blocks = (Bit32u)(BX_MEM_THIS len / BX_MEM_THIS block_size); + BX_INFO(("%.2fMB", (float)(BX_MEM_THIS len / (1024.0*1024.0)))); + BX_INFO(("mem block size = 0x%08x, blocks=%u", BX_MEM_THIS block_size, num_blocks)); + BX_MEM_THIS blocks = new Bit8u* [num_blocks]; + if (0) { + // all guest memory is allocated, just map it + for (unsigned idx = 0; idx < num_blocks; idx++) { + BX_MEM_THIS blocks[idx] = BX_MEM_THIS vector + (idx * BX_MEM_THIS block_size); + } + BX_MEM_THIS used_blocks = num_blocks; + } + else { + // host cannot allocate all requested guest memory + for (unsigned idx = 0; idx < num_blocks; idx++) { + BX_MEM_THIS blocks[idx] = NULL; + } + BX_MEM_THIS used_blocks = 0; + } +} + +Bit8u* BX_MEMORY_STUB_C::get_vector(bx_phy_address addr) +{ + Bit32u block = (Bit32u)(addr / BX_MEM_THIS block_size); +#if (BX_LARGE_RAMFILE) + if (!BX_MEM_THIS blocks[block] || (BX_MEM_THIS blocks[block] == BX_MEM_THIS swapped_out)) +#else + if (!BX_MEM_THIS blocks[block]) +#endif + allocate_block(block); + + return BX_MEM_THIS blocks[block] + (Bit32u)(addr & (BX_MEM_THIS block_size-1)); +} + +#if BX_LARGE_RAMFILE +void BX_MEMORY_STUB_C::read_block(Bit32u block) +{ + const Bit64u block_address = Bit64u(block) * BX_MEM_THIS block_size; + + if (fseeko64(BX_MEM_THIS overflow_file, block_address, SEEK_SET)) + BX_PANIC(("FATAL ERROR: Could not seek to 0x" FMT_LL "x in memory overflow file!", block_address)); + + // We could legitimately get an EOF condition if we are reading the last bit of memory.ram + if ((fread(BX_MEM_THIS blocks[block], BX_MEM_THIS block_size, 1, BX_MEM_THIS overflow_file) != 1) && + (!feof(BX_MEM_THIS overflow_file))) + BX_PANIC(("FATAL ERROR: Could not read from 0x" FMT_LL "x in memory overflow file!", block_address)); +} +#endif + +void BX_MEMORY_STUB_C::allocate_block(Bit32u block) +{ + const Bit32u max_blocks = (Bit32u)(BX_MEM_THIS allocated / BX_MEM_THIS block_size); + +#if BX_LARGE_RAMFILE + /* + * Match block to vector address + * First, see if there is any spare host memory blocks we can still freely allocate + */ + if (BX_MEM_THIS used_blocks >= max_blocks) { + Bit32u original_replacement_block = BX_MEM_THIS next_swapout_idx; + // Find a block to replace + bool used_for_tlb; + Bit8u *buffer; + do { + do { + // Wrap if necessary + if (++(BX_MEM_THIS next_swapout_idx)==((BX_MEM_THIS len)/BX_MEM_THIS block_size)) + BX_MEM_THIS next_swapout_idx = 0; + if (BX_MEM_THIS next_swapout_idx == original_replacement_block) + BX_PANIC(("FATAL ERROR: Insufficient working RAM, all blocks are currently used for TLB entries!")); + buffer = BX_MEM_THIS blocks[BX_MEM_THIS next_swapout_idx]; + } while ((!buffer) || (buffer == BX_MEMORY_STUB_C::swapped_out)); + + used_for_tlb = false; + // tlb buffer check loop + const Bit8u* buffer_end = buffer+BX_MEM_THIS block_size; + // Don't replace it if any CPU is using it as a TLB entry + for (int i=0; icheck_addr_in_tlb_buffers(buffer, buffer_end); + } while (used_for_tlb); + // Flush the block to be replaced + bx_phy_address address = bx_phy_address(BX_MEM_THIS next_swapout_idx) * BX_MEM_THIS block_size; + // Create overflow file if it does not currently exist. + if (!BX_MEM_THIS overflow_file) { + BX_MEM_THIS overflow_file = tmpfile64(); + if (!BX_MEM_THIS overflow_file) + BX_PANIC(("Unable to allocate memory overflow file")); + } + // Write swapped out block + if (fseeko64(BX_MEM_THIS overflow_file, address, SEEK_SET)) + BX_PANIC(("FATAL ERROR: Could not seek to 0x" FMT_PHY_ADDRX " in overflow file!", address)); + if (1 != fwrite (BX_MEM_THIS blocks[BX_MEM_THIS next_swapout_idx], BX_MEM_THIS block_size, 1, BX_MEM_THIS overflow_file)) + BX_PANIC(("FATAL ERROR: Could not write at 0x" FMT_PHY_ADDRX " in overflow file!", address)); + // Mark swapped out block + BX_MEM_THIS blocks[BX_MEM_THIS next_swapout_idx] = BX_MEMORY_STUB_C::swapped_out; + BX_MEM_THIS blocks[block] = buffer; + read_block(block); + BX_DEBUG(("allocate_block: block=0x%x, replaced 0x%x", block, BX_MEM_THIS next_swapout_idx)); + } + else { + BX_MEM_THIS blocks[block] = BX_MEM_THIS vector + (BX_MEM_THIS used_blocks++ * BX_MEM_THIS block_size); + BX_DEBUG(("allocate_block: block=0x%x used 0x%x of 0x%x", + block, BX_MEM_THIS used_blocks, max_blocks)); + } +#else + // Legacy default allocator + if (BX_MEM_THIS used_blocks >= max_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_THIS block_size); + BX_MEM_THIS used_blocks++; + } + BX_DEBUG(("allocate_block: used_blocks=0x%x of 0x%x", BX_MEM_THIS used_blocks, max_blocks)); +#endif +} + +void BX_MEMORY_STUB_C::cleanup_memory() +{ + if (BX_MEM_THIS vector != NULL) { + delete [] BX_MEM_THIS actual_vector; + BX_MEM_THIS actual_vector = NULL; + BX_MEM_THIS vector = NULL; + BX_MEM_THIS rom = NULL; + BX_MEM_THIS bogus = NULL; + delete [] BX_MEM_THIS blocks; + BX_MEM_THIS blocks = NULL; + BX_MEM_THIS used_blocks = 0; + BX_MEM_THIS allocated = 0; + BX_MEM_THIS len = 0; + } +} + +bool BX_MEMORY_STUB_C::dbg_fetch_mem(BX_CPU_C *cpu, bx_phy_address addr, unsigned len, Bit8u *buf) +{ + bx_phy_address a20addr = A20ADDR(addr); + bool ret = true; + + for (; len>0; len--) { + if (a20addr < BX_MEM_THIS len) { + *buf = *(BX_MEM_THIS get_vector(a20addr)); + } +#if BX_PHY_ADDRESS_LONG + else if (a20addr > BX_CONST64(0xffffffff)) { + *buf = 0xff; + ret = false; // error, beyond limits of memory + } +#endif + else { + *buf = 0xff; + ret = false; // error, beyond limits of memory + } + buf++; + a20addr++; + } + + return ret; +} + +#if BX_DEBUGGER || BX_GDBSTUB +bool BX_MEMORY_STUB_C::dbg_set_mem(BX_CPU_C *cpu, bx_phy_address addr, unsigned len, Bit8u *buf) +{ + bx_phy_address a20addr = A20ADDR(addr); + + if ((a20addr + len - 1) > BX_MEM_THIS len) { + return false; // error, beyond limits of memory + } + + for (; len>0; len--) { + *(BX_MEM_THIS get_vector(a20addr)) = *buf; + buf++; + a20addr++; + } + return true; +} + +bool BX_MEMORY_STUB_C::dbg_crc32(bx_phy_address addr1, bx_phy_address addr2, Bit32u *crc) +{ + *crc = 0; + if (addr1 > addr2) + return false; + + if (addr2 >= BX_MEM_THIS len) + return false; // error, specified address past last phy mem addr + + unsigned len = 1 + addr2 - addr1; + + // do not cross 4K boundary + while(1) { + unsigned remainsInPage = 0x1000 - (addr1 & 0xfff); + unsigned access_length = (len < remainsInPage) ? len : remainsInPage; + *crc = crc32(BX_MEM_THIS get_vector(addr1), access_length); + addr1 += access_length; + len -= access_length; + } + + return true; +} +#endif + +// +// 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. +// Values of 'op' are { BX_READ, BX_WRITE, BX_EXECUTE, BX_RW }. +// + +// +// The other assumption is that the calling code _only_ accesses memory +// directly within the page that encompasses the address requested. +// + +Bit8u *BX_MEMORY_STUB_C::getHostMemAddr(BX_CPU_C *cpu, bx_phy_address addr, unsigned rw) +{ + bx_phy_address a20addr = A20ADDR(addr); + + bool write = rw & 1; + +#if BX_SUPPORT_MONITOR_MWAIT + if (write && BX_MEM_THIS is_monitor(a20addr & ~((bx_phy_address)(0xfff)), 0xfff)) { + // Vetoed! Write monitored page ! + return(NULL); + } +#endif + + if (! write) { + if (a20addr < BX_MEM_THIS len) + return BX_MEM_THIS get_vector(a20addr); + else + // Error, requested addr is out of bounds. + return (Bit8u *) &BX_MEM_THIS bogus[a20addr & 0xfff]; + } + else + { // op == {BX_WRITE, BX_RW} + if (a20addr >= BX_MEM_THIS len) + return(NULL); // Error, requested addr is out of bounds. + return BX_MEM_THIS get_vector(a20addr); + } +} + +void BX_MEMORY_STUB_C::writePhysicalPage(BX_CPU_C *cpu, bx_phy_address addr, unsigned len, void *data) +{ + Bit8u *data_ptr; + bx_phy_address a20addr = A20ADDR(addr); + + // Note: accesses should always be contained within a single page + if ((addr>>12) != ((addr+len-1)>>12)) { + BX_PANIC(("writePhysicalPage: cross page access at address 0x" FMT_PHY_ADDRX ", len=%d", addr, len)); + } + +#if BX_SUPPORT_MONITOR_MWAIT + BX_MEM_THIS check_monitor(a20addr, len); +#endif + + // all memory access fits in single 4K page + if (a20addr < BX_MEM_THIS len) { + // all of data is within limits of physical memory + if (len == 8) { + pageWriteStampTable.decWriteStamp(a20addr, 8); + WriteHostQWordToLittleEndian((Bit64u*) BX_MEM_THIS get_vector(a20addr), *(Bit64u*)data); + return; + } + if (len == 4) { + pageWriteStampTable.decWriteStamp(a20addr, 4); + WriteHostDWordToLittleEndian((Bit32u*) BX_MEM_THIS get_vector(a20addr), *(Bit32u*)data); + return; + } + if (len == 2) { + pageWriteStampTable.decWriteStamp(a20addr, 2); + WriteHostWordToLittleEndian((Bit16u*) BX_MEM_THIS get_vector(a20addr), *(Bit16u*)data); + return; + } + if (len == 1) { + pageWriteStampTable.decWriteStamp(a20addr, 1); + * (BX_MEM_THIS get_vector(a20addr)) = * (Bit8u *) data; + 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 + + while(1) { + // Write in chunks of 8 bytes if we can + if ((len & 7) == 0) { + pageWriteStampTable.decWriteStamp(a20addr, 8); + WriteHostQWordToLittleEndian((Bit64u*) BX_MEM_THIS get_vector(a20addr), *(Bit64u*)data_ptr); + len -= 8; + a20addr += 8; +#ifdef BX_LITTLE_ENDIAN + data_ptr += 8; +#else + data_ptr -= 8; +#endif + if (len == 0) return; + } else { + pageWriteStampTable.decWriteStamp(a20addr, 1); + *(BX_MEM_THIS get_vector(a20addr)) = *data_ptr; + if (len == 1) return; + len--; + a20addr++; +#ifdef BX_LITTLE_ENDIAN + data_ptr++; +#else // BX_BIG_ENDIAN + data_ptr--; +#endif + } + } + + pageWriteStampTable.decWriteStamp(a20addr); + + } else { + // access outside limits of physical memory, ignore + BX_DEBUG(("Write outside the limits of physical memory (0x" FMT_PHY_ADDRX ") (ignore)", a20addr)); + } +} + +void BX_MEMORY_STUB_C::readPhysicalPage(BX_CPU_C *cpu, bx_phy_address addr, unsigned len, void *data) +{ + Bit8u *data_ptr; + bx_phy_address a20addr = A20ADDR(addr); + + // Note: accesses should always be contained within a single page + if ((addr>>12) != ((addr+len-1)>>12)) { + BX_PANIC(("readPhysicalPage: cross page access at address 0x" FMT_PHY_ADDRX ", len=%d", addr, len)); + } + + if (a20addr < BX_MEM_THIS len) { + if (len == 8) { + * (Bit64u*) data = ReadHostQWordFromLittleEndian((Bit64u*) BX_MEM_THIS get_vector(a20addr)); + return; + } + if (len == 4) { + * (Bit32u*) data = ReadHostDWordFromLittleEndian((Bit32u*) BX_MEM_THIS get_vector(a20addr)); + return; + } + if (len == 2) { + * (Bit16u*) data = ReadHostWordFromLittleEndian((Bit16u*) BX_MEM_THIS get_vector(a20addr)); + return; + } + if (len == 1) { + * (Bit8u *) data = * (BX_MEM_THIS get_vector(a20addr)); + return; + } + // len == other 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 + + // addr *not* in range 000A0000 .. 000FFFFF + while(1) { + // Read in chunks of 8 bytes if we can + if ((len & 7) == 0) { + *((Bit64u*)data_ptr) = ReadHostQWordFromLittleEndian((Bit64u*) BX_MEM_THIS get_vector(a20addr)); + len -= 8; + a20addr += 8; +#ifdef BX_LITTLE_ENDIAN + data_ptr += 8; +#else + data_ptr -= 8; +#endif + + if (len == 0) return; + } else { + *data_ptr = *(BX_MEM_THIS get_vector(a20addr)); + if (len == 1) return; + len--; + a20addr++; +#ifdef BX_LITTLE_ENDIAN + data_ptr++; +#else // BX_BIG_ENDIAN + data_ptr--; +#endif + } + } + } + else // access outside limits of physical memory + { + // bogus memory + memset(data, 0xFF, len); + } +} + +#if BX_SUPPORT_MONITOR_MWAIT + +// +// MONITOR/MWAIT - x86arch way to optimize idle loops in CPU +// + +bool BX_MEMORY_STUB_C::is_monitor(bx_phy_address begin_addr, unsigned len) +{ + for (int i=0; iis_monitor(begin_addr, len)) + return true; + } + + return false; // this is NOT monitored page +} + +void BX_MEMORY_STUB_C::check_monitor(bx_phy_address begin_addr, unsigned len) +{ + for (int i=0; icheck_monitor(begin_addr, len); + } +} + +#endif diff --git a/bochs/memory/misc_mem.cc b/bochs/memory/misc_mem.cc index 81292dad9..2b74431ac 100644 --- a/bochs/memory/misc_mem.cc +++ b/bochs/memory/misc_mem.cc @@ -28,20 +28,8 @@ #include "iodev/iodev.h" #define LOG_THIS BX_MEM(0)-> -// block size must be power of two -BX_CPP_INLINE bool is_power_of_2(Bit64u x) -{ - return (x & (x - 1)) == 0; -} - -// alignment of memory vector, must be a power of 2 -#define BX_MEM_VECTOR_ALIGN 4096 #define BX_MEM_HANDLERS ((BX_CONST64(1) << BX_PHY_ADDRESS_WIDTH) >> 20) /* one per megabyte */ -#if BX_LARGE_RAMFILE -Bit8u* const BX_MEM_C::swapped_out = ((Bit8u*)NULL - sizeof(Bit8u)); -#endif - #define FLASH_READ_ARRAY 0xff #define FLASH_INT_ID 0x90 #define FLASH_READ_STATUS 0x70 @@ -51,104 +39,25 @@ Bit8u* const BX_MEM_C::swapped_out = ((Bit8u*)NULL - sizeof(Bit8u)); #define FLASH_PROG_SETUP 0x40 #define FLASH_ERASE 0xd0 -BX_MEM_C::BX_MEM_C() +BX_MEM_C::BX_MEM_C() : BX_MEMORY_STUB_C() { - put("memory", "MEM0"); - - vector = NULL; - actual_vector = NULL; - blocks = NULL; - len = 0; - used_blocks = 0; - memory_handlers = NULL; - -#if BX_LARGE_RAMFILE - next_swapout_idx = 0; - overflow_file = NULL; -#endif -} - -Bit8u* BX_MEM_C::alloc_vector_aligned(Bit64u bytes, Bit64u alignment) -{ - Bit64u test_mask = alignment - 1; - BX_MEM_THIS actual_vector = new Bit8u [(Bit32u)(bytes + test_mask)]; - if (BX_MEM_THIS actual_vector == 0) { - BX_PANIC(("alloc_vector_aligned: unable to allocate host RAM !")); - return 0; - } - // round address forward to nearest multiple of alignment. Alignment - // MUST BE a power of two for this to work. - Bit64u masked = ((Bit64u)(BX_MEM_THIS actual_vector + test_mask)) & ~test_mask; - Bit8u *vector = (Bit8u *) masked; - // sanity check: no lost bits during pointer conversion - assert(sizeof(masked) >= sizeof(vector)); - // sanity check: after realignment, everything fits in allocated space - assert(vector+bytes <= BX_MEM_THIS actual_vector+bytes+test_mask); - return vector; } BX_MEM_C::~BX_MEM_C() { -#if BX_LARGE_RAMFILE - if (overflow_file) - fclose(BX_MEM_THIS overflow_file); -#endif - cleanup_memory(); } void BX_MEM_C::init_memory(Bit64u guest, Bit64u host, Bit32u block_size) { - unsigned i, idx; + unsigned idx, i; - // accept only memory size which is multiply of 1M - BX_ASSERT((host & 0xfffff) == 0); - BX_ASSERT((guest & 0xfffff) == 0); + BX_MEMORY_STUB_C::init_memory(guest, host, block_size); - if (! is_power_of_2(block_size)) { - BX_PANIC(("Block size %d is not power of two !", block_size)); - } - - if (BX_MEM_THIS actual_vector != NULL) { - 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(host + BIOSROMSZ + EXROMSIZE + 4096, BX_MEM_VECTOR_ALIGN); - BX_INFO(("allocated memory at %p. after alignment, vector=%p, block_size = %dK", - BX_MEM_THIS actual_vector, BX_MEM_THIS vector, block_size/1024)); - - 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); - - BX_MEM_THIS block_size = block_size; - // block must be large enough to fit num_blocks in 32-bit - BX_ASSERT((BX_MEM_THIS len / BX_MEM_THIS block_size) <= 0xffffffff); - - Bit32u num_blocks = (Bit32u)(BX_MEM_THIS len / BX_MEM_THIS block_size); - BX_INFO(("%.2fMB", (float)(BX_MEM_THIS len / (1024.0*1024.0)))); - BX_INFO(("mem block size = 0x%08x, blocks=%u", BX_MEM_THIS block_size, 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_THIS block_size); - } - 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 smram_available = false; + BX_MEM_THIS smram_enable = false; + BX_MEM_THIS smram_restricted = false; BX_MEM_THIS memory_handlers = new struct memory_handler_struct *[BX_MEM_HANDLERS]; for (idx = 0; idx < BX_MEM_HANDLERS; idx++) @@ -161,10 +70,6 @@ void BX_MEM_C::init_memory(Bit64u guest, Bit64u host, Bit32u block_size) BX_MEM_THIS flash_status = 0x80; BX_MEM_THIS flash_wsm_state = FLASH_READ_ARRAY; - BX_MEM_THIS smram_available = false; - BX_MEM_THIS smram_enable = false; - BX_MEM_THIS smram_restricted = false; - for (i = 0; i < 65; i++) BX_MEM_THIS rom_present[i] = false; for (i = 0; i <= BX_MEM_AREA_F0000; i++) { @@ -175,102 +80,6 @@ void BX_MEM_C::init_memory(Bit64u guest, Bit64u host, Bit32u block_size) BX_MEM_THIS register_state(); } -Bit8u* BX_MEM_C::get_vector(bx_phy_address addr) -{ - Bit32u block = (Bit32u)(addr / BX_MEM_THIS block_size); -#if (BX_LARGE_RAMFILE) - if (!BX_MEM_THIS blocks[block] || (BX_MEM_THIS blocks[block] == BX_MEM_THIS swapped_out)) -#else - if (!BX_MEM_THIS blocks[block]) -#endif - allocate_block(block); - - return BX_MEM_THIS blocks[block] + (Bit32u)(addr & (BX_MEM_THIS block_size-1)); -} - -#if BX_LARGE_RAMFILE -void BX_MEM_C::read_block(Bit32u block) -{ - const Bit64u block_address = Bit64u(block) * BX_MEM_THIS block_size; - - if (fseeko64(BX_MEM_THIS overflow_file, block_address, SEEK_SET)) - BX_PANIC(("FATAL ERROR: Could not seek to 0x" FMT_LL "x in memory overflow file!", block_address)); - - // We could legitimately get an EOF condition if we are reading the last bit of memory.ram - if ((fread(BX_MEM_THIS blocks[block], BX_MEM_THIS block_size, 1, BX_MEM_THIS overflow_file) != 1) && - (!feof(BX_MEM_THIS overflow_file))) - BX_PANIC(("FATAL ERROR: Could not read from 0x" FMT_LL "x in memory overflow file!", block_address)); -} -#endif - -void BX_MEM_C::allocate_block(Bit32u block) -{ - const Bit32u max_blocks = (Bit32u)(BX_MEM_THIS allocated / BX_MEM_THIS block_size); - -#if BX_LARGE_RAMFILE - /* - * Match block to vector address - * First, see if there is any spare host memory blocks we can still freely allocate - */ - if (BX_MEM_THIS used_blocks >= max_blocks) { - Bit32u original_replacement_block = BX_MEM_THIS next_swapout_idx; - // Find a block to replace - bool used_for_tlb; - Bit8u *buffer; - do { - do { - // Wrap if necessary - if (++(BX_MEM_THIS next_swapout_idx)==((BX_MEM_THIS len)/BX_MEM_THIS block_size)) - BX_MEM_THIS next_swapout_idx = 0; - if (BX_MEM_THIS next_swapout_idx == original_replacement_block) - BX_PANIC(("FATAL ERROR: Insufficient working RAM, all blocks are currently used for TLB entries!")); - buffer = BX_MEM_THIS blocks[BX_MEM_THIS next_swapout_idx]; - } while ((!buffer) || (buffer == BX_MEM_C::swapped_out)); - - used_for_tlb = false; - // tlb buffer check loop - const Bit8u* buffer_end = buffer+BX_MEM_THIS block_size; - // Don't replace it if any CPU is using it as a TLB entry - for (int i=0; icheck_addr_in_tlb_buffers(buffer, buffer_end); - } while (used_for_tlb); - // Flush the block to be replaced - bx_phy_address address = bx_phy_address(BX_MEM_THIS next_swapout_idx) * BX_MEM_THIS block_size; - // Create overflow file if it does not currently exist. - if (!BX_MEM_THIS overflow_file) { - BX_MEM_THIS overflow_file = tmpfile64(); - if (!BX_MEM_THIS overflow_file) - BX_PANIC(("Unable to allocate memory overflow file")); - } - // Write swapped out block - if (fseeko64(BX_MEM_THIS overflow_file, address, SEEK_SET)) - BX_PANIC(("FATAL ERROR: Could not seek to 0x" FMT_PHY_ADDRX " in overflow file!", address)); - if (1 != fwrite (BX_MEM_THIS blocks[BX_MEM_THIS next_swapout_idx], BX_MEM_THIS block_size, 1, BX_MEM_THIS overflow_file)) - BX_PANIC(("FATAL ERROR: Could not write at 0x" FMT_PHY_ADDRX " in overflow file!", address)); - // Mark swapped out block - BX_MEM_THIS blocks[BX_MEM_THIS next_swapout_idx] = BX_MEM_C::swapped_out; - BX_MEM_THIS blocks[block] = buffer; - read_block(block); - BX_DEBUG(("allocate_block: block=0x%x, replaced 0x%x", block, BX_MEM_THIS next_swapout_idx)); - } - else { - BX_MEM_THIS blocks[block] = BX_MEM_THIS vector + (BX_MEM_THIS used_blocks++ * BX_MEM_THIS block_size); - BX_DEBUG(("allocate_block: block=0x%x used 0x%x of 0x%x", - block, BX_MEM_THIS used_blocks, max_blocks)); - } -#else - // Legacy default allocator - if (BX_MEM_THIS used_blocks >= max_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_THIS block_size); - BX_MEM_THIS used_blocks++; - } - BX_DEBUG(("allocate_block: used_blocks=0x%x of 0x%x", BX_MEM_THIS used_blocks, max_blocks)); -#endif -} - #if BX_LARGE_RAMFILE // The blocks in RAM must also be flushed to the save file. void ramfile_save_handler(void *devptr, FILE *fp) @@ -366,30 +175,20 @@ void BX_MEM_C::register_state() void BX_MEM_C::cleanup_memory() { - unsigned idx; + BX_MEMORY_STUB_C::cleanup_memory(); - if (BX_MEM_THIS vector != NULL) { - delete [] BX_MEM_THIS actual_vector; - BX_MEM_THIS actual_vector = NULL; - BX_MEM_THIS vector = NULL; - BX_MEM_THIS rom = NULL; - BX_MEM_THIS bogus = NULL; - delete [] BX_MEM_THIS blocks; - BX_MEM_THIS blocks = 0; - BX_MEM_THIS used_blocks = 0; - if (BX_MEM_THIS memory_handlers != NULL) { - for (idx = 0; idx < BX_MEM_HANDLERS; idx++) { - struct memory_handler_struct *memory_handler = BX_MEM_THIS memory_handlers[idx]; - struct memory_handler_struct *prev = NULL; - while (memory_handler) { - prev = memory_handler; - memory_handler = memory_handler->next; - delete prev; - } + if (BX_MEM_THIS memory_handlers != NULL) { + for (unsigned idx = 0; idx < BX_MEM_HANDLERS; idx++) { + struct memory_handler_struct *memory_handler = BX_MEM_THIS memory_handlers[idx]; + struct memory_handler_struct *prev = NULL; + while (memory_handler) { + prev = memory_handler; + memory_handler = memory_handler->next; + delete prev; } - delete [] BX_MEM_THIS memory_handlers; - BX_MEM_THIS memory_handlers = NULL; } + delete [] BX_MEM_THIS memory_handlers; + BX_MEM_THIS memory_handlers = NULL; } } @@ -698,7 +497,7 @@ bool BX_MEM_C::dbg_set_mem(BX_CPU_C *cpu, bx_phy_address addr, unsigned len, Bit bool use_memory_handler = false, use_smram = false; if ((a20addr + len - 1) > BX_MEM_THIS len) { - return(0); // error, beyond limits of memory + return false; // error, beyond limits of memory } bool is_bios = (a20addr >= (bx_phy_address)BX_MEM_THIS bios_rom_addr); @@ -748,55 +547,10 @@ bool BX_MEM_C::dbg_set_mem(BX_CPU_C *cpu, bx_phy_address addr, unsigned len, Bit buf++; a20addr++; } - return(1); -} - -bool BX_MEM_C::dbg_crc32(bx_phy_address addr1, bx_phy_address addr2, Bit32u *crc) -{ - *crc = 0; - if (addr1 > addr2) - return(0); - - if (addr2 >= BX_MEM_THIS len) - return(0); // error, specified address past last phy mem addr - - unsigned len = 1 + addr2 - addr1; - - // do not cross 4K boundary - while(1) { - unsigned remainsInPage = 0x1000 - (addr1 & 0xfff); - unsigned access_length = (len < remainsInPage) ? len : remainsInPage; - *crc = crc32(BX_MEM_THIS get_vector(addr1), access_length); - addr1 += access_length; - len -= access_length; - } - - return(1); + return true; } #endif -// -// 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. -// Values of 'op' are { BX_READ, BX_WRITE, BX_EXECUTE, BX_RW }. -// -// The other assumption is that the calling code _only_ accesses memory -// directly within the page that encompasses the address requested. -// - -// -// Memory map inside the 1st megabyte: -// -// 0x00000 - 0x7ffff DOS area (512K) -// 0x80000 - 0x9ffff Optional fixed memory hole (128K) -// 0xa0000 - 0xbffff Standard PCI/ISA Video Mem / SMMRAM (128K) -// 0xc0000 - 0xdffff Expansion Card BIOS and Buffer Area (128K) -// 0xe0000 - 0xeffff Lower BIOS Area (64K) -// 0xf0000 - 0xfffff Upper BIOS Area (64K) -// - Bit8u *BX_MEM_C::getHostMemAddr(BX_CPU_C *cpu, bx_phy_address addr, unsigned rw) { bx_phy_address a20addr = A20ADDR(addr); @@ -924,9 +678,9 @@ BX_MEM_C::registerMemoryHandlers(void *param, memory_handler_t read_handler, bx_phy_address begin_addr, bx_phy_address end_addr) { if (end_addr < begin_addr) - return 0; + return false; if (!read_handler) // allow NULL write and fetch handler - return 0; + return false; BX_INFO(("Register memory access handlers: 0x" FMT_PHY_ADDRX " - 0x" FMT_PHY_ADDRX, begin_addr, end_addr)); for (Bit32u page_idx = (Bit32u)(begin_addr >> 20); page_idx <= (Bit32u)(end_addr >> 20); page_idx++) { Bit16u bitmap = 0xffff; @@ -939,7 +693,7 @@ BX_MEM_C::registerMemoryHandlers(void *param, memory_handler_t read_handler, if (BX_MEM_THIS memory_handlers[page_idx] != NULL) { if ((bitmap & BX_MEM_THIS memory_handlers[page_idx]->bitmap) != 0) { BX_ERROR(("Register failed: overlapping memory handlers!")); - return 0; + return false; } else { bitmap |= BX_MEM_THIS memory_handlers[page_idx]->bitmap; } @@ -955,7 +709,7 @@ BX_MEM_C::registerMemoryHandlers(void *param, memory_handler_t read_handler, memory_handler->end = end_addr; memory_handler->bitmap = bitmap; } - return 1; + return true; } bool BX_MEM_C::unregisterMemoryHandlers(void *param, bx_phy_address begin_addr, bx_phy_address end_addr) @@ -1123,28 +877,3 @@ void BX_MEM_C::flash_write(Bit32u addr, Bit8u data) } } } - -#if BX_SUPPORT_MONITOR_MWAIT - -// -// MONITOR/MWAIT - x86arch way to optimize idle loops in CPU -// - -bool BX_MEM_C::is_monitor(bx_phy_address begin_addr, unsigned len) -{ - for (int i=0; iis_monitor(begin_addr, len)) - return 1; - } - - return 0; // // this is NOT monitored page -} - -void BX_MEM_C::check_monitor(bx_phy_address begin_addr, unsigned len) -{ - for (int i=0; icheck_monitor(begin_addr, len); - } -} - -#endif