Start of DPCs. Queuing them, but not yet dispatching.
This commit is contained in:
parent
27d4938cc2
commit
c50fbafbd9
|
@ -0,0 +1,37 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* 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. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <xenia/kernel/dispatcher.h>
|
||||||
|
|
||||||
|
#include <xenia/kernel/kernel_state.h>
|
||||||
|
#include <xenia/kernel/native_list.h>
|
||||||
|
|
||||||
|
|
||||||
|
using namespace xe;
|
||||||
|
using namespace xe::kernel;
|
||||||
|
|
||||||
|
|
||||||
|
Dispatcher::Dispatcher(KernelState* kernel_state) :
|
||||||
|
kernel_state_(kernel_state) {
|
||||||
|
lock_ = xe_mutex_alloc();
|
||||||
|
dpc_list_ = new NativeList(kernel_state->memory());
|
||||||
|
}
|
||||||
|
|
||||||
|
Dispatcher::~Dispatcher() {
|
||||||
|
delete dpc_list_;
|
||||||
|
xe_mutex_free(lock_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dispatcher::Lock() {
|
||||||
|
xe_mutex_lock(lock_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dispatcher::Unlock() {
|
||||||
|
xe_mutex_unlock(lock_);
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* 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_XBOXKRNL_DISPATCHER_H_
|
||||||
|
#define XENIA_KERNEL_XBOXKRNL_DISPATCHER_H_
|
||||||
|
|
||||||
|
#include <xenia/common.h>
|
||||||
|
#include <xenia/core.h>
|
||||||
|
|
||||||
|
#include <xenia/xbox.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace kernel {
|
||||||
|
|
||||||
|
class KernelState;
|
||||||
|
class NativeList;
|
||||||
|
|
||||||
|
|
||||||
|
class Dispatcher {
|
||||||
|
public:
|
||||||
|
Dispatcher(KernelState* kernel_state);
|
||||||
|
virtual ~Dispatcher();
|
||||||
|
|
||||||
|
KernelState* kernel_state() const { return kernel_state_; }
|
||||||
|
|
||||||
|
void Lock();
|
||||||
|
void Unlock();
|
||||||
|
|
||||||
|
NativeList* dpc_list() const { return dpc_list_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
private:
|
||||||
|
KernelState* kernel_state_;
|
||||||
|
|
||||||
|
xe_mutex_t* lock_;
|
||||||
|
NativeList* dpc_list_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace kernel
|
||||||
|
} // namespace xe
|
||||||
|
|
||||||
|
|
||||||
|
#endif // XENIA_KERNEL_XBOXKRNL_DISPATCHER_H_
|
|
@ -10,6 +10,7 @@
|
||||||
#include <xenia/kernel/kernel_state.h>
|
#include <xenia/kernel/kernel_state.h>
|
||||||
|
|
||||||
#include <xenia/emulator.h>
|
#include <xenia/emulator.h>
|
||||||
|
#include <xenia/kernel/dispatcher.h>
|
||||||
#include <xenia/kernel/xam_module.h>
|
#include <xenia/kernel/xam_module.h>
|
||||||
#include <xenia/kernel/xboxkrnl_module.h>
|
#include <xenia/kernel/xboxkrnl_module.h>
|
||||||
#include <xenia/kernel/xboxkrnl_private.h>
|
#include <xenia/kernel/xboxkrnl_private.h>
|
||||||
|
@ -35,6 +36,8 @@ KernelState::KernelState(Emulator* emulator) :
|
||||||
processor_ = emulator->processor();
|
processor_ = emulator->processor();
|
||||||
file_system_ = emulator->file_system();
|
file_system_ = emulator->file_system();
|
||||||
|
|
||||||
|
dispatcher_ = new Dispatcher(this);
|
||||||
|
|
||||||
object_table_ = new ObjectTable();
|
object_table_ = new ObjectTable();
|
||||||
object_mutex_ = xe_mutex_alloc(10000);
|
object_mutex_ = xe_mutex_alloc(10000);
|
||||||
|
|
||||||
|
@ -49,6 +52,8 @@ KernelState::~KernelState() {
|
||||||
xe_mutex_free(object_mutex_);
|
xe_mutex_free(object_mutex_);
|
||||||
delete object_table_;
|
delete object_table_;
|
||||||
|
|
||||||
|
delete dispatcher_;
|
||||||
|
|
||||||
XEASSERT(shared_kernel_state_ == this);
|
XEASSERT(shared_kernel_state_ == this);
|
||||||
shared_kernel_state_ = NULL;
|
shared_kernel_state_ = NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
XEDECLARECLASS1(xe, Emulator);
|
XEDECLARECLASS1(xe, Emulator);
|
||||||
XEDECLARECLASS2(xe, cpu, Processor);
|
XEDECLARECLASS2(xe, cpu, Processor);
|
||||||
|
XEDECLARECLASS2(xe, kernel, Dispatcher);
|
||||||
XEDECLARECLASS2(xe, kernel, XModule);
|
XEDECLARECLASS2(xe, kernel, XModule);
|
||||||
XEDECLARECLASS2(xe, kernel, XThread);
|
XEDECLARECLASS2(xe, kernel, XThread);
|
||||||
XEDECLARECLASS2(xe, kernel, XUserModule);
|
XEDECLARECLASS2(xe, kernel, XUserModule);
|
||||||
|
@ -43,6 +44,8 @@ public:
|
||||||
cpu::Processor* processor() const { return processor_; }
|
cpu::Processor* processor() const { return processor_; }
|
||||||
fs::FileSystem* file_system() const { return file_system_; }
|
fs::FileSystem* file_system() const { return file_system_; }
|
||||||
|
|
||||||
|
Dispatcher* dispatcher() const { return dispatcher_; }
|
||||||
|
|
||||||
ObjectTable* object_table() const { return object_table_; }
|
ObjectTable* object_table() const { return object_table_; }
|
||||||
|
|
||||||
XModule* GetModule(const char* name);
|
XModule* GetModule(const char* name);
|
||||||
|
@ -59,6 +62,8 @@ private:
|
||||||
cpu::Processor* processor_;
|
cpu::Processor* processor_;
|
||||||
fs::FileSystem* file_system_;
|
fs::FileSystem* file_system_;
|
||||||
|
|
||||||
|
Dispatcher* dispatcher_;
|
||||||
|
|
||||||
ObjectTable* object_table_;
|
ObjectTable* object_table_;
|
||||||
xe_mutex_t* object_mutex_;
|
xe_mutex_t* object_mutex_;
|
||||||
std::unordered_map<uint32_t, XThread*> threads_by_id_;
|
std::unordered_map<uint32_t, XThread*> threads_by_id_;
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* 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. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <xenia/kernel/native_list.h>
|
||||||
|
|
||||||
|
|
||||||
|
using namespace xe;
|
||||||
|
using namespace xe::kernel;
|
||||||
|
|
||||||
|
|
||||||
|
NativeList::NativeList(Memory* memory) :
|
||||||
|
memory_(memory),
|
||||||
|
head_(kInvalidPointer) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void NativeList::Insert(uint32_t ptr) {
|
||||||
|
uint8_t* mem = memory_->membase();
|
||||||
|
XESETUINT32BE(mem + ptr + 4, head_);
|
||||||
|
XESETUINT32BE(mem + ptr + 8, 0);
|
||||||
|
if (head_) {
|
||||||
|
XESETUINT32BE(mem + head_ + 8, ptr);
|
||||||
|
}
|
||||||
|
head_ = ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NativeList::IsQueued(uint32_t ptr) {
|
||||||
|
uint8_t* mem = memory_->membase();
|
||||||
|
uint32_t flink = XEGETUINT32BE(mem + ptr + 4);
|
||||||
|
uint32_t blink = XEGETUINT32BE(mem + ptr + 8);
|
||||||
|
return head_ == ptr || flink || blink;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NativeList::Remove(uint32_t ptr) {
|
||||||
|
uint8_t* mem = memory_->membase();
|
||||||
|
uint32_t flink = XEGETUINT32BE(mem + ptr + 4);
|
||||||
|
uint32_t blink = XEGETUINT32BE(mem + ptr + 8);
|
||||||
|
if (ptr == head_) {
|
||||||
|
head_ = flink;
|
||||||
|
if (flink) {
|
||||||
|
XESETUINT32BE(mem + flink + 8, 0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (blink) {
|
||||||
|
XESETUINT32BE(mem + blink + 4, flink);
|
||||||
|
}
|
||||||
|
if (flink) {
|
||||||
|
XESETUINT32BE(mem + flink + 8, blink);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
XESETUINT32BE(mem + ptr + 4, 0);
|
||||||
|
XESETUINT32BE(mem + ptr + 8, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t NativeList::Shift() {
|
||||||
|
if (!head_) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ptr = head_;
|
||||||
|
Remove(ptr);
|
||||||
|
return ptr;
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* 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_XBOXKRNL_NATIVE_LIST_H_
|
||||||
|
#define XENIA_KERNEL_XBOXKRNL_NATIVE_LIST_H_
|
||||||
|
|
||||||
|
#include <xenia/common.h>
|
||||||
|
#include <xenia/core.h>
|
||||||
|
|
||||||
|
#include <xenia/xbox.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace kernel {
|
||||||
|
|
||||||
|
|
||||||
|
// List is designed for storing pointers to objects in the guest heap.
|
||||||
|
// All values in the list should be assumed to be in big endian.
|
||||||
|
|
||||||
|
// Entries, as kernel objects, are assumed to have a LIST_ENTRY struct at +4b.
|
||||||
|
// struct MYOBJ {
|
||||||
|
// uint32_t stuff;
|
||||||
|
// LIST_ENTRY list_entry; <-- manipulated
|
||||||
|
// ...
|
||||||
|
// }
|
||||||
|
|
||||||
|
class NativeList {
|
||||||
|
public:
|
||||||
|
NativeList(Memory* memory);
|
||||||
|
|
||||||
|
void Insert(uint32_t ptr);
|
||||||
|
bool IsQueued(uint32_t ptr);
|
||||||
|
void Remove(uint32_t ptr);
|
||||||
|
uint32_t Shift();
|
||||||
|
|
||||||
|
private:
|
||||||
|
const uint32_t kInvalidPointer = 0xE0FE0FFF;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Memory* memory_;
|
||||||
|
uint32_t head_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace kernel
|
||||||
|
} // namespace xe
|
||||||
|
|
||||||
|
|
||||||
|
#endif // XENIA_KERNEL_XBOXKRNL_NATIVE_LIST_H_
|
|
@ -3,10 +3,14 @@
|
||||||
'sources': [
|
'sources': [
|
||||||
'async_request.cc',
|
'async_request.cc',
|
||||||
'async_request.h',
|
'async_request.h',
|
||||||
|
'dispatcher.cc',
|
||||||
|
'dispatcher.h',
|
||||||
'kernel.h',
|
'kernel.h',
|
||||||
'kernel_state.cc',
|
'kernel_state.cc',
|
||||||
'kernel_state.h',
|
'kernel_state.h',
|
||||||
'modules.h',
|
'modules.h',
|
||||||
|
'native_list.cc',
|
||||||
|
'native_list.h',
|
||||||
'object_table.cc',
|
'object_table.cc',
|
||||||
'object_table.h',
|
'object_table.h',
|
||||||
'xam_content.cc',
|
'xam_content.cc',
|
||||||
|
|
|
@ -9,7 +9,9 @@
|
||||||
|
|
||||||
#include <xenia/kernel/xboxkrnl_threading.h>
|
#include <xenia/kernel/xboxkrnl_threading.h>
|
||||||
|
|
||||||
|
#include <xenia/kernel/dispatcher.h>
|
||||||
#include <xenia/kernel/kernel_state.h>
|
#include <xenia/kernel/kernel_state.h>
|
||||||
|
#include <xenia/kernel/native_list.h>
|
||||||
#include <xenia/kernel/xboxkrnl_private.h>
|
#include <xenia/kernel/xboxkrnl_private.h>
|
||||||
#include <xenia/kernel/objects/xevent.h>
|
#include <xenia/kernel/objects/xevent.h>
|
||||||
#include <xenia/kernel/objects/xmutant.h>
|
#include <xenia/kernel/objects/xmutant.h>
|
||||||
|
@ -1321,6 +1323,92 @@ SHIM_CALL KeLeaveCriticalRegion_shim(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SHIM_CALL KeInitializeDpc_shim(
|
||||||
|
PPCContext* ppc_state, KernelState* state) {
|
||||||
|
uint32_t dpc_ptr = SHIM_GET_ARG_32(0);
|
||||||
|
uint32_t routine = SHIM_GET_ARG_32(1);
|
||||||
|
uint32_t context = SHIM_GET_ARG_32(2);
|
||||||
|
|
||||||
|
XELOGD(
|
||||||
|
"KeInitializeDpc(%.8X, %.8X, %.8X)",
|
||||||
|
dpc_ptr, routine, context);
|
||||||
|
|
||||||
|
// KDPC (maybe) 0x18 bytes?
|
||||||
|
uint32_t type = 0;
|
||||||
|
uint32_t importance = 0;
|
||||||
|
uint32_t number = 0;
|
||||||
|
SHIM_SET_MEM_32(dpc_ptr + 0,
|
||||||
|
(type << 24) | (importance << 16) | (number));
|
||||||
|
SHIM_SET_MEM_32(dpc_ptr + 4, 0); // flink
|
||||||
|
SHIM_SET_MEM_32(dpc_ptr + 8, 0); // blink
|
||||||
|
SHIM_SET_MEM_32(dpc_ptr + 12, routine);
|
||||||
|
SHIM_SET_MEM_32(dpc_ptr + 16, context);
|
||||||
|
SHIM_SET_MEM_32(dpc_ptr + 20, 0); // arg1
|
||||||
|
SHIM_SET_MEM_32(dpc_ptr + 24, 0); // arg2
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SHIM_CALL KeInsertQueueDpc_shim(
|
||||||
|
PPCContext* ppc_state, KernelState* state) {
|
||||||
|
uint32_t dpc_ptr = SHIM_GET_ARG_32(0);
|
||||||
|
uint32_t arg1 = SHIM_GET_ARG_32(1);
|
||||||
|
uint32_t arg2 = SHIM_GET_ARG_32(2);
|
||||||
|
|
||||||
|
XELOGD(
|
||||||
|
"KeInsertQueueDpc(%.8X, %.8X, %.8X)",
|
||||||
|
dpc_ptr, arg1, arg2);
|
||||||
|
|
||||||
|
// Lock dispatcher.
|
||||||
|
auto dispatcher = state->dispatcher();
|
||||||
|
dispatcher->Lock();
|
||||||
|
|
||||||
|
auto dpc_list = dispatcher->dpc_list();
|
||||||
|
|
||||||
|
// If already in a queue, abort.
|
||||||
|
if (dpc_list->IsQueued(dpc_ptr)) {
|
||||||
|
SHIM_SET_RETURN(0);
|
||||||
|
dispatcher->Unlock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prep DPC.
|
||||||
|
SHIM_SET_MEM_32(dpc_ptr + 20, arg1);
|
||||||
|
SHIM_SET_MEM_32(dpc_ptr + 24, arg2);
|
||||||
|
|
||||||
|
dpc_list->Insert(dpc_ptr);
|
||||||
|
|
||||||
|
dispatcher->Unlock();
|
||||||
|
|
||||||
|
SHIM_SET_RETURN(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SHIM_CALL KeRemoveQueueDpc_shim(
|
||||||
|
PPCContext* ppc_state, KernelState* state) {
|
||||||
|
uint32_t dpc_ptr = SHIM_GET_ARG_32(0);
|
||||||
|
|
||||||
|
XELOGD(
|
||||||
|
"KeRemoveQueueDpc(%.8X)",
|
||||||
|
dpc_ptr);
|
||||||
|
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
auto dispatcher = state->dispatcher();
|
||||||
|
dispatcher->Lock();
|
||||||
|
|
||||||
|
auto dpc_list = dispatcher->dpc_list();
|
||||||
|
if (dpc_list->IsQueued(dpc_ptr)) {
|
||||||
|
dpc_list->Remove(dpc_ptr);
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatcher->Unlock();
|
||||||
|
|
||||||
|
SHIM_SET_RETURN(result ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace kernel
|
} // namespace kernel
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
|
@ -1381,4 +1469,8 @@ void xe::kernel::xboxkrnl::RegisterThreadingExports(
|
||||||
|
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeEnterCriticalRegion, state);
|
SHIM_SET_MAPPING("xboxkrnl.exe", KeEnterCriticalRegion, state);
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", KeLeaveCriticalRegion, state);
|
SHIM_SET_MAPPING("xboxkrnl.exe", KeLeaveCriticalRegion, state);
|
||||||
|
|
||||||
|
SHIM_SET_MAPPING("xboxkrnl.exe", KeInitializeDpc, state);
|
||||||
|
SHIM_SET_MAPPING("xboxkrnl.exe", KeInsertQueueDpc, state);
|
||||||
|
SHIM_SET_MAPPING("xboxkrnl.exe", KeRemoveQueueDpc, state);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue