From 1c1c541f0e66e2c668d2e26f45d64a39ee585b9d Mon Sep 17 00:00:00 2001 From: Ivan Tan Date: Sat, 2 Dec 2023 18:52:54 +0800 Subject: [PATCH] bringup raspi3b+, add device memory, disable uart init --- src/arch/aarch64/device/irqchip/gic.rs | 4 +- .../aarch64/device/irqchip/irq_bcm2835.rs | 2 +- .../aarch64/device/irqchip/irq_bcm2836.rs | 2 +- src/arch/aarch64/device/serial.rs | 4 +- src/arch/aarch64/init/device_tree/mod.rs | 67 ++++++++++++++++++- src/arch/aarch64/rmm.rs | 27 +++++++- src/arch/aarch64/start.rs | 16 +++-- 7 files changed, 108 insertions(+), 14 deletions(-) diff --git a/src/arch/aarch64/device/irqchip/gic.rs b/src/arch/aarch64/device/irqchip/gic.rs index 570f06315a..e19669e7f5 100644 --- a/src/arch/aarch64/device/irqchip/gic.rs +++ b/src/arch/aarch64/device/irqchip/gic.rs @@ -85,9 +85,9 @@ impl InterruptController for GenericInterruptController { //TODO: do kernel memory map using node.ranges // Map in the Distributor interface - io_mmap(dist_addr, dist_size); + //io_mmap(dist_addr, dist_size); // Map in CPU0's interface - io_mmap(cpu_addr, cpu_size); + //io_mmap(cpu_addr, cpu_size); self.gic_cpu_if.init(crate::PHYS_OFFSET + cpu_addr); self.gic_dist_if.init(crate::PHYS_OFFSET + dist_addr); diff --git a/src/arch/aarch64/device/irqchip/irq_bcm2835.rs b/src/arch/aarch64/device/irqchip/irq_bcm2835.rs index 522814953d..761b3b4e16 100644 --- a/src/arch/aarch64/device/irqchip/irq_bcm2835.rs +++ b/src/arch/aarch64/device/irqchip/irq_bcm2835.rs @@ -132,7 +132,7 @@ impl InterruptController for Bcm2835ArmInterruptController { Err(_) => return Err(Error::new(EINVAL)), }; unsafe { - io_mmap(base, size); + //io_mmap(base, size); self.address = base + crate::PHYS_OFFSET; diff --git a/src/arch/aarch64/device/irqchip/irq_bcm2836.rs b/src/arch/aarch64/device/irqchip/irq_bcm2836.rs index d9e135d91e..0e2e6b3bc7 100644 --- a/src/arch/aarch64/device/irqchip/irq_bcm2836.rs +++ b/src/arch/aarch64/device/irqchip/irq_bcm2836.rs @@ -116,7 +116,7 @@ impl InterruptController for Bcm2836ArmInterruptController { Err(_) => return Err(Error::new(EINVAL)), }; unsafe { - io_mmap(base, size); + //io_mmap(base, size); self.address = base + crate::PHYS_OFFSET; let mut cpuid: usize = 0; diff --git a/src/arch/aarch64/device/serial.rs b/src/arch/aarch64/device/serial.rs index 7b22a109e5..3347961c66 100644 --- a/src/arch/aarch64/device/serial.rs +++ b/src/arch/aarch64/device/serial.rs @@ -35,7 +35,7 @@ pub unsafe fn init_early(dtb_base: usize, dtb_size: usize) { let virt = crate::PHYS_OFFSET + phys; { let mut serial_port = SerialPort::new(virt); - serial_port.init(false); + //serial_port.init(false); *COM1.lock() = Some(serial_port); } println!("UART at {:X}", virt); @@ -46,7 +46,7 @@ pub unsafe fn init() { println!("test 1"); if let Some(ref mut serial_port) = *COM1.lock() { serial_port.receive(); - serial_port.init(true); + //serial_port.init(true); } println!("test 2"); let data = DTB_BINARY.get().unwrap(); diff --git a/src/arch/aarch64/init/device_tree/mod.rs b/src/arch/aarch64/init/device_tree/mod.rs index 50cea53ab7..6f3248b80e 100644 --- a/src/arch/aarch64/init/device_tree/mod.rs +++ b/src/arch/aarch64/init/device_tree/mod.rs @@ -79,6 +79,65 @@ fn memory_ranges(dt: &fdt::DeviceTree, address_cells: usize, size_cells: usize, index } +fn dev_memory_ranges(dt: &fdt::DeviceTree, address_cells: usize, size_cells: usize, ranges: &mut [(usize, usize); 10]) -> usize { + + //work around for qemu-arm64 + // dev mem: 128MB - 1GB, see https://github.com/qemu/qemu/blob/master/hw/arm/virt.c for details + let root_node = dt.nodes().nth(0).unwrap(); + let model = root_node.properties().find(|p| p.name.contains("model")).unwrap(); + let model_str = core::str::from_utf8(model.data).unwrap(); + if model_str.contains("linux,dummy-virt") { + ranges[0] = (0x08000000, 0x08000000); + ranges[1] = (0x10000000, 0x30000000); + return 2; + } + + let (memory_node, _memory_cells) = dt.find_node("/soc").unwrap(); + let reg = memory_node.properties().find(|p| p.name.contains("ranges")).unwrap(); + let chunk_sz = (address_cells * 2 + size_cells) * 4; + let chunk_count = (reg.data.len() / chunk_sz); + let mut index = 0; + for chunk in reg.data.chunks(chunk_sz as usize) { + if index == chunk_count { + return index; + } + let child_bus_addr = { + if address_cells == 1 { + BE::read_u32(&chunk[0..4]) as u64 + } else if address_cells == 2 { + BE::read_u64(&chunk[0..8]) + } else { + return 0; + } + }; + + let parent_bus_addr = { + if address_cells == 1 { + BE::read_u32(&chunk[4..8]) as u64 + } else if address_cells == 2 { + BE::read_u64(&chunk[8..16]) + } else { + return 0; + } + }; + + let addr_size = { + if address_cells == 1 { + BE::read_u32(&chunk[8..12]) as u64 + } else if address_cells == 2 { + BE::read_u64(&chunk[16..24]) + } else { + return 0; + } + }; + println!("dev mem 0x{:08x} 0x{:08x} 0x{:08x}", child_bus_addr, parent_bus_addr, addr_size); + + ranges[index] = (parent_bus_addr as usize, addr_size as usize); + index += 1; + } + index +} + pub fn diag_uart_range(dtb_base: usize, dtb_size: usize) -> Option<(usize, usize)> { let data = unsafe { slice::from_raw_parts(dtb_base as *const u8, dtb_size) }; let dt = fdt::DeviceTree::new(data).unwrap(); @@ -156,15 +215,17 @@ pub fn fill_memory_map(dtb_base: usize, dtb_size: usize) { let (address_cells, size_cells) = root_cell_sz(&dt).unwrap(); let mut ranges: [(usize, usize); 10] = [(0,0); 10]; - let nranges = memory_ranges(&dt, address_cells as usize, size_cells as usize, &mut ranges); + //in uefi boot mode, ignore memory node, just read the device memory range + //let nranges = memory_ranges(&dt, address_cells as usize, size_cells as usize, &mut ranges); + let nranges = dev_memory_ranges(&dt, address_cells as usize, size_cells as usize, &mut ranges); - for index in (0..nranges) { + for index in 0..nranges { let (base, size) = ranges[index]; unsafe { MEMORY_MAP[index] = MemoryArea { base_addr: base as u64, length: size as u64, - _type: 1, + _type: 2, acpi: 0, }; } diff --git a/src/arch/aarch64/rmm.rs b/src/arch/aarch64/rmm.rs index 0adbbd306d..5c1aab6ddf 100644 --- a/src/arch/aarch64/rmm.rs +++ b/src/arch/aarch64/rmm.rs @@ -22,7 +22,7 @@ use rmm::{ }; use spin::Mutex; -use crate::LogicalCpuId; +use crate::{LogicalCpuId, init::device_tree::MEMORY_MAP}; use super::CurrentRmmArch as RmmA; @@ -160,6 +160,7 @@ unsafe fn inner( identity_map(initfs_base, initfs_size_aligned); //TODO: this is another hack to map our UART + /* match crate::device::serial::COM1.lock().as_ref().map(|x| x.base()) { Some(serial_base) => { let flush = mapper.map_phys( @@ -171,6 +172,30 @@ unsafe fn inner( }, None => (), } + */ + + //map dev mem + for mem in MEMORY_MAP { + if mem._type == 2 { + let size_aligned = ((mem.length as usize + (A::PAGE_SIZE - 1))/A::PAGE_SIZE) * A::PAGE_SIZE; + let base = mem.base_addr as usize; + for i in 0..size_aligned / A::PAGE_SIZE { + let phys = PhysicalAddress::new(base + i * A::PAGE_SIZE); + let virt = A::phys_to_virt(phys); + // use the same mair_el1 value with bootloader, + // mair_el1 == 0x00000000000044FF + // set mem_attr == device memory + let flags = page_flags::(virt) + .custom_flag(2 << 2, true); + let flush = mapper.map_phys( + virt, + phys, + flags + ).expect("failed to map frame"); + flush.ignore(); // Not the active table + } + } + } // Ensure graphical debug region remains paged #[cfg(feature = "graphical_debug")] diff --git a/src/arch/aarch64/start.rs b/src/arch/aarch64/start.rs index 80432a2218..33de19e35f 100644 --- a/src/arch/aarch64/start.rs +++ b/src/arch/aarch64/start.rs @@ -56,6 +56,7 @@ pub unsafe extern "C" fn kstart(args_ptr: *const KernelArgs) -> ! { let bootstrap = { let args = &*args_ptr; + /* // BSS should already be zero { assert_eq!(BSS_TEST_ZERO, 0); @@ -65,17 +66,21 @@ pub unsafe extern "C" fn kstart(args_ptr: *const KernelArgs) -> ! { KERNEL_BASE.store(args.kernel_base, Ordering::SeqCst); KERNEL_SIZE.store(args.kernel_size, Ordering::SeqCst); + */ if args.dtb_base != 0 { // Try to find serial port prior to logging device::serial::init_early(crate::PHYS_OFFSET + args.dtb_base, args.dtb_size); } + KERNEL_BASE.store(args.kernel_base, Ordering::SeqCst); + KERNEL_SIZE.store(args.kernel_size, Ordering::SeqCst); + // Convert env to slice - let env = slice::from_raw_parts((args.env_base + crate::PHYS_OFFSET) as *const u8, args.env_size); + let env = slice::from_raw_parts((args.env_base) as *const u8, args.env_size); // Set up graphical debug #[cfg(feature = "graphical_debug")] - graphical_debug::init(env); + //graphical_debug::init(env); // Initialize logger log::init_logger(|r| { @@ -107,9 +112,12 @@ pub unsafe extern "C" fn kstart(args_ptr: *const KernelArgs) -> ! { tmp = out(reg) _, ); - /* NOT USED WITH UEFI - device_tree::fill_memory_map(crate::PHYS_OFFSET + dtb_base, dtb_size); + if args.dtb_base != 0 { + //Try to read device memory map + device_tree::fill_memory_map(crate::PHYS_OFFSET + args.dtb_base, args.dtb_size); + } + /* NOT USED WITH UEFI let env_size = device_tree::fill_env_data(crate::PHYS_OFFSET + dtb_base, dtb_size, env_base); */