#include <gic.h>
#include <rt/arch/sysreg.h>
#include <rt/abort.h>
#include <rt/context.h>
#include <rt/cycle.h>
#include <rt/idle.h>
#include <rt/interrupt.h>
#include <rt/mpu.h>
#include <rt/syscall.h>
#include <rt/task.h>
#include <rt/tls.h>
#include <rt/trap.h>
#include <stddef.h>
#include <stdint.h>
struct context
{
uint64_t cpacr, has_volatile;
uint64_t x19, x20, x21, x22, x23, x24, x25, x26, x27, x28;
uint64_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14,
x15, x16, x17, x18, padding1;
uint64_t fp, lr, pc, psr;
};
#define SPSR_EL1T 0x04
void *rt_context_init(uintptr_t fn, uintptr_t arg, void *stack,
size_t stack_size)
{
void *const sp = (char *)stack + stack_size;
struct context *ctx = sp;
--ctx;
ctx->cpacr = 0;
ctx->has_volatile = 1;
ctx->x0 = arg;
ctx->x1 = fn;
ctx->fp = 0;
ctx->lr = 0;
ctx->pc = (uint64_t)rt_task_entry;
ctx->psr = SPSR_EL1T;
return ctx;
}
__attribute__((noreturn, weak)) void rt_idle(void)
{
rt_task_drop_privilege();
for (;;)
{
__asm__("wfi" :::);
}
}
__attribute__((noreturn, weak)) void rt_abort(void)
{
for (;;)
{
__asm__("udf 0" :::);
}
}
__attribute__((noreturn, weak)) void rt_trap(void)
{
for (;;)
{
__asm__("brk 0" :::);
}
}
#define SYSCALL_CLOBBERS \
"x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", \
"x15", "x16", "x17", "x18", "x29", "x30"
void rt_syscall_0(enum rt_syscall syscall)
{
register enum rt_syscall x0 __asm__("x0") = syscall;
__asm__ __volatile__("svc 0"
: "+r"(x0)
:
: "x1", "x2", "x3", SYSCALL_CLOBBERS, "memory");
}
void rt_syscall_1(enum rt_syscall syscall, uintptr_t arg0)
{
register enum rt_syscall x0 __asm__("x0") = syscall;
register uintptr_t x1 __asm__("x1") = arg0;
__asm__ __volatile__("svc 0"
: "+r"(x0), "+r"(x1)
:
: "x2", "x3", SYSCALL_CLOBBERS, "memory");
}
void rt_syscall_2(enum rt_syscall syscall, uintptr_t arg0, uintptr_t arg1)
{
register enum rt_syscall x0 __asm__("x0") = syscall;
register uintptr_t x1 __asm__("x1") = arg0;
register uintptr_t x2 __asm__("x2") = arg1;
__asm__ __volatile__("svc 0"
: "+r"(x0), "+r"(x1), "+r"(x2)
:
: "x3", SYSCALL_CLOBBERS, "memory");
}
void rt_syscall_3(enum rt_syscall syscall, uintptr_t arg0, uintptr_t arg1,
uintptr_t arg2)
{
register enum rt_syscall x0 __asm__("x0") = syscall;
register uintptr_t x1 __asm__("x1") = arg0;
register uintptr_t x2 __asm__("x2") = arg1;
register uintptr_t x3 __asm__("x3") = arg2;
__asm__ __volatile__("svc 0"
: "+r"(x0), "+r"(x1), "+r"(x2), "+r"(x3)
:
: SYSCALL_CLOBBERS, "memory");
}
void rt_syscall_pend(void)
{
gic_syscall_pend();
}
bool rt_interrupt_is_active(void)
{
return tpidrro_el0() != 0;
}
void rt_task_drop_privilege(void)
{
uintptr_t elr;
__asm__ __volatile__("dsb sy;"
"adr %[elr], 0f;"
"msr spsr_el1, xzr;"
"msr elr_el1, %[elr];"
"eret;"
"0:;"
: [elr] "=&r"(elr)
:
: "memory", "cc");
}
__attribute__((weak)) void rt_cycle_init(void)
{
#if RT_CYCLE_ENABLE
pmcr_el0_set(PMCR_EL0_E | PMCR_EL0_C);
pmcntenset_el0_set(PMCNTENSET_EL0_C);
pmuserenr_el0_set(PMUSERENR_EL0_EN);
__asm__("isb" :::);
#endif
}
__attribute__((weak)) uint32_t rt_cycle(void)
{
#if RT_CYCLE_ENABLE
return (uint32_t)pmccntr_el0();
#else
return 0;
#endif
}
void rt_tls_set(void *tls)
{
tpidr_el0_set((uintptr_t)tls);
}