Smp (#23)
* 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:
parent
25dc44b348
commit
149b0297a4
16
Makefile
16
Makefile
|
@ -26,12 +26,14 @@ all: $(KBUILD)/harddrive.bin
|
|||
clean:
|
||||
cargo clean
|
||||
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/e1000d/Cargo.toml
|
||||
cargo clean --manifest-path drivers/ps2d/Cargo.toml
|
||||
cargo clean --manifest-path drivers/pcid/Cargo.toml
|
||||
cargo clean --manifest-path drivers/rtl8168d/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/ion/Cargo.toml
|
||||
cargo clean --manifest-path programs/coreutils/Cargo.toml
|
||||
|
@ -75,12 +77,14 @@ doc-%: schemes/%/Cargo.toml all FORCE
|
|||
update:
|
||||
cargo update
|
||||
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/e1000d/Cargo.toml
|
||||
cargo update --manifest-path drivers/ps2d/Cargo.toml
|
||||
cargo update --manifest-path drivers/pcid/Cargo.toml
|
||||
cargo update --manifest-path drivers/rtl8168d/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/ion/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)
|
||||
$(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
|
||||
$(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 $@ $<
|
||||
|
||||
$(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 $@ $<
|
||||
|
||||
openlibm/libopenlibm.a:
|
||||
|
@ -432,7 +436,7 @@ $(BUILD)/filesystem.bin: \
|
|||
filesystem/bin/smith \
|
||||
filesystem/bin/tar
|
||||
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/
|
||||
cargo run --manifest-path schemes/redoxfs/Cargo.toml --bin redoxfs-fuse $@ $(BUILD)/filesystem/ &
|
||||
sleep 2
|
||||
|
|
|
@ -7,6 +7,7 @@ bitflags = "*"
|
|||
hole_list_allocator = { path = "../../crates/hole_list_allocator/" }
|
||||
io = { path = "../../crates/io/" }
|
||||
spin = "*"
|
||||
syscall = { path = "../../syscall/" }
|
||||
|
||||
[dependencies.x86]
|
||||
version = "0.7"
|
||||
|
|
|
@ -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 {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,20 +4,19 @@
|
|||
use core::intrinsics::{atomic_load, atomic_store};
|
||||
use core::sync::atomic::Ordering;
|
||||
|
||||
use device::local_apic::LOCAL_APIC;
|
||||
use interrupt;
|
||||
use memory::{allocate_frames, Frame};
|
||||
use paging::{entry, ActivePageTable, Page, PhysicalAddress, VirtualAddress};
|
||||
use start::{kstart_ap, CPU_COUNT, AP_READY};
|
||||
|
||||
use self::dmar::{Dmar, DmarEntry};
|
||||
use self::local_apic::LocalApic;
|
||||
use self::madt::{Madt, MadtEntry};
|
||||
use self::rsdt::Rsdt;
|
||||
use self::sdt::Sdt;
|
||||
use self::xsdt::Xsdt;
|
||||
|
||||
pub mod dmar;
|
||||
pub mod local_apic;
|
||||
pub mod madt;
|
||||
pub mod rsdt;
|
||||
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) {
|
||||
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;
|
||||
|
||||
|
@ -60,7 +59,7 @@ pub fn init_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) {
|
|||
} else {
|
||||
if ap_local_apic.flags & 1 == 1 {
|
||||
// Increase CPU ID
|
||||
let cpu_id = CPU_COUNT.fetch_add(1, Ordering::SeqCst);
|
||||
CPU_COUNT.fetch_add(1, Ordering::SeqCst);
|
||||
|
||||
// Allocate a stack
|
||||
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
|
||||
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_stack_start, stack_start as u64) };
|
||||
unsafe { atomic_store(ap_stack_end, stack_end as u64) };
|
||||
|
|
|
@ -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
|
||||
/// 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 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);
|
||||
}
|
||||
|
|
114
arch/x86_64/src/device/local_apic.rs
Normal file
114
arch/x86_64/src/device/local_apic.rs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,15 @@
|
|||
use paging::ActivePageTable;
|
||||
|
||||
pub mod local_apic;
|
||||
pub mod rtc;
|
||||
pub mod serial;
|
||||
|
||||
pub unsafe fn init(){
|
||||
pub unsafe fn init(active_table: &mut ActivePageTable){
|
||||
local_apic::init(active_table);
|
||||
rtc::init();
|
||||
serial::init();
|
||||
}
|
||||
|
||||
pub unsafe fn init_ap() {
|
||||
local_apic::init_ap();
|
||||
}
|
||||
|
|
|
@ -58,6 +58,9 @@ pub unsafe fn init() {
|
|||
IDT[46].set_func(irq::ata1);
|
||||
IDT[47].set_func(irq::ata2);
|
||||
|
||||
// Set IPI handler (null)
|
||||
IDT[0x40].set_func(ipi::ipi);
|
||||
|
||||
// Set syscall function
|
||||
IDT[0x80].set_func(syscall::syscall);
|
||||
IDT[0x80].set_flags(IDT_PRESENT | IDT_RING_3 | IDT_INTERRUPT);
|
||||
|
|
|
@ -1,115 +1,140 @@
|
|||
use super::{halt, stack_trace};
|
||||
|
||||
interrupt!(divide_by_zero, {
|
||||
print!("Divide by zero fault\n");
|
||||
use syscall::flag::*;
|
||||
|
||||
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();
|
||||
loop { halt(); }
|
||||
});
|
||||
|
||||
interrupt!(debug, {
|
||||
print!("Debug trap\n");
|
||||
interrupt_stack!(debug, stack, {
|
||||
println!("Debug trap at {:>02X}:{:>016X}", stack.cs, stack.rip);
|
||||
ksignal(SIGTRAP);
|
||||
});
|
||||
|
||||
interrupt!(non_maskable, {
|
||||
print!("Non-maskable interrupt\n");
|
||||
interrupt_stack!(non_maskable, stack, {
|
||||
println!("Non-maskable interrupt at {:>02X}:{:>016X}", stack.cs, stack.rip);
|
||||
});
|
||||
|
||||
interrupt!(breakpoint, {
|
||||
print!("Breakpoint trap\n");
|
||||
interrupt_stack!(breakpoint, stack, {
|
||||
println!("Breakpoint trap at {:>02X}:{:>016X}", stack.cs, stack.rip);
|
||||
ksignal(SIGTRAP);
|
||||
});
|
||||
|
||||
interrupt!(overflow, {
|
||||
print!("Overflow trap\n");
|
||||
interrupt_stack!(overflow, stack, {
|
||||
println!("Overflow trap at {:>02X}:{:>016X}", stack.cs, stack.rip);
|
||||
ksignal(SIGFPE);
|
||||
});
|
||||
|
||||
interrupt!(bound_range, {
|
||||
print!("Bound range exceeded fault\n");
|
||||
interrupt_stack!(bound_range, stack, {
|
||||
println!("Bound range exceeded fault at {:>02X}:{:>016X}", stack.cs, stack.rip);
|
||||
ksignal(SIGSEGV);
|
||||
stack_trace();
|
||||
loop { halt(); }
|
||||
});
|
||||
|
||||
interrupt!(invalid_opcode, {
|
||||
print!("Invalid opcode fault\n");
|
||||
interrupt_stack!(invalid_opcode, stack, {
|
||||
println!("Invalid opcode fault at {:>02X}:{:>016X}", stack.cs, stack.rip);
|
||||
ksignal(SIGILL);
|
||||
stack_trace();
|
||||
loop { halt(); }
|
||||
});
|
||||
|
||||
interrupt!(device_not_available, {
|
||||
print!("Device not available fault\n");
|
||||
interrupt_stack!(device_not_available, stack, {
|
||||
println!("Device not available fault at {:>02X}:{:>016X}", stack.cs, stack.rip);
|
||||
ksignal(SIGILL);
|
||||
stack_trace();
|
||||
loop { halt(); }
|
||||
});
|
||||
|
||||
interrupt_error!(double_fault, {
|
||||
print!("Double fault\n");
|
||||
interrupt_error!(double_fault, stack, {
|
||||
println!("Double fault: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip);
|
||||
ksignal(SIGSEGV);
|
||||
stack_trace();
|
||||
loop { halt(); }
|
||||
});
|
||||
|
||||
interrupt_error!(invalid_tss, {
|
||||
print!("Invalid TSS fault\n");
|
||||
interrupt_error!(invalid_tss, stack, {
|
||||
println!("Invalid TSS fault: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip);
|
||||
ksignal(SIGSEGV);
|
||||
stack_trace();
|
||||
loop { halt(); }
|
||||
});
|
||||
|
||||
interrupt_error!(segment_not_present, {
|
||||
print!("Segment not present fault\n");
|
||||
interrupt_error!(segment_not_present, stack, {
|
||||
println!("Segment not present fault: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip);
|
||||
ksignal(SIGSEGV);
|
||||
stack_trace();
|
||||
loop { halt(); }
|
||||
});
|
||||
|
||||
interrupt_error!(stack_segment, {
|
||||
print!("Stack segment fault\n");
|
||||
interrupt_error!(stack_segment, stack, {
|
||||
println!("Stack segment fault: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip);
|
||||
ksignal(SIGSEGV);
|
||||
stack_trace();
|
||||
loop { halt(); }
|
||||
});
|
||||
|
||||
interrupt_error!(protection, {
|
||||
print!("Protection fault\n");
|
||||
interrupt_error!(protection, stack, {
|
||||
println!("Protection fault: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip);
|
||||
ksignal(SIGSEGV);
|
||||
stack_trace();
|
||||
loop { halt(); }
|
||||
});
|
||||
|
||||
interrupt_error!(page, {
|
||||
interrupt_error!(page, stack, {
|
||||
let cr2: usize;
|
||||
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();
|
||||
loop { halt(); }
|
||||
});
|
||||
|
||||
interrupt!(fpu, {
|
||||
print!("FPU floating point fault\n");
|
||||
interrupt_stack!(fpu, stack, {
|
||||
println!("FPU floating point fault at {:>02X}:{:>016X}", stack.cs, stack.rip);
|
||||
ksignal(SIGFPE);
|
||||
stack_trace();
|
||||
loop { halt(); }
|
||||
});
|
||||
|
||||
interrupt_error!(alignment_check, {
|
||||
print!("Alignment check fault\n");
|
||||
interrupt_error!(alignment_check, stack, {
|
||||
println!("Alignment check fault: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip);
|
||||
ksignal(SIGBUS);
|
||||
stack_trace();
|
||||
loop { halt(); }
|
||||
});
|
||||
|
||||
interrupt!(machine_check, {
|
||||
print!("Machine check fault\n");
|
||||
interrupt_stack!(machine_check, stack, {
|
||||
println!("Machine check fault at {:>02X}:{:>016X}", stack.cs, stack.rip);
|
||||
ksignal(SIGBUS);
|
||||
stack_trace();
|
||||
loop { halt(); }
|
||||
});
|
||||
|
||||
interrupt!(simd, {
|
||||
print!("SIMD floating point fault\n");
|
||||
interrupt_stack!(simd, stack, {
|
||||
println!("SIMD floating point fault at {:>02X}:{:>016X}", stack.cs, stack.rip);
|
||||
ksignal(SIGFPE);
|
||||
stack_trace();
|
||||
loop { halt(); }
|
||||
});
|
||||
|
||||
interrupt!(virtualization, {
|
||||
print!("Virtualization fault\n");
|
||||
interrupt_stack!(virtualization, stack, {
|
||||
println!("Virtualization fault at {:>02X}:{:>016X}", stack.cs, stack.rip);
|
||||
ksignal(SIGBUS);
|
||||
stack_trace();
|
||||
loop { halt(); }
|
||||
});
|
||||
|
||||
interrupt_error!(security, {
|
||||
print!("Security exception\n");
|
||||
interrupt_error!(security, stack, {
|
||||
println!("Security exception: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip);
|
||||
ksignal(SIGBUS);
|
||||
stack_trace();
|
||||
loop { halt(); }
|
||||
});
|
||||
|
|
5
arch/x86_64/src/interrupt/ipi.rs
Normal file
5
arch/x86_64/src/interrupt/ipi.rs
Normal file
|
@ -0,0 +1,5 @@
|
|||
use device::local_apic::LOCAL_APIC;
|
||||
|
||||
interrupt!(ipi, {
|
||||
LOCAL_APIC.eoi();
|
||||
});
|
|
@ -5,6 +5,7 @@ use core::mem;
|
|||
use paging::{ActivePageTable, VirtualAddress};
|
||||
|
||||
pub mod exception;
|
||||
pub mod ipi;
|
||||
pub mod irq;
|
||||
pub mod syscall;
|
||||
|
||||
|
|
|
@ -23,17 +23,21 @@ pub unsafe extern fn syscall() {
|
|||
asm!("" : : "{rax}"(a) : : "intel", "volatile");
|
||||
}
|
||||
|
||||
asm!("push fs
|
||||
push rax
|
||||
mov rax, 0x18
|
||||
mov fs, ax
|
||||
pop rax"
|
||||
asm!("push r15
|
||||
rdfsbase r15
|
||||
push r15
|
||||
push fs
|
||||
mov r15, 0x18
|
||||
mov fs, r15"
|
||||
: : : : "intel", "volatile");
|
||||
|
||||
inner();
|
||||
|
||||
// Interrupt return
|
||||
asm!("pop fs
|
||||
pop r15
|
||||
wrfsbase r15
|
||||
pop r15
|
||||
iretq"
|
||||
: : : : "intel", "volatile");
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ extern crate hole_list_allocator as allocator;
|
|||
extern crate bitflags;
|
||||
extern crate io;
|
||||
extern crate spin;
|
||||
extern crate syscall;
|
||||
pub extern crate x86;
|
||||
|
||||
// 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
|
||||
//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
|
||||
pub const KERNEL_PERCPU_SIZE: usize = 64 * 1024; // 64 KB
|
||||
|
||||
|
@ -61,8 +62,11 @@ pub extern crate x86;
|
|||
/// Size of user stack
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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
|
||||
#[macro_export]
|
||||
|
@ -111,6 +118,8 @@ macro_rules! interrupt {
|
|||
push r9
|
||||
push r10
|
||||
push r11
|
||||
rdfsbase rax
|
||||
push rax
|
||||
push fs
|
||||
mov rax, 0x18
|
||||
mov fs, ax"
|
||||
|
@ -121,6 +130,8 @@ macro_rules! interrupt {
|
|||
|
||||
// Pop scratch registers and return
|
||||
asm!("pop fs
|
||||
pop rax
|
||||
wrfsbase rax
|
||||
pop r11
|
||||
pop r10
|
||||
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_rules! interrupt_error {
|
||||
($name:ident, $func:block) => {
|
||||
macro_rules! interrupt_stack {
|
||||
($name:ident, $stack: ident, $func:block) => {
|
||||
#[naked]
|
||||
pub unsafe extern fn $name () {
|
||||
#[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
|
||||
}
|
||||
|
||||
|
@ -162,8 +261,12 @@ macro_rules! interrupt_error {
|
|||
mov fs, ax"
|
||||
: : : : "intel", "volatile");
|
||||
|
||||
// Get reference to stack variables
|
||||
let rsp: usize;
|
||||
asm!("" : "={rsp}"(rsp) : : : "intel", "volatile");
|
||||
|
||||
// Call inner rust function
|
||||
inner();
|
||||
inner(&*(rsp as *const $crate::InterruptErrorStack));
|
||||
|
||||
// Pop scratch registers, error code, and return
|
||||
asm!("pop fs
|
||||
|
|
|
@ -109,7 +109,7 @@ pub unsafe extern fn kstart() -> ! {
|
|||
}
|
||||
|
||||
// Initialize devices
|
||||
device::init();
|
||||
device::init(&mut active_table);
|
||||
|
||||
// Read ACPI tables, starts APs
|
||||
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);
|
||||
}
|
||||
|
||||
// Initialize devices (for AP)
|
||||
device::init_ap();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
pub unsafe fn usermode(ip: usize, sp: usize) -> ! {
|
||||
pub unsafe fn usermode(ip: usize, sp: usize, fs: usize) -> ! {
|
||||
// Go to usermode
|
||||
asm!("mov ds, ax
|
||||
asm!("xchg bx, bx
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
wrfsbase rbx
|
||||
push rax
|
||||
push rbx
|
||||
push rcx
|
||||
push rdx
|
||||
push rsi
|
||||
push rdi
|
||||
iretq"
|
||||
: // No output because it never returns
|
||||
: "{rax}"(gdt::GDT_USER_DATA << 3 | 3), // Stack segment
|
||||
"{rbx}"(sp), // Stack pointer
|
||||
"{rcx}"(3 << 12 | 1 << 9), // Flags - Set IOPL and interrupt enable flag
|
||||
"{rdx}"(gdt::GDT_USER_CODE << 3 | 3), // Code segment
|
||||
"{rsi}"(ip) // IP
|
||||
: "{rax}"(gdt::GDT_USER_DATA << 3 | 3), // Data segment
|
||||
"{rbx}"(fs), // TLS segment
|
||||
"{rcx}"(sp), // Stack pointer
|
||||
"{rdx}"(3 << 12 | 1 << 9), // Flags - Set IOPL and interrupt enable flag
|
||||
"{rsi}"(gdt::GDT_USER_CODE << 3 | 3), // Code segment
|
||||
"{rdi}"(ip) // IP
|
||||
: // No clobers because it never returns
|
||||
: "intel", "volatile");
|
||||
unreachable!();
|
||||
|
|
|
@ -26,9 +26,9 @@ startup_ap:
|
|||
mov edi, 0x70000
|
||||
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
|
||||
or eax, 1 << 7 | 1 << 5 | 1 << 4
|
||||
or eax, 1 << 16 | 1 << 9 | 1 << 7 | 1 << 5 | 1 << 4
|
||||
mov cr4, eax
|
||||
|
||||
; load protected mode GDT
|
||||
|
@ -91,9 +91,9 @@ startup_arch:
|
|||
mov edi, 0x70000
|
||||
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
|
||||
or eax, 1 << 7 | 1 << 5 | 1 << 4
|
||||
or eax, 1 << 16 | 1 << 9 | 1 << 7 | 1 << 5 | 1 << 4
|
||||
mov cr4, eax
|
||||
|
||||
; load protected mode GDT
|
||||
|
|
|
@ -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
|
||||
/// event loop
|
||||
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));
|
||||
|
||||
|
@ -41,7 +41,7 @@ impl<R> EventQueue<R> {
|
|||
/// 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>>>>> {
|
||||
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))
|
||||
} else {
|
||||
|
|
|
@ -30,11 +30,6 @@ fn main() {
|
|||
print!("{}", format!(" + AHCI on: {:X} IRQ: {}\n", bar, irq));
|
||||
|
||||
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 socket_fd = syscall::open(":disk", syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK).expect("ahcid: failed to create disk scheme");
|
||||
|
|
|
@ -30,11 +30,6 @@ fn main() {
|
|||
print!("{}", format!(" + E1000 on: {:X}, IRQ: {}\n", bar, irq));
|
||||
|
||||
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 = Arc::new(RefCell::new(unsafe { File::from_raw_fd(socket_fd) }));
|
||||
|
||||
|
|
|
@ -122,7 +122,7 @@ fn main() {
|
|||
thread::spawn(|| {
|
||||
unsafe {
|
||||
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");
|
||||
|
|
|
@ -31,11 +31,6 @@ fn main() {
|
|||
print!("{}", format!(" + RTL8168 on: {:X}, IRQ: {}\n", bar, irq));
|
||||
|
||||
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 = Arc::new(RefCell::new(unsafe { File::from_raw_fd(socket_fd) }));
|
||||
|
||||
|
|
|
@ -8,4 +8,4 @@ dhcpd
|
|||
httpd
|
||||
getty display:2
|
||||
getty display:3
|
||||
#orbital display:4
|
||||
orbital display:4
|
||||
|
|
|
@ -5,7 +5,7 @@ use spin::Mutex;
|
|||
|
||||
use arch;
|
||||
use context::file::File;
|
||||
use context::memory::{Grant, Memory, SharedMemory};
|
||||
use context::memory::{Grant, Memory, SharedMemory, Tls};
|
||||
use syscall::data::Event;
|
||||
use sync::{WaitCondition, WaitQueue};
|
||||
|
||||
|
@ -36,7 +36,7 @@ pub struct Context {
|
|||
/// Context running or not
|
||||
pub running: bool,
|
||||
/// CPU ID, if locked
|
||||
pub cpuid: Option<usize>,
|
||||
pub cpu_id: Option<usize>,
|
||||
/// Context is halting parent
|
||||
pub vfork: bool,
|
||||
/// Context is being waited on
|
||||
|
@ -55,6 +55,8 @@ pub struct Context {
|
|||
pub heap: Option<SharedMemory>,
|
||||
/// User stack
|
||||
pub stack: Option<Memory>,
|
||||
/// User Tls
|
||||
pub tls: Option<Tls>,
|
||||
/// User grants
|
||||
pub grants: Arc<Mutex<Vec<Grant>>>,
|
||||
/// The name of the context
|
||||
|
@ -81,7 +83,7 @@ impl Context {
|
|||
egid: 0,
|
||||
status: Status::Blocked,
|
||||
running: false,
|
||||
cpuid: None,
|
||||
cpu_id: None,
|
||||
vfork: false,
|
||||
waitpid: Arc::new(WaitCondition::new()),
|
||||
wake: None,
|
||||
|
@ -91,6 +93,7 @@ impl Context {
|
|||
image: Vec::new(),
|
||||
heap: None,
|
||||
stack: None,
|
||||
tls: None,
|
||||
grants: Arc::new(Mutex::new(Vec::new())),
|
||||
name: 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 {
|
||||
if self.status == Status::Blocked {
|
||||
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
|
||||
} else {
|
||||
false
|
||||
|
|
|
@ -332,3 +332,10 @@ impl Drop for Memory {
|
|||
self.unmap(true);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Tls {
|
||||
pub master: VirtualAddress,
|
||||
pub file_size: usize,
|
||||
pub mem: Memory
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ pub fn init() {
|
|||
context.kfx = Some(fx);
|
||||
context.status = Status::Runnable;
|
||||
context.running = true;
|
||||
context.cpuid = Some(::cpu_id());
|
||||
context.cpu_id = Some(::cpu_id());
|
||||
CONTEXT_ID.store(context.id, Ordering::SeqCst);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,18 +16,24 @@ pub unsafe fn switch() -> bool {
|
|||
arch::interrupt::pause();
|
||||
}
|
||||
|
||||
let cpu_id = ::cpu_id();
|
||||
|
||||
let from_ptr;
|
||||
let mut to_ptr = 0 as *mut Context;
|
||||
{
|
||||
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();
|
||||
from_ptr = context.deref_mut() as *mut Context;
|
||||
}
|
||||
|
||||
let check_context = |context: &mut Context| -> bool {
|
||||
if context.cpuid == None || context.cpuid == Some(::cpu_id()) {
|
||||
if context.cpu_id == None && cpu_id == 0 {
|
||||
context.cpu_id = Some(cpu_id);
|
||||
println!("{}: take {} {}", cpu_id, context.id, ::core::str::from_utf8_unchecked(&context.name.lock()));
|
||||
}
|
||||
|
||||
if context.status == Status::Blocked && context.wake.is_some() {
|
||||
let wake = context.wake.expect("context::switch: wake not set");
|
||||
|
||||
|
@ -37,6 +43,7 @@ pub unsafe fn switch() -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
if context.cpu_id == Some(cpu_id) {
|
||||
if context.status == Status::Runnable && ! context.running {
|
||||
return true;
|
||||
}
|
||||
|
@ -74,8 +81,6 @@ pub unsafe fn switch() -> bool {
|
|||
return false;
|
||||
}
|
||||
|
||||
// println!("{}: Switch {} to {}", ::cpu_id(), (&*from_ptr).id, (&*to_ptr).id);
|
||||
|
||||
(&mut *from_ptr).running = false;
|
||||
(&mut *to_ptr).running = true;
|
||||
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);
|
||||
|
||||
// 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);
|
||||
|
||||
true
|
||||
|
|
|
@ -152,6 +152,19 @@ pub extern fn userspace_init() {
|
|||
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]
|
||||
pub extern fn kmain(cpus: usize) {
|
||||
CPU_ID.store(0, Ordering::SeqCst);
|
||||
|
@ -195,6 +208,14 @@ pub extern fn kmain_ap(id: usize) {
|
|||
println!("AP {}: {:?}", id, pid);
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,12 +5,13 @@ use context;
|
|||
use syscall::error::Result;
|
||||
|
||||
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",
|
||||
"PPID",
|
||||
"UID",
|
||||
"GID",
|
||||
"STAT",
|
||||
"CPU",
|
||||
"MEM",
|
||||
"NAME");
|
||||
{
|
||||
|
@ -18,6 +19,35 @@ pub fn resource() -> Result<Vec<u8>> {
|
|||
for (_id, context_lock) in contexts.iter() {
|
||||
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;
|
||||
if let Some(ref kfx) = context.kstack {
|
||||
memory += kfx.len();
|
||||
|
@ -49,38 +79,16 @@ pub fn resource() -> Result<Vec<u8>> {
|
|||
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 = 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.ppid,
|
||||
context.euid,
|
||||
context.egid,
|
||||
stat_string,
|
||||
cpu_string,
|
||||
memory_string,
|
||||
name));
|
||||
}
|
||||
|
|
|
@ -62,6 +62,7 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<usize> {
|
|||
let rgid;
|
||||
let euid;
|
||||
let egid;
|
||||
let mut cpu_id = None;
|
||||
let arch;
|
||||
let vfork;
|
||||
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 heap_option = None;
|
||||
let mut stack_option = None;
|
||||
let mut tls_option = None;
|
||||
let grants;
|
||||
let name;
|
||||
let cwd;
|
||||
|
@ -88,6 +90,10 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<usize> {
|
|||
euid = context.euid;
|
||||
egid = context.egid;
|
||||
|
||||
if flags & CLONE_VM == CLONE_VM {
|
||||
cpu_id = context.cpu_id;
|
||||
}
|
||||
|
||||
arch = context.arch.clone();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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 {
|
||||
grants = context.grants.clone();
|
||||
} else {
|
||||
|
@ -277,6 +306,8 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<usize> {
|
|||
context.euid = euid;
|
||||
context.egid = egid;
|
||||
|
||||
context.cpu_id = cpu_id;
|
||||
|
||||
context.status = context::Status::Runnable;
|
||||
|
||||
context.vfork = vfork;
|
||||
|
@ -393,6 +424,12 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<usize> {
|
|||
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.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> {
|
||||
let entry;
|
||||
let mut sp = arch::USER_STACK_OFFSET + arch::USER_STACK_SIZE - 256;
|
||||
let fs = arch::USER_STACK_OFFSET;
|
||||
|
||||
{
|
||||
let mut args = Vec::new();
|
||||
|
@ -466,11 +504,12 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> {
|
|||
// Set name
|
||||
context.name = Arc::new(Mutex::new(canonical));
|
||||
|
||||
// Unmap previous image and stack
|
||||
// Unmap previous image, heap, grants, stack, and tls
|
||||
context.image.clear();
|
||||
drop(context.heap.take());
|
||||
drop(context.stack.take());
|
||||
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 {
|
||||
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
|
||||
let mut tls_option = None;
|
||||
for segment in elf.segments() {
|
||||
if segment.p_type == program_header::PT_LOAD {
|
||||
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);
|
||||
|
||||
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
|
||||
));
|
||||
|
||||
// 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;
|
||||
for arg in args.iter().rev() {
|
||||
sp -= mem::size_of::<usize>();
|
||||
|
@ -597,7 +672,7 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> {
|
|||
}
|
||||
|
||||
// Go to usermode
|
||||
unsafe { usermode(entry, sp); }
|
||||
unsafe { usermode(entry, sp, fs); }
|
||||
}
|
||||
|
||||
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> {
|
||||
loop {
|
||||
let mut exited = false;
|
||||
let mut running;
|
||||
let waitpid;
|
||||
{
|
||||
let contexts = context::contexts();
|
||||
|
@ -909,10 +985,23 @@ pub fn waitpid(pid: usize, status_ptr: usize, flags: usize) -> Result<usize> {
|
|||
}
|
||||
exited = true;
|
||||
}
|
||||
running = context.running;
|
||||
waitpid = context.waitpid.clone();
|
||||
}
|
||||
|
||||
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();
|
||||
return contexts.remove(pid).ok_or(Error::new(ESRCH)).and(Ok(pid));
|
||||
} else if flags & WNOHANG == WNOHANG {
|
||||
|
|
2
libstd
2
libstd
|
@ -1 +1 @@
|
|||
Subproject commit 8a29d8ff3304b78d74e0259270ba50cb33765a63
|
||||
Subproject commit 263ed59929e68073bd4e47ba07f2fbe283ee2854
|
18
libstd_real/Cargo.toml
Normal file
18
libstd_real/Cargo.toml
Normal 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" }
|
12
libstd_real/alloc_system/Cargo.toml
Normal file
12
libstd_real/alloc_system/Cargo.toml
Normal 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" }
|
6
libstd_real/alloc_system/src/lib.rs
Normal file
6
libstd_real/alloc_system/src/lib.rs
Normal file
|
@ -0,0 +1,6 @@
|
|||
#![allocator]
|
||||
#![feature(allocator)]
|
||||
#![no_std]
|
||||
|
||||
#[allocator]
|
||||
extern crate ralloc;
|
4
libstd_real/compiler_builtins/Cargo.toml
Normal file
4
libstd_real/compiler_builtins/Cargo.toml
Normal file
|
@ -0,0 +1,4 @@
|
|||
[package]
|
||||
name = "compiler_builtins"
|
||||
version = "0.1.0"
|
||||
authors = ["Jeremy Soller <jackpot51@gmail.com>"]
|
72
libstd_real/compiler_builtins/src/lib.rs
Normal file
72
libstd_real/compiler_builtins/src/lib.rs
Normal 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
|
||||
}
|
7
libstd_real/libc/Cargo.toml
Normal file
7
libstd_real/libc/Cargo.toml
Normal file
|
@ -0,0 +1,7 @@
|
|||
[package]
|
||||
name = "libc"
|
||||
version = "0.1.0"
|
||||
authors = ["Jeremy Soller <jackpot51@gmail.com>"]
|
||||
|
||||
[dependencies]
|
||||
syscall = { path = "../../syscall/" }
|
19
libstd_real/libc/src/funcs.rs
Normal file
19
libstd_real/libc/src/funcs.rs
Normal 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
|
||||
}
|
18
libstd_real/libc/src/lib.rs
Normal file
18
libstd_real/libc/src/lib.rs
Normal 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;
|
40
libstd_real/libc/src/start.rs
Normal file
40
libstd_real/libc/src/start.rs
Normal 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));
|
||||
}
|
87
libstd_real/libc/src/syscall.rs
Normal file
87
libstd_real/libc/src/syscall.rs
Normal 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)))
|
||||
}
|
96
libstd_real/libc/src/types.rs
Normal file
96
libstd_real/libc/src/types.rs
Normal 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,
|
||||
}
|
7
libstd_real/panic_unwind/Cargo.toml
Normal file
7
libstd_real/panic_unwind/Cargo.toml
Normal file
|
@ -0,0 +1,7 @@
|
|||
[package]
|
||||
name = "panic_unwind"
|
||||
version = "0.0.0"
|
||||
authors = ["Jeremy Soller <jackpot51@gmail.com>"]
|
||||
|
||||
[dependencies]
|
||||
syscall = { path = "../../syscall/" }
|
27
libstd_real/panic_unwind/src/lib.rs
Normal file
27
libstd_real/panic_unwind/src/lib.rs
Normal 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();
|
||||
}
|
4
libstd_real/unwind/Cargo.toml
Normal file
4
libstd_real/unwind/Cargo.toml
Normal file
|
@ -0,0 +1,4 @@
|
|||
[package]
|
||||
name = "unwind"
|
||||
version = "0.0.0"
|
||||
authors = ["Jeremy Soller <jackpot51@gmail.com>"]
|
1
libstd_real/unwind/src/lib.rs
Normal file
1
libstd_real/unwind/src/lib.rs
Normal file
|
@ -0,0 +1 @@
|
|||
#![no_std]
|
|
@ -1 +1 @@
|
|||
Subproject commit 1afcf7ab26ca3f697082674e6a72c94dd211c74b
|
||||
Subproject commit 519d98880c7c0a6b40111e7861259cf46998cee3
|
|
@ -1 +1 @@
|
|||
Subproject commit 7d5233187721918f4c00726771c3ec2d44a1f8c6
|
||||
Subproject commit a6e4162839279e639057b616ac79d34421f85754
|
2
rust
2
rust
|
@ -1 +1 @@
|
|||
Subproject commit 17af6b94b2ea39414e4449c17cc4ab066d790e8f
|
||||
Subproject commit 123d08b3d3901d5725af8303c1329b007089cde5
|
|
@ -6,7 +6,7 @@ use std::{cmp, str, u16};
|
|||
|
||||
use netutils::{getcfg, MacAddr, EthernetII};
|
||||
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::scheme::SchemeMut;
|
||||
|
||||
|
@ -63,7 +63,7 @@ impl EthernetScheme {
|
|||
impl SchemeMut for EthernetScheme {
|
||||
fn open(&mut self, url: &[u8], flags: usize, uid: u32, _gid: u32) -> Result<usize> {
|
||||
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 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) {
|
||||
frame.header.src = handle.host_addr;
|
||||
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 {
|
||||
Err(Error::new(EINVAL))
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ use std::os::unix::io::FromRawFd;
|
|||
use std::rc::Rc;
|
||||
use std::{slice, str, thread};
|
||||
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::scheme::SchemeMut;
|
||||
|
||||
|
@ -275,7 +275,7 @@ impl SchemeMut for Ipd {
|
|||
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());
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ use std::rc::Rc;
|
|||
use event::EventQueue;
|
||||
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::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::scheme::SchemeMut;
|
||||
|
||||
|
@ -274,7 +274,7 @@ impl Tcpd {
|
|||
|
||||
let tcp = handle.create_tcp(TCP_ACK | TCP_PSH, buf.to_vec());
|
||||
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() {
|
||||
handle.seq += buf.len() as u32;
|
||||
}
|
||||
|
@ -422,7 +422,7 @@ impl SchemeMut for Tcpd {
|
|||
|
||||
let tcp = handle.create_tcp(TCP_SYN, Vec::new());
|
||||
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;
|
||||
}
|
||||
|
@ -469,7 +469,7 @@ impl SchemeMut for Tcpd {
|
|||
|
||||
let tcp = new_handle.create_tcp(TCP_SYN | TCP_ACK, Vec::new());
|
||||
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;
|
||||
} else {
|
||||
|
@ -506,7 +506,7 @@ impl SchemeMut for Tcpd {
|
|||
|
||||
let tcp = new_handle.create_tcp(TCP_SYN, Vec::new());
|
||||
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 {
|
||||
return Err(Error::new(EINVAL));
|
||||
}
|
||||
|
@ -559,7 +559,7 @@ impl SchemeMut for Tcpd {
|
|||
State::Established => {
|
||||
let tcp = handle.create_tcp(TCP_ACK | TCP_PSH, buf.to_vec());
|
||||
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;
|
||||
Ok(buf.len())
|
||||
},
|
||||
|
@ -611,7 +611,7 @@ impl SchemeMut for Tcpd {
|
|||
|
||||
let tcp = handle.create_tcp(TCP_FIN | TCP_ACK, Vec::new());
|
||||
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;
|
||||
|
||||
|
@ -622,7 +622,7 @@ impl SchemeMut for Tcpd {
|
|||
|
||||
let tcp = handle.create_tcp(TCP_FIN | TCP_ACK, Vec::new());
|
||||
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;
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ use std::rc::Rc;
|
|||
use event::EventQueue;
|
||||
use netutils::{n16, Ipv4, Ipv4Addr, Ipv4Header, Udp, UdpHeader, Checksum};
|
||||
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::scheme::SchemeMut;
|
||||
|
||||
|
@ -265,7 +265,7 @@ impl SchemeMut for Udpd {
|
|||
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()))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -61,7 +61,13 @@ pub struct Stat {
|
|||
pub st_mode: u16,
|
||||
pub st_uid: 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 {
|
||||
|
|
|
@ -2,13 +2,13 @@ use core::{fmt, result};
|
|||
|
||||
#[derive(Eq, PartialEq)]
|
||||
pub struct Error {
|
||||
pub errno: isize,
|
||||
pub errno: i32,
|
||||
}
|
||||
|
||||
pub type Result<T> = result::Result<T, Error>;
|
||||
|
||||
impl Error {
|
||||
pub fn new(errno: isize) -> Error {
|
||||
pub fn new(errno: i32) -> Error {
|
||||
Error { errno: errno }
|
||||
}
|
||||
|
||||
|
@ -20,8 +20,8 @@ impl Error {
|
|||
}
|
||||
|
||||
pub fn demux(value: usize) -> Result<usize> {
|
||||
let errno = -(value as isize);
|
||||
if errno >= 1 && errno < STR_ERROR.len() as isize {
|
||||
let errno = -(value as i32);
|
||||
if errno >= 1 && errno < STR_ERROR.len() as i32 {
|
||||
Err(Error::new(errno))
|
||||
} else {
|
||||
Ok(value)
|
||||
|
@ -49,137 +49,137 @@ impl fmt::Display for Error {
|
|||
}
|
||||
}
|
||||
|
||||
pub const EPERM: isize = 1; /* Operation not permitted */
|
||||
pub const ENOENT: isize = 2; /* No such file or directory */
|
||||
pub const ESRCH: isize = 3; /* No such process */
|
||||
pub const EINTR: isize = 4; /* Interrupted system call */
|
||||
pub const EIO: isize = 5; /* I/O error */
|
||||
pub const ENXIO: isize = 6; /* No such device or address */
|
||||
pub const E2BIG: isize = 7; /* Argument list too long */
|
||||
pub const ENOEXEC: isize = 8; /* Exec format error */
|
||||
pub const EBADF: isize = 9; /* Bad file number */
|
||||
pub const ECHILD: isize = 10; /* No child processes */
|
||||
pub const EAGAIN: isize = 11; /* Try again */
|
||||
pub const ENOMEM: isize = 12; /* Out of memory */
|
||||
pub const EACCES: isize = 13; /* Permission denied */
|
||||
pub const EFAULT: isize = 14; /* Bad address */
|
||||
pub const ENOTBLK: isize = 15; /* Block device required */
|
||||
pub const EBUSY: isize = 16; /* Device or resource busy */
|
||||
pub const EEXIST: isize = 17; /* File exists */
|
||||
pub const EXDEV: isize = 18; /* Cross-device link */
|
||||
pub const ENODEV: isize = 19; /* No such device */
|
||||
pub const ENOTDIR: isize = 20; /* Not a directory */
|
||||
pub const EISDIR: isize = 21; /* Is a directory */
|
||||
pub const EINVAL: isize = 22; /* Invalid argument */
|
||||
pub const ENFILE: isize = 23; /* File table overflow */
|
||||
pub const EMFILE: isize = 24; /* Too many open files */
|
||||
pub const ENOTTY: isize = 25; /* Not a typewriter */
|
||||
pub const ETXTBSY: isize = 26; /* Text file busy */
|
||||
pub const EFBIG: isize = 27; /* File too large */
|
||||
pub const ENOSPC: isize = 28; /* No space left on device */
|
||||
pub const ESPIPE: isize = 29; /* Illegal seek */
|
||||
pub const EROFS: isize = 30; /* Read-only file system */
|
||||
pub const EMLINK: isize = 31; /* Too many links */
|
||||
pub const EPIPE: isize = 32; /* Broken pipe */
|
||||
pub const EDOM: isize = 33; /* Math argument out of domain of func */
|
||||
pub const ERANGE: isize = 34; /* Math result not representable */
|
||||
pub const EDEADLK: isize = 35; /* Resource deadlock would occur */
|
||||
pub const ENAMETOOLONG: isize = 36; /* File name too long */
|
||||
pub const ENOLCK: isize = 37; /* No record locks available */
|
||||
pub const ENOSYS: isize = 38; /* Function not implemented */
|
||||
pub const ENOTEMPTY: isize = 39; /* Directory not empty */
|
||||
pub const ELOOP: isize = 40; /* Too many symbolic links encountered */
|
||||
pub const EWOULDBLOCK: isize = 41; /* Operation would block */
|
||||
pub const ENOMSG: isize = 42; /* No message of desired type */
|
||||
pub const EIDRM: isize = 43; /* Identifier removed */
|
||||
pub const ECHRNG: isize = 44; /* Channel number out of range */
|
||||
pub const EL2NSYNC: isize = 45; /* Level 2 not synchronized */
|
||||
pub const EL3HLT: isize = 46; /* Level 3 halted */
|
||||
pub const EL3RST: isize = 47; /* Level 3 reset */
|
||||
pub const ELNRNG: isize = 48; /* Link number out of range */
|
||||
pub const EUNATCH: isize = 49; /* Protocol driver not attached */
|
||||
pub const ENOCSI: isize = 50; /* No CSI structure available */
|
||||
pub const EL2HLT: isize = 51; /* Level 2 halted */
|
||||
pub const EBADE: isize = 52; /* Invalid exchange */
|
||||
pub const EBADR: isize = 53; /* Invalid request descriptor */
|
||||
pub const EXFULL: isize = 54; /* Exchange full */
|
||||
pub const ENOANO: isize = 55; /* No anode */
|
||||
pub const EBADRQC: isize = 56; /* Invalid request code */
|
||||
pub const EBADSLT: isize = 57; /* Invalid slot */
|
||||
pub const EDEADLOCK: isize = 58; /* Resource deadlock would occur */
|
||||
pub const EBFONT: isize = 59; /* Bad font file format */
|
||||
pub const ENOSTR: isize = 60; /* Device not a stream */
|
||||
pub const ENODATA: isize = 61; /* No data available */
|
||||
pub const ETIME: isize = 62; /* Timer expired */
|
||||
pub const ENOSR: isize = 63; /* Out of streams resources */
|
||||
pub const ENONET: isize = 64; /* Machine is not on the network */
|
||||
pub const ENOPKG: isize = 65; /* Package not installed */
|
||||
pub const EREMOTE: isize = 66; /* Object is remote */
|
||||
pub const ENOLINK: isize = 67; /* Link has been severed */
|
||||
pub const EADV: isize = 68; /* Advertise error */
|
||||
pub const ESRMNT: isize = 69; /* Srmount error */
|
||||
pub const ECOMM: isize = 70; /* Communication error on send */
|
||||
pub const EPROTO: isize = 71; /* Protocol error */
|
||||
pub const EMULTIHOP: isize = 72; /* Multihop attempted */
|
||||
pub const EDOTDOT: isize = 73; /* RFS specific error */
|
||||
pub const EBADMSG: isize = 74; /* Not a data message */
|
||||
pub const EOVERFLOW: isize = 75; /* Value too large for defined data type */
|
||||
pub const ENOTUNIQ: isize = 76; /* Name not unique on network */
|
||||
pub const EBADFD: isize = 77; /* File descriptor in bad state */
|
||||
pub const EREMCHG: isize = 78; /* Remote address changed */
|
||||
pub const ELIBACC: isize = 79; /* Can not access a needed shared library */
|
||||
pub const ELIBBAD: isize = 80; /* Accessing a corrupted shared library */
|
||||
pub const ELIBSCN: isize = 81; /* .lib section in a.out corrupted */
|
||||
pub const ELIBMAX: isize = 82; /* Attempting to link in too many shared libraries */
|
||||
pub const ELIBEXEC: isize = 83; /* Cannot exec a shared library directly */
|
||||
pub const EILSEQ: isize = 84; /* Illegal byte sequence */
|
||||
pub const ERESTART: isize = 85; /* Interrupted system call should be restarted */
|
||||
pub const ESTRPIPE: isize = 86; /* Streams pipe error */
|
||||
pub const EUSERS: isize = 87; /* Too many users */
|
||||
pub const ENOTSOCK: isize = 88; /* Socket operation on non-socket */
|
||||
pub const EDESTADDRREQ: isize = 89; /* Destination address required */
|
||||
pub const EMSGSIZE: isize = 90; /* Message too long */
|
||||
pub const EPROTOTYPE: isize = 91; /* Protocol wrong type for socket */
|
||||
pub const ENOPROTOOPT: isize = 92; /* Protocol not available */
|
||||
pub const EPROTONOSUPPORT: isize = 93; /* Protocol not supported */
|
||||
pub const ESOCKTNOSUPPORT: isize = 94; /* Socket type not supported */
|
||||
pub const EOPNOTSUPP: isize = 95; /* Operation not supported on transport endpoint */
|
||||
pub const EPFNOSUPPORT: isize = 96; /* Protocol family not supported */
|
||||
pub const EAFNOSUPPORT: isize = 97; /* Address family not supported by protocol */
|
||||
pub const EADDRINUSE: isize = 98; /* Address already in use */
|
||||
pub const EADDRNOTAVAIL: isize = 99; /* Cannot assign requested address */
|
||||
pub const ENETDOWN: isize = 100; /* Network is down */
|
||||
pub const ENETUNREACH: isize = 101; /* Network is unreachable */
|
||||
pub const ENETRESET: isize = 102; /* Network dropped connection because of reset */
|
||||
pub const ECONNABORTED: isize = 103; /* Software caused connection abort */
|
||||
pub const ECONNRESET: isize = 104; /* Connection reset by peer */
|
||||
pub const ENOBUFS: isize = 105; /* No buffer space available */
|
||||
pub const EISCONN: isize = 106; /* Transport endpoint is already connected */
|
||||
pub const ENOTCONN: isize = 107; /* Transport endpoint is not connected */
|
||||
pub const ESHUTDOWN: isize = 108; /* Cannot send after transport endpoint shutdown */
|
||||
pub const ETOOMANYREFS: isize = 109; /* Too many references: cannot splice */
|
||||
pub const ETIMEDOUT: isize = 110; /* Connection timed out */
|
||||
pub const ECONNREFUSED: isize = 111; /* Connection refused */
|
||||
pub const EHOSTDOWN: isize = 112; /* Host is down */
|
||||
pub const EHOSTUNREACH: isize = 113; /* No route to host */
|
||||
pub const EALREADY: isize = 114; /* Operation already in progress */
|
||||
pub const EINPROGRESS: isize = 115; /* Operation now in progress */
|
||||
pub const ESTALE: isize = 116; /* Stale NFS file handle */
|
||||
pub const EUCLEAN: isize = 117; /* Structure needs cleaning */
|
||||
pub const ENOTNAM: isize = 118; /* Not a XENIX named type file */
|
||||
pub const ENAVAIL: isize = 119; /* No XENIX semaphores available */
|
||||
pub const EISNAM: isize = 120; /* Is a named type file */
|
||||
pub const EREMOTEIO: isize = 121; /* Remote I/O error */
|
||||
pub const EDQUOT: isize = 122; /* Quota exceeded */
|
||||
pub const ENOMEDIUM: isize = 123; /* No medium found */
|
||||
pub const EMEDIUMTYPE: isize = 124; /* Wrong medium type */
|
||||
pub const ECANCELED: isize = 125; /* Operation Canceled */
|
||||
pub const ENOKEY: isize = 126; /* Required key not available */
|
||||
pub const EKEYEXPIRED: isize = 127; /* Key has expired */
|
||||
pub const EKEYREVOKED: isize = 128; /* Key has been revoked */
|
||||
pub const EKEYREJECTED: isize = 129; /* Key was rejected by service */
|
||||
pub const EOWNERDEAD: isize = 130; /* Owner died */
|
||||
pub const ENOTRECOVERABLE: isize = 131; /* State not recoverable */
|
||||
pub const EPERM: i32 = 1; /* Operation not permitted */
|
||||
pub const ENOENT: i32 = 2; /* No such file or directory */
|
||||
pub const ESRCH: i32 = 3; /* No such process */
|
||||
pub const EINTR: i32 = 4; /* Interrupted system call */
|
||||
pub const EIO: i32 = 5; /* I/O error */
|
||||
pub const ENXIO: i32 = 6; /* No such device or address */
|
||||
pub const E2BIG: i32 = 7; /* Argument list too long */
|
||||
pub const ENOEXEC: i32 = 8; /* Exec format error */
|
||||
pub const EBADF: i32 = 9; /* Bad file number */
|
||||
pub const ECHILD: i32 = 10; /* No child processes */
|
||||
pub const EAGAIN: i32 = 11; /* Try again */
|
||||
pub const ENOMEM: i32 = 12; /* Out of memory */
|
||||
pub const EACCES: i32 = 13; /* Permission denied */
|
||||
pub const EFAULT: i32 = 14; /* Bad address */
|
||||
pub const ENOTBLK: i32 = 15; /* Block device required */
|
||||
pub const EBUSY: i32 = 16; /* Device or resource busy */
|
||||
pub const EEXIST: i32 = 17; /* File exists */
|
||||
pub const EXDEV: i32 = 18; /* Cross-device link */
|
||||
pub const ENODEV: i32 = 19; /* No such device */
|
||||
pub const ENOTDIR: i32 = 20; /* Not a directory */
|
||||
pub const EISDIR: i32 = 21; /* Is a directory */
|
||||
pub const EINVAL: i32 = 22; /* Invalid argument */
|
||||
pub const ENFILE: i32 = 23; /* File table overflow */
|
||||
pub const EMFILE: i32 = 24; /* Too many open files */
|
||||
pub const ENOTTY: i32 = 25; /* Not a typewriter */
|
||||
pub const ETXTBSY: i32 = 26; /* Text file busy */
|
||||
pub const EFBIG: i32 = 27; /* File too large */
|
||||
pub const ENOSPC: i32 = 28; /* No space left on device */
|
||||
pub const ESPIPE: i32 = 29; /* Illegal seek */
|
||||
pub const EROFS: i32 = 30; /* Read-only file system */
|
||||
pub const EMLINK: i32 = 31; /* Too many links */
|
||||
pub const EPIPE: i32 = 32; /* Broken pipe */
|
||||
pub const EDOM: i32 = 33; /* Math argument out of domain of func */
|
||||
pub const ERANGE: i32 = 34; /* Math result not representable */
|
||||
pub const EDEADLK: i32 = 35; /* Resource deadlock would occur */
|
||||
pub const ENAMETOOLONG: i32 = 36; /* File name too long */
|
||||
pub const ENOLCK: i32 = 37; /* No record locks available */
|
||||
pub const ENOSYS: i32 = 38; /* Function not implemented */
|
||||
pub const ENOTEMPTY: i32 = 39; /* Directory not empty */
|
||||
pub const ELOOP: i32 = 40; /* Too many symbolic links encountered */
|
||||
pub const EWOULDBLOCK: i32 = 41; /* Operation would block */
|
||||
pub const ENOMSG: i32 = 42; /* No message of desired type */
|
||||
pub const EIDRM: i32 = 43; /* Identifier removed */
|
||||
pub const ECHRNG: i32 = 44; /* Channel number out of range */
|
||||
pub const EL2NSYNC: i32 = 45; /* Level 2 not synchronized */
|
||||
pub const EL3HLT: i32 = 46; /* Level 3 halted */
|
||||
pub const EL3RST: i32 = 47; /* Level 3 reset */
|
||||
pub const ELNRNG: i32 = 48; /* Link number out of range */
|
||||
pub const EUNATCH: i32 = 49; /* Protocol driver not attached */
|
||||
pub const ENOCSI: i32 = 50; /* No CSI structure available */
|
||||
pub const EL2HLT: i32 = 51; /* Level 2 halted */
|
||||
pub const EBADE: i32 = 52; /* Invalid exchange */
|
||||
pub const EBADR: i32 = 53; /* Invalid request descriptor */
|
||||
pub const EXFULL: i32 = 54; /* Exchange full */
|
||||
pub const ENOANO: i32 = 55; /* No anode */
|
||||
pub const EBADRQC: i32 = 56; /* Invalid request code */
|
||||
pub const EBADSLT: i32 = 57; /* Invalid slot */
|
||||
pub const EDEADLOCK: i32 = 58; /* Resource deadlock would occur */
|
||||
pub const EBFONT: i32 = 59; /* Bad font file format */
|
||||
pub const ENOSTR: i32 = 60; /* Device not a stream */
|
||||
pub const ENODATA: i32 = 61; /* No data available */
|
||||
pub const ETIME: i32 = 62; /* Timer expired */
|
||||
pub const ENOSR: i32 = 63; /* Out of streams resources */
|
||||
pub const ENONET: i32 = 64; /* Machine is not on the network */
|
||||
pub const ENOPKG: i32 = 65; /* Package not installed */
|
||||
pub const EREMOTE: i32 = 66; /* Object is remote */
|
||||
pub const ENOLINK: i32 = 67; /* Link has been severed */
|
||||
pub const EADV: i32 = 68; /* Advertise error */
|
||||
pub const ESRMNT: i32 = 69; /* Srmount error */
|
||||
pub const ECOMM: i32 = 70; /* Communication error on send */
|
||||
pub const EPROTO: i32 = 71; /* Protocol error */
|
||||
pub const EMULTIHOP: i32 = 72; /* Multihop attempted */
|
||||
pub const EDOTDOT: i32 = 73; /* RFS specific error */
|
||||
pub const EBADMSG: i32 = 74; /* Not a data message */
|
||||
pub const EOVERFLOW: i32 = 75; /* Value too large for defined data type */
|
||||
pub const ENOTUNIQ: i32 = 76; /* Name not unique on network */
|
||||
pub const EBADFD: i32 = 77; /* File descriptor in bad state */
|
||||
pub const EREMCHG: i32 = 78; /* Remote address changed */
|
||||
pub const ELIBACC: i32 = 79; /* Can not access a needed shared library */
|
||||
pub const ELIBBAD: i32 = 80; /* Accessing a corrupted shared library */
|
||||
pub const ELIBSCN: i32 = 81; /* .lib section in a.out corrupted */
|
||||
pub const ELIBMAX: i32 = 82; /* Attempting to link in too many shared libraries */
|
||||
pub const ELIBEXEC: i32 = 83; /* Cannot exec a shared library directly */
|
||||
pub const EILSEQ: i32 = 84; /* Illegal byte sequence */
|
||||
pub const ERESTART: i32 = 85; /* Interrupted system call should be restarted */
|
||||
pub const ESTRPIPE: i32 = 86; /* Streams pipe error */
|
||||
pub const EUSERS: i32 = 87; /* Too many users */
|
||||
pub const ENOTSOCK: i32 = 88; /* Socket operation on non-socket */
|
||||
pub const EDESTADDRREQ: i32 = 89; /* Destination address required */
|
||||
pub const EMSGSIZE: i32 = 90; /* Message too long */
|
||||
pub const EPROTOTYPE: i32 = 91; /* Protocol wrong type for socket */
|
||||
pub const ENOPROTOOPT: i32 = 92; /* Protocol not available */
|
||||
pub const EPROTONOSUPPORT: i32 = 93; /* Protocol not supported */
|
||||
pub const ESOCKTNOSUPPORT: i32 = 94; /* Socket type not supported */
|
||||
pub const EOPNOTSUPP: i32 = 95; /* Operation not supported on transport endpoint */
|
||||
pub const EPFNOSUPPORT: i32 = 96; /* Protocol family not supported */
|
||||
pub const EAFNOSUPPORT: i32 = 97; /* Address family not supported by protocol */
|
||||
pub const EADDRINUSE: i32 = 98; /* Address already in use */
|
||||
pub const EADDRNOTAVAIL: i32 = 99; /* Cannot assign requested address */
|
||||
pub const ENETDOWN: i32 = 100; /* Network is down */
|
||||
pub const ENETUNREACH: i32 = 101; /* Network is unreachable */
|
||||
pub const ENETRESET: i32 = 102; /* Network dropped connection because of reset */
|
||||
pub const ECONNABORTED: i32 = 103; /* Software caused connection abort */
|
||||
pub const ECONNRESET: i32 = 104; /* Connection reset by peer */
|
||||
pub const ENOBUFS: i32 = 105; /* No buffer space available */
|
||||
pub const EISCONN: i32 = 106; /* Transport endpoint is already connected */
|
||||
pub const ENOTCONN: i32 = 107; /* Transport endpoint is not connected */
|
||||
pub const ESHUTDOWN: i32 = 108; /* Cannot send after transport endpoint shutdown */
|
||||
pub const ETOOMANYREFS: i32 = 109; /* Too many references: cannot splice */
|
||||
pub const ETIMEDOUT: i32 = 110; /* Connection timed out */
|
||||
pub const ECONNREFUSED: i32 = 111; /* Connection refused */
|
||||
pub const EHOSTDOWN: i32 = 112; /* Host is down */
|
||||
pub const EHOSTUNREACH: i32 = 113; /* No route to host */
|
||||
pub const EALREADY: i32 = 114; /* Operation already in progress */
|
||||
pub const EINPROGRESS: i32 = 115; /* Operation now in progress */
|
||||
pub const ESTALE: i32 = 116; /* Stale NFS file handle */
|
||||
pub const EUCLEAN: i32 = 117; /* Structure needs cleaning */
|
||||
pub const ENOTNAM: i32 = 118; /* Not a XENIX named type file */
|
||||
pub const ENAVAIL: i32 = 119; /* No XENIX semaphores available */
|
||||
pub const EISNAM: i32 = 120; /* Is a named type file */
|
||||
pub const EREMOTEIO: i32 = 121; /* Remote I/O error */
|
||||
pub const EDQUOT: i32 = 122; /* Quota exceeded */
|
||||
pub const ENOMEDIUM: i32 = 123; /* No medium found */
|
||||
pub const EMEDIUMTYPE: i32 = 124; /* Wrong medium type */
|
||||
pub const ECANCELED: i32 = 125; /* Operation Canceled */
|
||||
pub const ENOKEY: i32 = 126; /* Required key not available */
|
||||
pub const EKEYEXPIRED: i32 = 127; /* Key has expired */
|
||||
pub const EKEYREVOKED: i32 = 128; /* Key has been revoked */
|
||||
pub const EKEYREJECTED: i32 = 129; /* Key was rejected by service */
|
||||
pub const EOWNERDEAD: i32 = 130; /* Owner died */
|
||||
pub const ENOTRECOVERABLE: i32 = 131; /* State not recoverable */
|
||||
|
||||
pub static STR_ERROR: [&'static str; 132] = ["Success",
|
||||
"Operation not permitted",
|
||||
|
|
|
@ -47,6 +47,7 @@ pub const O_CLOEXEC: usize = 0x0100_0000;
|
|||
pub const O_CREAT: usize = 0x0200_0000;
|
||||
pub const O_TRUNC: usize = 0x0400_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_CUR: usize = 1;
|
||||
|
|
Loading…
Reference in a new issue