1
0
mirror of https://github.com/rcore-os/rCore.git synced 2025-01-18 17:07:04 +04:00

Add IDE back for mips, remove mipssim

This commit is contained in:
Jiajie Chen 2020-07-07 08:25:30 +08:00
parent 100db70184
commit a16a9e238b
15 changed files with 273 additions and 346 deletions

2
kernel/Cargo.lock generated
View File

@ -709,7 +709,7 @@ checksum = "3a385d94f3f62e60445a0adb9ff8d9621faa272234530d4c0f848ec98f88e316"
[[package]]
name = "trapframe"
version = "0.4.3"
source = "git+https://github.com/rcore-os/trapframe-rs?rev=063a844#063a844654aaf37af2ef2afac305b4b025407441"
source = "git+https://github.com/rcore-os/trapframe-rs?rev=e58d975#e58d9755f181de24431b5ff9437f396ac71e8429"
dependencies = [
"raw-cpuid",
"x86_64",

View File

@ -27,8 +27,7 @@ nographic = []
consolegraphic = []
board_raspi3 = ["bcm2837"]
# for qemu machine
board_malta = ["link_user"]
board_mipssim = ["link_user"]
board_malta = []
# for x86 PC
board_pc = ["link_user"]
# Hard link user program
@ -70,7 +69,7 @@ rcore-fs-devfs = { git = "https://github.com/rcore-os/rcore-fs", rev = "517af47"
rlibc = "1.0"
smoltcp = { git = "https://github.com/rcore-os/smoltcp", rev = "5bd87c7c", default-features = false, features = ["alloc", "log", "ethernet", "proto-ipv4", "proto-igmp", "socket-icmp", "socket-udp", "socket-tcp", "socket-raw"] }
spin = "0.5"
trapframe = { git = "https://github.com/rcore-os/trapframe-rs", rev = "063a844" }
trapframe = { git = "https://github.com/rcore-os/trapframe-rs", rev = "e58d975" }
virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers", rev = "dfa70e14" }
volatile = "0.2"
woke = "0.0.2"

View File

@ -65,11 +65,6 @@ ifeq ($(ARCH), mipsel)
DTB := src/arch/$(ARCH)/board/$(BOARD)/device.dtb
endif
# mipssim does not support SMP
ifeq ($(BOARD), mipssim)
SMP := 1
endif
### qemu options ###
qemu_opts := \
-smp cores=$(SMP)
@ -157,15 +152,10 @@ else ifeq ($(ARCH), mipsel)
ifeq ($(BOARD), malta)
qemu_opts += \
-machine $(BOARD) -device VGA \
-hda $(USER_QCOW2) \
-serial null -serial null -serial mon:stdio \
-kernel $(kernel_img)
endif
ifeq ($(BOARD), mipssim)
qemu_opts += \
-machine $(BOARD) \
-serial mon:stdio \
-kernel $(kernel_img)
endif
endif
ifdef D
@ -302,7 +292,7 @@ ifeq ($(ARCH), $(filter $(ARCH), riscv32 riscv64))
$(sysroot)/lib/rustlib/src/rust/src/libcore/sync/atomic.rs \
src/arch/riscv/atomic.patch
else ifeq ($(ARCH), mipsel)
@for file in context entry trap ; do \
@for file in entry ; do \
$(hostcc) -Dboard_$(BOARD) -E src/arch/$(ARCH)/boot/$${file}.S -o src/arch/$(ARCH)/boot/$${file}.gen.s ; \
done
$(hostcc) -Dboard_$(BOARD) -E src/arch/$(ARCH)/boot/linker.ld.S -o src/arch/$(ARCH)/boot/linker.ld

View File

@ -1,3 +1,3 @@
/// board specific constants
pub const MEMORY_END: usize = 0x8400_0000;
pub const MEMORY_END: usize = 0x8800_0000;
pub const KERNEL_HEAP_SIZE: usize = 0x0200_0000;

View File

@ -1,3 +1,4 @@
use crate::drivers::block::ide;
use crate::drivers::bus::pci;
use crate::drivers::gpu::fb::{self, FramebufferInfo};
use mips::registers::cp0;
@ -42,4 +43,5 @@ pub fn init_driver() {
screen_size: 800 * 600,
};
fb::init(fb_info);
ide::init();
}

View File

@ -1,3 +0,0 @@
/// board specific constants
pub const MEMORY_END: usize = 0x8800_0000;
pub const KERNEL_HEAP_SIZE: usize = 0x00a0_0000;

View File

@ -1,36 +0,0 @@
/dts-v1/;
/ {
model = "qemu mipssim";
compatible = "qemu,mipssim";
#address-cells = <1>;
#size-cells = <1>;
chosen {
stdio = &uart0;
};
aliases { };
cpu_intc: interrupt-controller {
compatible = "mti,cpu-interrupt-controller";
interrupt-controller;
#interrupt-cells = <1>;
};
main_memory: memory@0 {
device_type = "memory";
reg = <0x00000000 0x10000000>;
};
uart0: serial@bfd003f8 {
compatible = "ns16550a";
reg = <0xbfd003f8 0x8>;
clock-frequency = <1843200>;
/* attached to the MIPS CPU INT2 pin, ie interrupt 4 */
interrupt-parent = <&cpu_intc>;
interrupts = <4>;
};
};

View File

@ -1,18 +0,0 @@
pub mod consts;
#[path = "../../../../drivers/serial/uart16550.rs"]
pub mod serial;
/// Device tree bytes
pub static DTB: &'static [u8] = include_bytes!("device.dtb");
/// Initialize serial port first
pub fn init_serial_early() {
serial::init(0xbfd003f8);
println!("Hello QEMU MIPSSIM!");
}
/// Initialize other board drivers
pub fn init_driver() {
// TODO: add possibly more drivers
// timer::init();
}

View File

@ -1,67 +0,0 @@
#include "regdef.h"
.set noat
.set noreorder
.section .text.context
.globl switch_context
.extern _root_page_table_ptr
.extern _cur_kstack_ptr
.extern _cur_tls
switch_context:
// save from's registers
addi sp, sp, (-4*16)
sw sp, 0(a0)
sw ra, 0(sp)
sw s0, 4*4(sp)
sw s1, 5*4(sp)
sw s2, 6*4(sp)
sw s3, 7*4(sp)
sw s4, 8*4(sp)
sw s5, 9*4(sp)
sw s6, 10*4(sp)
sw s7, 11*4(sp)
sw s8, 12*4(sp)
sw gp, 13*4(sp)
// sw ra, 12*4(sp)
// sw sp, 13*4(sp)
// save page table address
la s0, _root_page_table_ptr
lw s1, 0(s0)
sw s1, 4(sp)
// save TLS
la s2, _cur_tls
lw s1, 0(s2)
sw s1, 2*4(sp)
// restore to's registers
lw sp, 0(a1)
// restore page table address
lw s1, 4(sp)
sw s1, 0(s0)
// restore TLS
lw s1, 2*4(sp)
sw s1, 0(s2)
mtc0 s1, $4, 2 // cp0.user_local
lw ra, 0(sp)
lw s0, 4*4(sp)
lw s1, 5*4(sp)
lw s2, 6*4(sp)
lw s3, 7*4(sp)
lw s4, 8*4(sp)
lw s5, 9*4(sp)
lw s6, 10*4(sp)
lw s7, 11*4(sp)
lw s8, 12*4(sp)
lw gp, 13*4(sp)
addi sp, sp, (4*16)
sw zero, 0(a1)
jr ra
nop

View File

@ -38,3 +38,14 @@ bootstack:
.space 4096 * 16 * 8
.global bootstacktop
bootstacktop:
.align 12 #PGSHIFT
.global _root_page_table_buffer
_root_page_table_buffer:
.space 1024 * 64 # 64KB
.global _root_page_table_ptr
_root_page_table_ptr:
.space 4 # 4bytes
.global _cur_tls
_cur_tls:
.space 4 # 4bytes

View File

@ -1,199 +0,0 @@
#include "regdef.h"
.set noat
.set noreorder
.section .text.ebase
.globl trap_entry
.org 0x0
trap_entry:
# +0x000: TLB-miss vector
b general_trap_vec
# +0x180: general vector
.org 0x180
general_trap_vec:
move k1, sp # save stack pointer to k1
mfc0 k0, $12 # read cp0.status
andi k0, k0, 0x10 # extract cp0.status.ksu
beq k0, zero, trap_from_kernel
nop # delayslot
trap_from_user:
# load kstack, we can use k0 to store something
# la k0, kernel_stack
# la sp, kernel_stack_top
la k0, _cur_kstack_ptr
lw sp, 0(k0)
trap_from_kernel:
/*
* k0 is damaged
* k1 = old stack pointer
* sp = kernel stack */
#define TRAPFRAME_SIZE 176
# align stack pointer
andi k0, sp, 0xf
beqz k0, sp_aligned
nop
la k0, 0xfffffff0
and k0, sp, k0
sw sp, -TRAPFRAME_SIZE(k0)
move sp, k0
sp_aligned:
# allocate 38 / 70 words for trapframe + 6 extra words
addiu sp, sp, -TRAPFRAME_SIZE
# save general registers
sw ra, 160(sp)
sw fp, 156(sp)
sw k1, 152(sp) # k1 = old sp
sw gp, 148(sp)
sw k1, 144(sp) # real k1 is damaged
sw k0, 140(sp) # real k0 is damaged
sw t9, 136(sp)
sw t8, 132(sp)
sw s7, 128(sp)
sw s6, 124(sp)
sw s5, 120(sp)
sw s4, 116(sp)
sw s3, 112(sp)
sw s2, 108(sp)
sw s1, 104(sp)
sw s0, 100(sp)
sw t7, 96(sp)
sw t6, 92(sp)
sw t5, 88(sp)
sw t4, 84(sp)
sw t3, 80(sp)
sw t2, 76(sp)
sw t1, 72(sp)
sw t0, 68(sp)
sw a3, 64(sp)
sw a2, 60(sp)
sw a1, 56(sp)
sw a0, 52(sp)
sw v1, 48(sp)
sw v0, 44(sp)
sw AT, 40(sp)
nop
# save hi/lo
mflo t1
sw t1, 36(sp)
mfhi t0
sw t0, 32(sp)
# save special registers
mfc0 t0, $8 # cp0.vaddr
sw t0, 28(sp)
mfc0 t1, $14 # cp0.epc
sw t1, 24(sp)
mfc0 t0, $13 # cp0.cause
sw t0, 20(sp)
mfc0 t1, $12 # cp0.status
sw t1, 16(sp)
# support nested interrupt
la t0, ~0x1b # reset status.ksu, status.exl, status.ie
and t1, t1, t0
mtc0 t1, $12 # cp0.status
# prepare to call rust_trap
ori a0, sp, 0 /* set argument (trapframe) */
jal rust_trap
nop
.globl trap_return
trap_return:
# restore special registers
lw t1, 16(sp)
ori t1, t1, 0x2 # status.exl
nop
mtc0 t1, $12 # cp0.status
lw k0, 24(sp)
mtc0 k0, $14 # cp0.epc
lw t0, 32(sp)
mthi t0
lw t1, 36(sp)
mtlo t1
# restore general registers
lw AT, 40(sp)
lw v0, 44(sp)
lw v1, 48(sp)
lw a0, 52(sp)
lw a1, 56(sp)
lw a2, 60(sp)
lw a3, 64(sp)
lw t0, 68(sp)
lw t1, 72(sp)
lw t2, 76(sp)
lw t3, 80(sp)
lw t4, 84(sp)
lw t5, 88(sp)
lw t6, 92(sp)
lw t7, 96(sp)
lw s0, 100(sp)
lw s1, 104(sp)
lw s2, 108(sp)
lw s3, 112(sp)
lw s4, 116(sp)
lw s5, 120(sp)
lw s6, 124(sp)
lw s7, 128(sp)
lw t8, 132(sp)
lw t9, 136(sp)
# lw k0, 140(sp)
# lw k1, 144(sp)
lw gp, 148(sp)
lw fp, 156(sp)
lw ra, 160(sp)
# save kernel stack
lw k0, 0(sp)
addiu k1, sp, TRAPFRAME_SIZE
movn k1, k0, k0
la k0, _cur_kstack_ptr
sw k1, 0(k0)
nop
// restore stack
lw sp, 152(sp)
eret
nop
.section .bss.stack
.align 12 #PGSHIFT
.global kernel_stack
kernel_stack:
.space 1024 * 16 # 16KB for kernel stack
.global kernel_stack_top
kernel_stack_top:
.align 12 #PGSHIFT
.global _root_page_table_buffer
_root_page_table_buffer:
.space 1024 * 64 # 64KB
.global _root_page_table_ptr
_root_page_table_ptr:
.space 4 # 4bytes
.global _cur_kstack_ptr
_cur_kstack_ptr:
.space 4 # 4bytes
.global _cur_tls
_cur_tls:
.space 4 # 4bytes

View File

@ -37,6 +37,7 @@ fn init_frame_allocator() {
/// Transform memory area `[start, end)` to integer range for `FrameAllocator`
fn to_range(start: usize, end: usize) -> Range<usize> {
info!("frame allocator: start {:#x} end {:#x}", start, end);
let page_start = (start - MEMORY_OFFSET) / PAGE_SIZE;
let page_end = (end - MEMORY_OFFSET - 1) / PAGE_SIZE + 1;
assert!(page_start < page_end, "illegal range for frame allocator");

View File

@ -17,10 +17,6 @@ use mips::registers::cp0;
#[path = "board/malta/mod.rs"]
pub mod board;
#[cfg(feature = "board_mipssim")]
#[path = "board/mipssim/mod.rs"]
pub mod board;
#[no_mangle]
pub extern "C" fn rust_main() -> ! {
// unsafe { cpu::set_cpu_id(hartid); }
@ -70,6 +66,4 @@ fn others_main() -> ! {
const BOOT_CPU_ID: u32 = 0;
global_asm!(include_str!("boot/context.gen.s"));
global_asm!(include_str!("boot/entry.gen.s"));
global_asm!(include_str!("boot/trap.gen.s"));

View File

@ -0,0 +1,252 @@
//! ATA IO code, handling device multiplexing and IO operations
//!
//! Borrow from Rucore project. Thanks GWord!
//! Port from ucore C code.
//! Currently used in MIPS
use crate::drivers::{block::BlockDriver, DeviceType, Driver};
use crate::drivers::{BLK_DRIVERS, DRIVERS};
use crate::sync::SpinNoIrqLock as Mutex;
use alloc::string::String;
use alloc::sync::Arc;
use core::slice;
pub const BLOCK_SIZE: usize = 512;
pub struct IDE {
num: u8,
/// I/O Base
base: u16,
/// Control Base
ctrl: u16,
}
pub struct IDEDriver(Mutex<IDE>);
impl Driver for IDEDriver {
fn try_handle_interrupt(&self, _irq: Option<usize>) -> bool {
false
}
fn device_type(&self) -> DeviceType {
DeviceType::Block
}
fn get_id(&self) -> String {
format!("ide")
}
fn as_block(&self) -> Option<&dyn BlockDriver> {
Some(self)
}
}
impl BlockDriver for IDEDriver {
fn read_block(&self, block_id: usize, buf: &mut [u8]) -> bool {
let mut driver = self.0.lock();
let buf = unsafe { slice::from_raw_parts_mut(buf.as_ptr() as *mut u32, BLOCK_SIZE / 4) };
driver.read(block_id as u64, 1, buf).is_ok()
}
fn write_block(&self, block_id: usize, buf: &[u8]) -> bool {
if buf.len() < BLOCK_SIZE {
return false;
}
let mut driver = self.0.lock();
let buf = unsafe { slice::from_raw_parts(buf.as_ptr() as *mut u32, BLOCK_SIZE / 4) };
driver.write(block_id as u64, 1, buf).is_ok()
}
}
impl IDE {
pub fn new(num: u8) -> Self {
let ide = match num {
0 => IDE {
num: 0,
base: 0x1f0,
ctrl: 0x3f4,
},
1 => IDE {
num: 1,
base: 0x1f0,
ctrl: 0x3f4,
},
2 => IDE {
num: 2,
base: 0x170,
ctrl: 0x374,
},
3 => IDE {
num: 3,
base: 0x170,
ctrl: 0x374,
},
_ => panic!("ide number should be 0,1,2,3"),
};
ide.init();
ide
}
/// Read ATA DMA. Block size = 512 bytes.
pub fn read(&self, sector: u64, count: usize, data: &mut [u32]) -> Result<(), ()> {
assert_eq!(data.len(), count * SECTOR_SIZE);
self.wait();
unsafe {
self.select(sector, count as u8);
port::outb(self.base + ISA_COMMAND, IDE_CMD_READ);
for i in 0..count {
let ptr = &mut data[(i as usize) * SECTOR_SIZE];
if self.wait_error() {
return Err(());
}
insl(self.base, ptr, SECTOR_SIZE);
}
}
Ok(())
}
/// Write ATA DMA. Block size = 512 bytes.
pub fn write(&self, sector: u64, count: usize, data: &[u32]) -> Result<(), ()> {
assert_eq!(data.len(), count * SECTOR_SIZE);
self.wait();
unsafe {
self.select(sector, count as u8);
port::outb(self.base + ISA_COMMAND, IDE_CMD_WRITE);
for i in 0..count {
let ptr = &data[(i as usize) * SECTOR_SIZE];
if self.wait_error() {
return Err(());
}
outsl(self.base, ptr, SECTOR_SIZE);
}
}
Ok(())
}
fn wait(&self) {
while unsafe { port::inb(self.base + ISA_STATUS) } & IDE_BUSY != 0 {}
}
fn wait_error(&self) -> bool {
self.wait();
let status = unsafe { port::inb(self.base + ISA_STATUS) };
status & (IDE_DF | IDE_ERR) != 0
}
fn init(&self) {
self.wait();
unsafe {
// step1: select drive
port::outb(self.base + ISA_SDH, (0xE0 | ((self.num & 1) << 4)) as u8);
self.wait();
// step2: send ATA identify command
port::outb(self.base + ISA_COMMAND, IDE_CMD_IDENTIFY);
self.wait();
// step3: polling
if port::inb(self.base + ISA_STATUS) == 0 || self.wait_error() {
return;
}
// ???
let mut data = [0; SECTOR_SIZE];
insl(self.base + ISA_DATA, data.as_mut_ptr(), SECTOR_SIZE);
}
}
fn select(&self, sector: u64, count: u8) {
assert_ne!(count, 0);
self.wait();
unsafe {
// generate interrupt
port::outb(self.ctrl + ISA_CTRL, 0);
port::outb(self.base + ISA_SECCNT, count);
port::outb(self.base + ISA_SECTOR, (sector & 0xFF) as u8);
port::outb(self.base + ISA_CYL_LO, ((sector >> 8) & 0xFF) as u8);
port::outb(self.base + ISA_CYL_HI, ((sector >> 16) & 0xFF) as u8);
port::outb(
self.base + ISA_SDH,
0xE0 | ((self.num & 1) << 4) | (((sector >> 24) & 0xF) as u8),
);
}
}
}
const SECTOR_SIZE: usize = 128;
const MAX_DMA_SECTORS: usize = 0x1F_F000 / SECTOR_SIZE; // Limited by sector count (and PRDT entries)
// 512 PDRT entries, assume maximum fragmentation = 512 * 4K max = 2^21 = 2MB per transfer
const ISA_DATA: u16 = 0x00;
const ISA_ERROR: u16 = 0x01;
const ISA_PRECOMP: u16 = 0x01;
const ISA_CTRL: u16 = 0x02;
const ISA_SECCNT: u16 = 0x02;
const ISA_SECTOR: u16 = 0x03;
const ISA_CYL_LO: u16 = 0x04;
const ISA_CYL_HI: u16 = 0x05;
const ISA_SDH: u16 = 0x06;
const ISA_COMMAND: u16 = 0x07;
const ISA_STATUS: u16 = 0x07;
const IDE_BUSY: u8 = 0x80;
const IDE_DRDY: u8 = 0x40;
const IDE_DF: u8 = 0x20;
const IDE_DRQ: u8 = 0x08;
const IDE_ERR: u8 = 0x01;
const IDE_CMD_READ: u8 = 0x20;
const IDE_CMD_WRITE: u8 = 0x30;
const IDE_CMD_IDENTIFY: u8 = 0xEC;
const MAX_NSECS: usize = 128;
#[cfg(target_arch = "x86_64")]
unsafe fn insl(addr: u16, data: *mut u32, len: usize) {
llvm_asm!("rep insl" :: "{dx}"(addr), "{rdi}"(data), "{cx}"(SECTOR_SIZE) : "rdi" : "volatile");
}
#[cfg(not(target_arch = "x86_64"))]
unsafe fn insl(addr: u16, data: *mut u32, len: usize) {
for i in 0..len {
*data.add(i) = port::inl(addr);
}
}
#[cfg(target_arch = "x86_64")]
unsafe fn outsl(addr: u16, data: *const u32, len: usize) {
llvm_asm!("rep insl" :: "{dx}"(addr), "{rdi}"(data), "{cx}"(SECTOR_SIZE) : "rdi" : "volatile");
}
#[cfg(not(target_arch = "x86_64"))]
unsafe fn outsl(addr: u16, data: *const u32, len: usize) {
for i in 0..len {
port::outl(addr, *data.add(i));
}
}
// MIPS
mod port {
const PCI_BASE: usize = 0xb8000000;
pub unsafe fn inb(port: u16) -> u8 {
crate::util::read(port as usize + PCI_BASE)
}
pub unsafe fn outb(port: u16, value: u8) {
crate::util::write(port as usize + PCI_BASE, value)
}
pub unsafe fn inl(port: u16) -> u32 {
crate::util::read(port as usize + PCI_BASE)
}
pub unsafe fn outl(port: u16, value: u32) {
crate::util::write(port as usize + PCI_BASE, value)
}
}
pub fn init() {
let ide = IDE::new(0);
let driver = Arc::new(IDEDriver(Mutex::new(ide)));
DRIVERS.write().push(driver.clone());
BLK_DRIVERS.write().push(driver.clone());
}

View File

@ -1,6 +1,7 @@
use super::Driver;
pub mod ahci;
pub mod ide;
pub mod virtio_blk;
pub trait BlockDriver: Driver {