diff --git a/src/alloy/backend/ivm/ivm_intcode.cc b/src/alloy/backend/ivm/ivm_intcode.cc index 03a7e1690..8533eda15 100644 --- a/src/alloy/backend/ivm/ivm_intcode.cc +++ b/src/alloy/backend/ivm/ivm_intcode.cc @@ -1499,7 +1499,9 @@ int Translate_LOAD(TranslationContext& ctx, Instr* i) { void MarkPageDirty(IntCodeState& ics, uint32_t address) { // 16KB pages. - ics.page_table[(address >> 14) & 0x7FFF] = 1; + if (ics.page_table) { + ics.page_table[(address >> 14) & 0x7FFF] = 1; + } } uint32_t IntCode_STORE_I8(IntCodeState& ics, const IntCode* i) { uint32_t address = ics.rf[i->src1_reg].u32; diff --git a/src/alloy/backend/x64/x64_sequences.cc b/src/alloy/backend/x64/x64_sequences.cc index 0de164066..e015fbd4b 100644 --- a/src/alloy/backend/x64/x64_sequences.cc +++ b/src/alloy/backend/x64/x64_sequences.cc @@ -1557,9 +1557,12 @@ EMITTER_OPCODE_TABLE( // Note: most *should* be aligned, but needs to be checked! void EmitMarkPageDirty(X64Emitter& e, RegExp& addr) { // 16KB pages. - e.shr(e.eax, 14); - e.and(e.eax, 0x7FFF); - e.mov(e.byte[e.rdx + e.rax + e.page_table_address()], 1); + auto page_table_address = e.page_table_address(); + if (page_table_address) { + e.shr(e.eax, 14); + e.and(e.eax, 0x7FFF); + e.mov(e.byte[e.rdx + e.rax + page_table_address], 1); + } } EMITTER(STORE_I8, MATCH(I, I8<>>)) { static void Emit(X64Emitter& e, const EmitArgType& i) { diff --git a/src/alloy/frontend/ppc/ppc_context.h b/src/alloy/frontend/ppc/ppc_context.h index f3365e192..c0409e067 100644 --- a/src/alloy/frontend/ppc/ppc_context.h +++ b/src/alloy/frontend/ppc/ppc_context.h @@ -172,7 +172,7 @@ typedef struct alignas(64) PPCContext_s { uint32_t thread_id; // Reserve address for load acquire/store release. Shared. - uint32_t* reserve_address; + uint64_t* reserve_address; // Runtime-specific data pointer. Used on callbacks to get access to the // current runtime and its data. diff --git a/src/alloy/memory.cc b/src/alloy/memory.cc index abc0a8635..4154e9e43 100644 --- a/src/alloy/memory.cc +++ b/src/alloy/memory.cc @@ -61,4 +61,43 @@ uint64_t Memory::SearchAligned(uint64_t start, uint64_t end, return 0; } +SimpleMemory::SimpleMemory(size_t capacity) : memory_(capacity) { + membase_ = reinterpret_cast(memory_.data()); + reserve_address_ = capacity - 8; +} + +SimpleMemory::~SimpleMemory() = default; + +uint8_t SimpleMemory::LoadI8(uint64_t address) { + return poly::load(membase_ + address); +} + +uint16_t SimpleMemory::LoadI16(uint64_t address) { + return poly::load(membase_ + address); +} + +uint32_t SimpleMemory::LoadI32(uint64_t address) { + return poly::load(membase_ + address); +} + +uint64_t SimpleMemory::LoadI64(uint64_t address) { + return poly::load(membase_ + address); +} + +void SimpleMemory::StoreI8(uint64_t address, uint8_t value) { + poly::store(membase_ + address, value); +} + +void SimpleMemory::StoreI16(uint64_t address, uint16_t value) { + poly::store(membase_ + address, value); +} + +void SimpleMemory::StoreI32(uint64_t address, uint32_t value) { + poly::store(membase_ + address, value); +} + +void SimpleMemory::StoreI64(uint64_t address, uint64_t value) { + poly::store(membase_ + address, value); +} + } // namespace alloy diff --git a/src/alloy/memory.h b/src/alloy/memory.h index 05d13115b..869fc4eb7 100644 --- a/src/alloy/memory.h +++ b/src/alloy/memory.h @@ -14,23 +14,6 @@ namespace alloy { -enum { - MEMORY_FLAG_64KB_PAGES = (1 << 1), - MEMORY_FLAG_ZERO = (1 << 2), - MEMORY_FLAG_PHYSICAL = (1 << 3), -}; - -// Equivalent to the Win32 MEMORY_BASIC_INFORMATION struct. -struct AllocationInfo { - uint64_t base_address; - uint64_t allocation_base; - uint32_t allocation_protect; // TBD - size_t region_size; - uint32_t state; // TBD - uint32_t protect; // TBD - uint32_t type; // TBD -}; - class Memory { public: Memory(); @@ -40,8 +23,9 @@ class Memory { inline uint8_t* Translate(uint64_t guest_address) const { return membase_ + guest_address; }; - inline uint32_t* reserve_address() { return &reserve_address_; } + inline uint64_t* reserve_address() { return &reserve_address_; } + // TODO(benvanik): remove with GPU refactor. virtual uint64_t page_table() const = 0; uint64_t trace_base() const { return trace_base_; } @@ -49,6 +33,7 @@ class Memory { virtual int Initialize(); + // TODO(benvanik): make poly memory utils for these. void Zero(uint64_t address, size_t size); void Fill(uint64_t address, size_t size, uint8_t value); void Copy(uint64_t dest, uint64_t src, size_t size); @@ -56,6 +41,7 @@ class Memory { uint64_t SearchAligned(uint64_t start, uint64_t end, const uint32_t* values, size_t value_count); + // TODO(benvanik): remove with IVM. virtual uint8_t LoadI8(uint64_t address) = 0; virtual uint16_t LoadI16(uint64_t address) = 0; virtual uint32_t LoadI32(uint64_t address) = 0; @@ -65,24 +51,34 @@ class Memory { virtual void StoreI32(uint64_t address, uint32_t value) = 0; virtual void StoreI64(uint64_t address, uint64_t value) = 0; - virtual uint64_t HeapAlloc(uint64_t base_address, size_t size, uint32_t flags, - uint32_t alignment = 0x20) = 0; - virtual int HeapFree(uint64_t address, size_t size) = 0; - - virtual bool QueryInformation(uint64_t base_address, - AllocationInfo* mem_info) = 0; - virtual size_t QuerySize(uint64_t base_address) = 0; - - virtual int Protect(uint64_t address, size_t size, uint32_t access) = 0; - virtual uint32_t QueryProtect(uint64_t address) = 0; - protected: size_t system_page_size_; uint8_t* membase_; - uint32_t reserve_address_; + uint64_t reserve_address_; uint64_t trace_base_; }; +class SimpleMemory : public Memory { + public: + SimpleMemory(size_t capacity); + ~SimpleMemory() override; + + uint64_t page_table() const override { return 0; } + + // TODO(benvanik): remove with IVM. + uint8_t LoadI8(uint64_t address) override; + uint16_t LoadI16(uint64_t address) override; + uint32_t LoadI32(uint64_t address) override; + uint64_t LoadI64(uint64_t address) override; + void StoreI8(uint64_t address, uint8_t value) override; + void StoreI16(uint64_t address, uint16_t value) override; + void StoreI32(uint64_t address, uint32_t value) override; + void StoreI64(uint64_t address, uint64_t value) override; + + private: + std::vector memory_; +}; + } // namespace alloy #endif // ALLOY_MEMORY_H_ diff --git a/src/alloy/runtime/raw_module.cc b/src/alloy/runtime/raw_module.cc index 365d620ac..765d6a371 100644 --- a/src/alloy/runtime/raw_module.cc +++ b/src/alloy/runtime/raw_module.cc @@ -15,11 +15,7 @@ namespace runtime { RawModule::RawModule(Runtime* runtime) : Module(runtime), base_address_(0), low_address_(0), high_address_(0) {} -RawModule::~RawModule() { - if (base_address_) { - memory_->HeapFree(base_address_, high_address_ - low_address_); - } -} +RawModule::~RawModule() {} int RawModule::LoadFile(uint64_t base_address, const std::string& path) { FILE* file = fopen(path.c_str(), "rb"); @@ -28,15 +24,12 @@ int RawModule::LoadFile(uint64_t base_address, const std::string& path) { fseek(file, 0, SEEK_SET); // Allocate memory. - base_address_ = - memory_->HeapAlloc(base_address, file_length, MEMORY_FLAG_ZERO); - if (!base_address_) { - fclose(file); - return 1; - } + // Since we have no real heap just load it wherever. + base_address_ = base_address; + uint8_t* p = memory_->Translate(base_address_); + memset(p, 0, file_length); // Read into memory. - uint8_t* p = memory_->Translate(base_address_); fread(p, file_length, 1, file); fclose(file); diff --git a/src/xenia/apu/audio_system.cc b/src/xenia/apu/audio_system.cc index bf73c5d90..8a8e30fa7 100644 --- a/src/xenia/apu/audio_system.cc +++ b/src/xenia/apu/audio_system.cc @@ -48,7 +48,7 @@ X_STATUS AudioSystem::Setup() { new XenonThreadState(emulator_->processor()->runtime(), 0, 16 * 1024, 0); thread_state_->set_name("Audio Worker"); thread_block_ = - (uint32_t)memory_->HeapAlloc(0, 2048, alloy::MEMORY_FLAG_ZERO); + (uint32_t)memory_->HeapAlloc(0, 2048, MEMORY_FLAG_ZERO); thread_state_->context()->r[13] = thread_block_; // Create worker thread. diff --git a/src/xenia/core.h b/src/xenia/core.h index 8193aecff..6027d653d 100644 --- a/src/xenia/core.h +++ b/src/xenia/core.h @@ -12,13 +12,9 @@ #include -#include -namespace xe { - using Memory = alloy::Memory; -} // namespace xe - #include #include #include +#include #endif // XENIA_CORE_H_ diff --git a/src/xenia/cpu/processor.cc b/src/xenia/cpu/processor.cc index 220c9dd4a..92ac73572 100644 --- a/src/xenia/cpu/processor.cc +++ b/src/xenia/cpu/processor.cc @@ -12,7 +12,6 @@ #include #include #include -#include #include #include diff --git a/src/xenia/cpu/processor.h b/src/xenia/cpu/processor.h index 6dc1634bd..fc0b5bc2a 100644 --- a/src/xenia/cpu/processor.h +++ b/src/xenia/cpu/processor.h @@ -19,6 +19,7 @@ XEDECLARECLASS2(alloy, runtime, Breakpoint); XEDECLARECLASS1(xe, Emulator); XEDECLARECLASS1(xe, ExportResolver); +XEDECLARECLASS1(xe, Memory); XEDECLARECLASS2(xe, cpu, XenonMemory); XEDECLARECLASS2(xe, cpu, XenonRuntime); XEDECLARECLASS2(xe, cpu, XenonThreadState); diff --git a/src/xenia/cpu/sources.gypi b/src/xenia/cpu/sources.gypi index 46c524816..c519655de 100644 --- a/src/xenia/cpu/sources.gypi +++ b/src/xenia/cpu/sources.gypi @@ -8,8 +8,6 @@ 'mmio_handler.h', 'processor.cc', 'processor.h', - 'xenon_memory.cc', - 'xenon_memory.h', 'xenon_runtime.cc', 'xenon_runtime.h', 'xenon_thread_state.cc', diff --git a/src/xenia/cpu/xenon_runtime.cc b/src/xenia/cpu/xenon_runtime.cc index 1ae38b8c9..61ca8aabe 100644 --- a/src/xenia/cpu/xenon_runtime.cc +++ b/src/xenia/cpu/xenon_runtime.cc @@ -10,25 +10,20 @@ #include #include - #include -using namespace alloy; -using namespace alloy::frontend::ppc; -using namespace alloy::runtime; using namespace xe; using namespace xe::cpu; -XenonRuntime::XenonRuntime(alloy::Memory* memory, - ExportResolver* export_resolver, +XenonRuntime::XenonRuntime(Memory* memory, ExportResolver* export_resolver, uint32_t debug_info_flags, uint32_t trace_flags) : Runtime(memory, debug_info_flags, trace_flags), export_resolver_(export_resolver) {} XenonRuntime::~XenonRuntime() = default; -int XenonRuntime::Initialize(std::unique_ptr backend) { - std::unique_ptr frontend(new PPCFrontend(this)); +int XenonRuntime::Initialize(std::unique_ptr backend) { + auto frontend = std::make_unique(this); // TODO(benvanik): set options/etc. int result = Runtime::Initialize(std::move(frontend), std::move(backend)); diff --git a/src/xenia/cpu/xenon_thread_state.cc b/src/xenia/cpu/xenon_thread_state.cc index 0a4190573..e2abd64a1 100644 --- a/src/xenia/cpu/xenon_thread_state.cc +++ b/src/xenia/cpu/xenon_thread_state.cc @@ -24,7 +24,7 @@ XenonThreadState::XenonThreadState(XenonRuntime* runtime, uint32_t thread_id, : ThreadState(runtime, thread_id), stack_size_(stack_size), thread_state_address_(thread_state_address) { - stack_address_ = memory_->HeapAlloc(0, stack_size, MEMORY_FLAG_ZERO); + stack_address_ = xenon_memory()->HeapAlloc(0, stack_size, MEMORY_FLAG_ZERO); assert_not_zero(stack_address_); // Allocate with 64b alignment. @@ -56,7 +56,7 @@ XenonThreadState::~XenonThreadState() { runtime_->debugger()->OnThreadDestroyed(this); xe_free_aligned(context_); - memory_->HeapFree(stack_address_, stack_size_); + xenon_memory()->HeapFree(stack_address_, stack_size_); } void XenonThreadState::WriteRegisters(xdb::protocol::Registers* registers) { diff --git a/src/xenia/cpu/xenon_thread_state.h b/src/xenia/cpu/xenon_thread_state.h index 409d85a97..aedf39df0 100644 --- a/src/xenia/cpu/xenon_thread_state.h +++ b/src/xenia/cpu/xenon_thread_state.h @@ -27,13 +27,13 @@ class XenonRuntime; using PPCContext = alloy::frontend::ppc::PPCContext; - class XenonThreadState : public alloy::runtime::ThreadState { -public: - XenonThreadState(XenonRuntime* runtime, uint32_t thread_id, - size_t stack_size, uint64_t thread_state_address); + public: + XenonThreadState(XenonRuntime* runtime, uint32_t thread_id, size_t stack_size, + uint64_t thread_state_address); virtual ~XenonThreadState(); + Memory* xenon_memory() { return static_cast(memory_); } uint64_t stack_address() const { return stack_address_; } size_t stack_size() const { return stack_size_; } uint64_t thread_state_address() const { return thread_state_address_; } @@ -41,18 +41,16 @@ public: void WriteRegisters(xdb::protocol::Registers* registers); -private: - uint64_t stack_address_; - size_t stack_size_; - uint64_t thread_state_address_; + private: + uint64_t stack_address_; + size_t stack_size_; + uint64_t thread_state_address_; // NOTE: must be 64b aligned for SSE ops. PPCContext* context_; }; - } // namespace cpu } // namespace xe - #endif // XENIA_CPU_XENON_THREAD_STATE_H_ diff --git a/src/xenia/emulator.cc b/src/xenia/emulator.cc index ae6eeb75d..81467ad67 100644 --- a/src/xenia/emulator.cc +++ b/src/xenia/emulator.cc @@ -13,13 +13,13 @@ #include #include #include -#include #include #include #include #include #include #include +#include #include namespace xe { @@ -87,7 +87,7 @@ X_STATUS Emulator::Setup() { XEEXPECTZERO(result); // Create memory system first, as it is required for other systems. - memory_ = new XenonMemory(); + memory_ = new Memory(); XEEXPECTNOTNULL(memory_); result = memory_->Initialize(); XEEXPECTZERO(result); diff --git a/src/xenia/emulator.h b/src/xenia/emulator.h index 77ffabd40..6da650108 100644 --- a/src/xenia/emulator.h +++ b/src/xenia/emulator.h @@ -14,7 +14,6 @@ #include #include -#include #include #include #include @@ -55,7 +54,7 @@ class Emulator { ui::Window* main_window() const { return main_window_; } void set_main_window(ui::Window* window); - cpu::XenonMemory* memory() const { return memory_; } + Memory* memory() const { return memory_; } DebugAgent* debug_agent() const { return debug_agent_.get(); } @@ -79,31 +78,29 @@ class Emulator { private: X_STATUS CompleteLaunch(const std::wstring& path, - const std::string& module_path); + const std::string& module_path); - std::wstring command_line_; + std::wstring command_line_; - ui::Window* main_window_; + ui::Window* main_window_; - cpu::XenonMemory* memory_; + Memory* memory_; std::unique_ptr debug_agent_; - cpu::Processor* processor_; - apu::AudioSystem* audio_system_; - gpu::GraphicsSystem* graphics_system_; - hid::InputSystem* input_system_; + cpu::Processor* processor_; + apu::AudioSystem* audio_system_; + gpu::GraphicsSystem* graphics_system_; + hid::InputSystem* input_system_; - ExportResolver* export_resolver_; + ExportResolver* export_resolver_; kernel::fs::FileSystem* file_system_; - kernel::KernelState* kernel_state_; - kernel::XamModule* xam_; + kernel::KernelState* kernel_state_; + kernel::XamModule* xam_; kernel::XboxkrnlModule* xboxkrnl_; }; - } // namespace xe - #endif // XENIA_EMULATOR_H_ diff --git a/src/xenia/kernel/objects/xthread.cc b/src/xenia/kernel/objects/xthread.cc index 8bef9479a..60c6086e3 100644 --- a/src/xenia/kernel/objects/xthread.cc +++ b/src/xenia/kernel/objects/xthread.cc @@ -152,7 +152,7 @@ X_STATUS XThread::Create() { // So, at offset 0x100 we have a 4b pointer to offset 200, then have the // structure. thread_state_address_ = - (uint32_t)memory()->HeapAlloc(0, 2048, alloy::MEMORY_FLAG_ZERO); + (uint32_t)memory()->HeapAlloc(0, 2048, MEMORY_FLAG_ZERO); if (!thread_state_address_) { XELOGW("Unable to allocate thread state block"); return X_STATUS_NO_MEMORY; @@ -167,13 +167,12 @@ X_STATUS XThread::Create() { // This is used by interrupts/APCs/etc so we can round-trip pointers through. scratch_size_ = 4 * 16; scratch_address_ = - (uint32_t)memory()->HeapAlloc(0, scratch_size_, alloy::MEMORY_FLAG_ZERO); + (uint32_t)memory()->HeapAlloc(0, scratch_size_, MEMORY_FLAG_ZERO); // Allocate TLS block. const xe_xex2_header_t* header = module->xex_header(); uint32_t tls_size = header->tls_info.slot_count * header->tls_info.data_size; - tls_address_ = - (uint32_t)memory()->HeapAlloc(0, tls_size, alloy::MEMORY_FLAG_ZERO); + tls_address_ = (uint32_t)memory()->HeapAlloc(0, tls_size, MEMORY_FLAG_ZERO); if (!tls_address_) { XELOGW("Unable to allocate thread local storage block"); module->Release(); diff --git a/src/xenia/kernel/util/xex2.cc b/src/xenia/kernel/util/xex2.cc index e9e8aeb31..1a7b48f41 100644 --- a/src/xenia/kernel/util/xex2.cc +++ b/src/xenia/kernel/util/xex2.cc @@ -21,14 +21,14 @@ #include #include -using namespace alloy; +// using namespace alloy; DEFINE_bool(xex_dev_key, false, "Use the devkit key."); typedef struct xe_xex2 { xe_ref_t ref; - Memory *memory; + xe::Memory *memory; xe_xex2_header_t header; @@ -44,13 +44,13 @@ int xe_xex2_read_header(const uint8_t *addr, const size_t length, xe_xex2_header_t *header); int xe_xex2_decrypt_key(xe_xex2_header_t *header); int xe_xex2_read_image(xe_xex2_ref xex, const uint8_t *xex_addr, - const size_t xex_length, Memory *memory); + const size_t xex_length, xe::Memory *memory); int xe_xex2_load_pe(xe_xex2_ref xex); int xe_xex2_find_import_infos(xe_xex2_ref xex, const xe_xex2_import_library_t *library); -xe_xex2_ref xe_xex2_load(Memory *memory, const void *addr, const size_t length, - xe_xex2_options_t options) { +xe_xex2_ref xe_xex2_load(xe::Memory *memory, const void *addr, + const size_t length, xe_xex2_options_t options) { xe_xex2_ref xex = (xe_xex2_ref)xe_calloc(sizeof(xe_xex2)); xe_ref_init((xe_ref)xex); @@ -542,12 +542,13 @@ void xe_xex2_decrypt_buffer(const uint8_t *session_key, int xe_xex2_read_image_uncompressed(const xe_xex2_header_t *header, const uint8_t *xex_addr, - const size_t xex_length, Memory *memory) { + const size_t xex_length, + xe::Memory *memory) { // Allocate in-place the XEX memory. const size_t exe_length = xex_length - header->exe_offset; size_t uncompressed_size = exe_length; uint32_t alloc_result = (uint32_t)memory->HeapAlloc( - header->exe_address, uncompressed_size, MEMORY_FLAG_ZERO); + header->exe_address, uncompressed_size, xe::MEMORY_FLAG_ZERO); if (!alloc_result) { XELOGE("Unable to allocate XEX memory at %.8X-%.8X.", header->exe_address, uncompressed_size); @@ -575,7 +576,7 @@ int xe_xex2_read_image_uncompressed(const xe_xex2_header_t *header, int xe_xex2_read_image_basic_compressed(const xe_xex2_header_t *header, const uint8_t *xex_addr, const size_t xex_length, - Memory *memory) { + xe::Memory *memory) { const size_t exe_length = xex_length - header->exe_offset; const uint8_t *source_buffer = (const uint8_t *)xex_addr + header->exe_offset; const uint8_t *p = source_buffer; @@ -592,7 +593,7 @@ int xe_xex2_read_image_basic_compressed(const xe_xex2_header_t *header, // Allocate in-place the XEX memory. uint32_t alloc_result = (uint32_t)memory->HeapAlloc( - header->exe_address, uncompressed_size, MEMORY_FLAG_ZERO); + header->exe_address, uncompressed_size, xe::MEMORY_FLAG_ZERO); if (!alloc_result) { XELOGE("Unable to allocate XEX memory at %.8X-%.8X.", header->exe_address, uncompressed_size); @@ -645,7 +646,7 @@ XECLEANUP: int xe_xex2_read_image_compressed(const xe_xex2_header_t *header, const uint8_t *xex_addr, - const size_t xex_length, Memory *memory) { + const size_t xex_length, xe::Memory *memory) { const size_t exe_length = xex_length - header->exe_offset; const uint8_t *exe_buffer = (const uint8_t *)xex_addr + header->exe_offset; @@ -726,7 +727,7 @@ int xe_xex2_read_image_compressed(const xe_xex2_header_t *header, // Allocate in-place the XEX memory. uint32_t alloc_result = (uint32_t)memory->HeapAlloc( - header->exe_address, uncompressed_size, MEMORY_FLAG_ZERO); + header->exe_address, uncompressed_size, xe::MEMORY_FLAG_ZERO); if (!alloc_result) { XELOGE("Unable to allocate XEX memory at %.8X-%.8X.", header->exe_address, uncompressed_size); @@ -778,7 +779,7 @@ XECLEANUP: } int xe_xex2_read_image(xe_xex2_ref xex, const uint8_t *xex_addr, - const size_t xex_length, Memory *memory) { + const size_t xex_length, xe::Memory *memory) { const xe_xex2_header_t *header = &xex->header; switch (header->file_format_info.compression_type) { case XEX_COMPRESSION_NONE: diff --git a/src/xenia/kernel/xboxkrnl_memory.cc b/src/xenia/kernel/xboxkrnl_memory.cc index ffdc4c7b1..e3f80cd15 100644 --- a/src/xenia/kernel/xboxkrnl_memory.cc +++ b/src/xenia/kernel/xboxkrnl_memory.cc @@ -158,7 +158,7 @@ SHIM_CALL NtQueryVirtualMemory_shim(PPCContext* ppc_state, KernelState* state) { XELOGD("NtQueryVirtualMemory(%.8X, %.8X)", base_address, memory_basic_information_ptr); - alloy::AllocationInfo mem_info; + AllocationInfo mem_info; size_t result = state->memory()->QueryInformation(base_address, &mem_info); if (!result) { SHIM_SET_RETURN_32(X_STATUS_INVALID_PARAMETER); @@ -250,7 +250,7 @@ SHIM_CALL MmAllocatePhysicalMemoryEx_shim(PPCContext* ppc_state, assert_true(max_addr_range == 0xFFFFFFFF); // Allocate. - uint32_t flags = alloy::MEMORY_FLAG_PHYSICAL; + uint32_t flags = MEMORY_FLAG_PHYSICAL; uint32_t base_address = (uint32_t)state->memory()->HeapAlloc( 0, adjusted_size, flags, adjusted_alignment); if (!base_address) { @@ -410,7 +410,7 @@ SHIM_CALL ExAllocatePoolTypeWithTag_shim(PPCContext* ppc_state, } uint32_t addr = (uint32_t)state->memory()->HeapAlloc( - 0, adjusted_size, alloy::MEMORY_FLAG_ZERO, alignment); + 0, adjusted_size, MEMORY_FLAG_ZERO, alignment); SHIM_SET_RETURN_32(addr); } diff --git a/src/xenia/cpu/xenon_memory.cc b/src/xenia/memory.cc similarity index 87% rename from src/xenia/cpu/xenon_memory.cc rename to src/xenia/memory.cc index 63f5cc6d7..596812317 100644 --- a/src/xenia/cpu/xenon_memory.cc +++ b/src/xenia/memory.cc @@ -7,16 +7,16 @@ ****************************************************************************** */ -#include +#include #include #include #include #include +#include -using namespace alloy; -using namespace xe::cpu; +using namespace xe; // TODO(benvanik): move xbox.h out #include @@ -84,10 +84,10 @@ DEFINE_bool(scribble_heap, false, #define XENON_MEMORY_VIRTUAL_HEAP_LOW 0x20000000 #define XENON_MEMORY_VIRTUAL_HEAP_HIGH 0x40000000 -class xe::cpu::XenonMemoryHeap { +class xe::MemoryHeap { public: - XenonMemoryHeap(XenonMemory* memory, bool is_physical); - ~XenonMemoryHeap(); + MemoryHeap(Memory* memory, bool is_physical); + ~MemoryHeap(); int Initialize(uint64_t low, uint64_t high); @@ -104,7 +104,7 @@ class xe::cpu::XenonMemoryHeap { void* context); private: - XenonMemory* memory_; + Memory* memory_; uint32_t heap_id_; bool is_physical_; std::mutex lock_; @@ -112,15 +112,15 @@ class xe::cpu::XenonMemoryHeap { uint8_t* ptr_; mspace space_; }; -uint32_t XenonMemoryHeap::next_heap_id_ = 1; +uint32_t MemoryHeap::next_heap_id_ = 1; -XenonMemory::XenonMemory() - : Memory(), mapping_(0), mapping_base_(0), page_table_(0) { - virtual_heap_ = new XenonMemoryHeap(this, false); - physical_heap_ = new XenonMemoryHeap(this, true); +Memory::Memory() + : alloy::Memory(), mapping_(0), mapping_base_(0), page_table_(0) { + virtual_heap_ = new MemoryHeap(this, false); + physical_heap_ = new MemoryHeap(this, true); } -XenonMemory::~XenonMemory() { +Memory::~Memory() { // Uninstall the MMIO handler, as we won't be able to service more // requests. mmio_handler_.reset(); @@ -142,8 +142,8 @@ XenonMemory::~XenonMemory() { } } -int XenonMemory::Initialize() { - int result = Memory::Initialize(); +int Memory::Initialize() { + int result = alloy::Memory::Initialize(); if (result) { return result; } @@ -196,7 +196,7 @@ int XenonMemory::Initialize() { VirtualAlloc(Translate(0xC0000000), 0x00100000, MEM_COMMIT, PAGE_READWRITE); // Add handlers for MMIO. - mmio_handler_ = MMIOHandler::Install(mapping_base_); + mmio_handler_ = cpu::MMIOHandler::Install(mapping_base_); if (!mmio_handler_) { XELOGE("Unable to install MMIO handlers"); assert_always(); @@ -227,7 +227,7 @@ const static struct { 0xC0000000, 0xDFFFFFFF, 0x00000000, // - physical 16mb pages 0xE0000000, 0xFFFFFFFF, 0x00000000, // - physical 4k pages }; -int XenonMemory::MapViews(uint8_t* mapping_base) { +int Memory::MapViews(uint8_t* mapping_base) { assert_true(poly::countof(map_info) == poly::countof(views_.all_views)); for (size_t n = 0; n < poly::countof(map_info); n++) { #if XE_PLATFORM_WIN32 @@ -252,7 +252,7 @@ XECLEANUP: return 1; } -void XenonMemory::UnmapViews() { +void Memory::UnmapViews() { for (size_t n = 0; n < poly::countof(views_.all_views); n++) { if (views_.all_views[n]) { #if XE_PLATFORM_WIN32 @@ -266,9 +266,9 @@ void XenonMemory::UnmapViews() { } } -bool XenonMemory::AddMappedRange(uint64_t address, uint64_t mask, uint64_t size, - void* context, MMIOReadCallback read_callback, - MMIOWriteCallback write_callback) { +bool Memory::AddMappedRange(uint64_t address, uint64_t mask, uint64_t size, + void* context, cpu::MMIOReadCallback read_callback, + cpu::MMIOWriteCallback write_callback) { DWORD protect = PAGE_NOACCESS; if (!VirtualAlloc(Translate(address), size, MEM_COMMIT, protect)) { XELOGE("Unable to map range; commit/protect failed"); @@ -278,7 +278,7 @@ bool XenonMemory::AddMappedRange(uint64_t address, uint64_t mask, uint64_t size, read_callback, write_callback); } -uint8_t XenonMemory::LoadI8(uint64_t address) { +uint8_t Memory::LoadI8(uint64_t address) { uint64_t value; if (!mmio_handler_->CheckLoad(address, &value)) { value = *reinterpret_cast(Translate(address)); @@ -286,7 +286,7 @@ uint8_t XenonMemory::LoadI8(uint64_t address) { return static_cast(value); } -uint16_t XenonMemory::LoadI16(uint64_t address) { +uint16_t Memory::LoadI16(uint64_t address) { uint64_t value; if (!mmio_handler_->CheckLoad(address, &value)) { value = *reinterpret_cast(Translate(address)); @@ -294,7 +294,7 @@ uint16_t XenonMemory::LoadI16(uint64_t address) { return static_cast(value); } -uint32_t XenonMemory::LoadI32(uint64_t address) { +uint32_t Memory::LoadI32(uint64_t address) { uint64_t value; if (!mmio_handler_->CheckLoad(address, &value)) { value = *reinterpret_cast(Translate(address)); @@ -302,7 +302,7 @@ uint32_t XenonMemory::LoadI32(uint64_t address) { return static_cast(value); } -uint64_t XenonMemory::LoadI64(uint64_t address) { +uint64_t Memory::LoadI64(uint64_t address) { uint64_t value; if (!mmio_handler_->CheckLoad(address, &value)) { value = *reinterpret_cast(Translate(address)); @@ -310,32 +310,32 @@ uint64_t XenonMemory::LoadI64(uint64_t address) { return static_cast(value); } -void XenonMemory::StoreI8(uint64_t address, uint8_t value) { +void Memory::StoreI8(uint64_t address, uint8_t value) { if (!mmio_handler_->CheckStore(address, value)) { *reinterpret_cast(Translate(address)) = value; } } -void XenonMemory::StoreI16(uint64_t address, uint16_t value) { +void Memory::StoreI16(uint64_t address, uint16_t value) { if (!mmio_handler_->CheckStore(address, value)) { *reinterpret_cast(Translate(address)) = value; } } -void XenonMemory::StoreI32(uint64_t address, uint32_t value) { +void Memory::StoreI32(uint64_t address, uint32_t value) { if (!mmio_handler_->CheckStore(address, value)) { *reinterpret_cast(Translate(address)) = value; } } -void XenonMemory::StoreI64(uint64_t address, uint64_t value) { +void Memory::StoreI64(uint64_t address, uint64_t value) { if (!mmio_handler_->CheckStore(address, value)) { *reinterpret_cast(Translate(address)) = value; } } -uint64_t XenonMemory::HeapAlloc(uint64_t base_address, size_t size, - uint32_t flags, uint32_t alignment) { +uint64_t Memory::HeapAlloc(uint64_t base_address, size_t size, uint32_t flags, + uint32_t alignment) { // If we were given a base address we are outside of the normal heap and // will place wherever asked (so long as it doesn't overlap the heap). if (!base_address) { @@ -384,7 +384,7 @@ uint64_t XenonMemory::HeapAlloc(uint64_t base_address, size_t size, } } -int XenonMemory::HeapFree(uint64_t address, size_t size) { +int Memory::HeapFree(uint64_t address, size_t size) { if (address >= XENON_MEMORY_VIRTUAL_HEAP_LOW && address < XENON_MEMORY_VIRTUAL_HEAP_HIGH) { return virtual_heap_->Free(address, size) ? 0 : 1; @@ -398,8 +398,7 @@ int XenonMemory::HeapFree(uint64_t address, size_t size) { } } -bool XenonMemory::QueryInformation(uint64_t base_address, - AllocationInfo* mem_info) { +bool Memory::QueryInformation(uint64_t base_address, AllocationInfo* mem_info) { uint8_t* p = Translate(base_address); MEMORY_BASIC_INFORMATION mbi; if (!VirtualQuery(p, &mbi, sizeof(mbi))) { @@ -416,7 +415,7 @@ bool XenonMemory::QueryInformation(uint64_t base_address, return true; } -size_t XenonMemory::QuerySize(uint64_t base_address) { +size_t Memory::QuerySize(uint64_t base_address) { if (base_address >= XENON_MEMORY_VIRTUAL_HEAP_LOW && base_address < XENON_MEMORY_VIRTUAL_HEAP_HIGH) { return virtual_heap_->QuerySize(base_address); @@ -436,7 +435,7 @@ size_t XenonMemory::QuerySize(uint64_t base_address) { } } -int XenonMemory::Protect(uint64_t address, size_t size, uint32_t access) { +int Memory::Protect(uint64_t address, size_t size, uint32_t access) { uint8_t* p = Translate(address); size_t heap_guard_size = FLAGS_heap_guard_pages * 4096; @@ -452,7 +451,7 @@ int XenonMemory::Protect(uint64_t address, size_t size, uint32_t access) { return VirtualProtect(p, size, new_protect, &old_protect) == TRUE ? 0 : 1; } -uint32_t XenonMemory::QueryProtect(uint64_t address) { +uint32_t Memory::QueryProtect(uint64_t address) { uint8_t* p = Translate(address); MEMORY_BASIC_INFORMATION info; size_t info_size = VirtualQuery((void*)p, &info, sizeof(info)); @@ -462,12 +461,12 @@ uint32_t XenonMemory::QueryProtect(uint64_t address) { return info.Protect; } -XenonMemoryHeap::XenonMemoryHeap(XenonMemory* memory, bool is_physical) +MemoryHeap::MemoryHeap(Memory* memory, bool is_physical) : memory_(memory), is_physical_(is_physical) { heap_id_ = next_heap_id_++; } -XenonMemoryHeap::~XenonMemoryHeap() { +MemoryHeap::~MemoryHeap() { if (space_) { std::lock_guard guard(lock_); destroy_mspace(space_); @@ -479,7 +478,7 @@ XenonMemoryHeap::~XenonMemoryHeap() { } } -int XenonMemoryHeap::Initialize(uint64_t low, uint64_t high) { +int MemoryHeap::Initialize(uint64_t low, uint64_t high) { // Commit the memory where our heap will live and allocate it. // TODO(benvanik): replace dlmalloc with an implementation that can commit // as it goes. @@ -494,8 +493,8 @@ int XenonMemoryHeap::Initialize(uint64_t low, uint64_t high) { return 0; } -uint64_t XenonMemoryHeap::Alloc(uint64_t base_address, size_t size, - uint32_t flags, uint32_t alignment) { +uint64_t MemoryHeap::Alloc(uint64_t base_address, size_t size, uint32_t flags, + uint32_t alignment) { lock_.lock(); size_t alloc_size = size; size_t heap_guard_size = FLAGS_heap_guard_pages * 4096; @@ -547,7 +546,7 @@ uint64_t XenonMemoryHeap::Alloc(uint64_t base_address, size_t size, return address; } -uint64_t XenonMemoryHeap::Free(uint64_t address, size_t size) { +uint64_t MemoryHeap::Free(uint64_t address, size_t size) { uint8_t* p = memory_->Translate(address); // Heap allocated address. @@ -590,7 +589,7 @@ uint64_t XenonMemoryHeap::Free(uint64_t address, size_t size) { return (uint64_t)real_size; } -size_t XenonMemoryHeap::QuerySize(uint64_t base_address) { +size_t MemoryHeap::QuerySize(uint64_t base_address) { uint8_t* p = memory_->Translate(base_address); // Heap allocated address. @@ -605,8 +604,8 @@ size_t XenonMemoryHeap::QuerySize(uint64_t base_address) { return real_size; } -void XenonMemoryHeap::Dump() { - XELOGI("XenonMemoryHeap::Dump - %s", is_physical_ ? "physical" : "virtual"); +void MemoryHeap::Dump() { + XELOGI("MemoryHeap::Dump - %s", is_physical_ ? "physical" : "virtual"); if (FLAGS_heap_guard_pages) { XELOGI(" (heap guard pages enabled, stats will be wrong)"); } @@ -622,10 +621,10 @@ void XenonMemoryHeap::Dump() { mspace_inspect_all(space_, DumpHandler, this); } -void XenonMemoryHeap::DumpHandler(void* start, void* end, size_t used_bytes, - void* context) { - XenonMemoryHeap* heap = (XenonMemoryHeap*)context; - XenonMemory* memory = heap->memory_; +void MemoryHeap::DumpHandler(void* start, void* end, size_t used_bytes, + void* context) { + MemoryHeap* heap = (MemoryHeap*)context; + Memory* memory = heap->memory_; size_t heap_guard_size = FLAGS_heap_guard_pages * 4096; uint64_t start_addr = (uint64_t)start + heap_guard_size; uint64_t end_addr = (uint64_t)end - heap_guard_size; diff --git a/src/xenia/cpu/xenon_memory.h b/src/xenia/memory.h similarity index 57% rename from src/xenia/cpu/xenon_memory.h rename to src/xenia/memory.h index f1dfe331f..91c87c6a9 100644 --- a/src/xenia/cpu/xenon_memory.h +++ b/src/xenia/memory.h @@ -7,8 +7,8 @@ ****************************************************************************** */ -#ifndef XENIA_CPU_XENON_MEMORY_H_ -#define XENIA_CPU_XENON_MEMORY_H_ +#ifndef XENIA_MEMORY_H_ +#define XENIA_MEMORY_H_ #include @@ -20,22 +20,41 @@ typedef struct xe_ppc_state xe_ppc_state_t; namespace xe { -namespace cpu { -class XenonMemoryHeap; +class MemoryHeap; -class XenonMemory : public alloy::Memory { +// TODO(benvanik): move to heap. +enum { + MEMORY_FLAG_64KB_PAGES = (1 << 1), + MEMORY_FLAG_ZERO = (1 << 2), + MEMORY_FLAG_PHYSICAL = (1 << 3), +}; + +// TODO(benvanik): move to heap. +// Equivalent to the Win32 MEMORY_BASIC_INFORMATION struct. +struct AllocationInfo { + uint64_t base_address; + uint64_t allocation_base; + uint32_t allocation_protect; // TBD + size_t region_size; + uint32_t state; // TBD + uint32_t protect; // TBD + uint32_t type; // TBD +}; + +class Memory : public alloy::Memory { public: - XenonMemory(); - virtual ~XenonMemory(); + Memory(); + ~Memory() override; int Initialize() override; + // TODO(benvanik): remove with GPU refactor. uint64_t page_table() const override { return page_table_; } bool AddMappedRange(uint64_t address, uint64_t mask, uint64_t size, - void* context, MMIOReadCallback read_callback, - MMIOWriteCallback write_callback); + void* context, cpu::MMIOReadCallback read_callback, + cpu::MMIOWriteCallback write_callback); uint8_t LoadI8(uint64_t address) override; uint16_t LoadI16(uint64_t address) override; @@ -47,15 +66,14 @@ class XenonMemory : public alloy::Memory { void StoreI64(uint64_t address, uint64_t value) override; uint64_t HeapAlloc(uint64_t base_address, size_t size, uint32_t flags, - uint32_t alignment = 0x20) override; - int HeapFree(uint64_t address, size_t size) override; + uint32_t alignment = 0x20); + int HeapFree(uint64_t address, size_t size); - bool QueryInformation(uint64_t base_address, - alloy::AllocationInfo* mem_info) override; - size_t QuerySize(uint64_t base_address) override; + bool QueryInformation(uint64_t base_address, AllocationInfo* mem_info); + size_t QuerySize(uint64_t base_address); - int Protect(uint64_t address, size_t size, uint32_t access) override; - uint32_t QueryProtect(uint64_t address) override; + int Protect(uint64_t address, size_t size, uint32_t access); + uint32_t QueryProtect(uint64_t address); private: int MapViews(uint8_t* mapping_base); @@ -76,17 +94,16 @@ class XenonMemory : public alloy::Memory { uint8_t* all_views[6]; } views_; - std::unique_ptr mmio_handler_; + std::unique_ptr mmio_handler_; - XenonMemoryHeap* virtual_heap_; - XenonMemoryHeap* physical_heap_; + MemoryHeap* virtual_heap_; + MemoryHeap* physical_heap_; uint64_t page_table_; - friend class XenonMemoryHeap; + friend class MemoryHeap; }; -} // namespace cpu } // namespace xe -#endif // XENIA_CPU_XENON_MEMORY_H_ +#endif // XENIA_MEMORY_H_ diff --git a/src/xenia/sources.gypi b/src/xenia/sources.gypi index cec755d15..26c0a909d 100644 --- a/src/xenia/sources.gypi +++ b/src/xenia/sources.gypi @@ -13,6 +13,8 @@ 'logging.h', 'malloc.cc', 'malloc.h', + 'memory.cc', + 'memory.h', 'profiling.cc', 'profiling.h', 'types.h', diff --git a/tools/alloy-sandbox/alloy-sandbox.cc b/tools/alloy-sandbox/alloy-sandbox.cc index 508ede3c9..393a1c6ac 100644 --- a/tools/alloy-sandbox/alloy-sandbox.cc +++ b/tools/alloy-sandbox/alloy-sandbox.cc @@ -15,7 +15,6 @@ #include #include #include -#include #include @@ -28,11 +27,12 @@ using alloy::runtime::Runtime; class ThreadState : public alloy::runtime::ThreadState { public: ThreadState(Runtime* runtime, uint32_t thread_id, size_t stack_size, - uint64_t thread_state_address) + uint64_t thread_state_address, uint64_t thread_stack_address) : alloy::runtime::ThreadState(runtime, thread_id), + stack_address_(thread_stack_address), stack_size_(stack_size), thread_state_address_(thread_state_address) { - stack_address_ = memory_->HeapAlloc(0, stack_size, MEMORY_FLAG_ZERO); + memset(memory_->Translate(stack_address_), 0, stack_size_); // Allocate with 64b alignment. context_ = (PPCContext*)xe_malloc_aligned(sizeof(PPCContext)); @@ -60,7 +60,6 @@ class ThreadState : public alloy::runtime::ThreadState { ~ThreadState() override { runtime_->debugger()->OnThreadDestroyed(this); xe_free_aligned(context_); - memory_->HeapFree(stack_address_, stack_size_); } PPCContext* context() const { return context_; } @@ -80,7 +79,8 @@ int main(std::vector& args) { xe::Profiler::Initialize(); xe::Profiler::ThreadEnter("main"); - auto memory = std::make_unique(); + size_t memory_size = 16 * 1024 * 1024; + auto memory = std::make_unique(memory_size); auto runtime = std::make_unique(memory.get()); auto frontend = @@ -97,11 +97,14 @@ int main(std::vector& args) { runtime->AddModule(std::move(module)); { - auto thread_state = - std::make_unique(runtime.get(), 100, 64 * 1024, 0); + uint64_t thread_state_address = 0; + uint64_t stack_address = memory_size - 1024; + uint64_t stack_size = 64 * 1024; + auto thread_state = std::make_unique( + runtime.get(), 100, stack_address, stack_size, thread_state_address); alloy::runtime::Function* fn; - runtime->ResolveFunction(0x82000000, &fn); + runtime->ResolveFunction(0x1000, &fn); auto ctx = thread_state->context(); ctx->lr = 0xBEBEBEBE; ctx->r[5] = 10;