Merge pull request #1 from rcore-os/dev

Dev branch sync.
master
NagiNikaido 6 years ago committed by GitHub
commit de02024b77
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -5,4 +5,3 @@ pub const KERNEL_HEAP_SIZE: usize = 8 * 1024 * 1024;
pub const MEMORY_OFFSET: usize = 0;
pub const USER_STACK_OFFSET: usize = 0x0000_8000_0000_0000 - USER_STACK_SIZE;
pub const USER_STACK_SIZE: usize = 1 * 1024 * 1024;
pub const USER32_STACK_OFFSET: usize = USER_STACK_OFFSET;

@ -163,7 +163,6 @@ impl Context {
entry_addr: usize,
ustack_top: usize,
kstack_top: usize,
_is32: bool,
ttbr: usize,
) -> Self {
InitStack {

@ -8,6 +8,5 @@ pub const MEMORY_OFFSET: usize = 0x8000_0000;
pub const USER_STACK_OFFSET: usize = 0x80000000 - USER_STACK_SIZE;
pub const USER_STACK_SIZE: usize = 0x10000;
pub const USER32_STACK_OFFSET: usize = 0x80000000 - USER_STACK_SIZE;
pub const MAX_DTB_SIZE: usize = 0x2000;

@ -206,7 +206,6 @@ impl Context {
entry_addr: usize,
ustack_top: usize,
kstack_top: usize,
_is32: bool,
satp: usize,
) -> Self {
info!(

@ -37,6 +37,5 @@ pub const MEMORY_END: usize = 0x8100_0000;
// FIXME: rv64 `sh` and `ls` will crash if stack top > 0x80000000 ???
pub const USER_STACK_OFFSET: usize = 0x80000000 - USER_STACK_SIZE;
pub const USER_STACK_SIZE: usize = 0x10000;
pub const USER32_STACK_OFFSET: usize = 0xC0000000 - USER_STACK_SIZE;
pub const MAX_DTB_SIZE: usize = 0x2000;

@ -236,7 +236,6 @@ impl Context {
entry_addr: usize,
ustack_top: usize,
kstack_top: usize,
_is32: bool,
satp: usize,
) -> Self {
InitStack {

@ -53,7 +53,6 @@ pub const USER_GRANT_PML4: usize = (USER_GRANT_OFFSET & PML4_MASK) / PML4_SIZE;
/// Offset to user stack
pub const USER_STACK_OFFSET: usize = USER_GRANT_OFFSET + PML4_SIZE;
pub const USER32_STACK_OFFSET: usize = 0xB000_0000;
pub const USER_STACK_PML4: usize = (USER_STACK_OFFSET & PML4_MASK) / PML4_SIZE;
/// Size of user stack
pub const USER_STACK_SIZE: usize = 1024 * 1024; // 1 MB

@ -73,14 +73,10 @@ impl TrapFrame {
tf.fpstate_offset = 16; // skip restoring for first time
tf
}
fn new_user_thread(entry_addr: usize, rsp: usize, is32: bool) -> Self {
fn new_user_thread(entry_addr: usize, rsp: usize) -> Self {
use crate::arch::gdt;
let mut tf = TrapFrame::default();
tf.cs = if is32 {
gdt::UCODE32_SELECTOR.0
} else {
gdt::UCODE_SELECTOR.0
} as usize;
tf.cs = gdt::UCODE_SELECTOR.0 as usize;
tf.rip = entry_addr;
tf.ss = gdt::UDATA32_SELECTOR.0 as usize;
tf.rsp = rsp;
@ -88,9 +84,6 @@ impl TrapFrame {
tf.fpstate_offset = 16; // skip restoring for first time
tf
}
pub fn is_user(&self) -> bool {
self.cs & 0x3 == 0x3
}
}
#[derive(Debug, Default)]
@ -203,12 +196,11 @@ impl Context {
entry_addr: usize,
ustack_top: usize,
kstack_top: usize,
is32: bool,
cr3: usize,
) -> Self {
InitStack {
context: ContextData::new(cr3),
tf: TrapFrame::new_user_thread(entry_addr, ustack_top, is32),
tf: TrapFrame::new_user_thread(entry_addr, ustack_top),
}
.push_at(kstack_top)
}

@ -123,24 +123,13 @@ impl rcore_thread::Context for Thread {
impl Thread {
/// Make a struct for the init thread
/// TODO: remove this, we only need `Context::null()`
pub unsafe fn new_init() -> Box<Thread> {
Box::new(Thread {
context: Context::null(),
kstack: KernelStack::new(),
clear_child_tid: 0,
proc: Arc::new(Mutex::new(Process {
vm: MemorySet::new(),
files: BTreeMap::default(),
cwd: String::from("/"),
futexes: BTreeMap::default(),
pid: Pid::uninitialized(),
parent: None,
children: Vec::new(),
threads: Vec::new(),
child_exit: Arc::new(Condvar::new()),
child_exit_code: BTreeMap::new(),
})),
// safety: this field will never be used
proc: core::mem::uninitialized(),
})
}
@ -175,10 +164,6 @@ impl Thread {
{
// Parse ELF
let elf = ElfFile::new(data).expect("failed to read elf");
let is32 = match elf.header.pt2 {
header::HeaderPt2::Header32(_) => true,
header::HeaderPt2::Header64(_) => false,
};
// Check ELF type
match elf.header.pt2.type_().as_type() {
@ -210,12 +195,10 @@ impl Thread {
let mut vm = elf.make_memory_set();
// User stack
use crate::consts::{USER32_STACK_OFFSET, USER_STACK_OFFSET, USER_STACK_SIZE};
use crate::consts::{USER_STACK_OFFSET, USER_STACK_SIZE};
let mut ustack_top = {
let (ustack_buttom, ustack_top) = match is32 {
true => (USER32_STACK_OFFSET, USER32_STACK_OFFSET + USER_STACK_SIZE),
false => (USER_STACK_OFFSET, USER_STACK_OFFSET + USER_STACK_SIZE),
};
let ustack_buttom = USER_STACK_OFFSET;
let ustack_top = USER_STACK_OFFSET + USER_STACK_SIZE;
vm.push(
ustack_buttom,
ustack_top,
@ -288,7 +271,7 @@ impl Thread {
Box::new(Thread {
context: unsafe {
Context::new_user_thread(entry_addr, ustack_top, kstack.top(), is32, vm.token())
Context::new_user_thread(entry_addr, ustack_top, kstack.top(), vm.token())
},
kstack,
clear_child_tid: 0,

@ -237,49 +237,24 @@ pub fn sys_openat(dir_fd: usize, path: *const u8, flags: usize, mode: usize) ->
dir_fd as isize, path, flags, mode
);
let inode = if dir_fd == AT_FDCWD {
// from process cwd
if flags.contains(OpenFlags::CREATE) {
let (dir_path, file_name) = split_path(&path);
// relative to cwd
let dir_inode = proc.lookup_inode(dir_path)?;
match dir_inode.find(file_name) {
Ok(file_inode) => {
if flags.contains(OpenFlags::EXCLUSIVE) {
return Err(SysError::EEXIST);
}
file_inode
let inode = if flags.contains(OpenFlags::CREATE) {
let (dir_path, file_name) = split_path(&path);
// relative to cwd
let dir_inode = proc.lookup_inode_at(dir_fd, dir_path)?;
match dir_inode.find(file_name) {
Ok(file_inode) => {
if flags.contains(OpenFlags::EXCLUSIVE) {
return Err(SysError::EEXIST);
}
Err(FsError::EntryNotFound) => {
dir_inode.create(file_name, FileType::File, mode as u32)?
}
Err(e) => return Err(SysError::from(e)),
file_inode
}
} else {
proc.lookup_inode(&path)?
}
} else {
// relative to dir_fd
let dir_file = proc.get_file(dir_fd)?;
if flags.contains(OpenFlags::CREATE) {
let (dir_path, file_name) = split_path(&path);
// relative to cwd
let dir_inode = dir_file.lookup_follow(dir_path, FOLLOW_MAX_DEPTH)?;
match dir_inode.find(file_name) {
Ok(file_inode) => {
if flags.contains(OpenFlags::EXCLUSIVE) {
return Err(SysError::EEXIST);
}
file_inode
}
Err(FsError::EntryNotFound) => {
dir_inode.create(file_name, FileType::File, mode as u32)?
}
Err(e) => return Err(SysError::from(e)),
Err(FsError::EntryNotFound) => {
dir_inode.create(file_name, FileType::File, mode as u32)?
}
} else {
dir_file.lookup_follow(&path, FOLLOW_MAX_DEPTH)?
Err(e) => return Err(SysError::from(e)),
}
} else {
proc.lookup_inode_at(dir_fd, &path)?
};
let fd = proc.get_free_fd();
@ -297,14 +272,22 @@ pub fn sys_close(fd: usize) -> SysResult {
}
pub fn sys_access(path: *const u8, mode: usize) -> SysResult {
sys_faccessat(AT_FDCWD, path, mode, 0)
}
pub fn sys_faccessat(dirfd: usize, path: *const u8, mode: usize, flags: usize) -> SysResult {
// TODO: check permissions based on uid/gid
let proc = process();
let path = unsafe { proc.vm.check_and_clone_cstr(path)? };
let flags = AtFlags::from_bits_truncate(flags);
if !proc.pid.is_init() {
// we trust pid 0 process
info!("access: path: {:?}, mode: {:#o}", path, mode);
info!(
"faccessat: dirfd: {}, path: {:?}, mode: {:#o}, flags: {:?}",
dirfd, path, mode, flags
);
}
let inode = proc.lookup_inode(&path)?;
let inode = proc.lookup_inode_at(dirfd, &path)?;
Ok(0)
}
@ -322,9 +305,9 @@ pub fn sys_getcwd(buf: *mut u8, len: usize) -> SysResult {
Ok(buf as usize)
}
pub fn sys_stat(path: *const u8, stat_ptr: *mut Stat) -> SysResult {
warn!("stat is partial implemented as lstat");
sys_lstat(path, stat_ptr)
pub fn sys_lstat(path: *const u8, stat_ptr: *mut Stat) -> SysResult {
warn!("lstat is partial implemented as stat");
sys_stat(path, stat_ptr)
}
pub fn sys_fstat(fd: usize, stat_ptr: *mut Stat) -> SysResult {
@ -333,20 +316,23 @@ pub fn sys_fstat(fd: usize, stat_ptr: *mut Stat) -> SysResult {
proc.vm.check_write_ptr(stat_ptr)?;
let file = proc.get_file(fd)?;
let stat = Stat::from(file.metadata()?);
// TODO: handle symlink
unsafe {
stat_ptr.write(stat);
}
Ok(0)
}
pub fn sys_lstat(path: *const u8, stat_ptr: *mut Stat) -> SysResult {
pub fn sys_fstatat(dirfd: usize, path: *const u8, stat_ptr: *mut Stat, flags: usize) -> SysResult {
let proc = process();
let path = unsafe { proc.vm.check_and_clone_cstr(path)? };
proc.vm.check_write_ptr(stat_ptr)?;
info!("lstat: path: {:?}, stat_ptr: {:?}", path, stat_ptr);
let flags = AtFlags::from_bits_truncate(flags);
info!(
"fstatat: dirfd: {}, path: {:?}, stat_ptr: {:?}, flags: {:?}",
dirfd, path, stat_ptr, flags
);
let inode = proc.lookup_inode(&path)?;
let inode = proc.lookup_inode_at(dirfd, &path)?;
let stat = Stat::from(inode.metadata()?);
unsafe {
stat_ptr.write(stat);
@ -354,13 +340,21 @@ pub fn sys_lstat(path: *const u8, stat_ptr: *mut Stat) -> SysResult {
Ok(0)
}
pub fn sys_stat(path: *const u8, stat_ptr: *mut Stat) -> SysResult {
sys_fstatat(AT_FDCWD, path, stat_ptr, 0)
}
pub fn sys_readlink(path: *const u8, base: *mut u8, len: usize) -> SysResult {
sys_readlinkat(AT_FDCWD, path, base, len)
}
pub fn sys_readlinkat(dirfd: usize, path: *const u8, base: *mut u8, len: usize) -> SysResult {
let proc = process();
let path = unsafe { proc.vm.check_and_clone_cstr(path)? };
proc.vm.check_write_array(base, len)?;
info!("readlink: path: {:?}, base: {:?}, len: {}", path, base, len);
let inode = proc.lookup_inode(&path)?;
let inode = proc.lookup_inode_at(dirfd, &path)?;
if inode.metadata()?.type_ == FileType::SymLink {
// TODO: recursive link resolution and loop detection
let mut slice = unsafe { slice::from_raw_parts_mut(base, len) };
@ -526,30 +520,27 @@ pub fn sys_renameat(
let (old_dir_path, old_file_name) = split_path(&oldpath);
let (new_dir_path, new_file_name) = split_path(&newpath);
let old_dir_inode = if olddirfd == AT_FDCWD {
proc.lookup_inode(old_dir_path)?
} else {
proc.get_file(olddirfd)?
.lookup_follow(old_dir_path, FOLLOW_MAX_DEPTH)?
};
let new_dir_inode = if newdirfd == AT_FDCWD {
proc.lookup_inode(new_dir_path)?
} else {
proc.get_file(newdirfd)?
.lookup_follow(new_dir_path, FOLLOW_MAX_DEPTH)?
};
let old_dir_inode = proc.lookup_inode_at(olddirfd, old_dir_path)?;
let new_dir_inode = proc.lookup_inode_at(newdirfd, new_dir_path)?;
old_dir_inode.move_(old_file_name, &new_dir_inode, new_file_name)?;
Ok(0)
}
pub fn sys_mkdir(path: *const u8, mode: usize) -> SysResult {
sys_mkdirat(AT_FDCWD, path, mode)
}
pub fn sys_mkdirat(dirfd: usize, path: *const u8, mode: usize) -> SysResult {
let proc = process();
let path = unsafe { proc.vm.check_and_clone_cstr(path)? };
// TODO: check pathname
info!("mkdir: path: {:?}, mode: {:#o}", path, mode);
info!(
"mkdirat: dirfd: {}, path: {:?}, mode: {:#o}",
dirfd, path, mode
);
let (dir_path, file_name) = split_path(&path);
let inode = proc.lookup_inode(dir_path)?;
let inode = proc.lookup_inode_at(dirfd, dir_path)?;
if inode.find(file_name).is_ok() {
return Err(SysError::EEXIST);
}
@ -573,25 +564,47 @@ pub fn sys_rmdir(path: *const u8) -> SysResult {
}
pub fn sys_link(oldpath: *const u8, newpath: *const u8) -> SysResult {
sys_linkat(AT_FDCWD, oldpath, AT_FDCWD, newpath, 0)
}
pub fn sys_linkat(
olddirfd: usize,
oldpath: *const u8,
newdirfd: usize,
newpath: *const u8,
flags: usize,
) -> SysResult {
let proc = process();
let oldpath = unsafe { proc.vm.check_and_clone_cstr(oldpath)? };
let newpath = unsafe { proc.vm.check_and_clone_cstr(newpath)? };
info!("link: oldpath: {:?}, newpath: {:?}", oldpath, newpath);
let flags = AtFlags::from_bits_truncate(flags);
info!(
"linkat: olddirfd: {}, oldpath: {:?}, newdirfd: {}, newpath: {:?}, flags: {:?}",
olddirfd, oldpath, newdirfd, newpath, flags
);
let (new_dir_path, new_file_name) = split_path(&newpath);
let inode = proc.lookup_inode(&oldpath)?;
let new_dir_inode = proc.lookup_inode(new_dir_path)?;
let inode = proc.lookup_inode_at(olddirfd, &oldpath)?;
let new_dir_inode = proc.lookup_inode_at(newdirfd, new_dir_path)?;
new_dir_inode.link(new_file_name, &inode)?;
Ok(0)
}
pub fn sys_unlink(path: *const u8) -> SysResult {
sys_unlinkat(AT_FDCWD, path, 0)
}
pub fn sys_unlinkat(dirfd: usize, path: *const u8, flags: usize) -> SysResult {
let proc = process();
let path = unsafe { proc.vm.check_and_clone_cstr(path)? };
info!("unlink: path: {:?}", path);
let flags = AtFlags::from_bits_truncate(flags);
info!(
"unlinkat: dirfd: {}, path: {:?}, flags: {:?}",
dirfd, path, flags
);
let (dir_path, file_name) = split_path(&path);
let dir_inode = proc.lookup_inode(dir_path)?;
let dir_inode = proc.lookup_inode_at(dirfd, dir_path)?;
let file_inode = dir_inode.find(file_name)?;
if file_inode.metadata()?.type_ == FileType::Dir {
return Err(SysError::EISDIR);
@ -723,11 +736,44 @@ impl Process {
_ => Err(SysError::EBADF),
}
}
/// Lookup INode from the process.
///
/// - If `path` is relative, then it is interpreted relative to the directory
/// referred to by the file descriptor `dirfd`.
///
/// - If the `dirfd` is the special value `AT_FDCWD`, then the directory is
/// current working directory of the process.
///
/// - If `path` is absolute, then `dirfd` is ignored.
///
/// - If `follow` is true, then dereference `path` if it is a symbolic link.
pub fn lookup_inode_at(
&self,
dirfd: usize,
path: &str,
// follow: bool,
) -> Result<Arc<INode>, SysError> {
let follow = true;
debug!(
"lookup_inode_at: fd: {:?}, cwd: {:?}, path: {:?}, follow: {:?}",
dirfd, self.cwd, path, follow
);
let follow_max_depth = if follow { FOLLOW_MAX_DEPTH } else { 0 };
if dirfd == AT_FDCWD {
Ok(ROOT_INODE
.lookup(&self.cwd)?
.lookup_follow(path, follow_max_depth)?)
} else {
let file = match self.files.get(&dirfd).ok_or(SysError::EBADF)? {
FileLike::File(file) => file,
_ => return Err(SysError::EBADF),
};
Ok(file.lookup_follow(path, follow_max_depth)?)
}
}
pub fn lookup_inode(&self, path: &str) -> Result<Arc<INode>, SysError> {
debug!("lookup_inode: cwd {} path {}", self.cwd, path);
Ok(ROOT_INODE
.lookup(&self.cwd)?
.lookup_follow(path, FOLLOW_MAX_DEPTH)?)
self.lookup_inode_at(AT_FDCWD, path)
}
}
@ -762,6 +808,13 @@ impl From<FsError> for SysError {
}
}
bitflags! {
struct AtFlags: usize {
const EMPTY_PATH = 0x1000;
const SYMLINK_NOFOLLOW = 0x100;
}
}
bitflags! {
struct OpenFlags: usize {
/// read only

@ -244,20 +244,21 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
}
SYS_CLOCK_GETTIME => sys_clock_gettime(args[0], args[1] as *mut TimeSpec),
SYS_EXIT_GROUP => sys_exit_group(args[0]),
SYS_OPENAT => sys_openat(args[0], args[1] as *const u8, args[2], args[3]), // TODO: handle `dfd`
SYS_MKDIRAT => sys_mkdir(args[1] as *const u8, args[2]), // TODO: handle `dfd`
SYS_OPENAT => sys_openat(args[0], args[1] as *const u8, args[2], args[3]),
SYS_MKDIRAT => sys_mkdirat(args[0], args[1] as *const u8, args[2]),
// SYS_MKNODAT => sys_mknod(),
// 260
SYS_FCHOWNAT => {
warn!("sys_fchownat is unimplemented");
Ok(0)
}
SYS_NEWFSTATAT => sys_stat(args[1] as *const u8, args[2] as *mut Stat), // TODO: handle `dfd`, `flag`
SYS_UNLINKAT => sys_unlink(args[1] as *const u8), // TODO: handle `dfd`, `flag`
SYS_RENAMEAT => sys_renameat(args[0], args[1] as *const u8, args[2], args[3] as *const u8), // TODO: handle `olddfd`, `newdfd`
SYS_LINKAT => sys_link(args[1] as *const u8, args[3] as *const u8), // TODO: handle `olddfd`, `newdfd`, `flags`
SYS_NEWFSTATAT => sys_fstatat(args[0], args[1] as *const u8, args[2] as *mut Stat, args[3]),
SYS_UNLINKAT => sys_unlinkat(args[0], args[1] as *const u8, args[2]),
SYS_READLINKAT => sys_readlinkat(args[0], args[1] as *const u8, args[2] as *mut u8, args[3]),
SYS_RENAMEAT => sys_renameat(args[0], args[1] as *const u8, args[2], args[3] as *const u8),
SYS_LINKAT => sys_linkat(args[0], args[1] as *const u8, args[2], args[3] as *const u8, args[4]),
SYS_SYMLINKAT => Err(SysError::EACCES),
SYS_FACCESSAT => sys_access(args[1] as *const u8, args[2]), // TODO: handle `dfd`
SYS_FACCESSAT => sys_faccessat(args[0], args[1] as *const u8, args[2], args[3]),
// 280
SYS_UTIMENSAT => {
warn!("sys_utimensat is unimplemented");

Loading…
Cancel
Save