mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-23 04:41:12 +00:00
thermosphere: add shadow page table hooks
note: HCR.TVM not supported by qemu yet
This commit is contained in:
parent
045f556f80
commit
e6c5eb3928
5 changed files with 82 additions and 5 deletions
|
@ -18,4 +18,15 @@
|
||||||
|
|
||||||
#include "../../types.h"
|
#include "../../types.h"
|
||||||
|
|
||||||
|
static inline u64 transformKernelAddress(u64 pa)
|
||||||
|
{
|
||||||
|
switch (pa) {
|
||||||
|
// GICv2 CPU -> vCPU interface
|
||||||
|
case 0x08010000:
|
||||||
|
return 0x08040000;
|
||||||
|
default:
|
||||||
|
return pa;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uintptr_t configureMemoryMap(u32 *addrSpaceSize);
|
uintptr_t configureMemoryMap(u32 *addrSpaceSize);
|
||||||
|
|
|
@ -18,4 +18,15 @@
|
||||||
|
|
||||||
#include "../../types.h"
|
#include "../../types.h"
|
||||||
|
|
||||||
|
static inline u64 transformKernelAddress(u64 pa)
|
||||||
|
{
|
||||||
|
switch (pa) {
|
||||||
|
// GICv2 CPU -> vCPU interface
|
||||||
|
case 0x50042000:
|
||||||
|
return 0x50046000;
|
||||||
|
default:
|
||||||
|
return pa;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uintptr_t configureMemoryMap(u32 *addrSpaceSize);
|
uintptr_t configureMemoryMap(u32 *addrSpaceSize);
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
|
|
||||||
|
|
||||||
#include "shadow_page_tables.h"
|
#include "shadow_page_tables.h"
|
||||||
|
#include "platform/memory_map_mmu_cfg.h"
|
||||||
|
#include "debug_log.h"
|
||||||
|
|
||||||
#ifdef A32_SUPPORTED
|
#ifdef A32_SUPPORTED
|
||||||
static void replacePageTableShortL2(u32 *ttbl)
|
static void replacePageTableShortL2(u32 *ttbl)
|
||||||
|
@ -91,9 +93,11 @@ static void replacePageTableLongImpl(u64 *ttbl, u32 level, u32 nbits)
|
||||||
replacePageTableLongImpl((u64 *)addr, level + 1, 9);
|
replacePageTableLongImpl((u64 *)addr, level + 1, 9);
|
||||||
} else {
|
} else {
|
||||||
u64 pa = ttbl[i] & MASK2L(47, 12);
|
u64 pa = ttbl[i] & MASK2L(47, 12);
|
||||||
// FIXME
|
u64 newPa = transformKernelAddress(pa);
|
||||||
if (pa == 0x50042000ull) {
|
if (pa != newPa) {
|
||||||
ttbl[i] = (ttbl[i] & ~MASK2L(47, 12)) | 0x50046000ull;
|
// Note: unreachable on QEMU yet
|
||||||
|
DEBUG("EL1 in-place page-table entry swap: 0x%08llx => 0x%08llx\n", pa, newPa);
|
||||||
|
ttbl[i] = (ttbl[i] & ~MASK2L(47, 12)) | newPa;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,6 +105,7 @@ static void replacePageTableLongImpl(u64 *ttbl, u32 level, u32 nbits)
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
__builtin_unreachable();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -126,3 +131,8 @@ void replacePageTableLong(u64 *ttbl, u32 txsz)
|
||||||
replacePageTableLongImpl(ttbl, 3, startBit - 11);
|
replacePageTableLongImpl(ttbl, 3, startBit - 11);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void replaceKernelPageTables(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
|
@ -18,6 +18,8 @@
|
||||||
#include "synchronization.h"
|
#include "synchronization.h"
|
||||||
#include "sysreg.h"
|
#include "sysreg.h"
|
||||||
#include "arm.h"
|
#include "arm.h"
|
||||||
|
#include "debug_log.h"
|
||||||
|
#include "shadow_page_tables.h"
|
||||||
|
|
||||||
static void doSystemRegisterRwImpl(u64 *val, u32 iss)
|
static void doSystemRegisterRwImpl(u64 *val, u32 iss)
|
||||||
{
|
{
|
||||||
|
@ -86,6 +88,49 @@ void doSystemRegisterWrite(ExceptionStackFrame *frame, u32 iss, u32 reg1, u32 re
|
||||||
val = frame->x[reg1];
|
val = frame->x[reg1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hooks go here:
|
||||||
|
switch (iss) {
|
||||||
|
case ENCODE_SYSREG_ISS(SCTLR_EL1): {
|
||||||
|
DEBUG("Hooked sysreg write: SCTLR_EL1 = %0x016llx\n", val);
|
||||||
|
// Possible MMU (re)-enablement
|
||||||
|
if (val & 1) {
|
||||||
|
u64 tcr = GET_SYSREG(tcr_el1);
|
||||||
|
if (((tcr >> 14) & 3) == 0) {
|
||||||
|
// 4KB granule
|
||||||
|
replacePageTableLong((u64 *)(GET_SYSREG(ttbr0_el1) & MASK2L(47, 1)), (u32)(tcr & 0x3F));
|
||||||
|
replacePageTableLong((u64 *)(GET_SYSREG(ttbr1_el1) & MASK2L(47, 1)), (u32)((tcr >> 16) & 0x3F));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ENCODE_SYSREG_ISS(TTBR1_EL1): {
|
||||||
|
DEBUG("Hooked sysreg write: TTBR1_EL1 = %0x016llx\n", val);
|
||||||
|
u64 tcr = GET_SYSREG(tcr_el1);
|
||||||
|
// MMU enabled & 4KB granule
|
||||||
|
if ((GET_SYSREG(sctlr_el1) & 1) && ((tcr >> 14) & 3) == 0) {
|
||||||
|
// Note: lack of ttbr0 intentional here
|
||||||
|
replacePageTableLong((u64 *)(val & MASK2L(47, 1)), (u32)((tcr >> 16) & 0x3F));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ENCODE_SYSREG_ISS(TCR_EL1): {
|
||||||
|
DEBUG("Hooked sysreg write: TCR_EL1 = %0x016llx\n", val);
|
||||||
|
u64 tcr = val;
|
||||||
|
// MMU enabled & 4KB granule
|
||||||
|
if ((GET_SYSREG(sctlr_el1) & 1) && ((tcr >> 14) & 3) == 0) {
|
||||||
|
// Note: lack of ttbr0 intentional here
|
||||||
|
replacePageTableLong((u64 *)(GET_SYSREG(ttbr1_el1) & MASK2L(47, 1)), (u32)((tcr >> 16) & 0x3F));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Note: TTBR0_EL1 deliberately not hooked
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
doSystemRegisterRwImpl(&val, iss);
|
doSystemRegisterRwImpl(&val, iss);
|
||||||
skipFaultingInstruction(frame, 4);
|
skipFaultingInstruction(frame, 4);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,8 +36,8 @@ void enableTraps(void)
|
||||||
u64 hcr = GET_SYSREG(hcr_el2);
|
u64 hcr = GET_SYSREG(hcr_el2);
|
||||||
|
|
||||||
// Trap *writes* to memory control registers
|
// Trap *writes* to memory control registers
|
||||||
//hcr |= HCR_TVM;
|
// Note: QEMU doesn't support this bit as of August 2019...
|
||||||
// actually don't
|
hcr |= HCR_TVM;
|
||||||
|
|
||||||
// Trap SMC instructions
|
// Trap SMC instructions
|
||||||
hcr |= HCR_TSC;
|
hcr |= HCR_TSC;
|
||||||
|
|
Loading…
Reference in a new issue