move gic into irqchip module
This commit is contained in:
@@ -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() {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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(())
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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); }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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"),
|
||||
|
||||
Reference in New Issue
Block a user