move gic into irqchip module

This commit is contained in:
Ivan Tan
2023-09-22 11:06:04 +08:00
committed by Jeremy Soller
parent 01d0e9a4b5
commit b65a7e9103
8 changed files with 33 additions and 221 deletions
+6 -5
View File
@@ -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() {
-189
View File
@@ -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);
}
}
+4 -4
View File
@@ -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(())
+15 -10
View File
@@ -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<Box<dyn InterruptController>>,
main_ic_idx: usize,
pub ic: Vec<Box<dyn InterruptController>>,
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();
}
}
}
+1 -2
View File
@@ -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();
}
-4
View File
@@ -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<Option<SerialPort>> = Mutex::new(None);
+2 -2
View File
@@ -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); }
}
}
+5 -5
View File
@@ -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"),