summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbunnei <bunneidev@gmail.com>2015-02-23 07:23:15 +0100
committerbunnei <bunneidev@gmail.com>2015-02-23 07:23:15 +0100
commit50a0c4f14fc0c6df4db63a5593c6ff477736034c (patch)
tree3ec4860e931eb307faf6cdd06504a82baad95e00
parentMerge pull request #598 from Subv/dpt (diff)
parentAdded information reporting from ThrowFatalError (diff)
downloadyuzu-50a0c4f14fc0c6df4db63a5593c6ff477736034c.tar
yuzu-50a0c4f14fc0c6df4db63a5593c6ff477736034c.tar.gz
yuzu-50a0c4f14fc0c6df4db63a5593c6ff477736034c.tar.bz2
yuzu-50a0c4f14fc0c6df4db63a5593c6ff477736034c.tar.lz
yuzu-50a0c4f14fc0c6df4db63a5593c6ff477736034c.tar.xz
yuzu-50a0c4f14fc0c6df4db63a5593c6ff477736034c.tar.zst
yuzu-50a0c4f14fc0c6df4db63a5593c6ff477736034c.zip
-rw-r--r--src/common/common_funcs.h2
-rw-r--r--src/common/logging/backend.cpp1
-rw-r--r--src/common/logging/log.h1
-rw-r--r--src/core/hle/service/err_f.cpp165
4 files changed, 166 insertions, 3 deletions
diff --git a/src/common/common_funcs.h b/src/common/common_funcs.h
index bc296ed3e..d56156e4a 100644
--- a/src/common/common_funcs.h
+++ b/src/common/common_funcs.h
@@ -14,8 +14,6 @@
#define SLEEP(x) usleep(x*1000)
#endif
-template <bool> struct CompileTimeAssert;
-template<> struct CompileTimeAssert<true> {};
#define b2(x) ( (x) | ( (x) >> 1) )
#define b4(x) ( b2(x) | ( b2(x) >> 2) )
diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp
index 8fee20a83..7c1010b22 100644
--- a/src/common/logging/backend.cpp
+++ b/src/common/logging/backend.cpp
@@ -33,6 +33,7 @@ static std::shared_ptr<Logger> global_logger;
CLS(Service) \
SUB(Service, SRV) \
SUB(Service, FS) \
+ SUB(Service, ERR) \
SUB(Service, APT) \
SUB(Service, GSP) \
SUB(Service, AC) \
diff --git a/src/common/logging/log.h b/src/common/logging/log.h
index 6c5ca3968..7b67b3c07 100644
--- a/src/common/logging/log.h
+++ b/src/common/logging/log.h
@@ -53,6 +53,7 @@ enum class Class : ClassType {
/// should have its own subclass.
Service_SRV, ///< The SRV (Service Directory) implementation
Service_FS, ///< The FS (Filesystem) service implementation
+ Service_ERR, ///< The ERR (Error) port implementation
Service_APT, ///< The APT (Applets) service
Service_GSP, ///< The GSP (GPU control) service
Service_AC, ///< The AC (WiFi status) service
diff --git a/src/core/hle/service/err_f.cpp b/src/core/hle/service/err_f.cpp
index 8d765acb5..58c5acd1e 100644
--- a/src/core/hle/service/err_f.cpp
+++ b/src/core/hle/service/err_f.cpp
@@ -10,8 +10,171 @@
namespace ERR_F {
+enum {
+ ErrSpecifier0 = 0,
+ ErrSpecifier1 = 1,
+ ErrSpecifier3 = 3,
+ ErrSpecifier4 = 4,
+};
+
+// This is used instead of ResultCode from result.h
+// because we can't have non-trivial data members in unions.
+union RSL {
+ u32 raw;
+
+ BitField<0, 10, u32> description;
+ BitField<10, 8, u32> module;
+ BitField<21, 6, u32> summary;
+ BitField<27, 5, u32> level;
+};
+
+union ErrInfo {
+ u8 specifier;
+
+ struct {
+ u8 specifier; // 0x0
+ u8 rev_high; // 0x1
+ u16 rev_low; // 0x2
+ RSL result_code; // 0x4
+ u32 address; // 0x8
+ INSERT_PADDING_BYTES(4); // 0xC
+ u32 pid_low; // 0x10
+ u32 pid_high; // 0x14
+ u32 aid_low; // 0x18
+ u32 aid_high; // 0x1C
+ } errtype1;
+
+ struct {
+ u8 specifier; // 0x0
+ u8 rev_high; // 0x1
+ u16 rev_low; // 0x2
+ INSERT_PADDING_BYTES(0xC); // 0x4
+ u32 pid_low; // 0x10
+ u32 pid_high; // 0x14
+ u32 aid_low; // 0x18
+ u32 aid_high; // 0x1C
+ u8 error_type; // 0x20
+ INSERT_PADDING_BYTES(3); // 0x21
+ u32 fault_status_reg; // 0x24
+ u32 fault_addr; // 0x28
+ u32 fpexc; // 0x2C
+ u32 finst; // 0x30
+ u32 finst2; // 0x34
+ INSERT_PADDING_BYTES(0x34); // 0x38
+ u32 sp; // 0x6C
+ u32 pc; // 0x70
+ u32 lr; // 0x74
+ u32 cpsr; // 0x78
+ } errtype3;
+
+ struct {
+ u8 specifier; // 0x0
+ u8 rev_high; // 0x1
+ u16 rev_low; // 0x2
+ RSL result_code; // 0x4
+ INSERT_PADDING_BYTES(8); // 0x8
+ u32 pid_low; // 0x10
+ u32 pid_high; // 0x14
+ u32 aid_low; // 0x18
+ u32 aid_high; // 0x1C
+ char debug_string1[0x2E]; // 0x20
+ char debug_string2[0x2E]; // 0x4E
+ } errtype4;
+};
+
+enum {
+ PrefetchAbort = 0,
+ DataAbort = 1,
+ UndefInstr = 2,
+ VectorFP = 3
+};
+
+static std::string GetErrInfo3Type(u8 type_code) {
+ switch (type_code) {
+ case PrefetchAbort: return "Prefetch Abort";
+ case DataAbort: return "Data Abort";
+ case UndefInstr: return "Undefined Instruction";
+ case VectorFP: return "Vector Floating Point";
+ default: return "unknown";
+ }
+}
+
+static void ThrowFatalError(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ LOG_CRITICAL(Service_ERR, "Fatal error!");
+ const ErrInfo* errinfo = reinterpret_cast<ErrInfo*>(&cmd_buff[1]);
+
+ switch (errinfo->specifier) {
+ case ErrSpecifier0:
+ case ErrSpecifier1:
+ {
+ const auto& errtype = errinfo->errtype1;
+ LOG_CRITICAL(Service_ERR, "PID: 0x%08X_0x%08X", errtype.pid_low, errtype.pid_high);
+ LOG_CRITICAL(Service_ERR, "REV: %d", errtype.rev_low | (errtype.rev_high << 16));
+ LOG_CRITICAL(Service_ERR, "AID: 0x%08X_0x%08X", errtype.aid_low, errtype.aid_high);
+ LOG_CRITICAL(Service_ERR, "ADR: 0x%08X", errtype.address);
+
+ LOG_CRITICAL(Service_ERR, "RSL: 0x%08X", errtype.result_code.raw);
+ LOG_CRITICAL(Service_ERR, " Level: %u", errtype.result_code.level.Value());
+ LOG_CRITICAL(Service_ERR, " Summary: %u", errtype.result_code.summary.Value());
+ LOG_CRITICAL(Service_ERR, " Module: %u", errtype.result_code.module.Value());
+ LOG_CRITICAL(Service_ERR, " Desc: %u", errtype.result_code.description.Value());
+ break;
+ }
+
+ case ErrSpecifier3:
+ {
+ const auto& errtype = errinfo->errtype3;
+ LOG_CRITICAL(Service_ERR, "PID: 0x%08X_0x%08X", errtype.pid_low, errtype.pid_high);
+ LOG_CRITICAL(Service_ERR, "REV: %d", errtype.rev_low | (errtype.rev_high << 16));
+ LOG_CRITICAL(Service_ERR, "AID: 0x%08X_0x%08X", errtype.aid_low, errtype.aid_high);
+ LOG_CRITICAL(Service_ERR, "TYPE: %s", GetErrInfo3Type(errtype.error_type).c_str());
+
+ LOG_CRITICAL(Service_ERR, "PC: 0x%08X", errtype.pc);
+ LOG_CRITICAL(Service_ERR, "LR: 0x%08X", errtype.lr);
+ LOG_CRITICAL(Service_ERR, "SP: 0x%08X", errtype.sp);
+ LOG_CRITICAL(Service_ERR, "CPSR: 0x%08X", errtype.cpsr);
+
+ switch (errtype.error_type) {
+ case PrefetchAbort:
+ case DataAbort:
+ LOG_CRITICAL(Service_ERR, "Fault Address: 0x%08X", errtype.fault_addr);
+ LOG_CRITICAL(Service_ERR, "Fault Status Register: 0x%08X", errtype.fault_status_reg);
+ break;
+ case VectorFP:
+ LOG_CRITICAL(Service_ERR, "FPEXC: 0x%08X", errtype.fpexc);
+ LOG_CRITICAL(Service_ERR, "FINST: 0x%08X", errtype.finst);
+ LOG_CRITICAL(Service_ERR, "FINST2: 0x%08X", errtype.finst2);
+ break;
+ }
+ break;
+ }
+
+ case ErrSpecifier4:
+ {
+ const auto& errtype = errinfo->errtype4;
+ LOG_CRITICAL(Service_ERR, "PID: 0x%08X_0x%08X", errtype.pid_low, errtype.pid_high);
+ LOG_CRITICAL(Service_ERR, "REV: %d", errtype.rev_low | (errtype.rev_high << 16));
+ LOG_CRITICAL(Service_ERR, "AID: 0x%08X_0x%08X", errtype.aid_low, errtype.aid_high);
+
+ LOG_CRITICAL(Service_ERR, "RSL: 0x%08X", errtype.result_code.raw);
+ LOG_CRITICAL(Service_ERR, " Level: %u", errtype.result_code.level.Value());
+ LOG_CRITICAL(Service_ERR, " Summary: %u", errtype.result_code.summary.Value());
+ LOG_CRITICAL(Service_ERR, " Module: %u", errtype.result_code.module.Value());
+ LOG_CRITICAL(Service_ERR, " Desc: %u", errtype.result_code.description.Value());
+
+ LOG_CRITICAL(Service_ERR, "%s", errtype.debug_string1);
+ LOG_CRITICAL(Service_ERR, "%s", errtype.debug_string2);
+ break;
+ }
+ }
+
+ cmd_buff[1] = 0; // No error
+}
+
const Interface::FunctionInfo FunctionTable[] = {
- {0x00010800, nullptr, "ThrowFatalError"}
+ {0x00010800, ThrowFatalError, "ThrowFatalError"}
};
////////////////////////////////////////////////////////////////////////////////////////////////////