First commit XiUOS

This commit is contained in:
xuetest
2021-04-28 17:49:18 +08:00
commit 6001051eb7
1331 changed files with 433955 additions and 0 deletions
+9
View File
@@ -0,0 +1,9 @@
SRC_FILES +=riscv64_switch.c
SRC_FILES +=prepare_rhwstack.c
ifeq ($(CONFIG_TASK_ISOLATION),y)
SRC_FILES += pmp.c
endif
include $(KERNEL_ROOT)/compiler.mk
+126
View File
@@ -0,0 +1,126 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "register_para.h"
.macro ZERO_X_REGISTERS
xor zero, zero, zero
xor ra, ra, ra
xor sp, sp, sp
xor gp, gp, gp
xor tp, tp, tp
xor t0, t0, t0
xor t1, t1, t1
xor t2, t2, t2
xor s0, s0, s0
xor s1, s1, s1
xor a0, a0, a0
xor a1, a1, a1
xor a2, a2, a2
xor a3, a3, a3
xor a4, a4, a4
xor a5, a5, a5
xor a6, a6, a6
xor a7, a7, a7
xor s2, s2, s2
xor s3, s3, s3
xor s4, s4, s4
xor s5, s5, s5
xor s6, s6, s6
xor s7, s7, s7
xor s8, s8, s8
xor s9, s9, s9
xor s10, s10, s10
xor s11, s11, s11
xor t3, t3, t3
xor t4, t4, t4
xor t5, t5, t5
xor t6, t6, t6
.endm
.macro ZERO_F_REGISTERS
FSubDS f0, f0, f0
FSubDS f1, f1, f1
FSubDS f2, f2, f2
FSubDS f3, f3, f3
FSubDS f4, f4, f4
FSubDS f5, f5, f5
FSubDS f6, f6, f6
FSubDS f7, f7, f7
FSubDS f8, f8, f8
FSubDS f9, f9, f9
FSubDS f10,f10,f10
FSubDS f11,f11,f11
FSubDS f12,f12,f12
FSubDS f13,f13,f13
FSubDS f14,f14,f14
FSubDS f15,f15,f15
FSubDS f16,f16,f16
FSubDS f17,f17,f17
FSubDS f18,f18,f18
FSubDS f19,f19,f19
FSubDS f20,f20,f20
FSubDS f21,f21,f21
FSubDS f22,f22,f22
FSubDS f23,f23,f23
FSubDS f24,f24,f24
FSubDS f25,f25,f25
FSubDS f26,f26,f26
FSubDS f27,f27,f27
FSubDS f28,f28,f28
FSubDS f29,f29,f29
FSubDS f30,f30,f30
FSubDS f31,f31,f31
.endm
.macro SAVE_X_REGISTERS
addi sp, sp, -32 * RegLength
StoreD ra, 1 * RegLength(sp)
csrr ra, mstatus
StoreD ra, 2 * RegLength(sp)
csrr ra, mepc
StoreD ra, 0 * RegLength(sp)
StoreD tp, 4 * RegLength(sp)
StoreD t0, 5 * RegLength(sp)
StoreD t1, 6 * RegLength(sp)
StoreD t2, 7 * RegLength(sp)
StoreD s0, 8 * RegLength(sp)
StoreD s1, 9 * RegLength(sp)
StoreD a0, 10 * RegLength(sp)
StoreD a1, 11 * RegLength(sp)
StoreD a2, 12 * RegLength(sp)
StoreD a3, 13 * RegLength(sp)
StoreD a4, 14 * RegLength(sp)
StoreD a5, 15 * RegLength(sp)
StoreD a6, 16 * RegLength(sp)
StoreD a7, 17 * RegLength(sp)
StoreD s2, 18 * RegLength(sp)
StoreD s3, 19 * RegLength(sp)
StoreD s4, 20 * RegLength(sp)
StoreD s5, 21 * RegLength(sp)
StoreD s6, 22 * RegLength(sp)
StoreD s7, 23 * RegLength(sp)
StoreD s8, 24 * RegLength(sp)
StoreD s9, 25 * RegLength(sp)
StoreD s10, 26 * RegLength(sp)
StoreD s11, 27 * RegLength(sp)
StoreD t3, 28 * RegLength(sp)
StoreD t4, 29 * RegLength(sp)
StoreD t5, 30 * RegLength(sp)
StoreD t6, 31 * RegLength(sp)
.endm
+324
View File
@@ -0,0 +1,324 @@
/****************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you 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 kswitch.h
* @brief risc-v ecall function
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
/*************************************************
File name: kswitch.h
Description: risc-v ecall function
Others: take incubator-nuttx arch/risc-v/include/rv64gc/syscall.h for references
https://github.com/apache/incubator-nuttx/tree/master/arch/risc-v/include/rv64gc
History:
1. Date: 2021-04-25
Author: AIIT XUOS Lab
Modification:
1. Modify function name for a unified
2. Add some functions when there is no system call
*************************************************/
#ifndef __XS_RISC_V_KSWITCH_H__
#define __XS_RISC_V_KSWITCH_H__
#include <stdint.h>
#include "../../../kernel/include/xs_service.h"
#ifdef TASK_ISOLATION
/****************************************************************************
* Name: KSwitch0
*
* Description:
* ecall with zero parameters.
*
****************************************************************************/
static inline uintptr_t KSwitch0(unsigned int nbr)
{
register long r0 asm("a0") = (long)(nbr);
asm volatile
(
"ecall"
:: "r"(r0)
);
asm volatile("nop" : "=r"(r0));
return r0;
}
/****************************************************************************
* Name: KSwitch1
*
* Description:
* ecall with one parameters.
*
****************************************************************************/
static inline uintptr_t KSwitch1(unsigned int nbr, uintptr_t parm1)
{
register long r0 asm("a0") = (long)(nbr);
register long r1 asm("a1") = (long)(parm1);
asm volatile
(
"ecall"
:: "r"(r0), "r"(r1)
);
asm volatile("nop" : "=r"(r0));
return r0;
}
/****************************************************************************
* Name: KSwitch2
*
* Description:
* ecall with two parameters.
*
****************************************************************************/
static inline uintptr_t KSwitch2(unsigned int nbr, uintptr_t parm1,
uintptr_t parm2)
{
register long r0 asm("a0") = (long)(nbr);
register long r1 asm("a1") = (long)(parm1);
register long r2 asm("a2") = (long)(parm2);
asm volatile
(
"ecall"
:: "r"(r0), "r"(r1), "r"(r2)
);
asm volatile("nop" : "=r"(r0));
return r0;
}
/****************************************************************************
* Name: KSwitch3
*
* Description:
* ecall with three parameters.
*
****************************************************************************/
static inline uintptr_t KSwitch3(unsigned int knum, uintptr_t arg1,
uintptr_t arg2, uintptr_t arg3)
{
register long reg0 asm("a0") = (long)(knum);
register long reg1 asm("a1") = (long)(arg1);
register long reg2 asm("a2") = (long)(arg2);
register long reg3 asm("a3") = (long)(arg3);
asm volatile
(
"ecall"
:: "r"(reg0), "r"(reg1), "r"(reg2), "r"(reg3)
);
asm volatile("nop" : "=r"(reg0));
return reg0;
}
/****************************************************************************
* Name: KSwitch4
*
* Description:
* ecall with four parameters.
*
****************************************************************************/
static inline uintptr_t KSwitch4(unsigned int nbr, uintptr_t parm1,
uintptr_t parm2, uintptr_t parm3,
uintptr_t parm4)
{
register long r0 asm("a0") = (long)(nbr);
register long r1 asm("a1") = (long)(parm1);
register long r2 asm("a2") = (long)(parm2);
register long r3 asm("a3") = (long)(parm3);
register long r4 asm("a4") = (long)(parm4);
asm volatile
(
"ecall"
:: "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4)
);
asm volatile("nop" : "=r"(r0));
return r0;
}
/****************************************************************************
* Name: KSwitch5
*
* Description:
* ecall with five parameters.
*
****************************************************************************/
static inline uintptr_t KSwitch5(unsigned int nbr, uintptr_t parm1,
uintptr_t parm2, uintptr_t parm3,
uintptr_t parm4, uintptr_t parm5)
{
register long r0 asm("a0") = (long)(nbr);
register long r1 asm("a1") = (long)(parm1);
register long r2 asm("a2") = (long)(parm2);
register long r3 asm("a3") = (long)(parm3);
register long r4 asm("a4") = (long)(parm4);
register long r5 asm("a5") = (long)(parm5);
asm volatile
(
"ecall"
:: "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5)
);
asm volatile("nop" : "=r"(r0));
return r0;
}
/****************************************************************************
* Name: KSwitch6
*
* Description:
* ecall with six parameters.
*
****************************************************************************/
static inline uintptr_t KSwitch6(unsigned int nbr, uintptr_t parm1,
uintptr_t parm2, uintptr_t parm3,
uintptr_t parm4, uintptr_t parm5,
uintptr_t parm6)
{
register long r0 asm("a0") = (long)(nbr);
register long r1 asm("a1") = (long)(parm1);
register long r2 asm("a2") = (long)(parm2);
register long r3 asm("a3") = (long)(parm3);
register long r4 asm("a4") = (long)(parm4);
register long r5 asm("a5") = (long)(parm5);
register long r6 asm("a6") = (long)(parm6);
asm volatile
(
"ecall"
:: "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5), "r"(r6)
);
asm volatile("nop" : "=r"(r0));
return r0;
}
#else
static inline unsigned long KSwitch0(unsigned int knum)
{
uintptr_t param[1] = {0};
uint8_t num = 0;
SERVICETABLE[knum].fun(knum, param, num);
}
static inline unsigned long KSwitch1(unsigned int knum, unsigned long arg1)
{
uintptr_t param[1] = {0};
uint8_t num = 0;
param[0] = arg1;
SERVICETABLE[knum].fun(knum, param, num );
}
static inline unsigned long KSwitch2(unsigned int knum, unsigned long arg1,
unsigned long arg2)
{
uintptr_t param[2] = {0};
uint8_t num = 0;
param[0] = arg1;
param[1] = arg2;
SERVICETABLE[knum].fun(knum, param, num );
}
static inline unsigned long KSwitch3(unsigned int knum, unsigned long arg1,
unsigned long arg2, unsigned long arg3)
{
uintptr_t param[3] = {0};
uint8_t num = 0;
param[0] = arg1;
param[1] = arg2;
param[2] = arg3;
SERVICETABLE[knum].fun(knum, param, num );
}
static inline unsigned long KSwitch4(unsigned int knum, unsigned long arg1,
unsigned long arg2, unsigned long arg3,
unsigned long arg4)
{
uintptr_t param[4] = {0};
uint8_t num = 0;
param[0] = arg1;
param[1] = arg2;
param[2] = arg3;
param[3] = arg4;
SERVICETABLE[knum].fun(knum, param, num );
}
static inline unsigned long KSwitch5(unsigned int knum, unsigned long arg1,
unsigned long arg2, unsigned long arg3,
unsigned long arg4, unsigned long arg5)
{
uintptr_t param[5] = {0};
uint8_t num = 0;
param[0] = arg1;
param[1] = arg2;
param[2] = arg3;
param[3] = arg4;
param[4] = arg5;
SERVICETABLE[knum].fun(knum, param, num );
}
static inline unsigned long KSwitch6(unsigned int knum, unsigned long arg1,
unsigned long arg2, unsigned long arg3,
unsigned long arg4, unsigned long arg5,
unsigned long arg6)
{
uintptr_t param[6] = {0};
uint8_t num = 0;
param[0] = arg1;
param[1] = arg2;
param[2] = arg3;
param[3] = arg4;
param[4] = arg5;
param[5] = arg6;
SERVICETABLE[knum].fun(knum, param, num );
}
#endif
#endif
+517
View File
@@ -0,0 +1,517 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "pmp.h"
#include <board.h>
#include <encoding.h>
#include <xs_isolation.h>
#define USER_TEXT_START (uintptr_t)( USERSPACE )
#define USER_TEXT_END (uintptr_t)( USERSPACE->us_textend )
#define USER_SRAM_START (uintptr_t)( USERSPACE->us_datastart )
#define USER_SRAM_END (uintptr_t)( USERSPACE->us_bssend )
/**
* This function add a pmp tor region to task pmp config
*
* @param task_pmp the task pmp config structure
* @param start the memory start address
* @param size the memory address size
* @param type the memory type
*
* @return EOK
*/
x_err_t PmpAddTorRegion(void *task_pmp, x_ubase start , size_t size , uint8_t type )
{
if( task_pmp == NONE)
return -ERROR;
if (size == 0)
return EOK;
struct Pmp *pmp;
pmp = (struct Pmp *)task_pmp ;
struct PmpRegionTor *region ;
region = (struct PmpRegionTor *)x_malloc(sizeof(struct PmpRegionTor ));
if (region == NONE)
return -ENOMEM;
uint8_t flag = 0;
switch (type)
{
case REGION_TYPE_CODE:
flag = PMP_R | PMP_X ;
break;
case REGION_TYPE_DATA :
flag = PMP_R | PMP_W ;
break;
case REGION_TYPE_BSS :
flag = PMP_R | PMP_W ;
break;
case REGION_TYPE_HEAP :
flag = PMP_R | PMP_W ;
break;
default:
break;
}
memset(region,0,sizeof(struct PmpRegionTor ));
InitDoubleLinkList(&(region->link));
region->region_type = PMP_TOR_TYPE;
region->start = start;
region->end = start + size ;
region->entry[0].pmpcfg = PMP_NA4 | flag;
region->entry[0].pmpaddr = TO_PMP_ADDR(start);
region->entry[1].pmpcfg = PMP_TOR | flag;
region->entry[1].pmpaddr = TO_PMP_ADDR(ALIGN_MEN_UP(region->end,4));
if (pmp->count <= PMP_MAX_ENTRY_NUMBER - 2 )
{
DoubleLinkListInsertNodeAfter(&pmp->tor_list, &region->link);
pmp->count = pmp->count + 2 ;
}else
{
struct PmpRegionTor *node ;
node = (struct PmpRegionTor *)pmp->tor_list.node_next ;
DoubleLinkListRmNode(&(node->link));
DoubleLinkListInsertNodeAfter(&pmp->tor_list, &region->link);
DoubleLinkListInsertNodeAfter(&pmp->tor_swap_list, &node->link);
node->swap_count ++;
}
return EOK;
}
/**
* This function free a pmp region
*
* @param task_pmp the task pmp config structure
* @param addr the memory address
*
* @return EOK
*/
x_err_t PmpClearRegion(void *task_pmp, x_ubase addr)
{
// KPrintf("PmpClearRegion\n");
if( task_pmp == NONE)
return -ERROR;
struct Pmp *pmp;
pmp = (struct Pmp *)task_pmp ;
struct PmpRegionTor *tor_node = NONE;
DoubleLinklistType *link = NONE;
if (!IsDoubleLinkListEmpty(&pmp->tor_list)) {
DOUBLE_LINKLIST_FOR_EACH(link, &pmp->tor_list) {
tor_node = CONTAINER_OF(link, struct PmpRegionTor, link);
if ( addr = tor_node->start ){
pmp->count = pmp->count -2;
goto __free ;
}
}
}
if (!IsDoubleLinkListEmpty(&pmp->tor_swap_list)) {
DOUBLE_LINKLIST_FOR_EACH(link, &pmp->tor_swap_list) {
tor_node = CONTAINER_OF(link, struct PmpRegionTor, link);
if ( addr = tor_node->start ) {
goto __free;
}
}
}
__free:
DoubleLinkListRmNode(&(tor_node->link));
x_free(tor_node);
return EOK;
}
/**
* This function init a task pmp config structure and add some pmp region
*
* @param task_pmp the task pmp config structure
* @param stack_start the task stack address
* @param stack_size the task stack size
*
* @return EOK
*/
x_err_t PmpInitIsolation(void **task_pmp, x_ubase stack_start , size_t stack_size)
{
struct Pmp *pmp ;
pmp = (struct Pmp *)x_malloc(sizeof(struct Pmp));
if(pmp == NONE)
return -ENOMEMORY;
memset(pmp,0,sizeof(struct Pmp));
InitDoubleLinkList(&(pmp->tor_list));
InitDoubleLinkList(&(pmp->tor_swap_list));
uint8_t index = 0;
// text
if (USER_TEXT_END - USER_TEXT_START > 0 ) {
pmp->pmp_entry_reserve[index].pmpcfg = PMP_NA4 | PMP_R | PMP_X ;
pmp->pmp_entry_reserve[index].pmpaddr = TO_PMP_ADDR(USER_TEXT_START);
pmp->pmp_entry_reserve[index + 1].pmpcfg = PMP_TOR | PMP_R | PMP_X ;
pmp->pmp_entry_reserve[index + 1].pmpaddr = TO_PMP_ADDR(ALIGN_MEN_UP(USER_TEXT_END,4));
index = index + 2 ;
pmp->count = pmp->count + 2;
pmp->reserve = pmp->reserve + 2;
}
// data & bss
if (USER_SRAM_END - USER_SRAM_START > 0 ) {
pmp->pmp_entry_reserve[index].pmpcfg = PMP_NA4 | PMP_R | PMP_W ;
pmp->pmp_entry_reserve[index].pmpaddr = TO_PMP_ADDR(USER_SRAM_START);
pmp->pmp_entry_reserve[index + 1].pmpcfg = PMP_TOR | PMP_R | PMP_W ;
pmp->pmp_entry_reserve[index + 1].pmpaddr = TO_PMP_ADDR(ALIGN_MEN_UP(USER_SRAM_END,4));
index = index + 2 ;
pmp->count = pmp->count + 2;
pmp->reserve = pmp->reserve + 2;
}
if (stack_size > 0 ) {
pmp->pmp_entry_reserve[index].pmpcfg = PMP_NA4 | PMP_R | PMP_W | PMP_X ;
pmp->pmp_entry_reserve[index].pmpaddr = TO_PMP_ADDR(stack_start);
pmp->pmp_entry_reserve[index + 1].pmpcfg = PMP_TOR | PMP_R | PMP_W | PMP_X ;
pmp->pmp_entry_reserve[index + 1].pmpaddr = TO_PMP_ADDR(ALIGN_MEN_UP((stack_start + stack_size),4));
pmp->count = pmp->count + 2;
pmp->reserve = pmp->reserve + 2;
}
*task_pmp = (void *)pmp;
return EOK;
}
/**
* This function free task pmp config structure
*
* @param task_pmp the task pmp config structure
*
*/
void PmpFree(void *task_pmp){
// KPrintf("pmp free \n");
if( task_pmp == NONE)
return ;
struct Pmp *pmp;
pmp = (struct Pmp *)task_pmp ;
struct PmpRegionTor *tor_node = NONE;
DoubleLinklistType *link = NONE;
if (!IsDoubleLinkListEmpty(&(pmp->tor_list)) ){
DOUBLE_LINKLIST_FOR_EACH(link, &pmp->tor_list)
{
tor_node = CONTAINER_OF(link, struct PmpRegionTor, link);
DoubleLinkListRmNode(&(tor_node->link));
x_free(tor_node);
}
}
if (!IsDoubleLinkListEmpty(&pmp->tor_swap_list)) {
DOUBLE_LINKLIST_FOR_EACH(link, &pmp->tor_swap_list) {
tor_node = CONTAINER_OF(link, struct PmpRegionTor, link);
DoubleLinkListRmNode(&(tor_node->link));
x_free(tor_node);
}
}
x_free(pmp);
}
/**
* This function write value to pmp config register
* @param index pmpcfg register index
* @param value pmpcfg register value
*
*/
void WritePmpcfg(uint8_t index , x_ubase value)
{
if ( index == 0 ) {
WRITE_CSR(pmpcfg0, value);
}else if ( index == 1 ) {
WRITE_CSR(pmpcfg1, value);
}else if ( index == 2 ) {
WRITE_CSR(pmpcfg2, value);
}else if ( index == 3 ) {
WRITE_CSR(pmpcfg3, value);
}
}
/**
* This function write value to pmp addr register
* @param index pmpaddr register index
* @param value pmpaddr register value
*
*/
void WritePmpaddr(uint8_t index, x_ubase value)
{
if ( index == 0 ) {
WRITE_CSR(pmpaddr0, value);
}else if ( index == 1 ) {
WRITE_CSR(pmpaddr1, value);
}else if ( index == 2 ) {
WRITE_CSR(pmpaddr2, value);
}else if ( index == 3 ) {
WRITE_CSR(pmpaddr3, value);
}else if ( index == 4 ) {
WRITE_CSR(pmpaddr4, value);
}else if ( index == 5 ) {
WRITE_CSR(pmpaddr5, value);
}else if ( index == 6 ) {
WRITE_CSR(pmpaddr6, value);
}else if ( index == 7 ) {
WRITE_CSR(pmpaddr7, value);
}else if ( index == 8 ) {
WRITE_CSR(pmpaddr8, value);
}else if ( index == 9 ) {
WRITE_CSR(pmpaddr9, value);
}else if ( index == 10 ) {
WRITE_CSR(pmpaddr10, value);
}else if ( index == 11 ) {
WRITE_CSR(pmpaddr11, value);
}else if ( index == 12 ) {
WRITE_CSR(pmpaddr12, value);
}else if ( index == 13 ) {
WRITE_CSR(pmpaddr13, value);
}else if ( index == 14 ) {
WRITE_CSR(pmpaddr14, value);
}else if ( index == 15 ) {
WRITE_CSR(pmpaddr15, value);
}
}
/**
* This function handle user task access memory fault, check addr in pmp swap list or not ,if addr is in
* pmp swap list, swap in to pmp list.
*
* @param task_pmp the task pmp config structure
* @param addr access addr when fault
*
* @return EOK
*/
x_bool PmpAccessFaultHandle(void *task_pmp, x_ubase addr)
{
if( task_pmp == NONE)
return RET_FALSE;
struct Pmp *pmp;
pmp = (struct Pmp *)task_pmp ;
x_bool ret = RET_FALSE;
uint8_t region_type;
DoubleLinklistType *link = NONE;
struct PmpRegionTor *tor_node = NONE;
if (!IsDoubleLinkListEmpty(&pmp->tor_swap_list) ) {
DOUBLE_LINKLIST_FOR_EACH(link, &pmp->tor_swap_list) {
tor_node = CONTAINER_OF(link, struct PmpRegionTor, link);
if ( addr >= tor_node->start && addr <= (tor_node->end) ) {
region_type = PMP_TOR;
goto __swap;
}
}
}
goto __exit;
__swap:
if ( region_type = PMP_TOR ) {
if( pmp->count < PMP_MAX_ENTRY_NUMBER - 2) {
DoubleLinkListRmNode(&(tor_node->link));
DoubleLinkListInsertNodeBefore(&pmp->tor_list, &tor_node->link);
pmp->count = pmp->count + 2;
} else {
struct PmpRegionTor *swap_node;
swap_node = (struct PmpRegionTor *)pmp->tor_list.node_next;
DoubleLinkListRmNode(&(swap_node->link));
DoubleLinkListRmNode(&(tor_node->link));
DoubleLinkListInsertNodeBefore(&pmp->tor_list, &tor_node->link);
DoubleLinkListInsertNodeBefore(&pmp->tor_swap_list, &swap_node->link);
swap_node->swap_count ++;
}
}
ret = RET_TRUE;
__exit:
return ret;
}
#if defined(ARCH_RISCV64)
/**
* This function clear pmp registers.
*/
void PmpClear(void)
{
WRITE_CSR(pmpcfg0, 0);
WRITE_CSR(pmpcfg2, 0);
WRITE_CSR(pmpaddr0, 0);
WRITE_CSR(pmpaddr1, 0);
WRITE_CSR(pmpaddr2, 0);
WRITE_CSR(pmpaddr3, 0);
WRITE_CSR(pmpaddr4, 0);
WRITE_CSR(pmpaddr5, 0);
WRITE_CSR(pmpaddr6, 0);
WRITE_CSR(pmpaddr7, 0);
WRITE_CSR(pmpaddr8, 0);
WRITE_CSR(pmpaddr9, 0);
WRITE_CSR(pmpaddr10, 0);
WRITE_CSR(pmpaddr11, 0);
WRITE_CSR(pmpaddr12, 0);
WRITE_CSR(pmpaddr13, 0);
WRITE_CSR(pmpaddr14, 0);
WRITE_CSR(pmpaddr15, 0);
}
/**
* This function load task pmp config to pmp register.
* @param task_pmp the task pmp config structure
*
*/
void PmpLoad(void *task_pmp)
{
// KPrintf("pmpLoad \n");
if( task_pmp == NONE)
return ;
struct Pmp *pmp;
pmp = (struct Pmp *)task_pmp ;
PmpClear();
uint8_t index = 0;
x_ubase pmpcfg0 = 0 ;
x_ubase pmpcfg2 = 0 ;
for( int i = 0 ; i < pmp->reserve; i++){
pmpcfg0 |= pmp->pmp_entry_reserve[i].pmpcfg << ( index * 8) ;
WritePmpaddr(index , pmp->pmp_entry_reserve[i].pmpaddr );
index ++ ;
}
DoubleLinklistType *link = NONE;
struct PmpRegionTor *node2 = NONE;
if (!IsDoubleLinkListEmpty(&pmp->tor_list) ){
DOUBLE_LINKLIST_FOR_EACH(link, &pmp->tor_list)
{
node2 = CONTAINER_OF(link, struct PmpRegionTor, link);
WritePmpaddr(index ,node2->entry[0].pmpaddr );
if (index < 8)
pmpcfg0 |= node2->entry[0].pmpcfg << ( index * 8);
else
pmpcfg2 |= node2->entry[0].pmpcfg << ( (index - 8) * 8);
index ++;
WritePmpaddr(index ,node2->entry[1].pmpaddr );
if (index < 8)
pmpcfg0 |= node2->entry[1].pmpcfg << ( index * 8);
else
pmpcfg2 |= node2->entry[1].pmpcfg << ( (index - 8) * 8);
index ++;
}
}
WritePmpcfg(0, pmpcfg0 );
WritePmpcfg(2, pmpcfg2 );
}
#else
/**
* This function clear pmp registers.
*/
void PmpClear(void)
{
WRITE_CSR(pmpcfg0, 0);
WRITE_CSR(pmpcfg1, 0);
WRITE_CSR(pmpcfg2, 0);
WRITE_CSR(pmpcfg3, 0);
WRITE_CSR(pmpaddr0, 0);
WRITE_CSR(pmpaddr1, 0);
WRITE_CSR(pmpaddr2, 0);
WRITE_CSR(pmpaddr3, 0);
WRITE_CSR(pmpaddr4, 0);
WRITE_CSR(pmpaddr5, 0);
WRITE_CSR(pmpaddr6, 0);
WRITE_CSR(pmpaddr7, 0);
WRITE_CSR(pmpaddr8, 0);
WRITE_CSR(pmpaddr9, 0);
WRITE_CSR(pmpaddr10, 0);
WRITE_CSR(pmpaddr11, 0);
WRITE_CSR(pmpaddr12, 0);
WRITE_CSR(pmpaddr13, 0);
WRITE_CSR(pmpaddr14, 0);
WRITE_CSR(pmpaddr15, 0);
}
#define PMP_CFG_CONVERSE(a,b,c,d) ( ((uint32_t)(d) << 24) | ((uint32_t)(c) << 16) | ((uint32_t)(b) << 8) | (uint32_t)(a) )
/**
* This function load task pmp config to pmp register.
* @param task_pmp the task pmp config structure
*
*/
void PmpLoad(void *task_pmp)
{
// KPrintf("pmpLoad \n");
if( task_pmp == NONE)
return ;
struct Pmp *pmp;
pmp = (struct Pmp *)task_pmp ;
PmpClear();
uint8_t index = 0;
uint8_t pmpcfg[16] = { 0 } ;
uint32_t pmpcfg0 = 0 ;
uint32_t pmpcfg1 = 0 ;
uint32_t pmpcfg2 = 0 ;
uint32_t pmpcfg3 = 0 ;
for( int i = 0 ; i < pmp->reserve; i++){
pmpcfg[index] = pmp->pmp_entry_reserve[i].pmpcfg ;
WritePmpaddr(index , pmp->pmp_entry_reserve[i].pmpaddr );
index ++ ;
}
DoubleLinklistType *node = NONE;
struct PmpRegionTor *tor_node = NONE;
if (!IsDoubleLinkListEmpty(&(pmp->tor_list)) ){
DOUBLE_LINKLIST_FOR_EACH(node, &(pmp->tor_list))
{
tor_node = CONTAINER_OF(node, struct PmpRegionTor, link);
WritePmpaddr(index ,tor_node->entry[0].pmpaddr );
pmpcfg[index] = tor_node->entry[0].pmpcfg;
index ++;
WritePmpaddr(index ,tor_node->entry[1].pmpaddr );
pmpcfg[index] = tor_node->entry[1].pmpcfg;
index ++;
}
}
pmpcfg0 = PMP_CFG_CONVERSE(pmpcfg[0], pmpcfg[1], pmpcfg[2], pmpcfg[3]);
pmpcfg1 = PMP_CFG_CONVERSE(pmpcfg[4], pmpcfg[5], pmpcfg[6], pmpcfg[7]);
pmpcfg2 = PMP_CFG_CONVERSE(pmpcfg[8], pmpcfg[9], pmpcfg[10], pmpcfg[11]);
pmpcfg3 = PMP_CFG_CONVERSE(pmpcfg[12], pmpcfg[13], pmpcfg[14], pmpcfg[15]);
WritePmpcfg(0, pmpcfg0);
WritePmpcfg(1, pmpcfg1);
WritePmpcfg(2, pmpcfg2);
WritePmpcfg(3, pmpcfg3);
}
#endif
+93
View File
@@ -0,0 +1,93 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#ifndef PMP_H
#define PMP_H
#include <xs_klist.h>
#define PMP_MAX_ENTRY_NUMBER 16
#define PMP_ENTRY_RESERVE 6
#define PMP_ENTRY_MAX 255
#define PMP_R 0x01 /* Allow read */
#define PMP_W 0x02 /* Allow write */
#define PMP_X 0x04 /* Allow execute */
#define PMP_L 0x80 /* PMP entry is locked */
#define PMP_OFF 0x00 /* Null region */
#define PMP_TOR 0x08 /* Top of range */
#define PMP_NA4 0x10 /* Naturally aligned four-byte region */
#define PMP_NAPOT 0x18 /* Naturally aligned power-of-two region */
#define PMP_TOR_TYPE 0 /* Top of range */
#define PMP_NAPOT_TYPE 1 /* Naturally aligned power-of-two region */
#define PMP_SHIFT_ADDR 2
#define PMP_TYPE_MASK 0x18
#define TO_PMP_ADDR(addr) ((addr) >> PMP_SHIFT_ADDR)
#define FROM_PMP_ADDR(addr) ((addr) << PMP_SHIFT_ADDR)
#define TO_NAPOT_RANGE(size) (((size) - 1) >> 1)
#define TO_PMP_NAPOT(addr, size) TO_PMP_ADDR(addr | TO_NAPOT_RANGE(size))
struct PmpEntry
{
uint8_t pmpcfg;
#if defined(ARCH_RISCV64)
uint64_t pmpaddr;
#else
uint32_t pmpaddr;
#endif
};
struct PmpRegionNapot
{
x_ubase start ;
x_ubase end;
uint16_t swap_count;
uint8_t region_type;
struct PmpEntry entry;
DoubleLinklistType link;
};
struct PmpRegionTor
{
x_ubase start ;
x_ubase end;
uint16_t swap_count;
uint8_t region_type;
struct PmpEntry entry[2];
DoubleLinklistType link;
};
struct Pmp
{
uint8_t count;
uint8_t reserve;
struct PmpEntry pmp_entry_reserve[PMP_ENTRY_RESERVE];
DoubleLinklistType tor_list;
DoubleLinklistType tor_swap_list;
};
x_err_t PmpAddTorRegion(void *task_pmp, x_ubase start , size_t size , uint8_t flag );
x_err_t PmpInitIsolation(void **task_pmp, x_ubase stack_start , size_t stack_size);
void PmpFree(void *task_pmp);
void PmpClear(void);
x_err_t PmpClearRegion(void *task_pmp, x_ubase addr);
void PmpLoad(void *task_pmp);
x_bool PmpAccessFaultHandle(void *task_pmp, x_ubase addr);
#endif
+124
View File
@@ -0,0 +1,124 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "register_para.h"
#include <board.h>
#include <xs_base.h>
#include <xs_ktask.h>
#include <xs_isr.h>
#ifdef TASK_ISOLATION
#include "encoding.h"
#include <stdint.h>
#include <xs_isolation.h>
#endif
struct StackRegisterContext
{
x_ubase epc;
x_ubase ra;
x_ubase mstatus;
x_ubase gp;
x_ubase tp;
x_ubase t0;
x_ubase t1;
x_ubase t2;
x_ubase s0_fp;
x_ubase s1;
x_ubase a0;
x_ubase a1;
x_ubase a2;
x_ubase a3;
x_ubase a4;
x_ubase a5;
x_ubase a6;
x_ubase a7;
x_ubase s2;
x_ubase s3;
x_ubase s4;
x_ubase s5;
x_ubase s6;
x_ubase s7;
x_ubase s8;
x_ubase s9;
x_ubase s10;
x_ubase s11;
x_ubase t3;
x_ubase t4;
x_ubase t5;
x_ubase t6;
};
uint8 KTaskStackSetup(struct TaskDescriptor *task)
{
struct StackRegisterContext *stack_contex;
int i;
task->stack_point = (uint8 *)ALIGN_MEN_DOWN((x_ubase)(task->task_base_info.stack_start + task->task_base_info.stack_depth), RegLength);
task->stack_point -= sizeof(struct StackRegisterContext);
stack_contex = (struct StackRegisterContext *)task->stack_point;
for (i = 0; i < sizeof(struct StackRegisterContext) / sizeof(x_ubase); i++)
((x_ubase *)stack_contex)[i] = 0xfadeface;
#ifdef SEPARATE_COMPILE
if (task->task_dync_sched_member.isolation_flag == 1) {
stack_contex->ra = (unsigned long)USERSPACE->us_taskquit;
} else {
stack_contex->ra = (x_ubase)KTaskQuit;
}
#else
stack_contex->ra = (x_ubase)KTaskQuit;
#endif
stack_contex->a0 = (x_ubase)task->task_base_info.func_param;
stack_contex->epc = (x_ubase)task->task_base_info.func_entry;
#ifdef TASK_ISOLATION
stack_contex->tp = (x_ubase)task;
if(task->task_dync_sched_member.isolation_flag == 1)
stack_contex->mstatus = 0x00006080;
else
#endif
stack_contex->mstatus = 0x00007880;
return EOK;
}
void ShutdownCpu()
{
uint32 level;
KPrintf("shutdown...\n");
level = DISABLE_INTERRUPT();
while (level)
CHECK(0);
}
#ifdef TASK_ISOLATION
void RestoreMstatus(uintptr_t *sp)
{
struct TaskDescriptor *tid;
tid = (struct TaskDescriptor *)(sp[4]);
if(tid->task_dync_sched_member.isolation_flag == 1 && tid->task_dync_sched_member.isolation_status == 0){
CLEAR_CSR(mstatus, (MSTATUS_MPP));
#ifdef MOMERY_PROTECT_ENABLE
mem_access.Load(tid->task_dync_sched_member.isolation);
#endif
}else{
SET_CSR(mstatus, MSTATUS_MPP);
}
}
#endif
+109
View File
@@ -0,0 +1,109 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#ifndef RISCV_PLIC_H__
#define RISCV_PLIC_H__
#ifndef PLIC_BASE_ADDR
#define PLIC_BASE_ADDR 0x0
#endif
#define PLIC_PRIORITY_OFFSET (0x00000000UL)
#define PLIC_PRIORITY_SHIFT_PER_SOURCE 2
#define PLIC_PENDING_OFFSET (0x00001000UL)
#define PLIC_PENDING_SHIFT_PER_SOURCE 0
#define PLIC_ENABLE_OFFSET (0x00002000UL)
#define PLIC_ENABLE_SHIFT_PER_TARGET 7
#define PLIC_THRESHOLD_OFFSET (0x00200000UL)
#define PLIC_THRESHOLD_SHIFT_PER_TARGET 12
#define PLIC_CLAIM_OFFSET (0x00200004UL)
#define PLIC_CLAIM_SHIFT_PER_TARGET 12
#if defined(__GNUC__) && !defined(__ASSEMBLER__)
__attribute__((always_inline)) static inline void PlicSetFeature(unsigned int feature)
{
volatile unsigned int *feature_ptr = (volatile unsigned int *)PLIC_BASE_ADDR;
*feature_ptr = feature;
}
__attribute__((always_inline)) static inline void PlicSetThreshold(unsigned int threshold)
{
unsigned int hart_id = READ_CSR(mhartid);
volatile unsigned int *threshold_ptr = (volatile unsigned int *)(PLIC_BASE_ADDR +
PLIC_THRESHOLD_OFFSET +
(hart_id << PLIC_THRESHOLD_SHIFT_PER_TARGET));
*threshold_ptr = threshold;
}
__attribute__((always_inline)) static inline void PlicSetPriority(unsigned int source, unsigned int priority)
{
volatile unsigned int *priority_ptr = (volatile unsigned int *)(PLIC_BASE_ADDR +
PLIC_PRIORITY_OFFSET +
(source << PLIC_PRIORITY_SHIFT_PER_SOURCE));
*priority_ptr = priority;
}
__attribute__((always_inline)) static inline void PlicSetPending(unsigned int source)
{
volatile unsigned int *current_ptr = (volatile unsigned int *)(PLIC_BASE_ADDR +
PLIC_PENDING_OFFSET +
((source >> 5) << 2));
*current_ptr = (1 << (source & 0x1F));
}
__attribute__((always_inline)) static inline void PlicIrqEnable(unsigned int source)
{
unsigned int hart_id = READ_CSR(mhartid);
volatile unsigned int *current_ptr = (volatile unsigned int *)(PLIC_BASE_ADDR +
PLIC_ENABLE_OFFSET +
(hart_id << PLIC_ENABLE_SHIFT_PER_TARGET) +
((source >> 5) << 2));
unsigned int current = *current_ptr;
current = current | (1 << (source & 0x1F));
*current_ptr = current;
}
__attribute__((always_inline)) static inline void PlicIrqDisable(unsigned int source)
{
unsigned int hart_id = READ_CSR(mhartid);
volatile unsigned int *current_ptr = (volatile unsigned int *)(PLIC_BASE_ADDR +
PLIC_ENABLE_OFFSET +
(hart_id << PLIC_ENABLE_SHIFT_PER_TARGET) +
((source >> 5) << 2));
unsigned int current = *current_ptr;
current = current & ~((1 << (source & 0x1F)));
*current_ptr = current;
}
__attribute__((always_inline)) static inline unsigned int PlicIrqClaim(void)
{
unsigned int hart_id = READ_CSR(mhartid);
volatile unsigned int *claim_addr = (volatile unsigned int *)(PLIC_BASE_ADDR +
PLIC_CLAIM_OFFSET +
(hart_id << PLIC_CLAIM_SHIFT_PER_TARGET));
return *claim_addr;
}
__attribute__((always_inline)) static inline void PlicIrqComplete(unsigned int source)
{
unsigned int hart_id = READ_CSR(mhartid);
volatile unsigned int *claim_addr = (volatile unsigned int *)(PLIC_BASE_ADDR +
PLIC_CLAIM_OFFSET +
(hart_id << PLIC_CLAIM_SHIFT_PER_TARGET));
*claim_addr = source;
}
#endif
#endif
+43
View File
@@ -0,0 +1,43 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#ifndef RISCV_OPS_H__
#define RISCV_OPS_H__
#if defined(__GNUC__) && !defined(__ASSEMBLER__)
#define READ_CSR(reg) ({ unsigned long __tmp; \
asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \
__tmp; })
#define WRITE_CSR(reg, val) ({ \
if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \
asm volatile ("csrw " #reg ", %0" :: "i"(val)); \
else \
asm volatile ("csrw " #reg ", %0" :: "r"(val)); })
#define SET_CSR(reg, bit) ({ unsigned long __tmp; \
if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \
asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \
else \
asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \
__tmp; })
#define CLEAR_CSR(reg, bit) ({ unsigned long __tmp; \
if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \
asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \
else \
asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \
__tmp; })
#endif
#endif
+36
View File
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#ifndef CPUPORT_H__
#define CPUPORT_H__
#include <xsconfig.h>
#ifdef ARCH_CPU_64BIT
#define StoreD sd
#define LoadD ld
#define FSubDS fsub.d
#define RegLength 8
#define StoreDS "sd"
#define LoadDS "ld"
#define RegLengthS "8"
#else
#define StoreD sw
#define LoadD lw
#define FSubDS fsub.s
#define RegLength 4
#define StoreDS "sw"
#define LoadDS "lw"
#define RegLengthS "4"
#endif
#endif
+134
View File
@@ -0,0 +1,134 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "register_para.h"
#include <xs_base.h>
#include <xs_ktask.h>
void __attribute__((naked)) SwitchKTaskContextExit()
{
asm volatile (LoadDS " a0, 0 * " RegLengthS "(sp)");
asm volatile ("csrw mepc, a0");
#ifdef TASK_ISOLATION
asm volatile (LoadDS " a0, 2 * " RegLengthS "(sp)");
asm volatile ("csrw mstatus, a0");
asm volatile ("mv a0, sp");
asm volatile ("jal RestoreMstatus");
#else
asm volatile ("li t0, 0x00001800");
asm volatile ("csrw mstatus, t0");
asm volatile (LoadDS " a0, 2 * " RegLengthS "(sp)");
asm volatile ("csrs mstatus, a0");
#endif
asm volatile (LoadDS " ra, 1 * " RegLengthS "(sp)");
asm volatile (LoadDS " tp, 4 * " RegLengthS "(sp)");
asm volatile (LoadDS " t0, 5 * " RegLengthS "(sp)");
asm volatile (LoadDS " t1, 6 * " RegLengthS "(sp)");
asm volatile (LoadDS " t2, 7 * " RegLengthS "(sp)");
asm volatile (LoadDS " s0, 8 * " RegLengthS "(sp)");
asm volatile (LoadDS " s1, 9 * " RegLengthS "(sp)");
asm volatile (LoadDS " a0, 10 * " RegLengthS "(sp)");
asm volatile (LoadDS " a1, 11 * " RegLengthS "(sp)");
asm volatile (LoadDS " a2, 12 * " RegLengthS "(sp)");
asm volatile (LoadDS " a3, 13 * " RegLengthS "(sp)");
asm volatile (LoadDS " a4, 14 * " RegLengthS "(sp)");
asm volatile (LoadDS " a5, 15 * " RegLengthS "(sp)");
asm volatile (LoadDS " a6, 16 * " RegLengthS "(sp)");
asm volatile (LoadDS " a7, 17 * " RegLengthS "(sp)");
asm volatile (LoadDS " s2, 18 * " RegLengthS "(sp)");
asm volatile (LoadDS " s3, 19 * " RegLengthS "(sp)");
asm volatile (LoadDS " s4, 20 * " RegLengthS "(sp)");
asm volatile (LoadDS " s5, 21 * " RegLengthS "(sp)");
asm volatile (LoadDS " s6, 22 * " RegLengthS "(sp)");
asm volatile (LoadDS " s7, 23 * " RegLengthS "(sp)");
asm volatile (LoadDS " s8, 24 * " RegLengthS "(sp)");
asm volatile (LoadDS " s9, 25 * " RegLengthS "(sp)");
asm volatile (LoadDS " s10, 26 * " RegLengthS "(sp)");
asm volatile (LoadDS " s11, 27 * " RegLengthS "(sp)");
asm volatile (LoadDS " t3, 28 * " RegLengthS "(sp)");
asm volatile (LoadDS " t4, 29 * " RegLengthS "(sp)");
asm volatile (LoadDS " t5, 30 * " RegLengthS "(sp)");
asm volatile (LoadDS " t6, 31 * " RegLengthS "(sp)");
asm volatile ("addi sp, sp, 32 * " RegLengthS "");
asm volatile ("mret");
}
void __attribute__((naked)) SaveMpie()
{
asm volatile (StoreDS " a0, 2 * " RegLengthS "(sp)");
asm volatile (StoreDS " tp, 4 * " RegLengthS "(sp)");
asm volatile (StoreDS " t0, 5 * " RegLengthS "(sp)");
asm volatile (StoreDS " t1, 6 * " RegLengthS "(sp)");
asm volatile (StoreDS " t2, 7 * " RegLengthS "(sp)");
asm volatile (StoreDS " s0, 8 * " RegLengthS "(sp)");
asm volatile (StoreDS " s1, 9 * " RegLengthS "(sp)");
asm volatile (StoreDS " a0, 10 * " RegLengthS "(sp)");
asm volatile (StoreDS " a1, 11 * " RegLengthS "(sp)");
asm volatile (StoreDS " a2, 12 * " RegLengthS "(sp)");
asm volatile (StoreDS " a3, 13 * " RegLengthS "(sp)");
asm volatile (StoreDS " a4, 14 * " RegLengthS "(sp)");
asm volatile (StoreDS " a5, 15 * " RegLengthS "(sp)");
asm volatile (StoreDS " a6, 16 * " RegLengthS "(sp)");
asm volatile (StoreDS " a7, 17 * " RegLengthS "(sp)");
asm volatile (StoreDS " s2, 18 * " RegLengthS "(sp)");
asm volatile (StoreDS " s3, 19 * " RegLengthS "(sp)");
asm volatile (StoreDS " s4, 20 * " RegLengthS "(sp)");
asm volatile (StoreDS " s5, 21 * " RegLengthS "(sp)");
asm volatile (StoreDS " s6, 22 * " RegLengthS "(sp)");
asm volatile (StoreDS " s7, 23 * " RegLengthS "(sp)");
asm volatile (StoreDS " s8, 24 * " RegLengthS "(sp)");
asm volatile (StoreDS " s9, 25 * " RegLengthS "(sp)");
asm volatile (StoreDS " s10, 26 * " RegLengthS "(sp)");
asm volatile (StoreDS " s11, 27 * " RegLengthS "(sp)");
asm volatile (StoreDS " t3, 28 * " RegLengthS "(sp)");
asm volatile (StoreDS " t4, 29 * " RegLengthS "(sp)");
asm volatile (StoreDS " t5, 30 * " RegLengthS "(sp)");
asm volatile (StoreDS " t6, 31 * " RegLengthS "(sp)");
asm volatile (LoadDS " sp, (a1)");
asm volatile ("mv a0, a2");
asm volatile ("jal RestoreCpusLockStatus");
asm volatile ("j SwitchKTaskContextExit");
}
void __attribute__((naked)) SwitchKtaskContextTo(x_ubase to, struct TaskDescriptor *to_task)
{
asm volatile (LoadDS " sp, (a0)\n");
asm volatile ("mv a0, a1");
asm volatile ("jal RestoreCpusLockStatus");
asm volatile (LoadDS " a7, 2 * " RegLengthS "(sp)");
asm volatile ("csrw mstatus, a7");
asm volatile ("j SwitchKTaskContextExit");
}
void __attribute__((naked)) SwitchKtaskContext(x_ubase from, x_ubase to, struct TaskDescriptor *to_task)
{
asm volatile ("addi sp, sp, -32 * " RegLengthS);
asm volatile (StoreDS " sp, (a0)");
asm volatile (StoreDS " x1, 0 * " RegLengthS "(sp)");
asm volatile (StoreDS " x1, 1 * " RegLengthS "(sp)");
asm volatile ("csrr a0, mstatus");
#ifndef TASK_ISOLATION
asm volatile ("andi a0, a0, 8");
asm volatile ("beqz a0, SaveMpie");
asm volatile ("li a0, 0x80");
#endif
asm volatile ("j SaveMpie");
}
void __attribute__((naked)) HwInterruptcontextSwitch(x_ubase from, x_ubase to, struct TaskDescriptor *to_task, void *context)
{
asm volatile (StoreDS " a3, 0(a0)");
asm volatile (LoadDS " sp, 0(a1)");
asm volatile ("move a0, a2");
asm volatile ("call RestoreCpusLockStatus");
asm volatile ("j SwitchKTaskContextExit");
}