1
0
mirror of https://github.com/rcore-os/rCore.git synced 2024-11-23 00:16:17 +04:00

Add fp save and restore and use accel=hvf in macOS

This commit is contained in:
Jiajie Chen 2020-06-29 22:53:30 +08:00
parent 34ca9963cb
commit e32597ac82
7 changed files with 97 additions and 14 deletions

View File

@ -15,6 +15,17 @@ Supported architectures and boards:
![demo](./docs/2_OSLab/os2atc/demo.png) ![demo](./docs/2_OSLab/os2atc/demo.png)
## What's included
rCore has the following features:
* Linux compatible syscall interface: run Linux userspace programs
* Network stack
* Simple file system
* Signal system
* Async IO
* Kernel module
## Building ## Building
### Environment ### Environment

View File

@ -77,7 +77,7 @@ qemu_net_opts :=
ifeq ($(ARCH), x86_64) ifeq ($(ARCH), x86_64)
qemu_opts += \ qemu_opts += \
-bios $(OVMF) \ -drive if=pflash,format=raw,readonly,file=$(OVMF) \
-drive format=raw,file=fat:rw:$(ESP) \ -drive format=raw,file=fat:rw:$(ESP) \
-serial mon:stdio \ -serial mon:stdio \
-m 4G \ -m 4G \
@ -93,13 +93,15 @@ qemu_net_opts += \
-netdev type=tap,id=net0,script=no,downscript=no \ -netdev type=tap,id=net0,script=no,downscript=no \
-device e1000e,netdev=net0 -device e1000e,netdev=net0
else else
qemu_opts += \
-machine accel=kvm
qemu_net_opts += \ qemu_net_opts += \
-device vfio-pci,host=$(PCI_PASSTHRU) -device vfio-pci,host=$(PCI_PASSTHRU)
qemu_ui_opts += \ qemu_ui_opts += \
-vga std -vga std
endif endif
ifeq ($(shell uname), Darwin)
qemu_opts += \
-machine accel=hvf
endif
ifeq ($(EXTRA_NIC), on) ifeq ($(EXTRA_NIC), on)
qemu_net_opts += \ qemu_net_opts += \
-netdev type=tap,id=net1,script=no,downscript=no \ -netdev type=tap,id=net1,script=no,downscript=no \

View File

@ -59,3 +59,7 @@
- fn main_start():第一个核的启动 - fn main_start():第一个核的启动
- fn others_start():其他核的启动 - fn others_start():其他核的启动
### fp
- struct FpState浮点的状态

View File

@ -0,0 +1,43 @@
// state saved by fxsave64
// 512 bytes
// https://www.felixcloutier.com/x86/fxsave#tbl-3-47
#[repr(C, align(16))]
#[derive(Debug, Copy, Clone, Default)]
pub struct FpState {
// 0
word1: u64,
word2: u64,
// 16
word3: u64,
mxcsr: u32,
mxcsr_mask: u32,
// 32
mm: [u64; 16],
// 160
xmm: [u64; 32],
// 416
rest: [u64; 12],
}
impl FpState {
pub fn new() -> Self {
assert!(core::mem::size_of::<Self>() == 512);
Self {
// default value
mxcsr: 0x1f80,
..Self::default()
}
}
pub fn save(&mut self) {
unsafe {
core::arch::x86_64::_fxsave64(self as *mut FpState as *mut u8);
}
}
pub fn restore(&self) {
unsafe {
core::arch::x86_64::_fxrstor64(self as *const FpState as *const u8);
}
}
}

View File

@ -6,6 +6,7 @@ pub mod acpi;
pub mod board; pub mod board;
pub mod consts; pub mod consts;
pub mod cpu; pub mod cpu;
pub mod fp;
pub mod gdt; pub mod gdt;
pub mod interrupt; pub mod interrupt;
pub mod io; pub mod io;

View File

@ -6,6 +6,7 @@ use crate::arch::interrupt::consts::{is_page_fault, IrqMax, IrqMin, Syscall, Tim
use crate::arch::interrupt::get_trap_num; use crate::arch::interrupt::get_trap_num;
use crate::arch::{ use crate::arch::{
cpu, cpu,
fp::FpState,
memory::{get_page_fault_addr, set_page_table}, memory::{get_page_fault_addr, set_page_table},
paging::*, paging::*,
}; };
@ -51,12 +52,18 @@ use xmas_elf::{
/// Tid type /// Tid type
pub type Tid = usize; pub type Tid = usize;
pub struct ThreadContext {
user: Box<UserContext>,
/// TODO: lazy fp
fp: Box<FpState>,
}
/// Mutable part of a thread struct /// Mutable part of a thread struct
#[derive(Default)] #[derive(Default)]
pub struct ThreadInner { pub struct ThreadInner {
/// user context /// user context
/// None when thread is running in user /// None when thread is running in user
context: Option<Box<UserContext>>, context: Option<ThreadContext>,
/// Kernel performs futex wake when thread exits. /// Kernel performs futex wake when thread exits.
/// Ref: [http://man7.org/linux/man-pages/man2/set_tid_address.2.html] /// Ref: [http://man7.org/linux/man-pages/man2/set_tid_address.2.html]
pub clear_child_tid: usize, pub clear_child_tid: usize,
@ -304,7 +311,10 @@ impl Thread {
let thread = Thread { let thread = Thread {
tid: 0, // allocated below tid: 0, // allocated below
inner: Mutex::new(ThreadInner { inner: Mutex::new(ThreadInner {
context: Some(Box::from(context)), context: Some(ThreadContext {
user: Box::from(context),
fp: Box::new(FpState::new()),
}),
clear_child_tid: 0, clear_child_tid: 0,
sig_mask: Sigset::default(), sig_mask: Sigset::default(),
signal_alternate_stack: SignalStack::default(), signal_alternate_stack: SignalStack::default(),
@ -381,7 +391,10 @@ impl Thread {
let new_thread = Thread { let new_thread = Thread {
tid: 0, // allocated below tid: 0, // allocated below
inner: Mutex::new(ThreadInner { inner: Mutex::new(ThreadInner {
context: Some(Box::new(context)), context: Some(ThreadContext {
user: Box::new(context),
fp: Box::new(FpState::new()),
}),
clear_child_tid: 0, clear_child_tid: 0,
sig_mask, sig_mask,
signal_alternate_stack: sigaltstack, signal_alternate_stack: sigaltstack,
@ -416,6 +429,10 @@ impl Thread {
new_context.set_syscall_ret(0); new_context.set_syscall_ret(0);
new_context.set_sp(stack_top); new_context.set_sp(stack_top);
new_context.set_tls(tls); new_context.set_tls(tls);
let thread_context = ThreadContext {
user: Box::new(new_context),
fp: Box::new(FpState::new()),
};
let sig_mask = self.inner.lock().sig_mask; let sig_mask = self.inner.lock().sig_mask;
let sigaltstack = self.inner.lock().signal_alternate_stack; let sigaltstack = self.inner.lock().signal_alternate_stack;
@ -423,7 +440,7 @@ impl Thread {
tid: 0, tid: 0,
inner: Mutex::new(ThreadInner { inner: Mutex::new(ThreadInner {
clear_child_tid, clear_child_tid,
context: Some(Box::new(new_context)), context: Some(thread_context),
sig_mask, sig_mask,
signal_alternate_stack: sigaltstack, signal_alternate_stack: sigaltstack,
}), }),
@ -435,11 +452,11 @@ impl Thread {
res res
} }
pub fn begin_running(&self) -> Box<UserContext> { pub fn begin_running(&self) -> ThreadContext {
self.inner.lock().context.take().unwrap() self.inner.lock().context.take().unwrap()
} }
pub fn end_running(&self, cx: Box<UserContext>) { pub fn end_running(&self, cx: ThreadContext) {
self.inner.lock().context = Some(cx); self.inner.lock().context = Some(cx);
} }
@ -468,9 +485,14 @@ pub fn spawn(thread: Arc<Thread>) {
let temp = thread.clone(); let temp = thread.clone();
let future = async move { let future = async move {
loop { loop {
let mut cx = thread.begin_running(); let mut thread_context = thread.begin_running();
let cx = &mut thread_context.user;
trace!("go to user: {:#x?}", cx); trace!("go to user: {:#x?}", cx);
thread_context.fp.restore();
cx.run(); cx.run();
thread_context.fp.save();
let trap_num = get_trap_num(&cx); let trap_num = get_trap_num(&cx);
trace!("back from user: {:#x?} trap_num {:#x}", cx, trap_num); trace!("back from user: {:#x?} trap_num {:#x}", cx, trap_num);
@ -487,7 +509,7 @@ pub fn spawn(thread: Arc<Thread>) {
panic!("page fault handle failed"); panic!("page fault handle failed");
} }
} }
Syscall => exit = handle_syscall(&thread, &mut cx).await, Syscall => exit = handle_syscall(&thread, cx).await,
IrqMin..=IrqMax => { IrqMin..=IrqMax => {
crate::arch::interrupt::ack(trap_num); crate::arch::interrupt::ack(trap_num);
trace!("handle irq {:#x}", trap_num); trace!("handle irq {:#x}", trap_num);
@ -506,10 +528,10 @@ pub fn spawn(thread: Arc<Thread>) {
// check signals // check signals
if !exit { if !exit {
exit = handle_signal(&thread, &mut cx); exit = handle_signal(&thread, cx);
} }
thread.end_running(cx); thread.end_running(thread_context);
if exit { if exit {
info!("thread {} stopped", thread.tid); info!("thread {} stopped", thread.tid);
break; break;

View File

@ -191,7 +191,7 @@ pub fn handle_signal(thread: &Arc<Thread>, tf: &mut UserContext) -> bool {
let mut inner = thread.inner.lock(); let mut inner = thread.inner.lock();
let sig_mask = inner.sig_mask; let sig_mask = inner.sig_mask;
// update sig mask // update sig mask (see man sigaction(2))
// 1. block current // 1. block current
// 2. block mask in disposition // 2. block mask in disposition
inner.sig_mask.add(signal); inner.sig_mask.add(signal);