Preparing to enable unshimmed kernel methods that can be called directly.
This commit is contained in:
parent
25d8b5f8d8
commit
fbe800aacd
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
#include <xenia/kernel/export.h>
|
#include <xenia/kernel/export.h>
|
||||||
#include <xenia/kernel/modules/xboxkrnl/kernel_state.h>
|
#include <xenia/kernel/modules/xboxkrnl/kernel_state.h>
|
||||||
|
#include <xenia/kernel/modules/xboxkrnl/xboxkrnl_private.h>
|
||||||
#include <xenia/kernel/modules/xboxkrnl/objects/xmodule.h>
|
#include <xenia/kernel/modules/xboxkrnl/objects/xmodule.h>
|
||||||
|
|
||||||
#include <xenia/kernel/modules/xboxkrnl/xboxkrnl_hal.h>
|
#include <xenia/kernel/modules/xboxkrnl/xboxkrnl_hal.h>
|
||||||
|
@ -31,6 +32,9 @@ DEFINE_bool(abort_before_entry, false,
|
||||||
"Abort execution right before launching the module.");
|
"Abort execution right before launching the module.");
|
||||||
|
|
||||||
|
|
||||||
|
KernelState* xe::kernel::xboxkrnl::shared_kernel_state_ = NULL;
|
||||||
|
|
||||||
|
|
||||||
XboxkrnlModule::XboxkrnlModule(Runtime* runtime) :
|
XboxkrnlModule::XboxkrnlModule(Runtime* runtime) :
|
||||||
KernelModule(runtime) {
|
KernelModule(runtime) {
|
||||||
ExportResolver* resolver = export_resolver_.get();
|
ExportResolver* resolver = export_resolver_.get();
|
||||||
|
@ -48,6 +52,10 @@ XboxkrnlModule::XboxkrnlModule(Runtime* runtime) :
|
||||||
// This is where all kernel objects are kept while running.
|
// This is where all kernel objects are kept while running.
|
||||||
kernel_state_ = auto_ptr<KernelState>(new KernelState(runtime));
|
kernel_state_ = auto_ptr<KernelState>(new KernelState(runtime));
|
||||||
|
|
||||||
|
// Setup the shared global state object.
|
||||||
|
XEASSERTNULL(shared_kernel_state_);
|
||||||
|
shared_kernel_state_ = kernel_state_.get();
|
||||||
|
|
||||||
// Register all exported functions.
|
// Register all exported functions.
|
||||||
RegisterHalExports(resolver, kernel_state_.get());
|
RegisterHalExports(resolver, kernel_state_.get());
|
||||||
RegisterMemoryExports(resolver, kernel_state_.get());
|
RegisterMemoryExports(resolver, kernel_state_.get());
|
||||||
|
@ -109,6 +117,8 @@ XboxkrnlModule::XboxkrnlModule(Runtime* runtime) :
|
||||||
}
|
}
|
||||||
|
|
||||||
XboxkrnlModule::~XboxkrnlModule() {
|
XboxkrnlModule::~XboxkrnlModule() {
|
||||||
|
// Clear the shared kernel state.
|
||||||
|
shared_kernel_state_ = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int XboxkrnlModule::LaunchModule(const char* path) {
|
int XboxkrnlModule::LaunchModule(const char* path) {
|
||||||
|
|
|
@ -41,4 +41,5 @@ private:
|
||||||
} // namespace kernel
|
} // namespace kernel
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
|
|
||||||
#endif // XENIA_KERNEL_MODULES_XBOXKRNL_MODULE_H_
|
#endif // XENIA_KERNEL_MODULES_XBOXKRNL_MODULE_H_
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
'xboxkrnl_module.cc',
|
'xboxkrnl_module.cc',
|
||||||
'xboxkrnl_module.h',
|
'xboxkrnl_module.h',
|
||||||
'xboxkrnl_ordinals.h',
|
'xboxkrnl_ordinals.h',
|
||||||
|
'xboxkrnl_private.h',
|
||||||
'xboxkrnl_rtl.cc',
|
'xboxkrnl_rtl.cc',
|
||||||
'xboxkrnl_rtl.h',
|
'xboxkrnl_rtl.h',
|
||||||
'xboxkrnl_table.inc',
|
'xboxkrnl_table.inc',
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
#include <xenia/kernel/shim_utils.h>
|
#include <xenia/kernel/shim_utils.h>
|
||||||
#include <xenia/kernel/xbox.h>
|
#include <xenia/kernel/xbox.h>
|
||||||
|
#include <xenia/kernel/modules/xboxkrnl/xboxkrnl_private.h>
|
||||||
|
|
||||||
|
|
||||||
using namespace xe;
|
using namespace xe;
|
||||||
|
@ -23,8 +24,13 @@ namespace kernel {
|
||||||
namespace xboxkrnl {
|
namespace xboxkrnl {
|
||||||
|
|
||||||
|
|
||||||
SHIM_CALL NtAllocateVirtualMemory_shim(
|
X_STATUS xeNtAllocateVirtualMemory(
|
||||||
xe_ppc_state_t* ppc_state, KernelState* state) {
|
uint32_t* base_addr_ptr, uint32_t* region_size_ptr,
|
||||||
|
uint32_t allocation_type, uint32_t protect_bits,
|
||||||
|
uint32_t unknown) {
|
||||||
|
KernelState* state = shared_kernel_state_;
|
||||||
|
XEASSERTNOTNULL(state);
|
||||||
|
|
||||||
// NTSTATUS
|
// NTSTATUS
|
||||||
// _Inout_ PVOID *BaseAddress,
|
// _Inout_ PVOID *BaseAddress,
|
||||||
// _In_ ULONG_PTR ZeroBits,
|
// _In_ ULONG_PTR ZeroBits,
|
||||||
|
@ -33,6 +39,55 @@ SHIM_CALL NtAllocateVirtualMemory_shim(
|
||||||
// _In_ ULONG Protect
|
// _In_ ULONG Protect
|
||||||
// ? handle?
|
// ? handle?
|
||||||
|
|
||||||
|
// I've only seen zero.
|
||||||
|
XEASSERT(unknown == 0);
|
||||||
|
|
||||||
|
// This allocates memory from the kernel heap, which is initialized on startup
|
||||||
|
// and shared by both the kernel implementation and user code.
|
||||||
|
// The xe_memory_ref object is used to actually get the memory, and although
|
||||||
|
// it's simple today we could extend it to do better things in the future.
|
||||||
|
|
||||||
|
// Must request a size.
|
||||||
|
if (!*region_size_ptr) {
|
||||||
|
return X_STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
// Check allocation type.
|
||||||
|
if (!(allocation_type & (X_MEM_COMMIT | X_MEM_RESET | X_MEM_RESERVE))) {
|
||||||
|
return X_STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
// If MEM_RESET is set only MEM_RESET can be set.
|
||||||
|
if (allocation_type & X_MEM_RESET && (allocation_type & ~X_MEM_RESET)) {
|
||||||
|
return X_STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
// Don't allow games to set execute bits.
|
||||||
|
if (protect_bits & (X_PAGE_EXECUTE | X_PAGE_EXECUTE_READ |
|
||||||
|
X_PAGE_EXECUTE_READWRITE | X_PAGE_EXECUTE_WRITECOPY)) {
|
||||||
|
return X_STATUS_ACCESS_DENIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adjust size.
|
||||||
|
uint32_t adjusted_size = *region_size_ptr;
|
||||||
|
// TODO(benvanik): adjust based on page size flags/etc?
|
||||||
|
|
||||||
|
// Allocate.
|
||||||
|
uint32_t flags = 0;
|
||||||
|
uint32_t addr = xe_memory_heap_alloc(
|
||||||
|
state->memory(), *base_addr_ptr, adjusted_size, flags);
|
||||||
|
if (!addr) {
|
||||||
|
// Failed - assume no memory available.
|
||||||
|
return X_STATUS_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stash back.
|
||||||
|
// Maybe set X_STATUS_ALREADY_COMMITTED if MEM_COMMIT?
|
||||||
|
*base_addr_ptr = addr;
|
||||||
|
*region_size_ptr = adjusted_size;
|
||||||
|
return X_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(benvanik): remove state parameter.
|
||||||
|
SHIM_CALL NtAllocateVirtualMemory_shim(
|
||||||
|
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||||
uint32_t base_addr_ptr = SHIM_GET_ARG_32(0);
|
uint32_t base_addr_ptr = SHIM_GET_ARG_32(0);
|
||||||
uint32_t base_addr_value = SHIM_MEM_32(base_addr_ptr);
|
uint32_t base_addr_value = SHIM_MEM_32(base_addr_ptr);
|
||||||
uint32_t region_size_ptr = SHIM_GET_ARG_32(1);
|
uint32_t region_size_ptr = SHIM_GET_ARG_32(1);
|
||||||
|
@ -41,61 +96,21 @@ SHIM_CALL NtAllocateVirtualMemory_shim(
|
||||||
uint32_t protect_bits = SHIM_GET_ARG_32(3); // X_PAGE_* bitmask
|
uint32_t protect_bits = SHIM_GET_ARG_32(3); // X_PAGE_* bitmask
|
||||||
uint32_t unknown = SHIM_GET_ARG_32(4);
|
uint32_t unknown = SHIM_GET_ARG_32(4);
|
||||||
|
|
||||||
// I've only seen zero.
|
|
||||||
XEASSERT(unknown == 0);
|
|
||||||
|
|
||||||
XELOGD(
|
XELOGD(
|
||||||
"NtAllocateVirtualMemory(%.8X(%.8X), %.8X(%.8X), %.8X, %.8X, %.8X)",
|
"NtAllocateVirtualMemory(%.8X(%.8X), %.8X(%.8X), %.8X, %.8X, %.8X)",
|
||||||
base_addr_ptr, base_addr_value,
|
base_addr_ptr, base_addr_value,
|
||||||
region_size_ptr, region_size_value,
|
region_size_ptr, region_size_value,
|
||||||
allocation_type, protect_bits, unknown);
|
allocation_type, protect_bits, unknown);
|
||||||
|
|
||||||
// This allocates memory from the kernel heap, which is initialized on startup
|
X_STATUS result = xeNtAllocateVirtualMemory(
|
||||||
// and shared by both the kernel implementation and user code.
|
&base_addr_value, ®ion_size_value,
|
||||||
// The xe_memory_ref object is used to actually get the memory, and although
|
allocation_type, protect_bits, unknown);
|
||||||
// it's simple today we could extend it to do better things in the future.
|
|
||||||
|
|
||||||
// Must request a size.
|
if (XSUCCEEDED(result)) {
|
||||||
if (!region_size_value) {
|
SHIM_SET_MEM_32(base_addr_ptr, base_addr_value);
|
||||||
SHIM_SET_RETURN(X_STATUS_INVALID_PARAMETER);
|
SHIM_SET_MEM_32(region_size_ptr, region_size_value);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
// Check allocation type.
|
SHIM_SET_RETURN(result);
|
||||||
if (!(allocation_type & (X_MEM_COMMIT | X_MEM_RESET | X_MEM_RESERVE))) {
|
|
||||||
SHIM_SET_RETURN(X_STATUS_INVALID_PARAMETER);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// If MEM_RESET is set only MEM_RESET can be set.
|
|
||||||
if (allocation_type & X_MEM_RESET && (allocation_type & ~X_MEM_RESET)) {
|
|
||||||
SHIM_SET_RETURN(X_STATUS_INVALID_PARAMETER);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Don't allow games to set execute bits.
|
|
||||||
if (protect_bits & (X_PAGE_EXECUTE | X_PAGE_EXECUTE_READ |
|
|
||||||
X_PAGE_EXECUTE_READWRITE | X_PAGE_EXECUTE_WRITECOPY)) {
|
|
||||||
SHIM_SET_RETURN(X_STATUS_ACCESS_DENIED);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adjust size.
|
|
||||||
uint32_t adjusted_size = region_size_value;
|
|
||||||
// TODO(benvanik): adjust based on page size flags/etc?
|
|
||||||
|
|
||||||
// Allocate.
|
|
||||||
uint32_t flags = 0;
|
|
||||||
uint32_t addr = xe_memory_heap_alloc(
|
|
||||||
state->memory(), base_addr_value, adjusted_size, flags);
|
|
||||||
if (!addr) {
|
|
||||||
// Failed - assume no memory available.
|
|
||||||
SHIM_SET_RETURN(X_STATUS_NO_MEMORY);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stash back.
|
|
||||||
// Maybe set X_STATUS_ALREADY_COMMITTED if MEM_COMMIT?
|
|
||||||
SHIM_SET_MEM_32(base_addr_ptr, addr);
|
|
||||||
SHIM_SET_MEM_32(region_size_ptr, adjusted_size);
|
|
||||||
SHIM_SET_RETURN(X_STATUS_SUCCESS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SHIM_CALL NtFreeVirtualMemory_shim(
|
SHIM_CALL NtFreeVirtualMemory_shim(
|
||||||
|
|
|
@ -19,6 +19,12 @@ namespace kernel {
|
||||||
namespace xboxkrnl {
|
namespace xboxkrnl {
|
||||||
|
|
||||||
|
|
||||||
|
X_STATUS xeNtAllocateVirtualMemory(
|
||||||
|
uint32_t* base_addr_ptr, uint32_t* region_size_ptr,
|
||||||
|
uint32_t allocation_type, uint32_t protect_bits,
|
||||||
|
uint32_t unknown);
|
||||||
|
|
||||||
|
|
||||||
void RegisterMemoryExports(ExportResolver* export_resolver, KernelState* state);
|
void RegisterMemoryExports(ExportResolver* export_resolver, KernelState* state);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
|
******************************************************************************
|
||||||
|
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||||
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef XENIA_KERNEL_MODULES_XBOXKRNL_PRIVATE_H_
|
||||||
|
#define XENIA_KERNEL_MODULES_XBOXKRNL_PRIVATE_H_
|
||||||
|
|
||||||
|
#include <xenia/common.h>
|
||||||
|
#include <xenia/core.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace kernel {
|
||||||
|
namespace xboxkrnl {
|
||||||
|
|
||||||
|
class KernelState;
|
||||||
|
|
||||||
|
|
||||||
|
extern KernelState* shared_kernel_state_;
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace xboxkrnl
|
||||||
|
} // namespace kernel
|
||||||
|
} // namespace xe
|
||||||
|
|
||||||
|
|
||||||
|
#endif // XENIA_KERNEL_MODULES_XBOXKRNL_PRIVATE_H_
|
Loading…
Reference in New Issue