aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Ryujinx.Cpu/LightningJit/Arm64/InstName.cs1
-rw-r--r--src/Ryujinx.Cpu/LightningJit/Arm64/SysUtils.cs48
-rw-r--r--src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/Decoder.cs7
-rw-r--r--src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstEmitMemory.cs8
-rw-r--r--src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstEmitSystem.cs15
5 files changed, 74 insertions, 5 deletions
diff --git a/src/Ryujinx.Cpu/LightningJit/Arm64/InstName.cs b/src/Ryujinx.Cpu/LightningJit/Arm64/InstName.cs
index 58d78ae6..36564064 100644
--- a/src/Ryujinx.Cpu/LightningJit/Arm64/InstName.cs
+++ b/src/Ryujinx.Cpu/LightningJit/Arm64/InstName.cs
@@ -1106,6 +1106,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64
case InstName.Mrs:
case InstName.MsrImm:
case InstName.MsrReg:
+ case InstName.Sysl:
return true;
}
diff --git a/src/Ryujinx.Cpu/LightningJit/Arm64/SysUtils.cs b/src/Ryujinx.Cpu/LightningJit/Arm64/SysUtils.cs
new file mode 100644
index 00000000..69689a39
--- /dev/null
+++ b/src/Ryujinx.Cpu/LightningJit/Arm64/SysUtils.cs
@@ -0,0 +1,48 @@
+using System.Diagnostics;
+
+namespace Ryujinx.Cpu.LightningJit.Arm64
+{
+ static class SysUtils
+ {
+ public static (uint, uint, uint, uint) UnpackOp1CRnCRmOp2(uint encoding)
+ {
+ uint op1 = (encoding >> 16) & 7;
+ uint crn = (encoding >> 12) & 0xf;
+ uint crm = (encoding >> 8) & 0xf;
+ uint op2 = (encoding >> 5) & 7;
+
+ return (op1, crn, crm, op2);
+ }
+
+ public static bool IsCacheInstEl0(uint encoding)
+ {
+ (uint op1, uint crn, uint crm, uint op2) = UnpackOp1CRnCRmOp2(encoding);
+
+ return ((op1 << 11) | (crn << 7) | (crm << 3) | op2) switch
+ {
+ 0b011_0111_0100_001 => true, // DC ZVA
+ 0b011_0111_1010_001 => true, // DC CVAC
+ 0b011_0111_1100_001 => true, // DC CVAP
+ 0b011_0111_1011_001 => true, // DC CVAU
+ 0b011_0111_1110_001 => true, // DC CIVAC
+ 0b011_0111_0101_001 => true, // IC IVAU
+ _ => false,
+ };
+ }
+
+ public static bool IsCacheInstUciTrapped(uint encoding)
+ {
+ (uint op1, uint crn, uint crm, uint op2) = UnpackOp1CRnCRmOp2(encoding);
+
+ return ((op1 << 11) | (crn << 7) | (crm << 3) | op2) switch
+ {
+ 0b011_0111_1010_001 => true, // DC CVAC
+ 0b011_0111_1100_001 => true, // DC CVAP
+ 0b011_0111_1011_001 => true, // DC CVAU
+ 0b011_0111_1110_001 => true, // DC CIVAC
+ 0b011_0111_0101_001 => true, // IC IVAU
+ _ => false,
+ };
+ }
+ }
+}
diff --git a/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/Decoder.cs b/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/Decoder.cs
index e9ba8ba2..00a1758f 100644
--- a/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/Decoder.cs
+++ b/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/Decoder.cs
@@ -257,7 +257,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
(name, flags, AddressForm addressForm) = InstTable.GetInstNameAndFlags(encoding, cpuPreset.Version, cpuPreset.Features);
- if (name.IsPrivileged())
+ if (name.IsPrivileged() || (name == InstName.Sys && IsPrivilegedSys(encoding)))
{
name = InstName.UdfPermUndef;
flags = InstFlags.None;
@@ -341,6 +341,11 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
return new(startAddress, address, insts, !isTruncated && !name.IsException(), isTruncated, isLoopEnd);
}
+ private static bool IsPrivilegedSys(uint encoding)
+ {
+ return !SysUtils.IsCacheInstEl0(encoding);
+ }
+
private static bool IsMrsNzcv(uint encoding)
{
return (encoding & ~0x1fu) == 0xd53b4200u;
diff --git a/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstEmitMemory.cs b/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstEmitMemory.cs
index ece1520f..e03d9373 100644
--- a/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstEmitMemory.cs
+++ b/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstEmitMemory.cs
@@ -13,6 +13,14 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
public static void RewriteSysInstruction(int asBits, MemoryManagerType mmType, CodeWriter writer, RegisterAllocator regAlloc, uint encoding)
{
+ // TODO: Handle IC instruction, it should invalidate the JIT cache.
+
+ if (InstEmitSystem.IsCacheInstForbidden(encoding))
+ {
+ // Current OS does not allow cache maintenance instructions from user mode, just do nothing.
+ return;
+ }
+
int rtIndex = RegisterUtils.ExtractRt(encoding);
if (rtIndex == RegisterUtils.ZrIndex)
{
diff --git a/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstEmitSystem.cs b/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstEmitSystem.cs
index 3d4204fc..82cb29d7 100644
--- a/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstEmitSystem.cs
+++ b/src/Ryujinx.Cpu/LightningJit/Arm64/Target/Arm64/InstEmitSystem.cs
@@ -69,7 +69,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
asm.LdrRiUn(Register((int)rd), Register(regAlloc.FixedContextRegister), NativeContextOffsets.TpidrEl0Offset);
}
}
- else if ((encoding & ~0x1f) == 0xd53b0020 && IsAppleOS()) // mrs x0, ctr_el0
+ else if ((encoding & ~0x1f) == 0xd53b0020 && IsCtrEl0AccessForbidden()) // mrs x0, ctr_el0
{
uint rd = encoding & 0x1f;
@@ -115,7 +115,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
{
return true;
}
- else if ((encoding & ~0x1f) == 0xd53b0020 && IsAppleOS()) // mrs x0, ctr_el0
+ else if ((encoding & ~0x1f) == 0xd53b0020 && IsCtrEl0AccessForbidden()) // mrs x0, ctr_el0
{
return true;
}
@@ -127,9 +127,16 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
return false;
}
- private static bool IsAppleOS()
+ private static bool IsCtrEl0AccessForbidden()
{
- return OperatingSystem.IsMacOS() || OperatingSystem.IsIOS();
+ // Only Linux allows accessing CTR_EL0 from user mode.
+ return OperatingSystem.IsWindows() || OperatingSystem.IsMacOS() || OperatingSystem.IsIOS();
+ }
+
+ public static bool IsCacheInstForbidden(uint encoding)
+ {
+ // Windows does not allow the cache maintenance instructions to be used from user mode.
+ return OperatingSystem.IsWindows() && SysUtils.IsCacheInstUciTrapped(encoding);
}
public static bool NeedsContextStoreLoad(InstName name)