forked from rcore-os/zCore
kernel-hal: refactor for libos
This commit is contained in:
parent
de809efca2
commit
937c86f01d
|
@ -3,9 +3,8 @@ members = [
|
|||
"zircon-object",
|
||||
"zircon-loader",
|
||||
"linux-object",
|
||||
"zircon-syscall",
|
||||
"zircon-syscall",
|
||||
"linux-loader",
|
||||
"kernel-hal-unix",
|
||||
"kernel-hal",
|
||||
]
|
||||
|
||||
|
@ -14,5 +13,5 @@ exclude = [
|
|||
"zCore",
|
||||
"rboot",
|
||||
"linux-syscall",
|
||||
"kernel-hal-bare",
|
||||
"kernel-hal-bare",
|
||||
]
|
||||
|
|
2
Makefile
2
Makefile
|
@ -67,7 +67,7 @@ riscv-image: rcore-fs-fuse riscv-rootfs
|
|||
@echo building riscv.img
|
||||
@rcore-fs-fuse zCore/riscv64.img riscv_rootfs zip
|
||||
@qemu-img resize -f raw zCore/riscv64.img +5M
|
||||
|
||||
|
||||
clean:
|
||||
cargo clean
|
||||
find zCore -maxdepth 1 -name "*.img" -delete
|
||||
|
|
|
@ -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, *};
|
||||
|
||||
|
|
|
@ -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, *};
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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"
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use core::fmt;
|
||||
|
||||
pub use trapframe::{GeneralRegs, UserContext};
|
||||
|
||||
#[repr(C, align(16))]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct VectorRegs {
|
|
@ -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;
|
|
@ -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
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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::*;
|
|
@ -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(())
|
||||
}
|
||||
}
|
|
@ -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!()
|
||||
}
|
|
@ -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};
|
||||
|
|
|
@ -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!()
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
pub fn u8() -> u8 {
|
||||
0
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
pub mod fb;
|
||||
pub mod input;
|
|
@ -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());
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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::*;
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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()))
|
||||
}
|
|
@ -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());
|
||||
});
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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!()
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
pub fn cpu_id() -> u8 {
|
||||
0
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
pub use crate::common::fb::*;
|
||||
|
||||
pub fn init() {
|
||||
unimplemented!()
|
||||
}
|
|
@ -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!()
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
pub mod fb;
|
||||
pub mod input;
|
|
@ -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!()
|
||||
}
|
|
@ -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!()
|
||||
}
|
|
@ -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!()
|
||||
}
|
|
@ -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!();
|
||||
}
|
|
@ -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!();
|
||||
}
|
||||
}
|
|
@ -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!()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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!()
|
||||
}
|
|
@ -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!()
|
||||
}
|
|
@ -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!()
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
pub use crate::common::vdso::*;
|
||||
|
||||
pub fn vdso_constants() -> VdsoConstants {
|
||||
unimplemented!()
|
||||
}
|
|
@ -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"]
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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::*;
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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,17 +128,21 @@ 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");
|
||||
devfs
|
||||
.add("fb0", Arc::new(Fbdev::default()))
|
||||
.expect("failed to mknod /dev/fb0");
|
||||
// TODO /dev/input/event0
|
||||
devfs
|
||||
.add("input-event0", Arc::new(InputEventInode::new(0)))
|
||||
.expect("failed to mknod /dev/input-event0");
|
||||
// TODO /dev/input/mice
|
||||
devfs
|
||||
.add("input-mice", Arc::new(InputMiceInode::default()))
|
||||
.expect("failed to mknod /dev/input-mice");
|
||||
|
||||
#[cfg(feature = "graphic")]
|
||||
{
|
||||
devfs
|
||||
.add("fb0", Arc::new(Fbdev::default()))
|
||||
.expect("failed to mknod /dev/fb0");
|
||||
// TODO /dev/input/event0
|
||||
devfs
|
||||
.add("input-event0", Arc::new(InputEventInode::new(0)))
|
||||
.expect("failed to mknod /dev/input-event0");
|
||||
// TODO /dev/input/mice
|
||||
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(|_| {
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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::*;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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"]
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 => {
|
||||
|
|
|
@ -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")]
|
||||
|
|
|
@ -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"] }
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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")]
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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! {
|
||||
|
|
|
@ -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())),
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
use super::*;
|
||||
|
||||
impl Syscall<'_> {
|
||||
/// Draw random bytes from the kernel CPRNG.
|
||||
/// Draw random bytes from the kernel CPRNG.
|
||||
///
|
||||
/// This data should be suitable for cryptographic applications.
|
||||
/// This data should be suitable for cryptographic applications.
|
||||
///
|
||||
/// Clients that require a large volume of randomness should consider using these bytes to seed a user-space random number generator for better performance.
|
||||
pub fn sys_cprng_draw_once(&self, mut buf: UserOutPtr<u8>, len: usize) -> ZxResult {
|
||||
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(())
|
||||
}
|
||||
|
|
|
@ -2,15 +2,15 @@ use super::*;
|
|||
use zircon_object::dev::*;
|
||||
|
||||
impl Syscall<'_> {
|
||||
/// Write debug info to the serial port.
|
||||
/// Write debug info to the serial port.
|
||||
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(())
|
||||
}
|
||||
|
||||
/// Read debug info from the serial port.
|
||||
/// Read debug info from the serial port.
|
||||
pub async fn sys_debug_read(
|
||||
&self,
|
||||
handle: HandleValue,
|
||||
|
@ -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(())
|
||||
|
|
|
@ -4,7 +4,7 @@ use {
|
|||
};
|
||||
|
||||
impl Syscall<'_> {
|
||||
/// Create a kernel managed debuglog reader or writer.
|
||||
/// Create a kernel managed debuglog reader or writer.
|
||||
pub fn sys_debuglog_create(
|
||||
&self,
|
||||
rsrc: HandleValue,
|
||||
|
@ -32,7 +32,7 @@ impl Syscall<'_> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Write log entry to debuglog.
|
||||
/// Write log entry to debuglog.
|
||||
pub fn sys_debuglog_write(
|
||||
&self,
|
||||
handle_value: HandleValue,
|
||||
|
@ -54,15 +54,15 @@ 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(())
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
/// Read log entries from debuglog.
|
||||
/// Read log entries from debuglog.
|
||||
pub fn sys_debuglog_read(
|
||||
&self,
|
||||
handle_value: HandleValue,
|
||||
|
|
|
@ -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::*},
|
||||
};
|
||||
|
||||
|
@ -16,7 +16,7 @@ const ZX_CLOCK_UTC: u32 = 1;
|
|||
const ZX_CLOCK_THREAD: u32 = 2;
|
||||
|
||||
impl Syscall<'_> {
|
||||
/// Create a new clock object.
|
||||
/// Create a new clock object.
|
||||
pub fn sys_clock_create(
|
||||
&self,
|
||||
_options: u64,
|
||||
|
@ -27,10 +27,10 @@ impl Syscall<'_> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Acquire the current time.
|
||||
///
|
||||
/// + Returns the current time of clock_id via `time`.
|
||||
/// + Returns whether `clock_id` was valid.
|
||||
/// Acquire the current time.
|
||||
///
|
||||
/// + Returns the current time of clock_id via `time`.
|
||||
/// + Returns whether `clock_id` was valid.
|
||||
pub fn sys_clock_get(&self, clock_id: u32, mut time: UserOutPtr<u64>) -> ZxResult {
|
||||
info!("clock.get: id={}", clock_id);
|
||||
match clock_id {
|
||||
|
@ -50,7 +50,7 @@ impl Syscall<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Perform a basic read of the clock.
|
||||
/// Perform a basic read of the clock.
|
||||
pub fn sys_clock_read(&self, handle: HandleValue, mut now: UserOutPtr<u64>) -> ZxResult {
|
||||
info!("clock.read: handle={:#x?}", handle);
|
||||
warn!("ignore clock handle");
|
||||
|
@ -89,16 +89,16 @@ impl Syscall<'_> {
|
|||
}
|
||||
|
||||
/// Sleep for some number of nanoseconds.
|
||||
///
|
||||
///
|
||||
/// A `deadline` value less than or equal to 0 immediately yields the thread.
|
||||
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,
|
||||
|
|
Loading…
Reference in New Issue