trivial: style and comment

Signed-off-by: Oliver Scott <Oliver.Scott@data61.csiro.au>
This commit is contained in:
Oliver Scott 2020-08-04 13:37:36 +10:00
parent 935714a4cb
commit c66d9cee7a
12 changed files with 855 additions and 827 deletions

View file

@ -125,8 +125,10 @@ unset(CONFIGURE_CLK_SHIFT CACHE)
unset(CONFIGURE_CLK_MAGIC CACHE)
unset(CONFIGURE_KERNEL_WCET CACHE)
unset(CONFIGURE_TIMER_PRECISION CACHE)
# CONFIGURE_MAX_CB and CONFIGURE_MAX_SID are related to the kernel SMMU on Arm.
unset(CONFIGURE_MAX_SID CACHE)
unset(CONFIGURE_MAX_CB CACHE)
# CLK_SHIFT and CLK_MAGIC are generated from tools/reciprocal.py
# based on the TIMER_CLK_HZ to simulate division.
# This could be moved to a cmake function

View file

@ -10,7 +10,7 @@
#define SMMU_SID_CNODE_SLOT_BITS 8
#define SMMU_CB_CNODE_SLOT_BITS 6
#define SID_INVALID SMMU_MAX_SID
#define CB_INVALID SMMU_MAX_CB
#define CB_INVALID SMMU_MAX_CB
#define ASID_INVALID nASIDs
@ -30,7 +30,7 @@ exception_t decodeARMCBInvocation(word_t label, unsigned int length, cptr_t cptr
cte_t *srcSlot, cap_t cap, extra_caps_t extraCaps,
bool_t call, word_t *buffer);
exception_t smmu_delete_cb(cap_t cap);
exception_t smmu_delete_sid(cap_t cap);
exception_t smmu_delete_sid(cap_t cap);
void smmu_cb_delete_vspace(word_t cb, asid_t asid);
void invalidateSMMUTLBByASID(asid_t asid, word_t bind_cb);
void invalidateSMMUTLBByASIDVA(asid_t asid, vptr_t vaddr, word_t bind_cb);

View file

@ -285,9 +285,9 @@
#define CBn_FSR_TF BIT(1)
#define CBn_FSR_CLEAR_ALL (CBn_FSR_MULTI | CBn_FSR_SS | \
CBn_FSR_UUT | CBn_FSR_ASF | CBn_FSR_TLBLKF | \
CBn_FSR_TLBLMCF | CBn_FSR_EF | CBn_FSR_PF | \
CBn_FSR_AFF | CBn_FSR_TF)
CBn_FSR_UUT | CBn_FSR_ASF | CBn_FSR_TLBLKF | \
CBn_FSR_TLBLMCF | CBn_FSR_EF | CBn_FSR_PF | \
CBn_FSR_AFF | CBn_FSR_TF)
/*SMMU_CBn_ACTLR defined in SMMU500*/
#define CBn_ACTLR_CPRE BIT(1)
@ -344,7 +344,7 @@
#define CBn_TCR_TG_64K 1
#define CBn_TCR_TG_16K 2
#define CBn_TCR_SH_NONE 0
#define CBn_TCR_SH_NONE 0
#define CBn_TCR_SH_OUTER 2
#define CBn_TCR_SH_INNER 3
@ -404,7 +404,7 @@ this is the same as the MAIR in core*/
/*8 bit per attribute*/
#define CBn_MAIRm_ATTR_SHIFT(n) ((n) << 3)
/*SMMU_CBn_SCTLR*/
/*SMMU_CBn_SCTLR*/
#define CBn_SCTLR_CFIE (1 << 6)
#define CBn_SCTLR_CFRE (1 << 5)
#define CBn_SCTLR_AFE (1 << 2)
@ -423,14 +423,14 @@ this is the same as the MAIR in core*/
/*SMMU_CBn_TLBIIPAS2*/
#define CBn_TLBIIPAS2_SET(vaddr) ((vaddr) >> 12 & 0xfffffffff)
void smmu_cb_assign_vspace(word_t cb, vspace_root_t *vspace, asid_t asid);
void smmu_cb_assign_vspace(word_t cb, vspace_root_t *vspace, asid_t asid);
void smmu_sid_bind_cb(word_t sid, word_t cb);
void plat_smmu_init(void);
void smmu_tlb_invalidate_all(void);
void smmu_tlb_invalidate_cb(int cb, asid_t asid);
void smmu_tlb_invalidate_cb_va(int cb, asid_t asid, vptr_t vaddr);
void smmu_cb_disable(word_t cb, asid_t asid);
void smmu_sid_unbind(word_t sid);
void smmu_sid_unbind(word_t sid);
void smmu_read_fault_state(uint32_t *status, uint32_t *syndrome_0, uint32_t *syndrome_1);
void smmu_clear_fault_state(void);
void smmu_cb_read_fault_state(int cb, uint32_t *status, word_t *address);

View file

@ -26,12 +26,12 @@ enum {
seL4_CapInitThreadIPCBuffer = 10, /* initial thread's IPC buffer frame cap */
seL4_CapDomain = 11, /* global domain controller cap */
seL4_CapSMMUSIDControl = 12, /*global SMMU SID controller cap, null cap if not supported*/
seL4_CapSMMUCBControl = 13, /*global SMMU CB controller cap, null cap if not supported*/
seL4_CapSMMUCBControl = 13, /*global SMMU CB controller cap, null cap if not supported*/
#ifdef CONFIG_KERNEL_MCS
seL4_CapInitThreadSC = 14, /* initial thread's scheduling context cap */
seL4_NumInitialCaps = 15
seL4_NumInitialCaps = 15
#else
seL4_NumInitialCaps = 14
seL4_NumInitialCaps = 14
#endif /* !CONFIG_KERNEL_MCS */
};

View file

@ -1218,8 +1218,9 @@ static inline void invalidateTLBByASID(asid_t asid)
{
#ifdef CONFIG_ARM_SMMU
vspace_root_t bind_cb = getASIDBindCB(asid);
if (unlikely(vtable_invalid_get_bind_cb(bind_cb)))
if (unlikely(vtable_invalid_get_bind_cb(bind_cb))) {
invalidateSMMUTLBByASID(asid, vtable_invalid_get_bind_cb(bind_cb));
}
#endif
#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT
vspace_root_t stored_hw_asid;
@ -1238,8 +1239,9 @@ static inline void invalidateTLBByASIDVA(asid_t asid, vptr_t vaddr)
{
#ifdef CONFIG_ARM_SMMU
vspace_root_t bind_cb = getASIDBindCB(asid);
if (unlikely(vtable_invalid_get_bind_cb(bind_cb)))
if (unlikely(vtable_invalid_get_bind_cb(bind_cb))) {
invalidateSMMUTLBByASIDVA(asid, vaddr, vtable_invalid_get_bind_cb(bind_cb));
}
#endif
#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT
vspace_root_t stored_hw_asid;

View file

@ -216,10 +216,10 @@ finaliseCap_ret_t Arch_finaliseCap(cap_t cap, bool_t final)
#ifdef CONFIG_ARM_SMMU
case cap_cb_cap:
if (cap_cb_cap_get_capBindSID(cap) != SID_INVALID) {
smmu_sid_unbind(cap_cb_cap_get_capBindSID(cap));
smmu_sid_unbind(cap_cb_cap_get_capBindSID(cap));
}
if (final) {
smmu_delete_cb(cap);
smmu_delete_cb(cap);
}
break;
case cap_sid_cap:
@ -227,7 +227,7 @@ finaliseCap_ret_t Arch_finaliseCap(cap_t cap, bool_t final)
smmu_delete_sid(cap);
}
break;
#endif
#endif
}
fc_ret.remainder = cap_null_cap_new();
@ -309,17 +309,17 @@ bool_t CONST Arch_sameRegionAs(cap_t cap_a, cap_t cap_b)
cap_get_capType(cap_b) == cap_cb_cap) {
return true;
}
case cap_sid_cap:
case cap_sid_cap:
if (cap_get_capType(cap_b) == cap_sid_cap) {
return cap_sid_cap_get_capSID(cap_a) ==
cap_sid_cap_get_capSID(cap_b);
}
}
case cap_cb_cap:
if (cap_get_capType(cap_b) == cap_cb_cap) {
return cap_cb_cap_get_capCB(cap_a) ==
cap_cb_cap_get_capCB(cap_b);
}
#endif
#endif
}
return false;
}
@ -412,22 +412,22 @@ cap_t Arch_createObject(object_t t, void *regionBase, word_t userSize, bool_t de
);
#ifndef AARCH64_VSPACE_S2_START_L1
case seL4_ARM_PageGlobalDirectoryObject:
#ifdef CONFIG_ARM_SMMU
#ifdef CONFIG_ARM_SMMU
return cap_page_global_directory_cap_new(
return cap_page_global_directory_cap_new(
asidInvalid, /* capPGDMappedASID */
(word_t)regionBase, /* capPGDBasePtr */
0, /* capPGDIsMapped */
CB_INVALID /* capPGDMappedCB */
);
#else
);
#else
return cap_page_global_directory_cap_new(
return cap_page_global_directory_cap_new(
asidInvalid, /* capPGDMappedASID */
(word_t)regionBase, /* capPGDBasePtr */
0 /* capPGDIsMapped */
);
#endif /*!CONFIG_ARM_SMMU*/
);
#endif /*!CONFIG_ARM_SMMU*/
#endif /*!AARCH64_VSPACE_S2_START_L1*/
case seL4_ARM_PageUpperDirectoryObject:
return cap_page_upper_directory_cap_new(
@ -482,13 +482,13 @@ exception_t Arch_decodeInvocation(word_t label, word_t length, cptr_t cptr,
#endif /* end of CONFIG_ARM_HYPERVISOR_SUPPORT */
#ifdef CONFIG_ARM_SMMU
case cap_sid_control_cap:
return decodeARMSIDControlInvocation(label, length, cptr, slot, cap, extraCaps, call, buffer);
return decodeARMSIDControlInvocation(label, length, cptr, slot, cap, extraCaps, call, buffer);
case cap_sid_cap:
return decodeARMSIDInvocation(label, length, cptr, slot, cap, extraCaps, call, buffer);
return decodeARMSIDInvocation(label, length, cptr, slot, cap, extraCaps, call, buffer);
case cap_cb_control_cap:
return decodeARMCBControlInvocation(label, length, cptr, slot, cap, extraCaps, call, buffer);
return decodeARMCBControlInvocation(label, length, cptr, slot, cap, extraCaps, call, buffer);
case cap_cb_cap:
return decodeARMCBInvocation(label, length, cptr, slot, cap, extraCaps, call, buffer);
return decodeARMCBInvocation(label, length, cptr, slot, cap, extraCaps, call, buffer);
#endif /*CONFIG_ARM_SMMU*/
default:
#else

View file

@ -113,11 +113,7 @@ config_option(
DEFAULT_DISABLED OFF
)
config_option(
KernelArmSMMU ARM_SMMU "Enable SystemMMU"
DEFAULT OFF
DEPENDS "KernelPlatformTx2"
)
config_option(KernelArmSMMU ARM_SMMU "Enable SystemMMU" DEFAULT OFF DEPENDS "KernelPlatformTx2")
config_option(
KernelTk1SMMU TK1_SMMU "Enable SystemMMU for the Tegra TK1 SoC"

View file

@ -125,7 +125,8 @@ BOOT_CODE static void init_irqs(cap_t root_cnode_cap)
}
#ifdef CONFIG_ARM_SMMU
BOOT_CODE static void init_smmu (cap_t root_cnode_cap) {
BOOT_CODE static void init_smmu(cap_t root_cnode_cap)
{
plat_smmu_init();
/*provide the SID and CB control cap*/
write_slot(SLOT_PTR(pptr_of_cap(root_cnode_cap), seL4_CapSMMUSIDControl), cap_sid_control_cap_new());

View file

@ -8,392 +8,396 @@
#ifdef CONFIG_ARM_SMMU
#include <arch/object/smmu.h>
static exception_t checkARMCBVspace(cap_t cap)
static exception_t checkARMCBVspace(cap_t cap)
{
word_t cb = cap_cb_cap_get_capCB(cap);
cte_t *cbSlot = smmuStateCBNode + cb;
if (unlikely(!isVTableRoot(cbSlot->cap))) {
return EXCEPTION_SYSCALL_ERROR;
}
return EXCEPTION_NONE;
word_t cb = cap_cb_cap_get_capCB(cap);
cte_t *cbSlot = smmuStateCBNode + cb;
if (unlikely(!isVTableRoot(cbSlot->cap))) {
return EXCEPTION_SYSCALL_ERROR;
}
return EXCEPTION_NONE;
}
exception_t decodeARMSIDControlInvocation(word_t label, unsigned int length, cptr_t cptr,
cte_t *srcSlot, cap_t cap, extra_caps_t extraCaps,
bool_t call, word_t *buffer) {
cte_t *srcSlot, cap_t cap, extra_caps_t extraCaps,
bool_t call, word_t *buffer)
{
word_t index, depth, sid;
cte_t *destSlot;
cap_t cnodeCap;
lookupSlot_ret_t lu_ret;
exception_t status;
uint32_t faultStatus, faultSyndrome_0, faultSyndrome_1;
word_t index, depth, sid;
cte_t *destSlot;
cap_t cnodeCap;
lookupSlot_ret_t lu_ret;
exception_t status;
uint32_t faultStatus, faultSyndrome_0, faultSyndrome_1;
if (label == ARMSIDGetFault) {
smmu_read_fault_state(&faultStatus, &faultSyndrome_0, &faultSyndrome_1);
setRegister(NODE_STATE(ksCurThread), msgRegisters[0], faultStatus);
setRegister(NODE_STATE(ksCurThread), msgRegisters[1], faultSyndrome_0);
setRegister(NODE_STATE(ksCurThread), msgRegisters[2], faultSyndrome_1);
setRegister(NODE_STATE(ksCurThread), msgInfoRegister,
if (label == ARMSIDGetFault) {
smmu_read_fault_state(&faultStatus, &faultSyndrome_0, &faultSyndrome_1);
setRegister(NODE_STATE(ksCurThread), msgRegisters[0], faultStatus);
setRegister(NODE_STATE(ksCurThread), msgRegisters[1], faultSyndrome_0);
setRegister(NODE_STATE(ksCurThread), msgRegisters[2], faultSyndrome_1);
setRegister(NODE_STATE(ksCurThread), msgInfoRegister,
wordFromMessageInfo(seL4_MessageInfo_new(0, 0, 0, 3)));
setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart);
return EXCEPTION_NONE;
}
setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart);
return EXCEPTION_NONE;
}
if (label == ARMSIDClearFault) {
smmu_clear_fault_state();
setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart);
return EXCEPTION_NONE;
}
if (label == ARMSIDClearFault) {
smmu_clear_fault_state();
setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart);
return EXCEPTION_NONE;
}
if (label != ARMSIDIssueSIDManager) {
userError("SIDControl: Illegal operation.");
current_syscall_error.type = seL4_IllegalOperation;
return EXCEPTION_SYSCALL_ERROR;
}
if (length < 3 || extraCaps.excaprefs[0] == NULL) {
current_syscall_error.type = seL4_TruncatedMessage;
return EXCEPTION_SYSCALL_ERROR;
}
if (label != ARMSIDIssueSIDManager) {
userError("SIDControl: Illegal operation.");
current_syscall_error.type = seL4_IllegalOperation;
return EXCEPTION_SYSCALL_ERROR;
}
if (length < 3 || extraCaps.excaprefs[0] == NULL) {
current_syscall_error.type = seL4_TruncatedMessage;
return EXCEPTION_SYSCALL_ERROR;
}
sid = getSyscallArg(0, buffer);
index = getSyscallArg(1, buffer);
depth = getSyscallArg(2, buffer);
cnodeCap = extraCaps.excaprefs[0]->cap;
sid = getSyscallArg(0, buffer);
index = getSyscallArg(1, buffer);
depth = getSyscallArg(2, buffer);
cnodeCap = extraCaps.excaprefs[0]->cap;
if (sid >= SMMU_MAX_SID) {
current_syscall_error.type = seL4_RangeError;
current_syscall_error.rangeErrorMin = 0;
current_syscall_error.rangeErrorMax = SMMU_MAX_SID - 1;
userError("Rejecting request for SID %u. SID is greater than or equal to SMMU_MAX_SID.", (int)sid);
return EXCEPTION_SYSCALL_ERROR;
}
if (smmuStateSIDTable[sid]) {
current_syscall_error.type = seL4_RevokeFirst;
userError("Rejecting request for SID %u. Already active.", (int)sid);
return EXCEPTION_SYSCALL_ERROR;
}
if (sid >= SMMU_MAX_SID) {
current_syscall_error.type = seL4_RangeError;
current_syscall_error.rangeErrorMin = 0;
current_syscall_error.rangeErrorMax = SMMU_MAX_SID - 1;
userError("Rejecting request for SID %u. SID is greater than or equal to SMMU_MAX_SID.", (int)sid);
return EXCEPTION_SYSCALL_ERROR;
}
if (smmuStateSIDTable[sid]) {
current_syscall_error.type = seL4_RevokeFirst;
userError("Rejecting request for SID %u. Already active.", (int)sid);
return EXCEPTION_SYSCALL_ERROR;
}
lu_ret = lookupTargetSlot(cnodeCap, index, depth);
if (lu_ret.status != EXCEPTION_NONE) {
userError("Target slot for new SID Handler cap invalid: cap %lu, SID %u.",
getExtraCPtr(buffer, 0), (int)sid);
return lu_ret.status;
}
destSlot = lu_ret.slot;
status = ensureEmptySlot(destSlot);
if (status != EXCEPTION_NONE) {
userError("Target slot for new SID Handler cap not empty: cap %lu, SID %u.",
getExtraCPtr(buffer, 0), (int)sid);
return status;
}
setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart);
smmuStateSIDTable[sid] = true;
cteInsert(cap_sid_cap_new(sid), srcSlot, destSlot);
return EXCEPTION_NONE;
lu_ret = lookupTargetSlot(cnodeCap, index, depth);
if (lu_ret.status != EXCEPTION_NONE) {
userError("Target slot for new SID Handler cap invalid: cap %lu, SID %u.",
getExtraCPtr(buffer, 0), (int)sid);
return lu_ret.status;
}
destSlot = lu_ret.slot;
status = ensureEmptySlot(destSlot);
if (status != EXCEPTION_NONE) {
userError("Target slot for new SID Handler cap not empty: cap %lu, SID %u.",
getExtraCPtr(buffer, 0), (int)sid);
return status;
}
setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart);
smmuStateSIDTable[sid] = true;
cteInsert(cap_sid_cap_new(sid), srcSlot, destSlot);
return EXCEPTION_NONE;
}
exception_t decodeARMSIDInvocation(word_t label, unsigned int length, cptr_t cptr,
cte_t *srcSlot, cap_t cap, extra_caps_t extraCaps,
bool_t call, word_t *buffer) {
cap_t cbCap;
cte_t *cbCapSlot;
cte_t *cbAssignSlot;
exception_t status;
word_t sid;
cte_t *srcSlot, cap_t cap, extra_caps_t extraCaps,
bool_t call, word_t *buffer)
{
cap_t cbCap;
cte_t *cbCapSlot;
cte_t *cbAssignSlot;
exception_t status;
word_t sid;
switch (label) {
case ARMSIDBindCB:
if (unlikely(extraCaps.excaprefs[0] == NULL)) {
userError("ARMSIDBindCB: Invalid CB cap.");
current_syscall_error.type = seL4_TruncatedMessage;
return EXCEPTION_SYSCALL_ERROR;
}
cbCapSlot = extraCaps.excaprefs[0];
cbCap = cbCapSlot->cap;
if (unlikely(cap_get_capType(cbCap) != cap_cb_cap)) {
userError("ARMSIDBindCB: Invalid CB cap.");
current_syscall_error.type = seL4_InvalidCapability;
current_syscall_error.invalidCapNumber = 1;
return EXCEPTION_SYSCALL_ERROR;
}
if (unlikely(checkARMCBVspace(cbCap) != EXCEPTION_NONE)) {
userError("ARMSIDBindCB: Invalid CB cap.");
current_syscall_error.type = seL4_InvalidCapability;
current_syscall_error.invalidCapNumber = 1;
return EXCEPTION_SYSCALL_ERROR;
}
sid = cap_sid_cap_get_capSID(cap);
cbAssignSlot = smmuStateSIDNode + sid;
status = ensureEmptySlot(cbAssignSlot);
if (status != EXCEPTION_NONE) {
userError("ARMSIDBindCB: The SID is already bound with a context bank.");
return status;
}
setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart);
/*binding the sid to cb in SMMU*/
smmu_sid_bind_cb(sid, cap_cb_cap_get_capCB(cbCap));
/* Building the connection between SID and CB caps by placing a
* copy of the given cb cap in sid's cnode*/
cteInsert(cbCap, cbCapSlot, cbAssignSlot);
/* Recording the SID number in the copied CB cap.
* Deleting the copied CB cap will trigger unbinding
* operations. As a CB can be used (bound)
* by multiple SID caps, each copied CB caps resulted from
* binding operations keeps track of its serving SID numbers.*/
cap_cb_cap_ptr_set_capBindSID(&(cbAssignSlot->cap), sid);
return EXCEPTION_NONE;
case ARMSIDUnbindCB:
sid = cap_sid_cap_get_capSID(cap);
cbAssignSlot = smmuStateSIDNode + sid;
if (unlikely(cap_get_capType(cbAssignSlot->cap) != cap_cb_cap)) {
userError("ARMSIDUnbindCB: The SID is not assigned with a context bank.");
current_syscall_error.type = seL4_IllegalOperation;
return EXCEPTION_SYSCALL_ERROR;
}
status = cteDelete(cbAssignSlot, true);
if (unlikely(status != EXCEPTION_NONE)) {
userError("ARMSIDUnbindCB: the Assigned context bank cannot be unassigned.");
return status;
}
setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart);
return EXCEPTION_NONE;
default:
userError("ARMSID: Illegal operation.");
current_syscall_error.type = seL4_IllegalOperation;
return EXCEPTION_SYSCALL_ERROR;
}
switch (label) {
case ARMSIDBindCB:
if (unlikely(extraCaps.excaprefs[0] == NULL)) {
userError("ARMSIDBindCB: Invalid CB cap.");
current_syscall_error.type = seL4_TruncatedMessage;
return EXCEPTION_SYSCALL_ERROR;
}
cbCapSlot = extraCaps.excaprefs[0];
cbCap = cbCapSlot->cap;
if (unlikely(cap_get_capType(cbCap) != cap_cb_cap)) {
userError("ARMSIDBindCB: Invalid CB cap.");
current_syscall_error.type = seL4_InvalidCapability;
current_syscall_error.invalidCapNumber = 1;
return EXCEPTION_SYSCALL_ERROR;
}
if (unlikely(checkARMCBVspace(cbCap) != EXCEPTION_NONE)) {
userError("ARMSIDBindCB: Invalid CB cap.");
current_syscall_error.type = seL4_InvalidCapability;
current_syscall_error.invalidCapNumber = 1;
return EXCEPTION_SYSCALL_ERROR;
}
sid = cap_sid_cap_get_capSID(cap);
cbAssignSlot = smmuStateSIDNode + sid;
status = ensureEmptySlot(cbAssignSlot);
if (status != EXCEPTION_NONE) {
userError("ARMSIDBindCB: The SID is already bound with a context bank.");
return status;
}
setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart);
/*binding the sid to cb in SMMU*/
smmu_sid_bind_cb(sid, cap_cb_cap_get_capCB(cbCap));
/* Building the connection between SID and CB caps by placing a
* copy of the given cb cap in sid's cnode*/
cteInsert(cbCap, cbCapSlot, cbAssignSlot);
/* Recording the SID number in the copied CB cap.
* Deleting the copied CB cap will trigger unbinding
* operations. As a CB can be used (bound)
* by multiple SID caps, each copied CB caps resulted from
* binding operations keeps track of its serving SID numbers.*/
cap_cb_cap_ptr_set_capBindSID(&(cbAssignSlot->cap), sid);
return EXCEPTION_NONE;
case ARMSIDUnbindCB:
sid = cap_sid_cap_get_capSID(cap);
cbAssignSlot = smmuStateSIDNode + sid;
if (unlikely(cap_get_capType(cbAssignSlot->cap) != cap_cb_cap)) {
userError("ARMSIDUnbindCB: The SID is not assigned with a context bank.");
current_syscall_error.type = seL4_IllegalOperation;
return EXCEPTION_SYSCALL_ERROR;
}
status = cteDelete(cbAssignSlot, true);
if (unlikely(status != EXCEPTION_NONE)) {
userError("ARMSIDUnbindCB: the Assigned context bank cannot be unassigned.");
return status;
}
setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart);
return EXCEPTION_NONE;
default:
userError("ARMSID: Illegal operation.");
current_syscall_error.type = seL4_IllegalOperation;
return EXCEPTION_SYSCALL_ERROR;
}
}
exception_t smmu_delete_sid(cap_t cap)
{
word_t sid = cap_sid_cap_get_capSID(cap);
cte_t *cbAssignSlot = smmuStateSIDNode + sid;
exception_t status = EXCEPTION_NONE;
/*deleting the assigned context bank cap if exsits*/
if (unlikely(cap_get_capType(cbAssignSlot->cap) == cap_cb_cap)) {
status = cteDelete(cbAssignSlot, true);
}
smmuStateSIDTable[sid] = false;
return status;
word_t sid = cap_sid_cap_get_capSID(cap);
cte_t *cbAssignSlot = smmuStateSIDNode + sid;
exception_t status = EXCEPTION_NONE;
/*deleting the assigned context bank cap if exsits*/
if (unlikely(cap_get_capType(cbAssignSlot->cap) == cap_cb_cap)) {
status = cteDelete(cbAssignSlot, true);
}
smmuStateSIDTable[sid] = false;
return status;
}
exception_t decodeARMCBControlInvocation(word_t label, unsigned int length, cptr_t cptr,
cte_t *srcSlot, cap_t cap, extra_caps_t extraCaps,
bool_t call, word_t *buffer) {
cte_t *srcSlot, cap_t cap, extra_caps_t extraCaps,
bool_t call, word_t *buffer)
{
word_t index, depth, cb;
cte_t *destSlot;
cap_t cnodeCap;
lookupSlot_ret_t lu_ret;
exception_t status;
word_t index, depth, cb;
cte_t *destSlot;
cap_t cnodeCap;
lookupSlot_ret_t lu_ret;
exception_t status;
if (label == ARMCBTLBInvalidateAll) {
setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart);
smmu_tlb_invalidate_all();
return EXCEPTION_NONE;
}
if (label == ARMCBTLBInvalidateAll) {
setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart);
smmu_tlb_invalidate_all();
return EXCEPTION_NONE;
}
if (label != ARMCBIssueCBManager) {
userError("ARMCBControl: Illegal operation.");
current_syscall_error.type = seL4_IllegalOperation;
return EXCEPTION_SYSCALL_ERROR;
}
if (length < 3 || extraCaps.excaprefs[0] == NULL) {
current_syscall_error.type = seL4_TruncatedMessage;
return EXCEPTION_SYSCALL_ERROR;
}
if (label != ARMCBIssueCBManager) {
userError("ARMCBControl: Illegal operation.");
current_syscall_error.type = seL4_IllegalOperation;
return EXCEPTION_SYSCALL_ERROR;
}
if (length < 3 || extraCaps.excaprefs[0] == NULL) {
current_syscall_error.type = seL4_TruncatedMessage;
return EXCEPTION_SYSCALL_ERROR;
}
cb = getSyscallArg(0, buffer);
index = getSyscallArg(1, buffer);
depth = getSyscallArg(2, buffer);
cnodeCap = extraCaps.excaprefs[0]->cap;
cb = getSyscallArg(0, buffer);
index = getSyscallArg(1, buffer);
depth = getSyscallArg(2, buffer);
cnodeCap = extraCaps.excaprefs[0]->cap;
if (cb >= SMMU_MAX_CB) {
current_syscall_error.type = seL4_RangeError;
current_syscall_error.rangeErrorMin = 0;
current_syscall_error.rangeErrorMax = SMMU_MAX_CB - 1;
userError("Rejecting request for CB %u. CB is greater than or equal to SMMU_MAX_CB.", (int)cb);
return EXCEPTION_SYSCALL_ERROR;
}
if (smmuStateCBTable[cb]) {
current_syscall_error.type = seL4_RevokeFirst;
userError("Rejecting request for CB %u. Already active.", (int)cb);
return EXCEPTION_SYSCALL_ERROR;
}
if (cb >= SMMU_MAX_CB) {
current_syscall_error.type = seL4_RangeError;
current_syscall_error.rangeErrorMin = 0;
current_syscall_error.rangeErrorMax = SMMU_MAX_CB - 1;
userError("Rejecting request for CB %u. CB is greater than or equal to SMMU_MAX_CB.", (int)cb);
return EXCEPTION_SYSCALL_ERROR;
}
if (smmuStateCBTable[cb]) {
current_syscall_error.type = seL4_RevokeFirst;
userError("Rejecting request for CB %u. Already active.", (int)cb);
return EXCEPTION_SYSCALL_ERROR;
}
lu_ret = lookupTargetSlot(cnodeCap, index, depth);
if (lu_ret.status != EXCEPTION_NONE) {
userError("Target slot for new CB Handler cap invalid: cap %lu, CB %u.",
getExtraCPtr(buffer, 0), (int)cb);
return lu_ret.status;
}
destSlot = lu_ret.slot;
status = ensureEmptySlot(destSlot);
if (status != EXCEPTION_NONE) {
userError("Target slot for new CB Handler cap not empty: cap %lu, CB %u.",
getExtraCPtr(buffer, 0), (int)cb);
return status;
}
lu_ret = lookupTargetSlot(cnodeCap, index, depth);
if (lu_ret.status != EXCEPTION_NONE) {
userError("Target slot for new CB Handler cap invalid: cap %lu, CB %u.",
getExtraCPtr(buffer, 0), (int)cb);
return lu_ret.status;
}
destSlot = lu_ret.slot;
status = ensureEmptySlot(destSlot);
if (status != EXCEPTION_NONE) {
userError("Target slot for new CB Handler cap not empty: cap %lu, CB %u.",
getExtraCPtr(buffer, 0), (int)cb);
return status;
}
setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart);
smmuStateCBTable[cb] = true;
cteInsert(cap_cb_cap_new(SID_INVALID, cb), srcSlot, destSlot);
return EXCEPTION_NONE;
setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart);
smmuStateCBTable[cb] = true;
cteInsert(cap_cb_cap_new(SID_INVALID, cb), srcSlot, destSlot);
return EXCEPTION_NONE;
}
exception_t decodeARMCBInvocation(word_t label, unsigned int length, cptr_t cptr,
cte_t *srcSlot, cap_t cap, extra_caps_t extraCaps,
bool_t call, word_t *buffer) {
cte_t *srcSlot, cap_t cap, extra_caps_t extraCaps,
bool_t call, word_t *buffer)
{
cap_t vspaceCap;
cte_t *vspaceCapSlot;
cte_t *cbSlot;
exception_t status;
word_t cb;
uint32_t faultStatus;
word_t faultAddress;
cap_t vspaceCap;
cte_t *vspaceCapSlot;
cte_t *cbSlot;
exception_t status;
word_t cb;
uint32_t faultStatus;
word_t faultAddress;
switch (label) {
case ARMCBTLBInvalidate:
if (unlikely(checkARMCBVspace(cap) != EXCEPTION_NONE)) {
userError("ARMCBTLBInvalidate: the CB does not have a vspace root.");
current_syscall_error.type = seL4_IllegalOperation;
return EXCEPTION_SYSCALL_ERROR;
}
cb = cap_cb_cap_get_capCB(cap);
cbSlot = smmuStateCBNode + cb;
setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart);
smmu_tlb_invalidate_cb(cb, cap_vtable_root_get_mappedASID(cbSlot->cap));
return EXCEPTION_NONE;
switch (label) {
case ARMCBTLBInvalidate:
if (unlikely(checkARMCBVspace(cap) != EXCEPTION_NONE)) {
userError("ARMCBTLBInvalidate: the CB does not have a vspace root.");
current_syscall_error.type = seL4_IllegalOperation;
return EXCEPTION_SYSCALL_ERROR;
}
cb = cap_cb_cap_get_capCB(cap);
cbSlot = smmuStateCBNode + cb;
setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart);
smmu_tlb_invalidate_cb(cb, cap_vtable_root_get_mappedASID(cbSlot->cap));
return EXCEPTION_NONE;
case ARMCBAssignVspace:
if (unlikely(extraCaps.excaprefs[0] == NULL)) {
current_syscall_error.type = seL4_TruncatedMessage;
return EXCEPTION_SYSCALL_ERROR;
}
case ARMCBAssignVspace:
if (unlikely(extraCaps.excaprefs[0] == NULL)) {
current_syscall_error.type = seL4_TruncatedMessage;
return EXCEPTION_SYSCALL_ERROR;
}
vspaceCapSlot = extraCaps.excaprefs[0];
vspaceCap = vspaceCapSlot->cap;
vspaceCapSlot = extraCaps.excaprefs[0];
vspaceCap = vspaceCapSlot->cap;
if (unlikely(!isVTableRoot(vspaceCap) || !cap_vtable_root_isMapped(vspaceCap))) {
userError("ARMCBAssignVspace: the vspace is invalid");
current_syscall_error.type = seL4_InvalidCapability;
current_syscall_error.invalidCapNumber = 1;
return EXCEPTION_SYSCALL_ERROR;
}
if (unlikely(!isVTableRoot(vspaceCap) || !cap_vtable_root_isMapped(vspaceCap))) {
userError("ARMCBAssignVspace: the vspace is invalid");
current_syscall_error.type = seL4_InvalidCapability;
current_syscall_error.invalidCapNumber = 1;
return EXCEPTION_SYSCALL_ERROR;
}
/*the cb number must be valid as it is created via the ARMCBIssueCBManager*/
cb = cap_cb_cap_get_capCB(cap);
cbSlot = smmuStateCBNode + cb;
status = ensureEmptySlot(cbSlot);
if (status != EXCEPTION_NONE) {
userError("ARMCBAssignVspace: the CB already assigned with a vspace root.");
return status;
}
/*the cb number must be valid as it is created via the ARMCBIssueCBManager*/
cb = cap_cb_cap_get_capCB(cap);
cbSlot = smmuStateCBNode + cb;
status = ensureEmptySlot(cbSlot);
if (status != EXCEPTION_NONE) {
userError("ARMCBAssignVspace: the CB already assigned with a vspace root.");
return status;
}
setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart);
/*setting up vspace for the context bank in SMMU*/
smmu_cb_assign_vspace(cb, cap_vtable_root_get_basePtr(vspaceCap),
cap_vtable_root_get_mappedASID(vspaceCap));
/*Connecting vspace cap to context bank*/
cteInsert(vspaceCap, vspaceCapSlot, cbSlot);
cap_vtable_root_ptr_set_mappedCB(&(cbSlot->cap), cb);
/*set relationship between CB and ASID*/
smmuStateCBAsidTable[cb] = cap_vtable_root_get_mappedASID(vspaceCap);
increaseASIDBindCB(cap_vtable_root_get_mappedASID(vspaceCap));
return EXCEPTION_NONE;
case ARMCBUnassignVspace:
if (unlikely(checkARMCBVspace(cap) != EXCEPTION_NONE)) {
userError("ARMCBUnassignVspace: the CB does not have an assigned VSpace.");
current_syscall_error.type = seL4_IllegalOperation;
return EXCEPTION_SYSCALL_ERROR;
}
cb = cap_cb_cap_get_capCB(cap);
cbSlot = smmuStateCBNode + cb;
status = cteDelete(cbSlot, true);
if (unlikely(status != EXCEPTION_NONE)) {
userError("ARMCBUnassignVspace: the Assigned VSpace cannot be deleted.");
return status;
}
setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart);
return EXCEPTION_NONE;
case ARMCBGetFault:
smmu_cb_read_fault_state(cap_cb_cap_get_capCB(cap), &faultStatus, &faultAddress);
setRegister(NODE_STATE(ksCurThread), msgRegisters[0], faultStatus);
setRegister(NODE_STATE(ksCurThread), msgRegisters[1], faultAddress);
setRegister(NODE_STATE(ksCurThread), msgInfoRegister,
wordFromMessageInfo(seL4_MessageInfo_new(0, 0, 0, 2)));
setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart);
return EXCEPTION_NONE;
case ARMCBClearFault:
smmu_cb_clear_fault_state(cap_cb_cap_get_capCB(cap));
setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart);
return EXCEPTION_NONE;
default:
userError("ARMCBInvocation: Illegal operation.");
current_syscall_error.type = seL4_IllegalOperation;
return EXCEPTION_SYSCALL_ERROR;
}
setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart);
/*setting up vspace for the context bank in SMMU*/
smmu_cb_assign_vspace(cb, cap_vtable_root_get_basePtr(vspaceCap),
cap_vtable_root_get_mappedASID(vspaceCap));
/*Connecting vspace cap to context bank*/
cteInsert(vspaceCap, vspaceCapSlot, cbSlot);
cap_vtable_root_ptr_set_mappedCB(&(cbSlot->cap), cb);
/*set relationship between CB and ASID*/
smmuStateCBAsidTable[cb] = cap_vtable_root_get_mappedASID(vspaceCap);
increaseASIDBindCB(cap_vtable_root_get_mappedASID(vspaceCap));
return EXCEPTION_NONE;
case ARMCBUnassignVspace:
if (unlikely(checkARMCBVspace(cap) != EXCEPTION_NONE)) {
userError("ARMCBUnassignVspace: the CB does not have an assigned VSpace.");
current_syscall_error.type = seL4_IllegalOperation;
return EXCEPTION_SYSCALL_ERROR;
}
cb = cap_cb_cap_get_capCB(cap);
cbSlot = smmuStateCBNode + cb;
status = cteDelete(cbSlot, true);
if (unlikely(status != EXCEPTION_NONE)) {
userError("ARMCBUnassignVspace: the Assigned VSpace cannot be deleted.");
return status;
}
setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart);
return EXCEPTION_NONE;
case ARMCBGetFault:
smmu_cb_read_fault_state(cap_cb_cap_get_capCB(cap), &faultStatus, &faultAddress);
setRegister(NODE_STATE(ksCurThread), msgRegisters[0], faultStatus);
setRegister(NODE_STATE(ksCurThread), msgRegisters[1], faultAddress);
setRegister(NODE_STATE(ksCurThread), msgInfoRegister,
wordFromMessageInfo(seL4_MessageInfo_new(0, 0, 0, 2)));
setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart);
return EXCEPTION_NONE;
case ARMCBClearFault:
smmu_cb_clear_fault_state(cap_cb_cap_get_capCB(cap));
setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart);
return EXCEPTION_NONE;
default:
userError("ARMCBInvocation: Illegal operation.");
current_syscall_error.type = seL4_IllegalOperation;
return EXCEPTION_SYSCALL_ERROR;
}
}
exception_t smmu_delete_cb(cap_t cap)
exception_t smmu_delete_cb(cap_t cap)
{
word_t cb = cap_cb_cap_get_capCB(cap);
cte_t *cbSlot;
exception_t status = EXCEPTION_NONE;
/*deleting assigned vspace root if exists*/
if (unlikely(checkARMCBVspace(cap) == EXCEPTION_NONE)) {
cbSlot = smmuStateCBNode + cb;
/*the relationship between CB and ASID is reset at the vspace deletion
triggered by the cteDelete*/
status = cteDelete(cbSlot, true);
}
smmuStateCBTable[cb] = false;
return status;
word_t cb = cap_cb_cap_get_capCB(cap);
cte_t *cbSlot;
exception_t status = EXCEPTION_NONE;
/*deleting assigned vspace root if exists*/
if (unlikely(checkARMCBVspace(cap) == EXCEPTION_NONE)) {
cbSlot = smmuStateCBNode + cb;
/*the relationship between CB and ASID is reset at the vspace deletion
triggered by the cteDelete*/
status = cteDelete(cbSlot, true);
}
smmuStateCBTable[cb] = false;
return status;
}
void smmu_cb_delete_vspace(word_t cb, asid_t asid)
{
/* Deleting the vsapce cap stored in context bank's CNode, causing:
* -reset the relationship between context bank and vspace's ASID
* -disabe the context bank as its vspace no longer exists*/
smmuStateCBAsidTable[cb] = ASID_INVALID;
decreaseASIDBindCB(asid);
smmu_cb_disable(cb, asid);
/* Deleting the vsapce cap stored in context bank's CNode, causing:
* -reset the relationship between context bank and vspace's ASID
* -disabe the context bank as its vspace no longer exists*/
smmuStateCBAsidTable[cb] = ASID_INVALID;
decreaseASIDBindCB(asid);
smmu_cb_disable(cb, asid);
}
void invalidateSMMUTLBByASID(asid_t asid, word_t bind_cb)
{
/* Due to the requirement of one vspace (ASID) can be shared by
* multiple threads and drivers, there is no obvious way to
* directly locate all context banks associated with a given ASID without a
* serch. Another possible solution is representing all context banks in
* bitmaps, which also requires a search. This operation can only be triggered
* by ASID invalidation or similar operations, hence the performance is not a major issue.*/
for (int cb = 0; cb < SMMU_MAX_CB && bind_cb; cb++) {
if (unlikely(smmuStateCBAsidTable[cb] == asid)) {
smmu_tlb_invalidate_cb(cb, asid);
bind_cb--;
}
}
/* Due to the requirement of one vspace (ASID) can be shared by
* multiple threads and drivers, there is no obvious way to
* directly locate all context banks associated with a given ASID without a
* serch. Another possible solution is representing all context banks in
* bitmaps, which also requires a search. This operation can only be triggered
* by ASID invalidation or similar operations, hence the performance is not a major issue.*/
for (int cb = 0; cb < SMMU_MAX_CB && bind_cb; cb++) {
if (unlikely(smmuStateCBAsidTable[cb] == asid)) {
smmu_tlb_invalidate_cb(cb, asid);
bind_cb--;
}
}
}
void invalidateSMMUTLBByASIDVA(asid_t asid, vptr_t vaddr, word_t bind_cb)
{
/* Implemeneted in the same way as invalidateSMMUTLBByASID */
for (int cb = 0; cb < SMMU_MAX_CB && bind_cb; cb++) {
if (unlikely(smmuStateCBAsidTable[cb] == asid)) {
smmu_tlb_invalidate_cb_va(cb, asid, vaddr);
bind_cb--;
}
}
/* Implemeneted in the same way as invalidateSMMUTLBByASID */
for (int cb = 0; cb < SMMU_MAX_CB && bind_cb; cb++) {
if (unlikely(smmuStateCBAsidTable[cb] == asid)) {
smmu_tlb_invalidate_cb_va(cb, asid, vaddr);
bind_cb--;
}
}
}
#endif

View file

@ -6,8 +6,4 @@
cmake_minimum_required(VERSION 3.7.2)
register_driver(
compatibility_strings "arm,mmu-500"
PREFIX src/drivers/smmu
CFILES "smmuv2.c"
)
register_driver(compatibility_strings "arm,mmu-500" PREFIX src/drivers/smmu CFILES "smmuv2.c")

File diff suppressed because it is too large Load diff

View file

@ -27,10 +27,9 @@ if(KernelPlatformTx2)
TIMER drivers/timer/arm_generic.h
CLK_SHIFT 57u
CLK_MAGIC 4611686019u
KERNEL_WCET 10u
SMMU drivers/smmu/smmuv2.h
MAX_SID 128
MAX_CB 64
KERNEL_WCET 10u SMMU drivers/smmu/smmuv2.h
MAX_SID 128
MAX_CB 64
)
endif()