mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-08 21:06:48 +00:00
add qemu pci virtio-blk device and trap registers
This commit is contained in:
parent
528888e632
commit
964a7413cd
9
src/Cargo.lock
generated
9
src/Cargo.lock
generated
@ -100,6 +100,7 @@ dependencies = [
|
||||
"font8x8",
|
||||
"lazy_static",
|
||||
"linked_list_allocator",
|
||||
"pci",
|
||||
"spin 0.9.4",
|
||||
"uart_16550",
|
||||
"volatile",
|
||||
@ -168,6 +169,14 @@ dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pci"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/rcore-os/pci-rs#a4e7cea640f8a92ae4b51c6c51fee3f1f0317af2"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.43"
|
||||
|
@ -1,28 +1,24 @@
|
||||
use anyhow::anyhow;
|
||||
use std::{
|
||||
fs::OpenOptions,
|
||||
path::{Path, PathBuf},
|
||||
process::{Command, ExitStatus},
|
||||
time::Duration,
|
||||
};
|
||||
const RUN_ARGS: &[&str] = &[
|
||||
const COMMON_ARGS: &[&str] = &[
|
||||
"--no-reboot",
|
||||
"-s",
|
||||
"-device",
|
||||
"isa-debug-exit,iobase=0xf4,iosize=0x04",
|
||||
"-serial",
|
||||
"stdio",
|
||||
"-display",
|
||||
"none",
|
||||
];
|
||||
const TEST_ARGS: &[&str] = &[
|
||||
"-device",
|
||||
"isa-debug-exit,iobase=0xf4,iosize=0x04",
|
||||
"-device",
|
||||
"virtio-blk-pci,bus=pci.0,addr=0x6,drive=x0",
|
||||
"-serial",
|
||||
"stdio",
|
||||
"-display",
|
||||
"none",
|
||||
"--no-reboot",
|
||||
];
|
||||
|
||||
const RUN_ARGS: &[&str] = &["-s"];
|
||||
const TEST_ARGS: &[&str] = &[];
|
||||
const TEST_TIMEOUT_SECS: u64 = 10;
|
||||
fn main() -> anyhow::Result<()> {
|
||||
let mut args = std::env::args().skip(1); // skip executable name
|
||||
@ -53,8 +49,13 @@ fn main() -> anyhow::Result<()> {
|
||||
.arg(format!("format=raw,file={}", bios.display()));
|
||||
|
||||
let binary_kind = runner_utils::binary_kind(&kernel_binary_path);
|
||||
let mut args = COMMON_ARGS.clone().to_vec();
|
||||
args.push("-drive");
|
||||
let binding = create_fs_image(kernel_binary_path.as_path())?;
|
||||
args.push(binding.as_str());
|
||||
if binary_kind.is_test() {
|
||||
run_cmd.args(TEST_ARGS);
|
||||
args.append(&mut TEST_ARGS.to_vec());
|
||||
run_cmd.args(args);
|
||||
|
||||
let exit_status = run_test_command(run_cmd)?;
|
||||
match exit_status.code() {
|
||||
@ -62,7 +63,8 @@ fn main() -> anyhow::Result<()> {
|
||||
other => return Err(anyhow!("Test failed (exit code: {:?})", other)),
|
||||
}
|
||||
} else {
|
||||
run_cmd.args(RUN_ARGS);
|
||||
args.append(&mut RUN_ARGS.to_vec());
|
||||
run_cmd.args(args);
|
||||
|
||||
let exit_status = run_cmd.status()?;
|
||||
if !exit_status.success() {
|
||||
@ -72,6 +74,29 @@ fn main() -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn create_fs_image(path: &Path) -> anyhow::Result<String> {
|
||||
let mut fs_img_path = path.parent().unwrap().to_str().unwrap().to_string();
|
||||
fs_img_path.push_str("/fs.img");
|
||||
let path = Path::new(fs_img_path.as_str());
|
||||
if path.exists() {
|
||||
return Ok(format!(
|
||||
"file={},if=none,format=raw,id=x0",
|
||||
fs_img_path.as_str()
|
||||
));
|
||||
}
|
||||
let f = OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.create(true)
|
||||
.open(fs_img_path.as_str())?;
|
||||
// 64MiB
|
||||
f.set_len(1 * 1024 * 1024).unwrap();
|
||||
Ok(format!(
|
||||
"file={},if=none,format=raw,id=x0",
|
||||
fs_img_path.as_str()
|
||||
))
|
||||
}
|
||||
|
||||
pub fn create_disk_images(kernel_binary_path: &Path) -> PathBuf {
|
||||
let bootloader_manifest_path = bootloader_locator::locate_bootloader("bootloader").unwrap();
|
||||
let kernel_manifest_path = locate_cargo_manifest::locate_manifest().unwrap();
|
||||
|
@ -15,7 +15,7 @@ linked_list_allocator = "0.9.0"
|
||||
bootloader = {version="0.10.12"}
|
||||
font8x8 = { version = "0.2.5", default-features = false, features = ["unicode"]}
|
||||
uart_16550 = "0.2.0"
|
||||
|
||||
pci = { git = "https://github.com/rcore-os/pci-rs" }
|
||||
|
||||
[dependencies.lazy_static]
|
||||
version = "1.0"
|
||||
|
@ -27,6 +27,16 @@ pub struct CpuContext {
|
||||
pub gp_regs: GpRegs,
|
||||
pub fs_base: u64,
|
||||
pub fp_regs: FpRegs,
|
||||
pub trap_information: Option<TrapInformation>,
|
||||
}
|
||||
#[derive(Clone, Default, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct TrapInformation {
|
||||
pub cr2: u64,
|
||||
pub id: u64,
|
||||
pub err: u64,
|
||||
pub cs: u64,
|
||||
pub ss: u64,
|
||||
}
|
||||
|
||||
/// The general-purpose registers of CPU.
|
||||
@ -57,27 +67,28 @@ impl From<SyscallFrame> for CpuContext {
|
||||
fn from(syscall: SyscallFrame) -> Self {
|
||||
Self {
|
||||
gp_regs: GpRegs {
|
||||
r8: syscall.caller.r8 as u64,
|
||||
r9: syscall.caller.r9 as u64,
|
||||
r10: syscall.caller.r10 as u64,
|
||||
r11: syscall.caller.r11 as u64,
|
||||
r12: syscall.callee.r12 as u64,
|
||||
r13: syscall.callee.r13 as u64,
|
||||
r14: syscall.callee.r14 as u64,
|
||||
r15: syscall.callee.r15 as u64,
|
||||
rdi: syscall.caller.rdi as u64,
|
||||
rsi: syscall.caller.rsi as u64,
|
||||
rbp: syscall.callee.rbp as u64,
|
||||
rbx: syscall.callee.rbx as u64,
|
||||
rdx: syscall.caller.rdx as u64,
|
||||
rax: syscall.caller.rax as u64,
|
||||
rcx: syscall.caller.rcx as u64,
|
||||
rsp: syscall.callee.rsp as u64,
|
||||
rip: syscall.caller.rcx as u64,
|
||||
r8: syscall.caller.r8,
|
||||
r9: syscall.caller.r9,
|
||||
r10: syscall.caller.r10,
|
||||
r11: syscall.caller.r11,
|
||||
r12: syscall.callee.r12,
|
||||
r13: syscall.callee.r13,
|
||||
r14: syscall.callee.r14,
|
||||
r15: syscall.callee.r15,
|
||||
rdi: syscall.caller.rdi,
|
||||
rsi: syscall.caller.rsi,
|
||||
rbp: syscall.callee.rbp,
|
||||
rbx: syscall.callee.rbx,
|
||||
rdx: syscall.caller.rdx,
|
||||
rax: syscall.caller.rax,
|
||||
rcx: syscall.caller.rcx,
|
||||
rsp: syscall.callee.rsp,
|
||||
rip: syscall.caller.rcx,
|
||||
rflag: 0,
|
||||
},
|
||||
fs_base: 0,
|
||||
fp_regs: FpRegs::default(),
|
||||
trap_information: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -86,24 +97,24 @@ impl Into<SyscallFrame> for CpuContext {
|
||||
fn into(self) -> SyscallFrame {
|
||||
SyscallFrame {
|
||||
caller: CallerRegs {
|
||||
rax: self.gp_regs.rax as usize,
|
||||
rcx: self.gp_regs.rcx as usize,
|
||||
rdx: self.gp_regs.rdx as usize,
|
||||
rsi: self.gp_regs.rsi as usize,
|
||||
rdi: self.gp_regs.rdi as usize,
|
||||
r8: self.gp_regs.r8 as usize,
|
||||
r9: self.gp_regs.r9 as usize,
|
||||
r10: self.gp_regs.r10 as usize,
|
||||
r11: self.gp_regs.r11 as usize,
|
||||
rax: self.gp_regs.rax,
|
||||
rcx: self.gp_regs.rcx,
|
||||
rdx: self.gp_regs.rdx,
|
||||
rsi: self.gp_regs.rsi,
|
||||
rdi: self.gp_regs.rdi,
|
||||
r8: self.gp_regs.r8,
|
||||
r9: self.gp_regs.r9,
|
||||
r10: self.gp_regs.r10,
|
||||
r11: self.gp_regs.r11,
|
||||
},
|
||||
callee: CalleeRegs {
|
||||
rsp: self.gp_regs.rsp as usize,
|
||||
rbx: self.gp_regs.rbx as usize,
|
||||
rbp: self.gp_regs.rbp as usize,
|
||||
r12: self.gp_regs.r12 as usize,
|
||||
r13: self.gp_regs.r13 as usize,
|
||||
r14: self.gp_regs.r14 as usize,
|
||||
r15: self.gp_regs.r15 as usize,
|
||||
rsp: self.gp_regs.rsp,
|
||||
rbx: self.gp_regs.rbx,
|
||||
rbp: self.gp_regs.rbp,
|
||||
r12: self.gp_regs.r12,
|
||||
r13: self.gp_regs.r13,
|
||||
r14: self.gp_regs.r14,
|
||||
r15: self.gp_regs.r15,
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -113,52 +124,70 @@ impl From<TrapFrame> for CpuContext {
|
||||
fn from(trap: TrapFrame) -> Self {
|
||||
Self {
|
||||
gp_regs: GpRegs {
|
||||
r8: trap.regs.r8 as u64,
|
||||
r9: trap.regs.r9 as u64,
|
||||
r10: trap.regs.r10 as u64,
|
||||
r11: trap.regs.r11 as u64,
|
||||
r12: trap.id as u64,
|
||||
r13: trap.err as u64,
|
||||
r14: trap.cs as u64,
|
||||
r15: trap.ss as u64,
|
||||
rdi: trap.regs.rdi as u64,
|
||||
rsi: trap.regs.rsi as u64,
|
||||
rbp: 0 as u64,
|
||||
rbx: 0 as u64,
|
||||
rdx: trap.regs.rdx as u64,
|
||||
rax: trap.regs.rax as u64,
|
||||
rcx: trap.regs.rcx as u64,
|
||||
rsp: trap.rsp as u64,
|
||||
rip: trap.rip as u64,
|
||||
rflag: trap.rflags as u64,
|
||||
r8: trap.caller.r8,
|
||||
r9: trap.caller.r9,
|
||||
r10: trap.caller.r10,
|
||||
r11: trap.caller.r11,
|
||||
r12: trap.callee.r12,
|
||||
r13: trap.callee.r13,
|
||||
r14: trap.callee.r14,
|
||||
r15: trap.callee.r15,
|
||||
rdi: trap.caller.rdi,
|
||||
rsi: trap.caller.rsi,
|
||||
rbp: trap.callee.rbp,
|
||||
rbx: trap.callee.rbx,
|
||||
rdx: trap.caller.rdx,
|
||||
rax: trap.caller.rax,
|
||||
rcx: trap.caller.rcx,
|
||||
rsp: trap.rsp,
|
||||
rip: trap.rip,
|
||||
rflag: trap.rflags,
|
||||
},
|
||||
fs_base: 0,
|
||||
fp_regs: FpRegs::default(),
|
||||
trap_information: Some(TrapInformation {
|
||||
cr2: trap.cr2,
|
||||
id: trap.id,
|
||||
err: trap.err,
|
||||
cs: trap.cs,
|
||||
ss: trap.ss,
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<TrapFrame> for CpuContext {
|
||||
fn into(self) -> TrapFrame {
|
||||
let trap_information = self.trap_information.unwrap();
|
||||
TrapFrame {
|
||||
regs: CallerRegs {
|
||||
rax: self.gp_regs.rax as usize,
|
||||
rcx: self.gp_regs.rcx as usize,
|
||||
rdx: self.gp_regs.rdx as usize,
|
||||
rsi: self.gp_regs.rsi as usize,
|
||||
rdi: self.gp_regs.rdi as usize,
|
||||
r8: self.gp_regs.r8 as usize,
|
||||
r9: self.gp_regs.r9 as usize,
|
||||
r10: self.gp_regs.r10 as usize,
|
||||
r11: self.gp_regs.r11 as usize,
|
||||
caller: CallerRegs {
|
||||
rax: self.gp_regs.rax,
|
||||
rcx: self.gp_regs.rcx,
|
||||
rdx: self.gp_regs.rdx,
|
||||
rsi: self.gp_regs.rsi,
|
||||
rdi: self.gp_regs.rdi,
|
||||
r8: self.gp_regs.r8,
|
||||
r9: self.gp_regs.r9,
|
||||
r10: self.gp_regs.r10,
|
||||
r11: self.gp_regs.r11,
|
||||
},
|
||||
id: self.gp_regs.r12 as usize,
|
||||
err: self.gp_regs.r13 as usize,
|
||||
rip: self.gp_regs.rip as usize,
|
||||
cs: self.gp_regs.r14 as usize,
|
||||
rflags: self.gp_regs.rflag as usize,
|
||||
rsp: self.gp_regs.rsp as usize,
|
||||
ss: self.gp_regs.r15 as usize,
|
||||
callee: CalleeRegs {
|
||||
rsp: self.gp_regs.rsp,
|
||||
rbx: self.gp_regs.rbx,
|
||||
rbp: self.gp_regs.rbp,
|
||||
r12: self.gp_regs.r12,
|
||||
r13: self.gp_regs.r13,
|
||||
r14: self.gp_regs.r14,
|
||||
r15: self.gp_regs.r15,
|
||||
},
|
||||
id: trap_information.id,
|
||||
err: trap_information.err,
|
||||
cr2: trap_information.cr2,
|
||||
rip: self.gp_regs.rip,
|
||||
cs: trap_information.cs,
|
||||
rflags: self.gp_regs.rflag,
|
||||
rsp: self.gp_regs.rsp,
|
||||
ss: trap_information.ss,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
5
src/kxos-frame/src/drivers/mod.rs
Normal file
5
src/kxos-frame/src/drivers/mod.rs
Normal file
@ -0,0 +1,5 @@
|
||||
mod pci;
|
||||
|
||||
pub fn init() {
|
||||
pci::init();
|
||||
}
|
62
src/kxos-frame/src/drivers/pci.rs
Normal file
62
src/kxos-frame/src/drivers/pci.rs
Normal file
@ -0,0 +1,62 @@
|
||||
use crate::*;
|
||||
use pci::*;
|
||||
|
||||
const PCI_COMMAND: u16 = 0x04;
|
||||
const PCI_CAP_PTR: u16 = 0x34;
|
||||
const PCI_INTERRUPT_LINE: u16 = 0x3c;
|
||||
const PCI_INTERRUPT_PIN: u16 = 0x3d;
|
||||
|
||||
const PCI_MSI_CTRL_CAP: u16 = 0x00;
|
||||
const PCI_MSI_ADDR: u16 = 0x04;
|
||||
const PCI_MSI_UPPER_ADDR: u16 = 0x08;
|
||||
const PCI_MSI_DATA_32: u16 = 0x08;
|
||||
const PCI_MSI_DATA_64: u16 = 0x0C;
|
||||
|
||||
const PCI_CAP_ID_MSI: u8 = 0x05;
|
||||
|
||||
struct PortOpsImpl;
|
||||
|
||||
impl PortOps for PortOpsImpl {
|
||||
unsafe fn read8(&self, port: u16) -> u8 {
|
||||
x86_64_util::in8(port)
|
||||
}
|
||||
unsafe fn read16(&self, port: u16) -> u16 {
|
||||
x86_64_util::in16(port)
|
||||
}
|
||||
unsafe fn read32(&self, port: u16) -> u32 {
|
||||
x86_64_util::in32(port)
|
||||
}
|
||||
unsafe fn write8(&self, port: u16, val: u8) {
|
||||
x86_64_util::out8(port, val);
|
||||
}
|
||||
unsafe fn write16(&self, port: u16, val: u16) {
|
||||
x86_64_util::out16(port, val);
|
||||
}
|
||||
unsafe fn write32(&self, port: u16, val: u32) {
|
||||
x86_64_util::out32(port, val);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init() {
|
||||
for dev in unsafe { scan_bus(&PortOpsImpl, CSpaceAccessMethod::IO) } {
|
||||
info!(
|
||||
"pci: {:02x}:{:02x}.{} {:#x} {:#x} ({} {}) irq: {}:{:?}",
|
||||
dev.loc.bus,
|
||||
dev.loc.device,
|
||||
dev.loc.function,
|
||||
dev.id.vendor_id,
|
||||
dev.id.device_id,
|
||||
dev.id.class,
|
||||
dev.id.subclass,
|
||||
dev.pic_interrupt_line,
|
||||
dev.interrupt_pin
|
||||
);
|
||||
if dev.id.vendor_id == 0x1af4
|
||||
&& (dev.id.device_id == 0x1001 || dev.id.device_id == 0x1042)
|
||||
&& dev.id.class == 0x01
|
||||
{
|
||||
// virtio block device mass storage
|
||||
info!("found virtio pci block device");
|
||||
}
|
||||
}
|
||||
}
|
@ -16,6 +16,7 @@ pub(crate) mod cell;
|
||||
pub mod config;
|
||||
pub mod cpu;
|
||||
pub mod device;
|
||||
pub(crate) mod drivers;
|
||||
mod error;
|
||||
pub mod log;
|
||||
pub(crate) mod mm;
|
||||
@ -75,6 +76,7 @@ pub fn init(boot_info: &'static mut BootInfo) {
|
||||
if !memory_init {
|
||||
panic!("memory init failed");
|
||||
}
|
||||
drivers::init();
|
||||
unsafe {
|
||||
for i in 0..256 {
|
||||
IRQ_CALLBACK_LIST.push(IrqLine::acquire(i as u8).on_active(general_handler))
|
||||
@ -82,9 +84,7 @@ pub fn init(boot_info: &'static mut BootInfo) {
|
||||
}
|
||||
}
|
||||
fn general_handler(trap_frame: TrapFrame) {
|
||||
println!("{:?}", trap_frame);
|
||||
println!("rip = 0x{:x}", trap_frame.rip);
|
||||
panic!("couldn't handler trap right now");
|
||||
debug!("TrapFrame:{:#x?}", trap_frame);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
@ -69,10 +69,9 @@ lazy_static! {
|
||||
};
|
||||
task.task_inner.exclusive_access().task_status = TaskStatus::Runnable;
|
||||
task.task_inner.exclusive_access().ctx.rip = context_switch_to_user_space as usize;
|
||||
task.task_inner.exclusive_access().ctx.regs.rsp = task.kstack.frame.end_pa().unwrap().kvaddr().0
|
||||
as usize
|
||||
task.task_inner.exclusive_access().ctx.regs.rsp = (task.kstack.frame.end_pa().unwrap().kvaddr().0
|
||||
- size_of::<usize>()
|
||||
- size_of::<SyscallFrame>();
|
||||
- size_of::<SyscallFrame>()) as u64;
|
||||
task
|
||||
});
|
||||
}
|
||||
@ -172,16 +171,15 @@ impl Task {
|
||||
result.task_inner.exclusive_access().task_status = TaskStatus::Runnable;
|
||||
result.task_inner.exclusive_access().ctx.rip = kernel_task_entry as usize;
|
||||
result.task_inner.exclusive_access().ctx.regs.rsp =
|
||||
result.kstack.frame.end_pa().unwrap().kvaddr().0 as usize
|
||||
(result.kstack.frame.end_pa().unwrap().kvaddr().0
|
||||
- size_of::<usize>()
|
||||
- size_of::<SyscallFrame>();
|
||||
- size_of::<SyscallFrame>()) as u64;
|
||||
|
||||
let arc_self = Arc::new(result);
|
||||
switch_to_task(arc_self.clone());
|
||||
Ok(arc_self)
|
||||
}
|
||||
|
||||
/// create a new task data structure without schedule it
|
||||
pub fn new<F, T>(
|
||||
task_fn: F,
|
||||
task_data: T,
|
||||
@ -217,14 +215,13 @@ impl Task {
|
||||
result.task_inner.exclusive_access().task_status = TaskStatus::Runnable;
|
||||
result.task_inner.exclusive_access().ctx.rip = kernel_task_entry as usize;
|
||||
result.task_inner.exclusive_access().ctx.regs.rsp =
|
||||
result.kstack.frame.end_pa().unwrap().kvaddr().0 as usize
|
||||
(result.kstack.frame.end_pa().unwrap().kvaddr().0
|
||||
- size_of::<usize>()
|
||||
- size_of::<SyscallFrame>();
|
||||
- size_of::<SyscallFrame>()) as u64;
|
||||
|
||||
Ok(Arc::new(result))
|
||||
}
|
||||
|
||||
/// send the task to schedule
|
||||
pub fn send_to_scheduler(self: &Arc<Self>) {
|
||||
switch_to_task(self.clone());
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ pub(crate) extern "C" fn trap_handler(f: &'static mut TrapFrame) {
|
||||
}
|
||||
}
|
||||
|
||||
fn is_from_kernel(cs: usize) -> bool {
|
||||
fn is_from_kernel(cs: u64) -> bool {
|
||||
if cs & 0x3 == 0 {
|
||||
true
|
||||
} else {
|
||||
|
@ -12,27 +12,27 @@ core::arch::global_asm!(include_str!("vector.S"));
|
||||
#[derive(Debug, Default, Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct CallerRegs {
|
||||
pub rax: usize,
|
||||
pub rcx: usize,
|
||||
pub rdx: usize,
|
||||
pub rsi: usize,
|
||||
pub rdi: usize,
|
||||
pub r8: usize,
|
||||
pub r9: usize,
|
||||
pub r10: usize,
|
||||
pub r11: usize,
|
||||
pub rax: u64,
|
||||
pub rcx: u64,
|
||||
pub rdx: u64,
|
||||
pub rsi: u64,
|
||||
pub rdi: u64,
|
||||
pub r8: u64,
|
||||
pub r9: u64,
|
||||
pub r10: u64,
|
||||
pub r11: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct CalleeRegs {
|
||||
pub rsp: usize,
|
||||
pub rbx: usize,
|
||||
pub rbp: usize,
|
||||
pub r12: usize,
|
||||
pub r13: usize,
|
||||
pub r14: usize,
|
||||
pub r15: usize,
|
||||
pub rsp: u64,
|
||||
pub rbx: u64,
|
||||
pub rbp: u64,
|
||||
pub r12: u64,
|
||||
pub r13: u64,
|
||||
pub r14: u64,
|
||||
pub r15: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy)]
|
||||
@ -45,15 +45,18 @@ pub struct SyscallFrame {
|
||||
#[derive(Debug, Default, Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct TrapFrame {
|
||||
pub regs: CallerRegs,
|
||||
pub id: usize,
|
||||
pub err: usize,
|
||||
pub cr2: u64,
|
||||
pub caller: CallerRegs,
|
||||
// do not use the rsp inside the callee, use another rsp instead
|
||||
pub callee: CalleeRegs,
|
||||
pub id: u64,
|
||||
pub err: u64,
|
||||
// Pushed by CPU
|
||||
pub rip: usize,
|
||||
pub cs: usize,
|
||||
pub rflags: usize,
|
||||
pub rsp: usize,
|
||||
pub ss: usize,
|
||||
pub rip: u64,
|
||||
pub cs: u64,
|
||||
pub rflags: u64,
|
||||
pub rsp: u64,
|
||||
pub ss: u64,
|
||||
}
|
||||
|
||||
const TSS_SIZE: usize = 104;
|
||||
|
@ -31,20 +31,40 @@ TSS:
|
||||
|
||||
.global __trap_entry
|
||||
__trap_entry:
|
||||
# 保存所有的调用者保存寄存器
|
||||
# 保存寄存器
|
||||
push r15
|
||||
push r14
|
||||
push r13
|
||||
push r12
|
||||
push rbp
|
||||
push rbx
|
||||
mov rdi, 0
|
||||
push rdi
|
||||
save
|
||||
# save cr2
|
||||
mov rdi, cr2
|
||||
push rdi
|
||||
# 将栈指针当成参数传入trap_handler
|
||||
mov rdi, rsp
|
||||
call trap_handler
|
||||
__trap_return:
|
||||
# judge whether the trap from kernel mode
|
||||
mov rax, [rsp + 96] # 96 = offsetof(TrapFrame, cs)
|
||||
mov rax, [rsp + 160] # 160 = offsetof(TrapFrame, cs)
|
||||
and rax, 0x3
|
||||
jz __from_kernel
|
||||
lea rax, [rsp + 128] # prepare new TSS.sp0, 128 = sizeof(TrapFrame)
|
||||
lea rax, [rsp + 192] # prepare new TSS.sp0, 192 = sizeof(TrapFrame)
|
||||
mov [TSS + rip + 4], rax
|
||||
__from_kernel:
|
||||
add rsp, 8 # skip cr2
|
||||
restore
|
||||
add rsp,8 # skip rsp in callee
|
||||
pop rbx
|
||||
pop rbp
|
||||
pop r12
|
||||
pop r13
|
||||
pop r14
|
||||
pop r15
|
||||
|
||||
add rsp, 16 # skip TrapFrame.err and id
|
||||
iretq
|
||||
|
||||
@ -104,4 +124,3 @@ trap_switch_to_user_space: # (cpu_context: *CpuContext,reg: *TrapFrame)
|
||||
jmp __trap_return
|
||||
|
||||
|
||||
|
||||
|
@ -114,9 +114,9 @@ impl<'a> UserMode<'a> {
|
||||
self.user_space.vm_space().activate();
|
||||
}
|
||||
if !self.executed {
|
||||
self.current.syscall_frame().caller.rcx = self.user_space.cpu_ctx.gp_regs.rip as usize;
|
||||
self.current.syscall_frame().callee.rsp = self.user_space.cpu_ctx.gp_regs.rsp as usize;
|
||||
self.current.syscall_frame().caller.rax = self.user_space.cpu_ctx.gp_regs.rax as usize;
|
||||
self.current.syscall_frame().caller.rcx = self.user_space.cpu_ctx.gp_regs.rip;
|
||||
self.current.syscall_frame().callee.rsp = self.user_space.cpu_ctx.gp_regs.rsp;
|
||||
self.current.syscall_frame().caller.rax = self.user_space.cpu_ctx.gp_regs.rax;
|
||||
self.executed = true;
|
||||
} else {
|
||||
if self.current.inner_exclusive_access().is_from_trap {
|
||||
@ -144,6 +144,8 @@ impl<'a> UserMode<'a> {
|
||||
self.context = CpuContext::from(*self.current.syscall_frame());
|
||||
debug!("[kernel] syscall id:{}", self.context.gp_regs.rax);
|
||||
debug!("[kernel] rsp: 0x{:x}", self.context.gp_regs.rsp);
|
||||
debug!("[kernel] rcx: 0x{:x}", self.context.gp_regs.rcx);
|
||||
debug!("[kernel] rip: 0x{:x}", self.context.gp_regs.rip);
|
||||
UserEvent::Syscall
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user