From 377adb53d86b46d829b3d534a012434be77b5372 Mon Sep 17 00:00:00 2001
From: Jeremy Soller <jackpot51@gmail.com>
Date: Fri, 11 Mar 2016 16:32:00 -0700
Subject: [PATCH] Match x86 paging with x86_64

---
 kernel/arch/x86_64/paging.rs |  79 +++++++++++++++++++-------------
 kernel/disk/ide.rs           | 105 +++++++++++++++++--------------------------
 x86_64-unknown-redox.json    |   2 +-
 3 files changed, 90 insertions(+), 96 deletions(-)

diff --git a/kernel/arch/x86_64/paging.rs b/kernel/arch/x86_64/paging.rs
index 51066ee..52fd368 100644
--- a/kernel/arch/x86_64/paging.rs
+++ b/kernel/arch/x86_64/paging.rs
@@ -1,5 +1,23 @@
 use core::ptr;
 
+//Page flags
+pub const PF_PRESENT: usize = 1;
+pub const PF_WRITE: usize = 1 << 1;
+pub const PF_USER: usize = 1 << 2;
+pub const PF_WRITE_THROUGH: usize = 1 << 3;
+pub const PF_CACHE_DISABLE: usize = 1 << 4;
+pub const PF_ACCESSED: usize = 1 << 5;
+pub const PF_DIRTY: usize = 1 << 6;
+pub const PF_SIZE: usize = 1 << 7;
+pub const PF_GLOBAL: usize = 1 << 8;
+//Extra flags (Redox specific)
+pub const PF_ALLOC: usize = 1 << 9;
+pub const PF_EXEC: usize = 1 << 10;
+pub const PF_STACK: usize = 1 << 11;
+
+pub const PF_ALL: usize =  0xFFF;
+pub const PF_NONE: usize = 0xFFFFFFFFFFFFF000;
+
 // PAGE_LEVEL_4:
 // 512 qwords pointing to page directory pointers
 // PAGE_DIR_PTRS:
@@ -32,32 +50,32 @@ impl Page {
     pub unsafe fn init() {
         for l4_i in 0..PAGE_TABLE_SIZE {
             if l4_i == 0 {
-                ptr::write((PAGE_LEVEL_4 + l4_i * PAGE_ENTRY_SIZE) as *mut u64,
-                           (PAGE_DIR_PTRS + l4_i * PAGE_TABLE_SIZE * PAGE_ENTRY_SIZE) as u64 |
-                           1 << 2 | 0b11 << 1 | 1); //Allow userspace, read/write, present
+                ptr::write((PAGE_LEVEL_4 + l4_i * PAGE_ENTRY_SIZE) as *mut usize,
+                           (PAGE_DIR_PTRS + l4_i * PAGE_TABLE_SIZE * PAGE_ENTRY_SIZE) |
+                           PF_USER | PF_WRITE | PF_PRESENT); //Allow userspace, read/write, present
             } else {
-                ptr::write((PAGE_LEVEL_4 + l4_i * PAGE_ENTRY_SIZE) as *mut u64, 0);
+                ptr::write((PAGE_LEVEL_4 + l4_i * PAGE_ENTRY_SIZE) as *mut usize, 0);
             }
         }
 
         for dp_i in 0..PAGE_TABLE_SIZE {
             if dp_i < 4 {
-                ptr::write((PAGE_DIR_PTRS + dp_i * PAGE_ENTRY_SIZE) as *mut u64,
-                           (PAGE_DIRECTORIES + dp_i * PAGE_TABLE_SIZE * PAGE_ENTRY_SIZE) as u64 |
-                           1 << 2 |
-                           0b11 << 1 | 1); //Allow userspace, read/write, present
+                ptr::write((PAGE_DIR_PTRS + dp_i * PAGE_ENTRY_SIZE) as *mut usize,
+                           (PAGE_DIRECTORIES + dp_i * PAGE_TABLE_SIZE * PAGE_ENTRY_SIZE) |
+                           PF_USER | PF_WRITE | PF_PRESENT); //Allow userspace, read/write, present
             } else {
-                ptr::write((PAGE_DIR_PTRS + dp_i * PAGE_ENTRY_SIZE) as *mut u64, 0);
+                ptr::write((PAGE_DIR_PTRS + dp_i * PAGE_ENTRY_SIZE) as *mut usize, 0);
             }
         }
 
         for table_i in 0..4 * PAGE_TABLE_SIZE {
-            ptr::write((PAGE_DIRECTORIES + table_i * PAGE_ENTRY_SIZE) as *mut u64,
-                       (PAGE_TABLES + table_i * PAGE_TABLE_SIZE * PAGE_ENTRY_SIZE) as u64 |
-                       1 << 2 | 0b11 << 1 | 1); //Allow userspace, read/write, present
+            ptr::write((PAGE_DIRECTORIES + table_i * PAGE_ENTRY_SIZE) as *mut usize,
+                       (PAGE_TABLES + table_i * PAGE_TABLE_SIZE * PAGE_ENTRY_SIZE) |
+                       PF_USER | PF_WRITE | PF_PRESENT); //Allow userspace, read/write, present
 
             for entry_i in 0..PAGE_TABLE_SIZE {
-                Page::new((table_i * PAGE_TABLE_SIZE + entry_i) * PAGE_SIZE).map_identity();
+                let addr = (table_i * PAGE_TABLE_SIZE + entry_i) * PAGE_SIZE;
+                Page::new(addr).map_kernel_write(addr);
             }
         }
 
@@ -66,7 +84,7 @@ impl Page {
             or $0, $1
             mov cr0, $0"
             :
-            : "r"(PAGE_LEVEL_4), "r"(0x80000000 as usize)
+            : "r"(PAGE_LEVEL_4), "r"((1 << 31 | 1 << 16) as usize)
             : "memory"
             : "intel", "volatile");
     }
@@ -96,44 +114,45 @@ impl Page {
 
     /// Get the current physical address
     pub fn phys_addr(&self) -> usize {
-        unsafe { (ptr::read(self.entry_address() as *mut u64) & 0xFFFFFFFFFFFFF000) as usize }
+        unsafe { (ptr::read(self.entry_address() as *mut usize) & PF_NONE) as usize }
     }
 
     /// Get the current virtual address
     pub fn virt_addr(&self) -> usize {
-        self.virtual_address & 0xFFFFFFFFFFFFF000
+        self.virtual_address & PF_NONE
     }
 
     /// Map the memory page to a given physical memory address
-    pub unsafe fn map(&mut self, physical_address: usize) {
-        ptr::write(self.entry_address() as *mut u64,
-                   (physical_address as u64 & 0xFFFFFFFFFFFFF000) | 1); //present
+    pub unsafe fn map_kernel_read(&mut self, physical_address: usize) {
+        ptr::write(self.entry_address() as *mut usize,
+                   (physical_address & PF_NONE) | PF_PRESENT); //present
+        self.flush();
+    }
+
+    /// Map the memory page to a given physical memory address and allow userspace read access
+    pub unsafe fn map_kernel_write(&mut self, physical_address: usize) {
+        ptr::write(self.entry_address() as *mut usize,
+                   (physical_address & PF_NONE) | PF_WRITE | PF_PRESENT); //Allow write, present
         self.flush();
     }
 
     /// Map the memory page to a given physical memory address and allow userspace read access
     pub unsafe fn map_user_read(&mut self, physical_address: usize) {
-        ptr::write(self.entry_address() as *mut u64,
-                   (physical_address as u64 & 0xFFFFFFFFFFFFF000) | 1 << 2 | 1); //Allow userspace, present
+        ptr::write(self.entry_address() as *mut usize,
+                   (physical_address & PF_NONE) | PF_USER | PF_PRESENT); //Allow userspace, present
         self.flush();
     }
 
     /// Map the memory page to a given physical memory address and allow userspace read/write access
     pub unsafe fn map_user_write(&mut self, physical_address: usize) {
-        ptr::write(self.entry_address() as *mut u64,
-                   (physical_address as u64 & 0xFFFFFFFFFFFFF000) | 1 << 2 | 1 << 1 | 1); //Allow userspace, read/write, present
+        ptr::write(self.entry_address() as *mut usize,
+                   (physical_address & PF_NONE) | PF_USER | PF_WRITE | PF_PRESENT); //Allow userspace, read/write, present
         self.flush();
     }
 
-    /// Map to the virtual address
-    pub unsafe fn map_identity(&mut self) {
-        let physical_address = self.virtual_address;
-        self.map(physical_address);
-    }
-
     /// Unmap the memory page
     pub unsafe fn unmap(&mut self) {
-        ptr::write(self.entry_address() as *mut u64, 0);
+        ptr::write(self.entry_address() as *mut usize, 0);
         self.flush();
     }
 }
diff --git a/kernel/disk/ide.rs b/kernel/disk/ide.rs
index f3959fc..388796b 100644
--- a/kernel/disk/ide.rs
+++ b/kernel/disk/ide.rs
@@ -231,6 +231,35 @@ impl IdeDisk {
         0
     }
 
+    pub fn ata(&mut self, cmd: u8, block: u64, len: u16) {
+        while self.cmdsts.readf(ATA_SR_BSY) {}
+
+        self.devsel.write(if self.master {
+            0x40
+        } else {
+            0x40 | 0x10
+        });
+
+        self.ctrl.read();
+        self.ctrl.read();
+        self.ctrl.read();
+        self.ctrl.read();
+
+        while self.cmdsts.readf(ATA_SR_BSY) {}
+
+        self.seccount.write((len >> 8) as u8);
+        self.sector0.write((block >> 24) as u8);
+        self.sector1.write((block >> 32) as u8);
+        self.sector2.write((block >> 40) as u8);
+
+        self.seccount.write(len as u8);
+        self.sector0.write(block as u8);
+        self.sector1.write((block >> 8) as u8);
+        self.sector2.write((block >> 16) as u8);
+
+        self.cmdsts.write(cmd);
+    }
+
     /// Identify
     pub unsafe fn identify(&mut self) -> bool {
         if self.cmdsts.read() == 0xFF {
@@ -239,20 +268,7 @@ impl IdeDisk {
             return false;
         }
 
-        while self.cmdsts.readf(ATA_SR_BSY) {}
-
-        if self.master {
-            self.devsel.write(0xA0);
-        } else {
-            self.devsel.write(0xB0);
-        }
-
-        self.seccount.write(0);
-        self.sector0.write(0);
-        self.sector1.write(0);
-        self.sector2.write(0);
-
-        self.cmdsts.write(ATA_CMD_IDENTIFY);
+        self.ata(ATA_CMD_IDENTIFY, 0, 0);
 
         let status = self.cmdsts.read();
         debug!(" Status: {:X}", status);
@@ -332,29 +348,11 @@ impl IdeDisk {
                             write: bool)
                             -> Result<usize> {
         if buf > 0 {
-            while self.cmdsts.readf(ATA_SR_BSY) {}
-
-            if self.master {
-                self.devsel.write(0x40);
-            } else {
-                self.devsel.write(0x50);
-            }
-
-            self.seccount.write(((sectors >> 8) & 0xFF) as u8);
-            self.sector0.write(((block >> 24) & 0xFF) as u8);
-            self.sector1.write(((block >> 32) & 0xFF) as u8);
-            self.sector2.write(((block >> 40) & 0xFF) as u8);
-
-            self.seccount.write(((sectors >> 0) & 0xFF) as u8);
-            self.sector0.write(((block >> 0) & 0xFF) as u8);
-            self.sector1.write(((block >> 8) & 0xFF) as u8);
-            self.sector2.write(((block >> 16) & 0xFF) as u8);
-
-            if write {
-                self.cmdsts.write(ATA_CMD_WRITE_PIO_EXT);
+            self.ata(if write {
+                ATA_CMD_WRITE_PIO_EXT
             } else {
-                self.cmdsts.write(ATA_CMD_READ_PIO_EXT);
-            }
+                ATA_CMD_READ_PIO_EXT
+            }, block, sectors);
 
             for sector in 0..sectors as usize {
                 let err = self.ide_poll(true);
@@ -385,7 +383,7 @@ impl IdeDisk {
     }
 
     fn ata_pio(&mut self, block: u64, sectors: usize, buf: usize, write: bool) -> Result<usize> {
-        // debugln!("IDE PIO BLOCK: {:X} SECTORS: {} BUF: {:X} WRITE: {}", block, sectors, buf, write);
+        // debugln!("IDE PIO BLOCK: {} SECTORS: {} BUF: {:X} WRITE: {}", block, sectors, buf, write);
 
         if buf > 0 && sectors > 0 {
             let mut sector: usize = 0;
@@ -468,29 +466,12 @@ impl IdeDisk {
 
             self.buscmd.writef(CMD_DIR, !write);
 
-            while self.cmdsts.readf(ATA_SR_BSY) {}
 
-            if self.master {
-                self.devsel.write(0x40);
+            self.ata(if write {
+                ATA_CMD_WRITE_DMA_EXT
             } else {
-                self.devsel.write(0x50);
-            }
-
-            self.seccount.write(((sectors >> 8) & 0xFF) as u8);
-            self.sector0.write(((block >> 24) & 0xFF) as u8);
-            self.sector1.write(((block >> 32) & 0xFF) as u8);
-            self.sector2.write(((block >> 40) & 0xFF) as u8);
-
-            self.seccount.write(((sectors >> 0) & 0xFF) as u8);
-            self.sector0.write(((block >> 0) & 0xFF) as u8);
-            self.sector1.write(((block >> 8) & 0xFF) as u8);
-            self.sector2.write(((block >> 16) & 0xFF) as u8);
-
-            if write {
-                self.cmdsts.write(ATA_CMD_WRITE_DMA_EXT);
-            } else {
-                self.cmdsts.write(ATA_CMD_READ_DMA_EXT);
-            }
+                ATA_CMD_READ_DMA_EXT
+            }, block, sectors);
 
             self.buscmd.writef(CMD_ACT, true);
 
@@ -516,7 +497,7 @@ impl IdeDisk {
     }
 
     fn ata_dma(&mut self, block: u64, sectors: usize, buf: usize, write: bool) -> Result<usize> {
-        // debugln!("IDE DMA BLOCK: {:X} SECTORS: {} BUF: {:X} WRITE: {}", block, sectors, buf, write);
+        // debugln!("IDE DMA BLOCK: {} SECTORS: {} BUF: {:X} WRITE: {}", block, sectors, buf, write);
 
         if buf > 0 && sectors > 0 {
             let mut sector: usize = 0;
@@ -562,16 +543,10 @@ impl Disk for IdeDisk {
     }
 
     fn read(&mut self, block: u64, buffer: &mut [u8]) -> Result<usize> {
-        if buffer.as_ptr() as usize % 512 > 0 {
-            panic!("IdeDisk::read not aligned");
-        }
         self.ata_dma(block, buffer.len() / 512, buffer.as_ptr() as usize, false)
     }
 
     fn write(&mut self, block: u64, buffer: &[u8]) -> Result<usize> {
-        if buffer.as_ptr() as usize % 512 > 0 {
-            panic!("IdeDisk::write not aligned");
-        }
         self.ata_dma(block, buffer.len() / 512, buffer.as_ptr() as usize, true)
     }
 }
diff --git a/x86_64-unknown-redox.json b/x86_64-unknown-redox.json
index 6b9445c..58b6a56 100644
--- a/x86_64-unknown-redox.json
+++ b/x86_64-unknown-redox.json
@@ -7,7 +7,7 @@
     "env": "",
     "vendor": "unknown",
     "pre-link-args": ["-m64", "-nostdlib", "-static", "build/x86_64-unknown-redox/debug/crt0.o"],
-    "features": "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2",
+    "features": "-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2",
     "dynamic-linking": false,
     "executables": true,
     "relocation-model": "static",
