arminterruptcpu-registersarmv7cortex-a

Send Inter-Processor Interrupts in Zynq (arm-v7 / cortex-a9)


I am trying to add multiprocessor support for an embedded operating system (DNA-OS) on the Zynq platform in the ZedBoard. The OS is actually flawlessly functional with CPU_0 alone. The OS architecture requires the implementation of a cpu_send_ipi function in order to activate multiprocessing support: Basically, this function would interrupt a processor and give him a new thread to process.

I looked for an IPI register in the ug585 (Technical Reference Manual for Zynq) but couldn't find any.

I tried digging further in the Cortex-A9 spec for an IPI register, and found out that software generated interrupts could be used as IPI.

After adding software interrupt support to my OS, the problem is that CPU_0 can interrupt itself, but cannot interrupt CPU_1 !

PS: for my OS to handle SGIs, I used the register spec from the ug585 in page 1486: SGI Control register

So is there any other special configuration to permit CPUs to interrupt each others? or any other way to implement IPI ?

Regards,


Solution

  • Your reference documentation is a form of the GIC (global interrupt controller). The Cortex-A9 MP cores include an integrated GIC controller. Each CPU includes an Interrupt interface. As well, there is a system wide distributor. In order to receive the IPI (also known as SGI or software generate interrupt), you need to enable the CPU interface to receive the SGI interrupts on the 2nd CPU. This entails several steps,

    1. Configuring the GIC interrupt interface registers on CPU2.
    2. Setting the CP15 vector table for CPU2.
    3. Enabling the CPSR I-bit on CPU2
    4. Possibly setting up some banked PPI distributor registers. note1

    Note1: While most distributor registers are system global, some are banked per CPU as well. For instance, see section 3.3.8. PPI Status Register in the Cortex-A9 MPcore TRM. I don't see any from a cursory investigation, but I would not rule it out.

    Testing that an unused SPI (shared peripheral interrupt) works by handling the vector on CPU2 by setting the GIC distributor GICD_ISPEND register on the CPU1. This should verify that you have steps 2 and 3 covered. You may also need to set the type to ensure that they are interrupts and not FIQ; especially if you have security support. You need to use the GICD_ITARGETSR register to include CPU2.

    GIC reference list

    Especially useful in the Appendix B of the Generic GIC manual. For some reason, ARM likes to keep changing the register names in each and every document they publish.