Refactor CpuContext; impl CpuException

This commit is contained in:
Yuke Peng
2023-04-01 22:32:03 -07:00
committed by Tate, Hongliang Tian
parent fbcfbe19d1
commit 4c7449d2c1
30 changed files with 399 additions and 299 deletions

View File

@ -11,6 +11,8 @@ const COMMON_ARGS: &[&str] = &[
"--no-reboot",
"-cpu",
"Icelake-Server",
"-m",
"1G",
"-device",
"isa-debug-exit,iobase=0xf4,iosize=0x04",
"-device",

View File

@ -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]

View File

@ -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::*;

View File

@ -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);

View File

@ -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)]

View File

@ -0,0 +1,6 @@
/// move interrupts instructions ..
/// irq 32,256
pub(crate) fn enable_interrupts() {
x86_64::instructions::interrupts::enable();
}

View File

@ -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 {

View File

@ -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::*;
}
}

View File

@ -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,
}
}

View File

@ -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
);

View File

@ -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
}
}

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -1,4 +1,4 @@
//! The frambuffer of jinux
//! The system time of jinux
#![no_std]
#![forbid(unsafe_code)]

View File

@ -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"

View File

@ -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" }

View File

@ -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(&current);
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);

View File

@ -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));

View File

@ -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;

View File

@ -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)

View File

@ -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);

View File

@ -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);

View File

@ -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());

View File

@ -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

View File

@ -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),

View File

@ -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);

View File

@ -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),

View File

@ -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!(),

View File

@ -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]