Skip to content

Commit

Permalink
WIP: Interrupt work for haiku
Browse files Browse the repository at this point in the history
  • Loading branch information
BuJo committed Oct 1, 2024
1 parent 60fdecd commit 57ac592
Show file tree
Hide file tree
Showing 16 changed files with 350 additions and 150 deletions.
4 changes: 1 addition & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
cargo-features = ["profile-rustflags"]

[package]
name = "rriscv"
version = "0.1.0"
Expand Down Expand Up @@ -31,5 +29,5 @@ opt-level = 3
lto = "fat"
opt-level = "z"
codegen-units = 1
rustflags = ["-C", "target-cpu=native"]
#rustflags = ["-C", "target-cpu=native"]
#panic = "abort"
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ limitations under the License.
* [Demystifying the RISC-V Linux software stack](https://www.european-processor-initiative.eu/wp-content/uploads/2022/06/[email protected])
* [6.S081: Interrupts](https://pdos.csail.mit.edu/6.828/2021/slides/6s081-lec-interrupts.pdf)
* [RISC-V Bytes: Introduction to Instruction Formats](https://danielmangum.com/posts/risc-v-bytes-intro-instruction-formats/)
* [RISC-V System, Booting, And Interrupts](https://marz.utk.edu/my-courses/cosc562/riscv/)

### Device Trees

Expand Down
Binary file modified data/linux.dtb
Binary file not shown.
5 changes: 4 additions & 1 deletion data/linux.dts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

chosen {
bootargs = "root=/dev/vda ro earlycon=uart8250,mmio,0x10000000,115200n8";
//rng-seed = <0x34f6690a 0xf83ff069 0xbeef75ff 0x2605cdf2 0x7b37efa8 0x8f1862ee 0x35fa733d 0x9666dd63>;
stdout-path = "/soc/serial@10000000";
};

Expand Down Expand Up @@ -35,7 +36,9 @@
reg = <0x00>;
status = "okay";
compatible = "riscv";
riscv,isa = "rv64im";
//riscv,isa = "rv64im";
riscv,isa-base = "rv64i";
riscv,isa-extensions = "i", "m", "a", "c";

interrupt-controller {
#interrupt-cells = <0x01>;
Expand Down
75 changes: 75 additions & 0 deletions src/bin/haiku.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
use std::sync::Arc;
use std::{env, fs};

use log::error;

use rriscv::bus::DynBus;
use rriscv::hart::Hart;
use rriscv::ram::Ram;
use rriscv::reg::treg;
use rriscv::rom::Rom;
use rriscv::rtc::Rtc;
use rriscv::uart::Uart8250;
use rriscv::virtio::BlkDevice;
use rriscv::{clint, dt, plic};

fn main() -> Result<(), Box<dyn std::error::Error>> {
env_logger::init();

let args: Vec<String> = env::args().collect();
let image_file = args.get(1).expect("expect u-boot file");
let disk_file = args.get(2).expect("expect disc file");

let bin_data = fs::read(image_file).expect("file");

let bus = Arc::new(DynBus::new());
let ram = Ram::sized(1024 * 1024 * 128);
let pc: usize = 0x80000000;
ram.write(0, bin_data.to_vec());

let s = ram.size();
bus.map(ram, pc..(pc + s));

// Add low ram
let ram = Ram::sized(0x10000);
bus.map(ram, 0x0..0x10000);

let rtc = Rtc::new();
bus.map(rtc, 0x40000..0x40020);

let console = Uart8250::new();
bus.map(console, 0x10000000..0x10000010);

// virtio block device vda
let vda = BlkDevice::new(disk_file, bus.clone());
bus.map(vda, 0x10001000..0x10002000);

let clint = clint::Clint::new(bus.clone(), 0x40000);
bus.map(clint, 0x2000000..0x2010000);

let plic = plic::Plic::new();
bus.map(plic, 0xc000000..0xc600000);

let device_tree = dt::load("linux");
let dtb_start = 0x80000;
let dtb_end = dtb_start + device_tree.len();
let dtb = Rom::new(device_tree);
bus.map(dtb, 0x80000..dtb_end);

let mut hart = Hart::new(0, pc, bus.clone());

// linux register state
hart.set_register(treg("a0"), 0);
hart.set_register(treg("a1"), dtb_start as u64);
hart.set_csr(rriscv::csr::SATP, 0);

loop {
match hart.tick() {
Ok(_) => {}
Err(err) => {
error!("err: {:?}", err);
return Ok(());
}
}
}
}
10 changes: 7 additions & 3 deletions src/bin/linux.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use std::{env, fs};
use std::sync::Arc;
use std::{env, fs};

use log::error;
use object::{Object, ObjectSection};

use rriscv::{clint, dt, plic};
use rriscv::bus::DynBus;
use rriscv::hart::Hart;
use rriscv::ram::Ram;
Expand All @@ -13,6 +12,7 @@ use rriscv::rom::Rom;
use rriscv::rtc::Rtc;
use rriscv::uart::Uart8250;
use rriscv::virtio::BlkDevice;
use rriscv::{clint, dt, plic};

fn main() -> Result<(), Box<dyn std::error::Error>> {
env_logger::init();
Expand Down Expand Up @@ -74,12 +74,16 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
hart.set_register(treg("a1"), dtb_start as u64);
hart.set_csr(rriscv::csr::SATP, 0);

let mut err_count = 0;
loop {
match hart.tick() {
Ok(_) => {}
Err(err) => {
err_count += 1;
error!("err: {:?}", err);
return Ok(());
if err_count > 10 {
return Ok(());
}
}
}
}
Expand Down
59 changes: 17 additions & 42 deletions src/bin/linuxdbg.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,10 @@
use std::{env, fs};
use std::net::TcpListener;
use std::sync::Arc;
use std::{env, fs};

use log::{info, LevelFilter};
use log4rs::append::console::ConsoleAppender;
use log4rs::append::rolling_file::policy::compound::CompoundPolicy;
use log4rs::append::rolling_file::policy::compound::roll::fixed_window::FixedWindowRoller;
use log4rs::append::rolling_file::policy::compound::trigger::size::SizeTrigger;
use log4rs::append::rolling_file::RollingFileAppender;
use log4rs::config::{Appender, Root};
use log4rs::Config;
use log4rs::encode::pattern::PatternEncoder;
use log4rs::filter::threshold::ThresholdFilter;
use log::info;
use object::{Object, ObjectSection};

use rriscv::{clint, dt, plic};
use rriscv::bus::DynBus;
use rriscv::gdb::emu::Emulator;
use rriscv::hart::Hart;
Expand All @@ -24,31 +14,10 @@ use rriscv::rom::Rom;
use rriscv::rtc::Rtc;
use rriscv::uart::Uart8250;
use rriscv::virtio::BlkDevice;
use rriscv::{clint, dt, plic};

fn main() -> Result<(), Box<dyn std::error::Error>> {
let stdout = ConsoleAppender::builder().build();
let rolling = CompoundPolicy::new(
Box::new(SizeTrigger::new(5 * 1024 * 1024)),
Box::new(FixedWindowRoller::builder().build("debug.log.{}", 3).unwrap()),
);
let debug = Appender::builder()
.filter(Box::new(ThresholdFilter::new(LevelFilter::Debug)))
.build(
"riscv",
Box::new(
RollingFileAppender::builder()
.encoder(Box::new(PatternEncoder::new("{d} {l}::{m}{n}")))
.build("debug.log", Box::new(rolling))?,
),
);

let config = Config::builder()
.appender(Appender::builder().build("stdout", Box::new(stdout)))
.appender(debug)
.build(Root::builder().appender("stdout").build(LevelFilter::Warn))
.unwrap();

let _ = log4rs::init_config(config).unwrap();
env_logger::init();

let args: Vec<String> = env::args().collect();
let image_file = args.get(1).expect("expect image file");
Expand All @@ -61,18 +30,24 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let ram = Ram::new();
let pc = elf.entry() as usize;

info!("ELF entry: 0x{:x}", pc);

for section in elf.sections() {
let name = section.name().expect("section name");
if name.contains("data") || name.contains("text") {
let start = section.address() as usize;
if let Ok(data) = section.uncompressed_data() {
ram.write(start - pc, data.to_vec());
}
//let name = section.name().expect("section name");
//if name.contains("data") || name.contains("text") {
let start = section.address() as usize;
if start == 0 {
continue;
}
if let Ok(data) = section.uncompressed_data() {
ram.write(start - 0x80000000, data.to_vec());
}
//}
}

let s = ram.size();
bus.map(ram, pc..(pc + s));
bus.map(ram, 0x80000000..(pc + s));
info!("mapped RAM: 0x{:x} (size: {})", pc, s);

// Add low ram
let ram = Ram::sized(0x10000);
Expand Down
37 changes: 24 additions & 13 deletions src/clint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ use std::sync::Arc;
use log::trace;

use crate::bus::DynBus;
use crate::csr::MINSTRET;
use crate::device::Device;
use crate::hart::Hart;
use crate::irq::Interrupt;
use crate::irq::{Interrupt, Mcause};
use crate::{csr, plic, rtc};

pub const CLINT_BASE: usize = 0x2000000;
Expand Down Expand Up @@ -107,6 +108,7 @@ impl Device for Clint {
fn read_double(&self, addr: usize) -> Result<u64, Interrupt> {
match addr {
MTIME_ADDR => self.bus.read_double(self.rtc_addr + rtc::MTIME_ADDR),
MTIMECMP_ADDR => self.bus.read_double(self.rtc_addr + rtc::MTIMECMP_ADDR),
_ => {
trace!("reading double word from 0x{:x}", addr);
Ok(0)
Expand Down Expand Up @@ -177,7 +179,7 @@ fn pending_interrupt(mip: u64, mie: u64) -> Option<InterruptType> {
None
}

pub(crate) fn interrupt(hart: &Hart) -> Option<u64> {
pub(crate) fn interrupt(hart: &Hart) -> Option<Mcause> {
let mode = PrivilegeLevel::M;
let mstatus = hart.get_csr(csr::MSTATUS);

Expand Down Expand Up @@ -205,17 +207,26 @@ pub(crate) fn interrupt(hart: &Hart) -> Option<u64> {
mip |= 1 << InterruptType::SEIP as u64;
}

pending_interrupt(mip, mie).map(|interrupt| {
match interrupt {
InterruptType::MEIP => 0x800000000000000b, // Machine external interrupt
InterruptType::SEIP => 0x8000000000000009,
InterruptType::UEIP => 0x8000000000000008,
InterruptType::MTIP => 0x8000000000000007, // Machine timer interrupt
InterruptType::STIP => 0x8000000000000005,
InterruptType::UTIP => 0x8000000000000004,
InterruptType::MSIP => 0x8000000000000003, // Machine software interrupt
InterruptType::SSIP => 0x8000000000000001,
InterruptType::USIP => 0x8000000000000000,
// Poor timer, check every other instruction if timer
let instret = hart.get_csr(MINSTRET);
if instret % 100 == 0 {
let mtimecmp = hart.bus.read_double(CLINT_BASE + MTIMECMP_ADDR).unwrap();
let time = hart.bus.read_double(CLINT_BASE + MTIME_ADDR).unwrap();
if mtimecmp <= time {
trace!("timer erupted {} - {}", mtimecmp, time);
mip |= 1 << InterruptType::MTIP as u64;
}
}

pending_interrupt(mip, mie).map(|interrupt| match interrupt {
InterruptType::MEIP => Mcause::MEIP,
InterruptType::SEIP => Mcause::SEIP,
InterruptType::UEIP => Mcause::UEIP,
InterruptType::MTIP => Mcause::MTIP,
InterruptType::STIP => Mcause::STIP,
InterruptType::UTIP => Mcause::UTIP,
InterruptType::MSIP => Mcause::MSIP,
InterruptType::SSIP => Mcause::SSIP,
InterruptType::USIP => Mcause::USIP,
})
}
3 changes: 2 additions & 1 deletion src/csr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub const MIP: usize = 0x344;
pub const MIE: usize = 0x304;
pub const MEPC: usize = 0x341;
pub const MCAUSE: usize = 0x342;
pub const MTVAL: usize = 0x343;

type CsrFn = for<'a> fn(&'a Csr, usize) -> u64;
type CsrWrFn = for<'a> fn(&'a mut Csr, usize, u64);
Expand Down Expand Up @@ -113,7 +114,7 @@ const CSR_MAP: [(usize, &str, CsrFn, CsrWrFn); 99] = [
(MSCRATCH, "mscratch", Csr::read_any, Csr::write_any),
(MEPC, "mepc", Csr::read_any, Csr::write_any),
(MCAUSE, "mcause", Csr::read_any, Csr::write_any),
(0x343, "mtval", Csr::read_any, Csr::write_any),
(MTVAL, "mtval", Csr::read_any, Csr::write_any),
(MIP, "mip", Csr::read_any, Csr::write_any),
(0x34A, "minst", Csr::read_any, Csr::write_any),
(0x34B, "mtval2", Csr::read_any, Csr::write_any),
Expand Down
12 changes: 7 additions & 5 deletions src/gdb/emu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,15 +124,17 @@ impl Handler for Emulator {
match cpu_ref.tick() {
Ok(_) => continue,
Err(e) => {
debug!("trapping error {:?}", e);
return match e {
Interrupt::MemoryFault(_) => Ok(StopReason::Signal(SIGTRAP as u8)),
/* Interrupt::MemoryFault(_) => Ok(StopReason::Signal(SIGTRAP as u8)),
Interrupt::Unmapped(_) => Ok(StopReason::Signal(SIGTRAP as u8)),
Interrupt::Unaligned(_) => Err(Error::from(e)),
Interrupt::Halt => Err(Error::from(e)),
Interrupt::Unimplemented(_) => Ok(StopReason::Signal(SIGTRAP as u8)),
Interrupt::InstructionDecodingError => Ok(StopReason::Signal(SIGTRAP as u8)),
Interrupt::Unimplemented(_) => Ok(StopReason::Signal(SIGTRAP as u8)),*/
Interrupt::InstructionDecodingError(_) => Ok(StopReason::Signal(SIGTRAP as u8)),
Interrupt::IllegalOpcode(_) => Ok(StopReason::Signal(SIGTRAP as u8)),
}
e => Err(Error::from(e)),
};
}
}
}
Expand Down Expand Up @@ -187,7 +189,7 @@ impl From<Interrupt> for gdb_remote_protocol::Error {
Interrupt::Unaligned(_) => Error::Error(2),
Interrupt::Halt => Error::Error(3),
Interrupt::Unimplemented(_) => Error::Unimplemented,
Interrupt::InstructionDecodingError => Error::Error(4),
Interrupt::InstructionDecodingError(_) => Error::Error(4),
Interrupt::IllegalOpcode(_) => Error::Error(5),
}
}
Expand Down
Loading

0 comments on commit 57ac592

Please sign in to comment.