kernel-hal: refactor for libos

This commit is contained in:
Yuekai Jia 2021-09-02 18:19:10 +08:00
parent de809efca2
commit 937c86f01d
89 changed files with 1373 additions and 1393 deletions

View File

@ -5,7 +5,6 @@ members = [
"linux-object",
"zircon-syscall",
"linux-loader",
"kernel-hal-unix",
"kernel-hal",
]

View File

@ -146,7 +146,7 @@ fn page_fault(stval: usize, tf: &mut TrapFrame) {
let vaddr = stval;
use crate::PageTableImpl;
use kernel_hal::{MMUFlags, PageTableTrait};
use kernel_hal::{MMUFlags, paging::PageTableTrait};
use riscv::addr::{Page, PhysAddr, VirtAddr};
use riscv::paging::{PageTableFlags as PTF, Rv39PageTable, *};

View File

@ -1,8 +1,6 @@
use super::super::*;
use kernel_hal::{
ColorDepth, ColorFormat, FramebufferInfo, HalError, PageTableTrait, PhysAddr, VirtAddr,
FRAME_BUFFER,
};
use kernel_hal::dev::fb::{ColorDepth, ColorFormat, FramebufferInfo, FRAME_BUFFER};
use kernel_hal::{HalError, PhysAddr, VirtAddr, paging::PageTableTrait};
use riscv::addr::Page;
use riscv::asm::sfence_vma_all;
use riscv::paging::{PageTableFlags as PTF, *};

View File

@ -9,9 +9,8 @@ use {
core::ptr::NonNull,
core::time::Duration,
git_version::git_version,
kernel_hal::{
ColorDepth, ColorFormat, FramebufferInfo, HalError, PageTableTrait, Result, FRAME_BUFFER,
},
kernel_hal::dev::fb::{ColorDepth, ColorFormat, FramebufferInfo, FRAME_BUFFER},
kernel_hal::{HalError, paging::PageTableTrait, HalResult as Result},
rcore_console::{Console, ConsoleOnGraphic, DrawTarget, Pixel, Rgb888, Size},
spin::Mutex,
uart_16550::SerialPort,

View File

@ -35,9 +35,9 @@ use core::{
pin::Pin,
task::{Context, Poll},
};
use kernel_hal::defs::*;
use kernel_hal::{VirtAddr, PhysAddr, PAGE_SIZE, CachePolicy, MMUFlags};
use kernel_hal::vdso::*;
use kernel_hal::UserContext;
use kernel_hal::context::UserContext;
use naive_timer::Timer;
use spin::Mutex;

View File

@ -1,19 +0,0 @@
[package]
name = "kernel-hal-unix"
version = "0.1.0"
authors = ["Runji Wang <wangrunji0408@163.com>"]
edition = "2018"
description = "Kernel HAL implementation on Linux and macOS."
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
log = "0.4"
libc = "0.2"
tempfile = "3"
bitflags = "1.2"
lazy_static = "1.4"
kernel-hal = { path = "../kernel-hal" }
async-std = "1.9"
git-version = "0.3"
trapframe = "0.8.0"

View File

@ -1,676 +0,0 @@
#![feature(asm)]
#![feature(linkage)]
#![deny(warnings)]
#[macro_use]
extern crate log;
extern crate alloc;
use {
alloc::collections::VecDeque,
async_std::task_local,
core::{cell::Cell, future::Future, pin::Pin},
git_version::git_version,
kernel_hal::PageTableTrait,
lazy_static::lazy_static,
std::fmt::{Debug, Formatter},
std::fs::{File, OpenOptions},
std::io::Error,
std::os::unix::io::AsRawFd,
std::sync::Mutex,
std::time::{Duration, SystemTime},
tempfile::tempdir,
};
pub use kernel_hal::defs::*;
use kernel_hal::vdso::*;
pub use kernel_hal::*;
use std::io::Read;
pub use trapframe::syscall_fn_entry as syscall_entry;
#[cfg(target_os = "macos")]
include!("macos.rs");
#[repr(C)]
pub struct Thread {
thread: usize,
}
impl Thread {
#[export_name = "hal_thread_spawn"]
pub fn spawn(
future: Pin<Box<dyn Future<Output = ()> + Send + 'static>>,
_vmtoken: usize,
) -> Self {
async_std::task::spawn(future);
Thread { thread: 0 }
}
#[export_name = "hal_thread_set_tid"]
pub fn set_tid(tid: u64, pid: u64) {
TID.with(|x| x.set(tid));
PID.with(|x| x.set(pid));
}
#[export_name = "hal_thread_get_tid"]
pub fn get_tid() -> (u64, u64) {
(TID.with(|x| x.get()), PID.with(|x| x.get()))
}
}
task_local! {
static TID: Cell<u64> = Cell::new(0);
static PID: Cell<u64> = Cell::new(0);
}
#[export_name = "hal_context_run"]
unsafe fn context_run(context: &mut UserContext) {
context.run_fncall();
}
/// Page Table
#[repr(C)]
pub struct PageTable {
table_phys: PhysAddr,
}
impl PageTable {
/// Create a new `PageTable`.
#[allow(clippy::new_without_default)]
#[export_name = "hal_pt_new"]
pub fn new() -> Self {
PageTable { table_phys: 0 }
}
}
impl PageTableTrait for PageTable {
/// Map the page of `vaddr` to the frame of `paddr` with `flags`.
#[export_name = "hal_pt_map"]
fn map(&mut self, vaddr: VirtAddr, paddr: PhysAddr, flags: MMUFlags) -> Result<()> {
debug_assert!(page_aligned(vaddr));
debug_assert!(page_aligned(paddr));
let prot = flags.to_mmap_prot();
mmap(FRAME_FILE.as_raw_fd(), paddr, PAGE_SIZE, vaddr, prot);
Ok(())
}
/// Unmap the page of `vaddr`.
#[export_name = "hal_pt_unmap"]
fn unmap(&mut self, vaddr: VirtAddr) -> Result<()> {
self.unmap_cont(vaddr, 1)
}
/// Change the `flags` of the page of `vaddr`.
#[export_name = "hal_pt_protect"]
fn protect(&mut self, vaddr: VirtAddr, flags: MMUFlags) -> Result<()> {
debug_assert!(page_aligned(vaddr));
let prot = flags.to_mmap_prot();
let ret = unsafe { libc::mprotect(vaddr as _, PAGE_SIZE, prot) };
assert_eq!(ret, 0, "failed to mprotect: {:?}", Error::last_os_error());
Ok(())
}
/// Query the physical address which the page of `vaddr` maps to.
#[export_name = "hal_pt_query"]
fn query(&mut self, vaddr: VirtAddr) -> Result<PhysAddr> {
debug_assert!(page_aligned(vaddr));
unimplemented!()
}
/// Get the physical address of root page table.
#[export_name = "hal_pt_table_phys"]
fn table_phys(&self) -> PhysAddr {
self.table_phys
}
#[export_name = "hal_pt_unmap_cont"]
fn unmap_cont(&mut self, vaddr: VirtAddr, pages: usize) -> Result<()> {
if pages == 0 {
return Ok(());
}
debug_assert!(page_aligned(vaddr));
let ret = unsafe { libc::munmap(vaddr as _, PAGE_SIZE * pages) };
assert_eq!(ret, 0, "failed to munmap: {:?}", Error::last_os_error());
Ok(())
}
}
#[repr(C)]
pub struct PhysFrame {
paddr: PhysAddr,
}
impl Debug for PhysFrame {
fn fmt(&self, f: &mut Formatter<'_>) -> core::result::Result<(), std::fmt::Error> {
write!(f, "PhysFrame({:#x})", self.paddr)
}
}
lazy_static! {
static ref AVAILABLE_FRAMES: Mutex<VecDeque<usize>> =
Mutex::new((PAGE_SIZE..PMEM_SIZE).step_by(PAGE_SIZE).collect());
}
impl PhysFrame {
#[export_name = "hal_frame_alloc"]
pub fn alloc() -> Option<Self> {
let ret = AVAILABLE_FRAMES
.lock()
.unwrap()
.pop_front()
.map(|paddr| PhysFrame { paddr });
trace!("frame alloc: {:?}", ret);
ret
}
#[export_name = "hal_zero_frame_paddr"]
pub fn zero_frame_addr() -> PhysAddr {
0
}
}
impl Drop for PhysFrame {
#[export_name = "hal_frame_dealloc"]
fn drop(&mut self) {
trace!("frame dealloc: {:?}", self);
AVAILABLE_FRAMES.lock().unwrap().push_back(self.paddr);
}
}
fn phys_to_virt(paddr: PhysAddr) -> VirtAddr {
/// Map physical memory from here.
const PMEM_BASE: VirtAddr = 0x8_0000_0000;
PMEM_BASE + paddr
}
/// Ensure physical memory are mmapped and accessible.
fn ensure_mmap_pmem() {
FRAME_FILE.as_raw_fd();
}
/// Read physical memory from `paddr` to `buf`.
#[export_name = "hal_pmem_read"]
pub fn pmem_read(paddr: PhysAddr, buf: &mut [u8]) {
trace!("pmem read: paddr={:#x}, len={:#x}", paddr, buf.len());
assert!(paddr + buf.len() <= PMEM_SIZE);
ensure_mmap_pmem();
unsafe {
(phys_to_virt(paddr) as *const u8).copy_to_nonoverlapping(buf.as_mut_ptr(), buf.len());
}
}
/// Write physical memory to `paddr` from `buf`.
#[export_name = "hal_pmem_write"]
pub fn pmem_write(paddr: PhysAddr, buf: &[u8]) {
trace!("pmem write: paddr={:#x}, len={:#x}", paddr, buf.len());
assert!(paddr + buf.len() <= PMEM_SIZE);
ensure_mmap_pmem();
unsafe {
buf.as_ptr()
.copy_to_nonoverlapping(phys_to_virt(paddr) as _, buf.len());
}
}
/// Zero physical memory at `[paddr, paddr + len)`
#[export_name = "hal_pmem_zero"]
pub fn pmem_zero(paddr: PhysAddr, len: usize) {
trace!("pmem_zero: addr={:#x}, len={:#x}", paddr, len);
assert!(paddr + len <= PMEM_SIZE);
ensure_mmap_pmem();
unsafe {
core::ptr::write_bytes(phys_to_virt(paddr) as *mut u8, 0, len);
}
}
/// Copy content of `src` frame to `target` frame
#[export_name = "hal_frame_copy"]
pub fn frame_copy(src: PhysAddr, target: PhysAddr) {
trace!("frame_copy: {:#x} <- {:#x}", target, src);
assert!(src + PAGE_SIZE <= PMEM_SIZE && target + PAGE_SIZE <= PMEM_SIZE);
ensure_mmap_pmem();
unsafe {
let buf = phys_to_virt(src) as *const u8;
buf.copy_to_nonoverlapping(phys_to_virt(target) as _, PAGE_SIZE);
}
}
/// Flush the physical frame.
#[export_name = "hal_frame_flush"]
pub fn frame_flush(_target: PhysAddr) {
// do nothing
}
const PAGE_SIZE: usize = 0x1000;
fn page_aligned(x: VirtAddr) -> bool {
x % PAGE_SIZE == 0
}
const PMEM_SIZE: usize = 0x4000_0000; // 1GiB
lazy_static! {
static ref FRAME_FILE: File = create_pmem_file();
}
fn create_pmem_file() -> File {
let dir = tempdir().expect("failed to create pmem dir");
let path = dir.path().join("pmem");
// workaround on macOS to avoid permission denied.
// see https://jiege.ch/software/2020/02/07/macos-mmap-exec/ for analysis on this problem.
#[cfg(target_os = "macos")]
std::mem::forget(dir);
let file = OpenOptions::new()
.read(true)
.write(true)
.create(true)
.open(&path)
.expect("failed to create pmem file");
file.set_len(PMEM_SIZE as u64)
.expect("failed to resize file");
trace!("create pmem file: path={:?}, size={:#x}", path, PMEM_SIZE);
let prot = libc::PROT_READ | libc::PROT_WRITE;
mmap(file.as_raw_fd(), 0, PMEM_SIZE, phys_to_virt(0), prot);
file
}
/// Mmap frame file `fd` to `vaddr`.
fn mmap(fd: libc::c_int, offset: usize, len: usize, vaddr: VirtAddr, prot: libc::c_int) {
// workaround on macOS to write text section.
#[cfg(target_os = "macos")]
let prot = if prot & libc::PROT_EXEC != 0 {
prot | libc::PROT_WRITE
} else {
prot
};
let ret = unsafe {
let flags = libc::MAP_SHARED | libc::MAP_FIXED;
libc::mmap(vaddr as _, len, prot, flags, fd, offset as _)
} as usize;
trace!(
"mmap file: fd={}, offset={:#x}, len={:#x}, vaddr={:#x}, prot={:#b}",
fd,
offset,
len,
vaddr,
prot,
);
assert_eq!(ret, vaddr, "failed to mmap: {:?}", Error::last_os_error());
}
trait FlagsExt {
fn to_mmap_prot(&self) -> libc::c_int;
}
impl FlagsExt for MMUFlags {
fn to_mmap_prot(&self) -> libc::c_int {
let mut flags = 0;
if self.contains(MMUFlags::READ) {
flags |= libc::PROT_READ;
}
if self.contains(MMUFlags::WRITE) {
flags |= libc::PROT_WRITE;
}
if self.contains(MMUFlags::EXECUTE) {
flags |= libc::PROT_EXEC;
}
flags
}
}
lazy_static! {
static ref STDIN: Mutex<VecDeque<u8>> = Mutex::new(VecDeque::new());
static ref STDIN_CALLBACK: Mutex<Vec<Box<dyn Fn() -> bool + Send + Sync>>> =
Mutex::new(Vec::new());
}
/// Put a char by serial interrupt handler.
fn serial_put(x: u8) {
STDIN.lock().unwrap().push_back(x);
STDIN_CALLBACK.lock().unwrap().retain(|f| !f());
}
#[export_name = "hal_serial_set_callback"]
pub fn serial_set_callback(callback: Box<dyn Fn() -> bool + Send + Sync>) {
STDIN_CALLBACK.lock().unwrap().push(callback);
}
#[export_name = "hal_serial_read"]
pub fn serial_read(buf: &mut [u8]) -> usize {
let mut stdin = STDIN.lock().unwrap();
let len = stdin.len().min(buf.len());
for c in &mut buf[..len] {
*c = stdin.pop_front().unwrap();
}
len
}
/// Output a char to console.
#[export_name = "hal_serial_write"]
pub fn serial_write(s: &str) {
eprint!("{}", s);
}
/// Get current time.
#[export_name = "hal_timer_now"]
pub fn timer_now() -> Duration {
SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
}
/// Set a new timer.
///
/// After `deadline`, the `callback` will be called.
#[export_name = "hal_timer_set"]
pub fn timer_set(deadline: Duration, callback: Box<dyn FnOnce(Duration) + Send + Sync>) {
std::thread::spawn(move || {
let now = timer_now();
if deadline > now {
std::thread::sleep(deadline - now);
}
callback(timer_now());
});
}
#[export_name = "hal_vdso_constants"]
pub fn vdso_constants() -> VdsoConstants {
let tsc_frequency = 3000u16;
let mut constants = VdsoConstants {
max_num_cpus: 1,
features: Features {
cpu: 0,
hw_breakpoint_count: 0,
hw_watchpoint_count: 0,
},
dcache_line_size: 0,
icache_line_size: 0,
ticks_per_second: tsc_frequency as u64 * 1_000_000,
ticks_to_mono_numerator: 1000,
ticks_to_mono_denominator: tsc_frequency as u32,
physmem: PMEM_SIZE as u64,
version_string_len: 0,
version_string: Default::default(),
};
constants.set_version_string(git_version!(
prefix = "git-",
args = ["--always", "--abbrev=40", "--dirty=-dirty"]
));
constants
}
#[export_name = "hal_current_pgtable"]
pub fn current_page_table() -> usize {
0
}
/// Initialize the HAL.
///
/// This function must be called at the beginning.
pub fn init() {
#[cfg(target_os = "macos")]
unsafe {
register_sigsegv_handler();
}
// spawn a thread to read stdin
// TODO: raw mode
std::thread::spawn(|| {
for i in std::io::stdin().bytes() {
serial_put(i.unwrap());
}
});
}
pub fn init_framebuffer() {
const FBIOGET_VSCREENINFO: u64 = 0x4600;
const FBIOGET_FSCREENINFO: u64 = 0x4602;
#[cfg(target_arch = "aarch64")]
let fbfd = unsafe { libc::open("/dev/fb0".as_ptr(), libc::O_RDWR) };
#[cfg(not(target_arch = "aarch64"))]
let fbfd = unsafe { libc::open("/dev/fb0".as_ptr() as *const i8, libc::O_RDWR) };
if fbfd < 0 {
return;
}
#[repr(C)]
#[derive(Debug, Default)]
struct FbFixScreeninfo {
id: [u8; 16],
smem_start: u64,
smem_len: u32,
type_: u32,
type_aux: u32,
visual: u32,
xpanstep: u16,
ypanstep: u16,
ywrapstep: u16,
line_length: u32,
mmio_start: u64,
mmio_len: u32,
accel: u32,
capabilities: u16,
reserved: [u16; 2],
}
impl FbFixScreeninfo {
pub fn size(&self) -> u32 {
self.smem_len
}
}
#[repr(C)]
#[derive(Debug, Default)]
struct FbVarScreeninfo {
xres: u32,
yres: u32,
xres_virtual: u32,
yres_virtual: u32,
xoffset: u32,
yoffset: u32,
bits_per_pixel: u32,
grayscale: u32,
red: FbBitfield,
green: FbBitfield,
blue: FbBitfield,
transp: FbBitfield,
nonstd: u32,
activate: u32,
height: u32,
width: u32,
accel_flags: u32,
pixclock: u32,
left_margin: u32,
right_margin: u32,
upper_margin: u32,
lower_margin: u32,
hsync_len: u32,
vsync_len: u32,
sync: u32,
vmode: u32,
rotate: u32,
colorspace: u32,
reserved: [u32; 4],
}
impl FbVarScreeninfo {
pub fn resolution(&self) -> (u32, u32) {
(self.xres, self.yres)
}
}
#[repr(C)]
#[derive(Debug, Default)]
pub struct FbBitfield {
offset: u32,
length: u32,
msb_right: u32,
}
let mut vinfo = FbVarScreeninfo::default();
if unsafe { libc::ioctl(fbfd, FBIOGET_VSCREENINFO, &mut vinfo) } < 0 {
return;
}
let mut finfo = FbFixScreeninfo::default();
if unsafe { libc::ioctl(fbfd, FBIOGET_FSCREENINFO, &mut finfo) } < 0 {
return;
}
let size = finfo.size() as usize;
let addr = unsafe {
libc::mmap(
std::ptr::null_mut::<libc::c_void>(),
size,
libc::PROT_READ | libc::PROT_WRITE,
libc::MAP_SHARED,
fbfd,
0,
)
};
if (addr as isize) < 0 {
return;
}
let (width, height) = vinfo.resolution();
let addr = addr as usize;
let fb_info = FramebufferInfo {
xres: width,
yres: height,
xres_virtual: width,
yres_virtual: height,
xoffset: 0,
yoffset: 0,
depth: ColorDepth::ColorDepth32,
format: ColorFormat::RGBA8888,
// paddr: virt_to_phys(addr),
paddr: addr,
vaddr: addr,
screen_size: size,
};
*FRAME_BUFFER.write() = Some(fb_info);
}
type MouseCallbackFn = dyn Fn([u8; 3]) + Send + Sync;
type KBDCallbackFn = dyn Fn(u16, i32) + Send + Sync;
lazy_static! {
static ref MOUSE_CALLBACK: Mutex<Vec<Box<MouseCallbackFn>>> = Mutex::new(Vec::new());
static ref KBD_CALLBACK: Mutex<Vec<Box<KBDCallbackFn>>> = Mutex::new(Vec::new());
}
#[export_name = "hal_mice_set_callback"]
pub fn mice_set_callback(callback: Box<dyn Fn([u8; 3]) + Send + Sync>) {
MOUSE_CALLBACK.lock().unwrap().push(callback);
}
#[export_name = "hal_kbd_set_callback"]
pub fn kbd_set_callback(callback: Box<dyn Fn(u16, i32) + Send + Sync>) {
KBD_CALLBACK.lock().unwrap().push(callback);
}
fn init_kbd() {
let fd = std::fs::File::open("/dev/input/event1").expect("Failed to open input event device.");
// ??
/* let inputfd = unsafe {
libc::open(
"/dev/input/event1".as_ptr() as *const i8,
libc::O_RDONLY /* | libc::O_NONBLOCK */,
)
}; */
if fd.as_raw_fd() < 0 {
return;
}
#[repr(C)]
#[derive(Debug, Copy, Clone, Default)]
pub struct TimeVal {
pub sec: usize,
pub usec: usize,
}
#[repr(C)]
#[derive(Debug, Copy, Clone, Default)]
struct InputEvent {
time: TimeVal,
type_: u16,
code: u16,
value: i32,
}
std::thread::spawn(move || {
use core::mem::{size_of, transmute, transmute_copy};
let ev = InputEvent::default();
const LEN: usize = size_of::<InputEvent>();
let mut buf: [u8; LEN] = unsafe { transmute(ev) };
loop {
std::thread::sleep(std::time::Duration::from_millis(8));
let ret =
unsafe { libc::read(fd.as_raw_fd(), buf.as_mut_ptr() as *mut libc::c_void, LEN) };
if ret < 0 {
break;
}
let ev: InputEvent = unsafe { transmute_copy(&buf) };
if ev.type_ == 1 {
KBD_CALLBACK.lock().unwrap().iter().for_each(|callback| {
callback(ev.code, ev.value);
});
}
}
});
}
fn init_mice() {
let fd = std::fs::File::open("/dev/input/mice").expect("Failed to open input event device.");
if fd.as_raw_fd() < 0 {
return;
}
std::thread::spawn(move || {
let mut buf = [0u8; 3];
loop {
std::thread::sleep(std::time::Duration::from_millis(8));
let ret =
unsafe { libc::read(fd.as_raw_fd(), buf.as_mut_ptr() as *mut libc::c_void, 3) };
if ret < 0 {
break;
}
MOUSE_CALLBACK.lock().unwrap().iter().for_each(|callback| {
callback(buf);
});
}
});
}
pub fn init_input() {
init_kbd();
init_mice();
}
#[cfg(test)]
mod tests {
use super::*;
/// A valid virtual address base to mmap.
const VBASE: VirtAddr = 0x2_00000000;
#[test]
fn map_unmap() {
let mut pt = PageTable::new();
let flags = MMUFlags::READ | MMUFlags::WRITE;
// map 2 pages to 1 frame
pt.map(VBASE, 0x1000, flags).unwrap();
pt.map(VBASE + 0x1000, 0x1000, flags).unwrap();
unsafe {
const MAGIC: usize = 0xdead_beaf;
(VBASE as *mut usize).write(MAGIC);
assert_eq!(((VBASE + 0x1000) as *mut usize).read(), MAGIC);
}
pt.unmap(VBASE + 0x1000).unwrap();
}
}

View File

@ -1,18 +1,54 @@
[package]
name = "kernel-hal"
version = "0.1.0"
authors = ["Runji Wang <wangrunji0408@163.com>"]
authors = ["Runji Wang <wangrunji0408@163.com>", "Yuekai Jia <equation618@gmail.com>"]
edition = "2018"
description = "Kernel HAL interface definations."
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
libos = ["async-std"]
[dependencies]
log = "0.4"
bitflags = "1.2"
trapframe = "0.8.0"
numeric-enum-macro = "0.2"
acpi = "1.1"
spin = "0.7"
git-version = "0.3"
cfg-if = "1.0"
acpi = "1.1"
#[patch.crates-io]
#trapframe = { path = "/home/xly/rust/arch-lib/trapframe-rs" }
# LibOS mode
[target.'cfg(not(target_os = "none"))'.dependencies]
riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"], rev = "0074cbc" }
libc = "0.2"
tempfile = "3"
lazy_static = "1.4"
async-std = { version = "1.9", optional = true }
# Bare-metal mode
[target.'cfg(target_os = "none")'.dependencies]
# executor = { git = "https://github.com/rcore-os/executor.git", rev = "a2d02ee9" }
# naive-timer = "0.1.0"
# lazy_static = { version = "1.4", features = ["spin_no_std"] }
# rcore-fs = { git = "https://github.com/rcore-os/rcore-fs", rev = "6df6cd2" }
# device_tree = { git = "https://github.com/rcore-os/device_tree-rs" }
# virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers", rev = "568276" }
# Bare-metal mode on x86_64
[target.'cfg(all(target_os = "none", target_arch = "x86_64"))'.dependencies]
# x86_64 = "0.14"
# uart_16550 = "=0.2.15"
# raw-cpuid = "9.0"
# pc-keyboard = "0.5"
# apic = { git = "https://github.com/rcore-os/apic-rs", rev = "fb86bd7" }
# x86-smpboot = { git = "https://github.com/rcore-os/x86-smpboot", rev = "43ffedf" }
# rcore-console = { git = "https://github.com/rcore-os/rcore-console", default-features = false, rev = "a980897b" }
# ps2-mouse = { git = "https://github.com/YXL76/ps2-mouse", branch = "feat" }
# Bare-metal mode on riscv64
[target.'cfg(all(target_os = "none", target_arch = "riscv64"))'.dependencies]
# riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"], rev = "0074cbc" }
# volatile = "0.2"

View File

@ -1,5 +1,7 @@
use core::fmt;
pub use trapframe::{GeneralRegs, UserContext};
#[repr(C, align(16))]
#[derive(Debug, Copy, Clone)]
pub struct VectorRegs {

View File

@ -0,0 +1,38 @@
use bitflags::bitflags;
use numeric_enum_macro::numeric_enum;
/// The error type which is returned from HAL functions.
#[derive(Debug)]
pub struct HalError;
/// The result type returned by HAL functions.
pub type HalResult<T> = core::result::Result<T, HalError>;
bitflags! {
pub struct MMUFlags: usize {
#[allow(clippy::identity_op)]
const CACHE_1 = 1 << 0;
const CACHE_2 = 1 << 1;
const READ = 1 << 2;
const WRITE = 1 << 3;
const EXECUTE = 1 << 4;
const USER = 1 << 5;
const RXW = Self::READ.bits | Self::WRITE.bits | Self::EXECUTE.bits;
}
}
numeric_enum! {
#[repr(u32)]
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum CachePolicy {
Cached = 0,
Uncached = 1,
UncachedDevice = 2,
WriteCombining = 3,
}
}
pub const CACHE_POLICY_MASK: u32 = 3;
pub type PhysAddr = usize;
pub type VirtAddr = usize;
pub type DevVAddr = usize;
pub const PAGE_SIZE: usize = 0x1000;

View File

@ -1,4 +1,3 @@
use crate::timer_now;
use alloc::boxed::Box;
use core::future::Future;
use core::pin::Pin;
@ -44,12 +43,12 @@ impl Future for SleepFuture {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
if timer_now() >= self.deadline {
if crate::timer::timer_now() >= self.deadline {
return Poll::Ready(());
}
if self.deadline.as_nanos() < i64::max_value() as u128 {
let waker = cx.waker().clone();
crate::timer_set(self.deadline, Box::new(move |_| waker.wake()));
crate::timer::timer_set(self.deadline, Box::new(move |_| waker.wake()));
}
Poll::Pending
}
@ -68,11 +67,11 @@ impl Future for SerialFuture {
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
let mut buf = [0u8];
if crate::serial_read(&mut buf) != 0 {
if crate::serial::serial_read(&mut buf) != 0 {
return Poll::Ready(buf[0]);
}
let waker = cx.waker().clone();
crate::serial_set_callback(Box::new({
crate::serial::serial_set_callback(Box::new({
move || {
waker.wake_by_ref();
true

View File

@ -0,0 +1,43 @@
use alloc::vec::Vec;
use crate::{PhysAddr, PAGE_SIZE};
#[repr(C)]
#[derive(Debug)]
pub struct PhysFrame {
paddr: PhysAddr,
}
impl PhysFrame {
pub fn alloc() -> Option<Self> {
crate::memory::frame_alloc().map(|paddr| Self { paddr })
}
pub fn alloc_contiguous_base(size: usize, align_log2: usize) -> Option<PhysAddr> {
crate::memory::frame_alloc_contiguous(size, align_log2)
}
pub fn alloc_contiguous(size: usize, align_log2: usize) -> Vec<Self> {
Self::alloc_contiguous_base(size, align_log2).map_or(Vec::new(), |base| {
(0..size)
.map(|i| PhysFrame {
paddr: base + i * PAGE_SIZE,
})
.collect()
})
}
pub fn addr(&self) -> PhysAddr {
self.paddr
}
pub fn zero_frame_addr() -> PhysAddr {
crate::memory::zero_frame_addr()
}
}
impl Drop for PhysFrame {
fn drop(&mut self) {
crate::memory::frame_dealloc(self.paddr)
}
}

View File

@ -0,0 +1,11 @@
pub(super) mod defs;
pub(super) mod fb;
pub mod context;
pub mod future;
pub mod memory;
pub mod paging;
pub mod user;
pub mod vdso;
pub use defs::*;

View File

@ -0,0 +1,57 @@
use super::{HalResult, MMUFlags, PhysAddr, VirtAddr, PAGE_SIZE};
pub trait PageTableTrait: Sync + Send {
/// Map the page of `vaddr` to the frame of `paddr` with `flags`.
fn map(&mut self, _vaddr: VirtAddr, _paddr: PhysAddr, _flags: MMUFlags) -> HalResult<()>;
/// Unmap the page of `vaddr`.
fn unmap(&mut self, _vaddr: VirtAddr) -> HalResult<()>;
/// Change the `flags` of the page of `vaddr`.
fn protect(&mut self, _vaddr: VirtAddr, _flags: MMUFlags) -> HalResult<()>;
/// Query the physical address which the page of `vaddr` maps to.
fn query(&mut self, _vaddr: VirtAddr) -> HalResult<PhysAddr>;
/// Get the physical address of root page table.
fn table_phys(&self) -> PhysAddr;
#[cfg(target_arch = "riscv64")]
/// Activate this page table
fn activate(&self);
fn map_many(
&mut self,
mut vaddr: VirtAddr,
paddrs: &[PhysAddr],
flags: MMUFlags,
) -> HalResult<()> {
for &paddr in paddrs {
self.map(vaddr, paddr, flags)?;
vaddr += PAGE_SIZE;
}
Ok(())
}
fn map_cont(
&mut self,
mut vaddr: VirtAddr,
paddr: PhysAddr,
pages: usize,
flags: MMUFlags,
) -> HalResult<()> {
for i in 0..pages {
let paddr = paddr + i * PAGE_SIZE;
self.map(vaddr, paddr, flags)?;
vaddr += PAGE_SIZE;
}
Ok(())
}
fn unmap_cont(&mut self, vaddr: VirtAddr, pages: usize) -> HalResult<()> {
for i in 0..pages {
self.unmap(vaddr + i * PAGE_SIZE)?;
}
Ok(())
}
}

View File

@ -1,485 +0,0 @@
use super::*;
use crate::vdso::VdsoConstants;
use acpi::Acpi;
use alloc::boxed::Box;
use alloc::vec::Vec;
use core::future::Future;
use core::ops::FnOnce;
use core::pin::Pin;
use core::time::Duration;
type ThreadId = usize;
/// The error type which is returned from HAL functions.
#[derive(Debug)]
pub struct HalError;
/// The result type returned by HAL functions.
pub type Result<T> = core::result::Result<T, HalError>;
#[repr(C)]
pub struct Thread {
id: ThreadId,
}
impl Thread {
/// Spawn a new thread.
#[linkage = "weak"]
#[export_name = "hal_thread_spawn"]
pub fn spawn(
_future: Pin<Box<dyn Future<Output = ()> + Send + 'static>>,
_vmtoken: usize,
) -> Self {
unimplemented!()
}
/// Set tid and pid of current task.
#[linkage = "weak"]
#[export_name = "hal_thread_set_tid"]
pub fn set_tid(_tid: u64, _pid: u64) {
unimplemented!()
}
/// Get tid and pid of current task.
#[linkage = "weak"]
#[export_name = "hal_thread_get_tid"]
pub fn get_tid() -> (u64, u64) {
unimplemented!()
}
}
#[linkage = "weak"]
#[export_name = "hal_context_run"]
pub fn context_run(_context: &mut UserContext) {
unimplemented!()
}
pub trait PageTableTrait: Sync + Send {
/// Map the page of `vaddr` to the frame of `paddr` with `flags`.
fn map(&mut self, _vaddr: VirtAddr, _paddr: PhysAddr, _flags: MMUFlags) -> Result<()>;
/// Unmap the page of `vaddr`.
fn unmap(&mut self, _vaddr: VirtAddr) -> Result<()>;
/// Change the `flags` of the page of `vaddr`.
fn protect(&mut self, _vaddr: VirtAddr, _flags: MMUFlags) -> Result<()>;
/// Query the physical address which the page of `vaddr` maps to.
fn query(&mut self, _vaddr: VirtAddr) -> Result<PhysAddr>;
/// Get the physical address of root page table.
fn table_phys(&self) -> PhysAddr;
#[cfg(target_arch = "riscv64")]
/// Activate this page table
fn activate(&self);
fn map_many(
&mut self,
mut vaddr: VirtAddr,
paddrs: &[PhysAddr],
flags: MMUFlags,
) -> Result<()> {
for &paddr in paddrs {
self.map(vaddr, paddr, flags)?;
vaddr += PAGE_SIZE;
}
Ok(())
}
fn map_cont(
&mut self,
mut vaddr: VirtAddr,
paddr: PhysAddr,
pages: usize,
flags: MMUFlags,
) -> Result<()> {
for i in 0..pages {
let paddr = paddr + i * PAGE_SIZE;
self.map(vaddr, paddr, flags)?;
vaddr += PAGE_SIZE;
}
Ok(())
}
fn unmap_cont(&mut self, vaddr: VirtAddr, pages: usize) -> Result<()> {
for i in 0..pages {
self.unmap(vaddr + i * PAGE_SIZE)?;
}
Ok(())
}
}
/// Page Table
#[repr(C)]
pub struct PageTable {
table_phys: PhysAddr,
}
impl PageTable {
/// Get current page table
#[linkage = "weak"]
#[export_name = "hal_pt_current"]
pub fn current() -> Self {
unimplemented!()
}
/// Create a new `PageTable`.
#[allow(clippy::new_without_default)]
#[linkage = "weak"]
#[export_name = "hal_pt_new"]
pub fn new() -> Self {
unimplemented!()
}
}
impl PageTableTrait for PageTable {
/// Map the page of `vaddr` to the frame of `paddr` with `flags`.
#[linkage = "weak"]
#[export_name = "hal_pt_map"]
fn map(&mut self, _vaddr: VirtAddr, _paddr: PhysAddr, _flags: MMUFlags) -> Result<()> {
unimplemented!()
}
/// Unmap the page of `vaddr`.
#[linkage = "weak"]
#[export_name = "hal_pt_unmap"]
fn unmap(&mut self, _vaddr: VirtAddr) -> Result<()> {
unimplemented!()
}
/// Change the `flags` of the page of `vaddr`.
#[linkage = "weak"]
#[export_name = "hal_pt_protect"]
fn protect(&mut self, _vaddr: VirtAddr, _flags: MMUFlags) -> Result<()> {
unimplemented!()
}
/// Query the physical address which the page of `vaddr` maps to.
#[linkage = "weak"]
#[export_name = "hal_pt_query"]
fn query(&mut self, _vaddr: VirtAddr) -> Result<PhysAddr> {
unimplemented!()
}
/// Get the physical address of root page table.
#[linkage = "weak"]
#[export_name = "hal_pt_table_phys"]
fn table_phys(&self) -> PhysAddr {
self.table_phys
}
/// Activate this page table
#[cfg(target_arch = "riscv64")]
#[linkage = "weak"]
#[export_name = "hal_pt_activate"]
fn activate(&self) {
unimplemented!()
}
#[linkage = "weak"]
#[export_name = "hal_pt_unmap_cont"]
fn unmap_cont(&mut self, vaddr: VirtAddr, pages: usize) -> Result<()> {
for i in 0..pages {
self.unmap(vaddr + i * PAGE_SIZE)?;
}
Ok(())
}
}
#[repr(C)]
pub struct PhysFrame {
paddr: PhysAddr,
}
impl PhysFrame {
#[linkage = "weak"]
#[export_name = "hal_frame_alloc"]
pub fn alloc() -> Option<Self> {
unimplemented!()
}
#[linkage = "weak"]
#[export_name = "hal_frame_alloc_contiguous"]
pub fn alloc_contiguous_base(_size: usize, _align_log2: usize) -> Option<PhysAddr> {
unimplemented!()
}
pub fn alloc_contiguous(size: usize, align_log2: usize) -> Vec<Self> {
PhysFrame::alloc_contiguous_base(size, align_log2).map_or(Vec::new(), |base| {
(0..size)
.map(|i| PhysFrame {
paddr: base + i * PAGE_SIZE,
})
.collect()
})
}
pub fn addr(&self) -> PhysAddr {
self.paddr
}
#[linkage = "weak"]
#[export_name = "hal_zero_frame_paddr"]
pub fn zero_frame_addr() -> PhysAddr {
unimplemented!()
}
}
impl Drop for PhysFrame {
#[linkage = "weak"]
#[export_name = "hal_frame_dealloc"]
fn drop(&mut self) {
unimplemented!()
}
}
/// Read physical memory from `paddr` to `buf`.
#[linkage = "weak"]
#[export_name = "hal_pmem_read"]
pub fn pmem_read(_paddr: PhysAddr, _buf: &mut [u8]) {
unimplemented!()
}
/// Write physical memory to `paddr` from `buf`.
#[linkage = "weak"]
#[export_name = "hal_pmem_write"]
pub fn pmem_write(_paddr: PhysAddr, _buf: &[u8]) {
unimplemented!()
}
/// Zero physical memory at `[paddr, paddr + len)`
#[linkage = "weak"]
#[export_name = "hal_pmem_zero"]
pub fn pmem_zero(_paddr: PhysAddr, _len: usize) {
unimplemented!()
}
/// Copy content of `src` frame to `target` frame.
#[linkage = "weak"]
#[export_name = "hal_frame_copy"]
pub fn frame_copy(_src: PhysAddr, _target: PhysAddr) {
unimplemented!()
}
/// Flush the physical frame.
#[linkage = "weak"]
#[export_name = "hal_frame_flush"]
pub fn frame_flush(_target: PhysAddr) {
unimplemented!()
}
/// Register a callback of serial readable event.
#[linkage = "weak"]
#[export_name = "hal_serial_set_callback"]
pub fn serial_set_callback(_callback: Box<dyn Fn() -> bool + Send + Sync>) {
unimplemented!()
}
/// Read a string from console.
#[linkage = "weak"]
#[export_name = "hal_serial_read"]
pub fn serial_read(_buf: &mut [u8]) -> usize {
unimplemented!()
}
/// Output a string to console.
#[linkage = "weak"]
#[export_name = "hal_serial_write"]
pub fn serial_write(_s: &str) {
unimplemented!()
}
/// Get current time.
#[linkage = "weak"]
#[export_name = "hal_timer_now"]
pub fn timer_now() -> Duration {
unimplemented!()
}
/// Set a new timer. After `deadline`, the `callback` will be called.
#[linkage = "weak"]
#[export_name = "hal_timer_set"]
pub fn timer_set(_deadline: Duration, _callback: Box<dyn FnOnce(Duration) + Send + Sync>) {
unimplemented!()
}
#[linkage = "weak"]
#[export_name = "hal_timer_set_next"]
pub fn timer_set_next() {
unimplemented!()
}
/// Check timers, call when timer interrupt happened.
#[linkage = "weak"]
#[export_name = "hal_timer_tick"]
pub fn timer_tick() {
unimplemented!()
}
pub struct InterruptManager {}
impl InterruptManager {
/// Enable IRQ.
#[linkage = "weak"]
#[export_name = "hal_irq_enable"]
pub fn enable_irq(_vector: u32) {
unimplemented!()
}
/// Disable IRQ.
#[linkage = "weak"]
#[export_name = "hal_irq_disable"]
pub fn disable_irq(_vector: u32) {
unimplemented!()
}
/// Is a valid IRQ number.
#[linkage = "weak"]
#[export_name = "hal_irq_isvalid"]
pub fn is_valid_irq(_vector: u32) -> bool {
unimplemented!()
}
/// Configure the specified interrupt vector. If it is invoked, it muust be
/// invoked prior to interrupt registration.
#[linkage = "weak"]
#[export_name = "hal_irq_configure"]
pub fn configure_irq(_vector: u32, _trig_mode: bool, _polarity: bool) -> bool {
unimplemented!()
}
/// Add an interrupt handle to an IRQ
#[linkage = "weak"]
#[export_name = "hal_irq_register_handler"]
pub fn register_irq_handler(_vector: u32, _handle: Box<dyn Fn() + Send + Sync>) -> Option<u32> {
unimplemented!()
}
/// Remove the interrupt handle to an IRQ
#[linkage = "weak"]
#[export_name = "hal_irq_unregister_handler"]
pub fn unregister_irq_handler(_vector: u32) -> bool {
unimplemented!()
}
/// Handle IRQ.
#[linkage = "weak"]
#[export_name = "hal_irq_handle"]
pub fn handle_irq(_vector: u32) {
unimplemented!()
}
/// Method used for platform allocation of blocks of MSI and MSI-X compatible
/// IRQ targets.
#[linkage = "weak"]
#[export_name = "hal_msi_allocate_block"]
pub fn msi_allocate_block(_irq_num: u32) -> Option<(usize, usize)> {
unimplemented!()
}
/// Method used to free a block of MSI IRQs previously allocated by msi_alloc_block().
/// This does not unregister IRQ handlers.
#[linkage = "weak"]
#[export_name = "hal_msi_free_block"]
pub fn msi_free_block(_irq_start: u32, _irq_num: u32) {
unimplemented!()
}
/// Register a handler function for a given msi_id within an msi_block_t. Passing a
/// NULL handler will effectively unregister a handler for a given msi_id within the
/// block.
#[linkage = "weak"]
#[export_name = "hal_msi_register_handler"]
pub fn msi_register_handler(
_irq_start: u32,
_irq_num: u32,
_msi_id: u32,
_handle: Box<dyn Fn() + Send + Sync>,
) {
unimplemented!()
}
}
/// Get platform specific information.
#[linkage = "weak"]
#[export_name = "hal_vdso_constants"]
pub fn vdso_constants() -> VdsoConstants {
unimplemented!()
}
/// Get fault address of the last page fault.
#[linkage = "weak"]
#[export_name = "fetch_fault_vaddr"]
pub fn fetch_fault_vaddr() -> VirtAddr {
unimplemented!()
}
#[linkage = "weak"]
#[export_name = "fetch_trap_num"]
pub fn fetch_trap_num(_context: &UserContext) -> usize {
unimplemented!()
}
/// Get physical address of `acpi_rsdp` and `smbios` on x86_64.
#[linkage = "weak"]
#[export_name = "hal_pc_firmware_tables"]
pub fn pc_firmware_tables() -> (u64, u64) {
unimplemented!()
}
/// Get ACPI Table
#[linkage = "weak"]
#[export_name = "hal_acpi_table"]
pub fn get_acpi_table() -> Option<Acpi> {
unimplemented!()
}
/// IO Ports access on x86 platform
#[linkage = "weak"]
#[export_name = "hal_outpd"]
pub fn outpd(_port: u16, _value: u32) {
unimplemented!()
}
#[linkage = "weak"]
#[export_name = "hal_inpd"]
pub fn inpd(_port: u16) -> u32 {
unimplemented!()
}
/// Get local APIC ID
#[linkage = "weak"]
#[export_name = "hal_apic_local_id"]
pub fn apic_local_id() -> u8 {
unimplemented!()
}
/// Fill random bytes to the buffer
#[cfg(target_arch = "x86_64")]
pub fn fill_random(buf: &mut [u8]) {
// TODO: optimize
for x in buf.iter_mut() {
let mut r = 0;
unsafe {
core::arch::x86_64::_rdrand16_step(&mut r);
}
*x = r as _;
}
}
#[cfg(target_arch = "aarch64")]
pub fn fill_random(_buf: &mut [u8]) {
// TODO
}
#[cfg(target_arch = "riscv64")]
pub fn fill_random(_buf: &mut [u8]) {
// TODO
}
#[linkage = "weak"]
#[export_name = "hal_current_pgtable"]
pub fn current_page_table() -> usize {
unimplemented!()
}
#[linkage = "weak"]
#[export_name = "hal_mice_set_callback"]
pub fn mice_set_callback(_callback: Box<dyn Fn([u8; 3]) + Send + Sync>) {
unimplemented!()
}
#[linkage = "weak"]
#[export_name = "hal_kbd_set_callback"]
pub fn kbd_set_callback(_callback: Box<dyn Fn(u16, i32) + Send + Sync>) {
unimplemented!()
}

View File

@ -1,55 +1,23 @@
//! Hardware Abstraction Layer
#![no_std]
#![feature(linkage)]
#![cfg_attr(not(feature = "libos"), no_std)]
#![feature(asm)]
#![deny(warnings)]
extern crate alloc;
pub mod defs {
use bitflags::bitflags;
use numeric_enum_macro::numeric_enum;
mod common;
bitflags! {
pub struct MMUFlags: usize {
#[allow(clippy::identity_op)]
const CACHE_1 = 1 << 0;
const CACHE_2 = 1 << 1;
const READ = 1 << 2;
const WRITE = 1 << 3;
const EXECUTE = 1 << 4;
const USER = 1 << 5;
const RXW = Self::READ.bits | Self::WRITE.bits | Self::EXECUTE.bits;
}
}
numeric_enum! {
#[repr(u32)]
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum CachePolicy {
Cached = 0,
Uncached = 1,
UncachedDevice = 2,
WriteCombining = 3,
}
}
pub const CACHE_POLICY_MASK: u32 = 3;
pub use common::{defs::*, future, user};
pub type PhysAddr = usize;
pub type VirtAddr = usize;
pub type DevVAddr = usize;
pub const PAGE_SIZE: usize = 0x1000;
cfg_if::cfg_if! {
if #[cfg(feature = "libos")] {
#[macro_use]
extern crate log;
mod libos;
pub use self::libos::*;
} else {
mod unimp;
pub use self::unimp::*;
}
}
mod context;
mod dummy;
mod fb;
mod future;
pub mod user;
pub mod vdso;
pub use self::context::*;
pub use self::defs::*;
pub use self::dummy::*;
pub use self::fb::*;
pub use self::future::*;
pub use trapframe::{GeneralRegs, UserContext};

View File

@ -0,0 +1,17 @@
pub use crate::common::context::*;
pub use trapframe::syscall_fn_entry as syscall_entry;
pub fn context_run(context: &mut UserContext) {
context.run_fncall();
}
/// Get fault address of the last page fault.
pub fn fetch_fault_vaddr() -> crate::VirtAddr {
unimplemented!()
}
/// Get the trap number when trap.
pub fn fetch_trap_num(_context: &UserContext) -> usize {
unimplemented!()
}

View File

@ -0,0 +1,3 @@
pub fn u8() -> u8 {
0
}

View File

@ -0,0 +1,132 @@
pub use crate::common::fb::*;
#[repr(C)]
#[derive(Debug, Default)]
struct FbFixScreeninfo {
id: [u8; 16],
smem_start: u64,
smem_len: u32,
type_: u32,
type_aux: u32,
visual: u32,
xpanstep: u16,
ypanstep: u16,
ywrapstep: u16,
line_length: u32,
mmio_start: u64,
mmio_len: u32,
accel: u32,
capabilities: u16,
reserved: [u16; 2],
}
impl FbFixScreeninfo {
pub fn size(&self) -> u32 {
self.smem_len
}
}
#[repr(C)]
#[derive(Debug, Default)]
struct FbVarScreeninfo {
xres: u32,
yres: u32,
xres_virtual: u32,
yres_virtual: u32,
xoffset: u32,
yoffset: u32,
bits_per_pixel: u32,
grayscale: u32,
red: FbBitfield,
green: FbBitfield,
blue: FbBitfield,
transp: FbBitfield,
nonstd: u32,
activate: u32,
height: u32,
width: u32,
accel_flags: u32,
pixclock: u32,
left_margin: u32,
right_margin: u32,
upper_margin: u32,
lower_margin: u32,
hsync_len: u32,
vsync_len: u32,
sync: u32,
vmode: u32,
rotate: u32,
colorspace: u32,
reserved: [u32; 4],
}
impl FbVarScreeninfo {
pub fn resolution(&self) -> (u32, u32) {
(self.xres, self.yres)
}
}
#[repr(C)]
#[derive(Debug, Default)]
struct FbBitfield {
offset: u32,
length: u32,
msb_right: u32,
}
pub fn init() {
const FBIOGET_VSCREENINFO: u64 = 0x4600;
const FBIOGET_FSCREENINFO: u64 = 0x4602;
#[cfg(target_arch = "aarch64")]
let fbfd = unsafe { libc::open("/dev/fb0".as_ptr(), libc::O_RDWR) };
#[cfg(not(target_arch = "aarch64"))]
let fbfd = unsafe { libc::open("/dev/fb0".as_ptr() as *const i8, libc::O_RDWR) };
if fbfd < 0 {
return;
}
let mut vinfo = FbVarScreeninfo::default();
if unsafe { libc::ioctl(fbfd, FBIOGET_VSCREENINFO, &mut vinfo) } < 0 {
return;
}
let mut finfo = FbFixScreeninfo::default();
if unsafe { libc::ioctl(fbfd, FBIOGET_FSCREENINFO, &mut finfo) } < 0 {
return;
}
let size = finfo.size() as usize;
let addr = unsafe {
libc::mmap(
std::ptr::null_mut::<libc::c_void>(),
size,
libc::PROT_READ | libc::PROT_WRITE,
libc::MAP_SHARED,
fbfd,
0,
)
};
if (addr as isize) < 0 {
return;
}
let (width, height) = vinfo.resolution();
let addr = addr as usize;
let fb_info = FramebufferInfo {
xres: width,
yres: height,
xres_virtual: width,
yres_virtual: height,
xoffset: 0,
yoffset: 0,
depth: ColorDepth::ColorDepth32,
format: ColorFormat::RGBA8888,
// paddr: virt_to_phys(addr),
paddr: addr,
vaddr: addr,
screen_size: size,
};
*FRAME_BUFFER.write() = Some(fb_info);
}

View File

@ -0,0 +1,96 @@
use lazy_static::lazy_static;
use std::os::unix::io::AsRawFd;
use std::sync::Mutex;
type MouseCallbackFn = dyn Fn([u8; 3]) + Send + Sync;
type KBDCallbackFn = dyn Fn(u16, i32) + Send + Sync;
lazy_static! {
static ref MOUSE_CALLBACK: Mutex<Vec<Box<MouseCallbackFn>>> = Mutex::new(Vec::new());
static ref KBD_CALLBACK: Mutex<Vec<Box<KBDCallbackFn>>> = Mutex::new(Vec::new());
}
fn init_kbd() {
let fd = std::fs::File::open("/dev/input/event1").expect("Failed to open input event device.");
// ??
/* let inputfd = unsafe {
libc::open(
"/dev/input/event1".as_ptr() as *const i8,
libc::O_RDONLY /* | libc::O_NONBLOCK */,
)
}; */
if fd.as_raw_fd() < 0 {
return;
}
#[repr(C)]
#[derive(Debug, Copy, Clone, Default)]
pub struct TimeVal {
pub sec: usize,
pub usec: usize,
}
#[repr(C)]
#[derive(Debug, Copy, Clone, Default)]
struct InputEvent {
time: TimeVal,
type_: u16,
code: u16,
value: i32,
}
std::thread::spawn(move || {
use core::mem::{size_of, transmute, transmute_copy};
let ev = InputEvent::default();
const LEN: usize = size_of::<InputEvent>();
let mut buf: [u8; LEN] = unsafe { transmute(ev) };
loop {
std::thread::sleep(std::time::Duration::from_millis(8));
let ret =
unsafe { libc::read(fd.as_raw_fd(), buf.as_mut_ptr() as *mut libc::c_void, LEN) };
if ret < 0 {
break;
}
let ev: InputEvent = unsafe { transmute_copy(&buf) };
if ev.type_ == 1 {
KBD_CALLBACK.lock().unwrap().iter().for_each(|callback| {
callback(ev.code, ev.value);
});
}
}
});
}
fn init_mice() {
let fd = std::fs::File::open("/dev/input/mice").expect("Failed to open input event device.");
if fd.as_raw_fd() < 0 {
return;
}
std::thread::spawn(move || {
let mut buf = [0u8; 3];
loop {
std::thread::sleep(std::time::Duration::from_millis(8));
let ret =
unsafe { libc::read(fd.as_raw_fd(), buf.as_mut_ptr() as *mut libc::c_void, 3) };
if ret < 0 {
break;
}
MOUSE_CALLBACK.lock().unwrap().iter().for_each(|callback| {
callback(buf);
});
}
});
}
pub fn mice_set_callback(callback: Box<dyn Fn([u8; 3]) + Send + Sync>) {
MOUSE_CALLBACK.lock().unwrap().push(callback);
}
pub fn kbd_set_callback(callback: Box<dyn Fn(u16, i32) + Send + Sync>) {
KBD_CALLBACK.lock().unwrap().push(callback);
}
pub fn init() {
init_kbd();
init_mice();
}

View File

@ -0,0 +1,2 @@
pub mod fb;
pub mod input;

View File

@ -0,0 +1,77 @@
use alloc::collections::VecDeque;
use lazy_static::lazy_static;
use std::fs::{File, OpenOptions};
use std::io::Error;
use std::os::unix::io::AsRawFd;
use std::sync::Mutex;
use crate::{PhysAddr, VirtAddr, PAGE_SIZE};
/// Map physical memory from here.
pub(super) const PMEM_SIZE: usize = 0x4000_0000; // 1GiB
lazy_static! {
pub(super) static ref FRAME_FILE: File = create_pmem_file();
pub(super) static ref AVAILABLE_FRAMES: Mutex<VecDeque<usize>> =
Mutex::new((PAGE_SIZE..PMEM_SIZE).step_by(PAGE_SIZE).collect());
}
pub(super) fn phys_to_virt(paddr: PhysAddr) -> VirtAddr {
/// Map physical memory from here.
const PMEM_BASE: VirtAddr = 0x8_0000_0000;
PMEM_BASE + paddr
}
/// Ensure physical memory are mmapped and accessible.
pub(super) fn ensure_mmap_pmem() {
FRAME_FILE.as_raw_fd();
}
pub(super) fn create_pmem_file() -> File {
let dir = tempfile::tempdir().expect("failed to create pmem dir");
let path = dir.path().join("pmem");
// workaround on macOS to avoid permission denied.
// see https://jiege.ch/software/2020/02/07/macos-mmap-exec/ for analysis on this problem.
#[cfg(target_os = "macos")]
std::mem::forget(dir);
let file = OpenOptions::new()
.read(true)
.write(true)
.create(true)
.open(&path)
.expect("failed to create pmem file");
file.set_len(PMEM_SIZE as u64)
.expect("failed to resize file");
trace!("create pmem file: path={:?}, size={:#x}", path, PMEM_SIZE);
let prot = libc::PROT_READ | libc::PROT_WRITE;
mmap(file.as_raw_fd(), 0, PMEM_SIZE, phys_to_virt(0), prot);
file
}
/// Mmap frame file `fd` to `vaddr`.
pub(super) fn mmap(fd: libc::c_int, offset: usize, len: usize, vaddr: VirtAddr, prot: libc::c_int) {
// workaround on macOS to write text section.
#[cfg(target_os = "macos")]
let prot = if prot & libc::PROT_EXEC != 0 {
prot | libc::PROT_WRITE
} else {
prot
};
let ret = unsafe {
let flags = libc::MAP_SHARED | libc::MAP_FIXED;
libc::mmap(vaddr as _, len, prot, flags, fd, offset as _)
} as usize;
trace!(
"mmap file: fd={}, offset={:#x}, len={:#x}, vaddr={:#x}, prot={:#b}",
fd,
offset,
len,
vaddr,
prot,
);
assert_eq!(ret, vaddr, "failed to mmap: {:?}", Error::last_os_error());
}

View File

@ -0,0 +1,69 @@
use super::mem_common::{ensure_mmap_pmem, phys_to_virt, AVAILABLE_FRAMES, PMEM_SIZE};
use crate::{PhysAddr, PAGE_SIZE};
pub use crate::common::memory::*;
/// Read physical memory from `paddr` to `buf`.
pub fn pmem_read(paddr: PhysAddr, buf: &mut [u8]) {
trace!("pmem read: paddr={:#x}, len={:#x}", paddr, buf.len());
assert!(paddr + buf.len() <= PMEM_SIZE);
ensure_mmap_pmem();
unsafe {
(phys_to_virt(paddr) as *const u8).copy_to_nonoverlapping(buf.as_mut_ptr(), buf.len());
}
}
/// Write physical memory to `paddr` from `buf`.
pub fn pmem_write(paddr: PhysAddr, buf: &[u8]) {
trace!("pmem write: paddr={:#x}, len={:#x}", paddr, buf.len());
assert!(paddr + buf.len() <= PMEM_SIZE);
ensure_mmap_pmem();
unsafe {
buf.as_ptr()
.copy_to_nonoverlapping(phys_to_virt(paddr) as _, buf.len());
}
}
/// Zero physical memory at `[paddr, paddr + len)`
pub fn pmem_zero(paddr: PhysAddr, len: usize) {
trace!("pmem_zero: addr={:#x}, len={:#x}", paddr, len);
assert!(paddr + len <= PMEM_SIZE);
ensure_mmap_pmem();
unsafe {
core::ptr::write_bytes(phys_to_virt(paddr) as *mut u8, 0, len);
}
}
/// Copy content of `src` frame to `target` frame
pub fn frame_copy(src: PhysAddr, target: PhysAddr) {
trace!("frame_copy: {:#x} <- {:#x}", target, src);
assert!(src + PAGE_SIZE <= PMEM_SIZE && target + PAGE_SIZE <= PMEM_SIZE);
ensure_mmap_pmem();
unsafe {
let buf = phys_to_virt(src) as *const u8;
buf.copy_to_nonoverlapping(phys_to_virt(target) as _, PAGE_SIZE);
}
}
pub fn frame_flush(_target: PhysAddr) {
// do nothing
}
pub fn frame_alloc() -> Option<PhysAddr> {
let ret = AVAILABLE_FRAMES.lock().unwrap().pop_front();
trace!("frame alloc: {:?}", ret);
ret
}
pub fn frame_alloc_contiguous(_size: usize, _align_log2: usize) -> Option<PhysAddr> {
unimplemented!()
}
pub fn frame_dealloc(paddr: PhysAddr) {
trace!("frame dealloc: {:?}", paddr);
AVAILABLE_FRAMES.lock().unwrap().push_back(paddr);
}
pub fn zero_frame_addr() -> PhysAddr {
0
}

View File

@ -0,0 +1,50 @@
mod mem_common;
pub mod context;
pub mod cpu;
pub mod memory;
pub mod paging;
pub mod serial;
pub mod thread;
pub mod timer;
pub mod vdso;
#[path = "../unimp/interrupt.rs"]
pub mod interrupt;
#[path = "../unimp/rand.rs"]
pub mod rand;
cfg_if::cfg_if! {
if #[cfg(target_os = "linux")] {
pub mod dev;
} else {
#[path = "../unimp/dev/mod.rs"]
pub mod dev;
}
}
#[cfg(target_os = "macos")]
include!("macos.rs");
/// Initialize the HAL.
///
/// This function must be called at the beginning.
pub fn init() {
#[cfg(target_os = "macos")]
unsafe {
register_sigsegv_handler();
}
// spawn a thread to read stdin
// TODO: raw mode
use std::io::Read;
std::thread::spawn(|| {
for i in std::io::stdin().bytes() {
serial::serial_put(i.unwrap());
}
});
}
// FIXME
#[path = "../unimp/misc.rs"]
mod misc;
pub use misc::*;

View File

@ -0,0 +1,115 @@
use std::io::Error;
use std::os::unix::io::AsRawFd;
use super::mem_common::{mmap, FRAME_FILE};
use crate::{HalResult, MMUFlags, PhysAddr, VirtAddr, PAGE_SIZE};
pub use crate::common::paging::*;
pub struct PageTable;
impl PageTable {
#[allow(clippy::new_without_default)]
pub fn new() -> Self {
PageTable
}
pub fn current() -> Self {
PageTable
}
}
impl PageTableTrait for PageTable {
/// Map the page of `vaddr` to the frame of `paddr` with `flags`.
fn map(&mut self, vaddr: VirtAddr, paddr: PhysAddr, flags: MMUFlags) -> HalResult<()> {
debug_assert!(page_aligned(vaddr));
debug_assert!(page_aligned(paddr));
let prot = flags.to_mmap_prot();
mmap(FRAME_FILE.as_raw_fd(), paddr, PAGE_SIZE, vaddr, prot);
Ok(())
}
/// Unmap the page of `vaddr`.
fn unmap(&mut self, vaddr: VirtAddr) -> HalResult<()> {
self.unmap_cont(vaddr, 1)
}
/// Change the `flags` of the page of `vaddr`.
fn protect(&mut self, vaddr: VirtAddr, flags: MMUFlags) -> HalResult<()> {
debug_assert!(page_aligned(vaddr));
let prot = flags.to_mmap_prot();
let ret = unsafe { libc::mprotect(vaddr as _, PAGE_SIZE, prot) };
assert_eq!(ret, 0, "failed to mprotect: {:?}", Error::last_os_error());
Ok(())
}
/// Query the physical address which the page of `vaddr` maps to.
fn query(&mut self, vaddr: VirtAddr) -> HalResult<PhysAddr> {
debug_assert!(page_aligned(vaddr));
unimplemented!()
}
/// Get the physical address of root page table.
fn table_phys(&self) -> PhysAddr {
0
}
fn unmap_cont(&mut self, vaddr: VirtAddr, pages: usize) -> HalResult<()> {
if pages == 0 {
return Ok(());
}
debug_assert!(page_aligned(vaddr));
let ret = unsafe { libc::munmap(vaddr as _, PAGE_SIZE * pages) };
assert_eq!(ret, 0, "failed to munmap: {:?}", Error::last_os_error());
Ok(())
}
}
fn page_aligned(x: VirtAddr) -> bool {
x % PAGE_SIZE == 0
}
trait FlagsExt {
fn to_mmap_prot(&self) -> libc::c_int;
}
impl FlagsExt for MMUFlags {
fn to_mmap_prot(&self) -> libc::c_int {
let mut flags = 0;
if self.contains(MMUFlags::READ) {
flags |= libc::PROT_READ;
}
if self.contains(MMUFlags::WRITE) {
flags |= libc::PROT_WRITE;
}
if self.contains(MMUFlags::EXECUTE) {
flags |= libc::PROT_EXEC;
}
flags
}
}
#[cfg(test)]
mod tests {
use super::*;
/// A valid virtual address base to mmap.
const VBASE: VirtAddr = 0x2_00000000;
#[test]
fn map_unmap() {
let mut pt = PageTable::new();
let flags = MMUFlags::READ | MMUFlags::WRITE;
// map 2 pages to 1 frame
pt.map(VBASE, 0x1000, flags).unwrap();
pt.map(VBASE + 0x1000, 0x1000, flags).unwrap();
unsafe {
const MAGIC: usize = 0xdead_beaf;
(VBASE as *mut usize).write(MAGIC);
assert_eq!(((VBASE + 0x1000) as *mut usize).read(), MAGIC);
}
pt.unmap(VBASE + 0x1000).unwrap();
}
}

View File

@ -0,0 +1,33 @@
use lazy_static::lazy_static;
use std::collections::VecDeque;
use std::sync::Mutex;
lazy_static! {
static ref STDIN: Mutex<VecDeque<u8>> = Mutex::new(VecDeque::new());
static ref STDIN_CALLBACK: Mutex<Vec<Box<dyn Fn() -> bool + Send + Sync>>> =
Mutex::new(Vec::new());
}
/// Put a char by serial interrupt handler.
pub fn serial_put(x: u8) {
STDIN.lock().unwrap().push_back(x);
STDIN_CALLBACK.lock().unwrap().retain(|f| !f());
}
pub fn serial_set_callback(callback: Box<dyn Fn() -> bool + Send + Sync>) {
STDIN_CALLBACK.lock().unwrap().push(callback);
}
pub fn serial_read(buf: &mut [u8]) -> usize {
let mut stdin = STDIN.lock().unwrap();
let len = stdin.len().min(buf.len());
for c in &mut buf[..len] {
*c = stdin.pop_front().unwrap();
}
len
}
/// Output a char to console.
pub fn serial_write(s: &str) {
eprint!("{}", s);
}

View File

@ -0,0 +1,20 @@
use async_std::task_local;
use core::{cell::Cell, future::Future, pin::Pin};
task_local! {
static TID: Cell<u64> = Cell::new(0);
static PID: Cell<u64> = Cell::new(0);
}
pub fn spawn(future: Pin<Box<dyn Future<Output = ()> + Send + 'static>>, _vmtoken: usize) {
async_std::task::spawn(future);
}
pub fn set_tid(tid: u64, pid: u64) {
TID.with(|x| x.set(tid));
PID.with(|x| x.set(pid));
}
pub fn get_tid() -> (u64, u64) {
(TID.with(|x| x.get()), PID.with(|x| x.get()))
}

View File

@ -0,0 +1,21 @@
use std::time::{Duration, SystemTime};
/// Get current time.
pub fn timer_now() -> Duration {
SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
}
/// Set a new timer.
///
/// After `deadline`, the `callback` will be called.
pub fn timer_set(deadline: Duration, callback: Box<dyn FnOnce(Duration) + Send + Sync>) {
std::thread::spawn(move || {
let now = timer_now();
if deadline > now {
std::thread::sleep(deadline - now);
}
callback(timer_now());
});
}

View File

@ -0,0 +1,30 @@
use git_version::git_version;
use super::mem_common::PMEM_SIZE;
pub use crate::common::vdso::*;
pub fn vdso_constants() -> VdsoConstants {
let tsc_frequency = 3000u16;
let mut constants = VdsoConstants {
max_num_cpus: 1,
features: Features {
cpu: 0,
hw_breakpoint_count: 0,
hw_watchpoint_count: 0,
},
dcache_line_size: 0,
icache_line_size: 0,
ticks_per_second: tsc_frequency as u64 * 1_000_000,
ticks_to_mono_numerator: 1000,
ticks_to_mono_denominator: tsc_frequency as u32,
physmem: PMEM_SIZE as u64,
version_string_len: 0,
version_string: Default::default(),
};
constants.set_version_string(git_version!(
prefix = "git-",
args = ["--always", "--abbrev=40", "--dirty=-dirty"]
));
constants
}

View File

@ -0,0 +1,15 @@
pub use crate::common::context::*;
pub fn context_run(_context: &mut UserContext) {
unimplemented!()
}
/// Get fault address of the last page fault.
pub fn fetch_fault_vaddr() -> crate::VirtAddr {
unimplemented!()
}
/// Get the trap number when trap.
pub fn fetch_trap_num(_context: &UserContext) -> usize {
unimplemented!()
}

View File

@ -0,0 +1,3 @@
pub fn cpu_id() -> u8 {
0
}

View File

@ -0,0 +1,5 @@
pub use crate::common::fb::*;
pub fn init() {
unimplemented!()
}

View File

@ -0,0 +1,13 @@
use alloc::boxed::Box;
pub fn kbd_set_callback(_callback: Box<dyn Fn(u16, i32) + Send + Sync>) {
unimplemented!()
}
pub fn mice_set_callback(_callback: Box<dyn Fn([u8; 3]) + Send + Sync>) {
unimplemented!()
}
pub fn init() {
unimplemented!()
}

View File

@ -0,0 +1,2 @@
pub mod fb;
pub mod input;

View File

@ -0,0 +1,61 @@
use alloc::boxed::Box;
/// Enable IRQ.
pub fn enable_irq(_vector: u32) {
unimplemented!()
}
/// Disable IRQ.
pub fn disable_irq(_vector: u32) {
unimplemented!()
}
/// Is a valid IRQ number.
pub fn is_valid_irq(_vector: u32) -> bool {
unimplemented!()
}
/// Configure the specified interrupt vector. If it is invoked, it muust be
/// invoked prior to interrupt registration.
pub fn configure_irq(_vector: u32, _trig_mode: bool, _polarity: bool) -> bool {
unimplemented!()
}
/// Add an interrupt handle to an IRQ
pub fn register_irq_handler(_vector: u32, _handle: Box<dyn Fn() + Send + Sync>) -> Option<u32> {
unimplemented!()
}
/// Remove the interrupt handle to an IRQ
pub fn unregister_irq_handler(_vector: u32) -> bool {
unimplemented!()
}
/// Handle IRQ.
pub fn handle_irq(_vector: u32) {
unimplemented!()
}
/// Method used for platform allocation of blocks of MSI and MSI-X compatible
/// IRQ targets.
pub fn msi_allocate_block(_irq_num: u32) -> Option<(usize, usize)> {
unimplemented!()
}
/// Method used to free a block of MSI IRQs previously allocated by msi_alloc_block().
/// This does not unregister IRQ handlers.
pub fn msi_free_block(_irq_start: u32, _irq_num: u32) {
unimplemented!()
}
/// Register a handler function for a given msi_id within an msi_block_t. Passing a
/// NULL handler will effectively unregister a handler for a given msi_id within the
/// block.
pub fn msi_register_handler(
_irq_start: u32,
_irq_num: u32,
_msi_id: u32,
_handle: Box<dyn Fn() + Send + Sync>,
) {
unimplemented!()
}

View File

@ -0,0 +1,44 @@
use crate::PhysAddr;
pub use crate::common::memory::*;
/// Read physical memory from `paddr` to `buf`.
pub fn pmem_read(_paddr: PhysAddr, _buf: &mut [u8]) {
unimplemented!()
}
/// Write physical memory to `paddr` from `buf`.
pub fn pmem_write(_paddr: PhysAddr, _buf: &[u8]) {
unimplemented!()
}
/// Zero physical memory at `[paddr, paddr + len)`.
pub fn pmem_zero(_paddr: PhysAddr, _len: usize) {
unimplemented!()
}
/// Copy content of `src` frame to `target` frame.
pub fn frame_copy(_src: PhysAddr, _target: PhysAddr) {
unimplemented!()
}
/// Flush the physical frame.
pub fn frame_flush(_target: PhysAddr) {
unimplemented!()
}
pub fn frame_alloc() -> Option<PhysAddr> {
unimplemented!()
}
pub fn frame_alloc_contiguous(_size: usize, _align_log2: usize) -> Option<PhysAddr> {
unimplemented!()
}
pub fn frame_dealloc(_paddr: PhysAddr) {
unimplemented!()
}
pub fn zero_frame_addr() -> PhysAddr {
unimplemented!()
}

View File

@ -0,0 +1,35 @@
use crate::{context::UserContext, VirtAddr};
use acpi::Acpi;
/// Get fault address of the last page fault.
pub fn fetch_fault_vaddr() -> VirtAddr {
unimplemented!()
}
pub fn fetch_trap_num(_context: &UserContext) -> usize {
unimplemented!()
}
/// Get physical address of `acpi_rsdp` and `smbios` on x86_64.
pub fn pc_firmware_tables() -> (u64, u64) {
unimplemented!()
}
/// Get ACPI Table
pub fn get_acpi_table() -> Option<Acpi> {
unimplemented!()
}
/// IO Ports access on x86 platform
pub fn outpd(_port: u16, _value: u32) {
unimplemented!()
}
pub fn inpd(_port: u16) -> u32 {
unimplemented!()
}
/// Get local APIC ID
pub fn apic_local_id() -> u8 {
unimplemented!()
}

View File

@ -0,0 +1,21 @@
pub mod context;
pub mod cpu;
pub mod dev;
pub mod interrupt;
pub mod memory;
pub mod misc;
pub mod paging;
pub mod rand;
pub mod serial;
pub mod thread;
pub mod timer;
pub mod vdso;
pub use self::misc::*; // FIXME
/// Initialize the HAL.
///
/// This function must be called at the beginning.
pub fn init() {
unimplemented!();
}

View File

@ -0,0 +1,50 @@
use crate::{HalResult, MMUFlags, PhysAddr, VirtAddr};
pub use crate::common::paging::*;
pub struct PageTable;
impl PageTable {
/// Create a new `PageTable`.
pub fn new() -> Self {
PageTable
}
/// Get the current root page table physical address. (e.g. CR3, SATP, ...)
pub fn current() -> Self {
unimplemented!();
}
}
impl PageTableTrait for PageTable {
/// Map the page of `vaddr` to the frame of `paddr` with `flags`.
fn map(&mut self, _vaddr: VirtAddr, _paddr: PhysAddr, _flags: MMUFlags) -> HalResult<()> {
unimplemented!();
}
/// Unmap the page of `vaddr`.
fn unmap(&mut self, _vaddr: VirtAddr) -> HalResult<()> {
unimplemented!();
}
/// Change the `flags` of the page of `vaddr`.
fn protect(&mut self, _vaddr: VirtAddr, _flags: MMUFlags) -> HalResult<()> {
unimplemented!();
}
/// Query the physical address which the page of `vaddr` maps to.
fn query(&mut self, _vaddr: VirtAddr) -> HalResult<PhysAddr> {
unimplemented!();
}
/// Get the physical address of root page table.
fn table_phys(&self) -> PhysAddr {
unimplemented!();
}
#[cfg(target_arch = "riscv64")]
/// Activate this page table
fn activate(&self) {
unimplemented!();
}
}

View File

@ -0,0 +1,18 @@
/// Fill random bytes to the buffer
#[allow(unused_variables)]
pub fn fill_random(buf: &mut [u8]) {
cfg_if::cfg_if! {
if #[cfg(target_arch = "x86_64")] {
// TODO: optimize
for x in buf.iter_mut() {
let mut r = 0;
unsafe {
core::arch::x86_64::_rdrand16_step(&mut r);
}
*x = r as _;
}
} else {
unimplemented!()
}
}
}

View File

@ -0,0 +1,21 @@
use alloc::boxed::Box;
/// Put a char by serial interrupt handler.
pub fn serial_put(_x: u8) {
unimplemented!()
}
/// Register a callback of serial readable event.
pub fn serial_set_callback(_callback: Box<dyn Fn() -> bool + Send + Sync>) {
unimplemented!()
}
/// Read a string from console.
pub fn serial_read(_buf: &mut [u8]) -> usize {
unimplemented!()
}
/// Output a string to console.
pub fn serial_write(_s: &str) {
unimplemented!()
}

View File

@ -0,0 +1,18 @@
use alloc::boxed::Box;
use core::future::Future;
use core::pin::Pin;
/// Spawn a new thread.
pub fn spawn(_future: Pin<Box<dyn Future<Output = ()> + Send + 'static>>, _vmtoken: usize) {
unimplemented!()
}
/// Set tid and pid of current task.
pub fn set_tid(_tid: u64, _pid: u64) {
unimplemented!()
}
/// Get tid and pid of current task.]
pub fn get_tid() -> (u64, u64) {
unimplemented!()
}

View File

@ -0,0 +1,21 @@
use alloc::boxed::Box;
use core::time::Duration;
/// Get current time.
pub fn timer_now() -> Duration {
unimplemented!()
}
/// Set a new timer. After `deadline`, the `callback` will be called.
pub fn timer_set(_deadline: Duration, _callback: Box<dyn FnOnce(Duration) + Send + Sync>) {
unimplemented!()
}
pub fn timer_set_next() {
unimplemented!()
}
/// Check timers, call when timer interrupt happened.
pub fn timer_tick() {
unimplemented!()
}

View File

@ -0,0 +1,5 @@
pub use crate::common::vdso::*;
pub fn vdso_constants() -> VdsoConstants {
unimplemented!()
}

View File

@ -16,10 +16,10 @@ zircon-object = { path = "../zircon-object" }
kernel-hal = { path = "../kernel-hal" }
rcore-fs-hostfs = { git = "https://github.com/rcore-os/rcore-fs", rev = "6df6cd2", optional = true }
env_logger = { version = "0.8", optional = true }
kernel-hal-unix = { path = "../kernel-hal-unix", optional = true }
async-std = { version = "1.9", features = ["attributes"], optional = true }
[features]
default = ["std"]
std = ["env_logger", "async-std", "kernel-hal-unix", "rcore-fs-hostfs", "zircon-object/aspace-separate"]
graphic = ["std"]
default = ["std", "libos"]
libos = ["kernel-hal/libos"]
std = ["env_logger", "async-std", "rcore-fs-hostfs", "zircon-object/aspace-separate"]
graphic = ["std", "linux-object/graphic"]

View File

@ -23,10 +23,10 @@ use {
};
#[cfg(target_arch = "riscv64")]
use {kernel_hal::UserContext, zircon_object::object::KernelObject};
use {kernel_hal::context::UserContext, zircon_object::object::KernelObject};
#[cfg(target_arch = "x86_64")]
use kernel_hal::GeneralRegs;
use kernel_hal::context::GeneralRegs;
/// Create and run main Linux process
pub fn run(args: Vec<String>, envs: Vec<String>, rootfs: Arc<dyn FileSystem>) -> Arc<Process> {
@ -35,7 +35,7 @@ pub fn run(args: Vec<String>, envs: Vec<String>, rootfs: Arc<dyn FileSystem>) ->
let thread = Thread::create_linux(&proc).unwrap();
let loader = LinuxElfLoader {
#[cfg(feature = "std")]
syscall_entry: kernel_hal_unix::syscall_entry as usize,
syscall_entry: kernel_hal::context::syscall_entry as usize,
#[cfg(not(feature = "std"))]
syscall_entry: 0,
stack_pages: 8,
@ -57,7 +57,8 @@ pub fn run(args: Vec<String>, envs: Vec<String>, rootfs: Arc<dyn FileSystem>) ->
let path = args[0].clone();
debug!("Linux process: {:?}", path);
let pg_token = kernel_hal::current_page_table();
use kernel_hal::paging::PageTableTrait;
let pg_token = kernel_hal::paging::PageTable::current().table_phys();
debug!("current pgt = {:#x}", pg_token);
//调用zircon-object/src/task/thread.start设置好要执行的thread
let (entry, sp) = loader.load(&proc.vmar(), &data, args, envs, path).unwrap();
@ -86,7 +87,7 @@ async fn new_thread(thread: CurrentThread) {
// run
trace!("go to user: {:#x?}", cx);
kernel_hal::context_run(&mut cx);
kernel_hal::context::context_run(&mut cx);
trace!("back from user: {:#x?}", cx);
// handle trap/interrupt/syscall
@ -94,13 +95,13 @@ async fn new_thread(thread: CurrentThread) {
match cx.trap_num {
0x100 => handle_syscall(&thread, &mut cx.general).await,
0x20..=0x3f => {
kernel_hal::InterruptManager::handle_irq(cx.trap_num as u32);
kernel_hal::interrupt::handle_irq(cx.trap_num as u32);
if cx.trap_num == 0x20 {
kernel_hal::yield_now().await;
kernel_hal::future::yield_now().await;
}
}
0xe => {
let vaddr = kernel_hal::fetch_fault_vaddr();
let vaddr = kernel_hal::context::fetch_fault_vaddr();
let flags = if cx.error_code & 0x2 == 0 {
MMUFlags::READ
} else {
@ -129,7 +130,7 @@ async fn new_thread(thread: CurrentThread) {
match trap_num {
//Irq
0 | 4 | 5 | 8 | 9 => {
kernel_hal::InterruptManager::handle_irq(trap_num as u32);
kernel_hal::interrupt::handle_irq(trap_num as u32);
//Timer
if trap_num == 4 || trap_num == 5 {
@ -141,10 +142,10 @@ async fn new_thread(thread: CurrentThread) {
kernel_hal::timer_tick();
*/
kernel_hal::yield_now().await;
kernel_hal::future::yield_now().await;
}
//kernel_hal::InterruptManager::handle_irq(trap_num as u32);
//kernel_hal::interrupt::handle_irq(trap_num as u32);
}
_ => panic!(
"not supported pid: {} interrupt {} from user mode. {:#x?}",
@ -204,7 +205,7 @@ async fn handle_syscall(thread: &CurrentThread, regs: &mut GeneralRegs) {
let mut syscall = Syscall {
thread,
#[cfg(feature = "std")]
syscall_entry: kernel_hal_unix::syscall_entry as usize,
syscall_entry: kernel_hal::context::syscall_entry as usize,
#[cfg(not(feature = "std"))]
syscall_entry: 0,
thread_fn,
@ -234,7 +235,7 @@ async fn handle_syscall(thread: &CurrentThread, cx: &mut UserContext) {
let mut syscall = Syscall {
thread,
#[cfg(feature = "std")]
syscall_entry: kernel_hal_unix::syscall_entry as usize,
syscall_entry: kernel_hal::context::syscall_entry as usize,
#[cfg(not(feature = "std"))]
syscall_entry: 0,
context: cx,

View File

@ -15,16 +15,16 @@ async fn main() {
// init loggger for debug
init_logger();
// init HAL implementation on unix
kernel_hal_unix::init();
kernel_hal::init();
#[cfg(feature = "graphic")]
{
kernel_hal_unix::init_framebuffer();
kernel_hal_unix::init_input();
kernel_hal::dev::fb::init();
kernel_hal::dev::input::init();
}
kernel_hal::serial_set_callback(Box::new({
kernel_hal::serial::serial_set_callback(Box::new({
move || {
let mut buffer = [0; 255];
let len = kernel_hal::serial_read(&mut buffer);
let len = kernel_hal::serial::serial_read(&mut buffer);
for c in &buffer[..len] {
STDIN.push((*c).into());
}
@ -70,7 +70,7 @@ mod tests {
/// test with cmd line
async fn test(cmdline: &str) -> i64 {
kernel_hal_unix::init();
kernel_hal::init();
let args: Vec<String> = cmdline.split(' ').map(|s| s.into()).collect();
let envs =

View File

@ -7,6 +7,9 @@ description = "Linux kernel objects"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
graphic = []
[dependencies]
async-trait = "0.1"
log = "0.4"
@ -24,3 +27,4 @@ rcore-fs-sfs = { git = "https://github.com/rcore-os/rcore-fs", rev = "6df6cd2" }
rcore-fs-ramfs = { git = "https://github.com/rcore-os/rcore-fs", rev = "6df6cd2" }
rcore-fs-mountfs = { git = "https://github.com/rcore-os/rcore-fs", rev = "6df6cd2" }
rcore-fs-devfs = { git = "https://github.com/rcore-os/rcore-fs", rev = "6df6cd2" }
cfg-if = "1.0"

View File

@ -1,7 +1,7 @@
//! Implement INode for framebuffer
use core::any::Any;
use kernel_hal::{ColorFormat, FramebufferInfo, FRAME_BUFFER};
use kernel_hal::dev::fb::{ColorFormat, FramebufferInfo, FRAME_BUFFER};
use rcore_fs::vfs::*;

View File

@ -3,6 +3,7 @@ use alloc::{boxed::Box, collections::VecDeque, sync::Arc};
use core::any::Any;
use spin::Mutex;
use kernel_hal::dev::input;
use rcore_fs::vfs::*;
/// input device
@ -18,7 +19,7 @@ impl InputEventInode {
pub fn new(id: usize) -> Self {
let data = Arc::new(Mutex::new(VecDeque::with_capacity(MAX_QUEUE)));
let data_clone = data.clone();
kernel_hal::kbd_set_callback(Box::new(move |code, value| {
input::kbd_set_callback(Box::new(move |code, value| {
let mut queue = data_clone.lock();
while queue.len() >= MAX_QUEUE {
queue.pop_front();

View File

@ -2,6 +2,7 @@ use alloc::{boxed::Box, collections::VecDeque, sync::Arc};
use core::any::Any;
use spin::Mutex;
use kernel_hal::dev::input;
use rcore_fs::vfs::*;
/// mice device
@ -15,7 +16,7 @@ impl InputMiceInode {
pub fn new() -> Self {
let data = Arc::new(Mutex::new(VecDeque::with_capacity(MAX_QUEUE)));
let data_clone = data.clone();
kernel_hal::mice_set_callback(Box::new(move |data| {
input::mice_set_callback(Box::new(move |data| {
let mut queue = data_clone.lock();
while queue.len() >= MAX_QUEUE {
queue.pop_front();

View File

@ -8,10 +8,8 @@ use rcore_fs_mountfs::MountFS;
use rcore_fs_ramfs::RamFS;
pub use self::device::*;
pub use self::fbdev::*;
pub use self::fcntl::*;
pub use self::file::*;
pub use self::input::*;
pub use self::pipe::*;
pub use self::pseudo::*;
pub use self::random::*;
@ -26,16 +24,23 @@ use downcast_rs::impl_downcast;
use zircon_object::object::*;
mod device;
mod fbdev;
mod fcntl;
mod file;
mod input;
mod ioctl;
mod pipe;
mod pseudo;
mod random;
mod stdio;
cfg_if::cfg_if! {
if #[cfg(feature = "graphic")] {
mod fbdev;
mod input;
pub use self::input::*;
pub use self::fbdev::*;
}
}
#[async_trait]
/// Generic file interface
///
@ -123,6 +128,9 @@ pub fn create_root_fs(rootfs: Arc<dyn FileSystem>) -> Arc<dyn INode> {
devfs
.add("urandom", Arc::new(RandomINode::new(true)))
.expect("failed to mknod /dev/urandom");
#[cfg(feature = "graphic")]
{
devfs
.add("fb0", Arc::new(Fbdev::default()))
.expect("failed to mknod /dev/fb0");
@ -134,6 +142,7 @@ pub fn create_root_fs(rootfs: Arc<dyn FileSystem>) -> Arc<dyn INode> {
devfs
.add("input-mice", Arc::new(InputMiceInode::default()))
.expect("failed to mknod /dev/input-mice");
}
// mount DevFS at /dev
let dev = root.find(true, "dev").unwrap_or_else(|_| {

View File

@ -132,7 +132,7 @@ impl INode for Stdout {
fn write_at(&self, _offset: usize, buf: &[u8]) -> Result<usize> {
// we do not care the utf-8 things, we just want to print it!
let s = unsafe { core::str::from_utf8_unchecked(buf) };
kernel_hal::serial_write(s);
kernel_hal::serial::serial_write(s);
Ok(buf.len())
}
fn poll(&self) -> Result<PollStatus> {

View File

@ -2,7 +2,6 @@
use alloc::sync::Arc;
use core::time::Duration;
use kernel_hal::timer_now;
use rcore_fs::vfs::*;
/// TimeSpec struct for clock_gettime, similar to Timespec
@ -39,7 +38,7 @@ impl TimeVal {
impl TimeSpec {
/// create TimeSpec
pub fn now() -> TimeSpec {
let time = timer_now();
let time = kernel_hal::timer::timer_now();
TimeSpec {
sec: time.as_secs() as usize,
nsec: (time.as_nanos() % 1_000_000_000) as usize,

View File

@ -12,7 +12,7 @@ use core::mem::size_of;
use core::pin::Pin;
use core::task::{Context, Poll};
use core::time::Duration;
use kernel_hal::timer_set;
use kernel_hal::timer::timer_set;
use linux_object::fs::FileDesc;
use linux_object::time::*;

View File

@ -8,7 +8,7 @@
//! let mut syscall = Syscall {
//! thread,
//! #[cfg(feature = "std")]
//! syscall_entry: kernel_hal_unix::syscall_entry as usize,
//! syscall_entry: kernel_hal::context::syscall_entry as usize,
//! #[cfg(not(feature = "std"))]
//! syscall_entry: 0,
//! thread_fn,
@ -32,13 +32,13 @@ use {
self::consts::SyscallType as Sys,
alloc::sync::Arc,
core::convert::TryFrom,
kernel_hal::{user::*, GeneralRegs},
kernel_hal::{context::GeneralRegs, user::*},
linux_object::{error::*, fs::FileDesc, process::*},
zircon_object::{object::*, task::*, vm::VirtAddr},
};
#[cfg(target_arch = "riscv64")]
use kernel_hal::UserContext;
use kernel_hal::context::UserContext;
mod consts {
// generated from syscall.h.in

View File

@ -132,7 +132,7 @@ impl Syscall<'_> {
pub fn sys_getrandom(&mut self, mut buf: UserOutPtr<u8>, len: usize, flag: u32) -> SysResult {
info!("getrandom: buf: {:?}, len: {:?}, flag {:?}", buf, len, flag);
let mut buffer = vec![0u8; len];
kernel_hal::fill_random(&mut buffer);
kernel_hal::rand::fill_random(&mut buffer);
buf.write_array(&buffer[..len])?;
Ok(len)
}

View File

@ -297,7 +297,7 @@ impl Syscall<'_> {
pub async fn sys_nanosleep(&self, req: UserInPtr<TimeSpec>) -> SysResult {
info!("nanosleep: deadline={:?}", req);
let req = req.read()?;
kernel_hal::sleep_until(req.into()).await;
kernel_hal::future::sleep_until(req.into()).await;
Ok(0)
}

View File

@ -22,6 +22,7 @@ lto = true
log = "0.4"
spin = "0.7"
buddy_system_allocator = "0.7"
kernel-hal = { path = "../kernel-hal" }
kernel-hal-bare = { path = "../kernel-hal-bare" }
lazy_static = { version = "1.4", features = ["spin_no_std" ] }
bitmap-allocator = { git = "https://github.com/rcore-os/bitmap-allocator", rev = "03bd9909" }

View File

@ -62,7 +62,7 @@ impl Log for SimpleLogger {
"[{:?} {:>5} {} {}:{}] {}\n",
kernel_hal_bare::timer_now(),
record.level(),
kernel_hal_bare::apic_local_id(),
kernel_hal::cpu::cpu_id(),
pid,
tid,
record.args()

View File

@ -15,10 +15,9 @@ zircon-syscall = { path = "../zircon-syscall" }
kernel-hal = { path = "../kernel-hal" }
env_logger = { version = "0.8", optional = true }
structopt = { version = "0.3", default-features = false, optional = true }
kernel-hal-unix = { path = "../kernel-hal-unix", optional = true }
async-std = { version = "1.9", features = ["attributes"], optional = true }
[features]
default = ["std"]
std = ["env_logger", "structopt", "async-std", "kernel-hal-unix",
"zircon-object/aspace-separate", "zircon-syscall/std"]
default = ["std", "libos"]
libos = ["kernel-hal/libos"]
std = ["env_logger", "structopt", "async-std", "zircon-object/aspace-separate", "zircon-syscall/std"]

View File

@ -34,8 +34,8 @@ pub fn create_kcounter_vmo() -> (Arc<VmObject>, Arc<VmObject>) {
fn kcounters_arena_start();
fn kcounters_arena_end();
}
use kernel_hal::PageTableTrait;
let mut pgtable = kernel_hal::PageTable::current();
use kernel_hal::paging::{PageTable, PageTableTrait};
let mut pgtable = PageTable::current();
let paddr = pgtable.query(kcounters_arena_start as usize).unwrap();
assert_eq!(
kcounters_arena_start as usize / PAGE_SIZE,

View File

@ -83,7 +83,7 @@ pub fn run_userboot(images: &Images<impl AsRef<[u8]>>, cmdline: &str) -> Arc<Pro
let offset = elf
.get_symbol_address("zcore_syscall_entry")
.expect("failed to locate syscall entry") as usize;
let syscall_entry = &(kernel_hal_unix::syscall_entry as usize).to_ne_bytes();
let syscall_entry = &(kernel_hal::context::syscall_entry as usize).to_ne_bytes();
// fill syscall entry x3
vdso_vmo.write(offset, syscall_entry).unwrap();
vdso_vmo.write(offset + 8, syscall_entry).unwrap();
@ -127,7 +127,7 @@ pub fn run_userboot(images: &Images<impl AsRef<[u8]>>, cmdline: &str) -> Arc<Pro
const VDSO_DATA_CONSTANTS: usize = 0x4a50;
const VDSO_DATA_CONSTANTS_SIZE: usize = 0x78;
let constants: [u8; VDSO_DATA_CONSTANTS_SIZE] =
unsafe { core::mem::transmute(kernel_hal::vdso_constants()) };
unsafe { core::mem::transmute(kernel_hal::vdso::vdso_constants()) };
vdso_vmo.write(VDSO_DATA_CONSTANTS, &constants).unwrap();
vdso_vmo.set_name("vdso/full");
let vdso_test1 = vdso_vmo.create_child(false, 0, vdso_vmo.len()).unwrap();
@ -172,7 +172,7 @@ kcounter!(EXCEPTIONS_TIMER, "exceptions.timer");
kcounter!(EXCEPTIONS_PGFAULT, "exceptions.pgfault");
async fn new_thread(thread: CurrentThread) {
kernel_hal::Thread::set_tid(thread.id(), thread.proc().id());
kernel_hal::thread::set_tid(thread.id(), thread.proc().id());
if thread.is_first_thread() {
thread
.handle_exception(ExceptionType::ProcessStarting)
@ -187,18 +187,18 @@ async fn new_thread(thread: CurrentThread) {
}
trace!("go to user: {:#x?}", cx);
debug!("switch to {}|{}", thread.proc().name(), thread.name());
let tmp_time = kernel_hal::timer_now().as_nanos();
let tmp_time = kernel_hal::timer::timer_now().as_nanos();
// * Attention
// The code will enter a magic zone from here.
// `context run` will be executed into a wrapped library where context switching takes place.
// The details are available in the trapframe crate on crates.io.
kernel_hal::context_run(&mut cx);
kernel_hal::context::context_run(&mut cx);
// Back from the userspace
let time = kernel_hal::timer_now().as_nanos() - tmp_time;
let time = kernel_hal::timer::timer_now().as_nanos() - tmp_time;
thread.time_add(time);
trace!("back from user: {:#x?}", cx);
EXCEPTIONS_USER.add(1);
@ -217,10 +217,10 @@ async fn new_thread(thread: CurrentThread) {
match trap_num {
0x100 => handle_syscall(&thread).await,
0x20..=0x3f => {
kernel_hal::InterruptManager::handle_irq(trap_num as u32);
kernel_hal::interrupt::handle_irq(trap_num as u32);
if trap_num == 0x20 {
EXCEPTIONS_TIMER.add(1);
kernel_hal::yield_now().await;
kernel_hal::future::yield_now().await;
}
}
0xe => {

View File

@ -23,7 +23,7 @@ struct Opt {
#[async_std::main]
async fn main() {
kernel_hal_unix::init();
kernel_hal::init();
init_logger();
let opt = Opt::from_args();
@ -53,7 +53,7 @@ fn init_logger() {
use log::Level;
use std::io::Write;
let (tid, pid) = kernel_hal::Thread::get_tid();
let (tid, pid) = kernel_hal::thread::get_tid();
let mut style = buf.style();
match record.level() {
Level::Trace => style.set_color(Color::Black).set_intense(true),
@ -62,7 +62,7 @@ fn init_logger() {
Level::Warn => style.set_color(Color::Yellow),
Level::Error => style.set_color(Color::Red).set_bold(true),
};
let now = kernel_hal_unix::timer_now();
let now = kernel_hal::timer::timer_now();
let level = style.value(record.level());
let args = record.args();
writeln!(buf, "[{:?} {:>5} {}:{}] {}", now, level, pid, tid, args)
@ -76,7 +76,7 @@ mod tests {
#[async_std::test]
async fn userboot() {
kernel_hal_unix::init();
kernel_hal::init();
let opt = Opt {
#[cfg(target_arch = "x86_64")]

View File

@ -29,5 +29,4 @@ cfg-if = "1.0"
#rvm = { git = "https://github.com/rcore-os/RVM", rev = "382fc60", optional = true }
[dev-dependencies]
kernel-hal-unix = { path = "../kernel-hal-unix" }
async-std = { version = "1.9", features = ["attributes", "unstable"] }

View File

@ -3,7 +3,6 @@ use {
super::*,
crate::object::*,
alloc::{sync::Arc, vec::Vec},
kernel_hal::timer_now,
lazy_static::lazy_static,
spin::Mutex,
};
@ -111,7 +110,7 @@ impl DlogBuffer {
datalen: data.len() as u16,
severity,
flags: flags as u8,
timestamp: timer_now().as_nanos() as u64,
timestamp: kernel_hal::timer::timer_now().as_nanos() as u64,
pid,
tid,
};

View File

@ -1,4 +1,4 @@
use kernel_hal::InterruptManager;
use kernel_hal::interrupt;
use {super::*, spin::Mutex};
pub struct EventInterrupt {
@ -25,14 +25,14 @@ impl InterruptTrait for EventInterrupt {
fn mask(&self) {
let inner = self.inner.lock();
if inner.register {
InterruptManager::disable_irq(self.vector as u32);
interrupt::disable_irq(self.vector as u32);
}
}
fn unmask(&self) {
let inner = self.inner.lock();
if inner.register {
InterruptManager::enable_irq(self.vector as u32);
interrupt::enable_irq(self.vector as u32);
}
}
@ -41,7 +41,7 @@ impl InterruptTrait for EventInterrupt {
if inner.register {
return Err(ZxError::ALREADY_BOUND);
}
if InterruptManager::register_irq_handler(self.vector, handle).is_some() {
if interrupt::register_irq_handler(self.vector, handle).is_some() {
inner.register = true;
Ok(())
} else {
@ -54,7 +54,7 @@ impl InterruptTrait for EventInterrupt {
if !inner.register {
return Ok(());
}
if InterruptManager::unregister_irq_handler(self.vector) {
if interrupt::unregister_irq_handler(self.vector) {
inner.register = false;
Ok(())
} else {

View File

@ -293,7 +293,7 @@ impl Interrupt {
}
if inner.timestamp == 0 {
// Not sure ZX_CLOCK_MONOTONIC or ZX_CLOCK_UTC
inner.timestamp = kernel_hal::timer_now().as_nanos() as i64;
inner.timestamp = kernel_hal::timer::timer_now().as_nanos() as i64;
}
match &inner.port {
Some(port) => {

View File

@ -3,7 +3,7 @@ use crate::{ZxError, ZxResult};
use alloc::boxed::Box;
use core::convert::TryFrom;
use kernel_hal::InterruptManager;
use kernel_hal::interrupt;
use spin::*;
/// Enumeration for PCI capabilities.
@ -46,8 +46,7 @@ impl PciMsiBlock {
if irq_num == 0 || irq_num > 32 {
return Err(ZxError::INVALID_ARGS);
}
let (start, size) =
InterruptManager::msi_allocate_block(irq_num).ok_or(ZxError::NO_RESOURCES)?;
let (start, size) = interrupt::msi_allocate_block(irq_num).ok_or(ZxError::NO_RESOURCES)?;
Ok(PciMsiBlock {
target_addr: (0xFEE0_0000 | 0x08) & !0x4,
target_data: start as u32,
@ -57,12 +56,12 @@ impl PciMsiBlock {
})
}
pub fn free(&self) {
InterruptManager::msi_free_block(self.base_irq, self.num_irq)
interrupt::msi_free_block(self.base_irq, self.num_irq)
}
pub fn register_handler(&self, msi_id: u32, handle: Box<dyn Fn() + Send + Sync>) {
assert!(self.allocated);
assert!(msi_id < self.num_irq);
InterruptManager::msi_register_handler(self.base_irq, self.num_irq, msi_id, handle);
interrupt::msi_register_handler(self.base_irq, self.num_irq, msi_id, handle);
}
}

View File

@ -13,7 +13,7 @@ use crate::{vm::PAGE_SIZE, ZxError, ZxResult};
use alloc::sync::{Arc, Weak};
use alloc::{boxed::Box, vec::Vec};
use kernel_hal::InterruptManager;
use kernel_hal::interrupt;
use numeric_enum_macro::numeric_enum;
use region_alloc::RegionAllocator;
use spin::{Mutex, MutexGuard};
@ -192,13 +192,13 @@ impl SharedLegacyIrqHandler {
/// Create a new SharedLegacyIrqHandler.
pub fn create(irq_id: u32) -> Option<Arc<SharedLegacyIrqHandler>> {
info!("SharedLegacyIrqHandler created for {:#x?}", irq_id);
InterruptManager::disable_irq(irq_id);
interrupt::disable_irq(irq_id);
let handler = Arc::new(SharedLegacyIrqHandler {
irq_id,
device_handler: Mutex::new(Vec::new()),
});
let handler_copy = handler.clone();
if InterruptManager::register_irq_handler(irq_id, Box::new(move || handler_copy.handle()))
if interrupt::register_irq_handler(irq_id, Box::new(move || handler_copy.handle()))
.is_some()
{
Some(handler)
@ -211,7 +211,7 @@ impl SharedLegacyIrqHandler {
pub fn handle(&self) {
let device_handler = self.device_handler.lock();
if device_handler.is_empty() {
InterruptManager::disable_irq(self.irq_id);
interrupt::disable_irq(self.irq_id);
return;
}
for dev in device_handler.iter() {
@ -260,7 +260,7 @@ impl SharedLegacyIrqHandler {
let is_first = device_handler.is_empty();
device_handler.push(device);
if is_first {
InterruptManager::enable_irq(self.irq_id);
interrupt::enable_irq(self.irq_id);
}
}
pub fn remove_device(&self, device: Arc<PcieDevice>) {
@ -272,7 +272,7 @@ impl SharedLegacyIrqHandler {
let mut device_handler = self.device_handler.lock();
device_handler.retain(|h| Arc::ptr_eq(h, &device));
if device_handler.is_empty() {
InterruptManager::disable_irq(self.irq_id);
interrupt::disable_irq(self.irq_id);
}
}
}

View File

@ -45,17 +45,17 @@ pub const PCI_INIT_ARG_MAX_SIZE: usize = core::mem::size_of::<PciInitArgsAddrWin
* PCI_INIT_ARG_MAX_ECAM_WINDOWS
+ core::mem::size_of::<PciInitArgsHeader>();
use kernel_hal::InterruptManager;
use kernel_hal::interrupt;
impl PciInitArgsHeader {
pub fn configure_interrupt(&mut self) -> ZxResult {
for i in 0..self.num_irqs as usize {
let irq = &mut self.irqs[i];
let global_irq = irq.global_irq;
if !InterruptManager::is_valid_irq(global_irq) {
if !interrupt::is_valid_irq(global_irq) {
irq.global_irq = PCI_NO_IRQ_MAPPING;
self.dev_pin_to_global_irq.remove_irq(global_irq);
} else if !InterruptManager::configure_irq(
} else if !interrupt::configure_irq(
global_irq,
irq.level_triggered, /* Trigger mode */
irq.active_high, /* Polarity */

View File

@ -73,7 +73,7 @@ impl Timer {
inner.deadline = Some(deadline);
self.base.signal_clear(Signal::SIGNALED);
let me = Arc::downgrade(self);
kernel_hal::timer_set(
kernel_hal::timer::timer_set(
deadline,
Box::new(move |now| me.upgrade().map(|timer| timer.touch(now)).unwrap_or(())),
);
@ -100,7 +100,7 @@ impl Timer {
#[cfg(test)]
mod tests {
use super::*;
use kernel_hal::timer_now;
use kernel_hal::timer::timer_now;
#[test]
fn one_shot() {

View File

@ -1,6 +1,6 @@
use {
super::*, crate::ipc::*, crate::object::*, alloc::sync::Arc, alloc::vec, alloc::vec::Vec,
core::mem::size_of, futures::channel::oneshot, kernel_hal::UserContext, spin::Mutex,
core::mem::size_of, futures::channel::oneshot, kernel_hal::context::UserContext, spin::Mutex,
};
/// Kernel-owned exception channel endpoint.
@ -157,7 +157,7 @@ impl ExceptionContext {
ExceptionContext {
vector: cx.trap_num as u64,
err_code: cx.error_code as u64,
cr2: kernel_hal::fetch_fault_vaddr() as u64,
cr2: kernel_hal::context::fetch_fault_vaddr() as u64,
}
}
#[cfg(target_arch = "aarch64")]

View File

@ -143,7 +143,7 @@ impl Process {
/// # use std::sync::Arc;
/// # use zircon_object::task::*;
/// # use zircon_object::object::*;
/// # kernel_hal_unix::init();
/// # kernel_hal::init();
/// # async_std::task::block_on(async {
/// let job = Job::root();
/// let proc = Process::create(&job, "proc").unwrap();

View File

@ -13,7 +13,7 @@ use {
/// # use std::sync::Arc;
/// # use zircon_object::task::*;
/// # use zircon_object::object::{KernelObject, Signal};
/// # kernel_hal_unix::init();
/// # kernel_hal::init();
/// let job = Job::root();
/// let proc = Process::create(&job, "proc").unwrap();
/// let thread = Thread::create(&proc, "thread").unwrap();

View File

@ -14,7 +14,8 @@ use {
time::Duration,
},
futures::{channel::oneshot::*, future::FutureExt, pin_mut, select_biased},
kernel_hal::{sleep_until, GeneralRegs, UserContext},
kernel_hal::context::{GeneralRegs, UserContext},
// kernel_hal::future::sleep_until,
spin::Mutex,
};
@ -193,7 +194,7 @@ impl Thread {
/// ```
/// # use std::sync::Arc;
/// # use zircon_object::task::*;
/// # kernel_hal_unix::init();
/// # kernel_hal::init();
/// let job = Job::root();
/// let proc = Process::create(&job, "proc").unwrap();
/// // create a thread with extension info
@ -272,7 +273,7 @@ impl Thread {
inner.change_state(ThreadState::Running, &self.base);
}
let vmtoken = self.proc().vmar().table_phys();
kernel_hal::Thread::spawn(thread_fn(CurrentThread(self.clone())), vmtoken);
kernel_hal::thread::spawn(thread_fn(CurrentThread(self.clone())), vmtoken);
Ok(())
}
@ -289,7 +290,7 @@ impl Thread {
inner.change_state(ThreadState::Running, &self.base);
}
let vmtoken = self.proc().vmar().table_phys();
kernel_hal::Thread::spawn(thread_fn(CurrentThread(self.clone())), vmtoken);
kernel_hal::thread::spawn(thread_fn(CurrentThread(self.clone())), vmtoken);
Ok(())
}
@ -313,7 +314,7 @@ impl Thread {
inner.change_state(ThreadState::Running, &self.base);
}
let vmtoken = self.proc().vmar().table_phys();
kernel_hal::Thread::spawn(thread_fn(CurrentThread(self.clone())), vmtoken);
kernel_hal::thread::spawn(thread_fn(CurrentThread(self.clone())), vmtoken);
Ok(())
}
@ -602,14 +603,14 @@ impl CurrentThread {
select_biased! {
ret = future.fuse() => ret.into_result(),
_ = killed.fuse() => Err(ZxError::STOP),
_ = sleep_until(deadline).fuse() => Err(ZxError::TIMED_OUT),
_ = kernel_hal::future::sleep_until(deadline).fuse() => Err(ZxError::TIMED_OUT),
_ = cancel_token.fuse() => Err(ZxError::CANCELED),
}
} else {
select_biased! {
ret = future.fuse() => ret.into_result(),
_ = killed.fuse() => Err(ZxError::STOP),
_ = sleep_until(deadline).fuse() => Err(ZxError::TIMED_OUT),
_ = kernel_hal::future::sleep_until(deadline).fuse() => Err(ZxError::TIMED_OUT),
}
};
let mut inner = self.inner.lock();
@ -765,7 +766,7 @@ pub struct ThreadInfo {
mod tests {
use super::job::Job;
use super::*;
use kernel_hal::timer_now;
use kernel_hal::timer::timer_now;
#[test]
fn create() {
@ -781,7 +782,7 @@ mod tests {
#[async_std::test]
async fn start() {
kernel_hal_unix::init();
kernel_hal::init();
let root_job = Job::root();
let proc = Process::create(&root_job, "proc").expect("failed to create process");
let thread = Thread::create(&proc, "thread").expect("failed to create thread");

View File

@ -1,5 +1,5 @@
use crate::{ZxError, ZxResult};
use kernel_hal::UserContext;
use kernel_hal::context::UserContext;
use numeric_enum_macro::numeric_enum;
numeric_enum! {

View File

@ -1,6 +1,6 @@
use {
super::*, crate::object::*, alloc::sync::Arc, alloc::vec, alloc::vec::Vec, bitflags::bitflags,
kernel_hal::PageTableTrait, spin::Mutex,
kernel_hal::paging::PageTableTrait, spin::Mutex,
};
bitflags! {
@ -78,7 +78,7 @@ impl VmAddressRegion {
addr,
size,
parent: None,
page_table: Arc::new(Mutex::new(kernel_hal::PageTable::new())), //hal PageTable
page_table: Arc::new(Mutex::new(kernel_hal::paging::PageTable::new())), //hal PageTable
inner: Mutex::new(Some(VmarInner::default())),
})
}
@ -94,7 +94,7 @@ impl VmAddressRegion {
addr: kernel_vmar_base,
size: kernel_vmar_size,
parent: None,
page_table: Arc::new(Mutex::new(kernel_hal::PageTable::new())),
page_table: Arc::new(Mutex::new(kernel_hal::paging::PageTable::new())),
inner: Mutex::new(Some(VmarInner::default())),
})
}

View File

@ -8,7 +8,7 @@ use {
core::ops::Range,
core::sync::atomic::*,
hashbrown::HashMap,
kernel_hal::{frame_flush, PhysFrame, PAGE_SIZE},
kernel_hal::{memory::PhysFrame, PAGE_SIZE},
spin::{Mutex, MutexGuard},
};
@ -188,7 +188,7 @@ impl VMObjectPaged {
let (_guard, mut inner) = vmo.get_inner_mut();
inner.contiguous = true;
for (i, f) in frames.drain(0..).enumerate() {
kernel_hal::pmem_zero(f.addr(), PAGE_SIZE);
kernel_hal::memory::pmem_zero(f.addr(), PAGE_SIZE);
let mut state = PageState::new(f);
state.pin_count += 1;
inner.frames.insert(i, state);
@ -225,7 +225,7 @@ impl VMObjectTrait for VMObjectPaged {
return Err(ZxError::BAD_STATE);
}
inner.for_each_page(offset, buf.len(), MMUFlags::READ, |paddr, buf_range| {
kernel_hal::pmem_read(paddr, &mut buf[buf_range]);
kernel_hal::memory::pmem_read(paddr, &mut buf[buf_range]);
})
}
@ -235,7 +235,7 @@ impl VMObjectTrait for VMObjectPaged {
return Err(ZxError::BAD_STATE);
}
inner.for_each_page(offset, buf.len(), MMUFlags::WRITE, |paddr, buf_range| {
kernel_hal::pmem_write(paddr, &buf[buf_range]);
kernel_hal::memory::pmem_write(paddr, &buf[buf_range]);
})
}
@ -259,7 +259,7 @@ impl VMObjectTrait for VMObjectPaged {
} else if inner.committed_pages_in_range(block.block, block.block + 1) != 0 {
// check whether this page is initialized, otherwise nothing should be done
let paddr = inner.commit_page(block.block, MMUFlags::WRITE)?;
kernel_hal::pmem_zero(paddr + block.begin, block.len());
kernel_hal::memory::pmem_zero(paddr + block.begin, block.len());
}
}
inner.release_unwanted_pages_in_parent(unwanted);
@ -371,7 +371,7 @@ impl VMObjectTrait for VMObjectPaged {
}
if inner.cache_policy == CachePolicy::Cached && policy != CachePolicy::Cached {
for (_, value) in inner.frames.iter() {
frame_flush(value.frame.addr());
kernel_hal::memory::frame_flush(value.frame.addr());
}
}
inner.cache_policy = policy;
@ -528,7 +528,7 @@ impl VMObjectPagedInner {
// lazy allocate zero frame
// 这里会调用HAL层的hal_frame_alloc, 请注意实现该函数时参数要一样
let target_frame = PhysFrame::alloc().ok_or(ZxError::NO_MEMORY)?;
kernel_hal::pmem_zero(target_frame.addr(), PAGE_SIZE);
kernel_hal::memory::pmem_zero(target_frame.addr(), PAGE_SIZE);
if out_of_range {
// can never be a hidden vmo
assert!(!self.type_.is_hidden());
@ -607,7 +607,7 @@ impl VMObjectPagedInner {
} else if flags.contains(MMUFlags::WRITE) && child_tag.is_split() {
// copy-on-write
let target_frame = PhysFrame::alloc().ok_or(ZxError::NO_MEMORY)?;
kernel_hal::frame_copy(frame.frame.addr(), target_frame.addr());
kernel_hal::memory::frame_copy(frame.frame.addr(), target_frame.addr());
frame.tag = child_tag;
return Ok(CommitResult::CopyOnWrite(target_frame, true));
}

View File

@ -39,21 +39,21 @@ impl VMObjectTrait for VMObjectPhysical {
fn read(&self, offset: usize, buf: &mut [u8]) -> ZxResult {
let _ = self.data_lock.lock();
assert!(offset + buf.len() <= self.len());
kernel_hal::pmem_read(self.paddr + offset, buf);
kernel_hal::memory::pmem_read(self.paddr + offset, buf);
Ok(())
}
fn write(&self, offset: usize, buf: &[u8]) -> ZxResult {
let _ = self.data_lock.lock();
assert!(offset + buf.len() <= self.len());
kernel_hal::pmem_write(self.paddr + offset, buf);
kernel_hal::memory::pmem_write(self.paddr + offset, buf);
Ok(())
}
fn zero(&self, offset: usize, len: usize) -> ZxResult {
let _ = self.data_lock.lock();
assert!(offset + len <= self.len());
kernel_hal::pmem_zero(self.paddr + offset, len);
kernel_hal::memory::pmem_zero(self.paddr + offset, len);
Ok(())
}

View File

@ -10,7 +10,7 @@ impl Syscall<'_> {
info!("cprng_draw_once: buf=({:?}; {:?})", buf, len);
let mut res = vec![0u8; len];
// Fill random bytes to the buffer
kernel_hal::fill_random(&mut res);
kernel_hal::rand::fill_random(&mut res);
buf.write_array(&res)?;
Ok(())
}

View File

@ -6,7 +6,7 @@ impl Syscall<'_> {
pub fn sys_debug_write(&self, buf: UserInPtr<u8>, len: usize) -> ZxResult {
info!("debug.write: buf=({:?}; {:#x})", buf, len);
let data = buf.read_array(len)?;
kernel_hal::serial_write(core::str::from_utf8(&data).unwrap());
kernel_hal::serial::serial_write(core::str::from_utf8(&data).unwrap());
Ok(())
}
@ -31,7 +31,7 @@ impl Syscall<'_> {
// let len = kernel_hal::serial_read(&mut vec);
// buf.write_array(&vec[..len])?;
// actual.write(len as u32)?;
let c = kernel_hal::serial_getchar().await;
let c = kernel_hal::future::serial_getchar().await;
buf.write_array(&[c])?;
actual.write(1)?;
Ok(())

View File

@ -54,9 +54,9 @@ impl Syscall<'_> {
let dlog = proc.get_object_with_rights::<DebugLog>(handle_value, Rights::WRITE)?;
dlog.write(Severity::Info, options, self.thread.id(), proc.id(), &data);
// print to kernel console
kernel_hal::serial_write(&data);
kernel_hal::serial::serial_write(&data);
if data.as_bytes().last() != Some(&b'\n') {
kernel_hal::serial_write("\n");
kernel_hal::serial::serial_write("\n");
}
Ok(())
}

View File

@ -5,7 +5,7 @@ use {
sync::atomic::{AtomicU64, Ordering},
time::Duration,
},
kernel_hal::{sleep_until, timer_now, yield_now},
kernel_hal::timer::timer_now,
zircon_object::{dev::*, task::*},
};
@ -94,11 +94,11 @@ impl Syscall<'_> {
pub async fn sys_nanosleep(&self, deadline: Deadline) -> ZxResult {
info!("nanosleep: deadline={:?}", deadline);
if deadline.0 <= 0 {
yield_now().await;
kernel_hal::future::yield_now().await;
} else {
self.thread
.blocking_run(
sleep_until(deadline.into()),
kernel_hal::future::sleep_until(deadline.into()),
ThreadState::BlockedSleeping,
Deadline::forever().into(),
None,