mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-30 12:13:56 +00:00
Refactor CpuContext; impl CpuException
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
fbcfbe19d1
commit
4c7449d2c1
@ -11,6 +11,8 @@ const COMMON_ARGS: &[&str] = &[
|
||||
"--no-reboot",
|
||||
"-cpu",
|
||||
"Icelake-Server",
|
||||
"-m",
|
||||
"1G",
|
||||
"-device",
|
||||
"isa-debug-exit,iobase=0xf4,iosize=0x04",
|
||||
"-device",
|
||||
|
@ -11,17 +11,18 @@ cfg-if = "1.0"
|
||||
spin = "0.9.4"
|
||||
volatile = { version = "0.4.5", features = ["unstable"] }
|
||||
buddy_system_allocator = "0.9.0"
|
||||
pod = { git = "https://github.com/sdww0/POD", rev = "7fa2ed2" }
|
||||
pod = { git = "https://github.com/jinzhao-dev/pod", rev = "7fa2ed2" }
|
||||
align_ext = { path = "../align_ext" }
|
||||
intrusive-collections = "0.9.5"
|
||||
log = "0.4"
|
||||
lazy_static = { version = "1.0", features = ["spin_no_std"] }
|
||||
trapframe = { git = "https://github.com/sdww0/trapframe-rs", rev = "94fc010" }
|
||||
trapframe = { git = "https://github.com/sdww0/trapframe-rs", rev = "4234db5" }
|
||||
|
||||
[target.x86_64-custom.dependencies]
|
||||
limine = { version = "0.1.10", features = ["into-uuid"] }
|
||||
x86_64 = "0.14.2"
|
||||
x86 = "0.52.0"
|
||||
acpi = "4.1.1"
|
||||
aml = "0.16.3"
|
||||
|
||||
[features]
|
||||
|
@ -1,20 +1,5 @@
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub mod x86;
|
||||
|
||||
/// Call before all the resources have been initialized
|
||||
pub(crate) fn before_all_init() {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
x86::before_all_init();
|
||||
}
|
||||
|
||||
/// Call after all the resources have been initialized
|
||||
pub(crate) fn after_all_init() {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
x86::after_all_init();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn interrupts_ack() {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
x86::interrupts_ack();
|
||||
}
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub use self::x86::*;
|
||||
|
@ -15,6 +15,7 @@ pub fn init() {
|
||||
.get()
|
||||
.expect("Not found HHDM Features");
|
||||
assert_eq!(config::PHYS_OFFSET as u64, response.offset);
|
||||
STACK_REQUEST.get_response().get().unwrap();
|
||||
}
|
||||
|
||||
static BOOTLOADER_INFO_REQUEST: LimineBootInfoRequest = LimineBootInfoRequest::new(0);
|
||||
|
@ -4,10 +4,13 @@ use core::arch::x86_64::{_fxrstor, _fxsave};
|
||||
use core::fmt::Debug;
|
||||
use core::mem::MaybeUninit;
|
||||
|
||||
use trapframe::{GeneralRegs, UserContext};
|
||||
use trapframe::{GeneralRegs, UserContext as RawUserContext};
|
||||
|
||||
use log::debug;
|
||||
use pod::Pod;
|
||||
use x86_64::registers::rflags::RFlags;
|
||||
|
||||
use crate::trap::call_irq_callback_functions;
|
||||
use crate::user::{UserContextApi, UserContextApiInternal, UserEvent};
|
||||
|
||||
/// Defines a CPU-local variable.
|
||||
#[macro_export]
|
||||
@ -31,8 +34,8 @@ pub fn this_cpu() -> u32 {
|
||||
/// Cpu context, including both general-purpose registers and floating-point registers.
|
||||
#[derive(Clone, Default, Copy, Debug)]
|
||||
#[repr(C)]
|
||||
pub struct CpuContext {
|
||||
pub(crate) user_context: UserContext,
|
||||
pub struct UserContext {
|
||||
pub(crate) user_context: RawUserContext,
|
||||
pub fp_regs: FpRegs,
|
||||
/// trap information, this field is all zero when it is syscall
|
||||
pub trap_information: TrapInformation,
|
||||
@ -46,19 +49,241 @@ pub struct TrapInformation {
|
||||
pub err: usize,
|
||||
}
|
||||
|
||||
impl CpuContext {
|
||||
pub fn general_regs(&self) -> GeneralRegs {
|
||||
self.user_context.general
|
||||
impl UserContext {
|
||||
pub fn general_regs(&self) -> &GeneralRegs {
|
||||
&self.user_context.general
|
||||
}
|
||||
|
||||
pub fn set_general_regs(&mut self, general_register: GeneralRegs) {
|
||||
self.user_context.general = general_register;
|
||||
pub fn general_regs_mut(&mut self) -> &mut GeneralRegs {
|
||||
&mut self.user_context.general
|
||||
}
|
||||
}
|
||||
|
||||
impl UserContextApiInternal for UserContext {
|
||||
fn execute(&mut self) -> crate::user::UserEvent {
|
||||
// set interrupt flag so that in user mode it can receive external interrupts
|
||||
// set ID flag which means cpu support CPUID instruction
|
||||
self.user_context.general.rflags |= (RFlags::INTERRUPT_FLAG | RFlags::ID).bits() as usize;
|
||||
|
||||
const SYSCALL_TRAPNUM: u16 = 0x100;
|
||||
// return when it is syscall or cpu exception type is Fault or Trap.
|
||||
loop {
|
||||
self.user_context.run();
|
||||
match CpuException::to_cpu_exception(self.user_context.trap_num as u16) {
|
||||
Some(exception) => {
|
||||
if exception.typ == CpuExceptionType::FaultOrTrap
|
||||
|| exception.typ == CpuExceptionType::Fault
|
||||
|| exception.typ == CpuExceptionType::Trap
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
None => {
|
||||
if self.user_context.trap_num as u16 == SYSCALL_TRAPNUM {
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
call_irq_callback_functions(&self.into_trap_frame());
|
||||
}
|
||||
|
||||
if self.user_context.trap_num as u16 != SYSCALL_TRAPNUM {
|
||||
self.trap_information = TrapInformation {
|
||||
cr2: unsafe { x86::controlregs::cr2() },
|
||||
id: self.user_context.trap_num,
|
||||
err: self.user_context.error_code,
|
||||
};
|
||||
UserEvent::Exception
|
||||
} else {
|
||||
crate::arch::irq::enable_interrupts();
|
||||
UserEvent::Syscall
|
||||
}
|
||||
}
|
||||
|
||||
fn into_trap_frame(&self) -> trapframe::TrapFrame {
|
||||
trapframe::TrapFrame {
|
||||
rax: self.user_context.general.rax,
|
||||
rbx: self.user_context.general.rbx,
|
||||
rcx: self.user_context.general.rcx,
|
||||
rdx: self.user_context.general.rdx,
|
||||
rsi: self.user_context.general.rsi,
|
||||
rdi: self.user_context.general.rdi,
|
||||
rbp: self.user_context.general.rbp,
|
||||
rsp: self.user_context.general.rsp,
|
||||
r8: self.user_context.general.r8,
|
||||
r9: self.user_context.general.r9,
|
||||
r10: self.user_context.general.r10,
|
||||
r11: self.user_context.general.r11,
|
||||
r12: self.user_context.general.r12,
|
||||
r13: self.user_context.general.r13,
|
||||
r14: self.user_context.general.r14,
|
||||
r15: self.user_context.general.r15,
|
||||
_pad: 0,
|
||||
trap_num: self.user_context.trap_num,
|
||||
error_code: self.user_context.error_code,
|
||||
rip: self.user_context.general.rip,
|
||||
cs: 0,
|
||||
rflags: self.user_context.general.rflags,
|
||||
}
|
||||
}
|
||||
}
|
||||
/// As Osdev Wiki defines(https://wiki.osdev.org/Exceptions):
|
||||
/// CPU exceptions are classified as:
|
||||
///
|
||||
/// Faults: These can be corrected and the program may continue as if nothing happened.
|
||||
///
|
||||
/// Traps: Traps are reported immediately after the execution of the trapping instruction.
|
||||
///
|
||||
/// Aborts: Some severe unrecoverable error.
|
||||
///
|
||||
/// But there exists some vector which are special. Vector 1 can be both fault or trap and vector 2 is interrupt.
|
||||
/// So here we also define FaultOrTrap and Interrupt
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
pub enum CpuExceptionType {
|
||||
Fault,
|
||||
Trap,
|
||||
FaultOrTrap,
|
||||
Interrupt,
|
||||
Abort,
|
||||
Reserved,
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct CpuException {
|
||||
pub number: u16,
|
||||
pub typ: CpuExceptionType,
|
||||
}
|
||||
|
||||
// impl const PartialEq for CpuException{
|
||||
// fn eq(&self, other: &Self) -> bool {
|
||||
// self.number == other.number
|
||||
// }
|
||||
// }
|
||||
|
||||
/// Copy from: https://veykril.github.io/tlborm/decl-macros/building-blocks/counting.html#slice-length
|
||||
macro_rules! replace_expr {
|
||||
($_t:tt $sub:expr) => {
|
||||
$sub
|
||||
};
|
||||
}
|
||||
|
||||
/// Copy from: https://veykril.github.io/tlborm/decl-macros/building-blocks/counting.html#slice-length
|
||||
macro_rules! count_tts {
|
||||
($($tts:tt)*) => {<[()]>::len(&[$(replace_expr!($tts ())),*])};
|
||||
}
|
||||
|
||||
macro_rules! define_cpu_exception {
|
||||
( $([ $name: ident = $exception_num:tt, $exception_type:tt]),* ) => {
|
||||
const EXCEPTION_LIST : [CpuException;count_tts!($($name)*)] = [
|
||||
$($name,)*
|
||||
];
|
||||
$(
|
||||
pub const $name : CpuException = CpuException{
|
||||
number: $exception_num,
|
||||
typ: CpuExceptionType::$exception_type,
|
||||
};
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
// We also defined the RESERVED Exception so that we can easily use the index of EXCEPTION_LIST to get the Exception
|
||||
define_cpu_exception!(
|
||||
[DIVIDE_BY_ZERO = 0, Fault],
|
||||
[DEBUG = 1, FaultOrTrap],
|
||||
[NON_MASKABLE_INTERRUPT = 2, Interrupt],
|
||||
[BREAKPOINT = 3, Trap],
|
||||
[OVERFLOW = 4, Trap],
|
||||
[BOUND_RANGE_EXCEEDED = 5, Fault],
|
||||
[INVALID_OPCODE = 6, Fault],
|
||||
[DEVICE_NOT_AVAILABLE = 7, Fault],
|
||||
[DOUBLE_FAULT = 8, Abort],
|
||||
[COPROCESSOR_SEGMENT_OVERRUN = 9, Fault],
|
||||
[INVAILD_TSS = 10, Fault],
|
||||
[SEGMENT_NOT_PRESENT = 11, Fault],
|
||||
[STACK_SEGMENT_FAULT = 12, Fault],
|
||||
[GENERAL_PROTECTION_FAULT = 13, Fault],
|
||||
[PAGE_FAULT = 14, Fault],
|
||||
[RESERVED_15 = 15, Reserved],
|
||||
[X87_FLOATING_POINT_EXCEPTION = 16, Fault],
|
||||
[ALIGNMENT_CHECK = 17, Fault],
|
||||
[MACHINE_CHECK = 18, Abort],
|
||||
[SIMD_FLOATING_POINT_EXCEPTION = 19, Fault],
|
||||
[VIRTUALIZATION_EXCEPTION = 20, Fault],
|
||||
[CONTROL_PROTECTION_EXCEPTION = 21, Fault],
|
||||
[RESERVED_22 = 22, Reserved],
|
||||
[RESERVED_23 = 23, Reserved],
|
||||
[RESERVED_24 = 24, Reserved],
|
||||
[RESERVED_25 = 25, Reserved],
|
||||
[RESERVED_26 = 26, Reserved],
|
||||
[RESERVED_27 = 27, Reserved],
|
||||
[HYPERVISOR_INJECTION_EXCEPTION = 28, Fault],
|
||||
[VMM_COMMUNICATION_EXCEPTION = 29, Fault],
|
||||
[SECURITY_EXCEPTION = 30, Fault],
|
||||
[RESERVED_31 = 31, Reserved]
|
||||
);
|
||||
|
||||
impl CpuException {
|
||||
pub fn is_cpu_exception(trap_num: u16) -> bool {
|
||||
trap_num < EXCEPTION_LIST.len() as u16
|
||||
}
|
||||
|
||||
pub fn to_cpu_exception(trap_num: u16) -> Option<&'static CpuException> {
|
||||
EXCEPTION_LIST.get(trap_num as usize)
|
||||
}
|
||||
}
|
||||
|
||||
impl UserContextApi for UserContext {
|
||||
fn trap_number(&self) -> usize {
|
||||
self.user_context.trap_num
|
||||
}
|
||||
|
||||
fn trap_error_code(&self) -> usize {
|
||||
self.user_context.error_code
|
||||
}
|
||||
|
||||
fn syscall_num(&self) -> usize {
|
||||
self.rax()
|
||||
}
|
||||
|
||||
fn syscall_ret(&self) -> usize {
|
||||
self.rax()
|
||||
}
|
||||
|
||||
fn set_syscall_ret(&mut self, ret: usize) {
|
||||
self.set_rax(ret);
|
||||
}
|
||||
|
||||
fn syscall_args(&self) -> [usize; 6] {
|
||||
[
|
||||
self.rdi(),
|
||||
self.rsi(),
|
||||
self.rdx(),
|
||||
self.r10(),
|
||||
self.r8(),
|
||||
self.r9(),
|
||||
]
|
||||
}
|
||||
|
||||
fn set_instruction_pointer(&mut self, ip: usize) {
|
||||
self.set_rip(ip);
|
||||
}
|
||||
|
||||
fn set_stack_pointer(&mut self, sp: usize) {
|
||||
self.set_rsp(sp)
|
||||
}
|
||||
|
||||
fn stack_pointer(&self) -> usize {
|
||||
self.rsp()
|
||||
}
|
||||
|
||||
fn instruction_pointer(&self) -> usize {
|
||||
self.rip()
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! cpu_context_impl_getter_setter {
|
||||
( $( [ $field: ident, $setter_name: ident] ),*) => {
|
||||
impl CpuContext {
|
||||
impl UserContext {
|
||||
$(
|
||||
#[inline(always)]
|
||||
pub fn $field(&self) -> usize {
|
||||
@ -97,10 +322,6 @@ cpu_context_impl_getter_setter!(
|
||||
[gsbase, set_gsbase]
|
||||
);
|
||||
|
||||
unsafe impl Pod for CpuContext {}
|
||||
unsafe impl Pod for TrapInformation {}
|
||||
unsafe impl Pod for FpRegs {}
|
||||
|
||||
/// The floating-point state of CPU.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[repr(C)]
|
||||
|
6
src/framework/jinux-frame/src/arch/x86/irq.rs
Normal file
6
src/framework/jinux-frame/src/arch/x86/irq.rs
Normal file
@ -0,0 +1,6 @@
|
||||
/// move interrupts instructions ..
|
||||
/// irq 32,256
|
||||
|
||||
pub(crate) fn enable_interrupts() {
|
||||
x86_64::instructions::interrupts::enable();
|
||||
}
|
@ -1,25 +1,14 @@
|
||||
mod boot;
|
||||
pub(crate) mod cpu;
|
||||
pub mod device;
|
||||
pub(crate) mod irq;
|
||||
mod kernel;
|
||||
pub(crate) mod mm;
|
||||
pub(crate) mod timer;
|
||||
|
||||
use alloc::fmt;
|
||||
use core::fmt::Write;
|
||||
use log::{debug, info};
|
||||
use trapframe::TrapFrame;
|
||||
use x86_64::registers::{
|
||||
rflags::RFlags,
|
||||
segmentation::{Segment64, FS},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
trap::call_irq_callback_functions,
|
||||
user::{UserEvent, UserMode, UserModeExecute},
|
||||
};
|
||||
|
||||
use self::cpu::TrapInformation;
|
||||
use log::info;
|
||||
|
||||
pub(crate) fn before_all_init() {
|
||||
enable_common_cpu_features();
|
||||
@ -47,90 +36,6 @@ pub(crate) fn interrupts_ack() {
|
||||
kernel::xapic::ack();
|
||||
}
|
||||
|
||||
impl<'a> UserModeExecute for UserMode<'a> {
|
||||
fn execute(&mut self) -> crate::user::UserEvent {
|
||||
unsafe {
|
||||
self.user_space.vm_space().activate();
|
||||
}
|
||||
if !self.executed {
|
||||
self.context = self.user_space.cpu_ctx;
|
||||
if self.context.user_context.general.rflags == 0 {
|
||||
self.context.user_context.general.rflags =
|
||||
((RFlags::INTERRUPT_FLAG | RFlags::ID).bits() | 0x2) as usize;
|
||||
}
|
||||
// write fsbase
|
||||
unsafe {
|
||||
FS::write_base(x86_64::VirtAddr::new(
|
||||
self.context.user_context.general.fsbase as u64,
|
||||
));
|
||||
}
|
||||
let fp_regs = self.context.fp_regs;
|
||||
if fp_regs.is_valid() {
|
||||
fp_regs.restore();
|
||||
}
|
||||
self.executed = true;
|
||||
} else {
|
||||
// write fsbase
|
||||
if FS::read_base().as_u64() != self.context.user_context.general.fsbase as u64 {
|
||||
debug!(
|
||||
"write fsbase: 0x{:x}",
|
||||
self.context.user_context.general.fsbase
|
||||
);
|
||||
unsafe {
|
||||
FS::write_base(x86_64::VirtAddr::new(
|
||||
self.context.user_context.general.fsbase as u64,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
self.context.user_context.run();
|
||||
let mut trap_frame;
|
||||
while self.context.user_context.trap_num >= 0x20
|
||||
&& self.context.user_context.trap_num < 0x100
|
||||
{
|
||||
trap_frame = TrapFrame {
|
||||
rax: self.context.user_context.general.rax,
|
||||
rbx: self.context.user_context.general.rbx,
|
||||
rcx: self.context.user_context.general.rcx,
|
||||
rdx: self.context.user_context.general.rdx,
|
||||
rsi: self.context.user_context.general.rsi,
|
||||
rdi: self.context.user_context.general.rdi,
|
||||
rbp: self.context.user_context.general.rbp,
|
||||
rsp: self.context.user_context.general.rsp,
|
||||
r8: self.context.user_context.general.r8,
|
||||
r9: self.context.user_context.general.r9,
|
||||
r10: self.context.user_context.general.r10,
|
||||
r11: self.context.user_context.general.r11,
|
||||
r12: self.context.user_context.general.r12,
|
||||
r13: self.context.user_context.general.r13,
|
||||
r14: self.context.user_context.general.r14,
|
||||
r15: self.context.user_context.general.r15,
|
||||
_pad: 0,
|
||||
trap_num: self.context.user_context.trap_num,
|
||||
error_code: self.context.user_context.error_code,
|
||||
rip: self.context.user_context.general.rip,
|
||||
cs: 0,
|
||||
rflags: self.context.user_context.general.rflags,
|
||||
};
|
||||
call_irq_callback_functions(&mut trap_frame);
|
||||
self.context.user_context.run();
|
||||
}
|
||||
// only syscall and irq < 32 will go back
|
||||
x86_64::instructions::interrupts::enable();
|
||||
self.context.user_context.general.fsbase = FS::read_base().as_u64() as usize;
|
||||
if self.context.user_context.trap_num != 0x100 {
|
||||
self.context.trap_information = TrapInformation {
|
||||
cr2: unsafe { x86::controlregs::cr2() },
|
||||
id: self.context.user_context.trap_num,
|
||||
err: self.context.user_context.error_code,
|
||||
};
|
||||
UserEvent::Exception
|
||||
} else {
|
||||
UserEvent::Syscall
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Stdout;
|
||||
|
||||
impl Write for Stdout {
|
||||
|
@ -2,11 +2,7 @@
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(target_arch = "x86_64")]{
|
||||
pub use crate::arch::x86::cpu::CpuContext;
|
||||
pub use crate::arch::x86::cpu::FpRegs;
|
||||
pub use crate::arch::x86::cpu::TrapInformation;
|
||||
pub use trapframe::GeneralRegs;
|
||||
pub use crate::arch::x86::cpu::num_cpus;
|
||||
pub use crate::arch::x86::cpu::this_cpu;
|
||||
pub use crate::arch::x86::cpu::*;
|
||||
}
|
||||
}
|
||||
|
@ -1,55 +1,24 @@
|
||||
use super::{irq::IRQ_LIST, *};
|
||||
use crate::cpu::CpuException;
|
||||
|
||||
use super::irq::IRQ_LIST;
|
||||
use trapframe::TrapFrame;
|
||||
|
||||
/// Only from kernel
|
||||
#[no_mangle]
|
||||
extern "sysv64" fn trap_handler(f: &mut TrapFrame) {
|
||||
if is_cpu_fault(f) {
|
||||
if CpuException::is_cpu_exception(f.trap_num as u16) {
|
||||
panic!("cannot handle kernel cpu fault now, information:{:#x?}", f);
|
||||
}
|
||||
call_irq_callback_functions(f);
|
||||
}
|
||||
|
||||
pub(crate) fn call_irq_callback_functions(f: &mut TrapFrame) {
|
||||
let irq_line = IRQ_LIST.get(f.trap_num as usize).unwrap();
|
||||
pub(crate) fn call_irq_callback_functions(trap_frame: &TrapFrame) {
|
||||
let irq_line = IRQ_LIST.get(trap_frame.trap_num as usize).unwrap();
|
||||
let callback_functions = irq_line.callback_list();
|
||||
for callback_function in callback_functions.iter() {
|
||||
callback_function.call(f);
|
||||
callback_function.call(trap_frame);
|
||||
}
|
||||
if f.trap_num >= 0x20 {
|
||||
if !CpuException::is_cpu_exception(trap_frame.trap_num as u16) {
|
||||
crate::arch::interrupts_ack();
|
||||
}
|
||||
}
|
||||
|
||||
/// As Osdev Wiki defines(https://wiki.osdev.org/Exceptions):
|
||||
/// CPU exceptions are classified as:
|
||||
|
||||
/// Faults: These can be corrected and the program may continue as if nothing happened.
|
||||
/// Traps: Traps are reported immediately after the execution of the trapping instruction.
|
||||
/// Aborts: Some severe unrecoverable error.
|
||||
|
||||
/// This function will determine a trap is a CPU faults.
|
||||
/// We will pass control to jinux-std if the trap is **faults**.
|
||||
pub fn is_cpu_fault(trap_frame: &TrapFrame) -> bool {
|
||||
match trap_frame.trap_num {
|
||||
DIVIDE_BY_ZERO
|
||||
| DEBUG
|
||||
| BOUND_RANGE_EXCEEDED
|
||||
| INVALID_OPCODE
|
||||
| DEVICE_NOT_AVAILABLE
|
||||
| INVAILD_TSS
|
||||
| SEGMENT_NOT_PRESENT
|
||||
| STACK_SEGMENT_FAULT
|
||||
| GENERAL_PROTECTION_FAULT
|
||||
| PAGE_FAULT
|
||||
| X87_FLOATING_POINT_EXCEPTION
|
||||
| ALIGNMENT_CHECK
|
||||
| SIMD_FLOATING_POINT_EXCEPTION
|
||||
| VIRTUALIZATION_EXCEPTION
|
||||
| CONTROL_PROTECTION_EXCEPTION
|
||||
| HYPERVISOR_INJECTION_EXCEPTION
|
||||
| VMM_COMMUNICATION_EXCEPTION
|
||||
| SECURITY_EXCEPTION => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
@ -11,40 +11,3 @@ pub(crate) fn init() {
|
||||
trapframe::init();
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! define_cpu_exception {
|
||||
( $( $name: ident = $exception_num: expr ),* ) => {
|
||||
$(
|
||||
pub const $name : usize = $exception_num;
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
define_cpu_exception!(
|
||||
DIVIDE_BY_ZERO = 0,
|
||||
DEBUG = 1,
|
||||
NON_MASKABLE_INTERRUPT = 2,
|
||||
BREAKPOINT = 3,
|
||||
OVERFLOW = 4,
|
||||
BOUND_RANGE_EXCEEDED = 5,
|
||||
INVALID_OPCODE = 6,
|
||||
DEVICE_NOT_AVAILABLE = 7,
|
||||
DOUBLE_FAULT = 8,
|
||||
COPROCESSOR_SEGMENT_OVERRUN = 9,
|
||||
INVAILD_TSS = 10,
|
||||
SEGMENT_NOT_PRESENT = 11,
|
||||
STACK_SEGMENT_FAULT = 12,
|
||||
GENERAL_PROTECTION_FAULT = 13,
|
||||
PAGE_FAULT = 14,
|
||||
// 15 reserved
|
||||
X87_FLOATING_POINT_EXCEPTION = 16,
|
||||
ALIGNMENT_CHECK = 17,
|
||||
MACHINE_CHECK = 18,
|
||||
SIMD_FLOATING_POINT_EXCEPTION = 19,
|
||||
VIRTUALIZATION_EXCEPTION = 20,
|
||||
CONTROL_PROTECTION_EXCEPTION = 21,
|
||||
// 22-27 reserved
|
||||
HYPERVISOR_INJECTION_EXCEPTION = 28,
|
||||
VMM_COMMUNICATION_EXCEPTION = 29,
|
||||
SECURITY_EXCEPTION = 30 // 31 reserved
|
||||
);
|
||||
|
@ -1,14 +1,10 @@
|
||||
//! User space.
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(target_arch = "x86_64")]{
|
||||
use crate::arch::x86::cpu::CpuContext;
|
||||
}
|
||||
}
|
||||
|
||||
use crate::cpu::UserContext;
|
||||
use crate::prelude::*;
|
||||
use crate::task::Task;
|
||||
use crate::vm::VmSpace;
|
||||
use trapframe::TrapFrame;
|
||||
|
||||
/// A user space.
|
||||
///
|
||||
@ -18,7 +14,7 @@ pub struct UserSpace {
|
||||
/// vm space
|
||||
vm_space: VmSpace,
|
||||
/// cpu context before entering user space
|
||||
pub cpu_ctx: CpuContext,
|
||||
init_ctx: UserContext,
|
||||
}
|
||||
|
||||
impl UserSpace {
|
||||
@ -26,11 +22,20 @@ impl UserSpace {
|
||||
///
|
||||
/// Each instance maintains a VM address space and the CPU state to enable
|
||||
/// execution in the user space.
|
||||
pub fn new(vm_space: VmSpace, cpu_ctx: CpuContext) -> Self {
|
||||
Self {
|
||||
vm_space: vm_space,
|
||||
cpu_ctx: cpu_ctx,
|
||||
}
|
||||
pub fn new(vm_space: VmSpace, init_ctx: UserContext) -> Self {
|
||||
Self { vm_space, init_ctx }
|
||||
}
|
||||
|
||||
pub fn instruction_pointer(&self) -> usize {
|
||||
self.init_ctx.instruction_pointer()
|
||||
}
|
||||
|
||||
pub fn stack_pointer(&self) -> usize {
|
||||
self.init_ctx.stack_pointer()
|
||||
}
|
||||
|
||||
pub fn syscall_ret(&self) -> usize {
|
||||
self.init_ctx.syscall_ret()
|
||||
}
|
||||
|
||||
/// Returns the VM address space.
|
||||
@ -53,18 +58,48 @@ impl UserSpace {
|
||||
}
|
||||
}
|
||||
|
||||
/// Specific architectures need to implement this trait so that UserMode tasks can be executed
|
||||
pub trait UserModeExecute {
|
||||
/// Starts executing in the user mode. Make sure current task is the task in `UserMode`.
|
||||
///
|
||||
/// The method returns for one of three possible reasons indicated by `UserEvent`.
|
||||
/// 1. The user invokes a system call;
|
||||
/// 2. The user triggers an exception;
|
||||
/// 3. The user triggers a fault.
|
||||
///
|
||||
/// After handling the user event and updating the user-mode CPU context,
|
||||
/// this method can be invoked again to go back to the user space.
|
||||
/// Specific architectures need to implement this trait. This should only used in `UserMode`
|
||||
///
|
||||
/// Only visible in jinux-frame
|
||||
pub(crate) trait UserContextApiInternal {
|
||||
/// Starts executing in the user mode.
|
||||
fn execute(&mut self) -> UserEvent;
|
||||
|
||||
/// Use the information inside CpuContext to build a trapframe
|
||||
fn into_trap_frame(&self) -> TrapFrame;
|
||||
}
|
||||
|
||||
/// The common interface that every CPU architecture-specific `CpuContext` implements.
|
||||
pub trait UserContextApi {
|
||||
/// Get the trap number of this interrupt.
|
||||
fn trap_number(&self) -> usize;
|
||||
|
||||
/// Get the trap error code of this interrupt.
|
||||
fn trap_error_code(&self) -> usize;
|
||||
|
||||
/// Get number of syscall
|
||||
fn syscall_num(&self) -> usize;
|
||||
|
||||
/// Get return value of syscall
|
||||
fn syscall_ret(&self) -> usize;
|
||||
|
||||
/// Set return value of syscall
|
||||
fn set_syscall_ret(&mut self, ret: usize);
|
||||
|
||||
/// Get syscall args
|
||||
fn syscall_args(&self) -> [usize; 6];
|
||||
|
||||
/// Set instruction pointer
|
||||
fn set_instruction_pointer(&mut self, ip: usize);
|
||||
|
||||
/// Get instruction pointer
|
||||
fn instruction_pointer(&self) -> usize;
|
||||
|
||||
/// Set stack pointer
|
||||
fn set_stack_pointer(&mut self, sp: usize);
|
||||
|
||||
/// Get stack pointer
|
||||
fn stack_pointer(&self) -> usize;
|
||||
}
|
||||
|
||||
/// Code execution in the user mode.
|
||||
@ -89,9 +124,8 @@ pub trait UserModeExecute {
|
||||
/// ```
|
||||
pub struct UserMode<'a> {
|
||||
current: Arc<Task>,
|
||||
pub(crate) user_space: &'a Arc<UserSpace>,
|
||||
pub(crate) context: CpuContext,
|
||||
pub(crate) executed: bool,
|
||||
user_space: &'a Arc<UserSpace>,
|
||||
context: UserContext,
|
||||
}
|
||||
|
||||
// An instance of `UserMode` is bound to the current task. So it cannot be
|
||||
@ -102,18 +136,34 @@ impl<'a> UserMode<'a> {
|
||||
Self {
|
||||
current: Task::current(),
|
||||
user_space,
|
||||
context: CpuContext::default(),
|
||||
executed: false,
|
||||
context: user_space.init_ctx,
|
||||
}
|
||||
}
|
||||
|
||||
/// Starts executing in the user mode. Make sure current task is the task in `UserMode`.
|
||||
///
|
||||
/// The method returns for one of three possible reasons indicated by `UserEvent`.
|
||||
/// 1. The user invokes a system call;
|
||||
/// 2. The user triggers an exception;
|
||||
/// 3. The user triggers a fault.
|
||||
///
|
||||
/// After handling the user event and updating the user-mode CPU context,
|
||||
/// this method can be invoked again to go back to the user space.
|
||||
pub fn execute(&mut self) -> UserEvent {
|
||||
unsafe {
|
||||
self.user_space.vm_space().activate();
|
||||
}
|
||||
debug_assert!(Arc::ptr_eq(&self.current, &Task::current()));
|
||||
self.context.execute()
|
||||
}
|
||||
|
||||
/// Returns an immutable reference the user-mode CPU context.
|
||||
pub fn context(&self) -> &CpuContext {
|
||||
pub fn context(&self) -> &UserContext {
|
||||
&self.context
|
||||
}
|
||||
|
||||
/// Returns a mutable reference the user-mode CPU context.
|
||||
pub fn context_mut(&mut self) -> &mut CpuContext {
|
||||
pub fn context_mut(&mut self) -> &mut UserContext {
|
||||
&mut self.context
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,6 @@ jinux-frame = { path = "../../../framework/jinux-frame" }
|
||||
jinux-pci = { path = "../pci" }
|
||||
jinux-virtio = { path = "../virtio" }
|
||||
jinux-util = { path = "../../libs/jinux-util" }
|
||||
pod = { git = "https://github.com/sdww0/POD", rev = "7fa2ed2" }
|
||||
component = { path = "../../comp-sys/component" }
|
||||
log = "0.4"
|
||||
|
||||
|
@ -12,7 +12,6 @@ jinux-frame = { path = "../../../framework/jinux-frame" }
|
||||
jinux-pci = { path = "../pci" }
|
||||
jinux-virtio = { path = "../virtio" }
|
||||
jinux-util = { path = "../../libs/jinux-util" }
|
||||
pod = { git = "https://github.com/sdww0/POD", rev = "7fa2ed2" }
|
||||
component = { path = "../../comp-sys/component" }
|
||||
virtio-input-decoder = "0.1.4"
|
||||
log = "0.4"
|
||||
|
@ -10,7 +10,7 @@ bitflags = "1.3"
|
||||
spin = "0.9.4"
|
||||
jinux-frame = { path = "../../../framework/jinux-frame" }
|
||||
jinux-util = { path = "../../libs/jinux-util" }
|
||||
pod = { git = "https://github.com/sdww0/POD", rev = "7fa2ed2" }
|
||||
pod = { git = "https://github.com/jinzhao-dev/pod", rev = "7fa2ed2" }
|
||||
component = { path = "../../comp-sys/component" }
|
||||
log = "0.4"
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
//! The frambuffer of jinux
|
||||
//! The system time of jinux
|
||||
#![no_std]
|
||||
#![forbid(unsafe_code)]
|
||||
|
||||
|
@ -11,7 +11,7 @@ spin = "0.9.4"
|
||||
jinux-frame = { path = "../../../framework/jinux-frame" }
|
||||
jinux-pci = { path = "../pci" }
|
||||
jinux-util = { path = "../../libs/jinux-util" }
|
||||
pod = { git = "https://github.com/sdww0/POD", rev = "7fa2ed2" }
|
||||
pod = { git = "https://github.com/jinzhao-dev/pod", rev = "7fa2ed2" }
|
||||
component = { path = "../../comp-sys/component" }
|
||||
log = "0.4"
|
||||
|
||||
|
@ -8,7 +8,7 @@ edition = "2021"
|
||||
[dependencies]
|
||||
jinux-frame = { path = "../../../framework/jinux-frame" }
|
||||
align_ext = { path = "../../../framework/align_ext" }
|
||||
pod = { git = "https://github.com/sdww0/POD", rev = "7fa2ed2" }
|
||||
pod = { git = "https://github.com/jinzhao-dev/pod", rev = "7fa2ed2" }
|
||||
jinux-input = { path = "../../comps/input" }
|
||||
jinux-block = { path = "../../comps/block" }
|
||||
jinux-time = { path = "../../comps/time" }
|
||||
|
@ -1,5 +1,5 @@
|
||||
use jinux_frame::{
|
||||
cpu::CpuContext,
|
||||
cpu::UserContext,
|
||||
user::UserSpace,
|
||||
vm::{VmIo, VmSpace},
|
||||
};
|
||||
@ -118,7 +118,7 @@ impl CloneFlags {
|
||||
}
|
||||
|
||||
/// Clone a child thread. Without schedule it to run.
|
||||
pub fn clone_child(parent_context: CpuContext, clone_args: CloneArgs) -> Result<Tid> {
|
||||
pub fn clone_child(parent_context: UserContext, clone_args: CloneArgs) -> Result<Tid> {
|
||||
clone_args.clone_flags.check_unsupported_flags()?;
|
||||
if clone_args.clone_flags.contains(CloneFlags::CLONE_THREAD) {
|
||||
let child_thread = clone_child_thread(parent_context, clone_args)?;
|
||||
@ -153,7 +153,7 @@ pub fn clone_child(parent_context: CpuContext, clone_args: CloneArgs) -> Result<
|
||||
}
|
||||
}
|
||||
|
||||
fn clone_child_thread(parent_context: CpuContext, clone_args: CloneArgs) -> Result<Arc<Thread>> {
|
||||
fn clone_child_thread(parent_context: UserContext, clone_args: CloneArgs) -> Result<Arc<Thread>> {
|
||||
let clone_flags = clone_args.clone_flags;
|
||||
let current = current!();
|
||||
debug_assert!(clone_flags.contains(CloneFlags::CLONE_VM));
|
||||
@ -193,7 +193,7 @@ fn clone_child_thread(parent_context: CpuContext, clone_args: CloneArgs) -> Resu
|
||||
Ok(child_thread)
|
||||
}
|
||||
|
||||
fn clone_child_process(parent_context: CpuContext, clone_args: CloneArgs) -> Result<Arc<Process>> {
|
||||
fn clone_child_process(parent_context: UserContext, clone_args: CloneArgs) -> Result<Arc<Process>> {
|
||||
let current = current!();
|
||||
let parent = Arc::downgrade(¤t);
|
||||
let clone_flags = clone_args.clone_flags;
|
||||
@ -327,11 +327,11 @@ fn clone_vm(
|
||||
}
|
||||
|
||||
fn clone_cpu_context(
|
||||
parent_context: CpuContext,
|
||||
parent_context: UserContext,
|
||||
new_sp: u64,
|
||||
tls: u64,
|
||||
clone_flags: CloneFlags,
|
||||
) -> CpuContext {
|
||||
) -> UserContext {
|
||||
let mut child_context = parent_context.clone();
|
||||
// The return value of child thread is zero
|
||||
child_context.set_rax(0);
|
||||
|
@ -1,4 +1,4 @@
|
||||
use jinux_frame::{cpu::CpuContext, user::UserSpace};
|
||||
use jinux_frame::{cpu::UserContext, user::UserSpace};
|
||||
|
||||
use crate::{
|
||||
fs::fs_resolver::FsResolver,
|
||||
@ -44,7 +44,7 @@ impl PosixThreadExt for Thread {
|
||||
)?;
|
||||
|
||||
let vm_space = root_vmar.vm_space().clone();
|
||||
let mut cpu_ctx = CpuContext::default();
|
||||
let mut cpu_ctx = UserContext::default();
|
||||
cpu_ctx.set_rip(elf_load_info.entry_point() as _);
|
||||
cpu_ctx.set_rsp(elf_load_info.user_stack_top() as _);
|
||||
let user_space = Arc::new(UserSpace::new(vm_space, cpu_ctx));
|
||||
|
@ -10,7 +10,7 @@ pub mod signals;
|
||||
use core::mem;
|
||||
|
||||
use align_ext::AlignExt;
|
||||
use jinux_frame::{cpu::CpuContext, task::Task};
|
||||
use jinux_frame::{cpu::UserContext, task::Task};
|
||||
|
||||
use self::c_types::siginfo_t;
|
||||
use self::sig_mask::SigMask;
|
||||
@ -26,7 +26,7 @@ use crate::{
|
||||
};
|
||||
|
||||
/// Handle pending signal for current process
|
||||
pub fn handle_pending_signal(context: &mut CpuContext) -> Result<()> {
|
||||
pub fn handle_pending_signal(context: &mut UserContext) -> Result<()> {
|
||||
let current = current!();
|
||||
let current_thread = current_thread!();
|
||||
let posix_thread = current_thread.as_posix_thread().unwrap();
|
||||
@ -108,7 +108,7 @@ pub fn handle_user_signal(
|
||||
flags: SigActionFlags,
|
||||
restorer_addr: Vaddr,
|
||||
mut mask: SigMask,
|
||||
context: &mut CpuContext,
|
||||
context: &mut UserContext,
|
||||
sig_info: siginfo_t,
|
||||
) -> Result<()> {
|
||||
debug!("sig_num = {:?}, signame = {}", sig_num, sig_num.sig_name());
|
||||
@ -144,7 +144,7 @@ pub fn handle_user_signal(
|
||||
user_rsp = alloc_aligned_in_user_stack(user_rsp, mem::size_of::<ucontext_t>(), 16)?;
|
||||
let mut ucontext = ucontext_t::default();
|
||||
ucontext.uc_sigmask = mask.as_u64();
|
||||
ucontext.uc_mcontext.inner.gp_regs = context.general_regs();
|
||||
ucontext.uc_mcontext.inner.gp_regs = *context.general_regs();
|
||||
let mut sig_context = posix_thread.sig_context().lock();
|
||||
if let Some(sig_context_addr) = *sig_context {
|
||||
ucontext.uc_link = sig_context_addr;
|
||||
|
@ -1,8 +1,9 @@
|
||||
use jinux_frame::cpu::TrapInformation;
|
||||
use jinux_frame::trap::{
|
||||
use jinux_frame::cpu::{CpuException, TrapInformation, UserContext};
|
||||
use jinux_frame::cpu::{
|
||||
ALIGNMENT_CHECK, BOUND_RANGE_EXCEEDED, DIVIDE_BY_ZERO, GENERAL_PROTECTION_FAULT,
|
||||
INVALID_OPCODE, PAGE_FAULT, SIMD_FLOATING_POINT_EXCEPTION, X87_FLOATING_POINT_EXCEPTION,
|
||||
};
|
||||
use jinux_frame::user::UserContextApi;
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::process::signal::c_types::siginfo_t;
|
||||
@ -20,7 +21,8 @@ pub struct FaultSignal {
|
||||
impl FaultSignal {
|
||||
pub fn new(trap_info: &TrapInformation) -> FaultSignal {
|
||||
debug!("Trap id: {}", trap_info.id);
|
||||
let (num, code, addr) = match trap_info.id {
|
||||
let exception = CpuException::to_cpu_exception(trap_info.id as u16).unwrap();
|
||||
let (num, code, addr) = match *exception {
|
||||
DIVIDE_BY_ZERO => (SIGFPE, FPE_INTDIV, None),
|
||||
X87_FLOATING_POINT_EXCEPTION | SIMD_FLOATING_POINT_EXCEPTION => {
|
||||
(SIGFPE, FPE_FLTDIV, None)
|
||||
|
@ -1,4 +1,4 @@
|
||||
use jinux_frame::cpu::CpuContext;
|
||||
use jinux_frame::cpu::UserContext;
|
||||
|
||||
use crate::syscall::SYS_ARCH_PRCTL;
|
||||
use crate::{log_syscall_entry, prelude::*};
|
||||
@ -28,7 +28,7 @@ impl TryFrom<u64> for ArchPrctlCode {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sys_arch_prctl(code: u64, addr: u64, context: &mut CpuContext) -> Result<SyscallReturn> {
|
||||
pub fn sys_arch_prctl(code: u64, addr: u64, context: &mut UserContext) -> Result<SyscallReturn> {
|
||||
log_syscall_entry!(SYS_ARCH_PRCTL);
|
||||
let arch_prctl_code = ArchPrctlCode::try_from(code)?;
|
||||
debug!(
|
||||
@ -39,7 +39,7 @@ pub fn sys_arch_prctl(code: u64, addr: u64, context: &mut CpuContext) -> Result<
|
||||
Ok(SyscallReturn::Return(res as _))
|
||||
}
|
||||
|
||||
pub fn do_arch_prctl(code: ArchPrctlCode, addr: u64, context: &mut CpuContext) -> Result<u64> {
|
||||
pub fn do_arch_prctl(code: ArchPrctlCode, addr: u64, context: &mut UserContext) -> Result<u64> {
|
||||
match code {
|
||||
ArchPrctlCode::ARCH_SET_FS => {
|
||||
context.set_fsbase(addr as usize);
|
||||
|
@ -1,4 +1,4 @@
|
||||
use jinux_frame::cpu::CpuContext;
|
||||
use jinux_frame::cpu::UserContext;
|
||||
|
||||
use crate::log_syscall_entry;
|
||||
use crate::process::clone::{clone_child, CloneArgs, CloneFlags};
|
||||
@ -14,7 +14,7 @@ pub fn sys_clone(
|
||||
parent_tidptr: Vaddr,
|
||||
child_tidptr: Vaddr,
|
||||
tls: u64,
|
||||
parent_context: CpuContext,
|
||||
parent_context: UserContext,
|
||||
) -> Result<SyscallReturn> {
|
||||
log_syscall_entry!(SYS_CLONE);
|
||||
let clone_flags = CloneFlags::from(clone_flags);
|
||||
|
@ -1,4 +1,4 @@
|
||||
use jinux_frame::cpu::CpuContext;
|
||||
use jinux_frame::cpu::UserContext;
|
||||
|
||||
use super::{constants::*, SyscallReturn};
|
||||
use crate::log_syscall_entry;
|
||||
@ -12,7 +12,7 @@ pub fn sys_execve(
|
||||
filename_ptr: Vaddr,
|
||||
argv_ptr_ptr: Vaddr,
|
||||
envp_ptr_ptr: Vaddr,
|
||||
context: &mut CpuContext,
|
||||
context: &mut UserContext,
|
||||
) -> Result<SyscallReturn> {
|
||||
log_syscall_entry!(SYS_EXECVE);
|
||||
let executable_path = read_cstring_from_user(filename_ptr, MAX_FILENAME_LEN)?;
|
||||
@ -50,10 +50,10 @@ pub fn sys_execve(
|
||||
// set signal disposition to default
|
||||
current.sig_dispositions().lock().inherit();
|
||||
// set cpu context to default
|
||||
let defalut_content = CpuContext::default();
|
||||
context.set_general_regs(defalut_content.general_regs());
|
||||
context.set_fsbase(defalut_content.fsbase());
|
||||
context.fp_regs = defalut_content.fp_regs;
|
||||
let default_content = UserContext::default();
|
||||
*context.general_regs_mut() = *default_content.general_regs();
|
||||
context.set_fsbase(default_content.fsbase());
|
||||
context.fp_regs = default_content.fp_regs;
|
||||
// set new entry point
|
||||
context.set_rip(elf_load_info.entry_point() as _);
|
||||
debug!("entry_point: 0x{:x}", elf_load_info.entry_point());
|
||||
|
@ -3,13 +3,13 @@ use crate::{
|
||||
prelude::*,
|
||||
process::clone::{clone_child, CloneArgs},
|
||||
};
|
||||
use jinux_frame::cpu::CpuContext;
|
||||
use jinux_frame::cpu::UserContext;
|
||||
|
||||
use crate::syscall::SYS_FORK;
|
||||
|
||||
use super::SyscallReturn;
|
||||
|
||||
pub fn sys_fork(parent_context: CpuContext) -> Result<SyscallReturn> {
|
||||
pub fn sys_fork(parent_context: UserContext) -> Result<SyscallReturn> {
|
||||
log_syscall_entry!(SYS_FORK);
|
||||
let current = current!();
|
||||
// FIXME: set correct args for fork
|
||||
|
@ -62,7 +62,7 @@ use crate::syscall::wait4::sys_wait4;
|
||||
use crate::syscall::waitid::sys_waitid;
|
||||
use crate::syscall::write::sys_write;
|
||||
use crate::syscall::writev::sys_writev;
|
||||
use jinux_frame::cpu::CpuContext;
|
||||
use jinux_frame::cpu::UserContext;
|
||||
|
||||
mod access;
|
||||
mod arch_prctl;
|
||||
@ -248,7 +248,7 @@ pub enum SyscallReturn {
|
||||
}
|
||||
|
||||
impl SyscallArgument {
|
||||
fn new_from_context(context: &CpuContext) -> Self {
|
||||
fn new_from_context(context: &UserContext) -> Self {
|
||||
let syscall_number = context.rax() as u64;
|
||||
let mut args = [0u64; 6];
|
||||
args[0] = context.rdi() as u64;
|
||||
@ -264,7 +264,7 @@ impl SyscallArgument {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_syscall(context: &mut CpuContext) {
|
||||
pub fn handle_syscall(context: &mut UserContext) {
|
||||
let syscall_frame = SyscallArgument::new_from_context(context);
|
||||
let syscall_return =
|
||||
syscall_dispatch(syscall_frame.syscall_number, syscall_frame.args, context);
|
||||
@ -286,7 +286,7 @@ pub fn handle_syscall(context: &mut CpuContext) {
|
||||
pub fn syscall_dispatch(
|
||||
syscall_number: u64,
|
||||
args: [u64; 6],
|
||||
context: &mut CpuContext,
|
||||
context: &mut UserContext,
|
||||
) -> Result<SyscallReturn> {
|
||||
match syscall_number {
|
||||
SYS_READ => syscall_handler!(3, sys_read, args),
|
||||
|
@ -4,11 +4,11 @@ use crate::{
|
||||
process::{posix_thread::posix_thread_ext::PosixThreadExt, signal::c_types::ucontext_t},
|
||||
util::read_val_from_user,
|
||||
};
|
||||
use jinux_frame::cpu::CpuContext;
|
||||
use jinux_frame::cpu::UserContext;
|
||||
|
||||
use super::{SyscallReturn, SYS_RT_SIGRETRUN};
|
||||
|
||||
pub fn sys_rt_sigreturn(context: &mut CpuContext) -> Result<SyscallReturn> {
|
||||
pub fn sys_rt_sigreturn(context: &mut UserContext) -> Result<SyscallReturn> {
|
||||
log_syscall_entry!(SYS_RT_SIGRETRUN);
|
||||
let current_thread = current_thread!();
|
||||
let posix_thread = current_thread.as_posix_thread().unwrap();
|
||||
@ -29,7 +29,7 @@ pub fn sys_rt_sigreturn(context: &mut CpuContext) -> Result<SyscallReturn> {
|
||||
} else {
|
||||
*sig_context = Some(ucontext.uc_link);
|
||||
};
|
||||
context.set_general_regs(ucontext.uc_mcontext.inner.gp_regs);
|
||||
*context.general_regs_mut() = ucontext.uc_mcontext.inner.gp_regs;
|
||||
// unblock sig mask
|
||||
let sig_mask = ucontext.uc_sigmask;
|
||||
posix_thread.sig_mask().lock().unblock(sig_mask);
|
||||
|
@ -1,20 +1,18 @@
|
||||
use jinux_frame::{
|
||||
cpu::{CpuContext, TrapInformation},
|
||||
trap::*,
|
||||
vm::VmIo,
|
||||
};
|
||||
use jinux_frame::user::UserContextApi;
|
||||
use jinux_frame::{cpu::*, vm::VmIo};
|
||||
|
||||
use crate::vm::page_fault_handler::PageFaultHandler;
|
||||
use crate::{prelude::*, process::signal::signals::fault::FaultSignal};
|
||||
|
||||
/// We can't handle most exceptions, just send self a fault signal before return to user space.
|
||||
pub fn handle_exception(context: &mut CpuContext) {
|
||||
pub fn handle_exception(context: &mut UserContext) {
|
||||
let trap_info = context.trap_information.clone();
|
||||
log_trap_info(&trap_info);
|
||||
let exception = CpuException::to_cpu_exception(trap_info.id as u16).unwrap();
|
||||
log_trap_info(exception, &trap_info);
|
||||
let current = current!();
|
||||
let root_vmar = current.root_vmar();
|
||||
|
||||
match trap_info.id {
|
||||
match *exception {
|
||||
PAGE_FAULT => handle_page_fault(&trap_info),
|
||||
_ => {
|
||||
// We current do nothing about other exceptions
|
||||
@ -73,8 +71,8 @@ macro_rules! log_trap_common {
|
||||
};
|
||||
}
|
||||
|
||||
fn log_trap_info(trap_info: &TrapInformation) {
|
||||
match trap_info.id {
|
||||
fn log_trap_info(exception: &CpuException, trap_info: &TrapInformation) {
|
||||
match *exception {
|
||||
DIVIDE_BY_ZERO => log_trap_common!(DIVIDE_BY_ZERO, trap_info),
|
||||
DEBUG => log_trap_common!(DEBUG, trap_info),
|
||||
NON_MASKABLE_INTERRUPT => log_trap_common!(NON_MASKABLE_INTERRUPT, trap_info),
|
||||
|
@ -1,7 +1,7 @@
|
||||
use jinux_frame::{
|
||||
cpu::CpuContext,
|
||||
cpu::UserContext,
|
||||
task::Task,
|
||||
user::{UserEvent, UserMode, UserModeExecute, UserSpace},
|
||||
user::{UserEvent, UserMode, UserSpace},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
@ -17,9 +17,12 @@ pub fn create_new_user_task(user_space: Arc<UserSpace>, thread_ref: Weak<Thread>
|
||||
let cur = Task::current();
|
||||
let user_space = cur.user_space().expect("user task should have user space");
|
||||
let mut user_mode = UserMode::new(user_space);
|
||||
debug!("[Task entry] rip = 0x{:x}", user_space.cpu_ctx.rip());
|
||||
debug!("[Task entry] rsp = 0x{:x}", user_space.cpu_ctx.rsp());
|
||||
debug!("[Task entry] rax = 0x{:x}", user_space.cpu_ctx.rax());
|
||||
debug!(
|
||||
"[Task entry] rip = 0x{:x}",
|
||||
user_space.instruction_pointer()
|
||||
);
|
||||
debug!("[Task entry] rsp = 0x{:x}", user_space.stack_pointer());
|
||||
debug!("[Task entry] rax = 0x{:x}", user_space.syscall_ret());
|
||||
loop {
|
||||
let user_event = user_mode.execute();
|
||||
let context = user_mode.context_mut();
|
||||
@ -50,7 +53,7 @@ pub fn create_new_user_task(user_space: Arc<UserSpace>, thread_ref: Weak<Thread>
|
||||
Task::new(user_task_entry, thread_ref, Some(user_space)).expect("spawn task failed")
|
||||
}
|
||||
|
||||
fn handle_user_event(user_event: UserEvent, context: &mut CpuContext) {
|
||||
fn handle_user_event(user_event: UserEvent, context: &mut UserContext) {
|
||||
match user_event {
|
||||
UserEvent::Syscall => handle_syscall(context),
|
||||
UserEvent::Fault => todo!(),
|
||||
|
@ -7,7 +7,7 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
jinux-frame = {path = "../../../framework/jinux-frame"}
|
||||
pod = { git = "https://github.com/sdww0/POD", rev = "7fa2ed2" }
|
||||
pod = { git = "https://github.com/jinzhao-dev/pod", rev = "7fa2ed2" }
|
||||
|
||||
[features]
|
||||
|
||||
|
Reference in New Issue
Block a user