Several changes for timestamp bundle:
Fully defined the structure. Single copy of it + single timer across all modules, managing it is now the responsibility of KernelState. add global_critical_region::PrepareToAcquire, which uses Prefetchw on the global crit. We now know we can use Prefetchw on all cpus that have AVX. add KeQueryInterruptTime, which is used by some dashboards. add threading::NanoSleep
This commit is contained in:
@@ -22,7 +22,9 @@ namespace xboxkrnl {
|
||||
void KeEnableFpuExceptions_entry(
|
||||
const ppc_context_t& ctx) { // dword_t enabled) {
|
||||
// TODO(benvanik): can we do anything about exceptions?
|
||||
// theres a lot more thats supposed to happen here, the floating point state has to be saved to kthread, the irql changes, the machine state register is changed to enable exceptions
|
||||
// theres a lot more thats supposed to happen here, the floating point state
|
||||
// has to be saved to kthread, the irql changes, the machine state register is
|
||||
// changed to enable exceptions
|
||||
|
||||
X_KTHREAD* kthread = ctx->TranslateVirtual<X_KTHREAD*>(
|
||||
ctx->TranslateVirtualGPR<X_KPCR*>(ctx->r[13])->current_thread);
|
||||
@@ -117,7 +119,15 @@ void KeSaveFloatingPointState_entry(ppc_context_t& ctx) {
|
||||
|
||||
DECLARE_XBOXKRNL_EXPORT1(KeSaveFloatingPointState, kNone, kImplemented);
|
||||
#endif
|
||||
static qword_result_t KeQueryInterruptTime_entry(const ppc_context_t& ctx) {
|
||||
auto kstate = ctx->kernel_state;
|
||||
uint32_t ts_bundle = kstate->GetKeTimestampBundle();
|
||||
X_TIME_STAMP_BUNDLE* bundle =
|
||||
ctx->TranslateVirtual<X_TIME_STAMP_BUNDLE*>(ts_bundle);
|
||||
|
||||
return xe::load_and_swap<uint64_t>(&bundle->interrupt_time);
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT1(KeQueryInterruptTime, kNone, kImplemented);
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
@@ -78,8 +78,7 @@ bool XboxkrnlModule::SendPIXCommand(const char* cmd) {
|
||||
}
|
||||
|
||||
XboxkrnlModule::XboxkrnlModule(Emulator* emulator, KernelState* kernel_state)
|
||||
: KernelModule(kernel_state, "xe:\\xboxkrnl.exe"),
|
||||
timestamp_timer_(nullptr) {
|
||||
: KernelModule(kernel_state, "xe:\\xboxkrnl.exe") {
|
||||
RegisterExportTable(export_resolver_);
|
||||
|
||||
// Register all exported functions.
|
||||
@@ -216,23 +215,9 @@ XboxkrnlModule::XboxkrnlModule(Emulator* emulator, KernelState* kernel_state)
|
||||
xe::store_and_swap<uint8_t>(lpXboxKrnlVersion + 6, 0x80);
|
||||
xe::store_and_swap<uint8_t>(lpXboxKrnlVersion + 7, 0x00);
|
||||
|
||||
// KeTimeStampBundle (ad)
|
||||
// This must be updated during execution, at 1ms intevals.
|
||||
// We setup a system timer here to do that.
|
||||
uint32_t pKeTimeStampBundle = memory_->SystemHeapAlloc(24);
|
||||
auto lpKeTimeStampBundle = memory_->TranslateVirtual(pKeTimeStampBundle);
|
||||
export_resolver_->SetVariableMapping(
|
||||
"xboxkrnl.exe", ordinals::KeTimeStampBundle, pKeTimeStampBundle);
|
||||
xe::store_and_swap<uint64_t>(lpKeTimeStampBundle + 0, 0);
|
||||
xe::store_and_swap<uint64_t>(lpKeTimeStampBundle + 8, 0);
|
||||
xe::store_and_swap<uint32_t>(lpKeTimeStampBundle + 16,
|
||||
Clock::QueryGuestUptimeMillis());
|
||||
xe::store_and_swap<uint32_t>(lpKeTimeStampBundle + 20, 0);
|
||||
timestamp_timer_ = xe::threading::HighResolutionTimer::CreateRepeating(
|
||||
std::chrono::milliseconds(1), [lpKeTimeStampBundle]() {
|
||||
xe::store_and_swap<uint32_t>(lpKeTimeStampBundle + 16,
|
||||
Clock::QueryGuestUptimeMillis());
|
||||
});
|
||||
export_resolver_->SetVariableMapping("xboxkrnl.exe",
|
||||
ordinals::KeTimeStampBundle,
|
||||
kernel_state->GetKeTimestampBundle());
|
||||
}
|
||||
|
||||
static auto& get_xboxkrnl_exports() {
|
||||
|
||||
@@ -40,9 +40,6 @@ class XboxkrnlModule : public KernelModule {
|
||||
|
||||
protected:
|
||||
uint32_t pix_function_ = 0;
|
||||
|
||||
private:
|
||||
std::unique_ptr<xe::threading::HighResolutionTimer> timestamp_timer_;
|
||||
};
|
||||
|
||||
} // namespace xboxkrnl
|
||||
|
||||
@@ -363,9 +363,18 @@ dword_result_t NtYieldExecution_entry() {
|
||||
DECLARE_XBOXKRNL_EXPORT2(NtYieldExecution, kThreading, kImplemented,
|
||||
kHighFrequency);
|
||||
|
||||
void KeQuerySystemTime_entry(lpqword_t time_ptr) {
|
||||
uint64_t time = Clock::QueryGuestSystemTime();
|
||||
void KeQuerySystemTime_entry(lpqword_t time_ptr, const ppc_context_t& ctx) {
|
||||
if (time_ptr) {
|
||||
// update the timestamp bundle to the time we queried.
|
||||
// this is a race, but i don't of any sw that requires it, it just seems
|
||||
// like we ought to keep it consistent with ketimestampbundle in case
|
||||
// something uses this function, but also reads it directly
|
||||
uint32_t ts_bundle = ctx->kernel_state->GetKeTimestampBundle();
|
||||
uint64_t time = Clock::QueryGuestSystemTime();
|
||||
//todo: cmpxchg?
|
||||
xe::store_and_swap<uint64_t>(
|
||||
&ctx->TranslateVirtual<X_TIME_STAMP_BUNDLE*>(ts_bundle)->system_time,
|
||||
time);
|
||||
*time_ptr = time;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user