From 2f2cbb81acdcedb156a145548a8d419e84fa1b66 Mon Sep 17 00:00:00 2001 From: Jiajie Chen Date: Tue, 7 May 2019 08:40:25 +0800 Subject: [PATCH] Embed rocket chip dtb in code --- kernel/Makefile | 7 +- kernel/build.rs | 6 +- .../arch/riscv32/board/rocket_chip/device.dts | 112 ++++++++++++++++++ .../arch/riscv32/board/rocket_chip/linker.ld | 50 ++++++++ .../src/arch/riscv32/board/rocket_chip/mod.rs | 18 +++ kernel/src/arch/riscv32/memory.rs | 2 +- kernel/src/arch/riscv32/mod.rs | 21 +++- 7 files changed, 210 insertions(+), 6 deletions(-) create mode 100644 kernel/src/arch/riscv32/board/rocket_chip/device.dts create mode 100644 kernel/src/arch/riscv32/board/rocket_chip/linker.ld create mode 100644 kernel/src/arch/riscv32/board/rocket_chip/mod.rs diff --git a/kernel/Makefile b/kernel/Makefile index d8bb97a..faba997 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -75,10 +75,13 @@ board := raspi3 need_bootloader := true endif -# currently only mipsel architecture needs DTB linked to the kernel +# currently only mipsel architecture and rocket-chip needs DTB linked to the kernel ifeq ($(arch), mipsel) dtb := src/arch/$(arch)/board/$(board)/device.dtb endif +ifeq ($(board), rocket_chip) +dtb := src/arch/riscv32/board/$(board)/device.dtb +endif # mipssim does not support SMP ifeq ($(board), mipssim) @@ -330,6 +333,8 @@ ifeq ($(arch), x86_64) else ifeq ($(arch), $(filter $(arch), riscv32 riscv64)) ifeq ($(board), k210) @cp src/arch/riscv32/board/k210/linker.ld src/arch/riscv32/boot/linker64.ld +else ifeq ($(board), rocket_chip) + @cp src/arch/riscv32/board/rocket_chip/linker.ld src/arch/riscv32/boot/linker64.ld else @cp src/arch/riscv32/board/u540/linker.ld src/arch/riscv32/boot/linker64.ld endif diff --git a/kernel/build.rs b/kernel/build.rs index 8e1440f..286606b 100644 --- a/kernel/build.rs +++ b/kernel/build.rs @@ -16,7 +16,11 @@ fn main() { gen_vector_asm().unwrap(); } "riscv32" => {} - "riscv64" => {} + "riscv64" => { + if board == "rocket_chip" { + gen_dtb_asm(&String::from("riscv32"), &board).unwrap(); + } + } "mipsel" => { gen_dtb_asm(&arch, &board).unwrap(); } diff --git a/kernel/src/arch/riscv32/board/rocket_chip/device.dts b/kernel/src/arch/riscv32/board/rocket_chip/device.dts new file mode 100644 index 0000000..774c238 --- /dev/null +++ b/kernel/src/arch/riscv32/board/rocket_chip/device.dts @@ -0,0 +1,112 @@ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "freechips,rocketchip-unknown-dev"; + model = "freechips,rocketchip-unknown"; + L14: cpus { + #address-cells = <1>; + #size-cells = <0>; + L5: cpu@0 { + clock-frequency = <0>; + compatible = "sifive,rocket0", "riscv"; + d-cache-block-size = <64>; + d-cache-sets = <64>; + d-cache-size = <16384>; + d-tlb-sets = <1>; + d-tlb-size = <32>; + device_type = "cpu"; + i-cache-block-size = <64>; + i-cache-sets = <64>; + i-cache-size = <16384>; + i-tlb-sets = <1>; + i-tlb-size = <32>; + mmu-type = "riscv,sv39"; + next-level-cache = <&L6>; + reg = <0>; + riscv,isa = "rv64imafdc"; + status = "okay"; + timebase-frequency = <1000000>; + tlb-split; + L3: interrupt-controller { + #interrupt-cells = <1>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + }; + }; + }; + L6: memory@80000000 { + device_type = "memory"; + reg = <0x80000000 0x10000000>; + }; + L13: soc { + #address-cells = <1>; + #size-cells = <1>; + compatible = "freechips,rocketchip-unknown-soc", "simple-bus"; + ranges; + L11: blkdev-controller@10015000 { + compatible = "ucbbar,blkdev"; + interrupt-parent = <&L0>; + interrupts = <3>; + reg = <0x10015000 0x1000>; + reg-names = "control"; + }; + L1: clint@2000000 { + compatible = "riscv,clint0"; + interrupts-extended = <&L3 3 &L3 7>; + reg = <0x2000000 0x10000>; + reg-names = "control"; + }; + L2: debug-controller@0 { + compatible = "sifive,debug-013", "riscv,debug-013"; + interrupts-extended = <&L3 65535>; + reg = <0x0 0x1000>; + reg-names = "control"; + }; + L8: error-device@3000 { + compatible = "sifive,error0"; + reg = <0x3000 0x1000>; + reg-names = "mem"; + }; + L10: external-interrupts { + interrupt-parent = <&L0>; + interrupts = <1 2>; + }; + L0: interrupt-controller@c000000 { + #interrupt-cells = <1>; + compatible = "riscv,plic0"; + interrupt-controller; + interrupts-extended = <&L3 11 &L3 9>; + reg = <0xc000000 0x4000000>; + reg-names = "control"; + riscv,max-priority = <7>; + riscv,ndev = <3>; + }; + L7: mmio-port-axi4@60000000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + ranges = <0x60000000 0x60000000 0x20000000>; + + serial0: serial@60000000 { + compatible = "xlnx,xps-uartlite-1.00.a"; + reg = <0x0 0x6000000 0x1000>; + interrupt-parent = <&L10>; + interrupts = <1>; + }; + + serial_net: serial@60010000 { + compatible = "xlnx,xps-uartlite-1.00.a"; + reg = <0x0 0x60010000 0x1000>; + interrupt-parent = <&L10>; + interrupts = <2>; + }; + }; + L9: rom@10000 { + compatible = "sifive,rom0"; + reg = <0x10000 0x10000>; + reg-names = "mem"; + }; + }; +}; \ No newline at end of file diff --git a/kernel/src/arch/riscv32/board/rocket_chip/linker.ld b/kernel/src/arch/riscv32/board/rocket_chip/linker.ld new file mode 100644 index 0000000..ba9d08a --- /dev/null +++ b/kernel/src/arch/riscv32/board/rocket_chip/linker.ld @@ -0,0 +1,50 @@ +/* Copy from bbl-ucore : https://ring00.github.io/bbl-ucore */ + +/* Simple linker script for the ucore kernel. + See the GNU ld 'info' manual ("info ld") to learn the syntax. */ + +OUTPUT_ARCH(riscv) +ENTRY(_start) + +BASE_ADDRESS = 0xffffffffc0200000; + +SECTIONS +{ + /* Load the kernel at this address: "." means the current address */ + . = BASE_ADDRESS; + start = .; + + .text : { + stext = .; + *(.text.entry) + *(.text .text.*) + . = ALIGN(4K); + etext = .; + } + + .rodata : { + srodata = .; + *(.rodata .rodata.*) + *(.dtb) + . = ALIGN(4K); + erodata = .; + } + + .data : { + sdata = .; + *(.data .data.*) + edata = .; + } + + .stack : { + *(.bss.stack) + } + + .bss : { + sbss = .; + *(.bss .bss.*) + ebss = .; + } + + PROVIDE(end = .); +} diff --git a/kernel/src/arch/riscv32/board/rocket_chip/mod.rs b/kernel/src/arch/riscv32/board/rocket_chip/mod.rs new file mode 100644 index 0000000..0e2ac03 --- /dev/null +++ b/kernel/src/arch/riscv32/board/rocket_chip/mod.rs @@ -0,0 +1,18 @@ +use super::consts::KERNEL_OFFSET; + +/// Mask all external interrupt except serial. +pub unsafe fn init_external_interrupt() { + const HART0_S_MODE_INTERRUPT_ENABLES: *mut u64 = (KERNEL_OFFSET + 0x0C00_2080) as *mut u64; + HART0_S_MODE_INTERRUPT_ENABLES.write_volatile(0xf); +} + +/// Claim and complete external interrupt by reading and writing to +/// PLIC Interrupt Claim/Complete Register. +pub unsafe fn handle_external_interrupt() { + const HART0_S_MODE_INTERRUPT_CLAIM_COMPLETE: *mut u32 = + (KERNEL_OFFSET + 0x0C20_2000) as *mut u32; + // claim + let source = HART0_S_MODE_INTERRUPT_CLAIM_COMPLETE.read_volatile(); + // complete + HART0_S_MODE_INTERRUPT_CLAIM_COMPLETE.write_volatile(source); +} \ No newline at end of file diff --git a/kernel/src/arch/riscv32/memory.rs b/kernel/src/arch/riscv32/memory.rs index 314c7f2..04a3388 100644 --- a/kernel/src/arch/riscv32/memory.rs +++ b/kernel/src/arch/riscv32/memory.rs @@ -92,7 +92,7 @@ fn remap_the_kernel(dtb: usize) { Linear::new(offset), "bss", ); - // TODO: dtb on rocket chip + // dtb on rocket chip is embedded into kernel #[cfg(not(feature = "board_rocket_chip"))] ms.push( dtb, diff --git a/kernel/src/arch/riscv32/mod.rs b/kernel/src/arch/riscv32/mod.rs index 75b7ccc..e34c2ea 100644 --- a/kernel/src/arch/riscv32/mod.rs +++ b/kernel/src/arch/riscv32/mod.rs @@ -1,7 +1,10 @@ #[cfg(feature = "board_u540")] #[path = "board/u540/mod.rs"] mod board; -#[cfg(not(feature = "board_u540"))] +#[cfg(feature = "board_rocket_chip")] +#[path = "board/rocket_chip/mod.rs"] +mod board; +#[cfg(not(any(feature = "board_u540", feature = "board_rocket_chip")))] #[path = "board/virt/mod.rs"] mod board; @@ -23,10 +26,20 @@ use log::*; #[no_mangle] pub extern "C" fn rust_main(hartid: usize, device_tree_paddr: usize) -> ! { - let device_tree_vaddr = device_tree_paddr - MEMORY_OFFSET + KERNEL_OFFSET; + let mut device_tree_vaddr = device_tree_paddr - MEMORY_OFFSET + KERNEL_OFFSET; unsafe { cpu::set_cpu_id(hartid); + + } + + #[cfg(feature = "board_rocket_chip")] + { + extern "C" { + fn _dtb_start(); + fn _dtb_end(); + } + device_tree_vaddr = _dtb_start as usize; } if hartid != BOOT_HART_ID { @@ -53,7 +66,7 @@ pub extern "C" fn rust_main(hartid: usize, device_tree_paddr: usize) -> ! { memory::init(device_tree_vaddr); timer::init(); // FIXME: init driver on u540 - #[cfg(not(any(feature = "board_u540", feature = "board_rocket_chip")))] + #[cfg(not(any(feature = "board_u540")))] crate::drivers::init(device_tree_vaddr); #[cfg(not(feature = "board_k210"))] unsafe { @@ -115,3 +128,5 @@ global_asm!(include_str!("boot/entry64.asm")); #[cfg(feature = "board_k210")] global_asm!(include_str!("boot/entry_k210.asm")); global_asm!(include_str!("boot/trap.asm")); +#[cfg(feature = "board_rocket_chip")] +global_asm!(include_str!("boot/dtb.gen.s"));