From b65a7e9103fce41b5c0ba7710bce0734bed98625 Mon Sep 17 00:00:00 2001 From: Ivan Tan Date: Fri, 22 Sep 2023 11:06:04 +0800 Subject: [PATCH] move gic into irqchip module --- src/arch/aarch64/device/generic_timer.rs | 11 +- src/arch/aarch64/device/gic.rs | 189 ----------------------- src/arch/aarch64/device/irqchip/gic.rs | 8 +- src/arch/aarch64/device/irqchip/mod.rs | 25 +-- src/arch/aarch64/device/mod.rs | 3 +- src/arch/aarch64/device/serial.rs | 4 - src/arch/aarch64/device/uart_pl011.rs | 4 +- src/arch/aarch64/interrupt/irq.rs | 10 +- 8 files changed, 33 insertions(+), 221 deletions(-) delete mode 100644 src/arch/aarch64/device/gic.rs diff --git a/src/arch/aarch64/device/generic_timer.rs b/src/arch/aarch64/device/generic_timer.rs index d8e6b6b9dd..6fb9189cce 100644 --- a/src/arch/aarch64/device/generic_timer.rs +++ b/src/arch/aarch64/device/generic_timer.rs @@ -1,4 +1,4 @@ -use crate::arch::device::gic; +use crate::arch::device::irqchip::IRQ_CHIP; use crate::device::cpu::registers::{control_regs}; bitflags! { @@ -36,7 +36,7 @@ pub struct GenericTimer { impl GenericTimer { pub fn init(&mut self) { let clk_freq = unsafe { control_regs::cntfreq_el0() }; - self.clk_freq = clk_freq;; + self.clk_freq = clk_freq; self.reload_count = clk_freq / 100; unsafe { control_regs::tmr_tval_write(self.reload_count) }; @@ -44,9 +44,10 @@ impl GenericTimer { let mut ctrl = TimerCtrlFlags::from_bits_truncate(unsafe { control_regs::tmr_ctrl() }); ctrl.insert(TimerCtrlFlags::ENABLE); ctrl.remove(TimerCtrlFlags::IMASK); - unsafe { control_regs::tmr_ctrl_write(ctrl.bits()) }; - - gic::irq_enable(30); + unsafe { + control_regs::tmr_ctrl_write(ctrl.bits()); + IRQ_CHIP.irq_enable(30); + } } fn disable() { diff --git a/src/arch/aarch64/device/gic.rs b/src/arch/aarch64/device/gic.rs deleted file mode 100644 index 04a383cd3a..0000000000 --- a/src/arch/aarch64/device/gic.rs +++ /dev/null @@ -1,189 +0,0 @@ -use core::ptr::{read_volatile, write_volatile}; - -use crate::memory::Frame; -use crate::paging::{KernelMapper, PhysicalAddress, Page, PageFlags, TableKind, VirtualAddress}; - -static GICD_CTLR: u32 = 0x000; -static GICD_TYPER: u32 = 0x004; -static GICD_ISENABLER: u32 = 0x100; -static GICD_ICENABLER: u32 = 0x180; -static GICD_IPRIORITY: u32 = 0x400; -static GICD_ITARGETSR: u32 = 0x800; -static GICD_ICFGR: u32 = 0xc00; - -static GICC_EOIR: u32 = 0x0010; -static GICC_IAR: u32 = 0x000c; -static GICC_CTLR: u32 = 0x0000; -static GICC_PMR: u32 = 0x0004; - -static mut GIC_DIST_IF: GicDistIf = GicDistIf { - address: 0, - ncpus: 0, - nirqs: 0, -}; - -static mut GIC_CPU_IF: GicCpuIf = GicCpuIf { - address: 0, -}; - -pub unsafe fn init() { - GIC_DIST_IF.init(); - GIC_CPU_IF.init(); -} - -pub fn irq_enable(irq_num: u32) { - unsafe { GIC_DIST_IF.irq_enable(irq_num) }; -} - -pub fn irq_disable(irq_num: u32) { - unsafe { GIC_DIST_IF.irq_disable(irq_num) }; -} - -pub unsafe fn irq_ack() -> u32 { - GIC_CPU_IF.irq_ack() -} - -pub unsafe fn irq_eoi(irq_num: u32) { - GIC_CPU_IF.irq_eoi(irq_num); -} - -pub struct GicDistIf { - pub address: usize, - pub ncpus: u32, - pub nirqs: u32, -} - -impl GicDistIf { - unsafe fn init(&mut self) { - // Map in the Distributor interface - let mut mapper = KernelMapper::lock(); - - let start_frame = Frame::containing_address(PhysicalAddress::new(0x08000000)); - let end_frame = Frame::containing_address(PhysicalAddress::new(0x08000000 + 0x10000 - 1)); - for frame in Frame::range_inclusive(start_frame, end_frame) { - let page = Page::containing_address(VirtualAddress::new(frame.start_address().data() + crate::PHYS_OFFSET)); - mapper - .get_mut() - .expect("failed to access KernelMapper for mapping GIC distributor") - .map_phys(page.start_address(), frame.start_address(), PageFlags::new().write(true)) - .expect("failed to map GIC distributor") - .flush(); - } - - self.address = crate::PHYS_OFFSET + 0x08000000; - - // Map in CPU0's interface - let start_frame = Frame::containing_address(PhysicalAddress::new(0x08010000)); - let end_frame = Frame::containing_address(PhysicalAddress::new(0x08010000 + 0x10000 - 1)); - for frame in Frame::range_inclusive(start_frame, end_frame) { - let page = Page::containing_address(VirtualAddress::new(frame.start_address().data() + crate::PHYS_OFFSET)); - mapper - .get_mut() - .expect("failed to access KernelMapper for mapping GIC interface") - .map_phys(page.start_address(), frame.start_address(), PageFlags::new().write(true)) - .expect("failed to map GIC interface") - .flush(); - } - - GIC_CPU_IF.address = crate::PHYS_OFFSET + 0x08010000; - - // Disable IRQ Distribution - self.write(GICD_CTLR, 0); - - let typer = self.read(GICD_TYPER); - self.ncpus = ((typer & (0x7 << 5)) >> 5) + 1; - self.nirqs = ((typer & 0x1f) + 1) * 32; - println!("gic: Distributor supports {:?} CPUs and {:?} IRQs", self.ncpus, self.nirqs); - - // Set all SPIs to level triggered - for irq in (32..self.nirqs).step_by(16) { - self.write(GICD_ICFGR + ((irq / 16) * 4), 0); - } - - // Disable all SPIs - for irq in (32..self.nirqs).step_by(32) { - self.write(GICD_ICENABLER + ((irq / 32) * 4), 0xffff_ffff); - } - - // Affine all SPIs to CPU0 and set priorities for all IRQs - for irq in 0..self.nirqs { - if irq > 31 { - let ext_offset = GICD_ITARGETSR + (4 * (irq / 4)); - let int_offset = irq % 4; - let mut val = self.read(ext_offset); - val |= 0b0000_0001 << (8 * int_offset); - self.write(ext_offset, val); - } - - let ext_offset = GICD_IPRIORITY + (4 * (irq / 4)); - let int_offset = irq % 4; - let mut val = self.read(ext_offset); - val |= 0b0000_0000 << (8 * int_offset); - self.write(ext_offset, val); - } - - // Enable CPU0's GIC interface - GIC_CPU_IF.write(GICC_CTLR, 1); - - // Set CPU0's Interrupt Priority Mask - GIC_CPU_IF.write(GICC_PMR, 0xff); - - // Enable IRQ distribution - self.write(GICD_CTLR, 0x1); - } - - unsafe fn irq_enable(&mut self, irq: u32) { - let offset = GICD_ISENABLER + (4 * (irq / 32)); - let shift = 1 << (irq % 32); - let mut val = self.read(offset); - val |= shift; - self.write(offset, val); - } - - unsafe fn irq_disable(&mut self, irq: u32) { - let offset = GICD_ICENABLER + (4 * (irq / 32)); - let shift = 1 << (irq % 32); - let mut val = self.read(offset); - val |= shift; - self.write(offset, val); - } - - unsafe fn read(&self, reg: u32) -> u32 { - let val = read_volatile((self.address + reg as usize) as *const u32); - val - } - - unsafe fn write(&mut self, reg: u32, value: u32) { - write_volatile((self.address + reg as usize) as *mut u32, value); - } -} - -pub struct GicCpuIf { - pub address: usize, -} - -impl GicCpuIf { - unsafe fn init(&mut self) { - } - - unsafe fn irq_ack(&mut self) -> u32 { - let irq = self.read(GICC_IAR) & 0x1ff; - if irq == 1023 { - panic!("irq_ack: got ID 1023!!!"); - } - irq - } - - unsafe fn irq_eoi(&mut self, irq: u32) { - self.write(GICC_EOIR, irq); - } - - unsafe fn read(&self, reg: u32) -> u32 { - let val = read_volatile((self.address + reg as usize) as *const u32); - val - } - - unsafe fn write(&mut self, reg: u32, value: u32) { - write_volatile((self.address + reg as usize) as *mut u32, value); - } -} diff --git a/src/arch/aarch64/device/irqchip/gic.rs b/src/arch/aarch64/device/irqchip/gic.rs index d92325203d..3319d3d6eb 100644 --- a/src/arch/aarch64/device/irqchip/gic.rs +++ b/src/arch/aarch64/device/irqchip/gic.rs @@ -63,13 +63,13 @@ impl InterruptController for GenericInterruptController { // Map in CPU0's interface io_mmap(cpu_addr, cpu_size); - self.gic_cpu_if.init(cpu_addr); - self.gic_dist_if.init(dist_addr); + self.gic_cpu_if.init(crate::PHYS_OFFSET + cpu_addr); + self.gic_dist_if.init(crate::PHYS_OFFSET + dist_addr); // Enable CPU0's GIC interface - self.gic_dist_if.write(GICC_CTLR, 1); + self.gic_cpu_if.write(GICC_CTLR, 1); // Set CPU0's Interrupt Priority Mask - self.gic_dist_if.write(GICC_PMR, 0xff); + self.gic_cpu_if.write(GICC_PMR, 0xff); } Ok(()) diff --git a/src/arch/aarch64/device/irqchip/mod.rs b/src/arch/aarch64/device/irqchip/mod.rs index 972b3b05df..c65582b65c 100644 --- a/src/arch/aarch64/device/irqchip/mod.rs +++ b/src/arch/aarch64/device/irqchip/mod.rs @@ -4,7 +4,7 @@ use fdt::DeviceTree; mod gic; -trait InterruptController { +pub trait InterruptController { fn irq_init(&mut self, fdt: Option<&DeviceTree>) -> Result<()>; fn irq_ack(&mut self) -> u32; fn irq_eoi(&mut self, irq_num: u32); @@ -12,33 +12,38 @@ trait InterruptController { fn irq_disable(&mut self, irq_num: u32); } -struct IrqChipCore { +pub struct IrqChipCore { //TODO: support multi level interrupt constrollers - ic: Vec>, - main_ic_idx: usize, + pub ic: Vec>, + pub ic_idx: usize, } impl IrqChipCore { pub fn irq_ack(&mut self) -> u32 { - self.ic[self.main_ic_idx].irq_ack() + self.ic[self.ic_idx].irq_ack() } pub fn irq_eoi(&mut self, irq_num: u32) { - self.ic[self.main_ic_idx].irq_eoi(irq_num) + self.ic[self.ic_idx].irq_eoi(irq_num) } pub fn irq_enable(&mut self, irq_num: u32) { - self.ic[self.main_ic_idx].irq_enable(irq_num) + self.ic[self.ic_idx].irq_enable(irq_num) } pub fn irq_disable(&mut self, irq_num: u32) { - self.ic[self.main_ic_idx].irq_disable(irq_num) + self.ic[self.ic_idx].irq_disable(irq_num) } } -static IRQ_CHIP = IrqChipCore { ic: Vec::new(), main_ic_idx: 0 }; +pub static mut IRQ_CHIP: IrqChipCore = IrqChipCore { ic: Vec::new(), ic_idx: 0 }; pub fn init(fdt: Option<&DeviceTree>) { let ic = Box::new(gic::GenericInterruptController::new()); - let irq_chip_core = IrqChipCore { ic }; + unsafe { + IRQ_CHIP.ic.push(ic); + for ic in IRQ_CHIP.ic.iter_mut() { + ic.irq_init(fdt).unwrap(); + } + } } diff --git a/src/arch/aarch64/device/mod.rs b/src/arch/aarch64/device/mod.rs index 343f3f5496..86c1d7a830 100644 --- a/src/arch/aarch64/device/mod.rs +++ b/src/arch/aarch64/device/mod.rs @@ -2,7 +2,6 @@ use crate::memory::Frame; use crate::paging::{KernelMapper, PhysicalAddress, Page, PageFlags, VirtualAddress}; pub mod cpu; -pub mod gic; pub mod irqchip; pub mod generic_timer; pub mod serial; @@ -11,7 +10,7 @@ pub mod uart_pl011; pub unsafe fn init() { println!("GIC INIT"); - gic::init(); + irqchip::init(None); println!("GIT INIT"); generic_timer::init(); } diff --git a/src/arch/aarch64/device/serial.rs b/src/arch/aarch64/device/serial.rs index 0cac8efa47..12d19e0f8b 100644 --- a/src/arch/aarch64/device/serial.rs +++ b/src/arch/aarch64/device/serial.rs @@ -1,11 +1,7 @@ -use core::sync::atomic::{Ordering}; use spin::Mutex; use crate::device::uart_pl011::SerialPort; use crate::init::device_tree; -use crate::memory::Frame; -use crate::paging::mapper::PageFlushAll; -use crate::paging::{KernelMapper, Page, PageFlags, PhysicalAddress, TableKind, VirtualAddress}; pub static COM1: Mutex> = Mutex::new(None); diff --git a/src/arch/aarch64/device/uart_pl011.rs b/src/arch/aarch64/device/uart_pl011.rs index e5982caa58..3a3b24c8de 100644 --- a/src/arch/aarch64/device/uart_pl011.rs +++ b/src/arch/aarch64/device/uart_pl011.rs @@ -1,7 +1,7 @@ use core::fmt::{self, Write}; use core::ptr; -use crate::device::gic; +use crate::device::irqchip::IRQ_CHIP; use crate::scheme::debug::{debug_input, debug_notify}; bitflags! { @@ -126,7 +126,7 @@ impl SerialPort { self.write_reg(self.intr_clr_reg, 0x7ff); // Enable interrupt at GIC distributor - gic::irq_enable(33); + unsafe { IRQ_CHIP.irq_enable(33); } } } diff --git a/src/arch/aarch64/interrupt/irq.rs b/src/arch/aarch64/interrupt/irq.rs index a11a03edb2..a7d4d18b78 100644 --- a/src/arch/aarch64/interrupt/irq.rs +++ b/src/arch/aarch64/interrupt/irq.rs @@ -3,14 +3,14 @@ use core::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT}; use crate::context; use crate::context::timeout; use crate::device::generic_timer::{GENTIMER}; -use crate::device::{gic}; +use crate::device::irqchip::IRQ_CHIP; use crate::device::serial::{COM1}; use crate::time; use crate::{exception_stack}; exception_stack!(irq_at_el0, |stack| { - match gic::irq_ack() { + match IRQ_CHIP.irq_ack() { 30 => irq_handler_gentimer(30), 33 => irq_handler_com1(33), _ => panic!("irq_demux: unregistered IRQ"), @@ -18,7 +18,7 @@ exception_stack!(irq_at_el0, |stack| { }); exception_stack!(irq_at_el1, |stack| { - match gic::irq_ack() { + match IRQ_CHIP.irq_ack() { 30 => irq_handler_gentimer(30), 33 => irq_handler_com1(33), _ => panic!("irq_demux: unregistered IRQ"), @@ -31,7 +31,7 @@ unsafe fn trigger(irq: u32) { } irq_trigger(irq); - gic::irq_eoi(irq); + IRQ_CHIP.irq_eoi(irq); } pub unsafe fn acknowledge(_irq: usize) { @@ -60,7 +60,7 @@ pub unsafe fn irq_handler_gentimer(irq: u32) { } unsafe fn irq_demux() { - match gic::irq_ack() { + match IRQ_CHIP.irq_ack() { 30 => irq_handler_gentimer(30), 33 => irq_handler_com1(33), _ => panic!("irq_demux: unregistered IRQ"),