Enable SSE and save FP registers in trapframe, implement sys_pread, sys_uname and sys_sched_getaffinity, support FIXED in mmap

master
Jiajie Chen 6 years ago
parent f7f740a021
commit 35dad6853f

@ -1,5 +1,6 @@
use apic::{LocalApic, XApic};
use raw_cpuid::CpuId;
use x86_64::registers::control::{Cr0, Cr0Flags};
/// Exit qemu
/// See: https://wiki.osdev.org/Shutdown
@ -24,6 +25,19 @@ pub fn send_ipi(cpu_id: usize) {
pub fn init() {
let mut lapic = unsafe { XApic::new(0xffffff00_fee00000) };
lapic.cpu_init();
// enable FPU, the manual Volume 3 Chapter 13
let mut value: u64;
unsafe {
asm!("mov %cr4, $0" : "=r" (value));
// OSFXSR | OSXMMEXCPT
value |= 1 << 9 | 1 << 10 ;
asm!("mov $0, %cr4" :: "r" (value) : "memory");
Cr0::update(|cr0| {
cr0.remove(Cr0Flags::EMULATE_COPROCESSOR);
cr0.insert(Cr0Flags::MONITOR_COPROCESSOR);
});
}
}
pub fn halt() {

@ -28,6 +28,21 @@ __alltraps:
or rdx, rax
push rdx
# save fp registers
# align to 16 byte boundary
sub rsp, 512
mov rax, rsp
and rax, 0xFFFFFFFFFFFFFFF0
# fxsave (rax)
.byte 0x0f
.byte 0xae
.byte 0x00
mov rbx, rsp
sub rbx, rax
# push fp state offset
sub rsp, 16
push rbx
mov rdi, rsp
call rust_trap
@ -37,6 +52,20 @@ trap_ret:
mov rdi, rsp
call set_return_rsp
# pop fp state offset
pop rbx
cmp rbx, 16 # only 0-15 are valid
jge skip_fxrstor
mov rax, rsp
add rax, 16
sub rax, rbx
# fxrstor (rax)
.byte 0x0f
.byte 0xae
.byte 0x08
skip_fxrstor:
add rsp, 16+512
# pop fs.base
pop rax
mov rdx, rax

@ -1,6 +1,31 @@
use core::fmt;
use core::default::Default;
#[derive(Clone)]
#[repr(C)]
pub struct FpState([u8; 16+512]);
impl fmt::Debug for FpState {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "fpstate")
}
}
impl Default for FpState {
fn default() -> Self {
FpState([0u8; 16+512])
}
}
#[derive(Debug, Clone, Default)]
#[repr(C)]
pub struct TrapFrame {
// fpstate needs to be 16-byte aligned
// so we reserve some space here and save the offset
// the read fpstate begin from fpstate[offset]
pub fpstate_offset: usize,
pub fpstate: FpState,
// Pushed by __alltraps at 'trap.asm'
pub fsbase: usize,
@ -46,6 +71,7 @@ impl TrapFrame {
tf.ss = gdt::KDATA_SELECTOR.0 as usize;
tf.rsp = rsp;
tf.rflags = 0x282;
tf.fpstate_offset = 16; // skip restoring for first time
tf
}
fn new_user_thread(entry_addr: usize, rsp: usize, is32: bool) -> Self {
@ -56,6 +82,7 @@ impl TrapFrame {
tf.ss = if is32 { gdt::UDATA32_SELECTOR.0 } else { gdt::UDATA_SELECTOR.0 } as usize;
tf.rsp = rsp;
tf.rflags = 0x282;
tf.fpstate_offset = 16; // skip restoring for first time
tf
}
pub fn is_user(&self) -> bool {

@ -41,16 +41,19 @@ impl PageTable for ActivePageTable {
fn map(&mut self, addr: usize, target: usize) -> &mut Entry {
let flags = EF::PRESENT | EF::WRITABLE | EF::NO_EXECUTE;
unsafe {
self.0.map_to(Page::of_addr(addr), Frame::of_addr(target), flags, &mut FrameAllocatorForX86)
.unwrap().flush();
if let Ok(flush) = self.0.map_to(Page::of_addr(addr), Frame::of_addr(target), flags, &mut FrameAllocatorForX86) {
flush.flush();
}
}
unsafe { &mut *(get_entry_ptr(addr, 1)) }
}
fn unmap(&mut self, addr: usize) {
let (_, flush) = self.0.unmap(Page::of_addr(addr)).unwrap();
// unmap and flush if it is mapped
if let Ok((_, flush)) = self.0.unmap(Page::of_addr(addr)) {
flush.flush();
}
}
fn get_entry(&mut self, addr: usize) -> Option<&mut Entry> {
for level in 0..3 {

@ -44,6 +44,14 @@ impl FileHandle {
Ok(len)
}
pub fn read_at(&mut self, offset: usize, buf: &mut [u8]) -> Result<usize> {
if !self.options.read {
return Err(FsError::InvalidParam); // FIXME: => EBADF
}
let len = self.inode.read_at(offset, buf)?;
Ok(len)
}
pub fn write(&mut self, buf: &[u8]) -> Result<usize> {
if !self.options.write {
return Err(FsError::InvalidParam); // FIXME: => EBADF

@ -65,3 +65,4 @@ impl StackWriter {
pub const AT_PHDR: u8 = 3;
pub const AT_PHENT: u8 = 4;
pub const AT_PHNUM: u8 = 5;
pub const AT_PAGESZ: u8 = 6;

@ -7,13 +7,13 @@ use spin::Mutex;
use xmas_elf::{ElfFile, header, program::{Flags, Type}};
use smoltcp::socket::{SocketSet, SocketHandle};
use smoltcp::wire::IpEndpoint;
use rcore_memory::PAGE_SIZE;
use crate::arch::interrupt::{Context, TrapFrame};
use crate::memory::{ByFrame, GlobalFrameAlloc, KernelStack, MemoryAttr, MemorySet};
use crate::fs::{FileHandle, OpenOptions};
use crate::sync::Condvar;
use crate::drivers::NET_DRIVERS;
use crate::consts::{USER_TLS_OFFSET, USER_TMP_TLS_OFFSET};
use super::abi::{self, ProcInitInfo};
@ -151,6 +151,7 @@ impl Thread {
}
map.insert(abi::AT_PHENT, elf.header.pt2.ph_entry_size() as usize);
map.insert(abi::AT_PHNUM, elf.header.pt2.ph_count() as usize);
map.insert(abi::AT_PAGESZ, PAGE_SIZE);
map
},
};

@ -36,6 +36,16 @@ pub fn sys_write(fd: usize, base: *const u8, len: usize) -> SysResult {
}
}
pub fn sys_pread(fd: usize, base: *mut u8, len: usize, offset: usize) -> SysResult {
info!("pread: fd: {}, base: {:?}, len: {}, offset: {}", fd, base, len, offset);
let mut proc = process();
proc.memory_set.check_mut_array(base, len)?;
let slice = unsafe { slice::from_raw_parts_mut(base, len) };
let len = proc.get_file(fd)?.read_at(offset, slice)?;
Ok(len as isize)
}
pub fn sys_read_file(proc: &mut Process, fd: usize, base: *mut u8, len: usize) -> SysResult {
let slice = unsafe { slice::from_raw_parts_mut(base, len) };
let len = proc.get_file(fd)?.read(slice)?;

@ -8,7 +8,7 @@ use crate::memory::GlobalFrameAlloc;
use super::*;
pub fn sys_mmap(mut addr: usize, len: usize, prot: usize, flags: usize, fd: i32, offset: usize) -> SysResult {
pub fn sys_mmap(mut addr: usize, mut len: usize, prot: usize, flags: usize, fd: i32, offset: usize) -> SysResult {
let prot = MmapProt::from_bits_truncate(prot);
let flags = MmapFlags::from_bits_truncate(flags);
info!("mmap: addr={:#x}, size={:#x}, prot={:?}, flags={:?}, fd={}, offset={:#x}", addr, len, prot, flags, fd, offset);
@ -20,7 +20,13 @@ pub fn sys_mmap(mut addr: usize, len: usize, prot: usize, flags: usize, fd: i32,
// so just skip it
addr = PAGE_SIZE;
}
if flags.contains(MmapFlags::FIXED) {
// we have to map it to addr, so remove the old mapping first
proc.memory_set.pop(addr, addr + len);
} else {
addr = proc.memory_set.find_free_area(addr, len);
}
if flags.contains(MmapFlags::ANONYMOUS) {
if flags.contains(MmapFlags::SHARED) {
@ -79,6 +85,8 @@ bitflags! {
const SHARED = 1 << 0;
/// Changes are private.
const PRIVATE = 1 << 1;
/// Place the mapping at the exact address
const FIXED = 1 << 4;
/// The mapping is not backed by any file. (non-POSIX)
const ANONYMOUS = 1 << 5;
}

@ -0,0 +1,36 @@
use super::*;
use core::mem::size_of;
pub fn sys_uname(buf: *mut u8) -> SysResult {
info!("sched_uname: buf: {:?}", buf);
let offset = 65;
let strings = ["rCore", "orz", "0.1.0", "1", "machine", "domain"];
let proc = process();
proc.memory_set
.check_mut_array(buf, strings.len() * offset)?;
for i in 0..strings.len() {
unsafe {
util::write_cstr(buf.add(i * offset), &strings[i]);
}
}
Ok(0)
}
pub fn sys_sched_getaffinity(pid: usize, size: usize, mask: *mut u32) -> SysResult {
info!(
"sched_getaffinity: pid: {}, size: {}, mask: {:?}",
pid, size, mask
);
let proc = process();
proc.memory_set
.check_mut_array(mask, size / size_of::<u32>())?;
// we only have 4 cpu at most.
// so just set it.
unsafe {
*mask = 0b1111;
}
Ok(0)
}

@ -21,6 +21,7 @@ use self::proc::*;
use self::time::*;
use self::ctrl::*;
use self::net::*;
use self::misc::*;
mod fs;
mod mem;
@ -28,6 +29,7 @@ mod proc;
mod time;
mod ctrl;
mod net;
mod misc;
/// System call dispatcher
pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
@ -48,6 +50,7 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
009 => sys_mmap(args[0], args[1], args[2], args[3], args[4] as i32, args[5]),
010 => sys_mprotect(args[0], args[1], args[2]),
011 => sys_munmap(args[0], args[1]),
017 => sys_pread(args[0], args[1] as *mut u8, args[2], args[3]),
019 => sys_readv(args[0], args[1] as *const IoVec, args[2]),
020 => sys_writev(args[0], args[1] as *const IoVec, args[2]),
021 => sys_access(args[0] as *const u8, args[1]),
@ -80,6 +83,7 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
060 => sys_exit(args[0] as isize),
061 => sys_wait(args[0], args[1] as *mut i32), // TODO: wait4
062 => sys_kill(args[0]),
063 => sys_uname(args[0] as *mut u8),
// 072 => sys_fcntl(),
074 => sys_fsync(args[0]),
075 => sys_fdatasync(args[0]),
@ -103,6 +107,7 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
// 169 => sys_reboot(),
186 => sys_gettid(),
201 => sys_time(args[0] as *mut u64),
204 => sys_sched_getaffinity(args[0], args[1], args[2] as *mut u32),
217 => sys_getdents64(args[0], args[1] as *mut LinuxDirent64, args[2]),
// 293 => sys_pipe(),
@ -171,12 +176,16 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
warn!("sys_exit_group is unimplemented");
sys_exit(args[0] as isize);
}
302 => {
warn!("sys_prlimit64 is unimplemented");
Ok(0)
}
_ => {
error!("unknown syscall id: {:#x?}, args: {:x?}", id, args);
crate::trap::error(tf);
}
};
debug!("{}:{} syscall id {} ret with {:?}", pid, tid, id, ret);
debug!("{}:{} syscall id {} ret with {:x?}", pid, tid, id, ret);
match ret {
Ok(code) => code,
Err(err) => -(err as isize),

@ -475,7 +475,6 @@ pub fn sys_close_socket(proc: &mut Process, fd: usize, handle: SocketHandle) ->
pub fn sys_bind(fd: usize, addr: *const SockaddrIn, len: usize) -> SysResult {
info!("sys_bind: fd: {} addr: {:?} len: {}", fd, addr, len);
let mut proc = process();
proc.memory_set.check_array(addr, len)?;
if len < size_of::<SockaddrIn>() {
return Err(SysError::EINVAL);
@ -509,6 +508,7 @@ pub fn sys_listen(fd: usize, backlog: usize) -> SysResult {
let mut sockets = iface.sockets();
let mut socket = sockets.get::<TcpSocket>(wrapper.handle);
info!("socket {} listening on {:?}", fd, endpoint);
match socket.listen(endpoint) {
Ok(()) => Ok(0),
Err(err) => {
@ -554,7 +554,7 @@ pub fn sys_accept(fd: usize, addr: *mut SockaddrIn, addr_len: *mut u32) -> SysRe
return Err(SysError::EINVAL);
}
proc.memory_set.check_mut_array(addr, max_addr_len)?;
proc.memory_set.check_mut_ptr(addr)?;
}
let wrapper = proc.get_socket_mut(fd)?;

@ -162,6 +162,7 @@ pub fn sys_exit(exit_code: isize) -> ! {
}
pub fn sys_sleep(time: usize) -> SysResult {
info!("sleep: time: {}", time);
if time >= 1 << 31 {
thread::park();
} else {

Loading…
Cancel
Save