Adjust directory structure
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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, ®ion->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, ®ion->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
|
||||
@@ -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
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
#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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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");
|
||||
}
|
||||
Reference in New Issue
Block a user