Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
rcore-os
RCore Tutorial V3
提交
1722d0d4
R
RCore Tutorial V3
项目概览
rcore-os
/
RCore Tutorial V3
上一次同步 1 年多
通知
15
Star
793
Fork
260
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
4
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
RCore Tutorial V3
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
4
Issue
4
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
1722d0d4
编写于
1月 02, 2023
作者:
chyyuu1972
1
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
run in qemu -bios none ENV
上级
683a4fdc
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
858 addition
and
9 deletion
+858
-9
os/Makefile
os/Makefile
+16
-2
os/src/boards/qemu.rs
os/src/boards/qemu.rs
+52
-1
os/src/entry.asm
os/src/entry.asm
+1
-1
os/src/linker-qemu.ld
os/src/linker-qemu.ld
+1
-1
os/src/main.rs
os/src/main.rs
+88
-4
os/src/riscvregs.rs
os/src/riscvregs.rs
+614
-0
os/src/start.rs
os/src/start.rs
+86
-0
未找到文件。
os/Makefile
浏览文件 @
1722d0d4
...
...
@@ -24,7 +24,7 @@ ifeq ($(MODE), release)
endif
# KERNEL ENTRY
KERNEL_ENTRY_PA
:=
0x80
2
00000
KERNEL_ENTRY_PA
:=
0x80
0
00000
# Binutils
OBJDUMP
:=
rust-objdump
--arch-name
=
riscv64
...
...
@@ -71,7 +71,21 @@ disasm-vim: kernel
@
nvim
$(DISASM_TMP)
@
rm
$(DISASM_TMP)
run
:
run-inner
run
:
run-inner-none
run-inner-none
:
build
@
qemu-system-riscv64
\
-M
128m
\
-machine
virt
\
-bios
none
\
$(GUI_OPTION)
\
-kernel
$(KERNEL_ELF)
\
-drive
file
=
$(FS_IMG)
,if
=
none,format
=
raw,id
=
x0
\
-device
virtio-blk-device,drive
=
x0
\
# -device virtio-gpu-device
\
-device
virtio-keyboard-device
\
-device
virtio-mouse-device
\
-serial
stdio
run-inner
:
build
@
qemu-system-riscv64
\
...
...
os/src/boards/qemu.rs
浏览文件 @
1722d0d4
...
...
@@ -2,7 +2,7 @@ pub const CLOCK_FREQ: usize = 12500000;
pub
const
MMIO
:
&
[(
usize
,
usize
)]
=
&
[
(
0x0010_0000
,
0x00_2000
),
// VIRT_TEST/RTC in virt machine
(
0x2000000
,
0x10000
),
(
0x2000000
,
0x10000
),
// core local interrupter (CLINT)
(
0xc000000
,
0x210000
),
// VIRT_PLIC in virt machine
(
0x10000000
,
0x9000
),
// VIRT_UART0 with GPU in virt machine
];
...
...
@@ -53,6 +53,57 @@ pub fn irq_handler() {
plic
.complete
(
0
,
IntrTargetPriority
::
Supervisor
,
intr_src_id
);
}
// core local interrupter (CLINT), which contains the timer
pub
const
CLINT
:
usize
=
0x2000000
;
pub
const
fn
clint_mtimecmp
(
hartid
:
usize
)
->
usize
{
CLINT
+
0x4000
+
8
*
hartid
}
pub
const
CLINT_MTIME
:
usize
=
CLINT
+
0xBFF8
;
// Cycles since boot.
#[naked]
#[repr(align(
16
))]
// if miss this alignment, a load access fault will occur.
#[no_mangle]
pub
unsafe
extern
"C"
fn
timervec
()
->
!
{
// start.rs has set up the memory that mscratch points to:
// scratch[0,8,16] : register save area.
// scratch[24] : address of CLINT's MTIMECMP register.
// scratch[32] : desired interval between interrupts.
// Now, mscrach has a pointer to an additional scratch space.
// to aboid overwriting the contents of the integer registers,
// the prologue of an interrupts handler usually begins by swapping
// an integer register(say a0) with mscratch CSR.
// The interrupt handler stores the integer registers
// used for processing in this scratch space.
// a0 saved in mscrach, a1 ~ a3 saved in scratch space.
//loop {}
asm!
(
"csrrw a0, mscratch, a0"
,
"sd a1, 0(a0)"
,
"sd a2, 8(a0)"
,
"sd a3, 16(a0)"
,
// schedule the next timer interrupt
// by adding interval to mtimecmp.
"ld a1, 24(a0)"
,
// CLINT_MTIMECMP(hartid) contents
"ld a2, 32(a0)"
,
// interval
"ld a3, 0(a1)"
,
"add a3, a3, a2"
,
"sd a3, 0(a1)"
,
// raise a supervisor software interrupt.
"li a1, 2"
,
"csrw sip, a1"
,
// restore and return
"ld a3, 16(a0)"
,
"ld a2, 8(a0)"
,
"ld a1, 0(a0)"
,
"csrrw a0, mscratch, a0"
,
"mret"
,
options
(
noreturn
)
);
}
//ref:: https://github.com/andre-richter/qemu-exit
use
core
::
arch
::
asm
;
...
...
os/src/entry.asm
浏览文件 @
1722d0d4
...
...
@@ -2,7 +2,7 @@
.globl
_start
_start:
la
sp
,
boot_stack_top
call
rust_
main
call
rust_
start
.section
.bss.stack
.globl
boot_stack_lower_bound
...
...
os/src/linker-qemu.ld
浏览文件 @
1722d0d4
OUTPUT_ARCH(riscv)
ENTRY(_start)
BASE_ADDRESS = 0x80
2
00000;
BASE_ADDRESS = 0x80
0
00000;
SECTIONS
{
...
...
os/src/main.rs
浏览文件 @
1722d0d4
...
...
@@ -2,6 +2,8 @@
#![no_main]
#![feature(panic_info_message)]
#![feature(alloc_error_handler)]
#![feature(naked_functions)]
#![feature(fn_align)]
use
crate
::
drivers
::{
GPU_DEVICE
,
KEYBOARD_DEVICE
,
MOUSE_DEVICE
};
...
...
@@ -27,7 +29,10 @@ mod syscall;
mod
task
;
mod
timer
;
mod
trap
;
//mod start;
mod
riscvregs
;
use
riscvregs
::
registers
::
*
;
use
riscvregs
::
registers
::
pmpcfg0
::
*
;
//use syscall::create_desktop; //for test
core
::
arch
::
global_asm!
(
include_str!
(
"entry.asm"
));
...
...
@@ -51,6 +56,85 @@ lazy_static! {
unsafe
{
UPIntrFreeCell
::
new
(
false
)
};
}
#[repr(C,
align(
16
))]
struct
Stack
([
u8
;
4096
*
4
*
1
]);
#[no_mangle]
static
mut
STACK0
:
Stack
=
Stack
([
0
;
4096
*
4
*
1
]);
#[no_mangle]
pub
unsafe
fn
rust_start
()
->
!
{
// set MPP mode to Supervisor, for mret
mstatus
::
set_mpp
(
mstatus
::
MPP
::
Supervisor
);
// set MEPC to main, for mret
mepc
::
write
(
rust_main
as
usize
);
// disable paging for now.
satp
::
write
(
0
);
// delegate all interrupts and exceptions to supervisor mode.
medeleg
::
set_all
();
mideleg
::
set_all
();
sie
::
set_sext
();
sie
::
set_ssoft
();
sie
::
set_stimer
();
// configure Physical Memory Protection to give supervisor mode
// access to all of physical memory.
pmpaddr0
::
write
(
0x3fffffffffffff
);
pmpcfg0
::
set_pmp
(
0
,
Range
::
TOR
,
Permission
::
RWX
,
false
);
// 0 < addr < pmpaddr0
// ask for clock interrupts.
timerinit
();
// keep each CPU's hartid in its tp register, for cpuid().
let
id
=
mhartid
::
read
();
core
::
arch
::
asm!
(
"mv tp, {0}"
,
in
(
reg
)
id
);
// switch to supervisor mode and jump to main().
core
::
arch
::
asm!
(
"mret"
);
extern
"C"
{
fn
rust_main
()
->
!
;
}
core
::
hint
::
unreachable_unchecked
();
}
// a scratch area per CPU for machine-mode timer interrupts.
static
mut
TIMER_SCRATCH
:
[[
u64
;
5
];
1
]
=
[[
0
;
5
];
1
];
unsafe
fn
timerinit
()
{
// each CPU has a separate source of timer interrupts
let
id
=
mhartid
::
read
();
// ask the CLINT for a timer interrupts
let
interval
=
1000000u64
;
// cycles; about 1/10th second in qemu.
let
mtimecmp
=
board
::
clint_mtimecmp
(
id
)
as
*
mut
u64
;
let
mtime
=
board
::
CLINT_MTIME
as
*
const
u64
;
mtimecmp
.write_volatile
(
mtime
.read_volatile
()
+
interval
);
// prepare information in scratch[] for timervec.
// scratch[0..2] : space for timervec to save registers.
// scratch[3] : address of CLINT MTIMECMP register.
// scratch[4] : desired interval (in cycles) between timer interrupts.
let
scratch
=
&
mut
TIMER_SCRATCH
[
id
];
scratch
[
3
]
=
mtimecmp
as
u64
;
scratch
[
4
]
=
interval
;
mscratch
::
write
(
scratch
.as_mut_ptr
()
as
usize
);
// set the machine-mode trap handler
mtvec
::
write
(
board
::
timervec
as
usize
,
mtvec
::
TrapMode
::
Direct
);
// enable machine-mode interrupts.
mstatus
::
set_mie
();
// enable machime-mode timer interrupts.
mie
::
set_mtimer
();
}
#[no_mangle]
pub
fn
rust_main
()
->
!
{
clear_bss
();
...
...
@@ -63,11 +147,11 @@ pub fn rust_main() -> ! {
let
_
mouse
=
MOUSE_DEVICE
.clone
();
println!
(
"KERN: init trap"
);
trap
::
init
();
trap
::
enable_timer_interrupt
();
timer
::
set_next_trigger
();
//
trap::enable_timer_interrupt();
//
timer::set_next_trigger();
board
::
device_init
();
fs
::
list_apps
();
gui
::
init_paint
();
//
gui::init_paint();
task
::
add_initproc
();
*
DEV_NON_BLOCKING_ACCESS
.exclusive_access
()
=
true
;
task
::
run_tasks
();
...
...
os/src/riscvregs.rs
0 → 100644
浏览文件 @
1722d0d4
// RISC-V registers
pub
mod
registers
{
// hart (core) id registers
pub
mod
mhartid
{
use
core
::
arch
::
asm
;
#[inline]
pub
fn
read
()
->
usize
{
let
id
:
usize
;
unsafe
{
asm!
(
"csrr {}, mhartid"
,
out
(
reg
)
id
);
}
id
}
}
// Machine Status Register, mstatus
pub
mod
mstatus
{
use
core
::
arch
::
asm
;
// Machine Status Register bit
const
MPP_MASK
:
usize
=
3
<<
11
;
const
MIE
:
usize
=
1
<<
3
;
// Machine Previous Privilege mode
#[derive(Clone,
Copy,
Debug,
PartialEq,
Eq)]
pub
enum
MPP
{
Machine
=
3
,
Supervisor
=
1
,
User
=
0
,
}
#[inline]
unsafe
fn
_
read
()
->
usize
{
let
bits
:
usize
;
asm!
(
"csrr {}, mstatus"
,
out
(
reg
)
bits
);
bits
}
#[inline]
unsafe
fn
_
write
(
bits
:
usize
)
{
asm!
(
"csrw mstatus, {}"
,
in
(
reg
)
bits
);
}
// Machine Previous Privilege Mode
#[inline]
pub
fn
set_mpp
(
mpp
:
MPP
)
{
unsafe
{
let
mut
value
=
_
read
();
value
&=
!
MPP_MASK
;
value
|
=
(
mpp
as
usize
)
<<
11
;
_
write
(
value
);
}
}
#[inline]
pub
fn
set_mie
()
{
unsafe
{
asm!
(
"csrs mstatus, {}"
,
in
(
reg
)
MIE
);
}
}
}
// machine exception program counter, holds the
// instruction address to which a return from
// exception will go.
pub
mod
mepc
{
use
core
::
arch
::
asm
;
#[inline]
pub
fn
write
(
x
:
usize
)
{
unsafe
{
asm!
(
"csrw mepc, {}"
,
in
(
reg
)
x
);
}
}
}
// Supervisor Status Register, sstatus
pub
mod
sstatus
{
use
core
::
arch
::
asm
;
// Supervisor Status Register bit
const
SPP
:
usize
=
1
<<
8
;
// Previous mode, 1=Supervisor, 0=user
const
SPIE
:
usize
=
1
<<
5
;
// Supervisor Previous Interrupt Enable
const
SIE
:
usize
=
1
<<
1
;
// Supervisor Interrupt Enable
#[derive(Clone,
Copy,
Debug)]
pub
struct
Sstatus
{
bits
:
usize
,
}
impl
Sstatus
{
// Supervisor Interrupt Enable
#[inline]
pub
(
in
crate
::
riscvregs
)
fn
sie
(
&
self
)
->
bool
{
self
.bits
&
SIE
!=
0
}
// Supervisor Previous Privilege mode
#[inline]
pub
fn
spp
(
&
self
)
->
SPP
{
match
self
.bits
&
SPP
{
0
=>
SPP
::
User
,
_
=>
SPP
::
Supervisor
,
}
}
// restore status bits
#[inline]
pub
fn
restore
(
&
self
)
{
unsafe
{
_
write
(
self
.bits
);
}
}
}
// Supervisor Previous Privilege Mode
#[derive(Clone,
Copy,
Debug,
PartialEq,
Eq)]
pub
enum
SPP
{
Supervisor
=
1
,
User
=
0
,
}
#[inline]
pub
fn
read
()
->
Sstatus
{
let
bits
:
usize
;
unsafe
{
asm!
(
"csrr {}, sstatus"
,
out
(
reg
)
bits
)
}
Sstatus
{
bits
}
}
#[inline]
unsafe
fn
_
write
(
bits
:
usize
)
{
asm!
(
"csrw sstatus, {}"
,
in
(
reg
)
bits
);
}
// bit set
#[inline]
unsafe
fn
_
set
(
bits
:
usize
)
{
asm!
(
"csrs sstatus, {}"
,
in
(
reg
)
bits
);
}
// bit clear
#[inline]
unsafe
fn
_
clear
(
bits
:
usize
)
{
asm!
(
"csrc sstatus, {}"
,
in
(
reg
)
bits
);
}
#[inline]
pub
(
in
crate
::
riscvregs
)
unsafe
fn
set_sie
()
{
_
set
(
SIE
)
}
#[inline]
pub
(
in
crate
::
riscvregs
)
unsafe
fn
clear_sie
()
{
_
clear
(
SIE
)
}
#[inline]
pub
unsafe
fn
set_spie
()
{
_
set
(
SPIE
);
}
#[inline]
pub
unsafe
fn
set_spp
(
spp
:
SPP
)
{
match
spp
{
SPP
::
Supervisor
=>
_
set
(
SPP
),
SPP
::
User
=>
_
clear
(
SPP
),
}
}
}
// Supervisor Interrupt Pending
pub
mod
sip
{
use
core
::
arch
::
asm
;
const
SSIP
:
usize
=
1
<<
1
;
// Supervisor Software Interrupt Pending
#[inline]
pub
unsafe
fn
clear_ssoft
()
{
asm!
(
"csrc sip, {}"
,
in
(
reg
)
SSIP
);
}
}
// Supervisor Interrupt Enable
pub
mod
sie
{
use
core
::
arch
::
asm
;
const
SEIE
:
usize
=
1
<<
9
;
// external
const
STIE
:
usize
=
1
<<
5
;
// timer
const
SSIE
:
usize
=
1
<<
1
;
// software
#[inline]
unsafe
fn
_
set
(
bits
:
usize
)
{
asm!
(
"csrs sie, {}"
,
in
(
reg
)
bits
);
}
#[inline]
pub
unsafe
fn
set_sext
()
{
_
set
(
SEIE
);
}
#[inline]
pub
unsafe
fn
set_stimer
()
{
_
set
(
STIE
);
}
#[inline]
pub
unsafe
fn
set_ssoft
()
{
_
set
(
SSIE
);
}
}
// Machine-mode Interrupt Enable
pub
mod
mie
{
use
core
::
arch
::
asm
;
const
MTIE
:
usize
=
1
<<
7
;
#[inline]
pub
unsafe
fn
set_mtimer
()
{
asm!
(
"csrs mie, {}"
,
in
(
reg
)
MTIE
);
}
}
// supervisor exceptions program counter, holds the
// instruction address to which a return from
// exception will go.
pub
mod
sepc
{
use
core
::
arch
::
asm
;
#[inline]
pub
fn
read
()
->
usize
{
let
bits
:
usize
;
unsafe
{
asm!
(
"csrr {}, sepc"
,
out
(
reg
)
bits
);
}
bits
}
#[inline]
pub
fn
write
(
bits
:
usize
)
{
unsafe
{
asm!
(
"csrw sepc, {}"
,
in
(
reg
)
bits
);
}
}
}
// Machine Exception Delegation
pub
mod
medeleg
{
use
core
::
arch
::
asm
;
pub
unsafe
fn
set_all
()
{
asm!
(
"csrw medeleg, {}"
,
in
(
reg
)
0xffff
);
}
}
// Machine Interrupt Delegation
pub
mod
mideleg
{
use
core
::
arch
::
asm
;
#[inline]
pub
unsafe
fn
set_all
()
{
asm!
(
"csrw mideleg, {}"
,
in
(
reg
)
0xffff
);
}
}
// Supervisor Trap-Vector Base Address
// low two bits are mode.
pub
mod
stvec
{
pub
use
super
::
mtvec
::
TrapMode
;
use
core
::
arch
::
asm
;
#[inline]
pub
unsafe
fn
write
(
addr
:
usize
,
mode
:
TrapMode
)
{
asm!
(
"csrw stvec, {}"
,
in
(
reg
)
addr
+
mode
as
usize
);
}
}
// Machine-mode interrupt vector
pub
mod
mtvec
{
use
core
::
arch
::
asm
;
#[derive(Clone,
Copy,
Debug,
PartialEq,
Eq)]
pub
enum
TrapMode
{
Direct
=
0
,
Vectored
=
1
,
}
#[inline]
pub
unsafe
fn
write
(
addr
:
usize
,
mode
:
TrapMode
)
{
asm!
(
"csrw mtvec, {}"
,
in
(
reg
)
addr
+
mode
as
usize
);
}
}
// Physical Memory Protection Configuration
pub
mod
pmpcfg0
{
use
core
::
arch
::
asm
;
// Permission enum contains all possible permission modes for pmp registers
#[derive(Clone,
Copy,
Debug)]
pub
enum
Permission
{
NONE
=
0b000
,
R
=
0b001
,
W
=
0b010
,
RW
=
0b011
,
X
=
0b100
,
RX
=
0b101
,
WX
=
0b110
,
RWX
=
0b111
,
}
// Range enum contains all possible addressing modes for pmp registers
pub
enum
Range
{
OFF
=
0b00
,
TOR
=
0b01
,
NA4
=
0b10
,
NAPOT
=
0b11
,
}
// Set the pmp configuration corresponging to the index
#[inline]
pub
unsafe
fn
set_pmp
(
index
:
usize
,
range
:
Range
,
permission
:
Permission
,
locked
:
bool
)
{
assert
!
(
index
<
8
);
let
mut
value
=
_
read
();
let
byte
=
(
locked
as
usize
)
<<
7
|
(
range
as
usize
)
<<
3
|
(
permission
as
usize
);
value
|
=
byte
<<
(
8
*
index
);
_
write
(
value
);
}
#[inline]
unsafe
fn
_
read
()
->
usize
{
let
bits
:
usize
;
asm!
(
"csrr {}, pmpcfg0"
,
out
(
reg
)
bits
);
bits
}
#[inline]
unsafe
fn
_
write
(
bits
:
usize
)
{
asm!
(
"csrw pmpcfg0, {}"
,
in
(
reg
)
bits
);
}
}
// Physical memory protection address register
pub
mod
pmpaddr0
{
use
core
::
arch
::
asm
;
pub
fn
write
(
bits
:
usize
)
{
unsafe
{
asm!
(
"csrw pmpaddr0, {}"
,
in
(
reg
)
bits
);
}
}
}
// Supervisor address translation and protection;
// holds the address of the page table.
pub
mod
satp
{
use
core
::
arch
::
asm
;
// stap register
#[derive(Clone,
Copy,
Debug)]
pub
struct
Satp
{
bits
:
usize
,
}
// 64-bit satp mode
pub
enum
Mode
{
// No translation or protection
Bare
=
0
,
// Page-based 39-bit virtual addressing
Sv39
=
8
,
// Page-based 48-bit virtual addressing
Sv48
=
9
,
// Page-based 57-bit virtual addressing
Sv57
=
10
,
// Page-based 64-bit virtual addressing
Sv64
=
11
,
}
impl
Satp
{
// Return the contents of the register as raw bits
#[inline]
pub
fn
bits
(
&
self
)
->
usize
{
self
.bits
}
}
#[inline]
pub
unsafe
fn
read
()
->
Satp
{
let
bits
:
usize
;
asm!
(
"csrr {}, satp"
,
out
(
reg
)
bits
);
Satp
{
bits
}
}
#[inline]
pub
unsafe
fn
write
(
bits
:
usize
)
{
asm!
(
"csrw satp, {}"
,
in
(
reg
)
bits
);
}
#[inline]
pub
fn
make
(
mode
:
Mode
,
asid
:
usize
,
ppn
:
usize
)
->
usize
{
let
mut
bits
:
usize
=
0
;
bits
|
=
(
mode
as
usize
)
<<
60
;
bits
|
=
asid
<<
44
;
bits
|
=
ppn
>>
12
;
bits
}
}
// mscratch register
pub
mod
mscratch
{
use
core
::
arch
::
asm
;
#[inline]
pub
fn
write
(
bits
:
usize
)
{
unsafe
{
asm!
(
"csrw mscratch, {}"
,
in
(
reg
)
bits
);
}
}
}
// Supervisor Trap Cause
pub
mod
scause
{
use
core
::{
arch
::
asm
,
mem
::
size_of
};
// scause register
#[derive(Clone,
Copy)]
pub
struct
Scause
{
bits
:
usize
,
}
// Trap Cause
#[derive(Clone,
Copy,
Debug,
PartialEq,
Eq)]
pub
enum
Trap
{
Interrupt
(
Interrupt
),
Exception
(
Exception
),
}
// Interrupt
#[derive(Clone,
Copy,
Debug,
PartialEq,
Eq)]
pub
enum
Interrupt
{
UserSoft
,
SupervisorSoft
,
UserTimer
,
SupervisorTimer
,
UserExternal
,
SupervisorExternal
,
Unknown
,
}
// Exception
#[derive(Copy,
Clone,
Debug,
Eq,
PartialEq)]
pub
enum
Exception
{
InstructionMisaligned
,
InstructionFault
,
IllegalInstruction
,
Breakpoint
,
LoadFault
,
StoreMisaligned
,
StoreFault
,
UserEnvCall
,
InstructionPageFault
,
LoadPageFault
,
StorePageFault
,
Unknown
,
}
impl
Interrupt
{
#[inline]
pub
fn
from
(
nr
:
usize
)
->
Self
{
match
nr
{
0
=>
Interrupt
::
UserSoft
,
1
=>
Interrupt
::
SupervisorSoft
,
4
=>
Interrupt
::
UserTimer
,
5
=>
Interrupt
::
SupervisorTimer
,
8
=>
Interrupt
::
UserExternal
,
9
=>
Interrupt
::
SupervisorExternal
,
_
=>
Interrupt
::
Unknown
,
}
}
}
impl
Exception
{
#[inline]
pub
fn
from
(
nr
:
usize
)
->
Self
{
match
nr
{
0
=>
Exception
::
InstructionMisaligned
,
1
=>
Exception
::
InstructionFault
,
2
=>
Exception
::
IllegalInstruction
,
3
=>
Exception
::
Breakpoint
,
5
=>
Exception
::
LoadFault
,
6
=>
Exception
::
StoreMisaligned
,
7
=>
Exception
::
StoreFault
,
8
=>
Exception
::
UserEnvCall
,
12
=>
Exception
::
InstructionPageFault
,
13
=>
Exception
::
LoadPageFault
,
15
=>
Exception
::
StorePageFault
,
_
=>
Exception
::
Unknown
,
}
}
}
impl
Scause
{
// Returns the contents of the register as raw bits
#[inline]
pub
fn
bits
(
&
self
)
->
usize
{
self
.bits
}
// Returns the code field
#[inline]
pub
fn
code
(
&
self
)
->
usize
{
let
bit
=
1
<<
(
size_of
::
<
usize
>
()
*
8
-
1
);
self
.bits
&
!
bit
}
// Trap cause
#[inline]
pub
fn
cause
(
&
self
)
->
Trap
{
if
self
.is_interrupt
()
{
Trap
::
Interrupt
(
Interrupt
::
from
(
self
.code
()))
}
else
{
Trap
::
Exception
(
Exception
::
from
(
self
.code
()))
}
}
// Is trap cause an interrupt.
#[inline]
pub
fn
is_interrupt
(
&
self
)
->
bool
{
self
.bits
&
(
1
<<
(
size_of
::
<
usize
>
()
*
8
-
1
))
!=
0
}
// Is trap cause an exception.
#[inline]
pub
fn
is_exception
(
&
self
)
->
bool
{
!
self
.is_interrupt
()
}
}
#[inline]
pub
fn
read
()
->
Scause
{
let
bits
:
usize
;
unsafe
{
asm!
(
"csrr {}, scause"
,
out
(
reg
)
bits
);
}
Scause
{
bits
}
}
}
// Supervisor Trap Value
pub
mod
stval
{
use
core
::
arch
::
asm
;
#[inline]
pub
fn
read
()
->
usize
{
let
bits
:
usize
;
unsafe
{
asm!
(
"csrr {}, stval"
,
out
(
reg
)
bits
)
}
bits
}
}
}
use
core
::
arch
::
asm
;
use
registers
::
*
;
// enable device interrupts
#[inline]
pub
fn
intr_on
()
{
unsafe
{
sstatus
::
set_sie
();
}
}
// disable device interrupts
#[inline]
pub
fn
intr_off
()
{
unsafe
{
sstatus
::
clear_sie
();
}
}
// are device interrupts enabled?
#[inline]
pub
fn
intr_get
()
->
bool
{
sstatus
::
read
()
.sie
()
}
// flush the TLB.
#[inline]
pub
unsafe
fn
sfence_vma
()
{
// the zero, zero means flush all TLB entries
asm!
(
"sfence.vma zero, zero"
);
}
pub
const
PGSIZE
:
usize
=
4096
;
// bytes per page
pub
const
PGSHIFT
:
usize
=
12
;
// bits of offset within a page
pub
const
fn
pgroundup
(
sz
:
usize
)
->
usize
{
(
sz
+
PGSIZE
-
1
)
&
!
(
PGSIZE
-
1
)
}
pub
const
fn
pgrounddown
(
sz
:
usize
)
->
usize
{
sz
&
!
(
PGSIZE
-
1
)
}
// PTE flags
pub
mod
pteflags
{
pub
const
PTE_V
:
usize
=
1
<<
0
;
// valid
pub
const
PTE_R
:
usize
=
1
<<
1
;
pub
const
PTE_W
:
usize
=
1
<<
2
;
pub
const
PTE_X
:
usize
=
1
<<
3
;
pub
const
PTE_U
:
usize
=
1
<<
4
;
// user can access
}
os/src/start.rs
0 → 100644
浏览文件 @
1722d0d4
//use crate::kernelvec::*;
//use crate::memlayout::*;
//use crate::param::NCPU;
//use super::main::*;
//use crate::riscv::registers::{pmpcfg0::*, *};
use
core
::
arch
::
asm
;
use
core
::
hint
::
unreachable_unchecked
;
mod
riscv
;
#[repr(C,
align(
16
))]
struct
Stack
([
u8
;
4096
*
4
*
NCPU
]);
#[no_mangle]
static
mut
STACK0
:
Stack
=
Stack
([
0
;
4096
*
4
*
NCPU
]);
#[no_mangle]
pub
unsafe
fn
rust_start
()
->
!
{
// set MPP mode to Supervisor, for mret
mstatus
::
set_mpp
(
mstatus
::
MPP
::
Supervisor
);
// set MEPC to main, for mret
mepc
::
write
(
rust_main
as
usize
);
// disable paging for now.
satp
::
write
(
0
);
// delegate all interrupts and exceptions to supervisor mode.
medeleg
::
set_all
();
mideleg
::
set_all
();
sie
::
set_sext
();
sie
::
set_ssoft
();
sie
::
set_stimer
();
// configure Physical Memory Protection to give supervisor mode
// access to all of physical memory.
pmpaddr0
::
write
(
0x3fffffffffffff
);
pmpcfg0
::
set_pmp
(
0
,
Range
::
TOR
,
Permission
::
RWX
,
false
);
// 0 < addr < pmpaddr0
// ask for clock interrupts.
timerinit
();
// keep each CPU's hartid in its tp register, for cpuid().
let
id
=
mhartid
::
read
();
asm!
(
"mv tp, {0}"
,
in
(
reg
)
id
);
// switch to supervisor mode and jump to main().
asm!
(
"mret"
);
extern
"C"
{
fn
rust_main
()
->
!
;
}
unreachable_unchecked
();
}
// a scratch area per CPU for machine-mode timer interrupts.
static
mut
TIMER_SCRATCH
:
[[
u64
;
5
];
1
]
=
[[
0
;
5
];
1
];
unsafe
fn
timerinit
()
{
// each CPU has a separate source of timer interrupts
let
id
=
mhartid
::
read
();
// ask the CLINT for a timer interrupts
let
interval
=
1000000u64
;
// cycles; about 1/10th second in qemu.
let
mtimecmp
=
clint_mtimecmp
(
id
)
as
*
mut
u64
;
let
mtime
=
CLINT_MTIME
as
*
const
u64
;
mtimecmp
.write_volatile
(
mtime
.read_volatile
()
+
interval
);
// prepare information in scratch[] for timervec.
// scratch[0..2] : space for timervec to save registers.
// scratch[3] : address of CLINT MTIMECMP register.
// scratch[4] : desired interval (in cycles) between timer interrupts.
let
scratch
=
&
mut
TIMER_SCRATCH
[
id
];
scratch
[
3
]
=
mtimecmp
as
u64
;
scratch
[
4
]
=
interval
;
mscratch
::
write
(
scratch
.as_mut_ptr
()
as
usize
);
// set the machine-mode trap handler
mtvec
::
write
(
timervec
as
usize
,
mtvec
::
TrapMode
::
Direct
);
// enable machine-mode interrupts.
mstatus
::
set_mie
();
// enable machime-mode timer interrupts.
mie
::
set_mtimer
();
}
\ No newline at end of file
Miykael_xxm
🚴
@xiongjiamu
mentioned in commit
a3223f68
·
1月 03, 2023
mentioned in commit
a3223f68
mentioned in commit a3223f686fc30704c1fdf907ca502c99f1ae16d8
开关提交列表
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录