* Fire up multiple processors

* Use IPIs to wake up secondary processors

* Much better exception information

* Modifications to show more information on fault

* WIP: Use real libstd

* Add TLS (not complete)

* Add random function, export getpid, cleanup

* Do not spin APs until new context

* Update rust

* Update rust

* Use rd/wrfsbase

* Implement TLS

* Implement compiler builtins and update rust

* Update rust

* Back to Redox libstd

* Update rust
This commit is contained in:
Jeremy Soller 2016-10-31 10:49:00 -06:00 committed by GitHub
parent 25dc44b348
commit 149b0297a4
54 changed files with 1121 additions and 380 deletions

View file

@ -26,12 +26,14 @@ all: $(KBUILD)/harddrive.bin
clean: clean:
cargo clean cargo clean
cargo clean --manifest-path libstd/Cargo.toml cargo clean --manifest-path libstd/Cargo.toml
cargo clean --manifest-path libstd_real/Cargo.toml
cargo clean --manifest-path drivers/ahcid/Cargo.toml cargo clean --manifest-path drivers/ahcid/Cargo.toml
cargo clean --manifest-path drivers/e1000d/Cargo.toml cargo clean --manifest-path drivers/e1000d/Cargo.toml
cargo clean --manifest-path drivers/ps2d/Cargo.toml cargo clean --manifest-path drivers/ps2d/Cargo.toml
cargo clean --manifest-path drivers/pcid/Cargo.toml cargo clean --manifest-path drivers/pcid/Cargo.toml
cargo clean --manifest-path drivers/rtl8168d/Cargo.toml cargo clean --manifest-path drivers/rtl8168d/Cargo.toml
cargo clean --manifest-path drivers/vesad/Cargo.toml cargo clean --manifest-path drivers/vesad/Cargo.toml
cargo clean --manifest-path programs/acid/Cargo.toml
cargo clean --manifest-path programs/init/Cargo.toml cargo clean --manifest-path programs/init/Cargo.toml
cargo clean --manifest-path programs/ion/Cargo.toml cargo clean --manifest-path programs/ion/Cargo.toml
cargo clean --manifest-path programs/coreutils/Cargo.toml cargo clean --manifest-path programs/coreutils/Cargo.toml
@ -75,12 +77,14 @@ doc-%: schemes/%/Cargo.toml all FORCE
update: update:
cargo update cargo update
cargo update --manifest-path libstd/Cargo.toml cargo update --manifest-path libstd/Cargo.toml
cargo update --manifest-path libstd_real/Cargo.toml
cargo update --manifest-path drivers/ahcid/Cargo.toml cargo update --manifest-path drivers/ahcid/Cargo.toml
cargo update --manifest-path drivers/e1000d/Cargo.toml cargo update --manifest-path drivers/e1000d/Cargo.toml
cargo update --manifest-path drivers/ps2d/Cargo.toml cargo update --manifest-path drivers/ps2d/Cargo.toml
cargo update --manifest-path drivers/pcid/Cargo.toml cargo update --manifest-path drivers/pcid/Cargo.toml
cargo update --manifest-path drivers/rtl8168d/Cargo.toml cargo update --manifest-path drivers/rtl8168d/Cargo.toml
cargo update --manifest-path drivers/vesad/Cargo.toml cargo update --manifest-path drivers/vesad/Cargo.toml
cargo update --manifest-path programs/acid/Cargo.toml
cargo update --manifest-path programs/init/Cargo.toml cargo update --manifest-path programs/init/Cargo.toml
cargo update --manifest-path programs/ion/Cargo.toml cargo update --manifest-path programs/ion/Cargo.toml
cargo update --manifest-path programs/coreutils/Cargo.toml cargo update --manifest-path programs/coreutils/Cargo.toml
@ -211,16 +215,16 @@ $(BUILD)/libcore.rlib: rust/src/libcore/lib.rs
mkdir -p $(BUILD) mkdir -p $(BUILD)
$(RUSTC) $(RUSTCFLAGS) -o $@ $< $(RUSTC) $(RUSTCFLAGS) -o $@ $<
$(BUILD)/librand.rlib: rust/src/librand/lib.rs $(BUILD)/libcore.rlib
$(RUSTC) $(RUSTCFLAGS) -o $@ $<
$(BUILD)/liballoc.rlib: rust/src/liballoc/lib.rs $(BUILD)/libcore.rlib $(BUILD)/liballoc.rlib: rust/src/liballoc/lib.rs $(BUILD)/libcore.rlib
$(RUSTC) $(RUSTCFLAGS) -o $@ $< $(RUSTC) $(RUSTCFLAGS) -o $@ $<
$(BUILD)/librustc_unicode.rlib: rust/src/librustc_unicode/lib.rs $(BUILD)/libcore.rlib $(BUILD)/libcollections.rlib: rust/src/libcollections/lib.rs $(BUILD)/libcore.rlib $(BUILD)/liballoc.rlib $(BUILD)/librustc_unicode.rlib
$(RUSTC) $(RUSTCFLAGS) -o $@ $< $(RUSTC) $(RUSTCFLAGS) -o $@ $<
$(BUILD)/libcollections.rlib: rust/src/libcollections/lib.rs $(BUILD)/libcore.rlib $(BUILD)/liballoc.rlib $(BUILD)/librustc_unicode.rlib $(BUILD)/librand.rlib: rust/src/librand/lib.rs $(BUILD)/libcore.rlib
$(RUSTC) $(RUSTCFLAGS) -o $@ $<
$(BUILD)/librustc_unicode.rlib: rust/src/librustc_unicode/lib.rs $(BUILD)/libcore.rlib
$(RUSTC) $(RUSTCFLAGS) -o $@ $< $(RUSTC) $(RUSTCFLAGS) -o $@ $<
openlibm/libopenlibm.a: openlibm/libopenlibm.a:
@ -432,7 +436,7 @@ $(BUILD)/filesystem.bin: \
filesystem/bin/smith \ filesystem/bin/smith \
filesystem/bin/tar filesystem/bin/tar
rm -rf $@ $(BUILD)/filesystem/ rm -rf $@ $(BUILD)/filesystem/
echo exit | cargo run --manifest-path schemes/redoxfs/Cargo.toml --bin redoxfs-utility $@ 64 echo exit | cargo run --manifest-path schemes/redoxfs/Cargo.toml --bin redoxfs-utility $@ 128
mkdir -p $(BUILD)/filesystem/ mkdir -p $(BUILD)/filesystem/
cargo run --manifest-path schemes/redoxfs/Cargo.toml --bin redoxfs-fuse $@ $(BUILD)/filesystem/ & cargo run --manifest-path schemes/redoxfs/Cargo.toml --bin redoxfs-fuse $@ $(BUILD)/filesystem/ &
sleep 2 sleep 2

View file

@ -7,6 +7,7 @@ bitflags = "*"
hole_list_allocator = { path = "../../crates/hole_list_allocator/" } hole_list_allocator = { path = "../../crates/hole_list_allocator/" }
io = { path = "../../crates/io/" } io = { path = "../../crates/io/" }
spin = "*" spin = "*"
syscall = { path = "../../syscall/" }
[dependencies.x86] [dependencies.x86]
version = "0.7" version = "0.7"

View file

@ -1,77 +0,0 @@
use core::intrinsics::{volatile_load, volatile_store};
use x86::cpuid::CpuId;
use x86::msr::*;
use memory::Frame;
use paging::{entry, ActivePageTable, PhysicalAddress};
/// Local APIC
pub struct LocalApic {
pub address: u32,
pub x2: bool
}
impl LocalApic {
pub fn new(active_table: &mut ActivePageTable) -> Self {
let mut apic = LocalApic {
address: (unsafe { rdmsr(IA32_APIC_BASE) as u32 } & 0xFFFF0000),
x2: false
};
if CpuId::new().get_feature_info().unwrap().has_x2apic() {
unsafe { wrmsr(IA32_APIC_BASE, rdmsr(IA32_APIC_BASE) | 1 << 10) };
apic.x2 = true;
} else {
active_table.identity_map(Frame::containing_address(PhysicalAddress::new(apic.address as usize)), entry::PRESENT | entry::WRITABLE | entry::NO_EXECUTE);
}
apic
}
unsafe fn read(&self, reg: u32) -> u32 {
volatile_load((self.address + reg) as *const u32)
}
unsafe fn write(&self, reg: u32, value: u32) {
volatile_store((self.address + reg) as *mut u32, value);
}
pub fn id(&self) -> u32 {
if self.x2 {
unsafe { rdmsr(IA32_X2APIC_APICID) as u32 }
} else {
unsafe { self.read(0x20) }
}
}
pub fn version(&self) -> u32 {
if self.x2 {
unsafe { rdmsr(IA32_X2APIC_VERSION) as u32 }
} else {
unsafe { self.read(0x30) }
}
}
pub fn icr(&self) -> u64 {
if self.x2 {
unsafe { rdmsr(IA32_X2APIC_ICR) }
} else {
unsafe {
(self.read(0x310) as u64) << 32 | self.read(0x300) as u64
}
}
}
pub fn set_icr(&mut self, value: u64) {
if self.x2 {
unsafe { wrmsr(IA32_X2APIC_ICR, value); }
} else {
unsafe {
while self.read(0x300) & 1 << 12 == 1 << 12 {}
self.write(0x310, (value >> 32) as u32);
self.write(0x300, value as u32);
while self.read(0x300) & 1 << 12 == 1 << 12 {}
}
}
}
}

View file

@ -4,20 +4,19 @@
use core::intrinsics::{atomic_load, atomic_store}; use core::intrinsics::{atomic_load, atomic_store};
use core::sync::atomic::Ordering; use core::sync::atomic::Ordering;
use device::local_apic::LOCAL_APIC;
use interrupt; use interrupt;
use memory::{allocate_frames, Frame}; use memory::{allocate_frames, Frame};
use paging::{entry, ActivePageTable, Page, PhysicalAddress, VirtualAddress}; use paging::{entry, ActivePageTable, Page, PhysicalAddress, VirtualAddress};
use start::{kstart_ap, CPU_COUNT, AP_READY}; use start::{kstart_ap, CPU_COUNT, AP_READY};
use self::dmar::{Dmar, DmarEntry}; use self::dmar::{Dmar, DmarEntry};
use self::local_apic::LocalApic;
use self::madt::{Madt, MadtEntry}; use self::madt::{Madt, MadtEntry};
use self::rsdt::Rsdt; use self::rsdt::Rsdt;
use self::sdt::Sdt; use self::sdt::Sdt;
use self::xsdt::Xsdt; use self::xsdt::Xsdt;
pub mod dmar; pub mod dmar;
pub mod local_apic;
pub mod madt; pub mod madt;
pub mod rsdt; pub mod rsdt;
pub mod sdt; pub mod sdt;
@ -35,7 +34,7 @@ pub fn init_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) {
if let Some(madt) = Madt::new(sdt) { if let Some(madt) = Madt::new(sdt) {
println!(": {:>08X}: {}", madt.local_address, madt.flags); println!(": {:>08X}: {}", madt.local_address, madt.flags);
let mut local_apic = LocalApic::new(active_table); let mut local_apic = unsafe { &mut LOCAL_APIC };
let me = local_apic.id() as u8; let me = local_apic.id() as u8;
@ -60,7 +59,7 @@ pub fn init_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) {
} else { } else {
if ap_local_apic.flags & 1 == 1 { if ap_local_apic.flags & 1 == 1 {
// Increase CPU ID // Increase CPU ID
let cpu_id = CPU_COUNT.fetch_add(1, Ordering::SeqCst); CPU_COUNT.fetch_add(1, Ordering::SeqCst);
// Allocate a stack // Allocate a stack
let stack_start = allocate_frames(64).expect("no more frames in acpi stack_start").start_address().get() + ::KERNEL_OFFSET; let stack_start = allocate_frames(64).expect("no more frames in acpi stack_start").start_address().get() + ::KERNEL_OFFSET;
@ -75,7 +74,7 @@ pub fn init_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) {
// Set the ap_ready to 0, volatile // Set the ap_ready to 0, volatile
unsafe { atomic_store(ap_ready, 0) }; unsafe { atomic_store(ap_ready, 0) };
unsafe { atomic_store(ap_cpu_id, cpu_id as u64) }; unsafe { atomic_store(ap_cpu_id, ap_local_apic.id as u64) };
unsafe { atomic_store(ap_page_table, active_table.address() as u64) }; unsafe { atomic_store(ap_page_table, active_table.address() as u64) };
unsafe { atomic_store(ap_stack_start, stack_start as u64) }; unsafe { atomic_store(ap_stack_start, stack_start as u64) };
unsafe { atomic_store(ap_stack_end, stack_end as u64) }; unsafe { atomic_store(ap_stack_end, stack_end as u64) };

View file

@ -1,4 +1,4 @@
use core::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering}; use core::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT};
/// This must be used by the kernel to ensure that context switches are done atomically /// This must be used by the kernel to ensure that context switches are done atomically
/// Compare and exchange this to true when beginning a context switch on any CPU /// Compare and exchange this to true when beginning a context switch on any CPU
@ -106,13 +106,5 @@ impl Context {
asm!("mov $0, rbp" : "=r"(self.rbp) : : "memory" : "intel", "volatile"); asm!("mov $0, rbp" : "=r"(self.rbp) : : "memory" : "intel", "volatile");
asm!("mov rbp, $0" : : "r"(next.rbp) : "memory" : "intel", "volatile"); asm!("mov rbp, $0" : : "r"(next.rbp) : "memory" : "intel", "volatile");
asm!("call context_switch_unlock" : : : "memory" : "intel", "volatile");
} }
} }
/// Unset global lock, set inside of kernel
#[no_mangle]
pub extern fn context_switch_unlock(){
CONTEXT_SWITCH_LOCK.store(false, Ordering::SeqCst);
}

View file

@ -0,0 +1,114 @@
use core::intrinsics::{volatile_load, volatile_store};
use x86::cpuid::CpuId;
use x86::msr::*;
use memory::Frame;
use paging::{entry, ActivePageTable, PhysicalAddress, Page, VirtualAddress};
pub static mut LOCAL_APIC: LocalApic = LocalApic {
address: 0,
x2: false
};
pub unsafe fn init(active_table: &mut ActivePageTable) {
LOCAL_APIC.init(active_table);
}
pub unsafe fn init_ap() {
LOCAL_APIC.init_ap();
}
/// Local APIC
pub struct LocalApic {
pub address: usize,
pub x2: bool
}
impl LocalApic {
unsafe fn init(&mut self, active_table: &mut ActivePageTable) {
self.address = (rdmsr(IA32_APIC_BASE) as usize & 0xFFFF0000) + ::KERNEL_OFFSET;
self.x2 = CpuId::new().get_feature_info().unwrap().has_x2apic();
if ! self.x2 {
let page = Page::containing_address(VirtualAddress::new(self.address));
let frame = Frame::containing_address(PhysicalAddress::new(self.address - ::KERNEL_OFFSET));
active_table.map_to(page, frame, entry::PRESENT | entry::WRITABLE | entry::NO_EXECUTE);
}
self.init_ap();
}
unsafe fn init_ap(&mut self) {
if self.x2 {
wrmsr(IA32_APIC_BASE, rdmsr(IA32_APIC_BASE) | 1 << 10);
wrmsr(IA32_X2APIC_SIVR, 0x100);
} else {
self.write(0xF0, 0x100);
}
}
unsafe fn read(&self, reg: u32) -> u32 {
volatile_load((self.address + reg as usize) as *const u32)
}
unsafe fn write(&mut self, reg: u32, value: u32) {
volatile_store((self.address + reg as usize) as *mut u32, value);
}
pub fn id(&self) -> u32 {
if self.x2 {
unsafe { rdmsr(IA32_X2APIC_APICID) as u32 }
} else {
unsafe { self.read(0x20) }
}
}
pub fn version(&self) -> u32 {
if self.x2 {
unsafe { rdmsr(IA32_X2APIC_VERSION) as u32 }
} else {
unsafe { self.read(0x30) }
}
}
pub fn icr(&self) -> u64 {
if self.x2 {
unsafe { rdmsr(IA32_X2APIC_ICR) }
} else {
unsafe {
(self.read(0x310) as u64) << 32 | self.read(0x300) as u64
}
}
}
pub fn set_icr(&mut self, value: u64) {
if self.x2 {
unsafe { wrmsr(IA32_X2APIC_ICR, value); }
} else {
unsafe {
while self.read(0x300) & 1 << 12 == 1 << 12 {}
self.write(0x310, (value >> 32) as u32);
self.write(0x300, value as u32);
while self.read(0x300) & 1 << 12 == 1 << 12 {}
}
}
}
pub fn ipi(&mut self, apic_id: usize) {
let mut icr = 0x4040;
if self.x2 {
icr |= (apic_id as u64) << 32;
} else {
icr |= (apic_id as u64) << 56;
}
self.set_icr(icr);
}
pub unsafe fn eoi(&mut self) {
if self.x2 {
wrmsr(IA32_X2APIC_EOI, 0);
} else {
self.write(0xB0, 0);
}
}
}

View file

@ -1,7 +1,15 @@
use paging::ActivePageTable;
pub mod local_apic;
pub mod rtc; pub mod rtc;
pub mod serial; pub mod serial;
pub unsafe fn init(){ pub unsafe fn init(active_table: &mut ActivePageTable){
local_apic::init(active_table);
rtc::init(); rtc::init();
serial::init(); serial::init();
} }
pub unsafe fn init_ap() {
local_apic::init_ap();
}

View file

@ -58,6 +58,9 @@ pub unsafe fn init() {
IDT[46].set_func(irq::ata1); IDT[46].set_func(irq::ata1);
IDT[47].set_func(irq::ata2); IDT[47].set_func(irq::ata2);
// Set IPI handler (null)
IDT[0x40].set_func(ipi::ipi);
// Set syscall function // Set syscall function
IDT[0x80].set_func(syscall::syscall); IDT[0x80].set_func(syscall::syscall);
IDT[0x80].set_flags(IDT_PRESENT | IDT_RING_3 | IDT_INTERRUPT); IDT[0x80].set_flags(IDT_PRESENT | IDT_RING_3 | IDT_INTERRUPT);

View file

@ -1,115 +1,140 @@
use super::{halt, stack_trace}; use super::{halt, stack_trace};
interrupt!(divide_by_zero, { use syscall::flag::*;
print!("Divide by zero fault\n");
extern {
fn ksignal(signal: usize);
}
interrupt_stack!(divide_by_zero, stack, {
println!("Divide by zero fault at {:>02X}:{:>016X}", stack.cs, stack.rip);
ksignal(SIGFPE);
stack_trace(); stack_trace();
loop { halt(); } loop { halt(); }
}); });
interrupt!(debug, { interrupt_stack!(debug, stack, {
print!("Debug trap\n"); println!("Debug trap at {:>02X}:{:>016X}", stack.cs, stack.rip);
ksignal(SIGTRAP);
}); });
interrupt!(non_maskable, { interrupt_stack!(non_maskable, stack, {
print!("Non-maskable interrupt\n"); println!("Non-maskable interrupt at {:>02X}:{:>016X}", stack.cs, stack.rip);
}); });
interrupt!(breakpoint, { interrupt_stack!(breakpoint, stack, {
print!("Breakpoint trap\n"); println!("Breakpoint trap at {:>02X}:{:>016X}", stack.cs, stack.rip);
ksignal(SIGTRAP);
}); });
interrupt!(overflow, { interrupt_stack!(overflow, stack, {
print!("Overflow trap\n"); println!("Overflow trap at {:>02X}:{:>016X}", stack.cs, stack.rip);
ksignal(SIGFPE);
}); });
interrupt!(bound_range, { interrupt_stack!(bound_range, stack, {
print!("Bound range exceeded fault\n"); println!("Bound range exceeded fault at {:>02X}:{:>016X}", stack.cs, stack.rip);
ksignal(SIGSEGV);
stack_trace(); stack_trace();
loop { halt(); } loop { halt(); }
}); });
interrupt!(invalid_opcode, { interrupt_stack!(invalid_opcode, stack, {
print!("Invalid opcode fault\n"); println!("Invalid opcode fault at {:>02X}:{:>016X}", stack.cs, stack.rip);
ksignal(SIGILL);
stack_trace(); stack_trace();
loop { halt(); } loop { halt(); }
}); });
interrupt!(device_not_available, { interrupt_stack!(device_not_available, stack, {
print!("Device not available fault\n"); println!("Device not available fault at {:>02X}:{:>016X}", stack.cs, stack.rip);
ksignal(SIGILL);
stack_trace(); stack_trace();
loop { halt(); } loop { halt(); }
}); });
interrupt_error!(double_fault, { interrupt_error!(double_fault, stack, {
print!("Double fault\n"); println!("Double fault: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip);
ksignal(SIGSEGV);
stack_trace(); stack_trace();
loop { halt(); } loop { halt(); }
}); });
interrupt_error!(invalid_tss, { interrupt_error!(invalid_tss, stack, {
print!("Invalid TSS fault\n"); println!("Invalid TSS fault: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip);
ksignal(SIGSEGV);
stack_trace(); stack_trace();
loop { halt(); } loop { halt(); }
}); });
interrupt_error!(segment_not_present, { interrupt_error!(segment_not_present, stack, {
print!("Segment not present fault\n"); println!("Segment not present fault: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip);
ksignal(SIGSEGV);
stack_trace(); stack_trace();
loop { halt(); } loop { halt(); }
}); });
interrupt_error!(stack_segment, { interrupt_error!(stack_segment, stack, {
print!("Stack segment fault\n"); println!("Stack segment fault: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip);
ksignal(SIGSEGV);
stack_trace(); stack_trace();
loop { halt(); } loop { halt(); }
}); });
interrupt_error!(protection, { interrupt_error!(protection, stack, {
print!("Protection fault\n"); println!("Protection fault: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip);
ksignal(SIGSEGV);
stack_trace(); stack_trace();
loop { halt(); } loop { halt(); }
}); });
interrupt_error!(page, { interrupt_error!(page, stack, {
let cr2: usize; let cr2: usize;
asm!("mov rax, cr2" : "={rax}"(cr2) : : : "intel", "volatile"); asm!("mov rax, cr2" : "={rax}"(cr2) : : : "intel", "volatile");
println!("Page fault: {:>016X}", cr2); println!("Page fault: {:>02X}:{:>016X} at {:>02X}:{:>016X}", stack.code, cr2, stack.cs, stack.rip);
ksignal(SIGSEGV);
stack_trace(); stack_trace();
loop { halt(); } loop { halt(); }
}); });
interrupt!(fpu, { interrupt_stack!(fpu, stack, {
print!("FPU floating point fault\n"); println!("FPU floating point fault at {:>02X}:{:>016X}", stack.cs, stack.rip);
ksignal(SIGFPE);
stack_trace(); stack_trace();
loop { halt(); } loop { halt(); }
}); });
interrupt_error!(alignment_check, { interrupt_error!(alignment_check, stack, {
print!("Alignment check fault\n"); println!("Alignment check fault: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip);
ksignal(SIGBUS);
stack_trace(); stack_trace();
loop { halt(); } loop { halt(); }
}); });
interrupt!(machine_check, { interrupt_stack!(machine_check, stack, {
print!("Machine check fault\n"); println!("Machine check fault at {:>02X}:{:>016X}", stack.cs, stack.rip);
ksignal(SIGBUS);
stack_trace(); stack_trace();
loop { halt(); } loop { halt(); }
}); });
interrupt!(simd, { interrupt_stack!(simd, stack, {
print!("SIMD floating point fault\n"); println!("SIMD floating point fault at {:>02X}:{:>016X}", stack.cs, stack.rip);
ksignal(SIGFPE);
stack_trace(); stack_trace();
loop { halt(); } loop { halt(); }
}); });
interrupt!(virtualization, { interrupt_stack!(virtualization, stack, {
print!("Virtualization fault\n"); println!("Virtualization fault at {:>02X}:{:>016X}", stack.cs, stack.rip);
ksignal(SIGBUS);
stack_trace(); stack_trace();
loop { halt(); } loop { halt(); }
}); });
interrupt_error!(security, { interrupt_error!(security, stack, {
print!("Security exception\n"); println!("Security exception: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip);
ksignal(SIGBUS);
stack_trace(); stack_trace();
loop { halt(); } loop { halt(); }
}); });

View file

@ -0,0 +1,5 @@
use device::local_apic::LOCAL_APIC;
interrupt!(ipi, {
LOCAL_APIC.eoi();
});

View file

@ -5,6 +5,7 @@ use core::mem;
use paging::{ActivePageTable, VirtualAddress}; use paging::{ActivePageTable, VirtualAddress};
pub mod exception; pub mod exception;
pub mod ipi;
pub mod irq; pub mod irq;
pub mod syscall; pub mod syscall;

View file

@ -23,17 +23,21 @@ pub unsafe extern fn syscall() {
asm!("" : : "{rax}"(a) : : "intel", "volatile"); asm!("" : : "{rax}"(a) : : "intel", "volatile");
} }
asm!("push fs asm!("push r15
push rax rdfsbase r15
mov rax, 0x18 push r15
mov fs, ax push fs
pop rax" mov r15, 0x18
mov fs, r15"
: : : : "intel", "volatile"); : : : : "intel", "volatile");
inner(); inner();
// Interrupt return // Interrupt return
asm!("pop fs asm!("pop fs
pop r15
wrfsbase r15
pop r15
iretq" iretq"
: : : : "intel", "volatile"); : : : : "intel", "volatile");
} }

View file

@ -17,6 +17,7 @@ extern crate hole_list_allocator as allocator;
extern crate bitflags; extern crate bitflags;
extern crate io; extern crate io;
extern crate spin; extern crate spin;
extern crate syscall;
pub extern crate x86; pub extern crate x86;
// Because the memory map is so important to not be aliased, it is defined here, in one place // Because the memory map is so important to not be aliased, it is defined here, in one place
@ -40,7 +41,7 @@ pub extern crate x86;
/// Offset to kernel percpu variables /// Offset to kernel percpu variables
//TODO: Use 64-bit fs offset to enable this pub const KERNEL_PERCPU_OFFSET: usize = KERNEL_HEAP_OFFSET - PML4_SIZE; //TODO: Use 64-bit fs offset to enable this pub const KERNEL_PERCPU_OFFSET: usize = KERNEL_HEAP_OFFSET - PML4_SIZE;
pub const KERNEL_PERCPU_OFFSET: usize = 0xC0000000; pub const KERNEL_PERCPU_OFFSET: usize = 0xC000_0000;
/// Size of kernel percpu variables /// Size of kernel percpu variables
pub const KERNEL_PERCPU_SIZE: usize = 64 * 1024; // 64 KB pub const KERNEL_PERCPU_SIZE: usize = 64 * 1024; // 64 KB
@ -61,8 +62,11 @@ pub extern crate x86;
/// Size of user stack /// Size of user stack
pub const USER_STACK_SIZE: usize = 1024 * 1024; // 1 MB pub const USER_STACK_SIZE: usize = 1024 * 1024; // 1 MB
/// Offset to user TLS
pub const USER_TLS_OFFSET: usize = USER_STACK_OFFSET + PML4_SIZE;
/// Offset to user temporary image (used when cloning) /// Offset to user temporary image (used when cloning)
pub const USER_TMP_OFFSET: usize = USER_STACK_OFFSET + PML4_SIZE; pub const USER_TMP_OFFSET: usize = USER_TLS_OFFSET + PML4_SIZE;
/// Offset to user temporary heap (used when cloning) /// Offset to user temporary heap (used when cloning)
pub const USER_TMP_HEAP_OFFSET: usize = USER_TMP_OFFSET + PML4_SIZE; pub const USER_TMP_HEAP_OFFSET: usize = USER_TMP_OFFSET + PML4_SIZE;
@ -73,6 +77,9 @@ pub extern crate x86;
/// Offset to user temporary stack (used when cloning) /// Offset to user temporary stack (used when cloning)
pub const USER_TMP_STACK_OFFSET: usize = USER_TMP_GRANT_OFFSET + PML4_SIZE; pub const USER_TMP_STACK_OFFSET: usize = USER_TMP_GRANT_OFFSET + PML4_SIZE;
/// Offset to user temporary tls (used when cloning)
pub const USER_TMP_TLS_OFFSET: usize = USER_TMP_STACK_OFFSET + PML4_SIZE;
/// Print to console /// Print to console
#[macro_export] #[macro_export]
@ -111,6 +118,8 @@ macro_rules! interrupt {
push r9 push r9
push r10 push r10
push r11 push r11
rdfsbase rax
push rax
push fs push fs
mov rax, 0x18 mov rax, 0x18
mov fs, ax" mov fs, ax"
@ -121,6 +130,8 @@ macro_rules! interrupt {
// Pop scratch registers and return // Pop scratch registers and return
asm!("pop fs asm!("pop fs
pop rax
wrfsbase rax
pop r11 pop r11
pop r10 pop r10
pop r9 pop r9
@ -136,13 +147,101 @@ macro_rules! interrupt {
}; };
} }
#[repr(packed)]
pub struct InterruptStack {
fs: usize,
r11: usize,
r10: usize,
r9: usize,
r8: usize,
rsi: usize,
rdi: usize,
rdx: usize,
rcx: usize,
rax: usize,
rip: usize,
cs: usize,
rflags: usize,
}
#[macro_export] #[macro_export]
macro_rules! interrupt_error { macro_rules! interrupt_stack {
($name:ident, $func:block) => { ($name:ident, $stack: ident, $func:block) => {
#[naked] #[naked]
pub unsafe extern fn $name () { pub unsafe extern fn $name () {
#[inline(never)] #[inline(never)]
unsafe fn inner() { unsafe fn inner($stack: &$crate::InterruptStack) {
$func
}
// Push scratch registers
asm!("push rax
push rcx
push rdx
push rdi
push rsi
push r8
push r9
push r10
push r11
rdfsbase rax
push rax
push fs
mov rax, 0x18
mov fs, ax"
: : : : "intel", "volatile");
// Get reference to stack variables
let rsp: usize;
asm!("" : "={rsp}"(rsp) : : : "intel", "volatile");
// Call inner rust function
inner(&*(rsp as *const $crate::InterruptStack));
// Pop scratch registers and return
asm!("pop fs
pop rax
wrfsbase rax
pop r11
pop r10
pop r9
pop r8
pop rsi
pop rdi
pop rdx
pop rcx
pop rax
iretq"
: : : : "intel", "volatile");
}
};
}
#[repr(packed)]
pub struct InterruptErrorStack {
fs: usize,
r11: usize,
r10: usize,
r9: usize,
r8: usize,
rsi: usize,
rdi: usize,
rdx: usize,
rcx: usize,
rax: usize,
code: usize,
rip: usize,
cs: usize,
rflags: usize,
}
#[macro_export]
macro_rules! interrupt_error {
($name:ident, $stack:ident, $func:block) => {
#[naked]
pub unsafe extern fn $name () {
#[inline(never)]
unsafe fn inner($stack: &$crate::InterruptErrorStack) {
$func $func
} }
@ -162,8 +261,12 @@ macro_rules! interrupt_error {
mov fs, ax" mov fs, ax"
: : : : "intel", "volatile"); : : : : "intel", "volatile");
// Get reference to stack variables
let rsp: usize;
asm!("" : "={rsp}"(rsp) : : : "intel", "volatile");
// Call inner rust function // Call inner rust function
inner(); inner(&*(rsp as *const $crate::InterruptErrorStack));
// Pop scratch registers, error code, and return // Pop scratch registers, error code, and return
asm!("pop fs asm!("pop fs

View file

@ -109,7 +109,7 @@ pub unsafe extern fn kstart() -> ! {
} }
// Initialize devices // Initialize devices
device::init(); device::init(&mut active_table);
// Read ACPI tables, starts APs // Read ACPI tables, starts APs
acpi::init(&mut active_table); acpi::init(&mut active_table);
@ -145,6 +145,9 @@ pub unsafe extern fn kstart_ap(cpu_id: usize, bsp_table: usize, stack_start: usi
assert_eq!(TDATA_TEST_NONZERO, 0xFFFFFFFFFFFFFFFE); assert_eq!(TDATA_TEST_NONZERO, 0xFFFFFFFFFFFFFFFE);
} }
// Initialize devices (for AP)
device::init_ap();
AP_READY.store(true, Ordering::SeqCst); AP_READY.store(true, Ordering::SeqCst);
} }
@ -155,24 +158,27 @@ pub unsafe extern fn kstart_ap(cpu_id: usize, bsp_table: usize, stack_start: usi
kmain_ap(cpu_id); kmain_ap(cpu_id);
} }
pub unsafe fn usermode(ip: usize, sp: usize) -> ! { pub unsafe fn usermode(ip: usize, sp: usize, fs: usize) -> ! {
// Go to usermode // Go to usermode
asm!("mov ds, ax asm!("xchg bx, bx
mov ds, ax
mov es, ax mov es, ax
mov fs, ax mov fs, ax
mov gs, ax mov gs, ax
wrfsbase rbx
push rax push rax
push rbx
push rcx push rcx
push rdx push rdx
push rsi push rsi
push rdi
iretq" iretq"
: // No output because it never returns : // No output because it never returns
: "{rax}"(gdt::GDT_USER_DATA << 3 | 3), // Stack segment : "{rax}"(gdt::GDT_USER_DATA << 3 | 3), // Data segment
"{rbx}"(sp), // Stack pointer "{rbx}"(fs), // TLS segment
"{rcx}"(3 << 12 | 1 << 9), // Flags - Set IOPL and interrupt enable flag "{rcx}"(sp), // Stack pointer
"{rdx}"(gdt::GDT_USER_CODE << 3 | 3), // Code segment "{rdx}"(3 << 12 | 1 << 9), // Flags - Set IOPL and interrupt enable flag
"{rsi}"(ip) // IP "{rsi}"(gdt::GDT_USER_CODE << 3 | 3), // Code segment
"{rdi}"(ip) // IP
: // No clobers because it never returns : // No clobers because it never returns
: "intel", "volatile"); : "intel", "volatile");
unreachable!(); unreachable!();

View file

@ -26,9 +26,9 @@ startup_ap:
mov edi, 0x70000 mov edi, 0x70000
mov cr3, edi mov cr3, edi
;enable Page Global, Page Address Extension, and Page Size Extension ;enable FSGSBASE, FXSAVE/FXRSTOR, Page Global, Page Address Extension, and Page Size Extension
mov eax, cr4 mov eax, cr4
or eax, 1 << 7 | 1 << 5 | 1 << 4 or eax, 1 << 16 | 1 << 9 | 1 << 7 | 1 << 5 | 1 << 4
mov cr4, eax mov cr4, eax
; load protected mode GDT ; load protected mode GDT
@ -91,9 +91,9 @@ startup_arch:
mov edi, 0x70000 mov edi, 0x70000
mov cr3, edi mov cr3, edi
;enable Page Global, Page Address Extension, and Page Size Extension ;enable FSGSBASE, FXSAVE/FXRSTOR, Page Global, Page Address Extension, and Page Size Extension
mov eax, cr4 mov eax, cr4
or eax, 1 << 7 | 1 << 5 | 1 << 4 or eax, 1 << 16 | 1 << 9 | 1 << 7 | 1 << 5 | 1 << 4
mov cr4, eax mov cr4, eax
; load protected mode GDT ; load protected mode GDT

View file

@ -31,7 +31,7 @@ impl<R> EventQueue<R> {
/// Err can be used to allow the callback to return an I/O error, and break the /// Err can be used to allow the callback to return an I/O error, and break the
/// event loop /// event loop
pub fn add<F: FnMut(usize) -> Result<Option<R>> + 'static>(&mut self, fd: RawFd, callback: F) -> Result<()> { pub fn add<F: FnMut(usize) -> Result<Option<R>> + 'static>(&mut self, fd: RawFd, callback: F) -> Result<()> {
syscall::fevent(fd, syscall::EVENT_READ).map_err(|x| Error::from_sys(x))?; syscall::fevent(fd, syscall::EVENT_READ).map_err(|x| Error::from_raw_os_error(x.errno))?;
self.callbacks.insert(fd, Box::new(callback)); self.callbacks.insert(fd, Box::new(callback));
@ -41,7 +41,7 @@ impl<R> EventQueue<R> {
/// Remove a file from the event queue, returning its callback if found /// Remove a file from the event queue, returning its callback if found
pub fn remove(&mut self, fd: RawFd) -> Result<Option<Box<FnMut(usize) -> Result<Option<R>>>>> { pub fn remove(&mut self, fd: RawFd) -> Result<Option<Box<FnMut(usize) -> Result<Option<R>>>>> {
if let Some(callback) = self.callbacks.remove(&fd) { if let Some(callback) = self.callbacks.remove(&fd) {
syscall::fevent(fd, 0).map_err(|x| Error::from_sys(x))?; syscall::fevent(fd, 0).map_err(|x| Error::from_raw_os_error(x.errno))?;
Ok(Some(callback)) Ok(Some(callback))
} else { } else {

View file

@ -30,11 +30,6 @@ fn main() {
print!("{}", format!(" + AHCI on: {:X} IRQ: {}\n", bar, irq)); print!("{}", format!(" + AHCI on: {:X} IRQ: {}\n", bar, irq));
thread::spawn(move || { thread::spawn(move || {
unsafe {
syscall::iopl(3).expect("ahcid: failed to get I/O permission");
asm!("cli" :::: "intel", "volatile");
}
let address = unsafe { syscall::physmap(bar, 4096, MAP_WRITE).expect("ahcid: failed to map address") }; let address = unsafe { syscall::physmap(bar, 4096, MAP_WRITE).expect("ahcid: failed to map address") };
{ {
let socket_fd = syscall::open(":disk", syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK).expect("ahcid: failed to create disk scheme"); let socket_fd = syscall::open(":disk", syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK).expect("ahcid: failed to create disk scheme");
@ -56,7 +51,7 @@ fn main() {
let mut packet = Packet::default(); let mut packet = Packet::default();
if socket.read(&mut packet).expect("ahcid: failed to read disk scheme") == 0 { if socket.read(&mut packet).expect("ahcid: failed to read disk scheme") == 0 {
break; break;
} }
scheme.handle(&mut packet); scheme.handle(&mut packet);
socket.write(&mut packet).expect("ahcid: failed to write disk scheme"); socket.write(&mut packet).expect("ahcid: failed to write disk scheme");
} }

View file

@ -30,11 +30,6 @@ fn main() {
print!("{}", format!(" + E1000 on: {:X}, IRQ: {}\n", bar, irq)); print!("{}", format!(" + E1000 on: {:X}, IRQ: {}\n", bar, irq));
thread::spawn(move || { thread::spawn(move || {
unsafe {
syscall::iopl(3).expect("e1000d: failed to get I/O permission");
asm!("cli" :::: "intel", "volatile");
}
let socket_fd = syscall::open(":network", syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK).expect("e1000d: failed to create network scheme"); let socket_fd = syscall::open(":network", syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK).expect("e1000d: failed to create network scheme");
let socket = Arc::new(RefCell::new(unsafe { File::from_raw_fd(socket_fd) })); let socket = Arc::new(RefCell::new(unsafe { File::from_raw_fd(socket_fd) }));

View file

@ -122,7 +122,7 @@ fn main() {
thread::spawn(|| { thread::spawn(|| {
unsafe { unsafe {
iopl(3).expect("ps2d: failed to get I/O permission"); iopl(3).expect("ps2d: failed to get I/O permission");
asm!("cli" :::: "intel", "volatile"); asm!("cli" : : : : "intel", "volatile");
} }
let input = File::open("display:input").expect("ps2d: failed to open display:input"); let input = File::open("display:input").expect("ps2d: failed to open display:input");

View file

@ -31,11 +31,6 @@ fn main() {
print!("{}", format!(" + RTL8168 on: {:X}, IRQ: {}\n", bar, irq)); print!("{}", format!(" + RTL8168 on: {:X}, IRQ: {}\n", bar, irq));
thread::spawn(move || { thread::spawn(move || {
unsafe {
syscall::iopl(3).expect("rtl8168d: failed to get I/O permission");
asm!("cli" :::: "intel", "volatile");
}
let socket_fd = syscall::open(":network", syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK).expect("rtl8168d: failed to create network scheme"); let socket_fd = syscall::open(":network", syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK).expect("rtl8168d: failed to create network scheme");
let socket = Arc::new(RefCell::new(unsafe { File::from_raw_fd(socket_fd) })); let socket = Arc::new(RefCell::new(unsafe { File::from_raw_fd(socket_fd) }));

View file

@ -8,4 +8,4 @@ dhcpd
httpd httpd
getty display:2 getty display:2
getty display:3 getty display:3
#orbital display:4 orbital display:4

View file

@ -5,7 +5,7 @@ use spin::Mutex;
use arch; use arch;
use context::file::File; use context::file::File;
use context::memory::{Grant, Memory, SharedMemory}; use context::memory::{Grant, Memory, SharedMemory, Tls};
use syscall::data::Event; use syscall::data::Event;
use sync::{WaitCondition, WaitQueue}; use sync::{WaitCondition, WaitQueue};
@ -36,7 +36,7 @@ pub struct Context {
/// Context running or not /// Context running or not
pub running: bool, pub running: bool,
/// CPU ID, if locked /// CPU ID, if locked
pub cpuid: Option<usize>, pub cpu_id: Option<usize>,
/// Context is halting parent /// Context is halting parent
pub vfork: bool, pub vfork: bool,
/// Context is being waited on /// Context is being waited on
@ -55,6 +55,8 @@ pub struct Context {
pub heap: Option<SharedMemory>, pub heap: Option<SharedMemory>,
/// User stack /// User stack
pub stack: Option<Memory>, pub stack: Option<Memory>,
/// User Tls
pub tls: Option<Tls>,
/// User grants /// User grants
pub grants: Arc<Mutex<Vec<Grant>>>, pub grants: Arc<Mutex<Vec<Grant>>>,
/// The name of the context /// The name of the context
@ -81,7 +83,7 @@ impl Context {
egid: 0, egid: 0,
status: Status::Blocked, status: Status::Blocked,
running: false, running: false,
cpuid: None, cpu_id: None,
vfork: false, vfork: false,
waitpid: Arc::new(WaitCondition::new()), waitpid: Arc::new(WaitCondition::new()),
wake: None, wake: None,
@ -91,6 +93,7 @@ impl Context {
image: Vec::new(), image: Vec::new(),
heap: None, heap: None,
stack: None, stack: None,
tls: None,
grants: Arc::new(Mutex::new(Vec::new())), grants: Arc::new(Mutex::new(Vec::new())),
name: Arc::new(Mutex::new(Vec::new())), name: Arc::new(Mutex::new(Vec::new())),
cwd: Arc::new(Mutex::new(Vec::new())), cwd: Arc::new(Mutex::new(Vec::new())),
@ -153,6 +156,13 @@ impl Context {
pub fn unblock(&mut self) -> bool { pub fn unblock(&mut self) -> bool {
if self.status == Status::Blocked { if self.status == Status::Blocked {
self.status = Status::Runnable; self.status = Status::Runnable;
if let Some(cpu_id) = self.cpu_id {
if cpu_id != ::cpu_id() {
// Send IPI if not on current CPU
// TODO: Make this more architecture independent
unsafe { arch::device::local_apic::LOCAL_APIC.ipi(cpu_id) };
}
}
true true
} else { } else {
false false

View file

@ -332,3 +332,10 @@ impl Drop for Memory {
self.unmap(true); self.unmap(true);
} }
} }
#[derive(Debug)]
pub struct Tls {
pub master: VirtualAddress,
pub file_size: usize,
pub mem: Memory
}

View file

@ -50,7 +50,7 @@ pub fn init() {
context.kfx = Some(fx); context.kfx = Some(fx);
context.status = Status::Runnable; context.status = Status::Runnable;
context.running = true; context.running = true;
context.cpuid = Some(::cpu_id()); context.cpu_id = Some(::cpu_id());
CONTEXT_ID.store(context.id, Ordering::SeqCst); CONTEXT_ID.store(context.id, Ordering::SeqCst);
} }

View file

@ -16,27 +16,34 @@ pub unsafe fn switch() -> bool {
arch::interrupt::pause(); arch::interrupt::pause();
} }
let cpu_id = ::cpu_id();
let from_ptr; let from_ptr;
let mut to_ptr = 0 as *mut Context; let mut to_ptr = 0 as *mut Context;
{ {
let contexts = contexts(); let contexts = contexts();
{ {
let context_lock = contexts.current().expect("context::switch: Not inside of context"); let context_lock = contexts.current().expect("context::switch: not inside of context");
let mut context = context_lock.write(); let mut context = context_lock.write();
from_ptr = context.deref_mut() as *mut Context; from_ptr = context.deref_mut() as *mut Context;
} }
let check_context = |context: &mut Context| -> bool { let check_context = |context: &mut Context| -> bool {
if context.cpuid == None || context.cpuid == Some(::cpu_id()) { if context.cpu_id == None && cpu_id == 0 {
if context.status == Status::Blocked && context.wake.is_some() { context.cpu_id = Some(cpu_id);
let wake = context.wake.expect("context::switch: wake not set"); println!("{}: take {} {}", cpu_id, context.id, ::core::str::from_utf8_unchecked(&context.name.lock()));
}
let current = arch::time::monotonic(); if context.status == Status::Blocked && context.wake.is_some() {
if current.0 > wake.0 || (current.0 == wake.0 && current.1 >= wake.1) { let wake = context.wake.expect("context::switch: wake not set");
context.unblock();
} let current = arch::time::monotonic();
if current.0 > wake.0 || (current.0 == wake.0 && current.1 >= wake.1) {
context.unblock();
} }
}
if context.cpu_id == Some(cpu_id) {
if context.status == Status::Runnable && ! context.running { if context.status == Status::Runnable && ! context.running {
return true; return true;
} }
@ -74,8 +81,6 @@ pub unsafe fn switch() -> bool {
return false; return false;
} }
// println!("{}: Switch {} to {}", ::cpu_id(), (&*from_ptr).id, (&*to_ptr).id);
(&mut *from_ptr).running = false; (&mut *from_ptr).running = false;
(&mut *to_ptr).running = true; (&mut *to_ptr).running = true;
if let Some(ref stack) = (*to_ptr).kstack { if let Some(ref stack) = (*to_ptr).kstack {
@ -83,6 +88,9 @@ pub unsafe fn switch() -> bool {
} }
CONTEXT_ID.store((&mut *to_ptr).id, Ordering::SeqCst); CONTEXT_ID.store((&mut *to_ptr).id, Ordering::SeqCst);
// Unset global lock before switch, as arch is only usable by the current CPU at this time
arch::context::CONTEXT_SWITCH_LOCK.store(false, Ordering::SeqCst);
(&mut *from_ptr).arch.switch_to(&mut (&mut *to_ptr).arch); (&mut *from_ptr).arch.switch_to(&mut (&mut *to_ptr).arch);
true true

View file

@ -152,6 +152,19 @@ pub extern fn userspace_init() {
panic!("initfs:init returned") panic!("initfs:init returned")
} }
/// Allow exception handlers to send signal to arch-independant kernel
#[no_mangle]
pub extern fn ksignal(signal: usize) {
println!("SIGNAL {}, CPU {}, PID {}", signal, cpu_id(), context::context_id());
{
let contexts = context::contexts();
if let Some(context_lock) = contexts.current() {
let context = context_lock.read();
println!("NAME {}", unsafe { ::core::str::from_utf8_unchecked(&context.name.lock()) });
}
}
}
#[no_mangle] #[no_mangle]
pub extern fn kmain(cpus: usize) { pub extern fn kmain(cpus: usize) {
CPU_ID.store(0, Ordering::SeqCst); CPU_ID.store(0, Ordering::SeqCst);
@ -195,6 +208,14 @@ pub extern fn kmain_ap(id: usize) {
println!("AP {}: {:?}", id, pid); println!("AP {}: {:?}", id, pid);
loop { loop {
unsafe { interrupt::enable_and_halt() } unsafe {
interrupt::disable();
if context::switch() {
interrupt::enable_and_nop();
} else {
// Enable interrupts, then halt CPU (to save power) until the next interrupt is actually fired.
interrupt::enable_and_halt();
}
}
} }
} }

View file

@ -5,12 +5,13 @@ use context;
use syscall::error::Result; use syscall::error::Result;
pub fn resource() -> Result<Vec<u8>> { pub fn resource() -> Result<Vec<u8>> {
let mut string = format!("{:<6}{:<6}{:<6}{:<6}{:<6}{:<8}{}\n", let mut string = format!("{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<8}{}\n",
"PID", "PID",
"PPID", "PPID",
"UID", "UID",
"GID", "GID",
"STAT", "STAT",
"CPU",
"MEM", "MEM",
"NAME"); "NAME");
{ {
@ -18,6 +19,35 @@ pub fn resource() -> Result<Vec<u8>> {
for (_id, context_lock) in contexts.iter() { for (_id, context_lock) in contexts.iter() {
let context = context_lock.read(); let context = context_lock.read();
let mut stat_string = String::new();
if context.stack.is_some() {
stat_string.push('U');
} else {
stat_string.push('K');
}
match context.status {
context::Status::Runnable => {
stat_string.push('R');
},
context::Status::Blocked => if context.wake.is_some() {
stat_string.push('S');
} else {
stat_string.push('B');
},
context::Status::Exited(_status) => {
stat_string.push('Z');
}
}
if context.running {
stat_string.push('+');
}
let cpu_string = if let Some(cpu_id) = context.cpu_id {
format!("{}", cpu_id)
} else {
format!("?")
};
let mut memory = 0; let mut memory = 0;
if let Some(ref kfx) = context.kstack { if let Some(ref kfx) = context.kstack {
memory += kfx.len(); memory += kfx.len();
@ -49,38 +79,16 @@ pub fn resource() -> Result<Vec<u8>> {
format!("{} B", memory) format!("{} B", memory)
}; };
let mut stat_string = String::new();
if context.stack.is_some() {
stat_string.push('U');
} else {
stat_string.push('K');
}
match context.status {
context::Status::Runnable => {
stat_string.push('R');
},
context::Status::Blocked => if context.wake.is_some() {
stat_string.push('S');
} else {
stat_string.push('B');
},
context::Status::Exited(_status) => {
stat_string.push('Z');
}
}
if context.running {
stat_string.push('+');
}
let name_bytes = context.name.lock(); let name_bytes = context.name.lock();
let name = str::from_utf8(&name_bytes).unwrap_or(""); let name = str::from_utf8(&name_bytes).unwrap_or("");
string.push_str(&format!("{:<6}{:<6}{:<6}{:<6}{:<6}{:<8}{}\n", string.push_str(&format!("{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<8}{}\n",
context.id, context.id,
context.ppid, context.ppid,
context.euid, context.euid,
context.egid, context.egid,
stat_string, stat_string,
cpu_string,
memory_string, memory_string,
name)); name));
} }

View file

@ -62,6 +62,7 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<usize> {
let rgid; let rgid;
let euid; let euid;
let egid; let egid;
let mut cpu_id = None;
let arch; let arch;
let vfork; let vfork;
let mut kfx_option = None; let mut kfx_option = None;
@ -70,6 +71,7 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<usize> {
let mut image = vec![]; let mut image = vec![];
let mut heap_option = None; let mut heap_option = None;
let mut stack_option = None; let mut stack_option = None;
let mut tls_option = None;
let grants; let grants;
let name; let name;
let cwd; let cwd;
@ -88,6 +90,10 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<usize> {
euid = context.euid; euid = context.euid;
egid = context.egid; egid = context.egid;
if flags & CLONE_VM == CLONE_VM {
cpu_id = context.cpu_id;
}
arch = context.arch.clone(); arch = context.arch.clone();
if let Some(ref fx) = context.kfx { if let Some(ref fx) = context.kfx {
@ -181,6 +187,29 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<usize> {
stack_option = Some(new_stack); stack_option = Some(new_stack);
} }
if let Some(ref tls) = context.tls {
let mut new_tls = context::memory::Tls {
master: tls.master,
file_size: tls.file_size,
mem: context::memory::Memory::new(
VirtualAddress::new(arch::USER_TMP_TLS_OFFSET),
tls.mem.size(),
entry::PRESENT | entry::NO_EXECUTE | entry::WRITABLE,
true,
false
)
};
unsafe {
arch::externs::memcpy(new_tls.mem.start_address().get() as *mut u8,
tls.master.get() as *const u8,
tls.file_size);
}
new_tls.mem.remap(tls.mem.flags(), true);
tls_option = Some(new_tls);
}
if flags & CLONE_VM == CLONE_VM { if flags & CLONE_VM == CLONE_VM {
grants = context.grants.clone(); grants = context.grants.clone();
} else { } else {
@ -277,6 +306,8 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<usize> {
context.euid = euid; context.euid = euid;
context.egid = egid; context.egid = egid;
context.cpu_id = cpu_id;
context.status = context::Status::Runnable; context.status = context::Status::Runnable;
context.vfork = vfork; context.vfork = vfork;
@ -393,6 +424,12 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<usize> {
context.stack = Some(stack); context.stack = Some(stack);
} }
// Setup user TLS
if let Some(mut tls) = tls_option {
tls.mem.move_to(VirtualAddress::new(arch::USER_TLS_OFFSET), &mut new_table, &mut temporary_page, true);
context.tls = Some(tls);
}
context.name = name; context.name = name;
context.cwd = cwd; context.cwd = cwd;
@ -411,6 +448,7 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<usize> {
pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> { pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> {
let entry; let entry;
let mut sp = arch::USER_STACK_OFFSET + arch::USER_STACK_SIZE - 256; let mut sp = arch::USER_STACK_OFFSET + arch::USER_STACK_SIZE - 256;
let fs = arch::USER_STACK_OFFSET;
{ {
let mut args = Vec::new(); let mut args = Vec::new();
@ -466,11 +504,12 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> {
// Set name // Set name
context.name = Arc::new(Mutex::new(canonical)); context.name = Arc::new(Mutex::new(canonical));
// Unmap previous image and stack // Unmap previous image, heap, grants, stack, and tls
context.image.clear(); context.image.clear();
drop(context.heap.take()); drop(context.heap.take());
drop(context.stack.take());
context.grants = Arc::new(Mutex::new(Vec::new())); context.grants = Arc::new(Mutex::new(Vec::new()));
drop(context.stack.take());
drop(context.tls.take());
if stat.st_mode & syscall::flag::MODE_SETUID == syscall::flag::MODE_SETUID { if stat.st_mode & syscall::flag::MODE_SETUID == syscall::flag::MODE_SETUID {
context.euid = stat.st_uid; context.euid = stat.st_uid;
@ -481,6 +520,7 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> {
} }
// Map and copy new segments // Map and copy new segments
let mut tls_option = None;
for segment in elf.segments() { for segment in elf.segments() {
if segment.p_type == program_header::PT_LOAD { if segment.p_type == program_header::PT_LOAD {
let mut memory = context::memory::Memory::new( let mut memory = context::memory::Memory::new(
@ -514,6 +554,12 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> {
memory.remap(flags, true); memory.remap(flags, true);
context.image.push(memory.to_shared()); context.image.push(memory.to_shared());
} else if segment.p_type == program_header::PT_TLS {
tls_option = Some((
VirtualAddress::new(segment.p_vaddr as usize),
segment.p_filesz as usize,
segment.p_memsz as usize
));
} }
} }
@ -535,6 +581,35 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> {
true true
)); ));
// Map TLS
if let Some((master, file_size, size)) = tls_option {
let tls = context::memory::Tls {
master: master,
file_size: file_size,
mem: context::memory::Memory::new(
VirtualAddress::new(arch::USER_TLS_OFFSET),
size,
entry::NO_EXECUTE | entry::WRITABLE | entry::USER_ACCESSIBLE,
true,
true
)
};
unsafe {
// Copy file data
memcpy(tls.mem.start_address().get() as *mut u8,
master.get() as *const u8,
file_size);
}
// Set TLS pointer
//TODO: Do not use stack to store TLS pointer, use a TCB structure instead
unsafe { *(arch::USER_STACK_OFFSET as *mut usize) = tls.mem.start_address().get() + size; }
context.tls = Some(tls);
}
// Push arguments
let mut arg_size = 0; let mut arg_size = 0;
for arg in args.iter().rev() { for arg in args.iter().rev() {
sp -= mem::size_of::<usize>(); sp -= mem::size_of::<usize>();
@ -597,7 +672,7 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> {
} }
// Go to usermode // Go to usermode
unsafe { usermode(entry, sp); } unsafe { usermode(entry, sp, fs); }
} }
pub fn exit(status: usize) -> ! { pub fn exit(status: usize) -> ! {
@ -897,6 +972,7 @@ pub fn virttophys(virtual_address: usize) -> Result<usize> {
pub fn waitpid(pid: usize, status_ptr: usize, flags: usize) -> Result<usize> { pub fn waitpid(pid: usize, status_ptr: usize, flags: usize) -> Result<usize> {
loop { loop {
let mut exited = false; let mut exited = false;
let mut running;
let waitpid; let waitpid;
{ {
let contexts = context::contexts(); let contexts = context::contexts();
@ -909,10 +985,23 @@ pub fn waitpid(pid: usize, status_ptr: usize, flags: usize) -> Result<usize> {
} }
exited = true; exited = true;
} }
running = context.running;
waitpid = context.waitpid.clone(); waitpid = context.waitpid.clone();
} }
if exited { if exited {
// Spin until not running
while running {
{
let contexts = context::contexts();
let context_lock = contexts.get(pid).ok_or(Error::new(ESRCH))?;
let context = context_lock.read();
running = context.running;
}
arch::interrupt::pause();
}
let mut contexts = context::contexts_mut(); let mut contexts = context::contexts_mut();
return contexts.remove(pid).ok_or(Error::new(ESRCH)).and(Ok(pid)); return contexts.remove(pid).ok_or(Error::new(ESRCH)).and(Ok(pid));
} else if flags & WNOHANG == WNOHANG { } else if flags & WNOHANG == WNOHANG {

2
libstd

@ -1 +1 @@
Subproject commit 8a29d8ff3304b78d74e0259270ba50cb33765a63 Subproject commit 263ed59929e68073bd4e47ba07f2fbe283ee2854

18
libstd_real/Cargo.toml Normal file
View file

@ -0,0 +1,18 @@
[package]
name = "redox_std"
version = "0.1.0"
authors = ["Jeremy Soller <jackpot51@gmail.com>"]
[lib]
name = "std"
path = "../rust/src/libstd/lib.rs"
[dependencies]
alloc_system = { path = "alloc_system" }
compiler_builtins = { path = "compiler_builtins" }
panic_unwind = { path = "panic_unwind" }
libc = { path = "libc" }
unwind = { path = "unwind" }
[replace]
"libc:0.2.17" = { git = "https://github.com/redox-os/liblibc.git", branch = "new_kernel" }

View file

@ -0,0 +1,12 @@
[package]
name = "alloc_system"
version = "0.0.0"
authors = ["Jeremy Soller <jackpot51@gmail.com>"]
[dependencies.ralloc]
path = "../../ralloc/"
default-features = false
features = ["allocator"]
[replace]
"libc:0.2.17" = { git = "https://github.com/redox-os/liblibc.git", branch = "new_kernel" }

View file

@ -0,0 +1,6 @@
#![allocator]
#![feature(allocator)]
#![no_std]
#[allocator]
extern crate ralloc;

View file

@ -0,0 +1,4 @@
[package]
name = "compiler_builtins"
version = "0.1.0"
authors = ["Jeremy Soller <jackpot51@gmail.com>"]

View file

@ -0,0 +1,72 @@
#![no_std]
/// Memcpy
///
/// Copy N bytes of memory from one location to another.
#[no_mangle]
pub unsafe extern fn memcpy(dest: *mut u8, src: *const u8,
n: usize) -> *mut u8 {
let mut i = 0;
while i < n {
*((dest as usize + i) as *mut u8) = *((src as usize + i) as *const u8);
i += 1;
}
dest
}
/// Memmove
///
/// Copy N bytes of memory from src to dest. The memory areas may overlap.
#[no_mangle]
pub unsafe extern fn memmove(dest: *mut u8, src: *const u8,
n: usize) -> *mut u8 {
if src < dest as *const u8 {
let mut i = n;
while i != 0 {
i -= 1;
*((dest as usize + i) as *mut u8) = *((src as usize + i) as *const u8);
}
} else {
let mut i = 0;
while i < n {
*((dest as usize + i) as *mut u8) = *((src as usize + i) as *const u8);
i += 1;
}
}
dest
}
/// Memset
///
/// Fill a block of memory with a specified value.
#[no_mangle]
pub unsafe extern fn memset(dest: *mut u8, c: i32, n: usize) -> *mut u8 {
let mut i = 0;
while i < n {
*((dest as usize + i) as *mut u8) = c as u8;
i += 1;
}
dest
}
/// Memcmp
///
/// Compare two blocks of memory.
#[no_mangle]
pub unsafe extern fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 {
let mut i = 0;
while i < n {
let a = *((s1 as usize + i) as *const u8);
let b = *((s2 as usize + i) as *const u8);
if a != b {
return a as i32 - b as i32
}
i += 1;
}
0
}

View file

@ -0,0 +1,7 @@
[package]
name = "libc"
version = "0.1.0"
authors = ["Jeremy Soller <jackpot51@gmail.com>"]
[dependencies]
syscall = { path = "../../syscall/" }

View file

@ -0,0 +1,19 @@
use super::{c_char, size_t};
pub unsafe extern fn strlen(ptr: *const c_char) -> size_t {
let mut i: size_t = 0;
while *ptr.offset(i as isize) != 0 {
i += 1;
}
i
}
pub unsafe extern fn random() -> u64 {
let rand;
asm!("rdrand rax"
: "={rax}"(rand)
:
:
: "intel", "volatile");
rand
}

View file

@ -0,0 +1,18 @@
#![no_std]
#![allow(non_camel_case_types)]
#![feature(asm)]
#![feature(naked_functions)]
pub use types::*;
pub use funcs::*;
pub use start::*;
pub use syscall::*;
/// Basic types (not usually system specific)
mod types;
/// Basic functions (not system specific)
mod funcs;
/// Start function and call in to libstd
mod start;
/// Conversion for syscall library (specific to Redox)
mod syscall;

View file

@ -0,0 +1,40 @@
use super::exit;
#[no_mangle]
#[naked]
#[cfg(target_arch = "x86")]
pub unsafe fn _start() {
asm!("push esp
call _start_stack
pop esp"
:
:
: "memory"
: "intel", "volatile");
let _ = exit(0);
}
#[no_mangle]
#[naked]
#[cfg(target_arch = "x86_64")]
pub unsafe fn _start() {
asm!("mov rdi, rsp
and rsp, 0xFFFFFFFFFFFFFFF0
call _start_stack"
:
:
: "memory"
: "intel", "volatile");
let _ = exit(0);
}
#[no_mangle]
pub unsafe extern "C" fn _start_stack(stack: *const usize){
extern "C" {
fn main(argc: usize, argv: *const *const u8) -> usize;
}
let argc = *stack as usize;
let argv = stack.offset(1) as *const *const u8;
let _ = exit(main(argc, argv));
}

View file

@ -0,0 +1,87 @@
/// Convert syscall types to libc types
extern crate syscall;
use super::{c_int, sa_family_t};
use self::syscall::data::{Stat, TimeSpec};
pub use self::syscall::error::*;
pub use self::syscall::flag::*;
pub use self::syscall::{
clock_gettime, clone, execve as exec, exit, futex, getpid, kill, nanosleep, setgid, setuid, waitpid,
chdir, getcwd, open, mkdir, rmdir, unlink, dup, pipe2,
read, write, fpath, fstat, fsync, ftruncate, lseek, close
};
//TODO: Thread local
pub static mut errno: c_int = 0;
pub type stat = Stat;
pub type timespec = TimeSpec;
pub const AF_INET: sa_family_t = 1;
pub const AF_INET6: sa_family_t = 2;
pub const STDIN_FILENO: usize = 0;
pub const STDOUT_FILENO: usize = 1;
pub const STDERR_FILENO: usize = 2;
fn cvt(result: syscall::Result<usize>) -> c_int {
match result {
Ok(res) => res as c_int,
Err(err) => {
unsafe { errno = err.errno };
-1
}
}
}
// ralloc shims {
/// Cooperatively gives up a timeslice to the OS scheduler.
#[no_mangle]
pub unsafe extern "C" fn sched_yield() -> c_int {
cvt(syscall::sched_yield())
}
/// Increment data segment of this process by some, _n_, return a pointer to the new data segment
/// start.
///
/// This uses the system call BRK as backend.
///
/// This is unsafe for multiple reasons. Most importantly, it can create an inconsistent state,
/// because it is not atomic. Thus, it can be used to create Undefined Behavior.
#[no_mangle]
pub extern "C" fn sbrk(n: isize) -> *mut u8 {
let orig_seg_end = match unsafe { syscall::brk(0) } {
Ok(end) => end,
Err(_) => return !0 as *mut u8
};
if n == 0 {
return orig_seg_end as *mut u8;
}
let expected_end = match orig_seg_end.checked_add(n as usize) {
Some(end) => end,
None => return !0 as *mut u8
};
let new_seg_end = match unsafe { syscall::brk(expected_end) } {
Ok(end) => end,
Err(_) => return !0 as *mut u8
};
if new_seg_end != expected_end {
// Reset the break.
let _ = unsafe { syscall::brk(orig_seg_end) };
!0 as *mut u8
} else {
orig_seg_end as *mut u8
}
}
// } ralloc shims
pub unsafe fn fcntl(_fd: usize, _cmd: c_int, _arg: c_int) -> c_int {
cvt(Err(Error::new(ENOSYS)))
}

View file

@ -0,0 +1,96 @@
// Use repr(u8) as LLVM expects `void*` to be the same as `i8*` to help enable
// more optimization opportunities around it recognizing things like
// malloc/free.
#[repr(u8)]
pub enum c_void {
// Two dummy variants so the #[repr] attribute can be used.
#[doc(hidden)]
__variant1,
#[doc(hidden)]
__variant2,
}
pub type int8_t = i8;
pub type int16_t = i16;
pub type int32_t = i32;
pub type int64_t = i64;
pub type uint8_t = u8;
pub type uint16_t = u16;
pub type uint32_t = u32;
pub type uint64_t = u64;
pub type c_schar = i8;
pub type c_uchar = u8;
pub type c_short = i16;
pub type c_ushort = u16;
pub type c_float = f32;
pub type c_double = f64;
pub type intmax_t = i64;
pub type uintmax_t = u64;
pub type c_char = i8;
pub type c_int = i32;
pub type c_uint = u32;
pub type c_long = i64;
pub type c_ulong = u64;
pub type c_longlong = i64;
pub type c_ulonglong = u64;
pub type off_t = usize;
pub type size_t = usize;
pub type ptrdiff_t = isize;
pub type intptr_t = isize;
pub type uintptr_t = usize;
pub type ssize_t = isize;
pub type mode_t = u16;
pub type time_t = i64;
pub type pid_t = usize;
pub type gid_t = usize;
pub type uid_t = usize;
pub type in_addr_t = u32;
pub type in_port_t = u16;
pub type socklen_t = u32;
pub type sa_family_t = u16;
#[derive(Copy, Clone)]
#[repr(C)]
pub struct in_addr {
pub s_addr: in_addr_t,
}
#[derive(Copy, Clone)]
#[repr(C)]
pub struct in6_addr {
pub s6_addr: [u8; 16],
__align: [u32; 0],
}
#[derive(Copy, Clone)]
#[repr(C)]
pub struct sockaddr {
pub sa_family: sa_family_t,
pub sa_data: [::c_char; 14],
}
#[derive(Copy, Clone)]
#[repr(C)]
pub struct sockaddr_in {
pub sin_family: sa_family_t,
pub sin_port: ::in_port_t,
pub sin_addr: ::in_addr,
pub sin_zero: [u8; 8],
}
#[derive(Copy, Clone)]
#[repr(C)]
pub struct sockaddr_in6 {
pub sin6_family: sa_family_t,
pub sin6_port: in_port_t,
pub sin6_flowinfo: u32,
pub sin6_addr: ::in6_addr,
pub sin6_scope_id: u32,
}

View file

@ -0,0 +1,7 @@
[package]
name = "panic_unwind"
version = "0.0.0"
authors = ["Jeremy Soller <jackpot51@gmail.com>"]
[dependencies]
syscall = { path = "../../syscall/" }

View file

@ -0,0 +1,27 @@
#![no_std]
#![feature(core_intrinsics)]
#![feature(lang_items)]
#![feature(panic_runtime)]
#![panic_runtime]
#[no_mangle]
pub unsafe extern fn __rust_maybe_catch_panic(f: fn(*mut u8), data: *mut u8,
_data_ptr: *mut usize, _vtable_ptr: *mut usize) -> u32 {
f(data);
0
}
#[no_mangle]
pub unsafe extern fn __rust_start_panic(_data: usize, _vtable: usize) -> u32 {
core::intrinsics::abort();
}
#[lang = "eh_personality"]
pub extern fn eh_personality() {}
#[allow(non_snake_case)]
#[no_mangle]
/// Required to handle panics
pub unsafe extern "C" fn _Unwind_Resume() -> ! {
core::intrinsics::abort();
}

View file

@ -0,0 +1,4 @@
[package]
name = "unwind"
version = "0.0.0"
authors = ["Jeremy Soller <jackpot51@gmail.com>"]

View file

@ -0,0 +1 @@
#![no_std]

@ -1 +1 @@
Subproject commit 1afcf7ab26ca3f697082674e6a72c94dd211c74b Subproject commit 519d98880c7c0a6b40111e7861259cf46998cee3

@ -1 +1 @@
Subproject commit 7d5233187721918f4c00726771c3ec2d44a1f8c6 Subproject commit a6e4162839279e639057b616ac79d34421f85754

2
rust

@ -1 +1 @@
Subproject commit 17af6b94b2ea39414e4449c17cc4ab066d790e8f Subproject commit 123d08b3d3901d5725af8303c1329b007089cde5

View file

@ -6,7 +6,7 @@ use std::{cmp, str, u16};
use netutils::{getcfg, MacAddr, EthernetII}; use netutils::{getcfg, MacAddr, EthernetII};
use syscall; use syscall;
use syscall::error::{Error, Result, EACCES, EBADF, EINVAL, EWOULDBLOCK}; use syscall::error::{Error, Result, EACCES, EBADF, EINVAL, EIO, EWOULDBLOCK};
use syscall::flag::O_NONBLOCK; use syscall::flag::O_NONBLOCK;
use syscall::scheme::SchemeMut; use syscall::scheme::SchemeMut;
@ -63,7 +63,7 @@ impl EthernetScheme {
impl SchemeMut for EthernetScheme { impl SchemeMut for EthernetScheme {
fn open(&mut self, url: &[u8], flags: usize, uid: u32, _gid: u32) -> Result<usize> { fn open(&mut self, url: &[u8], flags: usize, uid: u32, _gid: u32) -> Result<usize> {
if uid == 0 { if uid == 0 {
let mac_addr = MacAddr::from_str(&getcfg("mac").map_err(|err| err.into_sys())?); let mac_addr = MacAddr::from_str(&getcfg("mac").map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO)))?);
let path = try!(str::from_utf8(url).or(Err(Error::new(EINVAL)))); let path = try!(str::from_utf8(url).or(Err(Error::new(EINVAL))));
let ethertype = u16::from_str_radix(path, 16).unwrap_or(0); let ethertype = u16::from_str_radix(path, 16).unwrap_or(0);
@ -121,7 +121,7 @@ impl SchemeMut for EthernetScheme {
if let Some(mut frame) = EthernetII::from_bytes(buf) { if let Some(mut frame) = EthernetII::from_bytes(buf) {
frame.header.src = handle.host_addr; frame.header.src = handle.host_addr;
frame.header.ethertype.set(handle.ethertype); frame.header.ethertype.set(handle.ethertype);
self.network.write(&frame.to_bytes()).map_err(|err| err.into_sys()) self.network.write(&frame.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO)))
} else { } else {
Err(Error::new(EINVAL)) Err(Error::new(EINVAL))
} }

View file

@ -12,7 +12,7 @@ use std::os::unix::io::FromRawFd;
use std::rc::Rc; use std::rc::Rc;
use std::{slice, str, thread}; use std::{slice, str, thread};
use syscall::data::Packet; use syscall::data::Packet;
use syscall::error::{Error, Result, EACCES, EADDRNOTAVAIL, EBADF, EINVAL, ENOENT, EWOULDBLOCK}; use syscall::error::{Error, Result, EACCES, EADDRNOTAVAIL, EBADF, EIO, EINVAL, ENOENT, EWOULDBLOCK};
use syscall::flag::{EVENT_READ, O_NONBLOCK}; use syscall::flag::{EVENT_READ, O_NONBLOCK};
use syscall::scheme::SchemeMut; use syscall::scheme::SchemeMut;
@ -275,7 +275,7 @@ impl SchemeMut for Ipd {
data: ip.to_bytes() data: ip.to_bytes()
}; };
interface.ip_file.write(&frame.to_bytes()).map_err(|err| err.into_sys())?; interface.ip_file.write(&frame.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO)))?;
return Ok(buf.len()); return Ok(buf.len());
} }

View file

@ -15,7 +15,7 @@ use std::rc::Rc;
use event::EventQueue; use event::EventQueue;
use netutils::{n16, n32, Ipv4, Ipv4Addr, Ipv4Header, Tcp, TcpHeader, Checksum, TCP_FIN, TCP_SYN, TCP_RST, TCP_PSH, TCP_ACK}; use netutils::{n16, n32, Ipv4, Ipv4Addr, Ipv4Header, Tcp, TcpHeader, Checksum, TCP_FIN, TCP_SYN, TCP_RST, TCP_PSH, TCP_ACK};
use syscall::data::Packet; use syscall::data::Packet;
use syscall::error::{Error, Result, EACCES, EADDRINUSE, EBADF, EINVAL, EISCONN, EMSGSIZE, ENOTCONN, EWOULDBLOCK}; use syscall::error::{Error, Result, EACCES, EADDRINUSE, EBADF, EIO, EINVAL, EISCONN, EMSGSIZE, ENOTCONN, EWOULDBLOCK};
use syscall::flag::{EVENT_READ, O_CREAT, O_RDWR, O_NONBLOCK}; use syscall::flag::{EVENT_READ, O_CREAT, O_RDWR, O_NONBLOCK};
use syscall::scheme::SchemeMut; use syscall::scheme::SchemeMut;
@ -274,7 +274,7 @@ impl Tcpd {
let tcp = handle.create_tcp(TCP_ACK | TCP_PSH, buf.to_vec()); let tcp = handle.create_tcp(TCP_ACK | TCP_PSH, buf.to_vec());
let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes()); let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes());
let result = self.tcp_file.write(&ip.to_bytes()).map_err(|err| err.into_sys()); let result = self.tcp_file.write(&ip.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO)));
if result.is_ok() { if result.is_ok() {
handle.seq += buf.len() as u32; handle.seq += buf.len() as u32;
} }
@ -422,7 +422,7 @@ impl SchemeMut for Tcpd {
let tcp = handle.create_tcp(TCP_SYN, Vec::new()); let tcp = handle.create_tcp(TCP_SYN, Vec::new());
let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes()); let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes());
self.tcp_file.write(&ip.to_bytes()).map_err(|err| err.into_sys())?; self.tcp_file.write(&ip.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO)))?;
handle.seq += 1; handle.seq += 1;
} }
@ -469,7 +469,7 @@ impl SchemeMut for Tcpd {
let tcp = new_handle.create_tcp(TCP_SYN | TCP_ACK, Vec::new()); let tcp = new_handle.create_tcp(TCP_SYN | TCP_ACK, Vec::new());
let ip = new_handle.create_ip(self.rng.gen(), tcp.to_bytes()); let ip = new_handle.create_ip(self.rng.gen(), tcp.to_bytes());
self.tcp_file.write(&ip.to_bytes()).map_err(|err| err.into_sys()).and(Ok(buf.len()))?; self.tcp_file.write(&ip.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO))).and(Ok(buf.len()))?;
new_handle.seq += 1; new_handle.seq += 1;
} else { } else {
@ -506,7 +506,7 @@ impl SchemeMut for Tcpd {
let tcp = new_handle.create_tcp(TCP_SYN, Vec::new()); let tcp = new_handle.create_tcp(TCP_SYN, Vec::new());
let ip = new_handle.create_ip(self.rng.gen(), tcp.to_bytes()); let ip = new_handle.create_ip(self.rng.gen(), tcp.to_bytes());
self.tcp_file.write(&ip.to_bytes()).map_err(|err| err.into_sys()).and(Ok(buf.len()))?; self.tcp_file.write(&ip.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO))).and(Ok(buf.len()))?;
} else { } else {
return Err(Error::new(EINVAL)); return Err(Error::new(EINVAL));
} }
@ -559,7 +559,7 @@ impl SchemeMut for Tcpd {
State::Established => { State::Established => {
let tcp = handle.create_tcp(TCP_ACK | TCP_PSH, buf.to_vec()); let tcp = handle.create_tcp(TCP_ACK | TCP_PSH, buf.to_vec());
let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes()); let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes());
self.tcp_file.write(&ip.to_bytes()).map_err(|err| err.into_sys())?; self.tcp_file.write(&ip.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO)))?;
handle.seq += buf.len() as u32; handle.seq += buf.len() as u32;
Ok(buf.len()) Ok(buf.len())
}, },
@ -611,7 +611,7 @@ impl SchemeMut for Tcpd {
let tcp = handle.create_tcp(TCP_FIN | TCP_ACK, Vec::new()); let tcp = handle.create_tcp(TCP_FIN | TCP_ACK, Vec::new());
let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes()); let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes());
self.tcp_file.write(&ip.to_bytes()).map_err(|err| err.into_sys())?; self.tcp_file.write(&ip.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO)))?;
handle.seq += 1; handle.seq += 1;
@ -622,7 +622,7 @@ impl SchemeMut for Tcpd {
let tcp = handle.create_tcp(TCP_FIN | TCP_ACK, Vec::new()); let tcp = handle.create_tcp(TCP_FIN | TCP_ACK, Vec::new());
let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes()); let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes());
self.tcp_file.write(&ip.to_bytes()).map_err(|err| err.into_sys())?; self.tcp_file.write(&ip.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO)))?;
handle.seq += 1; handle.seq += 1;

View file

@ -15,7 +15,7 @@ use std::rc::Rc;
use event::EventQueue; use event::EventQueue;
use netutils::{n16, Ipv4, Ipv4Addr, Ipv4Header, Udp, UdpHeader, Checksum}; use netutils::{n16, Ipv4, Ipv4Addr, Ipv4Header, Udp, UdpHeader, Checksum};
use syscall::data::Packet; use syscall::data::Packet;
use syscall::error::{Error, Result, EACCES, EADDRINUSE, EBADF, EINVAL, EMSGSIZE, ENOTCONN, EWOULDBLOCK}; use syscall::error::{Error, Result, EACCES, EADDRINUSE, EBADF, EIO, EINVAL, EMSGSIZE, ENOTCONN, EWOULDBLOCK};
use syscall::flag::{EVENT_READ, O_CREAT, O_RDWR, O_NONBLOCK}; use syscall::flag::{EVENT_READ, O_CREAT, O_RDWR, O_NONBLOCK};
use syscall::scheme::SchemeMut; use syscall::scheme::SchemeMut;
@ -265,7 +265,7 @@ impl SchemeMut for Udpd {
data: ip_data data: ip_data
}; };
self.udp_file.write(&ip.to_bytes()).map_err(|err| err.into_sys()).and(Ok(buf.len())) self.udp_file.write(&ip.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO))).and(Ok(buf.len()))
} }
} }

View file

@ -61,7 +61,13 @@ pub struct Stat {
pub st_mode: u16, pub st_mode: u16,
pub st_uid: u32, pub st_uid: u32,
pub st_gid: u32, pub st_gid: u32,
pub st_size: u64 pub st_size: u64,
pub st_mtime: u64,
pub st_mtime_nsec: u32,
pub st_atime: u64,
pub st_atime_nsec: u32,
pub st_ctime: u64,
pub st_ctime_nsec: u32,
} }
impl Deref for Stat { impl Deref for Stat {

View file

@ -2,13 +2,13 @@ use core::{fmt, result};
#[derive(Eq, PartialEq)] #[derive(Eq, PartialEq)]
pub struct Error { pub struct Error {
pub errno: isize, pub errno: i32,
} }
pub type Result<T> = result::Result<T, Error>; pub type Result<T> = result::Result<T, Error>;
impl Error { impl Error {
pub fn new(errno: isize) -> Error { pub fn new(errno: i32) -> Error {
Error { errno: errno } Error { errno: errno }
} }
@ -20,8 +20,8 @@ impl Error {
} }
pub fn demux(value: usize) -> Result<usize> { pub fn demux(value: usize) -> Result<usize> {
let errno = -(value as isize); let errno = -(value as i32);
if errno >= 1 && errno < STR_ERROR.len() as isize { if errno >= 1 && errno < STR_ERROR.len() as i32 {
Err(Error::new(errno)) Err(Error::new(errno))
} else { } else {
Ok(value) Ok(value)
@ -49,137 +49,137 @@ impl fmt::Display for Error {
} }
} }
pub const EPERM: isize = 1; /* Operation not permitted */ pub const EPERM: i32 = 1; /* Operation not permitted */
pub const ENOENT: isize = 2; /* No such file or directory */ pub const ENOENT: i32 = 2; /* No such file or directory */
pub const ESRCH: isize = 3; /* No such process */ pub const ESRCH: i32 = 3; /* No such process */
pub const EINTR: isize = 4; /* Interrupted system call */ pub const EINTR: i32 = 4; /* Interrupted system call */
pub const EIO: isize = 5; /* I/O error */ pub const EIO: i32 = 5; /* I/O error */
pub const ENXIO: isize = 6; /* No such device or address */ pub const ENXIO: i32 = 6; /* No such device or address */
pub const E2BIG: isize = 7; /* Argument list too long */ pub const E2BIG: i32 = 7; /* Argument list too long */
pub const ENOEXEC: isize = 8; /* Exec format error */ pub const ENOEXEC: i32 = 8; /* Exec format error */
pub const EBADF: isize = 9; /* Bad file number */ pub const EBADF: i32 = 9; /* Bad file number */
pub const ECHILD: isize = 10; /* No child processes */ pub const ECHILD: i32 = 10; /* No child processes */
pub const EAGAIN: isize = 11; /* Try again */ pub const EAGAIN: i32 = 11; /* Try again */
pub const ENOMEM: isize = 12; /* Out of memory */ pub const ENOMEM: i32 = 12; /* Out of memory */
pub const EACCES: isize = 13; /* Permission denied */ pub const EACCES: i32 = 13; /* Permission denied */
pub const EFAULT: isize = 14; /* Bad address */ pub const EFAULT: i32 = 14; /* Bad address */
pub const ENOTBLK: isize = 15; /* Block device required */ pub const ENOTBLK: i32 = 15; /* Block device required */
pub const EBUSY: isize = 16; /* Device or resource busy */ pub const EBUSY: i32 = 16; /* Device or resource busy */
pub const EEXIST: isize = 17; /* File exists */ pub const EEXIST: i32 = 17; /* File exists */
pub const EXDEV: isize = 18; /* Cross-device link */ pub const EXDEV: i32 = 18; /* Cross-device link */
pub const ENODEV: isize = 19; /* No such device */ pub const ENODEV: i32 = 19; /* No such device */
pub const ENOTDIR: isize = 20; /* Not a directory */ pub const ENOTDIR: i32 = 20; /* Not a directory */
pub const EISDIR: isize = 21; /* Is a directory */ pub const EISDIR: i32 = 21; /* Is a directory */
pub const EINVAL: isize = 22; /* Invalid argument */ pub const EINVAL: i32 = 22; /* Invalid argument */
pub const ENFILE: isize = 23; /* File table overflow */ pub const ENFILE: i32 = 23; /* File table overflow */
pub const EMFILE: isize = 24; /* Too many open files */ pub const EMFILE: i32 = 24; /* Too many open files */
pub const ENOTTY: isize = 25; /* Not a typewriter */ pub const ENOTTY: i32 = 25; /* Not a typewriter */
pub const ETXTBSY: isize = 26; /* Text file busy */ pub const ETXTBSY: i32 = 26; /* Text file busy */
pub const EFBIG: isize = 27; /* File too large */ pub const EFBIG: i32 = 27; /* File too large */
pub const ENOSPC: isize = 28; /* No space left on device */ pub const ENOSPC: i32 = 28; /* No space left on device */
pub const ESPIPE: isize = 29; /* Illegal seek */ pub const ESPIPE: i32 = 29; /* Illegal seek */
pub const EROFS: isize = 30; /* Read-only file system */ pub const EROFS: i32 = 30; /* Read-only file system */
pub const EMLINK: isize = 31; /* Too many links */ pub const EMLINK: i32 = 31; /* Too many links */
pub const EPIPE: isize = 32; /* Broken pipe */ pub const EPIPE: i32 = 32; /* Broken pipe */
pub const EDOM: isize = 33; /* Math argument out of domain of func */ pub const EDOM: i32 = 33; /* Math argument out of domain of func */
pub const ERANGE: isize = 34; /* Math result not representable */ pub const ERANGE: i32 = 34; /* Math result not representable */
pub const EDEADLK: isize = 35; /* Resource deadlock would occur */ pub const EDEADLK: i32 = 35; /* Resource deadlock would occur */
pub const ENAMETOOLONG: isize = 36; /* File name too long */ pub const ENAMETOOLONG: i32 = 36; /* File name too long */
pub const ENOLCK: isize = 37; /* No record locks available */ pub const ENOLCK: i32 = 37; /* No record locks available */
pub const ENOSYS: isize = 38; /* Function not implemented */ pub const ENOSYS: i32 = 38; /* Function not implemented */
pub const ENOTEMPTY: isize = 39; /* Directory not empty */ pub const ENOTEMPTY: i32 = 39; /* Directory not empty */
pub const ELOOP: isize = 40; /* Too many symbolic links encountered */ pub const ELOOP: i32 = 40; /* Too many symbolic links encountered */
pub const EWOULDBLOCK: isize = 41; /* Operation would block */ pub const EWOULDBLOCK: i32 = 41; /* Operation would block */
pub const ENOMSG: isize = 42; /* No message of desired type */ pub const ENOMSG: i32 = 42; /* No message of desired type */
pub const EIDRM: isize = 43; /* Identifier removed */ pub const EIDRM: i32 = 43; /* Identifier removed */
pub const ECHRNG: isize = 44; /* Channel number out of range */ pub const ECHRNG: i32 = 44; /* Channel number out of range */
pub const EL2NSYNC: isize = 45; /* Level 2 not synchronized */ pub const EL2NSYNC: i32 = 45; /* Level 2 not synchronized */
pub const EL3HLT: isize = 46; /* Level 3 halted */ pub const EL3HLT: i32 = 46; /* Level 3 halted */
pub const EL3RST: isize = 47; /* Level 3 reset */ pub const EL3RST: i32 = 47; /* Level 3 reset */
pub const ELNRNG: isize = 48; /* Link number out of range */ pub const ELNRNG: i32 = 48; /* Link number out of range */
pub const EUNATCH: isize = 49; /* Protocol driver not attached */ pub const EUNATCH: i32 = 49; /* Protocol driver not attached */
pub const ENOCSI: isize = 50; /* No CSI structure available */ pub const ENOCSI: i32 = 50; /* No CSI structure available */
pub const EL2HLT: isize = 51; /* Level 2 halted */ pub const EL2HLT: i32 = 51; /* Level 2 halted */
pub const EBADE: isize = 52; /* Invalid exchange */ pub const EBADE: i32 = 52; /* Invalid exchange */
pub const EBADR: isize = 53; /* Invalid request descriptor */ pub const EBADR: i32 = 53; /* Invalid request descriptor */
pub const EXFULL: isize = 54; /* Exchange full */ pub const EXFULL: i32 = 54; /* Exchange full */
pub const ENOANO: isize = 55; /* No anode */ pub const ENOANO: i32 = 55; /* No anode */
pub const EBADRQC: isize = 56; /* Invalid request code */ pub const EBADRQC: i32 = 56; /* Invalid request code */
pub const EBADSLT: isize = 57; /* Invalid slot */ pub const EBADSLT: i32 = 57; /* Invalid slot */
pub const EDEADLOCK: isize = 58; /* Resource deadlock would occur */ pub const EDEADLOCK: i32 = 58; /* Resource deadlock would occur */
pub const EBFONT: isize = 59; /* Bad font file format */ pub const EBFONT: i32 = 59; /* Bad font file format */
pub const ENOSTR: isize = 60; /* Device not a stream */ pub const ENOSTR: i32 = 60; /* Device not a stream */
pub const ENODATA: isize = 61; /* No data available */ pub const ENODATA: i32 = 61; /* No data available */
pub const ETIME: isize = 62; /* Timer expired */ pub const ETIME: i32 = 62; /* Timer expired */
pub const ENOSR: isize = 63; /* Out of streams resources */ pub const ENOSR: i32 = 63; /* Out of streams resources */
pub const ENONET: isize = 64; /* Machine is not on the network */ pub const ENONET: i32 = 64; /* Machine is not on the network */
pub const ENOPKG: isize = 65; /* Package not installed */ pub const ENOPKG: i32 = 65; /* Package not installed */
pub const EREMOTE: isize = 66; /* Object is remote */ pub const EREMOTE: i32 = 66; /* Object is remote */
pub const ENOLINK: isize = 67; /* Link has been severed */ pub const ENOLINK: i32 = 67; /* Link has been severed */
pub const EADV: isize = 68; /* Advertise error */ pub const EADV: i32 = 68; /* Advertise error */
pub const ESRMNT: isize = 69; /* Srmount error */ pub const ESRMNT: i32 = 69; /* Srmount error */
pub const ECOMM: isize = 70; /* Communication error on send */ pub const ECOMM: i32 = 70; /* Communication error on send */
pub const EPROTO: isize = 71; /* Protocol error */ pub const EPROTO: i32 = 71; /* Protocol error */
pub const EMULTIHOP: isize = 72; /* Multihop attempted */ pub const EMULTIHOP: i32 = 72; /* Multihop attempted */
pub const EDOTDOT: isize = 73; /* RFS specific error */ pub const EDOTDOT: i32 = 73; /* RFS specific error */
pub const EBADMSG: isize = 74; /* Not a data message */ pub const EBADMSG: i32 = 74; /* Not a data message */
pub const EOVERFLOW: isize = 75; /* Value too large for defined data type */ pub const EOVERFLOW: i32 = 75; /* Value too large for defined data type */
pub const ENOTUNIQ: isize = 76; /* Name not unique on network */ pub const ENOTUNIQ: i32 = 76; /* Name not unique on network */
pub const EBADFD: isize = 77; /* File descriptor in bad state */ pub const EBADFD: i32 = 77; /* File descriptor in bad state */
pub const EREMCHG: isize = 78; /* Remote address changed */ pub const EREMCHG: i32 = 78; /* Remote address changed */
pub const ELIBACC: isize = 79; /* Can not access a needed shared library */ pub const ELIBACC: i32 = 79; /* Can not access a needed shared library */
pub const ELIBBAD: isize = 80; /* Accessing a corrupted shared library */ pub const ELIBBAD: i32 = 80; /* Accessing a corrupted shared library */
pub const ELIBSCN: isize = 81; /* .lib section in a.out corrupted */ pub const ELIBSCN: i32 = 81; /* .lib section in a.out corrupted */
pub const ELIBMAX: isize = 82; /* Attempting to link in too many shared libraries */ pub const ELIBMAX: i32 = 82; /* Attempting to link in too many shared libraries */
pub const ELIBEXEC: isize = 83; /* Cannot exec a shared library directly */ pub const ELIBEXEC: i32 = 83; /* Cannot exec a shared library directly */
pub const EILSEQ: isize = 84; /* Illegal byte sequence */ pub const EILSEQ: i32 = 84; /* Illegal byte sequence */
pub const ERESTART: isize = 85; /* Interrupted system call should be restarted */ pub const ERESTART: i32 = 85; /* Interrupted system call should be restarted */
pub const ESTRPIPE: isize = 86; /* Streams pipe error */ pub const ESTRPIPE: i32 = 86; /* Streams pipe error */
pub const EUSERS: isize = 87; /* Too many users */ pub const EUSERS: i32 = 87; /* Too many users */
pub const ENOTSOCK: isize = 88; /* Socket operation on non-socket */ pub const ENOTSOCK: i32 = 88; /* Socket operation on non-socket */
pub const EDESTADDRREQ: isize = 89; /* Destination address required */ pub const EDESTADDRREQ: i32 = 89; /* Destination address required */
pub const EMSGSIZE: isize = 90; /* Message too long */ pub const EMSGSIZE: i32 = 90; /* Message too long */
pub const EPROTOTYPE: isize = 91; /* Protocol wrong type for socket */ pub const EPROTOTYPE: i32 = 91; /* Protocol wrong type for socket */
pub const ENOPROTOOPT: isize = 92; /* Protocol not available */ pub const ENOPROTOOPT: i32 = 92; /* Protocol not available */
pub const EPROTONOSUPPORT: isize = 93; /* Protocol not supported */ pub const EPROTONOSUPPORT: i32 = 93; /* Protocol not supported */
pub const ESOCKTNOSUPPORT: isize = 94; /* Socket type not supported */ pub const ESOCKTNOSUPPORT: i32 = 94; /* Socket type not supported */
pub const EOPNOTSUPP: isize = 95; /* Operation not supported on transport endpoint */ pub const EOPNOTSUPP: i32 = 95; /* Operation not supported on transport endpoint */
pub const EPFNOSUPPORT: isize = 96; /* Protocol family not supported */ pub const EPFNOSUPPORT: i32 = 96; /* Protocol family not supported */
pub const EAFNOSUPPORT: isize = 97; /* Address family not supported by protocol */ pub const EAFNOSUPPORT: i32 = 97; /* Address family not supported by protocol */
pub const EADDRINUSE: isize = 98; /* Address already in use */ pub const EADDRINUSE: i32 = 98; /* Address already in use */
pub const EADDRNOTAVAIL: isize = 99; /* Cannot assign requested address */ pub const EADDRNOTAVAIL: i32 = 99; /* Cannot assign requested address */
pub const ENETDOWN: isize = 100; /* Network is down */ pub const ENETDOWN: i32 = 100; /* Network is down */
pub const ENETUNREACH: isize = 101; /* Network is unreachable */ pub const ENETUNREACH: i32 = 101; /* Network is unreachable */
pub const ENETRESET: isize = 102; /* Network dropped connection because of reset */ pub const ENETRESET: i32 = 102; /* Network dropped connection because of reset */
pub const ECONNABORTED: isize = 103; /* Software caused connection abort */ pub const ECONNABORTED: i32 = 103; /* Software caused connection abort */
pub const ECONNRESET: isize = 104; /* Connection reset by peer */ pub const ECONNRESET: i32 = 104; /* Connection reset by peer */
pub const ENOBUFS: isize = 105; /* No buffer space available */ pub const ENOBUFS: i32 = 105; /* No buffer space available */
pub const EISCONN: isize = 106; /* Transport endpoint is already connected */ pub const EISCONN: i32 = 106; /* Transport endpoint is already connected */
pub const ENOTCONN: isize = 107; /* Transport endpoint is not connected */ pub const ENOTCONN: i32 = 107; /* Transport endpoint is not connected */
pub const ESHUTDOWN: isize = 108; /* Cannot send after transport endpoint shutdown */ pub const ESHUTDOWN: i32 = 108; /* Cannot send after transport endpoint shutdown */
pub const ETOOMANYREFS: isize = 109; /* Too many references: cannot splice */ pub const ETOOMANYREFS: i32 = 109; /* Too many references: cannot splice */
pub const ETIMEDOUT: isize = 110; /* Connection timed out */ pub const ETIMEDOUT: i32 = 110; /* Connection timed out */
pub const ECONNREFUSED: isize = 111; /* Connection refused */ pub const ECONNREFUSED: i32 = 111; /* Connection refused */
pub const EHOSTDOWN: isize = 112; /* Host is down */ pub const EHOSTDOWN: i32 = 112; /* Host is down */
pub const EHOSTUNREACH: isize = 113; /* No route to host */ pub const EHOSTUNREACH: i32 = 113; /* No route to host */
pub const EALREADY: isize = 114; /* Operation already in progress */ pub const EALREADY: i32 = 114; /* Operation already in progress */
pub const EINPROGRESS: isize = 115; /* Operation now in progress */ pub const EINPROGRESS: i32 = 115; /* Operation now in progress */
pub const ESTALE: isize = 116; /* Stale NFS file handle */ pub const ESTALE: i32 = 116; /* Stale NFS file handle */
pub const EUCLEAN: isize = 117; /* Structure needs cleaning */ pub const EUCLEAN: i32 = 117; /* Structure needs cleaning */
pub const ENOTNAM: isize = 118; /* Not a XENIX named type file */ pub const ENOTNAM: i32 = 118; /* Not a XENIX named type file */
pub const ENAVAIL: isize = 119; /* No XENIX semaphores available */ pub const ENAVAIL: i32 = 119; /* No XENIX semaphores available */
pub const EISNAM: isize = 120; /* Is a named type file */ pub const EISNAM: i32 = 120; /* Is a named type file */
pub const EREMOTEIO: isize = 121; /* Remote I/O error */ pub const EREMOTEIO: i32 = 121; /* Remote I/O error */
pub const EDQUOT: isize = 122; /* Quota exceeded */ pub const EDQUOT: i32 = 122; /* Quota exceeded */
pub const ENOMEDIUM: isize = 123; /* No medium found */ pub const ENOMEDIUM: i32 = 123; /* No medium found */
pub const EMEDIUMTYPE: isize = 124; /* Wrong medium type */ pub const EMEDIUMTYPE: i32 = 124; /* Wrong medium type */
pub const ECANCELED: isize = 125; /* Operation Canceled */ pub const ECANCELED: i32 = 125; /* Operation Canceled */
pub const ENOKEY: isize = 126; /* Required key not available */ pub const ENOKEY: i32 = 126; /* Required key not available */
pub const EKEYEXPIRED: isize = 127; /* Key has expired */ pub const EKEYEXPIRED: i32 = 127; /* Key has expired */
pub const EKEYREVOKED: isize = 128; /* Key has been revoked */ pub const EKEYREVOKED: i32 = 128; /* Key has been revoked */
pub const EKEYREJECTED: isize = 129; /* Key was rejected by service */ pub const EKEYREJECTED: i32 = 129; /* Key was rejected by service */
pub const EOWNERDEAD: isize = 130; /* Owner died */ pub const EOWNERDEAD: i32 = 130; /* Owner died */
pub const ENOTRECOVERABLE: isize = 131; /* State not recoverable */ pub const ENOTRECOVERABLE: i32 = 131; /* State not recoverable */
pub static STR_ERROR: [&'static str; 132] = ["Success", pub static STR_ERROR: [&'static str; 132] = ["Success",
"Operation not permitted", "Operation not permitted",

View file

@ -47,6 +47,7 @@ pub const O_CLOEXEC: usize = 0x0100_0000;
pub const O_CREAT: usize = 0x0200_0000; pub const O_CREAT: usize = 0x0200_0000;
pub const O_TRUNC: usize = 0x0400_0000; pub const O_TRUNC: usize = 0x0400_0000;
pub const O_EXCL: usize = 0x0800_0000; pub const O_EXCL: usize = 0x0800_0000;
pub const O_ACCMODE: usize = O_RDONLY | O_WRONLY | O_RDWR;
pub const SEEK_SET: usize = 0; pub const SEEK_SET: usize = 0;
pub const SEEK_CUR: usize = 1; pub const SEEK_CUR: usize = 1;