mirror of
https://github.com/plctlab/riscv-operating-system-mooc.git
synced 2025-11-16 12:34:47 +00:00
Encapsulate some types related to cpu word length.
The purpose is to facilitate porting to RV64. Signed-off-by: Wang Chen <wangchen20@iscas.ac.cn>
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
* QEMU RISC-V Virt machine with 16550a UART and VirtIO MMIO
|
||||
*/
|
||||
|
||||
/*
|
||||
/*
|
||||
* maximum number of CPUs
|
||||
* see https://github.com/qemu/qemu/blob/master/include/hw/riscv/virt.h
|
||||
* #define VIRT_CPUS_MAX 8
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
/*
|
||||
* MemoryMap
|
||||
* see https://github.com/qemu/qemu/blob/master/hw/riscv/virt.c, virt_memmap[]
|
||||
* see https://github.com/qemu/qemu/blob/master/hw/riscv/virt.c, virt_memmap[]
|
||||
* 0x00001000 -- boot ROM, provided by qemu
|
||||
* 0x02000000 -- CLINT
|
||||
* 0x0C000000 -- PLIC
|
||||
|
||||
@@ -1,30 +1,32 @@
|
||||
#define SIZE_PTR .word
|
||||
|
||||
.section .rodata
|
||||
.global HEAP_START
|
||||
HEAP_START: .word _heap_start
|
||||
HEAP_START: SIZE_PTR _heap_start
|
||||
|
||||
.global HEAP_SIZE
|
||||
HEAP_SIZE: .word _heap_size
|
||||
HEAP_SIZE: SIZE_PTR _heap_size
|
||||
|
||||
.global TEXT_START
|
||||
TEXT_START: .word _text_start
|
||||
TEXT_START: SIZE_PTR _text_start
|
||||
|
||||
.global TEXT_END
|
||||
TEXT_END: .word _text_end
|
||||
TEXT_END: SIZE_PTR _text_end
|
||||
|
||||
.global DATA_START
|
||||
DATA_START: .word _data_start
|
||||
DATA_START: SIZE_PTR _data_start
|
||||
|
||||
.global DATA_END
|
||||
DATA_END: .word _data_end
|
||||
DATA_END: SIZE_PTR _data_end
|
||||
|
||||
.global RODATA_START
|
||||
RODATA_START: .word _rodata_start
|
||||
RODATA_START: SIZE_PTR _rodata_start
|
||||
|
||||
.global RODATA_END
|
||||
RODATA_END: .word _rodata_end
|
||||
RODATA_END: SIZE_PTR _rodata_end
|
||||
|
||||
.global BSS_START
|
||||
BSS_START: .word _bss_start
|
||||
BSS_START: SIZE_PTR _bss_start
|
||||
|
||||
.global BSS_END
|
||||
BSS_END: .word _bss_end
|
||||
BSS_END: SIZE_PTR _bss_end
|
||||
|
||||
@@ -3,24 +3,24 @@
|
||||
/*
|
||||
* Following global vars are defined in mem.S
|
||||
*/
|
||||
extern uint32_t TEXT_START;
|
||||
extern uint32_t TEXT_END;
|
||||
extern uint32_t DATA_START;
|
||||
extern uint32_t DATA_END;
|
||||
extern uint32_t RODATA_START;
|
||||
extern uint32_t RODATA_END;
|
||||
extern uint32_t BSS_START;
|
||||
extern uint32_t BSS_END;
|
||||
extern uint32_t HEAP_START;
|
||||
extern uint32_t HEAP_SIZE;
|
||||
extern ptr_t TEXT_START;
|
||||
extern ptr_t TEXT_END;
|
||||
extern ptr_t DATA_START;
|
||||
extern ptr_t DATA_END;
|
||||
extern ptr_t RODATA_START;
|
||||
extern ptr_t RODATA_END;
|
||||
extern ptr_t BSS_START;
|
||||
extern ptr_t BSS_END;
|
||||
extern ptr_t HEAP_START;
|
||||
extern ptr_t HEAP_SIZE;
|
||||
|
||||
/*
|
||||
* _alloc_start points to the actual start address of heap pool
|
||||
* _alloc_end points to the actual end address of heap pool
|
||||
* _num_pages holds the actual max number of pages we can allocate.
|
||||
*/
|
||||
static uint32_t _alloc_start = 0;
|
||||
static uint32_t _alloc_end = 0;
|
||||
static ptr_t _alloc_start = 0;
|
||||
static ptr_t _alloc_end = 0;
|
||||
static uint32_t _num_pages = 0;
|
||||
|
||||
#define PAGE_SIZE 4096
|
||||
@@ -70,9 +70,9 @@ static inline int _is_last(struct Page *page)
|
||||
/*
|
||||
* align the address to the border of page(4K)
|
||||
*/
|
||||
static inline uint32_t _align_page(uint32_t address)
|
||||
static inline ptr_t _align_page(ptr_t address)
|
||||
{
|
||||
uint32_t order = (1 << PAGE_ORDER) - 1;
|
||||
ptr_t order = (1 << PAGE_ORDER) - 1;
|
||||
return (address + order) & (~order);
|
||||
}
|
||||
|
||||
@@ -155,12 +155,12 @@ void page_free(void *p)
|
||||
/*
|
||||
* Assert (TBD) if p is invalid
|
||||
*/
|
||||
if (!p || (uint32_t)p >= _alloc_end) {
|
||||
if (!p || (ptr_t)p >= _alloc_end) {
|
||||
return;
|
||||
}
|
||||
/* get the first page descriptor of this memory block */
|
||||
struct Page *page = (struct Page *)HEAP_START;
|
||||
page += ((uint32_t)p - _alloc_start)/ PAGE_SIZE;
|
||||
page += ((ptr_t)p - _alloc_start)/ PAGE_SIZE;
|
||||
/* loop and clear all the page descriptors of the memory block */
|
||||
while (!_is_free(page)) {
|
||||
if (_is_last(page)) {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* QEMU RISC-V Virt machine with 16550a UART and VirtIO MMIO
|
||||
*/
|
||||
|
||||
/*
|
||||
/*
|
||||
* maximum number of CPUs
|
||||
* see https://github.com/qemu/qemu/blob/master/include/hw/riscv/virt.h
|
||||
* #define VIRT_CPUS_MAX 8
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
/*
|
||||
* MemoryMap
|
||||
* see https://github.com/qemu/qemu/blob/master/hw/riscv/virt.c, virt_memmap[]
|
||||
* see https://github.com/qemu/qemu/blob/master/hw/riscv/virt.c, virt_memmap[]
|
||||
* 0x00001000 -- boot ROM, provided by qemu
|
||||
* 0x02000000 -- CLINT
|
||||
* 0x0C000000 -- PLIC
|
||||
|
||||
@@ -6,4 +6,6 @@ typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
|
||||
typedef uint32_t ptr_t;
|
||||
|
||||
#endif /* __TYPES_H__ */
|
||||
@@ -1,3 +1,7 @@
|
||||
#define LOAD lw
|
||||
#define STORE sw
|
||||
#define SIZE_REG 4
|
||||
|
||||
# Save all General-Purpose(GP) registers to context.
|
||||
# struct context *base = &ctx_task;
|
||||
# base->ra = ra;
|
||||
@@ -10,34 +14,34 @@
|
||||
# which is a global value and would not be changed
|
||||
# during context-switch.
|
||||
.macro reg_save base
|
||||
sw ra, 0(\base)
|
||||
sw sp, 4(\base)
|
||||
sw t0, 16(\base)
|
||||
sw t1, 20(\base)
|
||||
sw t2, 24(\base)
|
||||
sw s0, 28(\base)
|
||||
sw s1, 32(\base)
|
||||
sw a0, 36(\base)
|
||||
sw a1, 40(\base)
|
||||
sw a2, 44(\base)
|
||||
sw a3, 48(\base)
|
||||
sw a4, 52(\base)
|
||||
sw a5, 56(\base)
|
||||
sw a6, 60(\base)
|
||||
sw a7, 64(\base)
|
||||
sw s2, 68(\base)
|
||||
sw s3, 72(\base)
|
||||
sw s4, 76(\base)
|
||||
sw s5, 80(\base)
|
||||
sw s6, 84(\base)
|
||||
sw s7, 88(\base)
|
||||
sw s8, 92(\base)
|
||||
sw s9, 96(\base)
|
||||
sw s10, 100(\base)
|
||||
sw s11, 104(\base)
|
||||
sw t3, 108(\base)
|
||||
sw t4, 112(\base)
|
||||
sw t5, 116(\base)
|
||||
STORE ra, 0*SIZE_REG(\base)
|
||||
STORE sp, 1*SIZE_REG(\base)
|
||||
STORE t0, 4*SIZE_REG(\base)
|
||||
STORE t1, 5*SIZE_REG(\base)
|
||||
STORE t2, 6*SIZE_REG(\base)
|
||||
STORE s0, 7*SIZE_REG(\base)
|
||||
STORE s1, 8*SIZE_REG(\base)
|
||||
STORE a0, 9*SIZE_REG(\base)
|
||||
STORE a1, 10*SIZE_REG(\base)
|
||||
STORE a2, 11*SIZE_REG(\base)
|
||||
STORE a3, 12*SIZE_REG(\base)
|
||||
STORE a4, 13*SIZE_REG(\base)
|
||||
STORE a5, 14*SIZE_REG(\base)
|
||||
STORE a6, 15*SIZE_REG(\base)
|
||||
STORE a7, 16*SIZE_REG(\base)
|
||||
STORE s2, 17*SIZE_REG(\base)
|
||||
STORE s3, 18*SIZE_REG(\base)
|
||||
STORE s4, 19*SIZE_REG(\base)
|
||||
STORE s5, 20*SIZE_REG(\base)
|
||||
STORE s6, 21*SIZE_REG(\base)
|
||||
STORE s7, 22*SIZE_REG(\base)
|
||||
STORE s8, 23*SIZE_REG(\base)
|
||||
STORE s9, 24*SIZE_REG(\base)
|
||||
STORE s10, 25*SIZE_REG(\base)
|
||||
STORE s11, 26*SIZE_REG(\base)
|
||||
STORE t3, 27*SIZE_REG(\base)
|
||||
STORE t4, 28*SIZE_REG(\base)
|
||||
STORE t5, 29*SIZE_REG(\base)
|
||||
# we don't save t6 here, due to we have used
|
||||
# it as base, we have to save t6 in an extra step
|
||||
# outside of reg_save
|
||||
@@ -49,35 +53,35 @@
|
||||
# ra = base->ra;
|
||||
# ......
|
||||
.macro reg_restore base
|
||||
lw ra, 0(\base)
|
||||
lw sp, 4(\base)
|
||||
lw t0, 16(\base)
|
||||
lw t1, 20(\base)
|
||||
lw t2, 24(\base)
|
||||
lw s0, 28(\base)
|
||||
lw s1, 32(\base)
|
||||
lw a0, 36(\base)
|
||||
lw a1, 40(\base)
|
||||
lw a2, 44(\base)
|
||||
lw a3, 48(\base)
|
||||
lw a4, 52(\base)
|
||||
lw a5, 56(\base)
|
||||
lw a6, 60(\base)
|
||||
lw a7, 64(\base)
|
||||
lw s2, 68(\base)
|
||||
lw s3, 72(\base)
|
||||
lw s4, 76(\base)
|
||||
lw s5, 80(\base)
|
||||
lw s6, 84(\base)
|
||||
lw s7, 88(\base)
|
||||
lw s8, 92(\base)
|
||||
lw s9, 96(\base)
|
||||
lw s10, 100(\base)
|
||||
lw s11, 104(\base)
|
||||
lw t3, 108(\base)
|
||||
lw t4, 112(\base)
|
||||
lw t5, 116(\base)
|
||||
lw t6, 120(\base)
|
||||
LOAD ra, 0*SIZE_REG(\base)
|
||||
LOAD sp, 1*SIZE_REG(\base)
|
||||
LOAD t0, 4*SIZE_REG(\base)
|
||||
LOAD t1, 5*SIZE_REG(\base)
|
||||
LOAD t2, 6*SIZE_REG(\base)
|
||||
LOAD s0, 7*SIZE_REG(\base)
|
||||
LOAD s1, 8*SIZE_REG(\base)
|
||||
LOAD a0, 9*SIZE_REG(\base)
|
||||
LOAD a1, 10*SIZE_REG(\base)
|
||||
LOAD a2, 11*SIZE_REG(\base)
|
||||
LOAD a3, 12*SIZE_REG(\base)
|
||||
LOAD a4, 13*SIZE_REG(\base)
|
||||
LOAD a5, 14*SIZE_REG(\base)
|
||||
LOAD a6, 15*SIZE_REG(\base)
|
||||
LOAD a7, 16*SIZE_REG(\base)
|
||||
LOAD s2, 17*SIZE_REG(\base)
|
||||
LOAD s3, 18*SIZE_REG(\base)
|
||||
LOAD s4, 19*SIZE_REG(\base)
|
||||
LOAD s5, 20*SIZE_REG(\base)
|
||||
LOAD s6, 21*SIZE_REG(\base)
|
||||
LOAD s7, 22*SIZE_REG(\base)
|
||||
LOAD s8, 23*SIZE_REG(\base)
|
||||
LOAD s9, 24*SIZE_REG(\base)
|
||||
LOAD s10, 25*SIZE_REG(\base)
|
||||
LOAD s11, 26*SIZE_REG(\base)
|
||||
LOAD t3, 27*SIZE_REG(\base)
|
||||
LOAD t4, 28*SIZE_REG(\base)
|
||||
LOAD t5, 29*SIZE_REG(\base)
|
||||
LOAD t6, 30*SIZE_REG(\base)
|
||||
.endm
|
||||
|
||||
# Something to note about save/restore:
|
||||
@@ -104,9 +108,9 @@ switch_to:
|
||||
|
||||
# Save the actual t6 register, which we swapped into
|
||||
# mscratch
|
||||
mv t5, t6 # t5 points to the context of current task
|
||||
csrr t6, mscratch # read t6 back from mscratch
|
||||
sw t6, 120(t5) # save t6 with t5 as base
|
||||
mv t5, t6 # t5 points to the context of current task
|
||||
csrr t6, mscratch # read t6 back from mscratch
|
||||
STORE t6, 30*SIZE_REG(t5) # save t6 with t5 as base
|
||||
|
||||
1:
|
||||
# switch mscratch to point to the context of the next task
|
||||
|
||||
@@ -1,30 +1,32 @@
|
||||
#define SIZE_PTR .word
|
||||
|
||||
.section .rodata
|
||||
.global HEAP_START
|
||||
HEAP_START: .word _heap_start
|
||||
HEAP_START: SIZE_PTR _heap_start
|
||||
|
||||
.global HEAP_SIZE
|
||||
HEAP_SIZE: .word _heap_size
|
||||
HEAP_SIZE: SIZE_PTR _heap_size
|
||||
|
||||
.global TEXT_START
|
||||
TEXT_START: .word _text_start
|
||||
TEXT_START: SIZE_PTR _text_start
|
||||
|
||||
.global TEXT_END
|
||||
TEXT_END: .word _text_end
|
||||
TEXT_END: SIZE_PTR _text_end
|
||||
|
||||
.global DATA_START
|
||||
DATA_START: .word _data_start
|
||||
DATA_START: SIZE_PTR _data_start
|
||||
|
||||
.global DATA_END
|
||||
DATA_END: .word _data_end
|
||||
DATA_END: SIZE_PTR _data_end
|
||||
|
||||
.global RODATA_START
|
||||
RODATA_START: .word _rodata_start
|
||||
RODATA_START: SIZE_PTR _rodata_start
|
||||
|
||||
.global RODATA_END
|
||||
RODATA_END: .word _rodata_end
|
||||
RODATA_END: SIZE_PTR _rodata_end
|
||||
|
||||
.global BSS_START
|
||||
BSS_START: .word _bss_start
|
||||
BSS_START: SIZE_PTR _bss_start
|
||||
|
||||
.global BSS_END
|
||||
BSS_END: .word _bss_end
|
||||
BSS_END: SIZE_PTR _bss_end
|
||||
|
||||
@@ -3,24 +3,24 @@
|
||||
/*
|
||||
* Following global vars are defined in mem.S
|
||||
*/
|
||||
extern uint32_t TEXT_START;
|
||||
extern uint32_t TEXT_END;
|
||||
extern uint32_t DATA_START;
|
||||
extern uint32_t DATA_END;
|
||||
extern uint32_t RODATA_START;
|
||||
extern uint32_t RODATA_END;
|
||||
extern uint32_t BSS_START;
|
||||
extern uint32_t BSS_END;
|
||||
extern uint32_t HEAP_START;
|
||||
extern uint32_t HEAP_SIZE;
|
||||
extern ptr_t TEXT_START;
|
||||
extern ptr_t TEXT_END;
|
||||
extern ptr_t DATA_START;
|
||||
extern ptr_t DATA_END;
|
||||
extern ptr_t RODATA_START;
|
||||
extern ptr_t RODATA_END;
|
||||
extern ptr_t BSS_START;
|
||||
extern ptr_t BSS_END;
|
||||
extern ptr_t HEAP_START;
|
||||
extern ptr_t HEAP_SIZE;
|
||||
|
||||
/*
|
||||
* _alloc_start points to the actual start address of heap pool
|
||||
* _alloc_end points to the actual end address of heap pool
|
||||
* _num_pages holds the actual max number of pages we can allocate.
|
||||
*/
|
||||
static uint32_t _alloc_start = 0;
|
||||
static uint32_t _alloc_end = 0;
|
||||
static ptr_t _alloc_start = 0;
|
||||
static ptr_t _alloc_end = 0;
|
||||
static uint32_t _num_pages = 0;
|
||||
|
||||
#define PAGE_SIZE 4096
|
||||
@@ -70,9 +70,9 @@ static inline int _is_last(struct Page *page)
|
||||
/*
|
||||
* align the address to the border of page(4K)
|
||||
*/
|
||||
static inline uint32_t _align_page(uint32_t address)
|
||||
static inline ptr_t _align_page(ptr_t address)
|
||||
{
|
||||
uint32_t order = (1 << PAGE_ORDER) - 1;
|
||||
ptr_t order = (1 << PAGE_ORDER) - 1;
|
||||
return (address + order) & (~order);
|
||||
}
|
||||
|
||||
@@ -155,12 +155,12 @@ void page_free(void *p)
|
||||
/*
|
||||
* Assert (TBD) if p is invalid
|
||||
*/
|
||||
if (!p || (uint32_t)p >= _alloc_end) {
|
||||
if (!p || (ptr_t)p >= _alloc_end) {
|
||||
return;
|
||||
}
|
||||
/* get the first page descriptor of this memory block */
|
||||
struct Page *page = (struct Page *)HEAP_START;
|
||||
page += ((uint32_t)p - _alloc_start)/ PAGE_SIZE;
|
||||
page += ((ptr_t)p - _alloc_start)/ PAGE_SIZE;
|
||||
/* loop and clear all the page descriptors of the memory block */
|
||||
while (!_is_free(page)) {
|
||||
if (_is_last(page)) {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* QEMU RISC-V Virt machine with 16550a UART and VirtIO MMIO
|
||||
*/
|
||||
|
||||
/*
|
||||
/*
|
||||
* maximum number of CPUs
|
||||
* see https://github.com/qemu/qemu/blob/master/include/hw/riscv/virt.h
|
||||
* #define VIRT_CPUS_MAX 8
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
/*
|
||||
* MemoryMap
|
||||
* see https://github.com/qemu/qemu/blob/master/hw/riscv/virt.c, virt_memmap[]
|
||||
* see https://github.com/qemu/qemu/blob/master/hw/riscv/virt.c, virt_memmap[]
|
||||
* 0x00001000 -- boot ROM, provided by qemu
|
||||
* 0x02000000 -- CLINT
|
||||
* 0x0C000000 -- PLIC
|
||||
|
||||
@@ -7,8 +7,9 @@ typedef unsigned int uint32_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
|
||||
/*
|
||||
* RISCV32: register is 32bits width
|
||||
*/
|
||||
* Register Width
|
||||
*/
|
||||
typedef uint32_t reg_t;
|
||||
typedef uint32_t ptr_t;
|
||||
|
||||
#endif /* __TYPES_H__ */
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
#define LOAD lw
|
||||
#define STORE sw
|
||||
#define SIZE_REG 4
|
||||
|
||||
# Save all General-Purpose(GP) registers to context.
|
||||
# struct context *base = &ctx_task;
|
||||
# base->ra = ra;
|
||||
@@ -10,34 +14,34 @@
|
||||
# which is a global value and would not be changed
|
||||
# during context-switch.
|
||||
.macro reg_save base
|
||||
sw ra, 0(\base)
|
||||
sw sp, 4(\base)
|
||||
sw t0, 16(\base)
|
||||
sw t1, 20(\base)
|
||||
sw t2, 24(\base)
|
||||
sw s0, 28(\base)
|
||||
sw s1, 32(\base)
|
||||
sw a0, 36(\base)
|
||||
sw a1, 40(\base)
|
||||
sw a2, 44(\base)
|
||||
sw a3, 48(\base)
|
||||
sw a4, 52(\base)
|
||||
sw a5, 56(\base)
|
||||
sw a6, 60(\base)
|
||||
sw a7, 64(\base)
|
||||
sw s2, 68(\base)
|
||||
sw s3, 72(\base)
|
||||
sw s4, 76(\base)
|
||||
sw s5, 80(\base)
|
||||
sw s6, 84(\base)
|
||||
sw s7, 88(\base)
|
||||
sw s8, 92(\base)
|
||||
sw s9, 96(\base)
|
||||
sw s10, 100(\base)
|
||||
sw s11, 104(\base)
|
||||
sw t3, 108(\base)
|
||||
sw t4, 112(\base)
|
||||
sw t5, 116(\base)
|
||||
STORE ra, 0*SIZE_REG(\base)
|
||||
STORE sp, 1*SIZE_REG(\base)
|
||||
STORE t0, 4*SIZE_REG(\base)
|
||||
STORE t1, 5*SIZE_REG(\base)
|
||||
STORE t2, 6*SIZE_REG(\base)
|
||||
STORE s0, 7*SIZE_REG(\base)
|
||||
STORE s1, 8*SIZE_REG(\base)
|
||||
STORE a0, 9*SIZE_REG(\base)
|
||||
STORE a1, 10*SIZE_REG(\base)
|
||||
STORE a2, 11*SIZE_REG(\base)
|
||||
STORE a3, 12*SIZE_REG(\base)
|
||||
STORE a4, 13*SIZE_REG(\base)
|
||||
STORE a5, 14*SIZE_REG(\base)
|
||||
STORE a6, 15*SIZE_REG(\base)
|
||||
STORE a7, 16*SIZE_REG(\base)
|
||||
STORE s2, 17*SIZE_REG(\base)
|
||||
STORE s3, 18*SIZE_REG(\base)
|
||||
STORE s4, 19*SIZE_REG(\base)
|
||||
STORE s5, 20*SIZE_REG(\base)
|
||||
STORE s6, 21*SIZE_REG(\base)
|
||||
STORE s7, 22*SIZE_REG(\base)
|
||||
STORE s8, 23*SIZE_REG(\base)
|
||||
STORE s9, 24*SIZE_REG(\base)
|
||||
STORE s10, 25*SIZE_REG(\base)
|
||||
STORE s11, 26*SIZE_REG(\base)
|
||||
STORE t3, 27*SIZE_REG(\base)
|
||||
STORE t4, 28*SIZE_REG(\base)
|
||||
STORE t5, 29*SIZE_REG(\base)
|
||||
# we don't save t6 here, due to we have used
|
||||
# it as base, we have to save t6 in an extra step
|
||||
# outside of reg_save
|
||||
@@ -49,35 +53,35 @@
|
||||
# ra = base->ra;
|
||||
# ......
|
||||
.macro reg_restore base
|
||||
lw ra, 0(\base)
|
||||
lw sp, 4(\base)
|
||||
lw t0, 16(\base)
|
||||
lw t1, 20(\base)
|
||||
lw t2, 24(\base)
|
||||
lw s0, 28(\base)
|
||||
lw s1, 32(\base)
|
||||
lw a0, 36(\base)
|
||||
lw a1, 40(\base)
|
||||
lw a2, 44(\base)
|
||||
lw a3, 48(\base)
|
||||
lw a4, 52(\base)
|
||||
lw a5, 56(\base)
|
||||
lw a6, 60(\base)
|
||||
lw a7, 64(\base)
|
||||
lw s2, 68(\base)
|
||||
lw s3, 72(\base)
|
||||
lw s4, 76(\base)
|
||||
lw s5, 80(\base)
|
||||
lw s6, 84(\base)
|
||||
lw s7, 88(\base)
|
||||
lw s8, 92(\base)
|
||||
lw s9, 96(\base)
|
||||
lw s10, 100(\base)
|
||||
lw s11, 104(\base)
|
||||
lw t3, 108(\base)
|
||||
lw t4, 112(\base)
|
||||
lw t5, 116(\base)
|
||||
lw t6, 120(\base)
|
||||
LOAD ra, 0*SIZE_REG(\base)
|
||||
LOAD sp, 1*SIZE_REG(\base)
|
||||
LOAD t0, 4*SIZE_REG(\base)
|
||||
LOAD t1, 5*SIZE_REG(\base)
|
||||
LOAD t2, 6*SIZE_REG(\base)
|
||||
LOAD s0, 7*SIZE_REG(\base)
|
||||
LOAD s1, 8*SIZE_REG(\base)
|
||||
LOAD a0, 9*SIZE_REG(\base)
|
||||
LOAD a1, 10*SIZE_REG(\base)
|
||||
LOAD a2, 11*SIZE_REG(\base)
|
||||
LOAD a3, 12*SIZE_REG(\base)
|
||||
LOAD a4, 13*SIZE_REG(\base)
|
||||
LOAD a5, 14*SIZE_REG(\base)
|
||||
LOAD a6, 15*SIZE_REG(\base)
|
||||
LOAD a7, 16*SIZE_REG(\base)
|
||||
LOAD s2, 17*SIZE_REG(\base)
|
||||
LOAD s3, 18*SIZE_REG(\base)
|
||||
LOAD s4, 19*SIZE_REG(\base)
|
||||
LOAD s5, 20*SIZE_REG(\base)
|
||||
LOAD s6, 21*SIZE_REG(\base)
|
||||
LOAD s7, 22*SIZE_REG(\base)
|
||||
LOAD s8, 23*SIZE_REG(\base)
|
||||
LOAD s9, 24*SIZE_REG(\base)
|
||||
LOAD s10, 25*SIZE_REG(\base)
|
||||
LOAD s11, 26*SIZE_REG(\base)
|
||||
LOAD t3, 27*SIZE_REG(\base)
|
||||
LOAD t4, 28*SIZE_REG(\base)
|
||||
LOAD t5, 29*SIZE_REG(\base)
|
||||
LOAD t6, 30*SIZE_REG(\base)
|
||||
.endm
|
||||
|
||||
# Something to note about save/restore:
|
||||
@@ -104,9 +108,9 @@ switch_to:
|
||||
|
||||
# Save the actual t6 register, which we swapped into
|
||||
# mscratch
|
||||
mv t5, t6 # t5 points to the context of current task
|
||||
csrr t6, mscratch # read t6 back from mscratch
|
||||
sw t6, 120(t5) # save t6 with t5 as base
|
||||
mv t5, t6 # t5 points to the context of current task
|
||||
csrr t6, mscratch # read t6 back from mscratch
|
||||
STORE t6, 30*SIZE_REG(t5) # save t6 with t5 as base
|
||||
|
||||
1:
|
||||
# switch mscratch to point to the context of the next task
|
||||
|
||||
@@ -1,30 +1,32 @@
|
||||
#define SIZE_PTR .word
|
||||
|
||||
.section .rodata
|
||||
.global HEAP_START
|
||||
HEAP_START: .word _heap_start
|
||||
HEAP_START: SIZE_PTR _heap_start
|
||||
|
||||
.global HEAP_SIZE
|
||||
HEAP_SIZE: .word _heap_size
|
||||
HEAP_SIZE: SIZE_PTR _heap_size
|
||||
|
||||
.global TEXT_START
|
||||
TEXT_START: .word _text_start
|
||||
TEXT_START: SIZE_PTR _text_start
|
||||
|
||||
.global TEXT_END
|
||||
TEXT_END: .word _text_end
|
||||
TEXT_END: SIZE_PTR _text_end
|
||||
|
||||
.global DATA_START
|
||||
DATA_START: .word _data_start
|
||||
DATA_START: SIZE_PTR _data_start
|
||||
|
||||
.global DATA_END
|
||||
DATA_END: .word _data_end
|
||||
DATA_END: SIZE_PTR _data_end
|
||||
|
||||
.global RODATA_START
|
||||
RODATA_START: .word _rodata_start
|
||||
RODATA_START: SIZE_PTR _rodata_start
|
||||
|
||||
.global RODATA_END
|
||||
RODATA_END: .word _rodata_end
|
||||
RODATA_END: SIZE_PTR _rodata_end
|
||||
|
||||
.global BSS_START
|
||||
BSS_START: .word _bss_start
|
||||
BSS_START: SIZE_PTR _bss_start
|
||||
|
||||
.global BSS_END
|
||||
BSS_END: .word _bss_end
|
||||
BSS_END: SIZE_PTR _bss_end
|
||||
|
||||
@@ -3,24 +3,24 @@
|
||||
/*
|
||||
* Following global vars are defined in mem.S
|
||||
*/
|
||||
extern uint32_t TEXT_START;
|
||||
extern uint32_t TEXT_END;
|
||||
extern uint32_t DATA_START;
|
||||
extern uint32_t DATA_END;
|
||||
extern uint32_t RODATA_START;
|
||||
extern uint32_t RODATA_END;
|
||||
extern uint32_t BSS_START;
|
||||
extern uint32_t BSS_END;
|
||||
extern uint32_t HEAP_START;
|
||||
extern uint32_t HEAP_SIZE;
|
||||
extern ptr_t TEXT_START;
|
||||
extern ptr_t TEXT_END;
|
||||
extern ptr_t DATA_START;
|
||||
extern ptr_t DATA_END;
|
||||
extern ptr_t RODATA_START;
|
||||
extern ptr_t RODATA_END;
|
||||
extern ptr_t BSS_START;
|
||||
extern ptr_t BSS_END;
|
||||
extern ptr_t HEAP_START;
|
||||
extern ptr_t HEAP_SIZE;
|
||||
|
||||
/*
|
||||
* _alloc_start points to the actual start address of heap pool
|
||||
* _alloc_end points to the actual end address of heap pool
|
||||
* _num_pages holds the actual max number of pages we can allocate.
|
||||
*/
|
||||
static uint32_t _alloc_start = 0;
|
||||
static uint32_t _alloc_end = 0;
|
||||
static ptr_t _alloc_start = 0;
|
||||
static ptr_t _alloc_end = 0;
|
||||
static uint32_t _num_pages = 0;
|
||||
|
||||
#define PAGE_SIZE 4096
|
||||
@@ -70,9 +70,9 @@ static inline int _is_last(struct Page *page)
|
||||
/*
|
||||
* align the address to the border of page(4K)
|
||||
*/
|
||||
static inline uint32_t _align_page(uint32_t address)
|
||||
static inline ptr_t _align_page(ptr_t address)
|
||||
{
|
||||
uint32_t order = (1 << PAGE_ORDER) - 1;
|
||||
ptr_t order = (1 << PAGE_ORDER) - 1;
|
||||
return (address + order) & (~order);
|
||||
}
|
||||
|
||||
@@ -155,12 +155,12 @@ void page_free(void *p)
|
||||
/*
|
||||
* Assert (TBD) if p is invalid
|
||||
*/
|
||||
if (!p || (uint32_t)p >= _alloc_end) {
|
||||
if (!p || (ptr_t)p >= _alloc_end) {
|
||||
return;
|
||||
}
|
||||
/* get the first page descriptor of this memory block */
|
||||
struct Page *page = (struct Page *)HEAP_START;
|
||||
page += ((uint32_t)p - _alloc_start)/ PAGE_SIZE;
|
||||
page += ((ptr_t)p - _alloc_start)/ PAGE_SIZE;
|
||||
/* loop and clear all the page descriptors of the memory block */
|
||||
while (!_is_free(page)) {
|
||||
if (_is_last(page)) {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* QEMU RISC-V Virt machine with 16550a UART and VirtIO MMIO
|
||||
*/
|
||||
|
||||
/*
|
||||
/*
|
||||
* maximum number of CPUs
|
||||
* see https://github.com/qemu/qemu/blob/master/include/hw/riscv/virt.h
|
||||
* #define VIRT_CPUS_MAX 8
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
/*
|
||||
* MemoryMap
|
||||
* see https://github.com/qemu/qemu/blob/master/hw/riscv/virt.c, virt_memmap[]
|
||||
* see https://github.com/qemu/qemu/blob/master/hw/riscv/virt.c, virt_memmap[]
|
||||
* 0x00001000 -- boot ROM, provided by qemu
|
||||
* 0x02000000 -- CLINT
|
||||
* 0x0C000000 -- PLIC
|
||||
|
||||
@@ -7,8 +7,9 @@ typedef unsigned int uint32_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
|
||||
/*
|
||||
* RISCV32: register is 32bits width
|
||||
*/
|
||||
* Register Width
|
||||
*/
|
||||
typedef uint32_t reg_t;
|
||||
typedef uint32_t ptr_t;
|
||||
|
||||
#endif /* __TYPES_H__ */
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
#define LOAD lw
|
||||
#define STORE sw
|
||||
#define SIZE_REG 4
|
||||
|
||||
# Save all General-Purpose(GP) registers to context.
|
||||
# struct context *base = &ctx_task;
|
||||
# base->ra = ra;
|
||||
@@ -10,34 +14,34 @@
|
||||
# which is a global value and would not be changed
|
||||
# during context-switch.
|
||||
.macro reg_save base
|
||||
sw ra, 0(\base)
|
||||
sw sp, 4(\base)
|
||||
sw t0, 16(\base)
|
||||
sw t1, 20(\base)
|
||||
sw t2, 24(\base)
|
||||
sw s0, 28(\base)
|
||||
sw s1, 32(\base)
|
||||
sw a0, 36(\base)
|
||||
sw a1, 40(\base)
|
||||
sw a2, 44(\base)
|
||||
sw a3, 48(\base)
|
||||
sw a4, 52(\base)
|
||||
sw a5, 56(\base)
|
||||
sw a6, 60(\base)
|
||||
sw a7, 64(\base)
|
||||
sw s2, 68(\base)
|
||||
sw s3, 72(\base)
|
||||
sw s4, 76(\base)
|
||||
sw s5, 80(\base)
|
||||
sw s6, 84(\base)
|
||||
sw s7, 88(\base)
|
||||
sw s8, 92(\base)
|
||||
sw s9, 96(\base)
|
||||
sw s10, 100(\base)
|
||||
sw s11, 104(\base)
|
||||
sw t3, 108(\base)
|
||||
sw t4, 112(\base)
|
||||
sw t5, 116(\base)
|
||||
STORE ra, 0*SIZE_REG(\base)
|
||||
STORE sp, 1*SIZE_REG(\base)
|
||||
STORE t0, 4*SIZE_REG(\base)
|
||||
STORE t1, 5*SIZE_REG(\base)
|
||||
STORE t2, 6*SIZE_REG(\base)
|
||||
STORE s0, 7*SIZE_REG(\base)
|
||||
STORE s1, 8*SIZE_REG(\base)
|
||||
STORE a0, 9*SIZE_REG(\base)
|
||||
STORE a1, 10*SIZE_REG(\base)
|
||||
STORE a2, 11*SIZE_REG(\base)
|
||||
STORE a3, 12*SIZE_REG(\base)
|
||||
STORE a4, 13*SIZE_REG(\base)
|
||||
STORE a5, 14*SIZE_REG(\base)
|
||||
STORE a6, 15*SIZE_REG(\base)
|
||||
STORE a7, 16*SIZE_REG(\base)
|
||||
STORE s2, 17*SIZE_REG(\base)
|
||||
STORE s3, 18*SIZE_REG(\base)
|
||||
STORE s4, 19*SIZE_REG(\base)
|
||||
STORE s5, 20*SIZE_REG(\base)
|
||||
STORE s6, 21*SIZE_REG(\base)
|
||||
STORE s7, 22*SIZE_REG(\base)
|
||||
STORE s8, 23*SIZE_REG(\base)
|
||||
STORE s9, 24*SIZE_REG(\base)
|
||||
STORE s10, 25*SIZE_REG(\base)
|
||||
STORE s11, 26*SIZE_REG(\base)
|
||||
STORE t3, 27*SIZE_REG(\base)
|
||||
STORE t4, 28*SIZE_REG(\base)
|
||||
STORE t5, 29*SIZE_REG(\base)
|
||||
# we don't save t6 here, due to we have used
|
||||
# it as base, we have to save t6 in an extra step
|
||||
# outside of reg_save
|
||||
@@ -49,35 +53,35 @@
|
||||
# ra = base->ra;
|
||||
# ......
|
||||
.macro reg_restore base
|
||||
lw ra, 0(\base)
|
||||
lw sp, 4(\base)
|
||||
lw t0, 16(\base)
|
||||
lw t1, 20(\base)
|
||||
lw t2, 24(\base)
|
||||
lw s0, 28(\base)
|
||||
lw s1, 32(\base)
|
||||
lw a0, 36(\base)
|
||||
lw a1, 40(\base)
|
||||
lw a2, 44(\base)
|
||||
lw a3, 48(\base)
|
||||
lw a4, 52(\base)
|
||||
lw a5, 56(\base)
|
||||
lw a6, 60(\base)
|
||||
lw a7, 64(\base)
|
||||
lw s2, 68(\base)
|
||||
lw s3, 72(\base)
|
||||
lw s4, 76(\base)
|
||||
lw s5, 80(\base)
|
||||
lw s6, 84(\base)
|
||||
lw s7, 88(\base)
|
||||
lw s8, 92(\base)
|
||||
lw s9, 96(\base)
|
||||
lw s10, 100(\base)
|
||||
lw s11, 104(\base)
|
||||
lw t3, 108(\base)
|
||||
lw t4, 112(\base)
|
||||
lw t5, 116(\base)
|
||||
lw t6, 120(\base)
|
||||
LOAD ra, 0*SIZE_REG(\base)
|
||||
LOAD sp, 1*SIZE_REG(\base)
|
||||
LOAD t0, 4*SIZE_REG(\base)
|
||||
LOAD t1, 5*SIZE_REG(\base)
|
||||
LOAD t2, 6*SIZE_REG(\base)
|
||||
LOAD s0, 7*SIZE_REG(\base)
|
||||
LOAD s1, 8*SIZE_REG(\base)
|
||||
LOAD a0, 9*SIZE_REG(\base)
|
||||
LOAD a1, 10*SIZE_REG(\base)
|
||||
LOAD a2, 11*SIZE_REG(\base)
|
||||
LOAD a3, 12*SIZE_REG(\base)
|
||||
LOAD a4, 13*SIZE_REG(\base)
|
||||
LOAD a5, 14*SIZE_REG(\base)
|
||||
LOAD a6, 15*SIZE_REG(\base)
|
||||
LOAD a7, 16*SIZE_REG(\base)
|
||||
LOAD s2, 17*SIZE_REG(\base)
|
||||
LOAD s3, 18*SIZE_REG(\base)
|
||||
LOAD s4, 19*SIZE_REG(\base)
|
||||
LOAD s5, 20*SIZE_REG(\base)
|
||||
LOAD s6, 21*SIZE_REG(\base)
|
||||
LOAD s7, 22*SIZE_REG(\base)
|
||||
LOAD s8, 23*SIZE_REG(\base)
|
||||
LOAD s9, 24*SIZE_REG(\base)
|
||||
LOAD s10, 25*SIZE_REG(\base)
|
||||
LOAD s11, 26*SIZE_REG(\base)
|
||||
LOAD t3, 27*SIZE_REG(\base)
|
||||
LOAD t4, 28*SIZE_REG(\base)
|
||||
LOAD t5, 29*SIZE_REG(\base)
|
||||
LOAD t6, 30*SIZE_REG(\base)
|
||||
.endm
|
||||
|
||||
# Something to note about save/restore:
|
||||
@@ -100,9 +104,9 @@ trap_vector:
|
||||
|
||||
# Save the actual t6 register, which we swapped into
|
||||
# mscratch
|
||||
mv t5, t6 # t5 points to the context of current task
|
||||
csrr t6, mscratch # read t6 back from mscratch
|
||||
sw t6, 120(t5) # save t6 with t5 as base
|
||||
mv t5, t6 # t5 points to the context of current task
|
||||
csrr t6, mscratch # read t6 back from mscratch
|
||||
STORE t6, 30*SIZE_REG(t5) # save t6 with t5 as base
|
||||
|
||||
# Restore the context pointer into mscratch
|
||||
csrw mscratch, t5
|
||||
@@ -137,9 +141,9 @@ switch_to:
|
||||
|
||||
# Save the actual t6 register, which we swapped into
|
||||
# mscratch
|
||||
mv t5, t6 # t5 points to the context of current task
|
||||
csrr t6, mscratch # read t6 back from mscratch
|
||||
sw t6, 120(t5) # save t6 with t5 as base
|
||||
mv t5, t6 # t5 points to the context of current task
|
||||
csrr t6, mscratch # read t6 back from mscratch
|
||||
STORE t6, 30*SIZE_REG(t5) # save t6 with t5 as base
|
||||
|
||||
1:
|
||||
# switch mscratch to point to the context of the next task
|
||||
|
||||
@@ -1,30 +1,32 @@
|
||||
#define SIZE_PTR .word
|
||||
|
||||
.section .rodata
|
||||
.global HEAP_START
|
||||
HEAP_START: .word _heap_start
|
||||
HEAP_START: SIZE_PTR _heap_start
|
||||
|
||||
.global HEAP_SIZE
|
||||
HEAP_SIZE: .word _heap_size
|
||||
HEAP_SIZE: SIZE_PTR _heap_size
|
||||
|
||||
.global TEXT_START
|
||||
TEXT_START: .word _text_start
|
||||
TEXT_START: SIZE_PTR _text_start
|
||||
|
||||
.global TEXT_END
|
||||
TEXT_END: .word _text_end
|
||||
TEXT_END: SIZE_PTR _text_end
|
||||
|
||||
.global DATA_START
|
||||
DATA_START: .word _data_start
|
||||
DATA_START: SIZE_PTR _data_start
|
||||
|
||||
.global DATA_END
|
||||
DATA_END: .word _data_end
|
||||
DATA_END: SIZE_PTR _data_end
|
||||
|
||||
.global RODATA_START
|
||||
RODATA_START: .word _rodata_start
|
||||
RODATA_START: SIZE_PTR _rodata_start
|
||||
|
||||
.global RODATA_END
|
||||
RODATA_END: .word _rodata_end
|
||||
RODATA_END: SIZE_PTR _rodata_end
|
||||
|
||||
.global BSS_START
|
||||
BSS_START: .word _bss_start
|
||||
BSS_START: SIZE_PTR _bss_start
|
||||
|
||||
.global BSS_END
|
||||
BSS_END: .word _bss_end
|
||||
BSS_END: SIZE_PTR _bss_end
|
||||
|
||||
@@ -3,24 +3,24 @@
|
||||
/*
|
||||
* Following global vars are defined in mem.S
|
||||
*/
|
||||
extern uint32_t TEXT_START;
|
||||
extern uint32_t TEXT_END;
|
||||
extern uint32_t DATA_START;
|
||||
extern uint32_t DATA_END;
|
||||
extern uint32_t RODATA_START;
|
||||
extern uint32_t RODATA_END;
|
||||
extern uint32_t BSS_START;
|
||||
extern uint32_t BSS_END;
|
||||
extern uint32_t HEAP_START;
|
||||
extern uint32_t HEAP_SIZE;
|
||||
extern ptr_t TEXT_START;
|
||||
extern ptr_t TEXT_END;
|
||||
extern ptr_t DATA_START;
|
||||
extern ptr_t DATA_END;
|
||||
extern ptr_t RODATA_START;
|
||||
extern ptr_t RODATA_END;
|
||||
extern ptr_t BSS_START;
|
||||
extern ptr_t BSS_END;
|
||||
extern ptr_t HEAP_START;
|
||||
extern ptr_t HEAP_SIZE;
|
||||
|
||||
/*
|
||||
* _alloc_start points to the actual start address of heap pool
|
||||
* _alloc_end points to the actual end address of heap pool
|
||||
* _num_pages holds the actual max number of pages we can allocate.
|
||||
*/
|
||||
static uint32_t _alloc_start = 0;
|
||||
static uint32_t _alloc_end = 0;
|
||||
static ptr_t _alloc_start = 0;
|
||||
static ptr_t _alloc_end = 0;
|
||||
static uint32_t _num_pages = 0;
|
||||
|
||||
#define PAGE_SIZE 4096
|
||||
@@ -70,9 +70,9 @@ static inline int _is_last(struct Page *page)
|
||||
/*
|
||||
* align the address to the border of page(4K)
|
||||
*/
|
||||
static inline uint32_t _align_page(uint32_t address)
|
||||
static inline ptr_t _align_page(ptr_t address)
|
||||
{
|
||||
uint32_t order = (1 << PAGE_ORDER) - 1;
|
||||
ptr_t order = (1 << PAGE_ORDER) - 1;
|
||||
return (address + order) & (~order);
|
||||
}
|
||||
|
||||
@@ -155,12 +155,12 @@ void page_free(void *p)
|
||||
/*
|
||||
* Assert (TBD) if p is invalid
|
||||
*/
|
||||
if (!p || (uint32_t)p >= _alloc_end) {
|
||||
if (!p || (ptr_t)p >= _alloc_end) {
|
||||
return;
|
||||
}
|
||||
/* get the first page descriptor of this memory block */
|
||||
struct Page *page = (struct Page *)HEAP_START;
|
||||
page += ((uint32_t)p - _alloc_start)/ PAGE_SIZE;
|
||||
page += ((ptr_t)p - _alloc_start)/ PAGE_SIZE;
|
||||
/* loop and clear all the page descriptors of the memory block */
|
||||
while (!_is_free(page)) {
|
||||
if (_is_last(page)) {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* QEMU RISC-V Virt machine with 16550a UART and VirtIO MMIO
|
||||
*/
|
||||
|
||||
/*
|
||||
/*
|
||||
* maximum number of CPUs
|
||||
* see https://github.com/qemu/qemu/blob/master/include/hw/riscv/virt.h
|
||||
* #define VIRT_CPUS_MAX 8
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
/*
|
||||
* MemoryMap
|
||||
* see https://github.com/qemu/qemu/blob/master/hw/riscv/virt.c, virt_memmap[]
|
||||
* see https://github.com/qemu/qemu/blob/master/hw/riscv/virt.c, virt_memmap[]
|
||||
* 0x00001000 -- boot ROM, provided by qemu
|
||||
* 0x02000000 -- CLINT
|
||||
* 0x0C000000 -- PLIC
|
||||
|
||||
@@ -92,6 +92,10 @@ static inline void w_mie(reg_t x)
|
||||
asm volatile("csrw mie, %0" : : "r" (x));
|
||||
}
|
||||
|
||||
/* Machine-mode Cause Masks */
|
||||
#define MCAUSE_MASK_INTERRUPT (reg_t)0x80000000
|
||||
#define MCAUSE_MASK_ECODE (reg_t)0x7FFFFFFF
|
||||
|
||||
static inline reg_t r_mcause()
|
||||
{
|
||||
reg_t x;
|
||||
|
||||
@@ -13,9 +13,9 @@ void trap_init()
|
||||
reg_t trap_handler(reg_t epc, reg_t cause)
|
||||
{
|
||||
reg_t return_pc = epc;
|
||||
reg_t cause_code = cause & 0xfff;
|
||||
reg_t cause_code = cause & MCAUSE_MASK_ECODE;
|
||||
|
||||
if (cause & 0x80000000) {
|
||||
if (cause & MCAUSE_MASK_INTERRUPT) {
|
||||
/* Asynchronous trap - interrupt */
|
||||
switch (cause_code) {
|
||||
case 3:
|
||||
|
||||
@@ -7,8 +7,9 @@ typedef unsigned int uint32_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
|
||||
/*
|
||||
* RISCV32: register is 32bits width
|
||||
*/
|
||||
* Register Width
|
||||
*/
|
||||
typedef uint32_t reg_t;
|
||||
typedef uint32_t ptr_t;
|
||||
|
||||
#endif /* __TYPES_H__ */
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
#define LOAD lw
|
||||
#define STORE sw
|
||||
#define SIZE_REG 4
|
||||
|
||||
# Save all General-Purpose(GP) registers to context.
|
||||
# struct context *base = &ctx_task;
|
||||
# base->ra = ra;
|
||||
@@ -10,34 +14,34 @@
|
||||
# which is a global value and would not be changed
|
||||
# during context-switch.
|
||||
.macro reg_save base
|
||||
sw ra, 0(\base)
|
||||
sw sp, 4(\base)
|
||||
sw t0, 16(\base)
|
||||
sw t1, 20(\base)
|
||||
sw t2, 24(\base)
|
||||
sw s0, 28(\base)
|
||||
sw s1, 32(\base)
|
||||
sw a0, 36(\base)
|
||||
sw a1, 40(\base)
|
||||
sw a2, 44(\base)
|
||||
sw a3, 48(\base)
|
||||
sw a4, 52(\base)
|
||||
sw a5, 56(\base)
|
||||
sw a6, 60(\base)
|
||||
sw a7, 64(\base)
|
||||
sw s2, 68(\base)
|
||||
sw s3, 72(\base)
|
||||
sw s4, 76(\base)
|
||||
sw s5, 80(\base)
|
||||
sw s6, 84(\base)
|
||||
sw s7, 88(\base)
|
||||
sw s8, 92(\base)
|
||||
sw s9, 96(\base)
|
||||
sw s10, 100(\base)
|
||||
sw s11, 104(\base)
|
||||
sw t3, 108(\base)
|
||||
sw t4, 112(\base)
|
||||
sw t5, 116(\base)
|
||||
STORE ra, 0*SIZE_REG(\base)
|
||||
STORE sp, 1*SIZE_REG(\base)
|
||||
STORE t0, 4*SIZE_REG(\base)
|
||||
STORE t1, 5*SIZE_REG(\base)
|
||||
STORE t2, 6*SIZE_REG(\base)
|
||||
STORE s0, 7*SIZE_REG(\base)
|
||||
STORE s1, 8*SIZE_REG(\base)
|
||||
STORE a0, 9*SIZE_REG(\base)
|
||||
STORE a1, 10*SIZE_REG(\base)
|
||||
STORE a2, 11*SIZE_REG(\base)
|
||||
STORE a3, 12*SIZE_REG(\base)
|
||||
STORE a4, 13*SIZE_REG(\base)
|
||||
STORE a5, 14*SIZE_REG(\base)
|
||||
STORE a6, 15*SIZE_REG(\base)
|
||||
STORE a7, 16*SIZE_REG(\base)
|
||||
STORE s2, 17*SIZE_REG(\base)
|
||||
STORE s3, 18*SIZE_REG(\base)
|
||||
STORE s4, 19*SIZE_REG(\base)
|
||||
STORE s5, 20*SIZE_REG(\base)
|
||||
STORE s6, 21*SIZE_REG(\base)
|
||||
STORE s7, 22*SIZE_REG(\base)
|
||||
STORE s8, 23*SIZE_REG(\base)
|
||||
STORE s9, 24*SIZE_REG(\base)
|
||||
STORE s10, 25*SIZE_REG(\base)
|
||||
STORE s11, 26*SIZE_REG(\base)
|
||||
STORE t3, 27*SIZE_REG(\base)
|
||||
STORE t4, 28*SIZE_REG(\base)
|
||||
STORE t5, 29*SIZE_REG(\base)
|
||||
# we don't save t6 here, due to we have used
|
||||
# it as base, we have to save t6 in an extra step
|
||||
# outside of reg_save
|
||||
@@ -49,35 +53,35 @@
|
||||
# ra = base->ra;
|
||||
# ......
|
||||
.macro reg_restore base
|
||||
lw ra, 0(\base)
|
||||
lw sp, 4(\base)
|
||||
lw t0, 16(\base)
|
||||
lw t1, 20(\base)
|
||||
lw t2, 24(\base)
|
||||
lw s0, 28(\base)
|
||||
lw s1, 32(\base)
|
||||
lw a0, 36(\base)
|
||||
lw a1, 40(\base)
|
||||
lw a2, 44(\base)
|
||||
lw a3, 48(\base)
|
||||
lw a4, 52(\base)
|
||||
lw a5, 56(\base)
|
||||
lw a6, 60(\base)
|
||||
lw a7, 64(\base)
|
||||
lw s2, 68(\base)
|
||||
lw s3, 72(\base)
|
||||
lw s4, 76(\base)
|
||||
lw s5, 80(\base)
|
||||
lw s6, 84(\base)
|
||||
lw s7, 88(\base)
|
||||
lw s8, 92(\base)
|
||||
lw s9, 96(\base)
|
||||
lw s10, 100(\base)
|
||||
lw s11, 104(\base)
|
||||
lw t3, 108(\base)
|
||||
lw t4, 112(\base)
|
||||
lw t5, 116(\base)
|
||||
lw t6, 120(\base)
|
||||
LOAD ra, 0*SIZE_REG(\base)
|
||||
LOAD sp, 1*SIZE_REG(\base)
|
||||
LOAD t0, 4*SIZE_REG(\base)
|
||||
LOAD t1, 5*SIZE_REG(\base)
|
||||
LOAD t2, 6*SIZE_REG(\base)
|
||||
LOAD s0, 7*SIZE_REG(\base)
|
||||
LOAD s1, 8*SIZE_REG(\base)
|
||||
LOAD a0, 9*SIZE_REG(\base)
|
||||
LOAD a1, 10*SIZE_REG(\base)
|
||||
LOAD a2, 11*SIZE_REG(\base)
|
||||
LOAD a3, 12*SIZE_REG(\base)
|
||||
LOAD a4, 13*SIZE_REG(\base)
|
||||
LOAD a5, 14*SIZE_REG(\base)
|
||||
LOAD a6, 15*SIZE_REG(\base)
|
||||
LOAD a7, 16*SIZE_REG(\base)
|
||||
LOAD s2, 17*SIZE_REG(\base)
|
||||
LOAD s3, 18*SIZE_REG(\base)
|
||||
LOAD s4, 19*SIZE_REG(\base)
|
||||
LOAD s5, 20*SIZE_REG(\base)
|
||||
LOAD s6, 21*SIZE_REG(\base)
|
||||
LOAD s7, 22*SIZE_REG(\base)
|
||||
LOAD s8, 23*SIZE_REG(\base)
|
||||
LOAD s9, 24*SIZE_REG(\base)
|
||||
LOAD s10, 25*SIZE_REG(\base)
|
||||
LOAD s11, 26*SIZE_REG(\base)
|
||||
LOAD t3, 27*SIZE_REG(\base)
|
||||
LOAD t4, 28*SIZE_REG(\base)
|
||||
LOAD t5, 29*SIZE_REG(\base)
|
||||
LOAD t6, 30*SIZE_REG(\base)
|
||||
.endm
|
||||
|
||||
# Something to note about save/restore:
|
||||
@@ -100,9 +104,9 @@ trap_vector:
|
||||
|
||||
# Save the actual t6 register, which we swapped into
|
||||
# mscratch
|
||||
mv t5, t6 # t5 points to the context of current task
|
||||
csrr t6, mscratch # read t6 back from mscratch
|
||||
sw t6, 120(t5) # save t6 with t5 as base
|
||||
mv t5, t6 # t5 points to the context of current task
|
||||
csrr t6, mscratch # read t6 back from mscratch
|
||||
STORE t6, 30*SIZE_REG(t5) # save t6 with t5 as base
|
||||
|
||||
# Restore the context pointer into mscratch
|
||||
csrw mscratch, t5
|
||||
@@ -137,9 +141,9 @@ switch_to:
|
||||
|
||||
# Save the actual t6 register, which we swapped into
|
||||
# mscratch
|
||||
mv t5, t6 # t5 points to the context of current task
|
||||
csrr t6, mscratch # read t6 back from mscratch
|
||||
sw t6, 120(t5) # save t6 with t5 as base
|
||||
mv t5, t6 # t5 points to the context of current task
|
||||
csrr t6, mscratch # read t6 back from mscratch
|
||||
STORE t6, 30*SIZE_REG(t5) # save t6 with t5 as base
|
||||
|
||||
1:
|
||||
# switch mscratch to point to the context of the next task
|
||||
|
||||
@@ -1,30 +1,32 @@
|
||||
#define SIZE_PTR .word
|
||||
|
||||
.section .rodata
|
||||
.global HEAP_START
|
||||
HEAP_START: .word _heap_start
|
||||
HEAP_START: SIZE_PTR _heap_start
|
||||
|
||||
.global HEAP_SIZE
|
||||
HEAP_SIZE: .word _heap_size
|
||||
HEAP_SIZE: SIZE_PTR _heap_size
|
||||
|
||||
.global TEXT_START
|
||||
TEXT_START: .word _text_start
|
||||
TEXT_START: SIZE_PTR _text_start
|
||||
|
||||
.global TEXT_END
|
||||
TEXT_END: .word _text_end
|
||||
TEXT_END: SIZE_PTR _text_end
|
||||
|
||||
.global DATA_START
|
||||
DATA_START: .word _data_start
|
||||
DATA_START: SIZE_PTR _data_start
|
||||
|
||||
.global DATA_END
|
||||
DATA_END: .word _data_end
|
||||
DATA_END: SIZE_PTR _data_end
|
||||
|
||||
.global RODATA_START
|
||||
RODATA_START: .word _rodata_start
|
||||
RODATA_START: SIZE_PTR _rodata_start
|
||||
|
||||
.global RODATA_END
|
||||
RODATA_END: .word _rodata_end
|
||||
RODATA_END: SIZE_PTR _rodata_end
|
||||
|
||||
.global BSS_START
|
||||
BSS_START: .word _bss_start
|
||||
BSS_START: SIZE_PTR _bss_start
|
||||
|
||||
.global BSS_END
|
||||
BSS_END: .word _bss_end
|
||||
BSS_END: SIZE_PTR _bss_end
|
||||
|
||||
@@ -3,24 +3,24 @@
|
||||
/*
|
||||
* Following global vars are defined in mem.S
|
||||
*/
|
||||
extern uint32_t TEXT_START;
|
||||
extern uint32_t TEXT_END;
|
||||
extern uint32_t DATA_START;
|
||||
extern uint32_t DATA_END;
|
||||
extern uint32_t RODATA_START;
|
||||
extern uint32_t RODATA_END;
|
||||
extern uint32_t BSS_START;
|
||||
extern uint32_t BSS_END;
|
||||
extern uint32_t HEAP_START;
|
||||
extern uint32_t HEAP_SIZE;
|
||||
extern ptr_t TEXT_START;
|
||||
extern ptr_t TEXT_END;
|
||||
extern ptr_t DATA_START;
|
||||
extern ptr_t DATA_END;
|
||||
extern ptr_t RODATA_START;
|
||||
extern ptr_t RODATA_END;
|
||||
extern ptr_t BSS_START;
|
||||
extern ptr_t BSS_END;
|
||||
extern ptr_t HEAP_START;
|
||||
extern ptr_t HEAP_SIZE;
|
||||
|
||||
/*
|
||||
* _alloc_start points to the actual start address of heap pool
|
||||
* _alloc_end points to the actual end address of heap pool
|
||||
* _num_pages holds the actual max number of pages we can allocate.
|
||||
*/
|
||||
static uint32_t _alloc_start = 0;
|
||||
static uint32_t _alloc_end = 0;
|
||||
static ptr_t _alloc_start = 0;
|
||||
static ptr_t _alloc_end = 0;
|
||||
static uint32_t _num_pages = 0;
|
||||
|
||||
#define PAGE_SIZE 4096
|
||||
@@ -70,9 +70,9 @@ static inline int _is_last(struct Page *page)
|
||||
/*
|
||||
* align the address to the border of page(4K)
|
||||
*/
|
||||
static inline uint32_t _align_page(uint32_t address)
|
||||
static inline ptr_t _align_page(ptr_t address)
|
||||
{
|
||||
uint32_t order = (1 << PAGE_ORDER) - 1;
|
||||
ptr_t order = (1 << PAGE_ORDER) - 1;
|
||||
return (address + order) & (~order);
|
||||
}
|
||||
|
||||
@@ -155,12 +155,12 @@ void page_free(void *p)
|
||||
/*
|
||||
* Assert (TBD) if p is invalid
|
||||
*/
|
||||
if (!p || (uint32_t)p >= _alloc_end) {
|
||||
if (!p || (ptr_t)p >= _alloc_end) {
|
||||
return;
|
||||
}
|
||||
/* get the first page descriptor of this memory block */
|
||||
struct Page *page = (struct Page *)HEAP_START;
|
||||
page += ((uint32_t)p - _alloc_start)/ PAGE_SIZE;
|
||||
page += ((ptr_t)p - _alloc_start)/ PAGE_SIZE;
|
||||
/* loop and clear all the page descriptors of the memory block */
|
||||
while (!_is_free(page)) {
|
||||
if (_is_last(page)) {
|
||||
|
||||
@@ -92,6 +92,10 @@ static inline void w_mie(reg_t x)
|
||||
asm volatile("csrw mie, %0" : : "r" (x));
|
||||
}
|
||||
|
||||
/* Machine-mode Cause Masks */
|
||||
#define MCAUSE_MASK_INTERRUPT (reg_t)0x80000000
|
||||
#define MCAUSE_MASK_ECODE (reg_t)0x7FFFFFFF
|
||||
|
||||
static inline reg_t r_mcause()
|
||||
{
|
||||
reg_t x;
|
||||
|
||||
@@ -29,9 +29,9 @@ void external_interrupt_handler()
|
||||
reg_t trap_handler(reg_t epc, reg_t cause)
|
||||
{
|
||||
reg_t return_pc = epc;
|
||||
reg_t cause_code = cause & 0xfff;
|
||||
reg_t cause_code = cause & MCAUSE_MASK_ECODE;
|
||||
|
||||
if (cause & 0x80000000) {
|
||||
if (cause & MCAUSE_MASK_INTERRUPT) {
|
||||
/* Asynchronous trap - interrupt */
|
||||
switch (cause_code) {
|
||||
case 3:
|
||||
|
||||
@@ -7,8 +7,9 @@ typedef unsigned int uint32_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
|
||||
/*
|
||||
* RISCV32: register is 32bits width
|
||||
*/
|
||||
* Register Width
|
||||
*/
|
||||
typedef uint32_t reg_t;
|
||||
typedef uint32_t ptr_t;
|
||||
|
||||
#endif /* __TYPES_H__ */
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
#define LOAD lw
|
||||
#define STORE sw
|
||||
#define SIZE_REG 4
|
||||
|
||||
# Save all General-Purpose(GP) registers to context.
|
||||
# struct context *base = &ctx_task;
|
||||
# base->ra = ra;
|
||||
@@ -10,34 +14,34 @@
|
||||
# which is a global value and would not be changed
|
||||
# during context-switch.
|
||||
.macro reg_save base
|
||||
sw ra, 0(\base)
|
||||
sw sp, 4(\base)
|
||||
sw t0, 16(\base)
|
||||
sw t1, 20(\base)
|
||||
sw t2, 24(\base)
|
||||
sw s0, 28(\base)
|
||||
sw s1, 32(\base)
|
||||
sw a0, 36(\base)
|
||||
sw a1, 40(\base)
|
||||
sw a2, 44(\base)
|
||||
sw a3, 48(\base)
|
||||
sw a4, 52(\base)
|
||||
sw a5, 56(\base)
|
||||
sw a6, 60(\base)
|
||||
sw a7, 64(\base)
|
||||
sw s2, 68(\base)
|
||||
sw s3, 72(\base)
|
||||
sw s4, 76(\base)
|
||||
sw s5, 80(\base)
|
||||
sw s6, 84(\base)
|
||||
sw s7, 88(\base)
|
||||
sw s8, 92(\base)
|
||||
sw s9, 96(\base)
|
||||
sw s10, 100(\base)
|
||||
sw s11, 104(\base)
|
||||
sw t3, 108(\base)
|
||||
sw t4, 112(\base)
|
||||
sw t5, 116(\base)
|
||||
STORE ra, 0*SIZE_REG(\base)
|
||||
STORE sp, 1*SIZE_REG(\base)
|
||||
STORE t0, 4*SIZE_REG(\base)
|
||||
STORE t1, 5*SIZE_REG(\base)
|
||||
STORE t2, 6*SIZE_REG(\base)
|
||||
STORE s0, 7*SIZE_REG(\base)
|
||||
STORE s1, 8*SIZE_REG(\base)
|
||||
STORE a0, 9*SIZE_REG(\base)
|
||||
STORE a1, 10*SIZE_REG(\base)
|
||||
STORE a2, 11*SIZE_REG(\base)
|
||||
STORE a3, 12*SIZE_REG(\base)
|
||||
STORE a4, 13*SIZE_REG(\base)
|
||||
STORE a5, 14*SIZE_REG(\base)
|
||||
STORE a6, 15*SIZE_REG(\base)
|
||||
STORE a7, 16*SIZE_REG(\base)
|
||||
STORE s2, 17*SIZE_REG(\base)
|
||||
STORE s3, 18*SIZE_REG(\base)
|
||||
STORE s4, 19*SIZE_REG(\base)
|
||||
STORE s5, 20*SIZE_REG(\base)
|
||||
STORE s6, 21*SIZE_REG(\base)
|
||||
STORE s7, 22*SIZE_REG(\base)
|
||||
STORE s8, 23*SIZE_REG(\base)
|
||||
STORE s9, 24*SIZE_REG(\base)
|
||||
STORE s10, 25*SIZE_REG(\base)
|
||||
STORE s11, 26*SIZE_REG(\base)
|
||||
STORE t3, 27*SIZE_REG(\base)
|
||||
STORE t4, 28*SIZE_REG(\base)
|
||||
STORE t5, 29*SIZE_REG(\base)
|
||||
# we don't save t6 here, due to we have used
|
||||
# it as base, we have to save t6 in an extra step
|
||||
# outside of reg_save
|
||||
@@ -49,35 +53,35 @@
|
||||
# ra = base->ra;
|
||||
# ......
|
||||
.macro reg_restore base
|
||||
lw ra, 0(\base)
|
||||
lw sp, 4(\base)
|
||||
lw t0, 16(\base)
|
||||
lw t1, 20(\base)
|
||||
lw t2, 24(\base)
|
||||
lw s0, 28(\base)
|
||||
lw s1, 32(\base)
|
||||
lw a0, 36(\base)
|
||||
lw a1, 40(\base)
|
||||
lw a2, 44(\base)
|
||||
lw a3, 48(\base)
|
||||
lw a4, 52(\base)
|
||||
lw a5, 56(\base)
|
||||
lw a6, 60(\base)
|
||||
lw a7, 64(\base)
|
||||
lw s2, 68(\base)
|
||||
lw s3, 72(\base)
|
||||
lw s4, 76(\base)
|
||||
lw s5, 80(\base)
|
||||
lw s6, 84(\base)
|
||||
lw s7, 88(\base)
|
||||
lw s8, 92(\base)
|
||||
lw s9, 96(\base)
|
||||
lw s10, 100(\base)
|
||||
lw s11, 104(\base)
|
||||
lw t3, 108(\base)
|
||||
lw t4, 112(\base)
|
||||
lw t5, 116(\base)
|
||||
lw t6, 120(\base)
|
||||
LOAD ra, 0*SIZE_REG(\base)
|
||||
LOAD sp, 1*SIZE_REG(\base)
|
||||
LOAD t0, 4*SIZE_REG(\base)
|
||||
LOAD t1, 5*SIZE_REG(\base)
|
||||
LOAD t2, 6*SIZE_REG(\base)
|
||||
LOAD s0, 7*SIZE_REG(\base)
|
||||
LOAD s1, 8*SIZE_REG(\base)
|
||||
LOAD a0, 9*SIZE_REG(\base)
|
||||
LOAD a1, 10*SIZE_REG(\base)
|
||||
LOAD a2, 11*SIZE_REG(\base)
|
||||
LOAD a3, 12*SIZE_REG(\base)
|
||||
LOAD a4, 13*SIZE_REG(\base)
|
||||
LOAD a5, 14*SIZE_REG(\base)
|
||||
LOAD a6, 15*SIZE_REG(\base)
|
||||
LOAD a7, 16*SIZE_REG(\base)
|
||||
LOAD s2, 17*SIZE_REG(\base)
|
||||
LOAD s3, 18*SIZE_REG(\base)
|
||||
LOAD s4, 19*SIZE_REG(\base)
|
||||
LOAD s5, 20*SIZE_REG(\base)
|
||||
LOAD s6, 21*SIZE_REG(\base)
|
||||
LOAD s7, 22*SIZE_REG(\base)
|
||||
LOAD s8, 23*SIZE_REG(\base)
|
||||
LOAD s9, 24*SIZE_REG(\base)
|
||||
LOAD s10, 25*SIZE_REG(\base)
|
||||
LOAD s11, 26*SIZE_REG(\base)
|
||||
LOAD t3, 27*SIZE_REG(\base)
|
||||
LOAD t4, 28*SIZE_REG(\base)
|
||||
LOAD t5, 29*SIZE_REG(\base)
|
||||
LOAD t6, 30*SIZE_REG(\base)
|
||||
.endm
|
||||
|
||||
# Something to note about save/restore:
|
||||
@@ -100,9 +104,9 @@ trap_vector:
|
||||
|
||||
# Save the actual t6 register, which we swapped into
|
||||
# mscratch
|
||||
mv t5, t6 # t5 points to the context of current task
|
||||
csrr t6, mscratch # read t6 back from mscratch
|
||||
sw t6, 120(t5) # save t6 with t5 as base
|
||||
mv t5, t6 # t5 points to the context of current task
|
||||
csrr t6, mscratch # read t6 back from mscratch
|
||||
STORE t6, 30*SIZE_REG(t5) # save t6 with t5 as base
|
||||
|
||||
# Restore the context pointer into mscratch
|
||||
csrw mscratch, t5
|
||||
@@ -137,9 +141,9 @@ switch_to:
|
||||
|
||||
# Save the actual t6 register, which we swapped into
|
||||
# mscratch
|
||||
mv t5, t6 # t5 points to the context of current task
|
||||
csrr t6, mscratch # read t6 back from mscratch
|
||||
sw t6, 120(t5) # save t6 with t5 as base
|
||||
mv t5, t6 # t5 points to the context of current task
|
||||
csrr t6, mscratch # read t6 back from mscratch
|
||||
STORE t6, 30*SIZE_REG(t5) # save t6 with t5 as base
|
||||
|
||||
1:
|
||||
# switch mscratch to point to the context of the next task
|
||||
|
||||
@@ -1,30 +1,32 @@
|
||||
#define SIZE_PTR .word
|
||||
|
||||
.section .rodata
|
||||
.global HEAP_START
|
||||
HEAP_START: .word _heap_start
|
||||
HEAP_START: SIZE_PTR _heap_start
|
||||
|
||||
.global HEAP_SIZE
|
||||
HEAP_SIZE: .word _heap_size
|
||||
HEAP_SIZE: SIZE_PTR _heap_size
|
||||
|
||||
.global TEXT_START
|
||||
TEXT_START: .word _text_start
|
||||
TEXT_START: SIZE_PTR _text_start
|
||||
|
||||
.global TEXT_END
|
||||
TEXT_END: .word _text_end
|
||||
TEXT_END: SIZE_PTR _text_end
|
||||
|
||||
.global DATA_START
|
||||
DATA_START: .word _data_start
|
||||
DATA_START: SIZE_PTR _data_start
|
||||
|
||||
.global DATA_END
|
||||
DATA_END: .word _data_end
|
||||
DATA_END: SIZE_PTR _data_end
|
||||
|
||||
.global RODATA_START
|
||||
RODATA_START: .word _rodata_start
|
||||
RODATA_START: SIZE_PTR _rodata_start
|
||||
|
||||
.global RODATA_END
|
||||
RODATA_END: .word _rodata_end
|
||||
RODATA_END: SIZE_PTR _rodata_end
|
||||
|
||||
.global BSS_START
|
||||
BSS_START: .word _bss_start
|
||||
BSS_START: SIZE_PTR _bss_start
|
||||
|
||||
.global BSS_END
|
||||
BSS_END: .word _bss_end
|
||||
BSS_END: SIZE_PTR _bss_end
|
||||
|
||||
@@ -3,24 +3,24 @@
|
||||
/*
|
||||
* Following global vars are defined in mem.S
|
||||
*/
|
||||
extern uint32_t TEXT_START;
|
||||
extern uint32_t TEXT_END;
|
||||
extern uint32_t DATA_START;
|
||||
extern uint32_t DATA_END;
|
||||
extern uint32_t RODATA_START;
|
||||
extern uint32_t RODATA_END;
|
||||
extern uint32_t BSS_START;
|
||||
extern uint32_t BSS_END;
|
||||
extern uint32_t HEAP_START;
|
||||
extern uint32_t HEAP_SIZE;
|
||||
extern ptr_t TEXT_START;
|
||||
extern ptr_t TEXT_END;
|
||||
extern ptr_t DATA_START;
|
||||
extern ptr_t DATA_END;
|
||||
extern ptr_t RODATA_START;
|
||||
extern ptr_t RODATA_END;
|
||||
extern ptr_t BSS_START;
|
||||
extern ptr_t BSS_END;
|
||||
extern ptr_t HEAP_START;
|
||||
extern ptr_t HEAP_SIZE;
|
||||
|
||||
/*
|
||||
* _alloc_start points to the actual start address of heap pool
|
||||
* _alloc_end points to the actual end address of heap pool
|
||||
* _num_pages holds the actual max number of pages we can allocate.
|
||||
*/
|
||||
static uint32_t _alloc_start = 0;
|
||||
static uint32_t _alloc_end = 0;
|
||||
static ptr_t _alloc_start = 0;
|
||||
static ptr_t _alloc_end = 0;
|
||||
static uint32_t _num_pages = 0;
|
||||
|
||||
#define PAGE_SIZE 4096
|
||||
@@ -70,9 +70,9 @@ static inline int _is_last(struct Page *page)
|
||||
/*
|
||||
* align the address to the border of page(4K)
|
||||
*/
|
||||
static inline uint32_t _align_page(uint32_t address)
|
||||
static inline ptr_t _align_page(ptr_t address)
|
||||
{
|
||||
uint32_t order = (1 << PAGE_ORDER) - 1;
|
||||
ptr_t order = (1 << PAGE_ORDER) - 1;
|
||||
return (address + order) & (~order);
|
||||
}
|
||||
|
||||
@@ -155,12 +155,12 @@ void page_free(void *p)
|
||||
/*
|
||||
* Assert (TBD) if p is invalid
|
||||
*/
|
||||
if (!p || (uint32_t)p >= _alloc_end) {
|
||||
if (!p || (ptr_t)p >= _alloc_end) {
|
||||
return;
|
||||
}
|
||||
/* get the first page descriptor of this memory block */
|
||||
struct Page *page = (struct Page *)HEAP_START;
|
||||
page += ((uint32_t)p - _alloc_start)/ PAGE_SIZE;
|
||||
page += ((ptr_t)p - _alloc_start)/ PAGE_SIZE;
|
||||
/* loop and clear all the page descriptors of the memory block */
|
||||
while (!_is_free(page)) {
|
||||
if (_is_last(page)) {
|
||||
|
||||
@@ -92,6 +92,10 @@ static inline void w_mie(reg_t x)
|
||||
asm volatile("csrw mie, %0" : : "r" (x));
|
||||
}
|
||||
|
||||
/* Machine-mode Cause Masks */
|
||||
#define MCAUSE_MASK_INTERRUPT (reg_t)0x80000000
|
||||
#define MCAUSE_MASK_ECODE (reg_t)0x7FFFFFFF
|
||||
|
||||
static inline reg_t r_mcause()
|
||||
{
|
||||
reg_t x;
|
||||
|
||||
@@ -30,9 +30,9 @@ void external_interrupt_handler()
|
||||
reg_t trap_handler(reg_t epc, reg_t cause)
|
||||
{
|
||||
reg_t return_pc = epc;
|
||||
reg_t cause_code = cause & 0xfff;
|
||||
reg_t cause_code = cause & MCAUSE_MASK_ECODE;
|
||||
|
||||
if (cause & 0x80000000) {
|
||||
if (cause & MCAUSE_MASK_INTERRUPT) {
|
||||
/* Asynchronous trap - interrupt */
|
||||
switch (cause_code) {
|
||||
case 3:
|
||||
|
||||
@@ -7,8 +7,9 @@ typedef unsigned int uint32_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
|
||||
/*
|
||||
* RISCV32: register is 32bits width
|
||||
*/
|
||||
* Register Width
|
||||
*/
|
||||
typedef uint32_t reg_t;
|
||||
typedef uint32_t ptr_t;
|
||||
|
||||
#endif /* __TYPES_H__ */
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
#define LOAD lw
|
||||
#define STORE sw
|
||||
#define SIZE_REG 4
|
||||
|
||||
# Save all General-Purpose(GP) registers to context.
|
||||
# struct context *base = &ctx_task;
|
||||
# base->ra = ra;
|
||||
@@ -10,34 +14,34 @@
|
||||
# which is a global value and would not be changed
|
||||
# during context-switch.
|
||||
.macro reg_save base
|
||||
sw ra, 0(\base)
|
||||
sw sp, 4(\base)
|
||||
sw t0, 16(\base)
|
||||
sw t1, 20(\base)
|
||||
sw t2, 24(\base)
|
||||
sw s0, 28(\base)
|
||||
sw s1, 32(\base)
|
||||
sw a0, 36(\base)
|
||||
sw a1, 40(\base)
|
||||
sw a2, 44(\base)
|
||||
sw a3, 48(\base)
|
||||
sw a4, 52(\base)
|
||||
sw a5, 56(\base)
|
||||
sw a6, 60(\base)
|
||||
sw a7, 64(\base)
|
||||
sw s2, 68(\base)
|
||||
sw s3, 72(\base)
|
||||
sw s4, 76(\base)
|
||||
sw s5, 80(\base)
|
||||
sw s6, 84(\base)
|
||||
sw s7, 88(\base)
|
||||
sw s8, 92(\base)
|
||||
sw s9, 96(\base)
|
||||
sw s10, 100(\base)
|
||||
sw s11, 104(\base)
|
||||
sw t3, 108(\base)
|
||||
sw t4, 112(\base)
|
||||
sw t5, 116(\base)
|
||||
STORE ra, 0*SIZE_REG(\base)
|
||||
STORE sp, 1*SIZE_REG(\base)
|
||||
STORE t0, 4*SIZE_REG(\base)
|
||||
STORE t1, 5*SIZE_REG(\base)
|
||||
STORE t2, 6*SIZE_REG(\base)
|
||||
STORE s0, 7*SIZE_REG(\base)
|
||||
STORE s1, 8*SIZE_REG(\base)
|
||||
STORE a0, 9*SIZE_REG(\base)
|
||||
STORE a1, 10*SIZE_REG(\base)
|
||||
STORE a2, 11*SIZE_REG(\base)
|
||||
STORE a3, 12*SIZE_REG(\base)
|
||||
STORE a4, 13*SIZE_REG(\base)
|
||||
STORE a5, 14*SIZE_REG(\base)
|
||||
STORE a6, 15*SIZE_REG(\base)
|
||||
STORE a7, 16*SIZE_REG(\base)
|
||||
STORE s2, 17*SIZE_REG(\base)
|
||||
STORE s3, 18*SIZE_REG(\base)
|
||||
STORE s4, 19*SIZE_REG(\base)
|
||||
STORE s5, 20*SIZE_REG(\base)
|
||||
STORE s6, 21*SIZE_REG(\base)
|
||||
STORE s7, 22*SIZE_REG(\base)
|
||||
STORE s8, 23*SIZE_REG(\base)
|
||||
STORE s9, 24*SIZE_REG(\base)
|
||||
STORE s10, 25*SIZE_REG(\base)
|
||||
STORE s11, 26*SIZE_REG(\base)
|
||||
STORE t3, 27*SIZE_REG(\base)
|
||||
STORE t4, 28*SIZE_REG(\base)
|
||||
STORE t5, 29*SIZE_REG(\base)
|
||||
# we don't save t6 here, due to we have used
|
||||
# it as base, we have to save t6 in an extra step
|
||||
# outside of reg_save
|
||||
@@ -49,35 +53,35 @@
|
||||
# ra = base->ra;
|
||||
# ......
|
||||
.macro reg_restore base
|
||||
lw ra, 0(\base)
|
||||
lw sp, 4(\base)
|
||||
lw t0, 16(\base)
|
||||
lw t1, 20(\base)
|
||||
lw t2, 24(\base)
|
||||
lw s0, 28(\base)
|
||||
lw s1, 32(\base)
|
||||
lw a0, 36(\base)
|
||||
lw a1, 40(\base)
|
||||
lw a2, 44(\base)
|
||||
lw a3, 48(\base)
|
||||
lw a4, 52(\base)
|
||||
lw a5, 56(\base)
|
||||
lw a6, 60(\base)
|
||||
lw a7, 64(\base)
|
||||
lw s2, 68(\base)
|
||||
lw s3, 72(\base)
|
||||
lw s4, 76(\base)
|
||||
lw s5, 80(\base)
|
||||
lw s6, 84(\base)
|
||||
lw s7, 88(\base)
|
||||
lw s8, 92(\base)
|
||||
lw s9, 96(\base)
|
||||
lw s10, 100(\base)
|
||||
lw s11, 104(\base)
|
||||
lw t3, 108(\base)
|
||||
lw t4, 112(\base)
|
||||
lw t5, 116(\base)
|
||||
lw t6, 120(\base)
|
||||
LOAD ra, 0*SIZE_REG(\base)
|
||||
LOAD sp, 1*SIZE_REG(\base)
|
||||
LOAD t0, 4*SIZE_REG(\base)
|
||||
LOAD t1, 5*SIZE_REG(\base)
|
||||
LOAD t2, 6*SIZE_REG(\base)
|
||||
LOAD s0, 7*SIZE_REG(\base)
|
||||
LOAD s1, 8*SIZE_REG(\base)
|
||||
LOAD a0, 9*SIZE_REG(\base)
|
||||
LOAD a1, 10*SIZE_REG(\base)
|
||||
LOAD a2, 11*SIZE_REG(\base)
|
||||
LOAD a3, 12*SIZE_REG(\base)
|
||||
LOAD a4, 13*SIZE_REG(\base)
|
||||
LOAD a5, 14*SIZE_REG(\base)
|
||||
LOAD a6, 15*SIZE_REG(\base)
|
||||
LOAD a7, 16*SIZE_REG(\base)
|
||||
LOAD s2, 17*SIZE_REG(\base)
|
||||
LOAD s3, 18*SIZE_REG(\base)
|
||||
LOAD s4, 19*SIZE_REG(\base)
|
||||
LOAD s5, 20*SIZE_REG(\base)
|
||||
LOAD s6, 21*SIZE_REG(\base)
|
||||
LOAD s7, 22*SIZE_REG(\base)
|
||||
LOAD s8, 23*SIZE_REG(\base)
|
||||
LOAD s9, 24*SIZE_REG(\base)
|
||||
LOAD s10, 25*SIZE_REG(\base)
|
||||
LOAD s11, 26*SIZE_REG(\base)
|
||||
LOAD t3, 27*SIZE_REG(\base)
|
||||
LOAD t4, 28*SIZE_REG(\base)
|
||||
LOAD t5, 29*SIZE_REG(\base)
|
||||
LOAD t6, 30*SIZE_REG(\base)
|
||||
.endm
|
||||
|
||||
# Something to note about save/restore:
|
||||
@@ -100,13 +104,13 @@ trap_vector:
|
||||
|
||||
# Save the actual t6 register, which we swapped into
|
||||
# mscratch
|
||||
mv t5, t6 # t5 points to the context of current task
|
||||
csrr t6, mscratch # read t6 back from mscratch
|
||||
sw t6, 120(t5) # save t6 with t5 as base
|
||||
mv t5, t6 # t5 points to the context of current task
|
||||
csrr t6, mscratch # read t6 back from mscratch
|
||||
STORE t6, 30*SIZE_REG(t5) # save t6 with t5 as base
|
||||
|
||||
# save mepc to context of current task
|
||||
csrr a0, mepc
|
||||
sw a0, 124(t5)
|
||||
STORE a0, 31*SIZE_REG(t5)
|
||||
|
||||
# Restore the context pointer into mscratch
|
||||
csrw mscratch, t5
|
||||
@@ -134,7 +138,7 @@ switch_to:
|
||||
# switch mscratch to point to the context of the next task
|
||||
csrw mscratch, a0
|
||||
# set mepc to the pc of the next task
|
||||
lw a1, 124(a0)
|
||||
LOAD a1, 31*SIZE_REG(a0)
|
||||
csrw mepc, a1
|
||||
|
||||
# Restore all GP registers
|
||||
|
||||
@@ -1,30 +1,32 @@
|
||||
#define SIZE_PTR .word
|
||||
|
||||
.section .rodata
|
||||
.global HEAP_START
|
||||
HEAP_START: .word _heap_start
|
||||
HEAP_START: SIZE_PTR _heap_start
|
||||
|
||||
.global HEAP_SIZE
|
||||
HEAP_SIZE: .word _heap_size
|
||||
HEAP_SIZE: SIZE_PTR _heap_size
|
||||
|
||||
.global TEXT_START
|
||||
TEXT_START: .word _text_start
|
||||
TEXT_START: SIZE_PTR _text_start
|
||||
|
||||
.global TEXT_END
|
||||
TEXT_END: .word _text_end
|
||||
TEXT_END: SIZE_PTR _text_end
|
||||
|
||||
.global DATA_START
|
||||
DATA_START: .word _data_start
|
||||
DATA_START: SIZE_PTR _data_start
|
||||
|
||||
.global DATA_END
|
||||
DATA_END: .word _data_end
|
||||
DATA_END: SIZE_PTR _data_end
|
||||
|
||||
.global RODATA_START
|
||||
RODATA_START: .word _rodata_start
|
||||
RODATA_START: SIZE_PTR _rodata_start
|
||||
|
||||
.global RODATA_END
|
||||
RODATA_END: .word _rodata_end
|
||||
RODATA_END: SIZE_PTR _rodata_end
|
||||
|
||||
.global BSS_START
|
||||
BSS_START: .word _bss_start
|
||||
BSS_START: SIZE_PTR _bss_start
|
||||
|
||||
.global BSS_END
|
||||
BSS_END: .word _bss_end
|
||||
BSS_END: SIZE_PTR _bss_end
|
||||
|
||||
@@ -58,7 +58,7 @@ struct context {
|
||||
// upon is trap frame
|
||||
|
||||
// save the pc to run in next schedule cycle
|
||||
reg_t pc; // offset: 31 *4 = 124
|
||||
reg_t pc; // offset: 31 * sizeof(reg_t)
|
||||
};
|
||||
|
||||
extern int task_create(void (*task)(void));
|
||||
|
||||
@@ -3,24 +3,24 @@
|
||||
/*
|
||||
* Following global vars are defined in mem.S
|
||||
*/
|
||||
extern uint32_t TEXT_START;
|
||||
extern uint32_t TEXT_END;
|
||||
extern uint32_t DATA_START;
|
||||
extern uint32_t DATA_END;
|
||||
extern uint32_t RODATA_START;
|
||||
extern uint32_t RODATA_END;
|
||||
extern uint32_t BSS_START;
|
||||
extern uint32_t BSS_END;
|
||||
extern uint32_t HEAP_START;
|
||||
extern uint32_t HEAP_SIZE;
|
||||
extern ptr_t TEXT_START;
|
||||
extern ptr_t TEXT_END;
|
||||
extern ptr_t DATA_START;
|
||||
extern ptr_t DATA_END;
|
||||
extern ptr_t RODATA_START;
|
||||
extern ptr_t RODATA_END;
|
||||
extern ptr_t BSS_START;
|
||||
extern ptr_t BSS_END;
|
||||
extern ptr_t HEAP_START;
|
||||
extern ptr_t HEAP_SIZE;
|
||||
|
||||
/*
|
||||
* _alloc_start points to the actual start address of heap pool
|
||||
* _alloc_end points to the actual end address of heap pool
|
||||
* _num_pages holds the actual max number of pages we can allocate.
|
||||
*/
|
||||
static uint32_t _alloc_start = 0;
|
||||
static uint32_t _alloc_end = 0;
|
||||
static ptr_t _alloc_start = 0;
|
||||
static ptr_t _alloc_end = 0;
|
||||
static uint32_t _num_pages = 0;
|
||||
|
||||
#define PAGE_SIZE 4096
|
||||
@@ -70,9 +70,9 @@ static inline int _is_last(struct Page *page)
|
||||
/*
|
||||
* align the address to the border of page(4K)
|
||||
*/
|
||||
static inline uint32_t _align_page(uint32_t address)
|
||||
static inline ptr_t _align_page(ptr_t address)
|
||||
{
|
||||
uint32_t order = (1 << PAGE_ORDER) - 1;
|
||||
ptr_t order = (1 << PAGE_ORDER) - 1;
|
||||
return (address + order) & (~order);
|
||||
}
|
||||
|
||||
@@ -155,12 +155,12 @@ void page_free(void *p)
|
||||
/*
|
||||
* Assert (TBD) if p is invalid
|
||||
*/
|
||||
if (!p || (uint32_t)p >= _alloc_end) {
|
||||
if (!p || (ptr_t)p >= _alloc_end) {
|
||||
return;
|
||||
}
|
||||
/* get the first page descriptor of this memory block */
|
||||
struct Page *page = (struct Page *)HEAP_START;
|
||||
page += ((uint32_t)p - _alloc_start)/ PAGE_SIZE;
|
||||
page += ((ptr_t)p - _alloc_start)/ PAGE_SIZE;
|
||||
/* loop and clear all the page descriptors of the memory block */
|
||||
while (!_is_free(page)) {
|
||||
if (_is_last(page)) {
|
||||
|
||||
@@ -92,6 +92,10 @@ static inline void w_mie(reg_t x)
|
||||
asm volatile("csrw mie, %0" : : "r" (x));
|
||||
}
|
||||
|
||||
/* Machine-mode Cause Masks */
|
||||
#define MCAUSE_MASK_INTERRUPT (reg_t)0x80000000
|
||||
#define MCAUSE_MASK_ECODE (reg_t)0x7FFFFFFF
|
||||
|
||||
static inline reg_t r_mcause()
|
||||
{
|
||||
reg_t x;
|
||||
|
||||
@@ -31,9 +31,9 @@ void external_interrupt_handler()
|
||||
reg_t trap_handler(reg_t epc, reg_t cause)
|
||||
{
|
||||
reg_t return_pc = epc;
|
||||
reg_t cause_code = cause & 0xfff;
|
||||
reg_t cause_code = cause & MCAUSE_MASK_ECODE;
|
||||
|
||||
if (cause & 0x80000000) {
|
||||
if (cause & MCAUSE_MASK_INTERRUPT) {
|
||||
/* Asynchronous trap - interrupt */
|
||||
switch (cause_code) {
|
||||
case 3:
|
||||
|
||||
@@ -7,8 +7,9 @@ typedef unsigned int uint32_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
|
||||
/*
|
||||
* RISCV32: register is 32bits width
|
||||
*/
|
||||
* Register Width
|
||||
*/
|
||||
typedef uint32_t reg_t;
|
||||
typedef uint32_t ptr_t;
|
||||
|
||||
#endif /* __TYPES_H__ */
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
#define LOAD lw
|
||||
#define STORE sw
|
||||
#define SIZE_REG 4
|
||||
|
||||
# Save all General-Purpose(GP) registers to context.
|
||||
# struct context *base = &ctx_task;
|
||||
# base->ra = ra;
|
||||
@@ -10,34 +14,34 @@
|
||||
# which is a global value and would not be changed
|
||||
# during context-switch.
|
||||
.macro reg_save base
|
||||
sw ra, 0(\base)
|
||||
sw sp, 4(\base)
|
||||
sw t0, 16(\base)
|
||||
sw t1, 20(\base)
|
||||
sw t2, 24(\base)
|
||||
sw s0, 28(\base)
|
||||
sw s1, 32(\base)
|
||||
sw a0, 36(\base)
|
||||
sw a1, 40(\base)
|
||||
sw a2, 44(\base)
|
||||
sw a3, 48(\base)
|
||||
sw a4, 52(\base)
|
||||
sw a5, 56(\base)
|
||||
sw a6, 60(\base)
|
||||
sw a7, 64(\base)
|
||||
sw s2, 68(\base)
|
||||
sw s3, 72(\base)
|
||||
sw s4, 76(\base)
|
||||
sw s5, 80(\base)
|
||||
sw s6, 84(\base)
|
||||
sw s7, 88(\base)
|
||||
sw s8, 92(\base)
|
||||
sw s9, 96(\base)
|
||||
sw s10, 100(\base)
|
||||
sw s11, 104(\base)
|
||||
sw t3, 108(\base)
|
||||
sw t4, 112(\base)
|
||||
sw t5, 116(\base)
|
||||
STORE ra, 0*SIZE_REG(\base)
|
||||
STORE sp, 1*SIZE_REG(\base)
|
||||
STORE t0, 4*SIZE_REG(\base)
|
||||
STORE t1, 5*SIZE_REG(\base)
|
||||
STORE t2, 6*SIZE_REG(\base)
|
||||
STORE s0, 7*SIZE_REG(\base)
|
||||
STORE s1, 8*SIZE_REG(\base)
|
||||
STORE a0, 9*SIZE_REG(\base)
|
||||
STORE a1, 10*SIZE_REG(\base)
|
||||
STORE a2, 11*SIZE_REG(\base)
|
||||
STORE a3, 12*SIZE_REG(\base)
|
||||
STORE a4, 13*SIZE_REG(\base)
|
||||
STORE a5, 14*SIZE_REG(\base)
|
||||
STORE a6, 15*SIZE_REG(\base)
|
||||
STORE a7, 16*SIZE_REG(\base)
|
||||
STORE s2, 17*SIZE_REG(\base)
|
||||
STORE s3, 18*SIZE_REG(\base)
|
||||
STORE s4, 19*SIZE_REG(\base)
|
||||
STORE s5, 20*SIZE_REG(\base)
|
||||
STORE s6, 21*SIZE_REG(\base)
|
||||
STORE s7, 22*SIZE_REG(\base)
|
||||
STORE s8, 23*SIZE_REG(\base)
|
||||
STORE s9, 24*SIZE_REG(\base)
|
||||
STORE s10, 25*SIZE_REG(\base)
|
||||
STORE s11, 26*SIZE_REG(\base)
|
||||
STORE t3, 27*SIZE_REG(\base)
|
||||
STORE t4, 28*SIZE_REG(\base)
|
||||
STORE t5, 29*SIZE_REG(\base)
|
||||
# we don't save t6 here, due to we have used
|
||||
# it as base, we have to save t6 in an extra step
|
||||
# outside of reg_save
|
||||
@@ -49,35 +53,35 @@
|
||||
# ra = base->ra;
|
||||
# ......
|
||||
.macro reg_restore base
|
||||
lw ra, 0(\base)
|
||||
lw sp, 4(\base)
|
||||
lw t0, 16(\base)
|
||||
lw t1, 20(\base)
|
||||
lw t2, 24(\base)
|
||||
lw s0, 28(\base)
|
||||
lw s1, 32(\base)
|
||||
lw a0, 36(\base)
|
||||
lw a1, 40(\base)
|
||||
lw a2, 44(\base)
|
||||
lw a3, 48(\base)
|
||||
lw a4, 52(\base)
|
||||
lw a5, 56(\base)
|
||||
lw a6, 60(\base)
|
||||
lw a7, 64(\base)
|
||||
lw s2, 68(\base)
|
||||
lw s3, 72(\base)
|
||||
lw s4, 76(\base)
|
||||
lw s5, 80(\base)
|
||||
lw s6, 84(\base)
|
||||
lw s7, 88(\base)
|
||||
lw s8, 92(\base)
|
||||
lw s9, 96(\base)
|
||||
lw s10, 100(\base)
|
||||
lw s11, 104(\base)
|
||||
lw t3, 108(\base)
|
||||
lw t4, 112(\base)
|
||||
lw t5, 116(\base)
|
||||
lw t6, 120(\base)
|
||||
LOAD ra, 0*SIZE_REG(\base)
|
||||
LOAD sp, 1*SIZE_REG(\base)
|
||||
LOAD t0, 4*SIZE_REG(\base)
|
||||
LOAD t1, 5*SIZE_REG(\base)
|
||||
LOAD t2, 6*SIZE_REG(\base)
|
||||
LOAD s0, 7*SIZE_REG(\base)
|
||||
LOAD s1, 8*SIZE_REG(\base)
|
||||
LOAD a0, 9*SIZE_REG(\base)
|
||||
LOAD a1, 10*SIZE_REG(\base)
|
||||
LOAD a2, 11*SIZE_REG(\base)
|
||||
LOAD a3, 12*SIZE_REG(\base)
|
||||
LOAD a4, 13*SIZE_REG(\base)
|
||||
LOAD a5, 14*SIZE_REG(\base)
|
||||
LOAD a6, 15*SIZE_REG(\base)
|
||||
LOAD a7, 16*SIZE_REG(\base)
|
||||
LOAD s2, 17*SIZE_REG(\base)
|
||||
LOAD s3, 18*SIZE_REG(\base)
|
||||
LOAD s4, 19*SIZE_REG(\base)
|
||||
LOAD s5, 20*SIZE_REG(\base)
|
||||
LOAD s6, 21*SIZE_REG(\base)
|
||||
LOAD s7, 22*SIZE_REG(\base)
|
||||
LOAD s8, 23*SIZE_REG(\base)
|
||||
LOAD s9, 24*SIZE_REG(\base)
|
||||
LOAD s10, 25*SIZE_REG(\base)
|
||||
LOAD s11, 26*SIZE_REG(\base)
|
||||
LOAD t3, 27*SIZE_REG(\base)
|
||||
LOAD t4, 28*SIZE_REG(\base)
|
||||
LOAD t5, 29*SIZE_REG(\base)
|
||||
LOAD t6, 30*SIZE_REG(\base)
|
||||
.endm
|
||||
|
||||
# Something to note about save/restore:
|
||||
@@ -100,13 +104,13 @@ trap_vector:
|
||||
|
||||
# Save the actual t6 register, which we swapped into
|
||||
# mscratch
|
||||
mv t5, t6 # t5 points to the context of current task
|
||||
csrr t6, mscratch # read t6 back from mscratch
|
||||
sw t6, 120(t5) # save t6 with t5 as base
|
||||
mv t5, t6 # t5 points to the context of current task
|
||||
csrr t6, mscratch # read t6 back from mscratch
|
||||
STORE t6, 30*SIZE_REG(t5) # save t6 with t5 as base
|
||||
|
||||
# save mepc to context of current task
|
||||
csrr a0, mepc
|
||||
sw a0, 124(t5)
|
||||
STORE a0, 31*SIZE_REG(t5)
|
||||
|
||||
# Restore the context pointer into mscratch
|
||||
csrw mscratch, t5
|
||||
@@ -134,7 +138,7 @@ switch_to:
|
||||
# switch mscratch to point to the context of the next task
|
||||
csrw mscratch, a0
|
||||
# set mepc to the pc of the next task
|
||||
lw a1, 124(a0)
|
||||
LOAD a1, 31*SIZE_REG(a0)
|
||||
csrw mepc, a1
|
||||
|
||||
# Restore all GP registers
|
||||
|
||||
@@ -1,30 +1,32 @@
|
||||
#define SIZE_PTR .word
|
||||
|
||||
.section .rodata
|
||||
.global HEAP_START
|
||||
HEAP_START: .word _heap_start
|
||||
HEAP_START: SIZE_PTR _heap_start
|
||||
|
||||
.global HEAP_SIZE
|
||||
HEAP_SIZE: .word _heap_size
|
||||
HEAP_SIZE: SIZE_PTR _heap_size
|
||||
|
||||
.global TEXT_START
|
||||
TEXT_START: .word _text_start
|
||||
TEXT_START: SIZE_PTR _text_start
|
||||
|
||||
.global TEXT_END
|
||||
TEXT_END: .word _text_end
|
||||
TEXT_END: SIZE_PTR _text_end
|
||||
|
||||
.global DATA_START
|
||||
DATA_START: .word _data_start
|
||||
DATA_START: SIZE_PTR _data_start
|
||||
|
||||
.global DATA_END
|
||||
DATA_END: .word _data_end
|
||||
DATA_END: SIZE_PTR _data_end
|
||||
|
||||
.global RODATA_START
|
||||
RODATA_START: .word _rodata_start
|
||||
RODATA_START: SIZE_PTR _rodata_start
|
||||
|
||||
.global RODATA_END
|
||||
RODATA_END: .word _rodata_end
|
||||
RODATA_END: SIZE_PTR _rodata_end
|
||||
|
||||
.global BSS_START
|
||||
BSS_START: .word _bss_start
|
||||
BSS_START: SIZE_PTR _bss_start
|
||||
|
||||
.global BSS_END
|
||||
BSS_END: .word _bss_end
|
||||
BSS_END: SIZE_PTR _bss_end
|
||||
|
||||
@@ -58,7 +58,7 @@ struct context {
|
||||
// upon is trap frame
|
||||
|
||||
// save the pc to run in next schedule cycle
|
||||
reg_t pc; // offset: 31 *4 = 124
|
||||
reg_t pc; // offset: 31 * sizeof(reg_t)
|
||||
};
|
||||
|
||||
extern int task_create(void (*task)(void));
|
||||
|
||||
@@ -3,24 +3,24 @@
|
||||
/*
|
||||
* Following global vars are defined in mem.S
|
||||
*/
|
||||
extern uint32_t TEXT_START;
|
||||
extern uint32_t TEXT_END;
|
||||
extern uint32_t DATA_START;
|
||||
extern uint32_t DATA_END;
|
||||
extern uint32_t RODATA_START;
|
||||
extern uint32_t RODATA_END;
|
||||
extern uint32_t BSS_START;
|
||||
extern uint32_t BSS_END;
|
||||
extern uint32_t HEAP_START;
|
||||
extern uint32_t HEAP_SIZE;
|
||||
extern ptr_t TEXT_START;
|
||||
extern ptr_t TEXT_END;
|
||||
extern ptr_t DATA_START;
|
||||
extern ptr_t DATA_END;
|
||||
extern ptr_t RODATA_START;
|
||||
extern ptr_t RODATA_END;
|
||||
extern ptr_t BSS_START;
|
||||
extern ptr_t BSS_END;
|
||||
extern ptr_t HEAP_START;
|
||||
extern ptr_t HEAP_SIZE;
|
||||
|
||||
/*
|
||||
* _alloc_start points to the actual start address of heap pool
|
||||
* _alloc_end points to the actual end address of heap pool
|
||||
* _num_pages holds the actual max number of pages we can allocate.
|
||||
*/
|
||||
static uint32_t _alloc_start = 0;
|
||||
static uint32_t _alloc_end = 0;
|
||||
static ptr_t _alloc_start = 0;
|
||||
static ptr_t _alloc_end = 0;
|
||||
static uint32_t _num_pages = 0;
|
||||
|
||||
#define PAGE_SIZE 4096
|
||||
@@ -70,9 +70,9 @@ static inline int _is_last(struct Page *page)
|
||||
/*
|
||||
* align the address to the border of page(4K)
|
||||
*/
|
||||
static inline uint32_t _align_page(uint32_t address)
|
||||
static inline ptr_t _align_page(ptr_t address)
|
||||
{
|
||||
uint32_t order = (1 << PAGE_ORDER) - 1;
|
||||
ptr_t order = (1 << PAGE_ORDER) - 1;
|
||||
return (address + order) & (~order);
|
||||
}
|
||||
|
||||
@@ -155,12 +155,12 @@ void page_free(void *p)
|
||||
/*
|
||||
* Assert (TBD) if p is invalid
|
||||
*/
|
||||
if (!p || (uint32_t)p >= _alloc_end) {
|
||||
if (!p || (ptr_t)p >= _alloc_end) {
|
||||
return;
|
||||
}
|
||||
/* get the first page descriptor of this memory block */
|
||||
struct Page *page = (struct Page *)HEAP_START;
|
||||
page += ((uint32_t)p - _alloc_start)/ PAGE_SIZE;
|
||||
page += ((ptr_t)p - _alloc_start)/ PAGE_SIZE;
|
||||
/* loop and clear all the page descriptors of the memory block */
|
||||
while (!_is_free(page)) {
|
||||
if (_is_last(page)) {
|
||||
|
||||
@@ -92,6 +92,10 @@ static inline void w_mie(reg_t x)
|
||||
asm volatile("csrw mie, %0" : : "r" (x));
|
||||
}
|
||||
|
||||
/* Machine-mode Cause Masks */
|
||||
#define MCAUSE_MASK_INTERRUPT (reg_t)0x80000000
|
||||
#define MCAUSE_MASK_ECODE (reg_t)0x7FFFFFFF
|
||||
|
||||
static inline reg_t r_mcause()
|
||||
{
|
||||
reg_t x;
|
||||
|
||||
@@ -31,9 +31,9 @@ void external_interrupt_handler()
|
||||
reg_t trap_handler(reg_t epc, reg_t cause)
|
||||
{
|
||||
reg_t return_pc = epc;
|
||||
reg_t cause_code = cause & 0xfff;
|
||||
reg_t cause_code = cause & MCAUSE_MASK_ECODE;
|
||||
|
||||
if (cause & 0x80000000) {
|
||||
if (cause & MCAUSE_MASK_INTERRUPT) {
|
||||
/* Asynchronous trap - interrupt */
|
||||
switch (cause_code) {
|
||||
case 3:
|
||||
|
||||
@@ -7,8 +7,9 @@ typedef unsigned int uint32_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
|
||||
/*
|
||||
* RISCV32: register is 32bits width
|
||||
*/
|
||||
* Register Width
|
||||
*/
|
||||
typedef uint32_t reg_t;
|
||||
typedef uint32_t ptr_t;
|
||||
|
||||
#endif /* __TYPES_H__ */
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
#define LOAD lw
|
||||
#define STORE sw
|
||||
#define SIZE_REG 4
|
||||
|
||||
# Save all General-Purpose(GP) registers to context.
|
||||
# struct context *base = &ctx_task;
|
||||
# base->ra = ra;
|
||||
@@ -10,34 +14,34 @@
|
||||
# which is a global value and would not be changed
|
||||
# during context-switch.
|
||||
.macro reg_save base
|
||||
sw ra, 0(\base)
|
||||
sw sp, 4(\base)
|
||||
sw t0, 16(\base)
|
||||
sw t1, 20(\base)
|
||||
sw t2, 24(\base)
|
||||
sw s0, 28(\base)
|
||||
sw s1, 32(\base)
|
||||
sw a0, 36(\base)
|
||||
sw a1, 40(\base)
|
||||
sw a2, 44(\base)
|
||||
sw a3, 48(\base)
|
||||
sw a4, 52(\base)
|
||||
sw a5, 56(\base)
|
||||
sw a6, 60(\base)
|
||||
sw a7, 64(\base)
|
||||
sw s2, 68(\base)
|
||||
sw s3, 72(\base)
|
||||
sw s4, 76(\base)
|
||||
sw s5, 80(\base)
|
||||
sw s6, 84(\base)
|
||||
sw s7, 88(\base)
|
||||
sw s8, 92(\base)
|
||||
sw s9, 96(\base)
|
||||
sw s10, 100(\base)
|
||||
sw s11, 104(\base)
|
||||
sw t3, 108(\base)
|
||||
sw t4, 112(\base)
|
||||
sw t5, 116(\base)
|
||||
STORE ra, 0*SIZE_REG(\base)
|
||||
STORE sp, 1*SIZE_REG(\base)
|
||||
STORE t0, 4*SIZE_REG(\base)
|
||||
STORE t1, 5*SIZE_REG(\base)
|
||||
STORE t2, 6*SIZE_REG(\base)
|
||||
STORE s0, 7*SIZE_REG(\base)
|
||||
STORE s1, 8*SIZE_REG(\base)
|
||||
STORE a0, 9*SIZE_REG(\base)
|
||||
STORE a1, 10*SIZE_REG(\base)
|
||||
STORE a2, 11*SIZE_REG(\base)
|
||||
STORE a3, 12*SIZE_REG(\base)
|
||||
STORE a4, 13*SIZE_REG(\base)
|
||||
STORE a5, 14*SIZE_REG(\base)
|
||||
STORE a6, 15*SIZE_REG(\base)
|
||||
STORE a7, 16*SIZE_REG(\base)
|
||||
STORE s2, 17*SIZE_REG(\base)
|
||||
STORE s3, 18*SIZE_REG(\base)
|
||||
STORE s4, 19*SIZE_REG(\base)
|
||||
STORE s5, 20*SIZE_REG(\base)
|
||||
STORE s6, 21*SIZE_REG(\base)
|
||||
STORE s7, 22*SIZE_REG(\base)
|
||||
STORE s8, 23*SIZE_REG(\base)
|
||||
STORE s9, 24*SIZE_REG(\base)
|
||||
STORE s10, 25*SIZE_REG(\base)
|
||||
STORE s11, 26*SIZE_REG(\base)
|
||||
STORE t3, 27*SIZE_REG(\base)
|
||||
STORE t4, 28*SIZE_REG(\base)
|
||||
STORE t5, 29*SIZE_REG(\base)
|
||||
# we don't save t6 here, due to we have used
|
||||
# it as base, we have to save t6 in an extra step
|
||||
# outside of reg_save
|
||||
@@ -49,35 +53,35 @@
|
||||
# ra = base->ra;
|
||||
# ......
|
||||
.macro reg_restore base
|
||||
lw ra, 0(\base)
|
||||
lw sp, 4(\base)
|
||||
lw t0, 16(\base)
|
||||
lw t1, 20(\base)
|
||||
lw t2, 24(\base)
|
||||
lw s0, 28(\base)
|
||||
lw s1, 32(\base)
|
||||
lw a0, 36(\base)
|
||||
lw a1, 40(\base)
|
||||
lw a2, 44(\base)
|
||||
lw a3, 48(\base)
|
||||
lw a4, 52(\base)
|
||||
lw a5, 56(\base)
|
||||
lw a6, 60(\base)
|
||||
lw a7, 64(\base)
|
||||
lw s2, 68(\base)
|
||||
lw s3, 72(\base)
|
||||
lw s4, 76(\base)
|
||||
lw s5, 80(\base)
|
||||
lw s6, 84(\base)
|
||||
lw s7, 88(\base)
|
||||
lw s8, 92(\base)
|
||||
lw s9, 96(\base)
|
||||
lw s10, 100(\base)
|
||||
lw s11, 104(\base)
|
||||
lw t3, 108(\base)
|
||||
lw t4, 112(\base)
|
||||
lw t5, 116(\base)
|
||||
lw t6, 120(\base)
|
||||
LOAD ra, 0*SIZE_REG(\base)
|
||||
LOAD sp, 1*SIZE_REG(\base)
|
||||
LOAD t0, 4*SIZE_REG(\base)
|
||||
LOAD t1, 5*SIZE_REG(\base)
|
||||
LOAD t2, 6*SIZE_REG(\base)
|
||||
LOAD s0, 7*SIZE_REG(\base)
|
||||
LOAD s1, 8*SIZE_REG(\base)
|
||||
LOAD a0, 9*SIZE_REG(\base)
|
||||
LOAD a1, 10*SIZE_REG(\base)
|
||||
LOAD a2, 11*SIZE_REG(\base)
|
||||
LOAD a3, 12*SIZE_REG(\base)
|
||||
LOAD a4, 13*SIZE_REG(\base)
|
||||
LOAD a5, 14*SIZE_REG(\base)
|
||||
LOAD a6, 15*SIZE_REG(\base)
|
||||
LOAD a7, 16*SIZE_REG(\base)
|
||||
LOAD s2, 17*SIZE_REG(\base)
|
||||
LOAD s3, 18*SIZE_REG(\base)
|
||||
LOAD s4, 19*SIZE_REG(\base)
|
||||
LOAD s5, 20*SIZE_REG(\base)
|
||||
LOAD s6, 21*SIZE_REG(\base)
|
||||
LOAD s7, 22*SIZE_REG(\base)
|
||||
LOAD s8, 23*SIZE_REG(\base)
|
||||
LOAD s9, 24*SIZE_REG(\base)
|
||||
LOAD s10, 25*SIZE_REG(\base)
|
||||
LOAD s11, 26*SIZE_REG(\base)
|
||||
LOAD t3, 27*SIZE_REG(\base)
|
||||
LOAD t4, 28*SIZE_REG(\base)
|
||||
LOAD t5, 29*SIZE_REG(\base)
|
||||
LOAD t6, 30*SIZE_REG(\base)
|
||||
.endm
|
||||
|
||||
# Something to note about save/restore:
|
||||
@@ -100,13 +104,13 @@ trap_vector:
|
||||
|
||||
# Save the actual t6 register, which we swapped into
|
||||
# mscratch
|
||||
mv t5, t6 # t5 points to the context of current task
|
||||
csrr t6, mscratch # read t6 back from mscratch
|
||||
sw t6, 120(t5) # save t6 with t5 as base
|
||||
mv t5, t6 # t5 points to the context of current task
|
||||
csrr t6, mscratch # read t6 back from mscratch
|
||||
STORE t6, 30*SIZE_REG(t5) # save t6 with t5 as base
|
||||
|
||||
# save mepc to context of current task
|
||||
csrr a0, mepc
|
||||
sw a0, 124(t5)
|
||||
STORE a0, 31*SIZE_REG(t5)
|
||||
|
||||
# Restore the context pointer into mscratch
|
||||
csrw mscratch, t5
|
||||
@@ -134,7 +138,7 @@ switch_to:
|
||||
# switch mscratch to point to the context of the next task
|
||||
csrw mscratch, a0
|
||||
# set mepc to the pc of the next task
|
||||
lw a1, 124(a0)
|
||||
LOAD a1, 31*SIZE_REG(a0)
|
||||
csrw mepc, a1
|
||||
|
||||
# Restore all GP registers
|
||||
|
||||
@@ -1,30 +1,32 @@
|
||||
#define SIZE_PTR .word
|
||||
|
||||
.section .rodata
|
||||
.global HEAP_START
|
||||
HEAP_START: .word _heap_start
|
||||
HEAP_START: SIZE_PTR _heap_start
|
||||
|
||||
.global HEAP_SIZE
|
||||
HEAP_SIZE: .word _heap_size
|
||||
HEAP_SIZE: SIZE_PTR _heap_size
|
||||
|
||||
.global TEXT_START
|
||||
TEXT_START: .word _text_start
|
||||
TEXT_START: SIZE_PTR _text_start
|
||||
|
||||
.global TEXT_END
|
||||
TEXT_END: .word _text_end
|
||||
TEXT_END: SIZE_PTR _text_end
|
||||
|
||||
.global DATA_START
|
||||
DATA_START: .word _data_start
|
||||
DATA_START: SIZE_PTR _data_start
|
||||
|
||||
.global DATA_END
|
||||
DATA_END: .word _data_end
|
||||
DATA_END: SIZE_PTR _data_end
|
||||
|
||||
.global RODATA_START
|
||||
RODATA_START: .word _rodata_start
|
||||
RODATA_START: SIZE_PTR _rodata_start
|
||||
|
||||
.global RODATA_END
|
||||
RODATA_END: .word _rodata_end
|
||||
RODATA_END: SIZE_PTR _rodata_end
|
||||
|
||||
.global BSS_START
|
||||
BSS_START: .word _bss_start
|
||||
BSS_START: SIZE_PTR _bss_start
|
||||
|
||||
.global BSS_END
|
||||
BSS_END: .word _bss_end
|
||||
BSS_END: SIZE_PTR _bss_end
|
||||
|
||||
@@ -58,7 +58,7 @@ struct context {
|
||||
// upon is trap frame
|
||||
|
||||
// save the pc to run in next schedule cycle
|
||||
reg_t pc; // offset: 31 *4 = 124
|
||||
reg_t pc; // offset: 31 * sizeof(reg_t)
|
||||
};
|
||||
|
||||
extern int task_create(void (*task)(void));
|
||||
|
||||
@@ -3,24 +3,24 @@
|
||||
/*
|
||||
* Following global vars are defined in mem.S
|
||||
*/
|
||||
extern uint32_t TEXT_START;
|
||||
extern uint32_t TEXT_END;
|
||||
extern uint32_t DATA_START;
|
||||
extern uint32_t DATA_END;
|
||||
extern uint32_t RODATA_START;
|
||||
extern uint32_t RODATA_END;
|
||||
extern uint32_t BSS_START;
|
||||
extern uint32_t BSS_END;
|
||||
extern uint32_t HEAP_START;
|
||||
extern uint32_t HEAP_SIZE;
|
||||
extern ptr_t TEXT_START;
|
||||
extern ptr_t TEXT_END;
|
||||
extern ptr_t DATA_START;
|
||||
extern ptr_t DATA_END;
|
||||
extern ptr_t RODATA_START;
|
||||
extern ptr_t RODATA_END;
|
||||
extern ptr_t BSS_START;
|
||||
extern ptr_t BSS_END;
|
||||
extern ptr_t HEAP_START;
|
||||
extern ptr_t HEAP_SIZE;
|
||||
|
||||
/*
|
||||
* _alloc_start points to the actual start address of heap pool
|
||||
* _alloc_end points to the actual end address of heap pool
|
||||
* _num_pages holds the actual max number of pages we can allocate.
|
||||
*/
|
||||
static uint32_t _alloc_start = 0;
|
||||
static uint32_t _alloc_end = 0;
|
||||
static ptr_t _alloc_start = 0;
|
||||
static ptr_t _alloc_end = 0;
|
||||
static uint32_t _num_pages = 0;
|
||||
|
||||
#define PAGE_SIZE 4096
|
||||
@@ -70,9 +70,9 @@ static inline int _is_last(struct Page *page)
|
||||
/*
|
||||
* align the address to the border of page(4K)
|
||||
*/
|
||||
static inline uint32_t _align_page(uint32_t address)
|
||||
static inline ptr_t _align_page(ptr_t address)
|
||||
{
|
||||
uint32_t order = (1 << PAGE_ORDER) - 1;
|
||||
ptr_t order = (1 << PAGE_ORDER) - 1;
|
||||
return (address + order) & (~order);
|
||||
}
|
||||
|
||||
@@ -155,12 +155,12 @@ void page_free(void *p)
|
||||
/*
|
||||
* Assert (TBD) if p is invalid
|
||||
*/
|
||||
if (!p || (uint32_t)p >= _alloc_end) {
|
||||
if (!p || (ptr_t)p >= _alloc_end) {
|
||||
return;
|
||||
}
|
||||
/* get the first page descriptor of this memory block */
|
||||
struct Page *page = (struct Page *)HEAP_START;
|
||||
page += ((uint32_t)p - _alloc_start)/ PAGE_SIZE;
|
||||
page += ((ptr_t)p - _alloc_start)/ PAGE_SIZE;
|
||||
/* loop and clear all the page descriptors of the memory block */
|
||||
while (!_is_free(page)) {
|
||||
if (_is_last(page)) {
|
||||
|
||||
@@ -92,6 +92,10 @@ static inline void w_mie(reg_t x)
|
||||
asm volatile("csrw mie, %0" : : "r" (x));
|
||||
}
|
||||
|
||||
/* Machine-mode Cause Masks */
|
||||
#define MCAUSE_MASK_INTERRUPT (reg_t)0x80000000
|
||||
#define MCAUSE_MASK_ECODE (reg_t)0x7FFFFFFF
|
||||
|
||||
static inline reg_t r_mcause()
|
||||
{
|
||||
reg_t x;
|
||||
|
||||
@@ -31,9 +31,9 @@ void external_interrupt_handler()
|
||||
reg_t trap_handler(reg_t epc, reg_t cause)
|
||||
{
|
||||
reg_t return_pc = epc;
|
||||
reg_t cause_code = cause & 0xfff;
|
||||
reg_t cause_code = cause & MCAUSE_MASK_ECODE;
|
||||
|
||||
if (cause & 0x80000000) {
|
||||
if (cause & MCAUSE_MASK_INTERRUPT) {
|
||||
/* Asynchronous trap - interrupt */
|
||||
switch (cause_code) {
|
||||
case 3:
|
||||
|
||||
@@ -7,8 +7,9 @@ typedef unsigned int uint32_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
|
||||
/*
|
||||
* RISCV32: register is 32bits width
|
||||
*/
|
||||
* Register Width
|
||||
*/
|
||||
typedef uint32_t reg_t;
|
||||
typedef uint32_t ptr_t;
|
||||
|
||||
#endif /* __TYPES_H__ */
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
#define LOAD lw
|
||||
#define STORE sw
|
||||
#define SIZE_REG 4
|
||||
|
||||
# Save all General-Purpose(GP) registers to context.
|
||||
# struct context *base = &ctx_task;
|
||||
# base->ra = ra;
|
||||
@@ -10,34 +14,34 @@
|
||||
# which is a global value and would not be changed
|
||||
# during context-switch.
|
||||
.macro reg_save base
|
||||
sw ra, 0(\base)
|
||||
sw sp, 4(\base)
|
||||
sw t0, 16(\base)
|
||||
sw t1, 20(\base)
|
||||
sw t2, 24(\base)
|
||||
sw s0, 28(\base)
|
||||
sw s1, 32(\base)
|
||||
sw a0, 36(\base)
|
||||
sw a1, 40(\base)
|
||||
sw a2, 44(\base)
|
||||
sw a3, 48(\base)
|
||||
sw a4, 52(\base)
|
||||
sw a5, 56(\base)
|
||||
sw a6, 60(\base)
|
||||
sw a7, 64(\base)
|
||||
sw s2, 68(\base)
|
||||
sw s3, 72(\base)
|
||||
sw s4, 76(\base)
|
||||
sw s5, 80(\base)
|
||||
sw s6, 84(\base)
|
||||
sw s7, 88(\base)
|
||||
sw s8, 92(\base)
|
||||
sw s9, 96(\base)
|
||||
sw s10, 100(\base)
|
||||
sw s11, 104(\base)
|
||||
sw t3, 108(\base)
|
||||
sw t4, 112(\base)
|
||||
sw t5, 116(\base)
|
||||
STORE ra, 0*SIZE_REG(\base)
|
||||
STORE sp, 1*SIZE_REG(\base)
|
||||
STORE t0, 4*SIZE_REG(\base)
|
||||
STORE t1, 5*SIZE_REG(\base)
|
||||
STORE t2, 6*SIZE_REG(\base)
|
||||
STORE s0, 7*SIZE_REG(\base)
|
||||
STORE s1, 8*SIZE_REG(\base)
|
||||
STORE a0, 9*SIZE_REG(\base)
|
||||
STORE a1, 10*SIZE_REG(\base)
|
||||
STORE a2, 11*SIZE_REG(\base)
|
||||
STORE a3, 12*SIZE_REG(\base)
|
||||
STORE a4, 13*SIZE_REG(\base)
|
||||
STORE a5, 14*SIZE_REG(\base)
|
||||
STORE a6, 15*SIZE_REG(\base)
|
||||
STORE a7, 16*SIZE_REG(\base)
|
||||
STORE s2, 17*SIZE_REG(\base)
|
||||
STORE s3, 18*SIZE_REG(\base)
|
||||
STORE s4, 19*SIZE_REG(\base)
|
||||
STORE s5, 20*SIZE_REG(\base)
|
||||
STORE s6, 21*SIZE_REG(\base)
|
||||
STORE s7, 22*SIZE_REG(\base)
|
||||
STORE s8, 23*SIZE_REG(\base)
|
||||
STORE s9, 24*SIZE_REG(\base)
|
||||
STORE s10, 25*SIZE_REG(\base)
|
||||
STORE s11, 26*SIZE_REG(\base)
|
||||
STORE t3, 27*SIZE_REG(\base)
|
||||
STORE t4, 28*SIZE_REG(\base)
|
||||
STORE t5, 29*SIZE_REG(\base)
|
||||
# we don't save t6 here, due to we have used
|
||||
# it as base, we have to save t6 in an extra step
|
||||
# outside of reg_save
|
||||
@@ -49,35 +53,35 @@
|
||||
# ra = base->ra;
|
||||
# ......
|
||||
.macro reg_restore base
|
||||
lw ra, 0(\base)
|
||||
lw sp, 4(\base)
|
||||
lw t0, 16(\base)
|
||||
lw t1, 20(\base)
|
||||
lw t2, 24(\base)
|
||||
lw s0, 28(\base)
|
||||
lw s1, 32(\base)
|
||||
lw a0, 36(\base)
|
||||
lw a1, 40(\base)
|
||||
lw a2, 44(\base)
|
||||
lw a3, 48(\base)
|
||||
lw a4, 52(\base)
|
||||
lw a5, 56(\base)
|
||||
lw a6, 60(\base)
|
||||
lw a7, 64(\base)
|
||||
lw s2, 68(\base)
|
||||
lw s3, 72(\base)
|
||||
lw s4, 76(\base)
|
||||
lw s5, 80(\base)
|
||||
lw s6, 84(\base)
|
||||
lw s7, 88(\base)
|
||||
lw s8, 92(\base)
|
||||
lw s9, 96(\base)
|
||||
lw s10, 100(\base)
|
||||
lw s11, 104(\base)
|
||||
lw t3, 108(\base)
|
||||
lw t4, 112(\base)
|
||||
lw t5, 116(\base)
|
||||
lw t6, 120(\base)
|
||||
LOAD ra, 0*SIZE_REG(\base)
|
||||
LOAD sp, 1*SIZE_REG(\base)
|
||||
LOAD t0, 4*SIZE_REG(\base)
|
||||
LOAD t1, 5*SIZE_REG(\base)
|
||||
LOAD t2, 6*SIZE_REG(\base)
|
||||
LOAD s0, 7*SIZE_REG(\base)
|
||||
LOAD s1, 8*SIZE_REG(\base)
|
||||
LOAD a0, 9*SIZE_REG(\base)
|
||||
LOAD a1, 10*SIZE_REG(\base)
|
||||
LOAD a2, 11*SIZE_REG(\base)
|
||||
LOAD a3, 12*SIZE_REG(\base)
|
||||
LOAD a4, 13*SIZE_REG(\base)
|
||||
LOAD a5, 14*SIZE_REG(\base)
|
||||
LOAD a6, 15*SIZE_REG(\base)
|
||||
LOAD a7, 16*SIZE_REG(\base)
|
||||
LOAD s2, 17*SIZE_REG(\base)
|
||||
LOAD s3, 18*SIZE_REG(\base)
|
||||
LOAD s4, 19*SIZE_REG(\base)
|
||||
LOAD s5, 20*SIZE_REG(\base)
|
||||
LOAD s6, 21*SIZE_REG(\base)
|
||||
LOAD s7, 22*SIZE_REG(\base)
|
||||
LOAD s8, 23*SIZE_REG(\base)
|
||||
LOAD s9, 24*SIZE_REG(\base)
|
||||
LOAD s10, 25*SIZE_REG(\base)
|
||||
LOAD s11, 26*SIZE_REG(\base)
|
||||
LOAD t3, 27*SIZE_REG(\base)
|
||||
LOAD t4, 28*SIZE_REG(\base)
|
||||
LOAD t5, 29*SIZE_REG(\base)
|
||||
LOAD t6, 30*SIZE_REG(\base)
|
||||
.endm
|
||||
|
||||
# Something to note about save/restore:
|
||||
@@ -100,13 +104,13 @@ trap_vector:
|
||||
|
||||
# Save the actual t6 register, which we swapped into
|
||||
# mscratch
|
||||
mv t5, t6 # t5 points to the context of current task
|
||||
csrr t6, mscratch # read t6 back from mscratch
|
||||
sw t6, 120(t5) # save t6 with t5 as base
|
||||
mv t5, t6 # t5 points to the context of current task
|
||||
csrr t6, mscratch # read t6 back from mscratch
|
||||
STORE t6, 30*SIZE_REG(t5) # save t6 with t5 as base
|
||||
|
||||
# save mepc to context of current task
|
||||
csrr a0, mepc
|
||||
sw a0, 124(t5)
|
||||
STORE a0, 31*SIZE_REG(t5)
|
||||
|
||||
# Restore the context pointer into mscratch
|
||||
csrw mscratch, t5
|
||||
@@ -135,7 +139,7 @@ switch_to:
|
||||
# switch mscratch to point to the context of the next task
|
||||
csrw mscratch, a0
|
||||
# set mepc to the pc of the next task
|
||||
lw a1, 124(a0)
|
||||
LOAD a1, 31*SIZE_REG(a0)
|
||||
csrw mepc, a1
|
||||
|
||||
# Restore all GP registers
|
||||
|
||||
@@ -1,30 +1,32 @@
|
||||
#define SIZE_PTR .word
|
||||
|
||||
.section .rodata
|
||||
.global HEAP_START
|
||||
HEAP_START: .word _heap_start
|
||||
HEAP_START: SIZE_PTR _heap_start
|
||||
|
||||
.global HEAP_SIZE
|
||||
HEAP_SIZE: .word _heap_size
|
||||
HEAP_SIZE: SIZE_PTR _heap_size
|
||||
|
||||
.global TEXT_START
|
||||
TEXT_START: .word _text_start
|
||||
TEXT_START: SIZE_PTR _text_start
|
||||
|
||||
.global TEXT_END
|
||||
TEXT_END: .word _text_end
|
||||
TEXT_END: SIZE_PTR _text_end
|
||||
|
||||
.global DATA_START
|
||||
DATA_START: .word _data_start
|
||||
DATA_START: SIZE_PTR _data_start
|
||||
|
||||
.global DATA_END
|
||||
DATA_END: .word _data_end
|
||||
DATA_END: SIZE_PTR _data_end
|
||||
|
||||
.global RODATA_START
|
||||
RODATA_START: .word _rodata_start
|
||||
RODATA_START: SIZE_PTR _rodata_start
|
||||
|
||||
.global RODATA_END
|
||||
RODATA_END: .word _rodata_end
|
||||
RODATA_END: SIZE_PTR _rodata_end
|
||||
|
||||
.global BSS_START
|
||||
BSS_START: .word _bss_start
|
||||
BSS_START: SIZE_PTR _bss_start
|
||||
|
||||
.global BSS_END
|
||||
BSS_END: .word _bss_end
|
||||
BSS_END: SIZE_PTR _bss_end
|
||||
|
||||
@@ -58,7 +58,7 @@ struct context {
|
||||
// upon is trap frame
|
||||
|
||||
// save the pc to run in next schedule cycle
|
||||
reg_t pc; // offset: 31 *4 = 124
|
||||
reg_t pc; // offset: 31 * sizeof(reg_t)
|
||||
};
|
||||
|
||||
extern int task_create(void (*task)(void));
|
||||
|
||||
@@ -3,24 +3,24 @@
|
||||
/*
|
||||
* Following global vars are defined in mem.S
|
||||
*/
|
||||
extern uint32_t TEXT_START;
|
||||
extern uint32_t TEXT_END;
|
||||
extern uint32_t DATA_START;
|
||||
extern uint32_t DATA_END;
|
||||
extern uint32_t RODATA_START;
|
||||
extern uint32_t RODATA_END;
|
||||
extern uint32_t BSS_START;
|
||||
extern uint32_t BSS_END;
|
||||
extern uint32_t HEAP_START;
|
||||
extern uint32_t HEAP_SIZE;
|
||||
extern ptr_t TEXT_START;
|
||||
extern ptr_t TEXT_END;
|
||||
extern ptr_t DATA_START;
|
||||
extern ptr_t DATA_END;
|
||||
extern ptr_t RODATA_START;
|
||||
extern ptr_t RODATA_END;
|
||||
extern ptr_t BSS_START;
|
||||
extern ptr_t BSS_END;
|
||||
extern ptr_t HEAP_START;
|
||||
extern ptr_t HEAP_SIZE;
|
||||
|
||||
/*
|
||||
* _alloc_start points to the actual start address of heap pool
|
||||
* _alloc_end points to the actual end address of heap pool
|
||||
* _num_pages holds the actual max number of pages we can allocate.
|
||||
*/
|
||||
static uint32_t _alloc_start = 0;
|
||||
static uint32_t _alloc_end = 0;
|
||||
static ptr_t _alloc_start = 0;
|
||||
static ptr_t _alloc_end = 0;
|
||||
static uint32_t _num_pages = 0;
|
||||
|
||||
#define PAGE_SIZE 4096
|
||||
@@ -70,9 +70,9 @@ static inline int _is_last(struct Page *page)
|
||||
/*
|
||||
* align the address to the border of page(4K)
|
||||
*/
|
||||
static inline uint32_t _align_page(uint32_t address)
|
||||
static inline ptr_t _align_page(ptr_t address)
|
||||
{
|
||||
uint32_t order = (1 << PAGE_ORDER) - 1;
|
||||
ptr_t order = (1 << PAGE_ORDER) - 1;
|
||||
return (address + order) & (~order);
|
||||
}
|
||||
|
||||
@@ -155,12 +155,12 @@ void page_free(void *p)
|
||||
/*
|
||||
* Assert (TBD) if p is invalid
|
||||
*/
|
||||
if (!p || (uint32_t)p >= _alloc_end) {
|
||||
if (!p || (ptr_t)p >= _alloc_end) {
|
||||
return;
|
||||
}
|
||||
/* get the first page descriptor of this memory block */
|
||||
struct Page *page = (struct Page *)HEAP_START;
|
||||
page += ((uint32_t)p - _alloc_start)/ PAGE_SIZE;
|
||||
page += ((ptr_t)p - _alloc_start)/ PAGE_SIZE;
|
||||
/* loop and clear all the page descriptors of the memory block */
|
||||
while (!_is_free(page)) {
|
||||
if (_is_last(page)) {
|
||||
|
||||
@@ -92,6 +92,10 @@ static inline void w_mie(reg_t x)
|
||||
asm volatile("csrw mie, %0" : : "r" (x));
|
||||
}
|
||||
|
||||
/* Machine-mode Cause Masks */
|
||||
#define MCAUSE_MASK_INTERRUPT (reg_t)0x80000000
|
||||
#define MCAUSE_MASK_ECODE (reg_t)0x7FFFFFFF
|
||||
|
||||
static inline reg_t r_mcause()
|
||||
{
|
||||
reg_t x;
|
||||
|
||||
@@ -32,9 +32,9 @@ void external_interrupt_handler()
|
||||
reg_t trap_handler(reg_t epc, reg_t cause, struct context *cxt)
|
||||
{
|
||||
reg_t return_pc = epc;
|
||||
reg_t cause_code = cause & 0xfff;
|
||||
reg_t cause_code = cause & MCAUSE_MASK_ECODE;
|
||||
|
||||
if (cause & 0x80000000) {
|
||||
if (cause & MCAUSE_MASK_INTERRUPT) {
|
||||
/* Asynchronous trap - interrupt */
|
||||
switch (cause_code) {
|
||||
case 3:
|
||||
|
||||
@@ -7,8 +7,9 @@ typedef unsigned int uint32_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
|
||||
/*
|
||||
* RISCV32: register is 32bits width
|
||||
*/
|
||||
* Register Width
|
||||
*/
|
||||
typedef uint32_t reg_t;
|
||||
typedef uint32_t ptr_t;
|
||||
|
||||
#endif /* __TYPES_H__ */
|
||||
|
||||
@@ -8,7 +8,8 @@ include ../defines.mk
|
||||
DEFS +=
|
||||
|
||||
CROSS_COMPILE = riscv64-unknown-elf-
|
||||
CFLAGS += -nostdlib -fno-builtin -march=rv32g -mabi=ilp32 -g -Wall
|
||||
CFLAGS += -nostdlib -fno-builtin -g -Wall
|
||||
CFLAGS += -march=rv32g -mabi=ilp32
|
||||
LDFLAGS ?= -T os.ld
|
||||
|
||||
QEMU = qemu-system-riscv32
|
||||
|
||||
Reference in New Issue
Block a user