Oh my bad, I had misunderstood the memory map of the GIC-400. I neglected the 0x1000 reserved bits at the start, hence the resultant base address just comes down to be the same.
I have a few questions regarding the above approach you have described:
1. Which exception level is the code executing in? I am asking this, because I am not able to perform the write operations into the `cntp_tval_el0` or the `cntp_ctl_el0` registers when in EL1, but can do it successfully in EL2.
2. Looking at the above implementation, I see that you have maintained an array of function pointers to the respective handlers. So a separate initialisation of the vector table is not required for the GIC-400?
3. I tried implementing the same code in C, but I don't seem to get any interrupts raised.
This is my code:
timer_init()GIC functions:All the constants used are verified to be matching with the addresses you have used in your code.
I get interrupt id 1023 (spurious interrupt) when I execute the `dispatch()` function after initialising the GIC, initialising the timer, and then registering the interrupt... I believe this is the case because the reset value of `GIC_C_ACK` (the Interrupt Acknowledge Register) is 0x3FF, and hence seems to be not initialised appropriately.
I have a few questions regarding the above approach you have described:
1. Which exception level is the code executing in? I am asking this, because I am not able to perform the write operations into the `cntp_tval_el0` or the `cntp_ctl_el0` registers when in EL1, but can do it successfully in EL2.
2. Looking at the above implementation, I see that you have maintained an array of function pointers to the respective handlers. So a separate initialisation of the vector table is not required for the GIC-400?
3. I tried implementing the same code in C, but I don't seem to get any interrupts raised.
This is my code:
timer_init()
Code:
.globl timer_inittimer_init: mrs x0, cntfrq_el0 msr cntp_tval_el0, x0 mov x0, #1 msr cntp_ctl_el0, x0 ret
Code:
void gic_init() { for (int i = 0; i < GIC_NUM_IRQ >> 5; i++) { mmio_write_32(GIC_D_DISABLE + 4 * i, 0xffffffff); } mmio_write_32(GIC_C_PRI_MASK, 0xff); for (int i = 0; i < GIC_NUM_IRQ; i++) { mmio_write_32(GIC_D_PRI + 4 * i, 0x7f); } for (int i = 0; i < GIC_NUM_IRQ >> 4; i++) { mmio_write_32(GIC_D_CONFIG + 4 * i, 0x55555555); } for (int i = 0; i < GIC_NUM_IRQ; i++) { if (i < 32) continue; mmio_write_32(GIC_D_TARGET + 4 * i, 0xff); } mmio_write_32(GIC_D_CTLR, 0x1); mmio_write_32(GIC_C_CTLR, 0x1);}void register_irq_handler(unsigned int irq) { unsigned int val = 0x1 << (irq & 0x1f); unsigned int n = irq >> 5; mmio_write_32(GIC_D_ENABLE + 4 * n, val);}void gic_dispatch() { while (1) { unsigned int interrupt_spi = mmio_read_32(GIC_C_ACK); unsigned int interrupt_id = interrupt_spi & 0x3FF; uart_puts("Dispatch Triggered!\n\0"); if (interrupt_id >= GIC_NUM_IRQ) { uart_puts("Spurious interrupt received: \0"); char buff[9] = ""; int_to_str(interrupt_id, buff); uart_puts(buff); uart_putc('\n'); __asm__("msr daifclr, #3\n\t" "wfi\n\t"); continue; } if (interrupt_id == 30) { uart_puts("Timer interrupt received!\n\0"); } else { uart_puts("Unknown interrupt received!\n\0"); } mmio_write_32(GIC_C_EOI, interrupt_spi); }}
I get interrupt id 1023 (spurious interrupt) when I execute the `dispatch()` function after initialising the GIC, initialising the timer, and then registering the interrupt... I believe this is the case because the reset value of `GIC_C_ACK` (the Interrupt Acknowledge Register) is 0x3FF, and hence seems to be not initialised appropriately.
Statistics: Posted by kvp_933 — Mon Jun 10, 2024 9:26 am