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
					
				
					 54 changed files with 1121 additions and 380 deletions
				
			
		
							
								
								
									
										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"); | ||||
|  | @ -56,7 +51,7 @@ fn main() { | |||
|                         let mut packet = Packet::default(); | ||||
|                         if socket.read(&mut packet).expect("ahcid: failed to read disk scheme") == 0 { | ||||
|                             break; | ||||
|                         }                        
 | ||||
|                         } | ||||
|                         scheme.handle(&mut packet); | ||||
|                         socket.write(&mut packet).expect("ahcid: failed to write 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,27 +16,34 @@ 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.status == Status::Blocked && context.wake.is_some() { | ||||
|                     let wake = context.wake.expect("context::switch: wake not set"); | ||||
|             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())); | ||||
|             } | ||||
| 
 | ||||
|                     let current = arch::time::monotonic(); | ||||
|                     if current.0 > wake.0 || (current.0 == wake.0 && current.1 >= wake.1) { | ||||
|                         context.unblock(); | ||||
|                     } | ||||
|             if context.status == Status::Blocked && context.wake.is_some() { | ||||
|                 let wake = context.wake.expect("context::switch: wake not set"); | ||||
| 
 | ||||
|                 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 { | ||||
|                     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…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Jeremy Soller
						Jeremy Soller