mirror of
https://github.com/AsahiLinux/m1n1
synced 2024-12-04 03:49:10 +00:00
8752d5fbba
Signed-off-by: Hector Martin <marcan@marcan.st>
99 lines
2.7 KiB
C
99 lines
2.7 KiB
C
/* SPDX-License-Identifier: MIT */
|
|
|
|
#include "cpu_regs.h"
|
|
#include "exception.h"
|
|
#include "gxf.h"
|
|
#include "memory.h"
|
|
#include "smp.h"
|
|
#include "uart.h"
|
|
#include "utils.h"
|
|
|
|
uint64_t gxf_enter(void *func, uint64_t a, uint64_t b, uint64_t c, uint64_t d);
|
|
|
|
u8 gl1_stack[MAX_CPUS][GL_STACK_SIZE] ALIGNED(0x4000);
|
|
u8 gl2_stack[MAX_CPUS][GL_STACK_SIZE] ALIGNED(0x4000);
|
|
|
|
bool gxf_enabled(void)
|
|
{
|
|
if (!(mrs(SYS_IMP_APL_SPRR_CONFIG_EL1) & SPRR_CONFIG_EN))
|
|
return false;
|
|
|
|
return (mrs(SYS_IMP_APL_GXF_CONFIG_EL1) & GXF_CONFIG_EN);
|
|
}
|
|
|
|
bool in_gl12(void)
|
|
{
|
|
if (!gxf_enabled())
|
|
return false;
|
|
|
|
return (mrs(SYS_IMP_APL_GXF_STATUS_EL1) & GXF_STATUS_GUARDED);
|
|
}
|
|
|
|
static uint64_t gl_call(void *func, uint64_t a, uint64_t b, uint64_t c, uint64_t d)
|
|
{
|
|
// disable the MMU first since enabling SPRR will change the meaning of all
|
|
// pagetable permission bits and also prevent us from having rwx pages
|
|
u64 sprr_state = mrs(SYS_IMP_APL_SPRR_CONFIG_EL1);
|
|
if (!(sprr_state & SPRR_CONFIG_EN))
|
|
reg_set_sync(SYS_IMP_APL_SPRR_CONFIG_EL1, sprr_state | SPRR_CONFIG_EN);
|
|
|
|
u64 gxf_state = mrs(SYS_IMP_APL_GXF_CONFIG_EL1);
|
|
if (!(gxf_state & GXF_CONFIG_EN))
|
|
reg_set_sync(SYS_IMP_APL_GXF_CONFIG_EL1, gxf_state | GXF_CONFIG_EN);
|
|
|
|
uint64_t ret = gxf_enter(func, a, b, c, d);
|
|
|
|
if (!(gxf_state & GXF_CONFIG_EN))
|
|
msr_sync(SYS_IMP_APL_GXF_CONFIG_EL1, gxf_state);
|
|
if (!(sprr_state & SPRR_CONFIG_EN))
|
|
msr_sync(SYS_IMP_APL_SPRR_CONFIG_EL1, sprr_state);
|
|
|
|
return ret;
|
|
}
|
|
|
|
uint64_t gl2_call(void *func, uint64_t a, uint64_t b, uint64_t c, uint64_t d)
|
|
{
|
|
if (mrs(CurrentEL) != 0x8)
|
|
return -1;
|
|
return gl_call(func, a, b, c, d);
|
|
}
|
|
|
|
struct gl_call_argv {
|
|
void *func;
|
|
uint64_t a, b, c, d;
|
|
};
|
|
|
|
static uint64_t gl_call_wrapper(struct gl_call_argv *args)
|
|
{
|
|
return gl_call(args->func, args->a, args->b, args->c, args->d);
|
|
}
|
|
|
|
uint64_t gl1_call(void *func, uint64_t a, uint64_t b, uint64_t c, uint64_t d)
|
|
{
|
|
if (mrs(CurrentEL) == 0x4)
|
|
return gl_call(func, a, b, c, d);
|
|
|
|
struct gl_call_argv args;
|
|
args.func = func;
|
|
args.a = a;
|
|
args.b = b;
|
|
args.c = c;
|
|
args.d = d;
|
|
|
|
// enable EL1 here since once GXF has been enabled HCR_EL2 writes are only possible from GL2
|
|
if (mrs(HCR_EL2) & HCR_TGE)
|
|
reg_clr(HCR_EL2, HCR_TGE);
|
|
|
|
u64 sprr_state = mrs(SYS_IMP_APL_SPRR_CONFIG_EL1) & SPRR_CONFIG_EN;
|
|
reg_set_sync(SYS_IMP_APL_SPRR_CONFIG_EL1, SPRR_CONFIG_EN);
|
|
|
|
u64 gxf_state = mrs(SYS_IMP_APL_GXF_CONFIG_EL1) & GXF_CONFIG_EN;
|
|
reg_set_sync(SYS_IMP_APL_GXF_CONFIG_EL1, GXF_CONFIG_EN);
|
|
|
|
uint64_t ret = el1_call(gl_call_wrapper, (uint64_t)&args, 0, 0, 0);
|
|
|
|
msr_sync(SYS_IMP_APL_GXF_CONFIG_EL1, gxf_state);
|
|
msr_sync(SYS_IMP_APL_SPRR_CONFIG_EL1, sprr_state);
|
|
|
|
return ret;
|
|
}
|