Merge branch 'master' into d3d12

This commit is contained in:
Triang3l
2018-11-25 12:44:30 +03:00
10 changed files with 347 additions and 199 deletions

View File

@@ -564,6 +564,10 @@ using xe::cpu::ExportTag;
DECLARE_EXPORT(xboxkrnl, name, category, \
xe::cpu::ExportTag::tag1 | xe::cpu::ExportTag::tag2 | \
xe::cpu::ExportTag::tag3)
#define DECLARE_XBOXKRNL_EXPORT4(name, category, tag1, tag2, tag3, tag4) \
DECLARE_EXPORT(xboxkrnl, name, category, \
xe::cpu::ExportTag::tag1 | xe::cpu::ExportTag::tag2 | \
xe::cpu::ExportTag::tag3 | xe::cpu::ExportTag::tag4)
} // namespace kernel
} // namespace xe

View File

@@ -28,28 +28,33 @@ namespace xam {
constexpr uint32_t X_LANGUAGE_ENGLISH = 1;
constexpr uint32_t X_LANGUAGE_JAPANESE = 2;
dword_result_t XamFeatureEnabled(dword_t unk) { return 0; }
DECLARE_XAM_EXPORT1(XamFeatureEnabled, kNone, kStub);
// Empty stub schema binary.
uint8_t schema_bin[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00,
0x00, 0x2C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x2C, 0x00,
0x00, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
};
dword_result_t XamGetOnlineSchema() {
static uint32_t schema_guest = 0;
static uint32_t schema_ptr_guest = 0;
if (!schema_guest) {
// create a dummy schema, 8 bytes of 0 seems to work fine
// (with another 8 bytes for schema ptr/schema size)
schema_guest = kernel_state()->memory()->SystemHeapAlloc(16);
schema_ptr_guest = schema_guest + 8;
schema_guest =
kernel_state()->memory()->SystemHeapAlloc(8 + sizeof(schema_bin));
auto schema = kernel_state()->memory()->TranslateVirtual(schema_guest);
memset(schema, 0, 16);
// store schema ptr + size
xe::store_and_swap<uint32_t>(schema + 0x8, schema_guest);
xe::store_and_swap<uint32_t>(schema + 0xC, 0x8);
std::memcpy(schema + 8, schema_bin, sizeof(schema_bin));
xe::store_and_swap<uint32_t>(schema + 0, schema_guest + 8);
xe::store_and_swap<uint32_t>(schema + 4, sizeof(schema_bin));
}
// return pointer to the schema ptr/schema size struct
return schema_ptr_guest;
return schema_guest;
}
DECLARE_XAM_EXPORT2(XamGetOnlineSchema, kNone, kImplemented, kSketchy);
DECLARE_XAM_EXPORT1(XamGetOnlineSchema, kNone, kImplemented);
void XamFormatDateString(dword_t unk, qword_t filetime, lpvoid_t buffer,
dword_t buffer_length) {

View File

@@ -373,8 +373,7 @@ void KeInitializeEvent(pointer_t<X_KEVENT> event_ptr, dword_t event_type,
}
DECLARE_XBOXKRNL_EXPORT1(KeInitializeEvent, kThreading, kImplemented);
dword_result_t KeSetEvent(pointer_t<X_KEVENT> event_ptr, dword_t increment,
dword_t wait) {
uint32_t keSetEvent(X_KEVENT* event_ptr, uint32_t increment, uint32_t wait) {
auto ev = XObject::GetNativeObject<XEvent>(kernel_state(), event_ptr);
if (!ev) {
assert_always();
@@ -383,6 +382,11 @@ dword_result_t KeSetEvent(pointer_t<X_KEVENT> event_ptr, dword_t increment,
return ev->Set(increment, !!wait);
}
dword_result_t KeSetEvent(pointer_t<X_KEVENT> event_ptr, dword_t increment,
dword_t wait) {
return keSetEvent(event_ptr, increment, wait);
}
DECLARE_XBOXKRNL_EXPORT2(KeSetEvent, kThreading, kImplemented, kHighFrequency);
dword_result_t KePulseEvent(pointer_t<X_KEVENT> event_ptr, dword_t increment,
@@ -508,9 +512,8 @@ void KeInitializeSemaphore(pointer_t<X_KSEMAPHORE> semaphore_ptr, dword_t count,
}
DECLARE_XBOXKRNL_EXPORT1(KeInitializeSemaphore, kThreading, kImplemented);
dword_result_t KeReleaseSemaphore(pointer_t<X_KSEMAPHORE> semaphore_ptr,
dword_t increment, dword_t adjustment,
dword_t wait) {
uint32_t keReleaseSemaphore(X_KSEMAPHORE* semaphore_ptr, uint32_t increment,
uint32_t adjustment, uint32_t wait) {
auto sem =
XObject::GetNativeObject<XSemaphore>(kernel_state(), semaphore_ptr);
if (!sem) {
@@ -523,6 +526,12 @@ dword_result_t KeReleaseSemaphore(pointer_t<X_KSEMAPHORE> semaphore_ptr,
return sem->ReleaseSemaphore(adjustment);
}
dword_result_t KeReleaseSemaphore(pointer_t<X_KSEMAPHORE> semaphore_ptr,
dword_t increment, dword_t adjustment,
dword_t wait) {
return keReleaseSemaphore(semaphore_ptr, increment, adjustment, wait);
}
DECLARE_XBOXKRNL_EXPORT1(KeReleaseSemaphore, kThreading, kImplemented);
dword_result_t NtCreateSemaphore(lpdword_t handle_ptr,
@@ -719,9 +728,9 @@ dword_result_t NtCancelTimer(dword_t timer_handle,
}
DECLARE_XBOXKRNL_EXPORT1(NtCancelTimer, kThreading, kImplemented);
dword_result_t KeWaitForSingleObject(lpvoid_t object_ptr, dword_t wait_reason,
dword_t processor_mode, dword_t alertable,
lpqword_t timeout_ptr) {
uint32_t keWaitForSingleObject(void* object_ptr, uint32_t wait_reason,
uint32_t processor_mode, uint32_t alertable,
uint64_t* timeout) {
auto object = XObject::GetNativeObject<XObject>(kernel_state(), object_ptr);
if (!object) {
@@ -730,12 +739,19 @@ dword_result_t KeWaitForSingleObject(lpvoid_t object_ptr, dword_t wait_reason,
return X_STATUS_ABANDONED_WAIT_0;
}
uint64_t timeout = timeout_ptr ? static_cast<uint64_t>(*timeout_ptr) : 0u;
X_STATUS result = object->Wait(wait_reason, processor_mode, alertable,
timeout_ptr ? &timeout : nullptr);
X_STATUS result =
object->Wait(wait_reason, processor_mode, alertable, timeout);
return result;
}
dword_result_t KeWaitForSingleObject(lpvoid_t object_ptr, dword_t wait_reason,
dword_t processor_mode, dword_t alertable,
lpqword_t timeout_ptr) {
uint64_t timeout = timeout_ptr ? static_cast<uint64_t>(*timeout_ptr) : 0u;
return keWaitForSingleObject(object_ptr, wait_reason, processor_mode,
alertable, &timeout);
}
DECLARE_XBOXKRNL_EXPORT3(KeWaitForSingleObject, kThreading, kImplemented,
kBlocking, kHighFrequency);
@@ -844,13 +860,12 @@ dword_result_t NtSignalAndWaitForSingleObjectEx(dword_t signal_handle,
DECLARE_XBOXKRNL_EXPORT3(NtSignalAndWaitForSingleObjectEx, kThreading,
kImplemented, kBlocking, kHighFrequency);
dword_result_t KfAcquireSpinLock(lpdword_t lock_ptr) {
uint32_t keKfAcquireSpinLock(uint32_t* lock) {
// XELOGD(
// "KfAcquireSpinLock(%.8X)",
// lock_ptr);
// Lock.
auto lock = reinterpret_cast<uint32_t*>(lock_ptr.host_address());
while (!xe::atomic_cas(0, 1, lock)) {
// Spin!
// TODO(benvanik): error on deadlock?
@@ -863,18 +878,27 @@ dword_result_t KfAcquireSpinLock(lpdword_t lock_ptr) {
return old_irql;
}
dword_result_t KfAcquireSpinLock(lpdword_t lock_ptr) {
auto lock = reinterpret_cast<uint32_t*>(lock_ptr.host_address());
return keKfAcquireSpinLock(lock);
}
DECLARE_XBOXKRNL_EXPORT3(KfAcquireSpinLock, kThreading, kImplemented, kBlocking,
kHighFrequency);
void KfReleaseSpinLock(lpdword_t lock_ptr, dword_t old_irql) {
void keKfReleaseSpinLock(uint32_t* lock, dword_t old_irql) {
// Restore IRQL.
XThread* thread = XThread::GetCurrentThread();
thread->LowerIrql(old_irql);
// Unlock.
auto lock = reinterpret_cast<uint32_t*>(lock_ptr.host_address());
xe::atomic_dec(lock);
}
void KfReleaseSpinLock(lpdword_t lock_ptr, dword_t old_irql) {
auto lock = reinterpret_cast<uint32_t*>(lock_ptr.host_address());
keKfReleaseSpinLock(lock, old_irql);
}
DECLARE_XBOXKRNL_EXPORT2(KfReleaseSpinLock, kThreading, kImplemented,
kHighFrequency);
@@ -1092,7 +1116,7 @@ struct X_ERWLOCK {
be<uint32_t> readers_entry_count; // 0xC
X_KEVENT writer_event; // 0x10
X_KSEMAPHORE reader_semaphore; // 0x20
be<uint32_t> spin_lock; // 0x34
uint32_t spin_lock; // 0x34
};
void ExInitializeReadWriteLock(pointer_t<X_ERWLOCK> lock_ptr) {
@@ -1105,6 +1129,51 @@ void ExInitializeReadWriteLock(pointer_t<X_ERWLOCK> lock_ptr) {
}
DECLARE_XBOXKRNL_EXPORT1(ExInitializeReadWriteLock, kThreading, kImplemented);
void ExAcquireReadWriteLockExclusive(pointer_t<X_ERWLOCK> lock_ptr) {
auto old_irql = keKfAcquireSpinLock(&lock_ptr->spin_lock);
lock_ptr->lock_count++;
keKfReleaseSpinLock(&lock_ptr->spin_lock, old_irql);
if (!lock_ptr->lock_count) {
return;
}
lock_ptr->writers_waiting_count++;
keWaitForSingleObject(&lock_ptr->writer_event, 0, 0, 0, nullptr);
}
DECLARE_XBOXKRNL_EXPORT4(ExAcquireReadWriteLockExclusive, kThreading,
kImplemented, kBlocking, kHighFrequency, kSketchy);
void ExReleaseReadWriteLock(pointer_t<X_ERWLOCK> lock_ptr) {
auto old_irql = keKfAcquireSpinLock(&lock_ptr->spin_lock);
lock_ptr->lock_count--;
if (lock_ptr->lock_count < 0) {
keKfReleaseSpinLock(&lock_ptr->spin_lock, old_irql);
return;
}
if (!lock_ptr->readers_entry_count) {
auto readers_waiting_count = lock_ptr->readers_waiting_count;
if (readers_waiting_count) {
lock_ptr->readers_waiting_count = 0;
lock_ptr->readers_entry_count = readers_waiting_count;
keKfReleaseSpinLock(&lock_ptr->spin_lock, old_irql);
keReleaseSemaphore(&lock_ptr->reader_semaphore, 1, readers_waiting_count,
0);
return;
}
}
auto count = lock_ptr->readers_entry_count--;
keKfReleaseSpinLock(&lock_ptr->spin_lock, old_irql);
if (!count) {
keSetEvent(&lock_ptr->writer_event, 1, 0);
}
}
DECLARE_XBOXKRNL_EXPORT2(ExReleaseReadWriteLock, kThreading, kImplemented,
kSketchy);
// NOTE: This function is very commonly inlined, and probably won't be called!
pointer_result_t InterlockedPushEntrySList(
pointer_t<X_SLIST_HEADER> plist_ptr, pointer_t<X_SINGLE_LIST_ENTRY> entry) {