summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/CMakeLists.txt1
-rw-r--r--src/core/arm/arm_interface.cpp26
-rw-r--r--src/core/arm/arm_interface.h8
-rw-r--r--src/core/arm/unicorn/arm_unicorn.cpp1
-rw-r--r--src/core/hle/kernel/process.cpp33
-rw-r--r--src/core/hle/kernel/process.h10
-rw-r--r--src/core/hle/kernel/svc.cpp21
-rw-r--r--src/core/hle/kernel/thread.cpp24
-rw-r--r--src/core/hle/kernel/thread.h23
-rw-r--r--src/core/hle/service/fatal/fatal.cpp3
-rw-r--r--src/core/hle/service/time/time.cpp20
-rw-r--r--src/core/hle/service/time/time.h12
-rw-r--r--src/yuzu/debugger/wait_tree.cpp4
13 files changed, 112 insertions, 74 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index f38271336..8f2db5bea 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -1,5 +1,6 @@
add_library(core STATIC
arm/arm_interface.h
+ arm/arm_interface.cpp
arm/exclusive_monitor.cpp
arm/exclusive_monitor.h
arm/unicorn/arm_unicorn.cpp
diff --git a/src/core/arm/arm_interface.cpp b/src/core/arm/arm_interface.cpp
new file mode 100644
index 000000000..bcc812da4
--- /dev/null
+++ b/src/core/arm/arm_interface.cpp
@@ -0,0 +1,26 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "arm_interface.h"
+#include "common/common_types.h"
+#include "common/logging/log.h"
+#include "core/memory.h"
+
+namespace Core {
+void ARM_Interface::LogBacktrace() {
+ VAddr fp = GetReg(29);
+ VAddr lr = GetReg(30);
+ VAddr sp = GetReg(13);
+ VAddr pc = GetPC();
+ LOG_ERROR(Core_ARM, "Backtrace, sp={:016X}, pc={:016X}", sp, pc);
+ for (;;) {
+ LOG_ERROR(Core_ARM, "{:016X}", lr);
+ if (!fp) {
+ break;
+ }
+ lr = Memory::Read64(fp + 8) - 4;
+ fp = Memory::Read64(fp);
+ }
+}
+}; // namespace Core
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h
index 59da33f30..91d2b0f81 100644
--- a/src/core/arm/arm_interface.h
+++ b/src/core/arm/arm_interface.h
@@ -141,6 +141,14 @@ public:
/// Prepare core for thread reschedule (if needed to correctly handle state)
virtual void PrepareReschedule() = 0;
+
+ /// fp (= r29) points to the last frame record.
+ /// Note that this is the frame record for the *previous* frame, not the current one.
+ /// Note we need to subtract 4 from our last read to get the proper address
+ /// Frame records are two words long:
+ /// fp+0 : pointer to previous frame record
+ /// fp+8 : value of lr for frame
+ void LogBacktrace();
};
} // namespace Core
diff --git a/src/core/arm/unicorn/arm_unicorn.cpp b/src/core/arm/unicorn/arm_unicorn.cpp
index ded4dd359..c455c81fb 100644
--- a/src/core/arm/unicorn/arm_unicorn.cpp
+++ b/src/core/arm/unicorn/arm_unicorn.cpp
@@ -10,6 +10,7 @@
#include "core/core.h"
#include "core/core_timing.h"
#include "core/hle/kernel/svc.h"
+#include "core/memory.h"
namespace Core {
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 06a673b9b..c5aa19afa 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -20,6 +20,35 @@
#include "core/settings.h"
namespace Kernel {
+namespace {
+/**
+ * Sets up the primary application thread
+ *
+ * @param owner_process The parent process for the main thread
+ * @param kernel The kernel instance to create the main thread under.
+ * @param entry_point The address at which the thread should start execution
+ * @param priority The priority to give the main thread
+ */
+void SetupMainThread(Process& owner_process, KernelCore& kernel, VAddr entry_point, u32 priority) {
+ // Setup page table so we can write to memory
+ SetCurrentPageTable(&owner_process.VMManager().page_table);
+
+ // Initialize new "main" thread
+ const VAddr stack_top = owner_process.VMManager().GetTLSIORegionEndAddress();
+ auto thread_res = Thread::Create(kernel, "main", entry_point, priority, 0,
+ owner_process.GetIdealCore(), stack_top, owner_process);
+
+ SharedPtr<Thread> thread = std::move(thread_res).Unwrap();
+
+ // Register 1 must be a handle to the main thread
+ const Handle guest_handle = owner_process.GetHandleTable().Create(thread).Unwrap();
+ thread->SetGuestHandle(guest_handle);
+ thread->GetContext().cpu_registers[1] = guest_handle;
+
+ // Threads by default are dormant, wake up the main thread so it runs when the scheduler fires
+ thread->ResumeFromWait();
+}
+} // Anonymous namespace
CodeSet::CodeSet() = default;
CodeSet::~CodeSet() = default;
@@ -64,7 +93,7 @@ ResultCode Process::ClearSignalState() {
ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata) {
program_id = metadata.GetTitleID();
- ideal_processor = metadata.GetMainThreadCore();
+ ideal_core = metadata.GetMainThreadCore();
is_64bit_process = metadata.Is64BitProgram();
vm_manager.Reset(metadata.GetAddressSpaceType());
@@ -86,7 +115,7 @@ void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) {
vm_manager.LogLayout();
ChangeStatus(ProcessStatus::Running);
- Kernel::SetupMainThread(kernel, entry_point, main_thread_priority, *this);
+ SetupMainThread(*this, kernel, entry_point, main_thread_priority);
}
void Process::PrepareForTermination() {
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index ac6956266..450dc6eeb 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -168,9 +168,9 @@ public:
/// Gets the resource limit descriptor for this process
SharedPtr<ResourceLimit> GetResourceLimit() const;
- /// Gets the default CPU ID for this process
- u8 GetDefaultProcessorID() const {
- return ideal_processor;
+ /// Gets the ideal CPU core ID for this process
+ u8 GetIdealCore() const {
+ return ideal_core;
}
/// Gets the bitmask of allowed CPUs that this process' threads can run on.
@@ -280,8 +280,8 @@ private:
/// Resource limit descriptor for this process
SharedPtr<ResourceLimit> resource_limit;
- /// The default CPU for this process, threads are scheduled on this cpu by default.
- u8 ideal_processor = 0;
+ /// The ideal CPU core for this process, threads are scheduled on this core by default.
+ u8 ideal_core = 0;
u32 is_virtual_address_memory_enabled = 0;
/// The Thread Local Storage area is allocated as processes create threads,
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index b955f9839..660e6f577 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -684,6 +684,9 @@ static void Break(u32 reason, u64 info1, u64 info2) {
"Emulated program broke execution! reason=0x{:016X}, info1=0x{:016X}, info2=0x{:016X}",
reason, info1, info2);
handle_debug_buffer(info1, info2);
+ Core::System::GetInstance()
+ .ArmInterface(static_cast<std::size_t>(GetCurrentThread()->GetProcessorID()))
+ .LogBacktrace();
ASSERT(false);
Core::CurrentProcess()->PrepareForTermination();
@@ -1224,10 +1227,10 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V
auto* const current_process = Core::CurrentProcess();
- if (processor_id == THREADPROCESSORID_DEFAULT) {
- // Set the target CPU to the one specified in the process' exheader.
- processor_id = current_process->GetDefaultProcessorID();
- ASSERT(processor_id != THREADPROCESSORID_DEFAULT);
+ if (processor_id == THREADPROCESSORID_IDEAL) {
+ // Set the target CPU to the one specified by the process.
+ processor_id = current_process->GetIdealCore();
+ ASSERT(processor_id != THREADPROCESSORID_IDEAL);
}
switch (processor_id) {
@@ -1636,13 +1639,13 @@ static ResultCode SetThreadCoreMask(Handle thread_handle, u32 core, u64 mask) {
return ERR_INVALID_HANDLE;
}
- if (core == static_cast<u32>(THREADPROCESSORID_DEFAULT)) {
- const u8 default_processor_id = thread->GetOwnerProcess()->GetDefaultProcessorID();
+ if (core == static_cast<u32>(THREADPROCESSORID_IDEAL)) {
+ const u8 ideal_cpu_core = thread->GetOwnerProcess()->GetIdealCore();
- ASSERT(default_processor_id != static_cast<u8>(THREADPROCESSORID_DEFAULT));
+ ASSERT(ideal_cpu_core != static_cast<u8>(THREADPROCESSORID_IDEAL));
- // Set the target CPU to the one specified in the process' exheader.
- core = default_processor_id;
+ // Set the target CPU to the ideal core specified by the process.
+ core = ideal_cpu_core;
mask = 1ULL << core;
}
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 434655638..d3984dfc4 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -12,7 +12,6 @@
#include "common/assert.h"
#include "common/common_types.h"
#include "common/logging/log.h"
-#include "common/math_util.h"
#include "common/thread_queue_list.h"
#include "core/arm/arm_interface.h"
#include "core/core.h"
@@ -232,29 +231,6 @@ void Thread::BoostPriority(u32 priority) {
current_priority = priority;
}
-SharedPtr<Thread> SetupMainThread(KernelCore& kernel, VAddr entry_point, u32 priority,
- Process& owner_process) {
- // Setup page table so we can write to memory
- SetCurrentPageTable(&owner_process.VMManager().page_table);
-
- // Initialize new "main" thread
- const VAddr stack_top = owner_process.VMManager().GetTLSIORegionEndAddress();
- auto thread_res = Thread::Create(kernel, "main", entry_point, priority, 0, THREADPROCESSORID_0,
- stack_top, owner_process);
-
- SharedPtr<Thread> thread = std::move(thread_res).Unwrap();
-
- // Register 1 must be a handle to the main thread
- const Handle guest_handle = owner_process.GetHandleTable().Create(thread).Unwrap();
- thread->SetGuestHandle(guest_handle);
- thread->GetContext().cpu_registers[1] = guest_handle;
-
- // Threads by default are dormant, wake up the main thread so it runs when the scheduler fires
- thread->ResumeFromWait();
-
- return thread;
-}
-
void Thread::SetWaitSynchronizationResult(ResultCode result) {
context.cpu_registers[0] = result.raw;
}
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index fe5398d56..c48b21aba 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -30,12 +30,12 @@ enum ThreadPriority : u32 {
};
enum ThreadProcessorId : s32 {
- THREADPROCESSORID_DEFAULT = -2, ///< Run thread on default core specified by exheader
- THREADPROCESSORID_0 = 0, ///< Run thread on core 0
- THREADPROCESSORID_1 = 1, ///< Run thread on core 1
- THREADPROCESSORID_2 = 2, ///< Run thread on core 2
- THREADPROCESSORID_3 = 3, ///< Run thread on core 3
- THREADPROCESSORID_MAX = 4, ///< Processor ID must be less than this
+ THREADPROCESSORID_IDEAL = -2, ///< Run thread on the ideal core specified by the process.
+ THREADPROCESSORID_0 = 0, ///< Run thread on core 0
+ THREADPROCESSORID_1 = 1, ///< Run thread on core 1
+ THREADPROCESSORID_2 = 2, ///< Run thread on core 2
+ THREADPROCESSORID_3 = 3, ///< Run thread on core 3
+ THREADPROCESSORID_MAX = 4, ///< Processor ID must be less than this
/// Allowed CPU mask
THREADPROCESSORID_DEFAULT_MASK = (1 << THREADPROCESSORID_0) | (1 << THREADPROCESSORID_1) |
@@ -456,17 +456,6 @@ private:
};
/**
- * Sets up the primary application thread
- * @param kernel The kernel instance to create the main thread under.
- * @param entry_point The address at which the thread should start execution
- * @param priority The priority to give the main thread
- * @param owner_process The parent process for the main thread
- * @return A shared pointer to the main thread
- */
-SharedPtr<Thread> SetupMainThread(KernelCore& kernel, VAddr entry_point, u32 priority,
- Process& owner_process);
-
-/**
* Gets the current thread
*/
Thread* GetCurrentThread();
diff --git a/src/core/hle/service/fatal/fatal.cpp b/src/core/hle/service/fatal/fatal.cpp
index 2f15ac2a6..770590d0b 100644
--- a/src/core/hle/service/fatal/fatal.cpp
+++ b/src/core/hle/service/fatal/fatal.cpp
@@ -111,7 +111,8 @@ static void GenerateErrorReport(ResultCode error_code, const FatalInfo& info) {
}
static void ThrowFatalError(ResultCode error_code, FatalType fatal_type, const FatalInfo& info) {
- LOG_ERROR(Service_Fatal, "Threw fatal error type {}", static_cast<u32>(fatal_type));
+ LOG_ERROR(Service_Fatal, "Threw fatal error type {} with error code 0x{:X}",
+ static_cast<u32>(fatal_type), error_code.raw);
switch (fatal_type) {
case FatalType::ErrorReportAndScreen:
GenerateErrorReport(error_code, info);
diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp
index 60b201d06..16564de24 100644
--- a/src/core/hle/service/time/time.cpp
+++ b/src/core/hle/service/time/time.cpp
@@ -264,14 +264,12 @@ void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called");
IPC::RequestParser rp{ctx};
- auto unknown_u8 = rp.PopRaw<u8>();
-
- ClockSnapshot clock_snapshot{};
+ const auto initial_type = rp.PopRaw<u8>();
const s64 time_since_epoch{std::chrono::duration_cast<std::chrono::seconds>(
std::chrono::system_clock::now().time_since_epoch())
.count()};
- CalendarTime calendar_time{};
+
const std::time_t time(time_since_epoch);
const std::tm* tm = std::localtime(&time);
if (tm == nullptr) {
@@ -280,16 +278,19 @@ void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) {
rb.Push(ResultCode(-1)); // TODO(ogniK): Find appropriate error code
return;
}
- SteadyClockTimePoint steady_clock_time_point{CoreTiming::cyclesToMs(CoreTiming::GetTicks()) /
- 1000};
- LocationName location_name{"UTC"};
+ const SteadyClockTimePoint steady_clock_time_point{
+ CoreTiming::cyclesToMs(CoreTiming::GetTicks()) / 1000, {}};
+
+ CalendarTime calendar_time{};
calendar_time.year = tm->tm_year + 1900;
calendar_time.month = tm->tm_mon + 1;
calendar_time.day = tm->tm_mday;
calendar_time.hour = tm->tm_hour;
calendar_time.minute = tm->tm_min;
calendar_time.second = tm->tm_sec;
+
+ ClockSnapshot clock_snapshot{};
clock_snapshot.system_posix_time = time_since_epoch;
clock_snapshot.network_posix_time = time_since_epoch;
clock_snapshot.system_calendar_time = calendar_time;
@@ -302,9 +303,10 @@ void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) {
clock_snapshot.network_calendar_info = additional_info;
clock_snapshot.steady_clock_timepoint = steady_clock_time_point;
- clock_snapshot.location_name = location_name;
+ clock_snapshot.location_name = LocationName{"UTC"};
clock_snapshot.clock_auto_adjustment_enabled = 1;
- clock_snapshot.ipc_u8 = unknown_u8;
+ clock_snapshot.type = initial_type;
+
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
ctx.WriteBuffer(&clock_snapshot, sizeof(ClockSnapshot));
diff --git a/src/core/hle/service/time/time.h b/src/core/hle/service/time/time.h
index ea43fbea7..f11affe95 100644
--- a/src/core/hle/service/time/time.h
+++ b/src/core/hle/service/time/time.h
@@ -22,7 +22,6 @@ struct CalendarTime {
u8 hour;
u8 minute;
u8 second;
- INSERT_PADDING_BYTES(1);
};
static_assert(sizeof(CalendarTime) == 0x8, "CalendarTime structure has incorrect size");
@@ -30,7 +29,7 @@ struct CalendarAdditionalInfo {
u32_le day_of_week;
u32_le day_of_year;
std::array<u8, 8> name;
- INSERT_PADDING_BYTES(1);
+ u8 is_dst;
s32_le utc_offset;
};
static_assert(sizeof(CalendarAdditionalInfo) == 0x18,
@@ -42,8 +41,10 @@ struct TimeZoneRule {
};
struct SteadyClockTimePoint {
+ using SourceID = std::array<u8, 16>;
+
u64_le value;
- INSERT_PADDING_WORDS(4);
+ SourceID source_id;
};
static_assert(sizeof(SteadyClockTimePoint) == 0x18, "SteadyClockTimePoint is incorrect size");
@@ -66,8 +67,9 @@ struct ClockSnapshot {
SteadyClockTimePoint steady_clock_timepoint;
LocationName location_name;
u8 clock_auto_adjustment_enabled;
- u8 ipc_u8;
- INSERT_PADDING_BYTES(2);
+ u8 type;
+ u8 version;
+ INSERT_PADDING_BYTES(1);
};
static_assert(sizeof(ClockSnapshot) == 0xd0, "ClockSnapshot is an invalid size");
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp
index 1adf6e330..df6eeb9a6 100644
--- a/src/yuzu/debugger/wait_tree.cpp
+++ b/src/yuzu/debugger/wait_tree.cpp
@@ -293,8 +293,8 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThread::GetChildren() const {
QString processor;
switch (thread.GetProcessorID()) {
- case Kernel::ThreadProcessorId::THREADPROCESSORID_DEFAULT:
- processor = tr("default");
+ case Kernel::ThreadProcessorId::THREADPROCESSORID_IDEAL:
+ processor = tr("ideal");
break;
case Kernel::ThreadProcessorId::THREADPROCESSORID_0:
case Kernel::ThreadProcessorId::THREADPROCESSORID_1: