This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

fvp: configuring gicv3 for operation in el1ns

I am trying to program FVP_Base_RevC-2xAEMv8A (el0, el1 and el3 implemented).

The bare-metal program (@ cpu0) runs at el3, and configures the gic and the system counter registers as shown below:

icc_sre_el3 = 0xf;
icc_ctlr_el3.pmhe = 1;
icc_ctlr_el3.eoimode_el1ns = 1;
gicr_igroupr0 = 0xffffffff;
cntfrq_el0 = refclk.cntcontrol;
cntcr.enable = 1;

Then, it switches to el1ns(t) and configures the gic:

gicd_ctlr.egrp1a = 1;
gicd_ctlr.are_ns = 1;
wait-for-gicr-waker-children-asleep-to-be-off;
icc_sre_el1.sre = 1;
icc_pmr_el1 = 0xff; /* To the implemented lowest priority. */
icc_brp1_el1 = icc_brp0_el1 + 1;
icc_ctlr_el1.eoimode = 1;
icc_ctlr_el1.pmhe = 1;
icc_igrpen1_el1.enable = 1;
gicr_ipriority7 = 0 << 16; /* ppi offset 14 == cntpnsirq  */
gicr_icfgr1 = 2 << 28; /* edge-triggered */
daif.i = 0;
gicr_isenabler0 = 1 << 30 ; /* irqid 30 == ppi off 14 == cntpnsirq */

Now it configures the timer registers:

cntp_tval_el0 = 1;  /* some timeout. */
cntp_ctl_el0.enable = 1;
wait-for-cntp-ctl-el0-istatus-1; /* LOOP0 */
print gicr_icpendr0
print gicr_icactiver0

The timer does fire, but I was expecting the CPU to jump to the irq vector. But the program exits LOOP0 and prints gicr_icpendr0 (where the irq is indeed shown as pending) and gicr_icactiver0 (where the irq is not shown as active).

I was expecting that when the timer fires, the CPU will attempt to fetch instructions from the table. Since VBAR = 0, the addresses the CPU will access belong to the trusted ROM. From el1ns such access should cause aborts over and over again, and the LCD panel of the FVP output must show an ever increasing number of instructions executed (which is how I usually detect that something went wrong). Instead, the CPU continues running under the same context, exits LOOP0, prints the registers, and halts at wfi() (not shown here).

The same sequence of instructions works on QEMU's gicv3 implementation. QEMU shows the IRQ as firing after the specified timeout, and the abort experienced when the CPU tries to fetch instructions at VBAR + 0x80. I believe that QEMU's implementation may not be as strict as that found in the FVP.

Is my expectation around FVP's behaviour correct? If so, what step am I missing?

Thank you,

Amol

Parents
  • I missed the fact that when ds == 0, gicr_waker is a secure register; it is raz/wi to el1ns. But I was trying to configure it from within el1ns.

    After moving gicr_waker configuration to el3, the expected interrupt does arrive.

Reply
  • I missed the fact that when ds == 0, gicr_waker is a secure register; it is raz/wi to el1ns. But I was trying to configure it from within el1ns.

    After moving gicr_waker configuration to el3, the expected interrupt does arrive.

Children
No data