xiuos3/arch/risc-v/k210/interrupt.c

423 lines
14 KiB
C

/* 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 <clint.h>
#include <interrupt.h>
#include <plic.h>
#include <xs_assign.h>
#include <xs_base.h>
#include <xs_isr.h>
#include <xs_ktask.h>
#ifdef TASK_ISOLATION
#include <xs_service.h>
#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 InitHwScondaryInterrupt(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