Implement tls setup code(not working yet), tcp sys_bind and sys_connect

master
Jiajie Chen 6 years ago
parent 82e273df58
commit a51b9dbd90

@ -136,6 +136,14 @@ impl MemoryAttr {
self
}
/*
** @brief unset the memory attribute's readonly bit
** @retval MemoryAttr the memory attribute itself
*/
pub fn writable(mut self) -> Self {
self.readonly = false;
self
}
/*
** @brief set the memory attribute's execute bit
** @retval MemoryAttr the memory attribute itself
*/

@ -40,7 +40,7 @@ impl Cpu {
}
unsafe fn init(&'static mut self) {
use x86_64::instructions::segmentation::set_cs;
use x86_64::instructions::segmentation::{set_cs, load_fs};
use x86_64::instructions::tables::load_tss;
// Set the stack when DoubleFault occurs

@ -48,7 +48,7 @@ impl TrapFrame {
tf.rflags = 0x282;
tf
}
fn new_user_thread(entry_addr: usize, rsp: usize, is32: bool) -> Self {
fn new_user_thread(entry_addr: usize, rsp: usize, is32: bool, tls: 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;
@ -56,6 +56,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.fsbase = tls;
tf
}
pub fn is_user(&self) -> bool {
@ -166,11 +167,11 @@ impl Context {
tf: TrapFrame::new_kernel_thread(entry, arg, kstack_top),
}.push_at(kstack_top)
}
pub unsafe fn new_user_thread(entry_addr: usize, ustack_top: usize, kstack_top: usize, is32: bool, cr3: usize) -> Self {
pub unsafe fn new_user_thread(entry_addr: usize, ustack_top: usize, kstack_top: usize, is32: bool, cr3: usize, tls: usize) -> Self {
InitStack {
context: ContextData::new(cr3),
trapret: trap_ret as usize,
tf: TrapFrame::new_user_thread(entry_addr, ustack_top, is32),
tf: TrapFrame::new_user_thread(entry_addr, ustack_top, is32, tls),
}.push_at(kstack_top)
}
pub unsafe fn new_fork(tf: &TrapFrame, kstack_top: usize, cr3: usize) -> Self {

@ -5,12 +5,14 @@ use rcore_fs::vfs::INode;
use spin::Mutex;
use xmas_elf::{ElfFile, header, program::{Flags, Type}};
use smoltcp::socket::{SocketSet, SocketHandle};
use smoltcp::wire::IpEndpoint;
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};
@ -24,7 +26,7 @@ pub struct Thread {
#[derive(Clone)]
pub enum SocketType {
Raw,
Tcp,
Tcp(Option<IpEndpoint>), // save local endpoint for bind()
Udp,
Icmp
}
@ -106,7 +108,7 @@ impl Thread {
}
// Make page table
let (mut memory_set, entry_addr) = memory_set_from(&elf);
let (mut memory_set, entry_addr, tls) = memory_set_from(&elf);
// User stack
use crate::consts::{USER_STACK_OFFSET, USER_STACK_SIZE, USER32_STACK_OFFSET};
@ -152,7 +154,7 @@ impl Thread {
Box::new(Thread {
context: unsafe {
Context::new_user_thread(
entry_addr, ustack_top, kstack.top(), is32, memory_set.token())
entry_addr, ustack_top, kstack.top(), is32, memory_set.token(), tls)
},
kstack,
proc: Arc::new(Mutex::new(Process {
@ -203,11 +205,12 @@ impl Process {
/// Generate a MemorySet according to the ELF file.
/// Also return the real entry point address.
fn memory_set_from(elf: &ElfFile<'_>) -> (MemorySet, usize) {
/// Also return the real entry point address and tls top addr.
fn memory_set_from(elf: &ElfFile<'_>) -> (MemorySet, usize, usize) {
debug!("come in to memory_set_from");
let mut ms = MemorySet::new();
let mut entry = elf.header.pt2.entry_point() as usize;
let mut tls = 0;
// [NoMMU] Get total memory size and alloc space
let va_begin = elf.program_iter()
@ -225,14 +228,19 @@ fn memory_set_from(elf: &ElfFile<'_>) -> (MemorySet, usize) {
{ entry += 0x40000000; }
for ph in elf.program_iter() {
if ph.get_type() != Ok(Type::Load) {
if ph.get_type() != Ok(Type::Load) && ph.get_type() != Ok(Type::Tls) {
continue;
}
let virt_addr = ph.virtual_addr() as usize;
let mut virt_addr = ph.virtual_addr() as usize;
let offset = ph.offset() as usize;
let file_size = ph.file_size() as usize;
let mem_size = ph.mem_size() as usize;
if ph.get_type() == Ok(Type::Tls) {
virt_addr = USER_TLS_OFFSET;
}
#[cfg(target_arch = "aarch64")]
assert_eq!((virt_addr >> 48), 0xffff, "Segment Fault");
@ -255,8 +263,35 @@ fn memory_set_from(elf: &ElfFile<'_>) -> (MemorySet, usize) {
target[file_size..].iter_mut().for_each(|x| *x = 0);
});
}
if ph.get_type() == Ok(Type::Tls) {
virt_addr = USER_TMP_TLS_OFFSET;
tls = virt_addr + ph.mem_size() as usize;
debug!("tls addr {:X}", tls);
// TODO: put this in a function
// Get target slice
#[cfg(feature = "no_mmu")]
let target = &mut target[virt_addr - va_begin..virt_addr - va_begin + mem_size];
#[cfg(feature = "no_mmu")]
info!("area @ {:?}, size = {:#x}", target.as_ptr(), mem_size);
#[cfg(not(feature = "no_mmu"))]
let target = {
ms.push(virt_addr, virt_addr + mem_size, ByFrame::new(memory_attr_from(ph.flags()).writable(), GlobalFrameAlloc), "");
unsafe { ::core::slice::from_raw_parts_mut(virt_addr as *mut u8, mem_size) }
};
// Copy data
unsafe {
ms.with(|| {
if file_size != 0 {
target[..file_size].copy_from_slice(&elf.input[offset..offset + file_size]);
}
target[file_size..].iter_mut().for_each(|x| *x = 0);
});
}
}
}
(ms, entry)
(ms, entry, tls)
}
fn memory_attr_from(elf_flags: Flags) -> MemoryAttr {

@ -59,8 +59,8 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
// 046 => sys_sendmsg(),
// 047 => sys_recvmsg(),
// 048 => sys_shutdown(),
// 049 => sys_bind(),
// 050 => sys_listen(),
049 => sys_bind(args[0], args[1] as *const u8, args[2]),
050 => sys_listen(args[0], args[1]),
054 => sys_setsockopt(args[0], args[1], args[2], args[3] as *const u8, args[4]),
// 055 => sys_getsockopt(),
// 056 => sys_clone(),

@ -77,7 +77,7 @@ pub fn sys_socket(domain: usize, socket_type: usize, protocol: usize) -> SysResu
fd,
FileLike::Socket(SocketWrapper {
handle: tcp_handle,
socket_type: SocketType::Tcp,
socket_type: SocketType::Tcp(None),
}),
);
@ -164,6 +164,14 @@ impl Process {
_ => Err(SysError::ENOTSOCK),
}
}
fn get_socket_mut(&mut self, fd: usize) -> Result<&mut SocketWrapper, SysError> {
let file = self.files.get_mut(&fd).ok_or(SysError::EBADF)?;
match file {
FileLike::Socket(ref mut wrapper) => Ok(wrapper),
_ => Err(SysError::ENOTSOCK),
}
}
}
pub fn sys_connect(fd: usize, addr: *const u8, addrlen: usize) -> SysResult {
@ -188,7 +196,7 @@ pub fn sys_connect(fd: usize, addr: *const u8, addrlen: usize) -> SysResult {
}
let wrapper = proc.get_socket(fd)?;
if let SocketType::Tcp = wrapper.socket_type {
if let SocketType::Tcp(_) = wrapper.socket_type {
let mut sockets = iface.sockets();
let mut socket = sockets.get::<TcpSocket>(wrapper.handle);
@ -229,7 +237,7 @@ pub fn sys_connect(fd: usize, addr: *const u8, addrlen: usize) -> SysResult {
pub fn sys_write_socket(proc: &mut Process, fd: usize, base: *const u8, len: usize) -> SysResult {
let iface = &mut *(NET_DRIVERS.lock()[0]);
let wrapper = proc.get_socket(fd)?;
if let SocketType::Tcp = wrapper.socket_type {
if let SocketType::Tcp(_) = wrapper.socket_type {
let mut sockets = iface.sockets();
let mut socket = sockets.get::<TcpSocket>(wrapper.handle);
@ -261,7 +269,7 @@ pub fn sys_write_socket(proc: &mut Process, fd: usize, base: *const u8, len: usi
pub fn sys_read_socket(proc: &mut Process, fd: usize, base: *mut u8, len: usize) -> SysResult {
let iface = &mut *(NET_DRIVERS.lock()[0]);
let wrapper = proc.get_socket(fd)?;
if let SocketType::Tcp = wrapper.socket_type {
if let SocketType::Tcp(_) = wrapper.socket_type {
loop {
let mut sockets = iface.sockets();
let mut socket = sockets.get::<TcpSocket>(wrapper.handle);
@ -517,3 +525,69 @@ pub fn sys_close_socket(proc: &mut Process, fd: usize, handle: SocketHandle) ->
Ok(0)
}
pub fn sys_bind(fd: usize, addr: *const u8, len: usize) -> SysResult {
let mut proc = process();
proc.memory_set.check_array(addr, len)?;
if len < size_of::<SockaddrIn>() {
return Err(SysError::EINVAL);
}
let mut host = None;
let mut port = 0;
let sockaddr_in = unsafe { &*(addr as *const SockaddrIn) };
parse_addr(&sockaddr_in, &mut host, &mut port);
if host == None {
return Err(SysError::EINVAL);
}
let iface = &mut *(NET_DRIVERS.lock()[0]);
let wrapper = proc.get_socket_mut(fd)?;
if let SocketType::Tcp(_) = wrapper.socket_type {
wrapper.socket_type = SocketType::Tcp(Some(IpEndpoint::new(host.unwrap(), port)));
Ok(0)
} else {
Err(SysError::EINVAL)
}
}
pub fn sys_listen(fd: usize, backlog: usize) -> SysResult {
// smoltcp tcp sockets do not support backlog
// open multiple sockets for each connection
let mut proc = process();
let iface = &mut *(NET_DRIVERS.lock()[0]);
let wrapper = proc.get_socket_mut(fd)?;
if let SocketType::Tcp(Some(endpoint)) = wrapper.socket_type {
let mut sockets = iface.sockets();
let mut socket = sockets.get::<TcpSocket>(wrapper.handle);
if let Err(_) = socket.listen(endpoint) {
return Err(SysError::EINVAL);
}
// avoid deadlock
drop(socket);
drop(sockets);
loop {
let mut sockets = iface.sockets();
let mut socket = sockets.get::<TcpSocket>(wrapper.handle);
if socket.is_active() {
// use the same one for now, but we should create a new one instead
return Ok(fd as isize);
}
// avoid deadlock
drop(socket);
drop(sockets);
SOCKET_ACTIVITY._wait()
}
} else {
Err(SysError::EINVAL)
}
}

@ -1 +1 @@
Subproject commit 64dac11ac304eece980ba4cffb2eac2040aa08b3
Subproject commit fb9a1d5f7014b3be4f4a234bcaecd069335a216c
Loading…
Cancel
Save