smc_cap: Add badge handling to smc cap
Signed-off-by: Alex Pavey <Alex.Pavey@dornerworks.com>
This commit is contained in:
parent
e62bc9bba3
commit
7d029e56e2
4 changed files with 76 additions and 44 deletions
|
|
@ -128,7 +128,7 @@ block cb_cap {
|
|||
|
||||
#ifdef CONFIG_ALLOW_SMC_CALLS
|
||||
block smc_cap {
|
||||
padding 64
|
||||
field capSMCBadge 64
|
||||
|
||||
field capType 5
|
||||
padding 59
|
||||
|
|
|
|||
|
|
@ -100,7 +100,19 @@ deriveCap_ret_t Arch_deriveCap(cte_t *slot, cap_t cap)
|
|||
|
||||
cap_t CONST Arch_updateCapData(bool_t preserve, word_t data, cap_t cap)
|
||||
{
|
||||
return cap;
|
||||
#ifdef CONFIG_ALLOW_SMC_CALLS
|
||||
if (cap_get_capType(cap) == cap_smc_cap) {
|
||||
if (!preserve && cap_smc_cap_get_capSMCBadge(cap) == 0) {
|
||||
return cap_smc_cap_set_capSMCBadge(cap, data);
|
||||
} else {
|
||||
return cap_null_cap_new();
|
||||
}
|
||||
} else {
|
||||
#endif
|
||||
return cap;
|
||||
#ifdef CONFIG_ALLOW_SMC_CALLS
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
cap_t CONST Arch_maskCapRights(seL4_CapRights_t cap_rights_mask, cap_t cap)
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ BOOT_CODE static void init_smmu(cap_t root_cnode_cap)
|
|||
BOOT_CODE static void init_smc(cap_t root_cnode_cap)
|
||||
{
|
||||
/* Provide the SMC cap*/
|
||||
write_slot(SLOT_PTR(pptr_of_cap(root_cnode_cap), seL4_CapSMC), cap_smc_cap_new());
|
||||
write_slot(SLOT_PTR(pptr_of_cap(root_cnode_cap), seL4_CapSMC), cap_smc_cap_new(0));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -8,56 +8,76 @@
|
|||
#ifdef CONFIG_ALLOW_SMC_CALLS
|
||||
#include <arch/object/smc.h>
|
||||
|
||||
exception_t decodeARMSMCInvocation(word_t label, unsigned int length, cptr_t cptr,
|
||||
cte_t *srcSlot, cap_t cap, bool_t call, word_t *buffer)
|
||||
static exception_t performSMCCall(word_t *buffer)
|
||||
{
|
||||
word_t i;
|
||||
seL4_Word arg[NUM_SMC_REGS];
|
||||
word_t *ipcBuffer;
|
||||
|
||||
for (i = 0; i < NUM_SMC_REGS; i++) {
|
||||
arg[i] = getSyscallArg(i, buffer);
|
||||
}
|
||||
|
||||
ipcBuffer = lookupIPCBuffer(true, NODE_STATE(ksCurThread));
|
||||
|
||||
register seL4_Word r0 asm("x0") = arg[0];
|
||||
register seL4_Word r1 asm("x1") = arg[1];
|
||||
register seL4_Word r2 asm("x2") = arg[2];
|
||||
register seL4_Word r3 asm("x3") = arg[3];
|
||||
register seL4_Word r4 asm("x4") = arg[4];
|
||||
register seL4_Word r5 asm("x5") = arg[5];
|
||||
register seL4_Word r6 asm("x6") = arg[6];
|
||||
register seL4_Word r7 asm("x7") = arg[7];
|
||||
asm volatile("smc #0\n"
|
||||
: "+r"(r0), "+r"(r1), "+r"(r2), "+r"(r3),
|
||||
"+r"(r4), "+r"(r5), "+r"(r6), "+r"(r7)
|
||||
:: "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "memory");
|
||||
|
||||
arg[0] = r0;
|
||||
arg[1] = r1;
|
||||
arg[2] = r2;
|
||||
arg[3] = r3;
|
||||
arg[4] = r4;
|
||||
arg[5] = r5;
|
||||
arg[6] = r6;
|
||||
arg[7] = r7;
|
||||
|
||||
for (i = 0; i < n_msgRegisters; i++) {
|
||||
setRegister(NODE_STATE(ksCurThread), msgRegisters[i], arg[i]);
|
||||
}
|
||||
|
||||
if (ipcBuffer != NULL && i < NUM_SMC_REGS) {
|
||||
for (; i < NUM_SMC_REGS; i++) {
|
||||
ipcBuffer[i + 1] = arg[i];
|
||||
}
|
||||
}
|
||||
setRegister(NODE_STATE(ksCurThread), msgInfoRegister, wordFromMessageInfo(
|
||||
seL4_MessageInfo_new(0, 0, 0, i)));
|
||||
|
||||
return EXCEPTION_NONE;
|
||||
}
|
||||
|
||||
exception_t decodeARMSMCInvocation(word_t label, unsigned int length, cptr_t cptr,
|
||||
cte_t *srcSlot, cap_t cap, bool_t call, word_t *buffer)
|
||||
{
|
||||
word_t badge;
|
||||
word_t smc_func_id;
|
||||
|
||||
switch (label) {
|
||||
case ARMSMCCall:
|
||||
for (i = 0; i < NUM_SMC_REGS; i++) {
|
||||
arg[i] = getSyscallArg(i, buffer);
|
||||
badge = cap_smc_cap_get_capSMCBadge(cap);
|
||||
smc_func_id = getSyscallArg(0, buffer);
|
||||
|
||||
if (badge == smc_func_id) {
|
||||
performSMCCall(buffer);
|
||||
} else if (badge == 0) {
|
||||
performSMCCall(buffer);
|
||||
} else {
|
||||
userError("ARMSMCInvocation: Illegal operation.");
|
||||
current_syscall_error.type = seL4_IllegalOperation;
|
||||
return EXCEPTION_SYSCALL_ERROR;
|
||||
}
|
||||
|
||||
ipcBuffer = lookupIPCBuffer(true, NODE_STATE(ksCurThread));
|
||||
|
||||
register seL4_Word r0 asm("x0") = arg[0];
|
||||
register seL4_Word r1 asm("x1") = arg[1];
|
||||
register seL4_Word r2 asm("x2") = arg[2];
|
||||
register seL4_Word r3 asm("x3") = arg[3];
|
||||
register seL4_Word r4 asm("x4") = arg[4];
|
||||
register seL4_Word r5 asm("x5") = arg[5];
|
||||
register seL4_Word r6 asm("x6") = arg[6];
|
||||
register seL4_Word r7 asm("x7") = arg[7];
|
||||
asm volatile("smc #0\n"
|
||||
: "+r"(r0), "+r"(r1), "+r"(r2), "+r"(r3),
|
||||
"+r"(r4), "+r"(r5), "+r"(r6), "+r"(r7)
|
||||
:: "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "memory");
|
||||
|
||||
arg[0] = r0;
|
||||
arg[1] = r1;
|
||||
arg[2] = r2;
|
||||
arg[3] = r3;
|
||||
arg[4] = r4;
|
||||
arg[5] = r5;
|
||||
arg[6] = r6;
|
||||
arg[7] = r7;
|
||||
|
||||
for (i = 0; i < n_msgRegisters; i++) {
|
||||
setRegister(NODE_STATE(ksCurThread), msgRegisters[i], arg[i]);
|
||||
}
|
||||
|
||||
if (ipcBuffer != NULL && i < NUM_SMC_REGS) {
|
||||
for (; i < NUM_SMC_REGS; i++) {
|
||||
ipcBuffer[i + 1] = arg[i];
|
||||
}
|
||||
}
|
||||
|
||||
setRegister(NODE_STATE(ksCurThread), msgInfoRegister, wordFromMessageInfo(
|
||||
seL4_MessageInfo_new(0, 0, 0, i)));
|
||||
|
||||
setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart);
|
||||
return EXCEPTION_NONE;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue