exceptions: add el3_call()

Signed-off-by: Nick Chan <towinchenmi@gmail.com>
This commit is contained in:
Nick Chan 2024-09-30 15:29:34 +08:00 committed by Hector Martin
parent 1fd17b8933
commit 9ca6d1c16f
9 changed files with 33 additions and 2 deletions

View file

@ -494,6 +494,7 @@ class M1N1Proxy(Reloadable):
P_PUT_SIMD_STATE = 0x00f
P_REBOOT = 0x010
P_SLEEP = 0x011
P_EL3_CALL = 0x012
P_WRITE64 = 0x100
P_WRITE32 = 0x101
@ -760,6 +761,10 @@ class M1N1Proxy(Reloadable):
self.request(self.P_REBOOT, no_reply=True)
def sleep(self, deep=False):
self.request(self.P_SLEEP, deep, no_reply=True)
def el3_call(self, addr, *args):
if len(args) > 4:
raise ValueError("Too many arguments")
return self.request(self.P_EL3_CALL, addr, *args)
def write64(self, addr, data):
'''write 8 byte value to given address'''

View file

@ -281,6 +281,10 @@ void exc_sync(u64 *regs)
// Monitor call
u32 imm = mrs(ESR_EL3) & 0xffff;
switch (imm) {
case 42:
regs[0] = ((uint64_t(*)(uint64_t, uint64_t, uint64_t, uint64_t))regs[0])(
regs[1], regs[2], regs[3], regs[4]);
return;
default:
printf("Unknown SMC: 0x%x\n", imm);
break;

View file

@ -49,6 +49,7 @@ void print_regs(u64 *regs, int el12);
uint64_t el0_call(void *func, uint64_t a, uint64_t b, uint64_t c, uint64_t d);
uint64_t el1_call(void *func, uint64_t a, uint64_t b, uint64_t c, uint64_t d);
uint64_t el3_call(void *func, uint64_t a, uint64_t b, uint64_t c, uint64_t d);
#endif

View file

@ -242,3 +242,9 @@ _el1_vectors_start:
hvc 0x1e
.align 7
hvc 0x1f
.globl el3_call
.type el3_call, @function
el3_call:
smc 42
ret

View file

@ -116,6 +116,9 @@ int proxy_process(ProxyRequest *request, ProxyReply *reply)
case P_SLEEP:
cpu_sleep(request->args[0]);
break;
case P_EL3_CALL:
reply->retval = el3_call((void *)request->args[0], request->args[1], request->args[2],
request->args[3], request->args[4]);
case P_WRITE64:
exc_guard = GUARD_SKIP;

View file

@ -24,6 +24,7 @@ typedef enum {
P_PUT_SIMD_STATE,
P_REBOOT,
P_SLEEP,
P_EL3_CALL,
P_WRITE64 = 0x100, // Generic register functions
P_WRITE32,

View file

@ -107,6 +107,12 @@ void smp_secondary_entry(void)
}
}
void smp_secondary_prep_el3(void)
{
msr(TPIDR_EL3, target_cpu);
return;
}
static void smp_start_cpu(int index, int die, int cluster, int core, u64 impl, u64 cpu_start_base)
{
int i;

View file

@ -14,6 +14,7 @@ extern u8 *secondary_stacks[MAX_CPUS];
extern u8 *secondary_stacks_el3[MAX_EL3_CPUS];
void smp_secondary_entry(void);
void smp_secondary_prep_el3(void);
void smp_start_secondaries(void);
void smp_stop_secondaries(bool deep_sleep);
@ -35,7 +36,9 @@ void smp_send_ipi(int cpu);
static inline int smp_id(void)
{
if (in_el2())
if (in_el3())
return mrs(TPIDR_EL3);
else if (in_el2())
return mrs(TPIDR_EL2);
else
return mrs(TPIDR_EL1);

View file

@ -193,8 +193,10 @@ void _cpu_reset_c(void *stack)
exception_initialize();
if (in_el3())
if (in_el3()) {
smp_secondary_prep_el3();
return;
}
if (!is_boot_cpu())
smp_secondary_entry();