Skip to content

Commit

Permalink
Support net for aarch64
Browse files Browse the repository at this point in the history
  • Loading branch information
equation314 committed Feb 21, 2023
1 parent a664211 commit 2702ffa
Show file tree
Hide file tree
Showing 14 changed files with 250 additions and 31 deletions.
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ members = [
"crates/memory_addr",
"crates/page_table",
"crates/page_table_entry",
"crates/ratio",
"crates/scheduler",
"crates/tuple_for_each",

Expand Down
9 changes: 9 additions & 0 deletions crates/ratio/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[package]
name = "ratio"
version = "0.1.0"
edition = "2021"
authors = ["Yuekai Jia <[email protected]>"]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
130 changes: 130 additions & 0 deletions crates/ratio/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
#![cfg_attr(not(test), no_std)]
#![feature(const_trait_impl)]

use core::{cmp::PartialEq, fmt};

/// Convert `numerator / denominator` to `mult / (1 << shift)` to avoid `u128` division.
pub struct Ratio {
numerator: u32,
denominator: u32,
mult: u32,
shift: u32,
}

impl Ratio {
pub const fn zero() -> Self {
Self {
numerator: 0,
denominator: 0,
mult: 0,
shift: 0,
}
}

pub const fn new(numerator: u32, denominator: u32) -> Self {
assert!(!(denominator == 0 && numerator != 0));
if numerator == 0 {
return Self {
numerator,
denominator,
mult: 0,
shift: 0,
};
}

// numerator / denominator == (numerator * (1 << shift) / denominator) / (1 << shift)
let mut shift = 32;
let mut mult;
loop {
mult = (((numerator as u64) << shift) + denominator as u64 / 2) / denominator as u64;
if mult <= u32::MAX as u64 || shift == 0 {
break;
}
shift -= 1;
}

while mult % 2 == 0 && shift > 0 {
mult /= 2;
shift -= 1;
}

Self {
numerator,
denominator,
mult: mult as u32,
shift,
}
}

pub const fn inverse(&self) -> Self {
Self::new(self.denominator, self.numerator)
}

pub const fn mul_trunc(&self, value: u64) -> u64 {
((value as u128 * self.mult as u128) >> self.shift) as u64
}

pub const fn mul_round(&self, value: u64) -> u64 {
((value as u128 * self.mult as u128 + (1 << self.shift >> 1)) >> self.shift) as u64
}
}

impl fmt::Debug for Ratio {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"Ratio({}/{} ~= {}/{})",
self.numerator,
self.denominator,
self.mult,
1u64 << self.shift
)
}
}

impl const PartialEq<Ratio> for Ratio {
fn eq(&self, other: &Ratio) -> bool {
self.mult == other.mult && self.shift == other.shift
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_ratio() {
let a = Ratio::new(625_000, 1_000_000);
let b = Ratio::new(1, u32::MAX);
let c = Ratio::new(u32::MAX, u32::MAX);
let d = Ratio::new(u32::MAX, 1);

assert_eq!(a.mult, 5);
assert_eq!(a.shift, 3);
assert_eq!(a.mul_trunc(800), 500);

assert_eq!(b.mult, 1);
assert_eq!(b.shift, 32);
assert_eq!(b.mul_trunc(u32::MAX as _), 0);
assert_eq!(b.mul_round(u32::MAX as _), 1);

assert_eq!(c.mult, 1);
assert_eq!(c.shift, 0);
assert_eq!(c.mul_trunc(u32::MAX as _), u32::MAX as _);

println!("{:?}", a);
println!("{:?}", b);
println!("{:?}", c);
println!("{:?}", d);
}

#[test]
fn test_zero() {
let z1 = Ratio::new(0, 100);
let z2 = Ratio::zero();
let z3 = Ratio::new(0, 0);
assert_eq!(z1.mul_trunc(233), 0);
assert_eq!(z2.mul_trunc(0), 0);
assert_eq!(z3.mul_round(456), 0);
}
}
29 changes: 15 additions & 14 deletions modules/axconfig/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,23 +60,24 @@ fn gen_config_rs(arch: &str, platform: &str) -> Result<()> {
} else {
writeln!(output, "pub const {var_name}: &str = \"{s}\";")?;
}
} else if let Value::Array(regions) = value {
if key != "mmio-regions" && key != "virtio-mmio-regions" {
continue;
}
writeln!(output, "pub const {var_name}: &[(usize, usize)] = &[")?;
for r in regions {
let r = r.as_array().unwrap();
writeln!(
output,
" ({}, {}),",
r[0].as_str().unwrap(),
r[1].as_str().unwrap()
)?;
}
writeln!(output, "];")?;
}
}

writeln!(output, "pub const MMIO_REGIONS: &[(usize, usize)] = &[")?;
if let Some(regions) = config["mmio-regions"].as_array() {
for r in regions {
let r = r.as_array().unwrap();
writeln!(
output,
" ({}, {}),",
r[0].as_str().unwrap(),
r[1].as_str().unwrap()
)?;
}
}
writeln!(output, "];")?;

let out_path = format!("src/config_{}.rs", platform.replace('-', "_"));
fs::write(out_path, output)?;

Expand Down
1 change: 1 addition & 0 deletions modules/axconfig/src/platform/dummy.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ kernel-base-paddr = "0"
kernel-base-vaddr = "0"
phys-virt-offset = "0"
mmio-regions = []
virtio-mmio-regions = []

timer_frequency = "0"
35 changes: 35 additions & 0 deletions modules/axconfig/src/platform/qemu-virt-aarch64.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,39 @@ phys-virt-offset = "0xffff_0000_0000_0000"
mmio-regions = [
["0x0900_0000", "0x1000"], # PL011 UART
["0x0800_0000", "0x2_0000"], # GICv2
["0x0a00_0000", "0x4000"], # VirtIO
]
virtio-mmio-regions = [
["0x0a00_0000", "0x200"],
["0x0a00_0200", "0x200"],
["0x0a00_0400", "0x200"],
["0x0a00_0600", "0x200"],
["0x0a00_0800", "0x200"],
["0x0a00_0a00", "0x200"],
["0x0a00_0c00", "0x200"],
["0x0a00_0e00", "0x200"],
["0x0a00_1000", "0x200"],
["0x0a00_1200", "0x200"],
["0x0a00_1400", "0x200"],
["0x0a00_1600", "0x200"],
["0x0a00_1800", "0x200"],
["0x0a00_1a00", "0x200"],
["0x0a00_1c00", "0x200"],
["0x0a00_1e00", "0x200"],
["0x0a00_3000", "0x200"],
["0x0a00_2200", "0x200"],
["0x0a00_2400", "0x200"],
["0x0a00_2600", "0x200"],
["0x0a00_2800", "0x200"],
["0x0a00_2a00", "0x200"],
["0x0a00_2c00", "0x200"],
["0x0a00_2e00", "0x200"],
["0x0a00_3000", "0x200"],
["0x0a00_3200", "0x200"],
["0x0a00_3400", "0x200"],
["0x0a00_3600", "0x200"],
["0x0a00_3800", "0x200"],
["0x0a00_3a00", "0x200"],
["0x0a00_3c00", "0x200"],
["0x0a00_3e00", "0x200"],
]
10 changes: 10 additions & 0 deletions modules/axconfig/src/platform/qemu-virt-riscv.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,15 @@ mmio-regions = [
["0x1000_0000", "0x1000"], # UART
["0x1000_1000", "0x8000"], # VirtIO
]
virtio-mmio-regions = [
["0x1000_1000", "0x1000"],
["0x1000_2000", "0x1000"],
["0x1000_3000", "0x1000"],
["0x1000_4000", "0x1000"],
["0x1000_5000", "0x1000"],
["0x1000_6000", "0x1000"],
["0x1000_7000", "0x1000"],
["0x1000_8000", "0x1000"],
]

timer_frequency = "10_000_000" # 10MHz
3 changes: 2 additions & 1 deletion modules/axdriver/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ authors = ["Yuekai Jia <[email protected]>"]
[features]
bus-mmio = ["driver_virtio?/bus-mmio"]
bus-pci = ["driver_virtio?/bus-pci"]
virtio = ["driver_virtio", "dep:axalloc", "dep:axhal"]
virtio = ["driver_virtio", "dep:axalloc", "dep:axhal", "dep:axconfig"]

# various types of drivers
virtio-blk = ["virtio", "dep:driver_block", "driver_virtio/block"]
Expand All @@ -29,3 +29,4 @@ driver_net = { path = "../../crates/driver_net", optional = true }
driver_virtio = { path = "../../crates/driver_virtio", optional = true }
axalloc = { path = "../axalloc", optional = true }
axhal = { path = "../axhal", optional = true }
axconfig = { path = "../axconfig", optional = true }
13 changes: 1 addition & 12 deletions modules/axdriver/src/virtio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,6 @@ cfg_if! {
}
}

const VIRTIO_MMIO_REGIONS: &[(usize, usize)] = &[
(0x1000_1000, 0x1000),
(0x1000_2000, 0x1000),
(0x1000_3000, 0x1000),
(0x1000_4000, 0x1000),
(0x1000_5000, 0x1000),
(0x1000_6000, 0x1000),
(0x1000_7000, 0x1000),
(0x1000_8000, 0x1000),
];

pub struct VirtIoHalImpl;

unsafe impl VirtIoHal for VirtIoHalImpl {
Expand Down Expand Up @@ -83,7 +72,7 @@ impl AllDevices {
F: FnOnce(VirtIoTransport) -> Option<D>,
{
// TODO: parse device tree
for reg in VIRTIO_MMIO_REGIONS {
for reg in axconfig::VIRTIO_MMIO_REGIONS {
if let Some(transport) = driver_virtio::probe_mmio_device(
phys_to_virt(reg.0.into()).as_mut_ptr(),
reg.1,
Expand Down
7 changes: 6 additions & 1 deletion modules/axhal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ authors = ["Yuekai Jia <[email protected]>"]

[features]
platform-qemu-virt-riscv = ["axconfig/platform-qemu-virt-riscv"]
platform-qemu-virt-aarch64 = ["axconfig/platform-qemu-virt-aarch64", "dep:page_table_entry"]
platform-qemu-virt-aarch64 = [
"axconfig/platform-qemu-virt-aarch64",
"dep:page_table_entry", "dep:lazy_init", "dep:ratio",
]
paging = ["axalloc", "page_table"]
default = []

Expand All @@ -21,6 +24,8 @@ static_assertions = "1.1.0"
axconfig = { path = "../axconfig" }
axalloc = { path = "../axalloc", optional = true }
axerror = { path = "../axerror" }
ratio = { path = "../../crates/ratio", optional = true }
lazy_init = { path = "../../crates/lazy_init", optional = true }
page_table = { path = "../../crates/page_table", optional = true }
page_table_entry = { path = "../../crates/page_table_entry", optional = true }
memory_addr = { path = "../../crates/memory_addr" }
Expand Down
2 changes: 1 addition & 1 deletion modules/axhal/src/arch/aarch64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ pub fn flush_tlb(vaddr: Option<VirtAddr>) {
if let Some(vaddr) = vaddr {
asm!("tlbi vaae1is, {}; dsb sy; isb", in(reg) vaddr.as_usize())
} else {
// flush the entire all
// flush the entire TLB
asm!("tlbi vmalle1; dsb sy; isb")
}
}
Expand Down
24 changes: 24 additions & 0 deletions modules/axhal/src/platform/qemu_virt_aarch64/generic_timer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use aarch64_cpu::registers::{CNTFRQ_EL0, CNTPCT_EL0};
use lazy_init::LazyInit;
use ratio::Ratio;
use tock_registers::interfaces::Readable;

use crate::time::NANOS_PER_SEC;

#[allow(unused)]
const PHYS_TIMER_IRQ_NUM: usize = 30;

static CNTPCT_TO_NANOS_RATIO: LazyInit<Ratio> = LazyInit::new();

pub fn current_ticks() -> u64 {
CNTPCT_EL0.get()
}

#[inline(never)]
pub fn ticks_to_nanos(ticks: u64) -> u64 {
CNTPCT_TO_NANOS_RATIO.mul_trunc(ticks)
}

pub(crate) fn init() {
CNTPCT_TO_NANOS_RATIO.init_by(Ratio::new(NANOS_PER_SEC as u32, CNTFRQ_EL0.get() as u32));
}
Loading

0 comments on commit 2702ffa

Please sign in to comment.