SMMU: supporting probing fault status
Providing system calls that enquiry the fault status in context banks and in SMMU overall. Signed-off-by: Oliver Scott <Oliver.Scott@data61.csiro.au>
This commit is contained in:
parent
35bb485e29
commit
81f9a88ff7
4 changed files with 116 additions and 3 deletions
|
|
@ -424,3 +424,7 @@ void smmu_tlb_invalidate_all(void);
|
|||
void smmu_tlb_invalidate_cb(int cb, asid_t asid);
|
||||
void smmu_cb_disable(word_t cb, asid_t asid);
|
||||
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);
|
||||
void smmu_cb_clear_fault_state(int cb);
|
||||
|
|
|
|||
|
|
@ -319,6 +319,29 @@
|
|||
<param dir="in" name="index" type="seL4_Word" description="CPTR to the destination slot. Resolved from the root of the destination CSpace."/>
|
||||
<param dir="in" name="depth" type="seL4_Uint8" description="Number of bits of dest_index to resolve to find the destination slot."/>
|
||||
</method>
|
||||
<method id="ARMSIDGetFault" name="GetFault" manual_name="GetFault"
|
||||
manual_label="sid_controlgetfault">
|
||||
<brief>
|
||||
Get the fault status of the SMMU.
|
||||
</brief>
|
||||
<return>
|
||||
A <texttt text='seL4_ARM_SMMU_GetFault_t'/> struct that contains a
|
||||
<texttt text='seL4_Word status'/>, which holds the global fault status of the SMMU,
|
||||
<texttt text='seL4_Word syndrome_0'/>, which holds the global fault syndrome 0 of the SMMU,
|
||||
<texttt text='seL4_Word syndrome_1'/>, which holds the global fault syndrome 1 of the SMMU,
|
||||
and <texttt text='int error'/>.<docref> See <autoref label='sec:errors'/> for a description
|
||||
of the message register and tag contents upon error.</docref>
|
||||
</return>
|
||||
<param dir="out" name="status" type="seL4_Word"/>
|
||||
<param dir="out" name="syndrome_0" type="seL4_Word"/>
|
||||
<param dir="out" name="syndrome_1" type="seL4_Word"/>
|
||||
</method>
|
||||
<method id="ARMSIDClearFault" name="ClearFault" manual_name="ClearFault"
|
||||
manual_label="sid_controlclearfault">
|
||||
<brief>
|
||||
Clear the fault status of the SMMU.
|
||||
</brief>
|
||||
</method>
|
||||
</interface>
|
||||
<interface name="seL4_ARM_SID" manual_name="SID" cap_description="A SID capability. This gives you the authority to make this call.">
|
||||
<method id="ARMSIDBindCB" name="BindCB" manual_name="BindCB"
|
||||
|
|
@ -375,5 +398,26 @@
|
|||
Invalidating TLB entries used by the current ASID in this context bank.
|
||||
</brief>
|
||||
</method>
|
||||
<method id="ARMCBGetFault" name="CBGetFault" manual_name="CBGetFault"
|
||||
manual_label="cb_getfault">
|
||||
<brief>
|
||||
Get the fault status of the context bank.
|
||||
</brief>
|
||||
<return>
|
||||
A <texttt text='seL4_ARM_SMMU_CB_GetFault_t'/> struct that contains a
|
||||
<texttt text='seL4_Word status'/>, which holds the fault status of the context bank,
|
||||
<texttt text='seL4_Word address'/>, which holds the faulty address,
|
||||
and <texttt text='int error'/>.<docref> See <autoref label='sec:errors'/> for a description
|
||||
of the message register and tag contents upon error.</docref>
|
||||
</return>
|
||||
<param dir="out" name="status" type="seL4_Word"/>
|
||||
<param dir="out" name="address" type="seL4_Word"/>
|
||||
</method>
|
||||
<method id="ARMCBClearFault" name="CBClearFault" manual_name="CBClearFault"
|
||||
manual_label="cb_clearfault">
|
||||
<brief>
|
||||
Clear the fault status of the context bank.
|
||||
</brief>
|
||||
</method>
|
||||
</interface>
|
||||
</api>
|
||||
|
|
|
|||
|
|
@ -27,6 +27,24 @@ exception_t decodeARMSIDControlInvocation(word_t label, unsigned int length, cpt
|
|||
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,
|
||||
wordFromMessageInfo(seL4_MessageInfo_new(0, 0, 0, 3)));
|
||||
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.");
|
||||
|
|
@ -234,6 +252,8 @@ exception_t decodeARMCBInvocation(word_t label, unsigned int length, cptr_t cptr
|
|||
cte_t *cbSlot;
|
||||
exception_t status;
|
||||
word_t cb;
|
||||
uint32_t faultStatus;
|
||||
word_t faultAddress;
|
||||
|
||||
switch (label) {
|
||||
case ARMCBTLBInvalidate:
|
||||
|
|
@ -297,6 +317,21 @@ exception_t decodeARMCBInvocation(word_t label, unsigned int length, cptr_t cptr
|
|||
}
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -259,13 +259,17 @@ BOOT_CODE static void smmu_config_prob(void)
|
|||
}
|
||||
|
||||
|
||||
|
||||
BOOT_CODE static void smmu_dev_reset(void)
|
||||
{
|
||||
uint32_t reg;
|
||||
uint32_t reg = 0;
|
||||
pptr_t cb_bank_ptr;
|
||||
uint32_t major;
|
||||
|
||||
/*clear the global FSR by writing back the read value*/
|
||||
/*clear the fault syndrom registers*/
|
||||
smmu_write_reg32(SMMU_GR0_PPTR, SMMU_sGFSYNR0, reg);
|
||||
smmu_write_reg32(SMMU_GR0_PPTR, SMMU_sGFSYNR1, reg);
|
||||
/*clear the global FSR by writing back the read value*/
|
||||
reg = smmu_read_reg32(SMMU_GR0_PPTR, SMMU_sGFSR);
|
||||
smmu_write_reg32(SMMU_GR0_PPTR, SMMU_sGFSR, reg);
|
||||
|
||||
|
|
@ -306,8 +310,9 @@ BOOT_CODE static void smmu_dev_reset(void)
|
|||
cb_bank_ptr = SMMU_CBn_BASE_PPTR(i);
|
||||
/*disable context banks and clear the context bank fault registers*/
|
||||
smmu_write_reg32(cb_bank_ptr, SMMU_CBn_SCTLR, 0);
|
||||
/*clear the syndrom register*/
|
||||
smmu_write_reg64(cb_bank_ptr, SMMU_CBn_FAR, 0ULL);
|
||||
smmu_write_reg32(cb_bank_ptr, SMMU_CBn_FSR, CBn_FSR_CLEAR_ALL);
|
||||
|
||||
/*special init requested by the smmu-500: start*/
|
||||
/*disable MMU-500's next page prefetch due to errata 841119 and 826419*/
|
||||
reg = smmu_read_reg32(cb_bank_ptr, SMMU_CBn_ACTLR);
|
||||
|
|
@ -567,3 +572,28 @@ void smmu_tlb_invalidate_cb(int cb, asid_t asid) {
|
|||
smmu_tlb_sync(SMMU_CBn_BASE_PPTR(cb), SMMU_CBn_TLBSYNC, SMMU_CBn_TLBSTATUS);
|
||||
#endif
|
||||
}
|
||||
|
||||
void smmu_read_fault_state(uint32_t *status, uint32_t *syndrome_0, uint32_t *syndrome_1)
|
||||
{
|
||||
*status = smmu_read_reg32(SMMU_GR0_PPTR, SMMU_sGFSR);
|
||||
*syndrome_0 = smmu_read_reg32(SMMU_GR0_PPTR, SMMU_sGFSYNR0);
|
||||
*syndrome_1 = smmu_read_reg32(SMMU_GR0_PPTR, SMMU_sGFSYNR1);
|
||||
}
|
||||
|
||||
void smmu_clear_fault_state(void)
|
||||
{
|
||||
uint32_t reg = smmu_read_reg32(SMMU_GR0_PPTR, SMMU_sGFSR);
|
||||
smmu_write_reg32(SMMU_GR0_PPTR, SMMU_sGFSR, reg);
|
||||
}
|
||||
|
||||
void smmu_cb_read_fault_state(int cb, uint32_t *status, word_t *address)
|
||||
{
|
||||
*status = smmu_read_reg32(SMMU_CBn_BASE_PPTR(cb), SMMU_CBn_FSR);
|
||||
*address = smmu_read_reg64(SMMU_CBn_BASE_PPTR(cb),SMMU_CBn_FAR);
|
||||
}
|
||||
|
||||
void smmu_cb_clear_fault_state(int cb)
|
||||
{
|
||||
smmu_write_reg32(SMMU_CBn_BASE_PPTR(cb), SMMU_CBn_FSR, CBn_FSR_CLEAR_ALL);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue