Merge pull request #156 from chrisps/misc_krnl4_23_23

[Kernel] Misc fixes, stubs
This commit is contained in:
chrisps 2023-04-23 11:51:31 -04:00 committed by GitHub
commit 1b307ae129
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 225 additions and 41 deletions

View File

@ -52,6 +52,10 @@ XE_GPU_REGISTER(0x057F, kDword, SCRATCH_REG7)
XE_GPU_REGISTER(0x05C8, kDword, WAIT_UNTIL)
//src is flash_xam.xex, i've seen it used by the kernel and aurora
//seems to have a negative value while the gpu is busy
//XE_GPU_REGISTER(0x05D0, kDword, RBBM_STATUS)
//update count = 6 bit field, bits 8- 14
//there are several other fields here, they have an unknown purpose
@ -271,6 +275,8 @@ XE_GPU_REGISTER(0x0F0C, kDword, BC_PERFCOUNTER2_LOW)
XE_GPU_REGISTER(0x0F0D, kDword, BC_PERFCOUNTER2_HI)
XE_GPU_REGISTER(0x0F0E, kDword, BC_PERFCOUNTER3_LOW)
XE_GPU_REGISTER(0x0F0F, kDword, BC_PERFCOUNTER3_HI)
//src is flash_xam.xex
//XE_GPU_REGISTER(0x0F12, RB_SIDEBAND_DATA,
XE_GPU_REGISTER(0x1004, kDword, HZ_PERFCOUNTER0_SELECT)
XE_GPU_REGISTER(0x1005, kDword, HZ_PERFCOUNTER0_HI)

View File

@ -67,6 +67,14 @@ KernelState::KernelState(Emulator* emulator)
// Hardcoded maximum of 2048 TLS slots.
tls_bitmap_.Resize(2048);
auto hc_loc_heap = memory_->LookupHeap(strange_hardcoded_page_);
bool fixed_alloc_worked = hc_loc_heap->AllocFixed(
strange_hardcoded_page_, 65536, 0,
kMemoryAllocationCommit | kMemoryAllocationReserve,
kMemoryProtectRead | kMemoryProtectWrite);
xenia_assert(fixed_alloc_worked);
xam::AppManager::RegisterApps(this, app_manager_.get());
}
@ -954,9 +962,7 @@ void KernelState::UpdateKeTimestampBundle() {
}
uint32_t KernelState::GetKeTimestampBundle() {
XE_LIKELY_IF(ke_timestamp_bundle_ptr_) {
return ke_timestamp_bundle_ptr_;
}
XE_LIKELY_IF(ke_timestamp_bundle_ptr_) { return ke_timestamp_bundle_ptr_; }
else {
global_critical_region::PrepareToAcquire();
return CreateKeTimestampBundle();

View File

@ -22,6 +22,7 @@
#include "xenia/base/cvar.h"
#include "xenia/base/mutex.h"
#include "xenia/cpu/export_resolver.h"
#include "xenia/kernel/util/kernel_fwd.h"
#include "xenia/kernel/util/native_list.h"
#include "xenia/kernel/util/object_table.h"
#include "xenia/kernel/util/xdbf_utils.h"
@ -45,14 +46,6 @@ namespace kernel {
constexpr fourcc_t kKernelSaveSignature = make_fourcc("KRNL");
class Dispatcher;
class XHostThread;
class KernelModule;
class XModule;
class XNotifyListener;
class XThread;
class UserModule;
// (?), used by KeGetCurrentProcessType
constexpr uint32_t X_PROCTYPE_IDLE = 0;
constexpr uint32_t X_PROCTYPE_USER = 1;
@ -292,7 +285,13 @@ class KernelState {
BitMap tls_bitmap_;
uint32_t ke_timestamp_bundle_ptr_ = 0;
std::unique_ptr<xe::threading::HighResolutionTimer> timestamp_timer_;
//fixed address referenced by dashboards. Data is currently unknown
uint32_t strange_hardcoded_page_ = 0x8E038634 & (~0xFFFF);
uint32_t strange_hardcoded_location_ = 0x8E038634;
friend class XObject;
public:
uint32_t dash_context_ = 0;
};
} // namespace kernel

View File

@ -0,0 +1,30 @@
#ifndef XENIA_KERNEL_UTIL_KERNEL_FWD_H_
#define XENIA_KERNEL_UTIL_KERNEL_FWD_H_
namespace xe::kernel {
class Dispatcher;
class XHostThread;
class KernelModule;
class XModule;
class XNotifyListener;
class XThread;
class UserModule;
struct ProcessInfoBlock;
struct TerminateNotification;
struct X_TIME_STAMP_BUNDLE;
class KernelState;
struct XAPC;
struct X_KPCR;
struct X_KTHREAD;
struct X_OBJECT_HEADER;
struct X_OBJECT_CREATE_INFORMATION;
struct X_OBJECT_TYPE;
} // namespace xe::kernel
namespace xe::kernel::util {
class NativeList;
class ObjectTable;
}
#endif

View File

@ -8,7 +8,7 @@
*/
#include "xenia/kernel/util/shim_utils.h"
#include "xenia/kernel/xthread.h"
namespace xe {
namespace kernel {
namespace shim {
@ -17,6 +17,10 @@ thread_local StringBuffer string_buffer_;
StringBuffer* thread_local_string_buffer() { return &string_buffer_; }
XThread* ContextParam::CurrentXThread() const {
return XThread::GetCurrentThread();
}
} // namespace shim
} // namespace kernel
} // namespace xe

View File

@ -203,8 +203,21 @@ class ContextParam : public Param {
PPCContext* operator->() const { return ctx_; }
template <typename T>
inline T TranslateVirtual(uint32_t guest_addr) const {
return ctx_->TranslateVirtual<T>(guest_addr);
}
template <typename T>
inline T TranslateGPR(uint32_t which_gpr) const {
return ctx_->TranslateVirtualGPR<T>(ctx_->r[which_gpr]);
}
X_KPCR* GetPCR() const { return TranslateGPR<X_KPCR*>(13); }
XThread* CurrentXThread() const;
protected:
PPCContext* ctx_;
PPCContext* XE_RESTRICT ctx_;
};
class PointerParam : public ParamBase<uint32_t> {

View File

@ -475,7 +475,7 @@ dword_result_t XamSwapDisc_entry(
completion_event();
return X_ERROR_SUCCESS;
}
auto filesystem = kernel_state()->file_system();
auto mount_path = "\\Device\\LauncherData";
@ -498,6 +498,14 @@ dword_result_t XamSwapDisc_entry(
}
DECLARE_XAM_EXPORT1(XamSwapDisc, kContent, kSketchy);
dword_result_t XamLoaderGetMediaInfoEx_entry(dword_t unk1, dword_t unk2,
lpdword_t unk3) {
*unk3 = 0;
return 0;
}
DECLARE_XAM_EXPORT1(XamLoaderGetMediaInfoEx, kContent, kStub);
} // namespace xam
} // namespace kernel
} // namespace xe

View File

@ -529,6 +529,22 @@ dword_result_t XamShowCommunitySessionsUI_entry(unknown_t r3, unknown_t r4) {
}
DECLARE_XAM_EXPORT1(XamShowCommunitySessionsUI, kNone, kStub);
// this is supposed to do a lot more, calls another function that triggers some
// cbs
dword_result_t XamSetDashContext_entry(dword_t value,
const ppc_context_t& ctx) {
ctx->kernel_state->dash_context_ = value;
return 0;
}
DECLARE_XAM_EXPORT1(XamSetDashContext, kNone, kImplemented);
dword_result_t XamGetDashContext_entry(const ppc_context_t& ctx) {
return ctx->kernel_state->dash_context_;
}
DECLARE_XAM_EXPORT1(XamGetDashContext, kNone, kImplemented);
} // namespace xam
} // namespace kernel
} // namespace xe

View File

@ -808,6 +808,28 @@ dword_result_t XamSessionRefObjByHandle_entry(dword_t handle,
}
DECLARE_XAM_EXPORT1(XamSessionRefObjByHandle, kUserProfiles, kStub);
dword_result_t XamUserIsUnsafeProgrammingAllowed_entry(dword_t unk1, dword_t unk2,
lpdword_t unk3, dword_t unk4,
dword_t unk5, dword_t unk6) {
if (!unk3 || unk1 != 255 && unk1 >= 4) {
return 87;
}
*unk3 = 1;
return 0;
}
DECLARE_XAM_EXPORT1(XamUserIsUnsafeProgrammingAllowed, kUserProfiles, kStub);
dword_result_t XamUserGetSubscriptionType_entry(dword_t user_index, dword_t unk2,
dword_t unk3, dword_t unk4,
dword_t unk5, dword_t unk6) {
if (!unk2 || !unk3 || user_index > 4) {
return 0x80070057;
}
return 0;
}
DECLARE_XAM_EXPORT1(XamUserGetSubscriptionType, kUserProfiles, kStub);
} // namespace xam
} // namespace kernel
} // namespace xe

View File

@ -632,9 +632,30 @@ void ExFreePool_entry(lpvoid_t base_address) {
}
DECLARE_XBOXKRNL_EXPORT1(ExFreePool, kMemory, kImplemented);
dword_result_t KeGetImagePageTableEntry_entry(lpvoid_t address) {
// Unknown
return 1;
// hv syscall 15, jumps into (bootloader function table??) alternative table ptr
// offset 224
// this is not a correct implementation. i just wanted to get it to return a
// value thats in the same range as the hv's values that kind of reflects the
// pages index and heap
dword_result_t KeGetImagePageTableEntry_entry(dword_t address,
const ppc_context_t& ctx) {
auto kernel_state = ctx->kernel_state;
xe::BaseHeap* image_heap = kernel_state->memory()->LookupHeap(address);
if (image_heap->heap_type() != HeapType::kGuestXex) {
return 0;
}
uint32_t returned_value = address - image_heap->heap_base();
// todo: its always a power of two, should shift
returned_value /= image_heap->page_size();
if (image_heap->page_size() < 65536) {
returned_value |= 0x40000000;
}
return returned_value & 0x400FFFFF; // this is actually the mask it applies
// to the final
// result before returning it
}
DECLARE_XBOXKRNL_EXPORT1(KeGetImagePageTableEntry, kMemory, kStub);

View File

@ -83,12 +83,25 @@ dword_result_t ObLookupThreadByThreadId_entry(dword_t thread_id,
return X_STATUS_SUCCESS;
}
DECLARE_XBOXKRNL_EXPORT1(ObLookupThreadByThreadId, kNone, kImplemented);
template <uint32_t ordinal>
static constexpr uint32_t object_type_id_for_ordinal_v =
0xD000BEEF | (ordinal << 16);
// These values come from how Xenia handles uninitialized kernel data exports.
// D###BEEF where ### is the ordinal.
const static std::unordered_map<XObject::Type, uint32_t> object_types = {
{XObject::Type::Event, 0xD00EBEEF},
{XObject::Type::Semaphore, 0xD017BEEF},
{XObject::Type::Thread, 0xD01BBEEF}};
{XObject::Type::Event,
object_type_id_for_ordinal_v<ordinals::ExEventObjectType>},
{XObject::Type::Semaphore,
object_type_id_for_ordinal_v<ordinals::ExSemaphoreObjectType>},
{XObject::Type::Thread,
object_type_id_for_ordinal_v<ordinals::ExThreadObjectType>},
{XObject::Type::File,
object_type_id_for_ordinal_v<ordinals::IoFileObjectType>},
{XObject::Type::Mutant,
object_type_id_for_ordinal_v<ordinals::ExMutantObjectType>},
{XObject::Type::Device,
object_type_id_for_ordinal_v<ordinals::IoDeviceObjectType>}};
dword_result_t ObReferenceObjectByHandle_entry(dword_t handle,
dword_t object_type_ptr,
lpdword_t out_object_ptr) {
@ -113,6 +126,8 @@ dword_result_t ObReferenceObjectByHandle_entry(dword_t handle,
// Caller takes the reference.
// It's released in ObDereferenceObject.
object->RetainHandle();
xenia_assert(native_ptr != 0);
if (out_object_ptr.guest_address()) {
*out_object_ptr = native_ptr;
}
@ -120,14 +135,17 @@ dword_result_t ObReferenceObjectByHandle_entry(dword_t handle,
}
DECLARE_XBOXKRNL_EXPORT1(ObReferenceObjectByHandle, kNone, kImplemented);
dword_result_t ObReferenceObjectByName_entry(lpstring_t name,
dword_result_t ObReferenceObjectByName_entry(pointer_t<X_ANSI_STRING> name,
dword_t attributes,
dword_t object_type_ptr,
lpvoid_t parse_context,
lpdword_t out_object_ptr) {
lpdword_t out_object_ptr,
const ppc_context_t& ctx) {
X_HANDLE handle = X_INVALID_HANDLE_VALUE;
char* name_str = ctx.TranslateVirtual<char*>(name->pointer);
X_STATUS result =
kernel_state()->object_table()->GetObjectByName(name.value(), &handle);
kernel_state()->object_table()->GetObjectByName(name_str, &handle);
if (XSUCCEEDED(result)) {
return ObReferenceObjectByHandle_entry(handle, object_type_ptr,
out_object_ptr);
@ -142,6 +160,10 @@ void ObDereferenceObject_entry(dword_t native_ptr, const ppc_context_t& ctx) {
if (native_ptr == 0xDEADF00D) {
return;
}
if (!native_ptr) {
XELOGE("Null native ptr in ObDereferenceObject!");
return;
}
auto object = XObject::GetNativeObject<XObject>(
kernel_state(), kernel_memory()->TranslateVirtual(native_ptr));

View File

@ -245,7 +245,7 @@ void KeSetCurrentStackPointers_entry(lpvoid_t stack_ptr,
pcr->stack_base_ptr = stack_base.guest_address();
pcr->stack_end_ptr = stack_limit.guest_address();
context->r[1] = stack_ptr.guest_address();
// If a fiber is set, and the thread matches, reenter to avoid issues with
// host stack overflowing.
if (thread->fiber_ptr &&
@ -337,8 +337,8 @@ DECLARE_XBOXKRNL_EXPORT2(KeQueryPerformanceFrequency, kThreading, kImplemented,
kHighFrequency);
uint32_t KeDelayExecutionThread(uint32_t processor_mode,
uint32_t alertable,
uint64_t* interval_ptr) {
uint32_t alertable,
uint64_t* interval_ptr) {
XThread* thread = XThread::GetCurrentThread();
X_STATUS result = thread->Delay(processor_mode, alertable, *interval_ptr);
@ -521,7 +521,7 @@ uint32_t xeNtSetEvent(uint32_t handle, xe::be<uint32_t>* previous_state_ptr) {
//d3 ros does this
if (ev->type() != XObject::Type::Event) {
return X_STATUS_OBJECT_TYPE_MISMATCH;
}
}
int32_t was_signalled = ev->Set(0, false);
if (previous_state_ptr) {
*previous_state_ptr = static_cast<uint32_t>(was_signalled);
@ -746,7 +746,7 @@ dword_result_t NtReleaseMutant_entry(dword_t mutant_handle, dword_t unknown) {
auto mutant =
kernel_state()->object_table()->LookupObject<XMutant>(mutant_handle);
if (mutant) {
result = mutant->ReleaseMutant(priority_increment, abandon, wait);
mutant->ReleaseMutant(priority_increment, abandon, wait);
} else {
result = X_STATUS_INVALID_HANDLE;
}
@ -992,11 +992,7 @@ dword_result_t NtSignalAndWaitForSingleObjectEx_entry(dword_t signal_handle,
DECLARE_XBOXKRNL_EXPORT3(NtSignalAndWaitForSingleObjectEx, kThreading,
kImplemented, kBlocking, kHighFrequency);
static void PrefetchForCAS(const void* value) {
if (amd64::GetFeatureFlags() & amd64::kX64EmitPrefetchW) {
swcache::PrefetchW(value);
}
}
static void PrefetchForCAS(const void* value) { swcache::PrefetchW(value); }
uint32_t xeKeKfAcquireSpinLock(uint32_t* lock, uint64_t r13 = 1) {
// XELOGD(
@ -1111,21 +1107,58 @@ void KeLeaveCriticalRegion_entry() {
DECLARE_XBOXKRNL_EXPORT2(KeLeaveCriticalRegion, kThreading, kImplemented,
kHighFrequency);
dword_result_t KeRaiseIrqlToDpcLevel_entry() {
auto old_value = kernel_state()->processor()->RaiseIrql(cpu::Irql::DPC);
return (uint32_t)old_value;
dword_result_t KeRaiseIrqlToDpcLevel_entry(const ppc_context_t& ctx) {
auto pcr = ctx.GetPCR();
uint32_t old_irql = pcr->current_irql;
if (old_irql > 2) {
XELOGE("KeRaiseIrqlToDpcLevel - old_irql > 2");
}
pcr->current_irql = 2;
return old_irql;
}
DECLARE_XBOXKRNL_EXPORT2(KeRaiseIrqlToDpcLevel, kThreading, kImplemented,
kHighFrequency);
void KfLowerIrql_entry(dword_t old_value) {
kernel_state()->processor()->LowerIrql(
static_cast<cpu::Irql>((uint32_t)old_value));
// irql is supposed to be per thread afaik...
void KfLowerIrql_entry(dword_t new_irql, const ppc_context_t& ctx) {
X_KPCR* kpcr = ctx.GetPCR();
XThread::GetCurrentThread()->CheckApcs();
if (new_irql > kpcr->current_irql) {
XELOGE("KfLowerIrql : new_irql > kpcr->current_irql!");
}
kpcr->current_irql = new_irql;
if (new_irql < 2) {
{
// this actually calls a function that eventually calls checkapcs.
// the called function does a ton of other stuff including changing the
// irql and interrupt_related
ctx.CurrentXThread()->CheckApcs();
}
}
}
DECLARE_XBOXKRNL_EXPORT2(KfLowerIrql, kThreading, kImplemented, kHighFrequency);
// used by aurora's nova plugin
// like the other irql related functions, writes to an unknown mmio range (
// 0x7FFF ). The range is indexed by the low 16 bits of the KPCR's pointer (so
// r13)
dword_result_t KfRaiseIrql_entry(dword_t new_irql, const ppc_context_t& ctx) {
X_KPCR* v1 = ctx.GetPCR();
uint32_t old_irql = v1->current_irql;
v1->current_irql = new_irql;
if (old_irql > (unsigned int)new_irql) {
XELOGE("KfRaiseIrql - old_irql > new_irql!");
}
return old_irql;
}
DECLARE_XBOXKRNL_EXPORT2(KfRaiseIrql, kThreading, kImplemented, kHighFrequency);
void NtQueueApcThread_entry(dword_t thread_handle, lpvoid_t apc_routine,
lpvoid_t apc_routine_context, lpvoid_t arg1,
lpvoid_t arg2) {

View File

@ -134,6 +134,7 @@ class XObject {
SymbolicLink,
Thread,
Timer,
Device
};
XObject(Type type);

View File

@ -71,7 +71,10 @@ struct XAPC {
struct X_KPCR {
xe::be<uint32_t> tls_ptr; // 0x0
xe::be<uint32_t> msr_mask; // 0x4
uint8_t unk_08[0x28]; // 0x8
xe::be<uint16_t> interrupt_related; // 0x8
uint8_t unk_08[0xE]; // 0xA
uint8_t current_irql; // 0x18
uint8_t unk_19[0x17]; // 0x19
xe::be<uint32_t> pcr_ptr; // 0x30
uint8_t unk_34[0x38]; // 0x34
xe::be<uint32_t> use_alternative_stack; //0x6C