mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-18 12:16:31 +00:00
在riscv输出hello world (#466)
增加了以下内容: - SBI驱动 - 把内核的rust工具链升级到2023-08-15版本 - 输出riscv的helloworld - 设置内核是PIC的
This commit is contained in:
34
kernel/src/arch/riscv64/asm/head.S
Normal file
34
kernel/src/arch/riscv64/asm/head.S
Normal file
@ -0,0 +1,34 @@
|
||||
#include "common/asm.h"
|
||||
|
||||
.section .bootstrap
|
||||
|
||||
#define CSR_SIE 0x104
|
||||
#define CSR_SIP 0x144
|
||||
|
||||
#define CSR_IE CSR_SIE
|
||||
#define CSR_IP CSR_SIP
|
||||
|
||||
// 内核入口(从DragonStub跳转到这里)
|
||||
// 参数:
|
||||
// a0: hartid (核心ID)
|
||||
// a1: fdt (平坦设备树)
|
||||
.global _start
|
||||
.type _start, @function
|
||||
ENTRY(_start)
|
||||
/* Mask all interrupts */
|
||||
csrw CSR_IE, zero
|
||||
csrw CSR_IP, zero
|
||||
/* Load the global pointer */
|
||||
.option push
|
||||
.option norelax
|
||||
la sp, BSP_IDLE_STACK_SPACE
|
||||
li t0, 32768
|
||||
add sp, sp, t0
|
||||
.option pop
|
||||
/* Call the kernel */
|
||||
call kernel_main
|
||||
nop
|
||||
_loop:
|
||||
j _loop
|
||||
|
||||
|
@ -1,9 +0,0 @@
|
||||
#include "common/asm.h"
|
||||
|
||||
.section .bootstrap
|
||||
|
||||
.global _start
|
||||
.type _start, @function
|
||||
ENTRY(_start)
|
||||
loop:
|
||||
j loop
|
1
kernel/src/arch/riscv64/driver/mod.rs
Normal file
1
kernel/src/arch/riscv64/driver/mod.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod sbi;
|
220
kernel/src/arch/riscv64/driver/sbi/ecall.rs
Normal file
220
kernel/src/arch/riscv64/driver/sbi/ecall.rs
Normal file
@ -0,0 +1,220 @@
|
||||
#![allow(dead_code)]
|
||||
use super::SbiError;
|
||||
|
||||
/// 使用给定的扩展和函数 ID 进行零参数的 `ecall`。
|
||||
///
|
||||
/// # 安全性
|
||||
/// 只有在给定的函数 ID 不接受任何参数时,调用此函数才是安全的,否则行为是未定义的,
|
||||
/// 因为当传递给 SBI 实现时,额外的参数寄存器将具有未定义的内容。
|
||||
#[inline]
|
||||
pub unsafe fn ecall0(extension_id: usize, function_id: usize) -> Result<usize, SbiError> {
|
||||
let error: isize;
|
||||
let value: usize;
|
||||
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
in("a6") function_id,
|
||||
in("a7") extension_id,
|
||||
lateout("a0") error,
|
||||
lateout("a1") value,
|
||||
);
|
||||
|
||||
match error {
|
||||
0 => Result::Ok(value),
|
||||
e => Result::Err(SbiError::new(e)),
|
||||
}
|
||||
}
|
||||
|
||||
/// 使用给定的扩展和函数 ID 进行单参数的 `ecall`。
|
||||
///
|
||||
/// # 安全性
|
||||
/// 只有在给定的函数 ID 接受一个参数时,调用此函数才是安全的,否则行为是未定义的,
|
||||
/// 因为当传递给 SBI 实现时,额外的参数寄存器将具有未定义的内容。
|
||||
#[inline]
|
||||
pub unsafe fn ecall1(
|
||||
arg: usize,
|
||||
extension_id: usize,
|
||||
function_id: usize,
|
||||
) -> Result<usize, SbiError> {
|
||||
let error: isize;
|
||||
let value: usize;
|
||||
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
inlateout("a0") arg => error,
|
||||
in("a6") function_id,
|
||||
in("a7") extension_id,
|
||||
lateout("a1") value,
|
||||
);
|
||||
|
||||
match error {
|
||||
0 => Result::Ok(value),
|
||||
e => Result::Err(SbiError::new(e)),
|
||||
}
|
||||
}
|
||||
|
||||
/// 一个带有给定扩展和函数ID的两参数`ecall`。
|
||||
///
|
||||
/// # 安全性
|
||||
/// 只有在给定的函数ID接受两个参数时,才安全调用此函数。否则,行为将是未定义的,
|
||||
/// 因为将额外的中断寄存器传递给SBI实现时,其内容将是未定义的。
|
||||
#[inline]
|
||||
pub unsafe fn ecall2(
|
||||
arg0: usize,
|
||||
arg1: usize,
|
||||
extension_id: usize,
|
||||
function_id: usize,
|
||||
) -> Result<usize, SbiError> {
|
||||
let error: isize;
|
||||
let value: usize;
|
||||
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
inlateout("a0") arg0 => error,
|
||||
inlateout("a1") arg1 => value,
|
||||
in("a6") function_id,
|
||||
in("a7") extension_id,
|
||||
);
|
||||
|
||||
match error {
|
||||
0 => Result::Ok(value),
|
||||
e => Result::Err(SbiError::new(e)),
|
||||
}
|
||||
}
|
||||
|
||||
/// 使用给定的扩展和函数 ID 进行 3参数 的 `ecall`。
|
||||
///
|
||||
/// # 安全性
|
||||
/// 只有在给定的函数 ID 接受一个参数时,调用此函数才是安全的,否则行为是未定义的,
|
||||
/// 因为当传递给 SBI 实现时,额外的参数寄存器将具有未定义的内容。
|
||||
#[inline]
|
||||
pub unsafe fn ecall3(
|
||||
arg0: usize,
|
||||
arg1: usize,
|
||||
arg2: usize,
|
||||
extension_id: usize,
|
||||
function_id: usize,
|
||||
) -> Result<usize, SbiError> {
|
||||
let error: isize;
|
||||
let value: usize;
|
||||
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
inlateout("a0") arg0 => error,
|
||||
inlateout("a1") arg1 => value,
|
||||
in("a2") arg2,
|
||||
in("a6") function_id,
|
||||
in("a7") extension_id,
|
||||
);
|
||||
|
||||
match error {
|
||||
0 => Result::Ok(value),
|
||||
e => Result::Err(SbiError::new(e)),
|
||||
}
|
||||
}
|
||||
|
||||
/// 使用给定的扩展和函数 ID 进行 4参数 的 `ecall`。
|
||||
///
|
||||
/// # 安全性
|
||||
/// 只有在给定的函数 ID 接受一个参数时,调用此函数才是安全的,否则行为是未定义的,
|
||||
/// 因为当传递给 SBI 实现时,额外的参数寄存器将具有未定义的内容。
|
||||
#[inline]
|
||||
pub unsafe fn ecall4(
|
||||
arg0: usize,
|
||||
arg1: usize,
|
||||
arg2: usize,
|
||||
arg3: usize,
|
||||
extension_id: usize,
|
||||
function_id: usize,
|
||||
) -> Result<usize, SbiError> {
|
||||
let error: isize;
|
||||
let value: usize;
|
||||
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
inlateout("a0") arg0 => error,
|
||||
inlateout("a1") arg1 => value,
|
||||
in("a2") arg2,
|
||||
in("a3") arg3,
|
||||
in("a6") function_id,
|
||||
in("a7") extension_id,
|
||||
);
|
||||
|
||||
match error {
|
||||
0 => Result::Ok(value),
|
||||
e => Result::Err(SbiError::new(e)),
|
||||
}
|
||||
}
|
||||
|
||||
/// 使用给定的扩展和函数 ID 进行 5参数 的 `ecall`。
|
||||
///
|
||||
/// # 安全性
|
||||
/// 只有在给定的函数 ID 接受一个参数时,调用此函数才是安全的,否则行为是未定义的,
|
||||
/// 因为当传递给 SBI 实现时,额外的参数寄存器将具有未定义的内容。
|
||||
#[inline]
|
||||
pub unsafe fn ecall5(
|
||||
arg0: usize,
|
||||
arg1: usize,
|
||||
arg2: usize,
|
||||
arg3: usize,
|
||||
arg4: usize,
|
||||
extension_id: usize,
|
||||
function_id: usize,
|
||||
) -> Result<usize, SbiError> {
|
||||
let error: isize;
|
||||
let value: usize;
|
||||
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
inlateout("a0") arg0 => error,
|
||||
inlateout("a1") arg1 => value,
|
||||
in("a2") arg2,
|
||||
in("a3") arg3,
|
||||
in("a4") arg4,
|
||||
in("a6") function_id,
|
||||
in("a7") extension_id,
|
||||
);
|
||||
|
||||
match error {
|
||||
0 => Result::Ok(value),
|
||||
e => Result::Err(SbiError::new(e)),
|
||||
}
|
||||
}
|
||||
|
||||
/// 使用给定的扩展和函数 ID 进行 6参数 的 `ecall`。
|
||||
///
|
||||
/// # 安全性
|
||||
/// 只有在给定的函数 ID 接受一个参数时,调用此函数才是安全的,否则行为是未定义的,
|
||||
/// 因为当传递给 SBI 实现时,额外的参数寄存器将具有未定义的内容。
|
||||
#[inline]
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub unsafe fn ecall6(
|
||||
arg0: usize,
|
||||
arg1: usize,
|
||||
arg2: usize,
|
||||
arg3: usize,
|
||||
arg4: usize,
|
||||
arg5: usize,
|
||||
extension_id: usize,
|
||||
function_id: usize,
|
||||
) -> Result<usize, SbiError> {
|
||||
let error: isize;
|
||||
let value: usize;
|
||||
|
||||
core::arch::asm!(
|
||||
"ecall",
|
||||
inlateout("a0") arg0 => error,
|
||||
inlateout("a1") arg1 => value,
|
||||
in("a2") arg2,
|
||||
in("a3") arg3,
|
||||
in("a4") arg4,
|
||||
in("a5") arg5,
|
||||
in("a6") function_id,
|
||||
in("a7") extension_id,
|
||||
);
|
||||
|
||||
match error {
|
||||
0 => Result::Ok(value),
|
||||
e => Result::Err(SbiError::new(e)),
|
||||
}
|
||||
}
|
194
kernel/src/arch/riscv64/driver/sbi/legacy.rs
Normal file
194
kernel/src/arch/riscv64/driver/sbi/legacy.rs
Normal file
@ -0,0 +1,194 @@
|
||||
use crate::{
|
||||
arch::driver::sbi::ecall::{ecall0, ecall1},
|
||||
mm::VirtAddr,
|
||||
};
|
||||
use core::arch::asm;
|
||||
|
||||
/// `sbi_set_timer` extension ID
|
||||
pub const SET_TIMER_EID: usize = 0x00;
|
||||
/// `sbi_console_putchar` extension ID
|
||||
pub const CONSOLE_PUTCHAR_EID: usize = 0x01;
|
||||
/// `sbi_console_getchar` extension ID
|
||||
pub const CONSOLE_GETCHAR_EID: usize = 0x02;
|
||||
/// `sbi_clear_ipi` extension ID
|
||||
pub const CLEAR_IPI_EID: usize = 0x03;
|
||||
/// `sbi_send_ipi` extension ID
|
||||
pub const SEND_IPI_EID: usize = 0x04;
|
||||
/// `sbi_remote_fence_i` extension ID
|
||||
pub const REMOTE_FENCE_I_EID: usize = 0x05;
|
||||
/// `sbi_remote_sfence_vma` extension ID
|
||||
pub const REMOTE_SFENCE_VMA_EID: usize = 0x06;
|
||||
/// `sbi_remote_sfence_vma_asid` extension ID
|
||||
pub const REMOTE_SFENCE_VMA_ASID_EID: usize = 0x07;
|
||||
/// `sbi_shutdown` extension ID
|
||||
pub const SHUTDOWN_EID: usize = 0x08;
|
||||
|
||||
/// 计划在未来的某个时间触发中断。
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - `stime`:要触发中断的绝对时间,以滴答为单位。如果`stime`小于当前时间,则不会触发中断。
|
||||
///
|
||||
/// ## 详情
|
||||
///
|
||||
/// 要清除计时器中断而不预约另一个计时器事件,可以将时间设置为无限远(`u64::MAX`)或
|
||||
/// mask `sie` CSR的`STIE` 位。此函数将清除待处理计时器中断位。
|
||||
///
|
||||
/// 注意:`time` 是一个绝对时间,不是从调用时刻开始的偏移量。这意味着如果您想要设置一个未来`n`和tick之后
|
||||
/// 触发的时钟,您需要首先读取 `time` CSR,然后将滴答数添加到该值。关于如何确定每个滴答的时间,
|
||||
/// 这是平台依赖的,而时钟频率应在 CPU 节点的 `timebase-frequency` 属性中表达,如果可用的话。
|
||||
#[inline]
|
||||
pub unsafe fn set_timer(stime: u64) {
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
unsafe {
|
||||
ecall1(stime as usize, SET_TIMER_EID, 0).ok();
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "riscv32")]
|
||||
unsafe {
|
||||
asm!(
|
||||
"ecall",
|
||||
inout ("a0") stime as usize => _,
|
||||
inout ("a1") (stime >> 32) as usize => _,
|
||||
in("a7") SET_TIMER_EID,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 将字符写入调试控制台。如果仍有待处理的控制台输出,此调用将阻塞。如果不存在控制台,则不会执行任何操作。
|
||||
#[inline]
|
||||
pub unsafe fn console_putchar(c: u8) {
|
||||
unsafe {
|
||||
ecall1(c.into(), CONSOLE_PUTCHAR_EID, 0).ok();
|
||||
}
|
||||
}
|
||||
|
||||
/// 尝试从调试控制台获取一个字符。
|
||||
/// 如果没有任何字符等待阅读,或者没有调试控制台设备,则此函数将返回[`None`]。
|
||||
#[inline]
|
||||
pub unsafe fn console_getchar() -> Option<u8> {
|
||||
let mut ret: i8;
|
||||
|
||||
unsafe {
|
||||
asm!(
|
||||
"ecall",
|
||||
lateout("a0") ret,
|
||||
in("a7") CONSOLE_GETCHAR_EID,
|
||||
);
|
||||
}
|
||||
|
||||
match ret {
|
||||
-1 => None,
|
||||
_ => Some(ret as u8),
|
||||
}
|
||||
}
|
||||
|
||||
/// 清除current核心的待处理中断(IPIs)。
|
||||
#[inline]
|
||||
#[deprecated = "S模式可以直接清除`sip.SSIP` CSR位,因此无需调用此函数。"]
|
||||
pub unsafe fn clear_ipi() {
|
||||
unsafe {
|
||||
asm!(
|
||||
"ecall",
|
||||
in("a7") CLEAR_IPI_EID,
|
||||
lateout("a0") _,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 向所有由`hart_mask`位掩码指定的核心发送中断(IPI)。接收到的中断表示为监视器软件中断。
|
||||
///
|
||||
/// ## 参数
|
||||
/// - `hart_mask`: 一个长度为`n_harts / size_of::<usize>()`的二进制位向量,向上取整到下一个`usize`。
|
||||
#[inline]
|
||||
pub unsafe fn send_ipi(hart_mask: &[usize]) {
|
||||
unsafe {
|
||||
asm!(
|
||||
"ecall",
|
||||
inlateout("a0") hart_mask.as_ptr() => _,
|
||||
in("a7") SEND_IPI_EID,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 对指定的心脏(hart)执行 `FENCE.I` 指令
|
||||
///
|
||||
/// ## 参数
|
||||
/// - `hart_mask`: 一个长度为 `n_harts / size_of::<usize>()` 的位矢量,
|
||||
/// 向上取整到下一个 `usize」。
|
||||
#[inline]
|
||||
pub unsafe fn remote_fence_i(hart_mask: &[usize]) {
|
||||
unsafe {
|
||||
asm!(
|
||||
"ecall",
|
||||
inlateout("a0") hart_mask.as_ptr() => _,
|
||||
in("a7") REMOTE_FENCE_I_EID,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 在指定的hart上执行`SFENCE.VMA`指令
|
||||
/// 为指定的虚拟内存范围(由`start`和`size`指定)执行。
|
||||
///
|
||||
/// ## 参数
|
||||
/// - `hart_mask`: 一个长度为`n_harts / size_of::<usize>()`的二进制向量,
|
||||
/// 向上取整到下一个`usize`。
|
||||
/// - `start`: 要执行`SFENCE.VMA`的起始虚拟地址。
|
||||
/// - `size`: 要对`start`执行的`SFENCE.VMA`的字节大小。例如,要失效一个
|
||||
/// 包含2个4-KiB页面的区域,您会为`size`传递`8192`。
|
||||
///
|
||||
/// 如果`start`和`size`都为`0`,或者如果`size`为[`usize::MAX`],则将执行完整的
|
||||
/// `SFENCE.VMA`,而不仅仅是一个或多个页面大小的`SFENCE.VMA`。
|
||||
#[inline]
|
||||
pub unsafe fn remote_sfence_vma(hart_mask: &[usize], start: VirtAddr, size: usize) {
|
||||
unsafe {
|
||||
asm!(
|
||||
"ecall",
|
||||
inlateout("a0") hart_mask.as_ptr() => _,
|
||||
in("a1") start.data(),
|
||||
in("a2") size,
|
||||
in("a7") REMOTE_SFENCE_VMA_EID,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 在指定的hart上执行SFENCE.VMA指令
|
||||
///
|
||||
/// 仅针对指定的地址空间ID(ASID)执行虚拟内存范围指定的
|
||||
/// start和size的hart_mask位掩码。
|
||||
///
|
||||
/// ## 参数
|
||||
/// - `hart_mask`: 一个长度为`n_harts / size_of::<usize>()`的二进制向量,
|
||||
/// 向上取整到下一个`usize`。
|
||||
/// - `start`: 要执行`SFENCE.VMA`的起始虚拟地址。
|
||||
/// - `size`: 要对`start`执行的`SFENCE.VMA`的字节大小。例如,要失效一个
|
||||
/// 包含2个4-KiB页面的区域,您会为`size`传递`8192`。
|
||||
/// - `asid`: 要执行`SFENCE.VMA`的地址空间ID。
|
||||
///
|
||||
/// 如果start和size都为0,或者如果size为[usize::MAX],则将执行全
|
||||
/// 部SFENCE.VMA,而不是多个页面大小的SFENCE.VMA`。
|
||||
#[inline]
|
||||
pub unsafe fn remote_sfence_vma_asid(hart_mask: &[usize], start: usize, size: usize, asid: usize) {
|
||||
unsafe {
|
||||
asm!(
|
||||
"ecall",
|
||||
inlateout("a0") hart_mask.as_ptr() => _,
|
||||
in("a1") start,
|
||||
in("a2") size,
|
||||
in("a3") asid,
|
||||
in("a7") REMOTE_SFENCE_VMA_ASID_EID,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 将所有核心置于关闭状态,此时处理器的执行模式比当前监督模式具有更高的特权。此调用不会返回。
|
||||
#[inline]
|
||||
pub unsafe fn shutdown() -> ! {
|
||||
unsafe {
|
||||
asm!(
|
||||
"ecall",
|
||||
in("a7") SHUTDOWN_EID,
|
||||
options(noreturn)
|
||||
);
|
||||
}
|
||||
}
|
93
kernel/src/arch/riscv64/driver/sbi/mod.rs
Normal file
93
kernel/src/arch/riscv64/driver/sbi/mod.rs
Normal file
@ -0,0 +1,93 @@
|
||||
use self::legacy::console_putchar;
|
||||
|
||||
/// The SBI S-mode driver.
|
||||
///
|
||||
/// Some code takes from `https://github.com/repnop/sbi.git`
|
||||
mod ecall;
|
||||
pub mod legacy;
|
||||
|
||||
/// Error codes returned by SBI calls
|
||||
///
|
||||
/// note: `SBI_SUCCESS` is not represented here since this is to be used as the
|
||||
/// error type in a `Result`
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum SbiError {
|
||||
/// The SBI call failed
|
||||
Failed,
|
||||
/// The SBI call is not implemented or the functionality is not available
|
||||
NotSupported,
|
||||
/// An invalid parameter was passed
|
||||
InvalidParameter,
|
||||
/// The SBI implementation has denied execution of the call functionality
|
||||
Denied,
|
||||
/// An invalid address was passed
|
||||
InvalidAddress,
|
||||
/// The resource is already available
|
||||
AlreadyAvailable,
|
||||
/// The resource was previously started
|
||||
AlreadyStarted,
|
||||
/// The resource was previously stopped
|
||||
AlreadyStopped,
|
||||
}
|
||||
|
||||
impl SbiError {
|
||||
#[inline]
|
||||
fn new(n: isize) -> Self {
|
||||
match n {
|
||||
-1 => SbiError::Failed,
|
||||
-2 => SbiError::NotSupported,
|
||||
-3 => SbiError::InvalidParameter,
|
||||
-4 => SbiError::Denied,
|
||||
-5 => SbiError::InvalidAddress,
|
||||
-6 => SbiError::AlreadyAvailable,
|
||||
-7 => SbiError::AlreadyStarted,
|
||||
-8 => SbiError::AlreadyStopped,
|
||||
n => unreachable!("bad SBI error return value: {}", n),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Display for SbiError {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match self {
|
||||
SbiError::AlreadyAvailable => "resource is already available",
|
||||
SbiError::Denied => "SBI implementation denied execution",
|
||||
SbiError::Failed => "call to SBI failed",
|
||||
SbiError::InvalidAddress => "invalid address passed",
|
||||
SbiError::InvalidParameter => "invalid parameter passed",
|
||||
SbiError::NotSupported => "SBI call not implemented or functionality not available",
|
||||
SbiError::AlreadyStarted => "resource was already started",
|
||||
SbiError::AlreadyStopped => "resource was already stopped",
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// 向控制台打印字符串。
|
||||
///
|
||||
/// 该函数接受一个字节切片 `s` 作为输入,并迭代切片中的每个字节 `c`。
|
||||
/// 然后调用 `console_putchar` 函数,将 `c` 的值作为参数传递给它。
|
||||
///
|
||||
/// # 安全性
|
||||
/// 该函数被标记为 `unsafe`,因为它调用了 `console_putchar` 函数,
|
||||
/// 而假设该函数执行可能有副作用或违反内存安全的底层操作。
|
||||
/// 调用者有责任确保 `s` 切片是有效的并且正确终止的。
|
||||
///
|
||||
/// # 参数
|
||||
///
|
||||
/// * `s` - 表示要打印的字符串的字节切片。
|
||||
///
|
||||
/// # 示例
|
||||
///
|
||||
/// ```
|
||||
/// let message = b"Hello, World!";
|
||||
/// console_putstr(message);
|
||||
/// ```
|
||||
pub unsafe fn console_putstr(s: &[u8]) {
|
||||
for c in s {
|
||||
unsafe { console_putchar(*c) };
|
||||
}
|
||||
}
|
14
kernel/src/arch/riscv64/init/mod.rs
Normal file
14
kernel/src/arch/riscv64/init/mod.rs
Normal file
@ -0,0 +1,14 @@
|
||||
use core::intrinsics::unreachable;
|
||||
|
||||
use crate::{
|
||||
driver::tty::serial::serial8250::send_to_default_serial8250_port, init::init_before_mem_init,
|
||||
kdebug,
|
||||
};
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn kernel_main(hartid: usize, fdt_addr: usize) -> ! {
|
||||
init_before_mem_init();
|
||||
send_to_default_serial8250_port(&b"Hello, world! RISC-V!\n"[..]);
|
||||
loop {}
|
||||
unreachable()
|
||||
}
|
@ -10,8 +10,8 @@ ENTRY(_start)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
KERNEL_VMA = 0xffffffc000000000;
|
||||
//KERNEL_VMA = 0;
|
||||
//KERNEL_VMA = 0xffffffc000000000;
|
||||
KERNEL_VMA = 0;
|
||||
. = 0x1000000;
|
||||
|
||||
.boot.text :
|
||||
@ -44,7 +44,8 @@ SECTIONS
|
||||
_data = .;
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
|
||||
*(.got.plt)
|
||||
*(.got)
|
||||
_edata = .;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
pub mod asm;
|
||||
pub mod cpu;
|
||||
pub mod driver;
|
||||
mod init;
|
||||
pub mod interrupt;
|
||||
pub mod ipc;
|
||||
mod kvm;
|
||||
|
@ -10,6 +10,19 @@ use super::interrupt::TrapFrame;
|
||||
pub mod kthread;
|
||||
pub mod syscall;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[repr(align(32768))]
|
||||
union InitProcUnion {
|
||||
/// 用于存放idle进程的内核栈
|
||||
idle_stack: [u8; 32768],
|
||||
}
|
||||
|
||||
#[link_section = ".data.init_proc_union"]
|
||||
#[no_mangle]
|
||||
static BSP_IDLE_STACK_SPACE: InitProcUnion = InitProcUnion {
|
||||
idle_stack: [0; 32768],
|
||||
};
|
||||
|
||||
pub unsafe fn arch_switch_to_user(path: String, argv: Vec<String>, envp: Vec<String>) -> ! {
|
||||
unimplemented!("RiscV64 arch_switch_to_user")
|
||||
}
|
||||
|
18
kernel/src/arch/riscv64/riscv64imac-unknown-none-elf.json
Normal file
18
kernel/src/arch/riscv64/riscv64imac-unknown-none-elf.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"arch": "riscv64",
|
||||
"code-model": "medium",
|
||||
"cpu": "generic-rv64",
|
||||
"data-layout": "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128",
|
||||
"eh-frame-header": false,
|
||||
"emit-debug-gdb-scripts": false,
|
||||
"features": "+m,+a,+c",
|
||||
"is-builtin": false,
|
||||
"linker": "rust-lld",
|
||||
"linker-flavor": "ld.lld",
|
||||
"llvm-target": "riscv64",
|
||||
"max-atomic-width": 64,
|
||||
"panic-strategy": "abort",
|
||||
"relocation-model": "pic",
|
||||
"position-independent-executables": true,
|
||||
"target-pointer-width": "64"
|
||||
}
|
@ -67,7 +67,7 @@ impl Hpet {
|
||||
let tm_num = hpet.timers_num();
|
||||
kinfo!("HPET has {} timers", tm_num);
|
||||
hpet_info.hpet_number = tm_num as u8;
|
||||
drop(hpet);
|
||||
|
||||
drop(mmio);
|
||||
if tm_num == 0 {
|
||||
return Err(SystemError::ENODEV);
|
||||
@ -118,7 +118,6 @@ impl Hpet {
|
||||
|
||||
unsafe { regs.write_main_counter_value(0) };
|
||||
|
||||
drop(regs);
|
||||
drop(inner_guard);
|
||||
|
||||
let (inner_guard, timer_reg) = unsafe { self.timer_mut(0).ok_or(SystemError::ENODEV) }?;
|
||||
@ -130,7 +129,6 @@ impl Hpet {
|
||||
volwrite!(timer_reg, config, 0x004c);
|
||||
volwrite!(timer_reg, comparator_value, ticks);
|
||||
}
|
||||
drop(timer_reg);
|
||||
drop(inner_guard);
|
||||
|
||||
// todo!("register irq in C");
|
||||
@ -142,7 +140,6 @@ impl Hpet {
|
||||
// 置位旧设备中断路由兼容标志位、定时器组使能标志位
|
||||
unsafe { regs.write_general_config(3) };
|
||||
|
||||
drop(regs);
|
||||
drop(inner_guard);
|
||||
|
||||
kinfo!("HPET enabled");
|
||||
@ -208,7 +205,7 @@ impl Hpet {
|
||||
pub fn main_counter_value(&self) -> u64 {
|
||||
let (inner_guard, regs) = unsafe { self.hpet_regs() };
|
||||
let value = regs.main_counter_value();
|
||||
drop(regs);
|
||||
|
||||
drop(inner_guard);
|
||||
return value;
|
||||
}
|
||||
@ -217,7 +214,7 @@ impl Hpet {
|
||||
let (inner_guard, regs) = unsafe { self.hpet_regs() };
|
||||
let period = regs.counter_clock_period();
|
||||
kdebug!("HPET period: {}", period);
|
||||
drop(regs);
|
||||
|
||||
drop(inner_guard);
|
||||
return period;
|
||||
}
|
||||
|
Reference in New Issue
Block a user