/* Copyright 2018 Canaan Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * @file interrupt.c * @brief support k210 interrupt configure * @version 1.0 * @author AIIT XUOS Lab * @date 2021-04-29 */ /************************************************* File name: interrupt.c Description: support k210 interrupt configure Others: take plic.c for references from Canaan k210 SDK * https://canaan-creative.com/developer History: 1. Date: 2021-04-29 Author: AIIT XUOS Lab Modification: 1. support K210 interrupt configure *************************************************/ #include "tick.h" #include #include #include #include #include #include #include #ifdef TASK_ISOLATION #include #endif #define CPU_NUM 2 x_base DisableLocalInterrupt() { x_base level; asm volatile ("csrrci %0, mstatus, 8" : "=r"(level)); return level; } void EnableLocalInterrupt(x_base level) { asm volatile ("csrw mstatus, %0" :: "r"(level)); } int EnableHwclintIpi(void) { SET_CSR(mie, MIP_MSIP); return 0; } int DisableHwclintIpi(void) { CLEAR_CSR(mie, MIP_MSIP); return 0; } int EnableHwplicIrq(plic_irq_t irq_number) { unsigned long core_id = 0; if (PLIC_NUM_SOURCES < irq_number || 0 > irq_number) return -1; uint32_t current = plic->target_enables.target[core_id].enable[irq_number / 32]; current |= (uint32_t)1 << (irq_number % 32); plic->target_enables.target[core_id].enable[irq_number / 32] = current; return 0; } int DisableHwplicIrq(plic_irq_t irq_number) { unsigned long core_id = 0; if (PLIC_NUM_SOURCES < irq_number || 0 > irq_number) return -1; uint32_t current = plic->target_enables.target[core_id].enable[irq_number / 32]; current &= ~((uint32_t)1 << (irq_number % 32)); plic->target_enables.target[core_id].enable[irq_number / 32] = current; return 0; } void InitHwinterrupt(void) { int idx; int cpuid; cpuid = current_coreid(); for (idx = 0; idx < ((PLIC_NUM_SOURCES + 32u) / 32u); idx ++) plic->target_enables.target[cpuid].enable[idx] = 0; for (idx = 0; idx < PLIC_NUM_SOURCES; idx++) plic->source_priorities.priority[idx] = 0; plic->targets.target[cpuid].priority_threshold = 0; SET_CSR(mie, MIP_MEIP); } void InitHwSecondaryInterrupt(void) { int idx; int cpuid; cpuid = current_coreid(); for (idx = 0; idx < ((PLIC_NUM_SOURCES + 32u) / 32u); idx ++) plic->target_enables.target[cpuid].enable[idx] = 0; plic->targets.target[cpuid].priority_threshold = 0; SET_CSR(mie, MIP_MEIP); } int32 ArchEnableHwIrq(uint32 irq_num) { plic_set_priority(irq_num, 1); EnableHwplicIrq(irq_num); } int32 ArchDisableHwIrq(uint32 irq_num) { DisableHwplicIrq(irq_num); } __attribute__((weak)) void PlicIrqHandle(plic_irq_t irq) { KPrintf("UN-handled interrupt %d occurred!!!\n", irq); return ; } uintptr_t HandleIrqMExt(uintptr_t cause, uintptr_t epc) { if (READ_CSR(mip) & MIP_MEIP) { uint64_t core_id = current_coreid(); uint64_t ie_flag = READ_CSR(mie); uint32_t int_num = plic->targets.target[core_id].claim_complete; uint32_t int_threshold = plic->targets.target[core_id].priority_threshold; plic->targets.target[core_id].priority_threshold = plic->source_priorities.priority[int_num]; CLEAR_CSR(mie, MIP_MTIP | MIP_MSIP); isrManager.done->handleIrq(int_num); plic->targets.target[core_id].claim_complete = int_num; SET_CSR(mstatus, MSTATUS_MPIE | MSTATUS_MPP); WRITE_CSR(mie, ie_flag); plic->targets.target[core_id].priority_threshold = int_threshold; } return epc; } struct ExceptionStackFrame { uint64_t x1; uint64_t x2; uint64_t x3; uint64_t x4; uint64_t x5; uint64_t x6; uint64_t x7; uint64_t x8; uint64_t x9; uint64_t x10; uint64_t x11; uint64_t x12; uint64_t x13; uint64_t x14; uint64_t x15; uint64_t x16; uint64_t x17; uint64_t x18; uint64_t x19; uint64_t x20; uint64_t x21; uint64_t x22; uint64_t x23; uint64_t x24; uint64_t x25; uint64_t x26; uint64_t x27; uint64_t x28; uint64_t x29; uint64_t x30; uint64_t x31; }; void PrintStackFrame(uintptr_t * sp) { struct ExceptionStackFrame * esf = (struct ExceptionStackFrame *)(sp+1); KPrintf("\n=================================================================\n"); KPrintf("x1 (ra : Return address ) ==> 0x%08x%08x\n", esf->x1 >> 32 , esf->x1 & UINT32_MAX); KPrintf("x2 (sp : Stack pointer ) ==> 0x%08x%08x\n", esf->x2 >> 32 , esf->x2 & UINT32_MAX); KPrintf("x3 (gp : Global pointer ) ==> 0x%08x%08x\n", esf->x3 >> 32 , esf->x3 & UINT32_MAX); KPrintf("x4 (tp : Task pointer ) ==> 0x%08x%08x\n", esf->x4 >> 32 , esf->x4 & UINT32_MAX); KPrintf("x5 (t0 : Temporary ) ==> 0x%08x%08x\n", esf->x5 >> 32 , esf->x5 & UINT32_MAX); KPrintf("x6 (t1 : Temporary ) ==> 0x%08x%08x\n", esf->x6 >> 32 , esf->x6 & UINT32_MAX); KPrintf("x7 (t2 : Temporary ) ==> 0x%08x%08x\n", esf->x7 >> 32 , esf->x7 & UINT32_MAX); KPrintf("x8 (s0/fp: Save register,frame pointer ) ==> 0x%08x%08x\n", esf->x8 >> 32 , esf->x8 & UINT32_MAX); KPrintf("x9 (s1 : Save register ) ==> 0x%08x%08x\n", esf->x9 >> 32 , esf->x9 & UINT32_MAX); KPrintf("x10(a0 : Function argument,return value) ==> 0x%08x%08x\n", esf->x10 >> 32 , esf->x10 & UINT32_MAX); KPrintf("x11(a1 : Function argument,return value) ==> 0x%08x%08x\n", esf->x11 >> 32 , esf->x11 & UINT32_MAX); KPrintf("x12(a2 : Function argument ) ==> 0x%08x%08x\n", esf->x12 >> 32 , esf->x12 & UINT32_MAX); KPrintf("x13(a3 : Function argument ) ==> 0x%08x%08x\n", esf->x13 >> 32 , esf->x13 & UINT32_MAX); KPrintf("x14(a4 : Function argument ) ==> 0x%08x%08x\n", esf->x14 >> 32 , esf->x14 & UINT32_MAX); KPrintf("x15(a5 : Function argument ) ==> 0x%08x%08x\n", esf->x15 >> 32 , esf->x15 & UINT32_MAX); KPrintf("x16(a6 : Function argument ) ==> 0x%08x%08x\n", esf->x16 >> 32 , esf->x16 & UINT32_MAX); KPrintf("x17(a7 : Function argument ) ==> 0x%08x%08x\n", esf->x17 >> 32 , esf->x17 & UINT32_MAX); KPrintf("x18(s2 : Save register ) ==> 0x%08x%08x\n", esf->x18 >> 32 , esf->x18 & UINT32_MAX); KPrintf("x19(s3 : Save register ) ==> 0x%08x%08x\n", esf->x19 >> 32 , esf->x19 & UINT32_MAX); KPrintf("x20(s4 : Save register ) ==> 0x%08x%08x\n", esf->x20 >> 32 , esf->x20 & UINT32_MAX); KPrintf("x21(s5 : Save register ) ==> 0x%08x%08x\n", esf->x21 >> 32 , esf->x21 & UINT32_MAX); KPrintf("x22(s6 : Save register ) ==> 0x%08x%08x\n", esf->x22 >> 32 , esf->x22 & UINT32_MAX); KPrintf("x23(s7 : Save register ) ==> 0x%08x%08x\n", esf->x23 >> 32 , esf->x23 & UINT32_MAX); KPrintf("x24(s8 : Save register ) ==> 0x%08x%08x\n", esf->x24 >> 32 , esf->x24 & UINT32_MAX); KPrintf("x25(s9 : Save register ) ==> 0x%08x%08x\n", esf->x25 >> 32 , esf->x25 & UINT32_MAX); KPrintf("x26(s10 : Save register ) ==> 0x%08x%08x\n", esf->x26 >> 32 , esf->x26 & UINT32_MAX); KPrintf("x27(s11 : Save register ) ==> 0x%08x%08x\n", esf->x27 >> 32 , esf->x27 & UINT32_MAX); KPrintf("x28(t3 : Temporary ) ==> 0x%08x%08x\n", esf->x28 >> 32 , esf->x28 & UINT32_MAX); KPrintf("x29(t4 : Temporary ) ==> 0x%08x%08x\n", esf->x29 >> 32 , esf->x29 & UINT32_MAX); KPrintf("x30(t5 : Temporary ) ==> 0x%08x%08x\n", esf->x30 >> 32 , esf->x30 & UINT32_MAX); KPrintf("x31(t6 : Temporary ) ==> 0x%08x%08x\n", esf->x31 >> 32 , esf->x31 & UINT32_MAX); KPrintf("=================================================================\n"); } #ifdef TASK_ISOLATION uintptr_t HandleTrap(uintptr_t mcause, uintptr_t epc, uintptr_t * sp) { int cause = mcause & CAUSE_MACHINE_IRQ_REASON_MASK; if (mcause & (1UL << 63)) { isrManager.done->incCounter(); switch (cause) { case IRQ_M_SOFT: { uint64_t core_id = current_coreid(); clint_ipi_clear(core_id); DO_KTASK_ASSIGN; } break; case IRQ_M_EXT: HandleIrqMExt(mcause, epc); break; case IRQ_M_TIMER: TickIsr(); break; } isrManager.done->decCounter(); } else { x_base temp; temp = DISABLE_INTERRUPT(); KTaskDescriptorType tid; extern long ShowTask(); tid = GetKTaskDescriptor(); if(cause == CAUSE_USER_ECALL) { tid->task_dync_sched_member.isolation_status = 1; sp[0] += 4; unsigned long service_num = (unsigned long)(sp[10]); //KPrintf("Environment call from U-mode,service_num: %ld\n",service_num); uint8_t param_num = g_service_table[service_num].param_num; uintptr_t *param = sp + 11; ENABLE_INTERRUPT(temp); sp[10] = g_service_table[service_num].fun(service_num,param,param_num) ; tid->task_dync_sched_member.isolation_status = 0; } else if (cause == CAUSE_MACHINE_ECALL) { unsigned long service_num = (unsigned long)(sp[10]); KPrintf("Environment call from M-mode, task:%s, flag: %d,service_num: %d\n \n",tid->task_base_info.name,tid->task_dync_sched_member.isolation_flag, service_num); sp[0] += 4; ENABLE_INTERRUPT(temp); } else { KPrintf("\nException:\n"); tid = GetKTaskDescriptor(); switch (cause) { case CAUSE_MISALIGNED_FETCH: KPrintf("Instruction address misaligned"); break; case CAUSE_FAULT_FETCH: KPrintf("Instruction access fault"); break; case CAUSE_ILLEGAL_INSTRUCTION: KPrintf("Illegal instruction"); break; case CAUSE_BREAKPOINT: KPrintf("Breakpoint"); break; case CAUSE_MISALIGNED_LOAD: KPrintf("Load address misaligned"); break; case CAUSE_FAULT_LOAD: KPrintf("Load access fault"); break; case CAUSE_MISALIGNED_STORE: KPrintf("Store address misaligned"); break; case CAUSE_FAULT_STORE: KPrintf("Store access fault"); break; case CAUSE_SUPERVISOR_ECALL: KPrintf("Environment call from S-mode"); break; case CAUSE_HYPERVISOR_ECALL: KPrintf("Environment call from H-mode"); break; default: KPrintf("Uknown exception : %08lX", cause); break; } KPrintf("\n"); PrintStackFrame(sp); KPrintf("exception pc => 0x%08x\n", epc); KPrintf("current thread: %.*s\n", NAME_NUM_MAX, tid->task_base_info.name); #ifdef TOOL_SHELL ShowTask(); #endif while (RET_TRUE); } } return epc; } #else uintptr_t HandleTrap(uintptr_t mcause, uintptr_t epc, uintptr_t * sp) { int cause = mcause & CAUSE_MACHINE_IRQ_REASON_MASK; if (mcause & (1UL << 63)) { isrManager.done->incCounter(); switch (cause) { case IRQ_M_SOFT: { uint64_t core_id = current_coreid(); clint_ipi_clear(core_id); DO_KTASK_ASSIGN; } break; case IRQ_M_EXT: HandleIrqMExt(mcause, epc); break; case IRQ_M_TIMER: TickIsr(); break; } isrManager.done->decCounter(); } else { KTaskDescriptorType tid; extern long ShowTask(); DISABLE_INTERRUPT(); tid = GetKTaskDescriptor(); KPrintf("\nException:\n"); switch (cause) { case CAUSE_MISALIGNED_FETCH: KPrintf("Instruction address misaligned"); break; case CAUSE_FAULT_FETCH: KPrintf("Instruction access fault"); break; case CAUSE_ILLEGAL_INSTRUCTION: KPrintf("Illegal instruction"); break; case CAUSE_BREAKPOINT: KPrintf("Breakpoint"); break; case CAUSE_MISALIGNED_LOAD: KPrintf("Load address misaligned"); break; case CAUSE_FAULT_LOAD: KPrintf("Load access fault"); break; case CAUSE_MISALIGNED_STORE: KPrintf("Store address misaligned"); break; case CAUSE_FAULT_STORE: KPrintf("Store access fault"); break; case CAUSE_USER_ECALL: KPrintf("Environment call from U-mode"); break; case CAUSE_SUPERVISOR_ECALL: KPrintf("Environment call from S-mode"); break; case CAUSE_HYPERVISOR_ECALL: KPrintf("Environment call from H-mode"); break; case CAUSE_MACHINE_ECALL: KPrintf("Environment call from M-mode"); break; default: KPrintf("Uknown exception : %08lX", cause); break; } KPrintf("\n"); PrintStackFrame(sp); KPrintf("exception pc => 0x%08x\n", epc); KPrintf("current task: %.*s\n", NAME_NUM_MAX, tid->task_base_info.name); #ifdef TOOL_SHELL ShowTask(); #endif while (RET_TRUE); } return epc; } #endif