merge #1 :: enable MMU and supervisor mode switch support

* Supervisor mode related code.
* Update to fix type mismatch in debugging code.
* Smode switch worked with command loop.
* Wip, turn off debugging and not used code.
* Delte debugging code and add compile flag for priviledge related functions.
* delete debugging code
* use smode scratch register for ecall index
* delete unused code.
* The first code worked with mmu and smode.
* The code updates such that mmu and s-mode switching working.
* Use compile flag to enable/disable MMU. Code clean up.
This commit is contained in:
Enya Cheng 2020-07-28 16:31:26 -07:00 committed by GitHub
parent 021e86659d
commit 37f2fa5db7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 184 additions and 9 deletions

View file

@ -166,7 +166,11 @@ void vPortSetupTimerInterrupt(void)
BaseType_t xPortStartScheduler(void)
{
extern void xPortStartFirstTask(void);
#if( USE_PRIVILEDGE_MODE == 1 )
{
vRaisePriviledge();
}
#endif
#if (configASSERT_DEFINED == 1)
{
volatile uint32_t mtvec = 0;

View file

@ -100,9 +100,16 @@ specific version of freertos_risc_v_chip_specific_extensions.h. See the notes
at the top of this file. */
#define portCONTEXT_SIZE ( 30 * portWORD_SIZE )
#ifdef DISABLE_PRIVILEDGE_MODE
#define USE_PRIVILEDGE_MODE 0
#else
#define USE_PRIVILEDGE_MODE 1
#endif
.global xPortStartFirstTask
.global freertos_risc_v_trap_handler
.global pxPortInitialiseStack
.extern pxCurrentTCB
.extern ulPortTrapHandler
.extern vTaskSwitchContext
@ -114,11 +121,103 @@ at the top of this file. */
.extern xISRStackTop
.extern portasmHANDLE_INTERRUPT
#if 0
.extern int_record //the variable used for debugging utility
#endif
#if( USE_PRIVILEDGE_MODE != 0 )
.extern priviledge_status
#endif
/*-----------------------------------------------------------*/
.align 8
.func
freertos_risc_v_trap_handler:
#if( USE_PRIVILEDGE_MODE != 0 )
//csrw mscratch, t0
csrr t0, mcause
blt t0, x0, handle_other_traps
addi t0, t0, -8
blt t0, x0, is_exception /* mcause < 8, not ecall */
addi t0, t0, -3
bgt t0, x0, is_exception
environment_switch:
csrr t5, sscratch
csrw mscratch, t5
csrwi sscratch, 1
beq t5, x0, handle_other_traps
la t0, 1f
slli t5, t5, 2
add t0, t0, t5
jr t0
1:
jal x0, ecall_yield
jal x0, ecall_disable_interrupt
jal x0, ecall_enable_interrupt
jal x0, ecall_switch_to_machine
jal x0, ecall_switch_to_supervisor
ecall_disable_interrupt:
/* Clear mpie */
li t6, 0x880
csrc mie, t6
j ecall_mret
ecall_enable_interrupt:
/* Set mpie */
li t6, 0x880
csrs mie, t6
j ecall_mret
ecall_switch_to_machine:
/* Set mpp */
li t6, 0x1800
csrs mstatus, t6
j ecall_mret
ecall_switch_to_supervisor:
/* Clear mpp */
li t6, 0x1800
csrc mstatus, t6
li t6, 0x800
csrs mstatus, t6
j ecall_mret
ecall_mret:
csrr t0, mstatus
li t6, 0x1800
and t0, t0, t6
srli t0, t0, 11
//for debug
#if 0
csrr t1, mie
la t6, int_record
sw t1, 0(t6)
add t0, t0, t1
slli t0, t0, 4
csrr t1, mscratch
add t0, t0, t1
#endif
la t6, priviledge_status
sw t0, 0(t6)
csrr t0, mepc
addi t0, t0, 4
csrw mepc, t0
/* restore t0 */
//csrr t0, mscratch
mret
ecall_yield:
handle_other_traps:
#endif
addi sp, sp, -portCONTEXT_SIZE
store_x x1, 1 * portWORD_SIZE( sp )
store_x x5, 2 * portWORD_SIZE( sp )
@ -149,8 +248,10 @@ freertos_risc_v_trap_handler:
store_x x30, 27 * portWORD_SIZE( sp )
store_x x31, 28 * portWORD_SIZE( sp )
#if ( USE_PRIVILEDGE_MODE == 0 )
csrr t0, mstatus /* Required for MPIE bit. */
store_x t0, 29 * portWORD_SIZE( sp )
#endif
portasmSAVE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_chip_specific_extensions.h to save any registers unique to the RISC-V implementation. */
@ -172,11 +273,9 @@ handle_asynchronous:
test_if_mtimer: /* If there is a CLINT then the mtimer is used to generate the tick interrupt. */
addi t0, x0, 1
slli t0, t0, __riscv_xlen - 1 /* LSB is already set, shift into MSB. Shift 31 on 32-bit or 63 on 64-bit cores. */
addi t1, t0, 7 /* 0x8000[]0007 == machine timer interrupt. */
bne a0, t1, test_if_external_interrupt
load_x t0, pullMachineTimerCompareRegister /* Load address of compare register into t0. */
load_x t1, pullNextTime /* Load the address of ullNextTime into t1. */
@ -230,8 +329,16 @@ handle_synchronous:
store_x a1, 0( sp ) /* Save updated exception return address. */
test_if_environment_call:
#if( USE_PRIVILEDGE_MODE == 0 )
li t0, 11 /* 11 == environment call. */
#else
li t0, 9 /* 9 == environment call. */
#endif
beq a0, t0, next
li t0, 11
bne a0, t0, is_exception /* Not an M environment call, so some other exception. */
next:
load_x sp, xISRStackTop /* Switch to ISR stack before function call. */
jal vTaskSwitchContext
j processed_source
@ -257,8 +364,38 @@ processed_source:
portasmRESTORE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_chip_specific_extensions.h to restore any registers unique to the RISC-V implementation. */
/* Load mstatus with the interrupt enable bits used by the task. */
#if ( USE_PRIVILEDGE_MODE == 0 )
load_x t0, 29 * portWORD_SIZE( sp )
csrw mstatus, t0 /* Required for MPIE bit. */
#endif
#if( USE_PRIVILEDGE_MODE != 0 )
li a0, 0x1000
csrc mstatus, a0
li a0, 0x800
csrs mstatus, a0
csrr t0, mstatus
li a0, 0x1800
and t0, t0, a0
srli t0, t0, 11
#if 0 //for debug
csrr t1, mie
la t6, int_record
sw t1, 0(t6)
add t0, t0, t1
slli t0, t0, 4
csrr t1, mscratch
add t0, t0, t1
#endif
la t6, priviledge_status
sw t0, 0(t6)
li t0, 0x880
csrw mie, t0
#endif
load_x x1, 1 * portWORD_SIZE( sp )
load_x x5, 2 * portWORD_SIZE( sp ) /* t0 */
@ -312,10 +449,15 @@ xPortStartFirstTask:
load_x x1, 0( sp ) /* Note for starting the scheduler the exception return address is used as the function return address. */
portasmRESTORE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_chip_specific_extensions.h to restore any registers unique to the RISC-V implementation. */
#if ( USE_PRIVILEDGE_MODE == 0 )
load_x t0, 29 * portWORD_SIZE( sp ) /* mstatus */
addi t0, t0, 0x08 /* Set MIE bit so the first task starts with interrupts enabled - required as returns with ret not eret. */
csrrw x0, mstatus, t0 /* Interrupts enabled from here! */
#endif
#if( USE_PRIVILEDGE_MODE != 0 )
csrwi sscratch, 4
#endif
load_x x5, 2 * portWORD_SIZE( sp ) /* t0 */
load_x x6, 3 * portWORD_SIZE( sp ) /* t1 */
@ -345,6 +487,11 @@ xPortStartFirstTask:
load_x x30, 27 * portWORD_SIZE( sp ) /* t5 */
load_x x31, 28 * portWORD_SIZE( sp ) /* t6 */
addi sp, sp, portCONTEXT_SIZE
#if( USE_PRIVILEDGE_MODE != 0 )
ecall
#endif
ret
.endfunc
/*-----------------------------------------------------------*/
@ -416,7 +563,11 @@ xPortStartFirstTask:
pxPortInitialiseStack:
csrr t0, mstatus /* Obtain current mstatus value. */
#if ( USE_PRIVILEDGE_MODE == 0 )
addi t1, x0, 0x188 /* Generate the value 0x1880, which are the MPIE and MPP bits to set in mstatus. */
#else
addi t1, x0, 0x180
#endif
slli t1, t1, 4
or t0, t0, t1 /* Set MPIE and MPP bits in mstatus value. */
@ -436,6 +587,7 @@ chip_specific_stack_frame: /* First add any chip specific registers to the st
1:
addi a0, a0, -portWORD_SIZE
store_x a1, 0(a0) /* mret value (pxCode parameter) onto the stack. */
ret
.endfunc
/*-----------------------------------------------------------*/

View file

@ -29,6 +29,8 @@
#ifndef PORTMACRO_H
#define PORTMACRO_H
#include "../../../../../src/scpu/hal/drivers/recogni_priviledge.h"
#ifdef __cplusplus
extern "C"
{
@ -90,7 +92,12 @@ not need to be guarded with a critical section. */
/* Scheduler utilities. */
extern void vTaskSwitchContext(void);
#if( USE_PRIVILEDGE_MODE != 1 )
#define portYIELD() __asm volatile( "ecall" );
#else
#define portYIELD() vPortSyscall()
#endif
#define portEND_SWITCHING_ISR(xSwitchRequired) \
if (xSwitchRequired) vTaskSwitchContext()
#define portYIELD_FROM_ISR(x) portEND_SWITCHING_ISR(x)
@ -104,8 +111,14 @@ not need to be guarded with a critical section. */
#define portSET_INTERRUPT_MASK_FROM_ISR() 0
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedStatusValue) \
(void)uxSavedStatusValue
#if( USE_PRIVILEDGE_MODE != 1 )
#define portDISABLE_INTERRUPTS() __asm volatile("csrc mstatus, 8")
#define portENABLE_INTERRUPTS() __asm volatile("csrs mstatus, 8")
#else
#define portDISABLE_INTERRUPTS() vDisableInterrupt()
#define portENABLE_INTERRUPTS() vEnableInterrupt()
#endif
#define portENTER_CRITICAL() vTaskEnterCritical()
#define portEXIT_CRITICAL() vTaskExitCritical()

14
tasks.c
View file

@ -1013,6 +1013,11 @@ UBaseType_t x;
but had been interrupted by the scheduler. The return address is set
to the start of the task function. Once the stack has been initialised
the top of stack variable is updated. */
#if( USE_PRIVILEDGE_MODE == 1 )
{
vRaisePriviledge();
}
#endif
#if( portUSING_MPU_WRAPPERS == 1 )
{
/* If the port has capability to detect stack overflow,
@ -1061,6 +1066,11 @@ UBaseType_t x;
}
#endif /* portUSING_MPU_WRAPPERS */
#if( USE_PRIVILEDGE_MODE == 1 )
{
vResetPriviledge();
}
#endif
if( pxCreatedTask != NULL )
{
/* Pass the handle out in an anonymous way. The handle can be used to
@ -1156,7 +1166,6 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB )
}
}
/*-----------------------------------------------------------*/
#if ( INCLUDE_vTaskDelete == 1 )
void vTaskDelete( TaskHandle_t xTaskToDelete )
@ -1251,7 +1260,6 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB )
#endif /* INCLUDE_vTaskDelete */
/*-----------------------------------------------------------*/
#if ( INCLUDE_vTaskDelayUntil == 1 )
void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement )
@ -1947,7 +1955,6 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB )
{
mtCOVERAGE_TEST_MARKER();
}
( void ) uxListRemove( &( pxTCB->xStateListItem ) );
prvAddTaskToReadyList( pxTCB );
}
@ -3134,7 +3141,6 @@ void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xIte
#endif /* configUSE_TIMERS */
/*-----------------------------------------------------------*/
BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList )
{
TCB_t *pxUnblockedTCB;