Flush TLB correctly when remapping
Seperate mouse and keyboard structs in PS/2 driver
This commit is contained in:
		
							parent
							
								
									44e8b99b46
								
							
						
					
					
						commit
						8563961f28
					
				
					 8 changed files with 169 additions and 112 deletions
				
			
		
							
								
								
									
										5
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										5
									
								
								Makefile
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -47,7 +47,10 @@ qemu: $(KBUILD)/harddrive.bin
 | 
			
		|||
	$(QEMU) $(QEMUFLAGS) -kernel $<
 | 
			
		||||
else
 | 
			
		||||
	LD=ld
 | 
			
		||||
	QEMUFLAGS+=-enable-kvm -cpu host -machine q35 -smp 4
 | 
			
		||||
	QEMUFLAGS+=-machine q35 -smp 4
 | 
			
		||||
ifneq ($(kvm),no)
 | 
			
		||||
	QEMUFLAGS+=-enable-kvm -cpu host
 | 
			
		||||
endif
 | 
			
		||||
ifeq ($(vga),no)
 | 
			
		||||
	QEMUFLAGS+=-nographic -vga none
 | 
			
		||||
endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,10 +3,13 @@ use spin::Mutex;
 | 
			
		|||
 | 
			
		||||
use io::{Io, Pio, ReadOnly, WriteOnly};
 | 
			
		||||
 | 
			
		||||
pub static PS2: Mutex<Ps2> = Mutex::new(Ps2::new());
 | 
			
		||||
pub static PS2_KEYBOARD: Mutex<Option<Ps2Keyboard>> = Mutex::new(None);
 | 
			
		||||
pub static PS2_MOUSE: Mutex<Option<Ps2Mouse>> = Mutex::new(None);
 | 
			
		||||
 | 
			
		||||
pub unsafe fn init() {
 | 
			
		||||
    PS2.lock().init();
 | 
			
		||||
    let (keyboard, mouse) = Ps2::new().init();
 | 
			
		||||
    *PS2_KEYBOARD.lock() = keyboard;
 | 
			
		||||
    *PS2_MOUSE.lock() = mouse;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bitflags! {
 | 
			
		||||
| 
						 | 
				
			
			@ -95,12 +98,36 @@ bitflags! {
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub struct Ps2 {
 | 
			
		||||
    data: Pio<u8>,
 | 
			
		||||
    status: ReadOnly<Pio<u8>>,
 | 
			
		||||
    command: WriteOnly<Pio<u8>>,
 | 
			
		||||
pub struct Ps2Keyboard {
 | 
			
		||||
    data: ReadOnly<Pio<u8>>,
 | 
			
		||||
    key: [u8; 3],
 | 
			
		||||
    key_i: usize,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Ps2Keyboard {
 | 
			
		||||
    fn new() -> Self {
 | 
			
		||||
        Ps2Keyboard {
 | 
			
		||||
            data: ReadOnly::new(Pio::new(0x60)),
 | 
			
		||||
            key: [0; 3],
 | 
			
		||||
            key_i: 0
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn on_irq(&mut self) {
 | 
			
		||||
        let scancode = self.data.read();
 | 
			
		||||
        self.key[self.key_i] = scancode;
 | 
			
		||||
        self.key_i += 1;
 | 
			
		||||
        if self.key_i >= self.key.len() || scancode < 0xE0 {
 | 
			
		||||
            println!("KEY: {:X} {:X} {:X}", self.key[0], self.key[1], self.key[2]);
 | 
			
		||||
 | 
			
		||||
            self.key = [0; 3];
 | 
			
		||||
            self.key_i = 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub struct Ps2Mouse {
 | 
			
		||||
    data: ReadOnly<Pio<u8>>,
 | 
			
		||||
    mouse: [u8; 4],
 | 
			
		||||
    mouse_i: usize,
 | 
			
		||||
    mouse_extra: bool,
 | 
			
		||||
| 
						 | 
				
			
			@ -108,19 +135,76 @@ pub struct Ps2 {
 | 
			
		|||
    mouse_y: usize
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Ps2Mouse {
 | 
			
		||||
    fn new(mouse_extra: bool) -> Self {
 | 
			
		||||
        Ps2Mouse {
 | 
			
		||||
            data: ReadOnly::new(Pio::new(0x60)),
 | 
			
		||||
            mouse: [0; 4],
 | 
			
		||||
            mouse_i: 0,
 | 
			
		||||
            mouse_extra: mouse_extra,
 | 
			
		||||
            mouse_x: 0,
 | 
			
		||||
            mouse_y: 0
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn on_irq(&mut self) {
 | 
			
		||||
        self.mouse[self.mouse_i] = self.data.read();
 | 
			
		||||
        self.mouse_i += 1;
 | 
			
		||||
 | 
			
		||||
        let flags = MousePacketFlags::from_bits_truncate(self.mouse[0]);
 | 
			
		||||
        if ! flags.contains(ALWAYS_ON) {
 | 
			
		||||
            println!("MOUSE MISALIGN {:X}", self.mouse[0]);
 | 
			
		||||
 | 
			
		||||
            self.mouse = [0; 4];
 | 
			
		||||
            self.mouse_i = 0;
 | 
			
		||||
        } else if self.mouse_i >= self.mouse.len() || (!self.mouse_extra && self.mouse_i >= 3) {
 | 
			
		||||
            if ! flags.contains(X_OVERFLOW) && ! flags.contains(Y_OVERFLOW) {
 | 
			
		||||
                let mut dx = self.mouse[1] as isize;
 | 
			
		||||
                if flags.contains(X_SIGN) {
 | 
			
		||||
                    dx -= 0x100;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                let mut dy = self.mouse[2] as isize;
 | 
			
		||||
                if flags.contains(Y_SIGN) {
 | 
			
		||||
                    dy -= 0x100;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                let _extra = if self.mouse_extra {
 | 
			
		||||
                    self.mouse[3]
 | 
			
		||||
                } else {
 | 
			
		||||
                    0
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                //print!("MOUSE {:?}, {}, {}, {}\n", flags, dx, dy, extra);
 | 
			
		||||
 | 
			
		||||
                if let Some(ref mut display) = *super::display::DISPLAY.lock() {
 | 
			
		||||
                    self.mouse_x = cmp::max(0, cmp::min(display.width as isize - 1, self.mouse_x as isize + dx)) as usize;
 | 
			
		||||
                    self.mouse_y = cmp::max(0, cmp::min(display.height as isize - 1, self.mouse_y as isize - dy)) as usize;
 | 
			
		||||
                    let offset = self.mouse_y * display.width + self.mouse_x;
 | 
			
		||||
                    display.onscreen[offset as usize] = 0xFF0000;
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                println!("MOUSE OVERFLOW {:X} {:X} {:X} {:X}", self.mouse[0], self.mouse[1], self.mouse[2], self.mouse[3]);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            self.mouse = [0; 4];
 | 
			
		||||
            self.mouse_i = 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub struct Ps2 {
 | 
			
		||||
    data: Pio<u8>,
 | 
			
		||||
    status: ReadOnly<Pio<u8>>,
 | 
			
		||||
    command: WriteOnly<Pio<u8>>
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Ps2 {
 | 
			
		||||
    const fn new() -> Ps2 {
 | 
			
		||||
    const fn new() -> Self {
 | 
			
		||||
        Ps2 {
 | 
			
		||||
            data: Pio::new(0x60),
 | 
			
		||||
            status: ReadOnly::new(Pio::new(0x64)),
 | 
			
		||||
            command: WriteOnly::new(Pio::new(0x64)),
 | 
			
		||||
            key: [0; 3],
 | 
			
		||||
            key_i: 0,
 | 
			
		||||
            mouse: [0; 4],
 | 
			
		||||
            mouse_i: 0,
 | 
			
		||||
            mouse_extra: false,
 | 
			
		||||
            mouse_x: 0,
 | 
			
		||||
            mouse_y: 0
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -194,7 +278,7 @@ impl Ps2 {
 | 
			
		|||
        self.read()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn init(&mut self) {
 | 
			
		||||
    fn init(&mut self) -> (Option<Ps2Keyboard>, Option<Ps2Mouse>) {
 | 
			
		||||
        // Disable devices
 | 
			
		||||
        self.command(Command::DisableFirst);
 | 
			
		||||
        self.command(Command::DisableSecond);
 | 
			
		||||
| 
						 | 
				
			
			@ -242,7 +326,7 @@ impl Ps2 {
 | 
			
		|||
        assert_eq!(self.mouse_command_data(MouseCommandData::SetSampleRate, 80), 0xFA);
 | 
			
		||||
        assert_eq!(self.mouse_command(MouseCommand::GetDeviceId), 0xFA);
 | 
			
		||||
        let mouse_id = self.read();
 | 
			
		||||
        self.mouse_extra = mouse_id == 3;
 | 
			
		||||
        let mouse_extra = mouse_id == 3;
 | 
			
		||||
 | 
			
		||||
        // Enable extra buttons, TODO
 | 
			
		||||
        /*
 | 
			
		||||
| 
						 | 
				
			
			@ -272,57 +356,9 @@ impl Ps2 {
 | 
			
		|||
            config.insert(SECOND_INTERRUPT);
 | 
			
		||||
            self.set_config(config);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn on_keyboard(&mut self) {
 | 
			
		||||
        let scancode = self.data.read();
 | 
			
		||||
        self.key[self.key_i] = scancode;
 | 
			
		||||
        self.key_i += 1;
 | 
			
		||||
        if self.key_i >= self.key.len() || scancode < 0xE0 {
 | 
			
		||||
            //println!("KEY: {:X} {:X} {:X}", self.key[0], self.key[1], self.key[2]);
 | 
			
		||||
        self.flush_read();
 | 
			
		||||
 | 
			
		||||
            self.key = [0; 3];
 | 
			
		||||
            self.key_i = 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn on_mouse(&mut self) {
 | 
			
		||||
        self.mouse[self.mouse_i] = self.data.read();
 | 
			
		||||
        self.mouse_i += 1;
 | 
			
		||||
        if self.mouse_i >= self.mouse.len() || (!self.mouse_extra && self.mouse_i >= 3) {
 | 
			
		||||
            let flags = MousePacketFlags::from_bits_truncate(self.mouse[0]);
 | 
			
		||||
 | 
			
		||||
            if flags.contains(ALWAYS_ON) && ! flags.contains(X_OVERFLOW) && ! flags.contains(Y_OVERFLOW) {
 | 
			
		||||
                let mut dx = self.mouse[1] as isize;
 | 
			
		||||
                if flags.contains(X_SIGN) {
 | 
			
		||||
                    dx -= 0x100;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                let mut dy = self.mouse[2] as isize;
 | 
			
		||||
                if flags.contains(Y_SIGN) {
 | 
			
		||||
                    dy -= 0x100;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                let _extra = if self.mouse_extra {
 | 
			
		||||
                    self.mouse[3]
 | 
			
		||||
                } else {
 | 
			
		||||
                    0
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                //print!("MOUSE {:?}, {}, {}, {}\n", flags, dx, dy, extra);
 | 
			
		||||
 | 
			
		||||
                if let Some(ref mut display) = *super::display::DISPLAY.lock() {
 | 
			
		||||
                    self.mouse_x = cmp::max(0, cmp::min(display.width as isize - 1, self.mouse_x as isize + dx)) as usize;
 | 
			
		||||
                    self.mouse_y = cmp::max(0, cmp::min(display.height as isize - 1, self.mouse_y as isize - dy)) as usize;
 | 
			
		||||
                    let offset = self.mouse_y * display.width + self.mouse_x;
 | 
			
		||||
                    display.onscreen[offset as usize] = 0xFF0000;
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                println!("BAD MOUSE {:?}", self.mouse);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            self.mouse = [0; 4];
 | 
			
		||||
            self.mouse_i = 0;
 | 
			
		||||
        }
 | 
			
		||||
        (Some(Ps2Keyboard::new()), Some(Ps2Mouse::new(mouse_extra)))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
use x86::io;
 | 
			
		||||
 | 
			
		||||
use device::ps2::PS2;
 | 
			
		||||
use device::ps2::{PS2_KEYBOARD, PS2_MOUSE};
 | 
			
		||||
use device::serial::{COM1, COM2};
 | 
			
		||||
 | 
			
		||||
#[inline(always)]
 | 
			
		||||
| 
						 | 
				
			
			@ -19,76 +19,80 @@ interrupt!(pit, {
 | 
			
		|||
});
 | 
			
		||||
 | 
			
		||||
interrupt!(keyboard, {
 | 
			
		||||
    PS2.lock().on_keyboard();
 | 
			
		||||
    master_ack();
 | 
			
		||||
    if let Some(ref mut keyboard) = *PS2_KEYBOARD.lock(){
 | 
			
		||||
        keyboard.on_irq();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
interrupt!(cascade, {
 | 
			
		||||
    print!("CASCADE\n");
 | 
			
		||||
    master_ack();
 | 
			
		||||
    print!("CASCADE\n");
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
interrupt!(com2, {
 | 
			
		||||
    COM2.lock().on_receive();
 | 
			
		||||
    master_ack();
 | 
			
		||||
    COM2.lock().on_receive();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
interrupt!(com1, {
 | 
			
		||||
    COM1.lock().on_receive();
 | 
			
		||||
    master_ack();
 | 
			
		||||
    COM1.lock().on_receive();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
interrupt!(lpt2, {
 | 
			
		||||
    print!("LPT2\n");
 | 
			
		||||
    master_ack();
 | 
			
		||||
    print!("LPT2\n");
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
interrupt!(floppy, {
 | 
			
		||||
    print!("FLOPPY\n");
 | 
			
		||||
    master_ack();
 | 
			
		||||
    print!("FLOPPY\n");
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
interrupt!(lpt1, {
 | 
			
		||||
    print!("LPT1\n");
 | 
			
		||||
    master_ack();
 | 
			
		||||
    print!("LPT1\n");
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
interrupt!(rtc, {
 | 
			
		||||
    print!("RTC\n");
 | 
			
		||||
    slave_ack();
 | 
			
		||||
    print!("RTC\n");
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
interrupt!(pci1, {
 | 
			
		||||
    print!("PCI1\n");
 | 
			
		||||
    slave_ack();
 | 
			
		||||
    print!("PCI1\n");
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
interrupt!(pci2, {
 | 
			
		||||
    print!("PCI2\n");
 | 
			
		||||
    slave_ack();
 | 
			
		||||
    print!("PCI2\n");
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
interrupt!(pci3, {
 | 
			
		||||
    print!("PCI3\n");
 | 
			
		||||
    slave_ack();
 | 
			
		||||
    print!("PCI3\n");
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
interrupt!(mouse, {
 | 
			
		||||
    PS2.lock().on_mouse();
 | 
			
		||||
    slave_ack();
 | 
			
		||||
    if let Some(ref mut mouse) = *PS2_MOUSE.lock() {
 | 
			
		||||
        mouse.on_irq();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
interrupt!(fpu, {
 | 
			
		||||
    print!("FPU\n");
 | 
			
		||||
    slave_ack();
 | 
			
		||||
    print!("FPU\n");
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
interrupt!(ata1, {
 | 
			
		||||
    print!("ATA1\n");
 | 
			
		||||
    slave_ack();
 | 
			
		||||
    print!("ATA1\n");
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
interrupt!(ata2, {
 | 
			
		||||
    print!("ATA2\n");
 | 
			
		||||
    slave_ack();
 | 
			
		||||
    print!("ATA2\n");
 | 
			
		||||
});
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,6 +21,8 @@ pub unsafe fn enable() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
/// Set interrupts and halt
 | 
			
		||||
/// This will atomically wait for the next interrupt
 | 
			
		||||
/// Performing enable followed by halt is not guaranteed to be atomic, use this instead!
 | 
			
		||||
#[inline(always)]
 | 
			
		||||
pub unsafe fn enable_and_halt() {
 | 
			
		||||
    asm!("sti
 | 
			
		||||
| 
						 | 
				
			
			@ -28,6 +30,16 @@ pub unsafe fn enable_and_halt() {
 | 
			
		|||
        : : : : "intel", "volatile");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Set interrupts and nop
 | 
			
		||||
/// This will enable interrupts and allow the IF flag to be processed
 | 
			
		||||
/// Simply enabling interrupts does not gurantee that they will trigger, use this instead!
 | 
			
		||||
#[inline(always)]
 | 
			
		||||
pub unsafe fn enable_and_nop() {
 | 
			
		||||
    asm!("sti
 | 
			
		||||
        nop"
 | 
			
		||||
        : : : : "intel", "volatile");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Halt instruction
 | 
			
		||||
#[inline(always)]
 | 
			
		||||
pub unsafe fn halt() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -128,14 +128,14 @@ pub unsafe fn init(stack_start: usize, stack_end: usize) -> ActivePageTable {
 | 
			
		|||
                {
 | 
			
		||||
                    let frame = Frame::containing_address(PhysicalAddress::new(page.start_address().get()));
 | 
			
		||||
                    active_table.identity_map(frame, PRESENT | NO_EXECUTE);
 | 
			
		||||
                    tlb::flush_all();
 | 
			
		||||
                    active_table.flush(page);
 | 
			
		||||
                    ::externs::memcpy(temporary_page.start_address().get() as *mut u8, page.start_address().get() as *const u8, 4096);
 | 
			
		||||
                    active_table.unmap(page);
 | 
			
		||||
                }
 | 
			
		||||
                // Copy temporary page to child
 | 
			
		||||
                {
 | 
			
		||||
                    active_table.map(page, PRESENT | NO_EXECUTE | WRITABLE);
 | 
			
		||||
                    tlb::flush_all();
 | 
			
		||||
                    active_table.flush(page);
 | 
			
		||||
                    ::externs::memcpy(page.start_address().get() as *mut u8, temporary_page.start_address().get() as *const u8, 4096);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -153,7 +153,7 @@ pub unsafe fn init(stack_start: usize, stack_end: usize) -> ActivePageTable {
 | 
			
		|||
            let end_page = Page::containing_address(VirtualAddress::new(end - 1));
 | 
			
		||||
            for page in Page::range_inclusive(start_page, end_page) {
 | 
			
		||||
                active_table.map(page, PRESENT | NO_EXECUTE | WRITABLE);
 | 
			
		||||
                tlb::flush_all();
 | 
			
		||||
                active_table.flush(page);
 | 
			
		||||
                ::externs::memset(page.start_address().get() as *mut u8, 0, 4096);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -161,6 +161,8 @@ pub unsafe fn init(stack_start: usize, stack_end: usize) -> ActivePageTable {
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    active_table.flush_all();
 | 
			
		||||
 | 
			
		||||
    active_table
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -203,12 +205,19 @@ impl ActivePageTable {
 | 
			
		|||
        old_table
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn flush(&mut self, page: Page) {
 | 
			
		||||
        unsafe { tlb::flush(page.start_address().get()); }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn flush_all(&mut self) {
 | 
			
		||||
        unsafe { tlb::flush_all(); }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn with<F>(&mut self, table: &mut InactivePageTable, temporary_page: &mut temporary_page::TemporaryPage, f: F)
 | 
			
		||||
        where F: FnOnce(&mut Mapper)
 | 
			
		||||
    {
 | 
			
		||||
        use x86::{controlregs, tlb};
 | 
			
		||||
        let flush_tlb = || unsafe { tlb::flush_all() };
 | 
			
		||||
 | 
			
		||||
        use x86::controlregs;
 | 
			
		||||
        
 | 
			
		||||
        {
 | 
			
		||||
            let backup = Frame::containing_address(PhysicalAddress::new(unsafe { controlregs::cr3() } as usize));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -217,14 +226,14 @@ impl ActivePageTable {
 | 
			
		|||
 | 
			
		||||
            // overwrite recursive mapping
 | 
			
		||||
            self.p4_mut()[511].set(table.p4_frame.clone(), PRESENT | WRITABLE | NO_EXECUTE);
 | 
			
		||||
            flush_tlb();
 | 
			
		||||
            self.flush_all();
 | 
			
		||||
 | 
			
		||||
            // execute f in the new context
 | 
			
		||||
            f(self);
 | 
			
		||||
 | 
			
		||||
            // restore recursive mapping to original p4 table
 | 
			
		||||
            p4_table[511].set(backup, PRESENT | WRITABLE | NO_EXECUTE);
 | 
			
		||||
            flush_tlb();
 | 
			
		||||
            self.flush_all();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        temporary_page.unmap(self);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,7 +13,6 @@ use goblin::elf64::{header, program_header};
 | 
			
		|||
use arch::externs::{memcpy, memset};
 | 
			
		||||
use arch::paging::{entry, ActivePageTable, Page, VirtualAddress};
 | 
			
		||||
use arch::start::usermode;
 | 
			
		||||
use arch::x86::tlb;
 | 
			
		||||
 | 
			
		||||
/// An ELF executable
 | 
			
		||||
pub struct Elf<'a> {
 | 
			
		||||
| 
						 | 
				
			
			@ -63,11 +62,9 @@ impl<'a> Elf<'a> {
 | 
			
		|||
                for page in Page::range_inclusive(start_page, end_page) {
 | 
			
		||||
                    active_table.map(page, entry::NO_EXECUTE | entry::WRITABLE);
 | 
			
		||||
                }
 | 
			
		||||
                active_table.flush_all();
 | 
			
		||||
 | 
			
		||||
                unsafe {
 | 
			
		||||
                    // Update the page table
 | 
			
		||||
                    tlb::flush_all();
 | 
			
		||||
 | 
			
		||||
                    // Copy file data
 | 
			
		||||
                    memcpy(segment.p_vaddr as *mut u8,
 | 
			
		||||
                            (self.data.as_ptr() as usize + segment.p_offset as usize) as *const u8,
 | 
			
		||||
| 
						 | 
				
			
			@ -94,26 +91,20 @@ impl<'a> Elf<'a> {
 | 
			
		|||
                for page in Page::range_inclusive(start_page, end_page) {
 | 
			
		||||
                    active_table.remap(page, flags);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                unsafe {
 | 
			
		||||
                    // Update the page table
 | 
			
		||||
                    tlb::flush_all();
 | 
			
		||||
                }
 | 
			
		||||
                active_table.flush_all();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Map stack
 | 
			
		||||
        let start_page = Page::containing_address(VirtualAddress::new(0x80000000));
 | 
			
		||||
        let end_page = Page::containing_address(VirtualAddress::new(0x80000000 + 64*1024 - 1));
 | 
			
		||||
 | 
			
		||||
        for page in Page::range_inclusive(start_page, end_page) {
 | 
			
		||||
            active_table.map(page, entry::NO_EXECUTE | entry::WRITABLE | entry::USER_ACCESSIBLE);
 | 
			
		||||
        }
 | 
			
		||||
        active_table.flush_all();
 | 
			
		||||
 | 
			
		||||
        unsafe {
 | 
			
		||||
            // Map stack
 | 
			
		||||
            let start_page = Page::containing_address(VirtualAddress::new(0x80000000));
 | 
			
		||||
            let end_page = Page::containing_address(VirtualAddress::new(0x80000000 + 64*1024 - 1));
 | 
			
		||||
 | 
			
		||||
            for page in Page::range_inclusive(start_page, end_page) {
 | 
			
		||||
                active_table.map(page, entry::NO_EXECUTE | entry::WRITABLE | entry::USER_ACCESSIBLE);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Update the page table
 | 
			
		||||
            tlb::flush_all();
 | 
			
		||||
 | 
			
		||||
            // Clear stack
 | 
			
		||||
            memset(0x80000000 as *mut u8, 0, 64 * 1024);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,6 +34,7 @@ pub fn brk(address: usize) -> Result<usize> {
 | 
			
		|||
            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);
 | 
			
		||||
                active_table.flush(page);
 | 
			
		||||
            } else {
 | 
			
		||||
                //println!("Found - skipping");
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -49,6 +50,7 @@ pub fn brk(address: usize) -> Result<usize> {
 | 
			
		|||
            if active_table.translate_page(page).is_some() {
 | 
			
		||||
                //println!("Found - unmapping");
 | 
			
		||||
                active_table.unmap(page);
 | 
			
		||||
                active_table.flush(page);
 | 
			
		||||
            } else {
 | 
			
		||||
                //println!("Not found - skipping");
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								libstd
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								libstd
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1 +1 @@
 | 
			
		|||
Subproject commit 7ead704d48411cc66ce71ffe4f1fbe86a6a4cbe4
 | 
			
		||||
Subproject commit 7b20e739903a4877a10b64b875a3fd7a06cdcd16
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue