Implement exec
Implement brk
This commit is contained in:
		
							parent
							
								
									f2ca411cd6
								
							
						
					
					
						commit
						44e8b99b46
					
				
					 11 changed files with 122 additions and 59 deletions
				
			
		
							
								
								
									
										12
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										12
									
								
								Makefile
									
										
									
									
									
								
							|  | @ -37,10 +37,10 @@ ifeq ($(ARCH),arm) | |||
| 	QEMUFLAGS+=-cpu arm1176 -machine integratorcp | ||||
| 	QEMUFLAGS+=-nographic | ||||
| 
 | ||||
| $(KBUILD)/kernel.list: $(KBUILD)/kernel.bin | ||||
| build/%.list: build/% | ||||
| 	$(ARCH)-none-eabi-objdump -C -D $< > $@ | ||||
| 
 | ||||
| $(KBUILD)/harddrive.bin: $(KBUILD)/kernel.bin | ||||
| $(KBUILD)/harddrive.bin: $(KBUILD)/kernel | ||||
| 	cp $< $@ | ||||
| 
 | ||||
| qemu: $(KBUILD)/harddrive.bin | ||||
|  | @ -60,11 +60,11 @@ endif | |||
| 		QEMUFLAGS= | ||||
| 	endif | ||||
| 
 | ||||
| $(KBUILD)/kernel.list: $(KBUILD)/kernel.bin | ||||
| build/%.list: build/% | ||||
| 	objdump -C -M intel -D $< > $@ | ||||
| 
 | ||||
| $(KBUILD)/harddrive.bin: $(KBUILD)/kernel.bin bootloader/$(ARCH)/** | ||||
| 	nasm -f bin -o $@ -D ARCH_$(ARCH) -ibootloader/$(ARCH)/ -i$(KBUILD)/ bootloader/$(ARCH)/harddrive.asm | ||||
| $(KBUILD)/harddrive.bin: $(KBUILD)/kernel bootloader/$(ARCH)/** | ||||
| 	nasm -f bin -o $@ -D ARCH_$(ARCH) -ibootloader/$(ARCH)/ bootloader/$(ARCH)/harddrive.asm | ||||
| 
 | ||||
| qemu: $(KBUILD)/harddrive.bin | ||||
| 	$(QEMU) $(QEMUFLAGS) -drive file=$<,format=raw,index=0,media=disk | ||||
|  | @ -93,7 +93,7 @@ $(KBUILD)/libcollections.rlib: rust/src/libcollections/lib.rs $(KBUILD)/libcore. | |||
| $(KBUILD)/libkernel.a: $(KBUILD)/libcore.rlib $(KBUILD)/liballoc.rlib $(KBUILD)/libcollections.rlib $(BUILD)/init kernel/** FORCE | ||||
| 	$(KCARGO) rustc $(KCARGOFLAGS) -o $@ | ||||
| 
 | ||||
| $(KBUILD)/kernel.bin: $(KBUILD)/libkernel.a | ||||
| $(KBUILD)/kernel: $(KBUILD)/libkernel.a | ||||
| 	$(LD) --gc-sections -z max-page-size=0x1000 -T arch/$(ARCH)/src/linker.ld -o $@ $< | ||||
| 
 | ||||
| # Userspace recipes
 | ||||
|  |  | |||
|  | @ -29,7 +29,11 @@ pub const BITMAP_OFFSET: usize = 0xffff_fe80_0000_0000; | |||
| /// Offset to kernel heap
 | ||||
| pub const HEAP_OFFSET: usize = 0xffff_fe00_0000_0000; | ||||
| /// Size of heap
 | ||||
| pub const HEAP_SIZE: usize = 64 * 1024 * 1024; // 128 MB
 | ||||
| pub const HEAP_SIZE: usize = 64 * 1024 * 1024; // 64 MB
 | ||||
| /// Offset to user heap
 | ||||
| pub const USER_HEAP_OFFSET: usize = 0x0000_0080_0000_0000; | ||||
| /// Size of user heap
 | ||||
| pub const USER_HEAP_SIZE: usize = 64 * 1024 * 1024; // 64 MB
 | ||||
| 
 | ||||
| /// Print to console
 | ||||
| #[macro_export] | ||||
|  |  | |||
|  | @ -12,7 +12,7 @@ align 512, db 0 | |||
| startup_end: | ||||
| 
 | ||||
| kernel_file: | ||||
|   incbin "kernel.bin" | ||||
|   incbin "build/kernel/kernel" | ||||
|   align 512, db 0 | ||||
| .end: | ||||
| .length equ kernel_file.end - kernel_file | ||||
|  |  | |||
|  | @ -1,7 +1,15 @@ | |||
| use std::fs::File; | ||||
| use std::io::{BufRead, BufReader}; | ||||
| use std::thread; | ||||
| 
 | ||||
| pub fn main() { | ||||
|     println!("Hello, World!"); | ||||
|     let mut file = File::open("initfs:etc/init.rc").expect("failed to open init.rc"); | ||||
|     let mut reader = BufReader::new(file); | ||||
| 
 | ||||
|     for line in reader.lines() { | ||||
|         println!("{}", line.expect("failed to read init.rc")); | ||||
|     } | ||||
| 
 | ||||
|     loop { | ||||
|         thread::yield_now(); | ||||
|     } | ||||
|  |  | |||
|  | @ -71,7 +71,7 @@ impl ContextList { | |||
|         let context_lock = self.new_context()?; | ||||
|         { | ||||
|             let mut context = context_lock.write(); | ||||
|             let mut stack = Box::new([0; 4096]); | ||||
|             let mut stack = Box::new([0; 65536]); | ||||
|             let offset = stack.len() - mem::size_of::<usize>(); | ||||
|             unsafe { | ||||
|                 let offset = stack.len() - mem::size_of::<usize>(); | ||||
|  |  | |||
|  | @ -116,14 +116,14 @@ pub mod syscall; | |||
| #[cfg(test)] | ||||
| pub mod tests; | ||||
| 
 | ||||
| pub extern fn context_test() { | ||||
|     print!("Test\n"); | ||||
|     unsafe { context::switch(); } | ||||
| pub extern fn userspace_init() { | ||||
|     assert_eq!(syscall::open(b"debug:", 0), Ok(0)); | ||||
|     assert_eq!(syscall::open(b"debug:", 0), Ok(1)); | ||||
|     assert_eq!(syscall::open(b"debug:", 0), Ok(2)); | ||||
| 
 | ||||
|     print!("Test halt\n"); | ||||
|     loop { | ||||
|         unsafe { interrupt::enable_and_halt(); } | ||||
|     } | ||||
|     syscall::exec(b"initfs:bin/init", &[]).expect("failed to execute initfs:init"); | ||||
| 
 | ||||
|     panic!("initfs:init returned") | ||||
| } | ||||
| 
 | ||||
| #[no_mangle] | ||||
|  | @ -133,36 +133,10 @@ pub extern fn kmain() { | |||
|     let pid = syscall::getpid(); | ||||
|     println!("BSP: {:?}", pid); | ||||
| 
 | ||||
|     assert_eq!(syscall::open(b"debug:", 0), Ok(0)); | ||||
|     assert_eq!(syscall::open(b"debug:", 0), Ok(1)); | ||||
|     assert_eq!(syscall::open(b"debug:", 0), Ok(2)); | ||||
|     context::contexts_mut().spawn(userspace_init).expect("failed to spawn userspace_init"); | ||||
| 
 | ||||
|     let init_file = syscall::open(b"initfs:init", 0).expect("failed to open initfs:init"); | ||||
|     let mut init_data = collections::Vec::new(); | ||||
|     loop { | ||||
|         let mut buf = [0; 65536]; | ||||
|         let count = syscall::read(init_file, &mut buf).expect("failed to read initfs:init"); | ||||
|         if count > 0 { | ||||
|             init_data.extend_from_slice(&buf[..count]); | ||||
|         } else { | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     let elf = elf::Elf::from(&init_data).expect("could not load elf"); | ||||
|     elf.run(); | ||||
| 
 | ||||
|     /* | ||||
|     if let Ok(_context_lock) = context::contexts_mut().spawn(context_test) { | ||||
|         print!("Spawned context\n"); | ||||
|     } | ||||
| 
 | ||||
|     print!("Main\n"); | ||||
|     unsafe { context::switch(); } | ||||
| 
 | ||||
|     print!("Main halt\n"); | ||||
|     */ | ||||
| 
 | ||||
|     loop { | ||||
|         unsafe { interrupt::enable_and_halt(); } | ||||
|     } | ||||
|  | @ -175,10 +149,6 @@ pub extern fn kmain_ap(id: usize) { | |||
|     let pid = syscall::getpid(); | ||||
|     println!("AP {}: {:?}", id, pid); | ||||
| 
 | ||||
|     assert_eq!(syscall::open(b"debug:", 0), Ok(0)); | ||||
|     assert_eq!(syscall::open(b"debug:", 0), Ok(1)); | ||||
|     assert_eq!(syscall::open(b"debug:", 0), Ok(2)); | ||||
| 
 | ||||
|     loop { | ||||
|         unsafe { interrupt::enable_and_halt() } | ||||
|     } | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ use super::Scheme; | |||
| pub struct DebugScheme; | ||||
| 
 | ||||
| impl Scheme for DebugScheme { | ||||
|     fn open(&mut self, path: &[u8], _flags: usize) -> Result<usize> { | ||||
|     fn open(&mut self, _path: &[u8], _flags: usize) -> Result<usize> { | ||||
|         Ok(0) | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -18,7 +18,8 @@ impl InitFsScheme { | |||
|     pub fn new() -> InitFsScheme { | ||||
|         let mut files: BTreeMap<&'static [u8], &'static [u8]> = BTreeMap::new(); | ||||
| 
 | ||||
|         files.insert(b"init", include_bytes!("../../build/userspace/init")); | ||||
|         files.insert(b"bin/init", include_bytes!("../../build/userspace/init")); | ||||
|         files.insert(b"etc/init.rc", b"echo testing\n"); | ||||
| 
 | ||||
|         InitFsScheme { | ||||
|             next_id: 0, | ||||
|  |  | |||
|  | @ -30,6 +30,8 @@ pub enum Call { | |||
|     Exec = 11, | ||||
|     /// Get process ID
 | ||||
|     GetPid = 20, | ||||
|     /// Set process break
 | ||||
|     Brk = 45, | ||||
|     /// Yield to scheduler
 | ||||
|     SchedYield = 158 | ||||
| } | ||||
|  | @ -46,6 +48,7 @@ impl Call { | |||
|             6 => Ok(Call::Close), | ||||
|             11 => Ok(Call::Exec), | ||||
|             20 => Ok(Call::GetPid), | ||||
|             45 => Ok(Call::Brk), | ||||
|             158 => Ok(Call::SchedYield), | ||||
|             _ => Err(Error::NoCall) | ||||
|         } | ||||
|  | @ -63,6 +66,8 @@ pub enum Error { | |||
|     NoEntry = 2, | ||||
|     /// No such process
 | ||||
|     NoProcess = 3, | ||||
|     /// Invalid executable format
 | ||||
|     NoExec = 8, | ||||
|     /// Bad file number
 | ||||
|     BadFile = 9, | ||||
|     /// Try again
 | ||||
|  | @ -100,6 +105,7 @@ pub fn handle(a: usize, b: usize, c: usize, d: usize, e: usize, _f: usize) -> Re | |||
|         Call::Close => close(b), | ||||
|         Call::Exec => exec(convert_slice(b as *const u8, c)?, convert_slice(d as *const [usize; 2], e)?), | ||||
|         Call::GetPid => getpid(), | ||||
|         Call::Brk => brk(b), | ||||
|         Call::SchedYield => sched_yield() | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -1,10 +1,63 @@ | |||
| ///! Process syscalls
 | ||||
| 
 | ||||
| use core::str; | ||||
| 
 | ||||
| use arch; | ||||
| use arch::interrupt::halt; | ||||
| 
 | ||||
| use arch::paging::{ActivePageTable, Page, VirtualAddress, entry}; | ||||
| use context; | ||||
| use elf; | ||||
| use syscall::{self, Error, Result}; | ||||
| 
 | ||||
| use super::{convert_slice, Error, Result}; | ||||
| pub fn brk(address: usize) -> Result<usize> { | ||||
|     //TODO: Make this more efficient
 | ||||
|     let mut active_table = unsafe { ActivePageTable::new() }; | ||||
|     let mut current = arch::USER_HEAP_OFFSET; | ||||
|     { | ||||
|         let min_page = Page::containing_address(VirtualAddress::new(arch::USER_HEAP_OFFSET)); | ||||
|         let max_page = Page::containing_address(VirtualAddress::new(arch::USER_HEAP_OFFSET + arch::USER_HEAP_SIZE - 1)); | ||||
|         for page in Page::range_inclusive(min_page, max_page) { | ||||
|             if active_table.translate_page(page).is_none() { | ||||
|                 break; | ||||
|             } | ||||
|             current = page.start_address().get() + 4096; | ||||
|         } | ||||
|     } | ||||
|     if address == 0 { | ||||
|         //println!("Brk query {:X}", current);
 | ||||
|         Ok(current) | ||||
|     } else if address > current { | ||||
|         let start_page = Page::containing_address(VirtualAddress::new(current)); | ||||
|         let end_page = Page::containing_address(VirtualAddress::new(address - 1)); | ||||
|         for page in Page::range_inclusive(start_page, end_page) { | ||||
|             //println!("Map {:X}", page.start_address().get());
 | ||||
|             if active_table.translate_page(page).is_none() { | ||||
|                 //println!("Not found - mapping");
 | ||||
|                 active_table.map(page, entry::PRESENT | entry::WRITABLE | entry::NO_EXECUTE | entry::USER_ACCESSIBLE); | ||||
|             } else { | ||||
|                 //println!("Found - skipping");
 | ||||
|             } | ||||
|         } | ||||
|         //let new = end_page.start_address().get() + 4096;
 | ||||
|         //println!("Brk increase {:X}: from {:X} to {:X}", address, current, new);
 | ||||
|         Ok(address) | ||||
|     } else { | ||||
|         let start_page = Page::containing_address(VirtualAddress::new(address)); | ||||
|         let end_page = Page::containing_address(VirtualAddress::new(current - 1)); | ||||
|         for page in Page::range_inclusive(start_page, end_page) { | ||||
|             //println!("Unmap {:X}", page.start_address().get());
 | ||||
|             if active_table.translate_page(page).is_some() { | ||||
|                 //println!("Found - unmapping");
 | ||||
|                 active_table.unmap(page); | ||||
|             } else { | ||||
|                 //println!("Not found - skipping");
 | ||||
|             } | ||||
|         } | ||||
|         //let new = start_page.start_address().get();
 | ||||
|         //println!("Brk decrease {:X}: from {:X} to {:X}", address, current, new);
 | ||||
|         Ok(address) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub fn exit(status: usize) -> ! { | ||||
|     println!("Exit {}", status); | ||||
|  | @ -13,13 +66,34 @@ pub fn exit(status: usize) -> ! { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| pub fn exec(path: &[u8], args: &[[usize; 2]]) -> Result<usize> { | ||||
|     print!("Exec {:?}", ::core::str::from_utf8(path)); | ||||
|     for arg in args { | ||||
|         print!(" {:?}", ::core::str::from_utf8(convert_slice(arg[0] as *const u8, arg[1])?)); | ||||
| pub fn exec(path: &[u8], _args: &[[usize; 2]]) -> Result<usize> { | ||||
|     //TODO: Use args
 | ||||
|     //TODO: Unmap previous mappings
 | ||||
|     //TODO: Drop init_data
 | ||||
| 
 | ||||
|     let init_file = syscall::open(path, 0)?; | ||||
|     let mut init_data = vec![]; | ||||
|     loop { | ||||
|         let mut buf = [0; 4096]; | ||||
|         let count = syscall::read(init_file, &mut buf)?; | ||||
|         if count > 0 { | ||||
|             init_data.extend_from_slice(&buf[..count]); | ||||
|         } else { | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|     let _ = syscall::close(init_file); | ||||
| 
 | ||||
|     match elf::Elf::from(&init_data) { | ||||
|         Ok(elf) => { | ||||
|             elf.run(); | ||||
|             Ok(0) | ||||
|         }, | ||||
|         Err(err) => { | ||||
|             println!("failed to execute {}: {}", unsafe { str::from_utf8_unchecked(path) }, err); | ||||
|             Err(Error::NoExec) | ||||
|         } | ||||
|     } | ||||
|     println!(""); | ||||
|     Ok(0) | ||||
| } | ||||
| 
 | ||||
| pub fn getpid() -> Result<usize> { | ||||
|  |  | |||
							
								
								
									
										2
									
								
								libstd
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								libstd
									
										
									
									
									
								
							|  | @ -1 +1 @@ | |||
| Subproject commit 7b20e739903a4877a10b64b875a3fd7a06cdcd16 | ||||
| Subproject commit 7ead704d48411cc66ce71ffe4f1fbe86a6a4cbe4 | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Jeremy Soller
						Jeremy Soller