RE: [EXTERNAL] Re: enabling same PPI interrupt to all CPU in ARM64 SMP

From: Souradeep Chakrabarti <schakrabarti_at_microsoft.com>
Date: Sun, 14 May 2023 14:59:29 UTC


>-----Original Message-----
>From: Kyle Evans <kevans@freebsd.org>
>Sent: Friday, May 12, 2023 10:40 PM
>To: Souradeep Chakrabarti <schakrabarti@microsoft.com>
>Cc: Wei Hu <weh@microsoft.com>; freebsd-hackers@FreeBSD.org
>Subject: [EXTERNAL] Re: enabling same PPI interrupt to all CPU in ARM64 SMP
>
>On Fri, May 12, 2023 at 9:51 AM Souradeep Chakrabarti
><schakrabarti@microsoft.com> wrote:
>>
>>
>>
>>
>> >-----Original Message-----
>> >From: Souradeep Chakrabarti
>> >Sent: Monday, May 8, 2023 6:39 PM
>> >To: Kyle Evans <kevans@freebsd.org>
>> >Cc: Wei Hu <weh@microsoft.com>; freebsd-hackers@FreeBSD.org
>> >Subject: enabling same PPI interrupt to all CPU in ARM64 SMP
>> >
>> >Hi ,
>> >
>> >While using SMP in ARM64 Hyper-V we are getting stuck in boot if
>> >there is a interrupt for VMBus coming to CPU1 and VMBus interrupt
>> >handler is not getting that interrupt.
>> >
>> >In ARM64 Hyper-V we are using IRQ18 for VMBus and it is a PPI interrupt.
>> >
>> >But Hypev-V host sends interrupt to this IRQ 18 for both CPU0 and
>> >CPU1 in 2CPU system.
>> >This is based on the corresponding VMBus channel which assigned with the CPU.
>> >
>> >Now VMBus ISR is getting the interrupt in CPU0 but not getting from CPU1.
>> >Any idea, how we can use the same PPI 18 for all the CPU cores?
>> >
>> >Any help will be appreciated, as this is blocking the enablement of
>> >FreeBSD in Azure ARM64.
>> [Souradeep]
>> Can someone please help me it.
>>
>
>Looking at least at the GIC implementation, it looks like this is a known limitation:
>
> 875         /*
> 876          * XXX - In case that per CPU interrupt is going to be
>enabled in time
> 877          *       when SMP is already started, we need some IPI
>call which
> 878          *       enables it on others CPUs. Further, it's more
>complicated as
> 879          *       pic_enable_source() and pic_disable_source()
>should act on
> 880          *       per CPU basis only. Thus, it should be solved
>here somehow.
> 881          */
> 882         if (isrc->isrc_flags & INTR_ISRCF_PPI)
> 883                 CPU_SET(PCPU_GET(cpuid), &isrc->isrc_cpu);
>
>I think we need something /like/ this:
>https://people.fr/
>eebsd.org%2F~kevans%2Fppi.diff&data=05%7C01%7Cschakrabarti%40microsoft.c
>om%7Cc5c3d254b9d841e9ae9b08db530bb3d2%7C72f988bf86f141af91ab2d7c
>d011db47%7C1%7C0%7C638195082027744706%7CUnknown%7CTWFpbGZsb3
>d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D
>%7C3000%7C%7C%7C&sdata=SwoR2vHxh6QQhwpOgFcQ9378nDVovhdEKEXoEo
>gPKsc%3D&reserved=0, though it still has the caveat that PPIs effectively cannot be
>fully setup before SI_SUB_SMP.
>So, it's likely almost a NOP for existing platforms (will emit a warning with
>bootverbose for armv8 timers) but might do the trick for you.
[Souradeep]
Thanks for the change but it did not solve the problem. Still the interrupt handler
vmbus_handle_intr(struct trapframe *trap_frame), is not getting called for the CPU 1.
It is only getting called for CPU 0 all the time in ARM64 but in x86 it is getting called
for both CPU1 and CPU0.
From DDB I have collected this data in arm64. irq18 is for vmbus.
db> show irqs
irq0   <gic0,i0>: cpu 03 (bound) cnt 0
irq1   <gic0,i1>: cpu 03 cnt 0
irq2   <gic0,i2>: cpu 03 cnt 0
irq3   <gic0,i3>: cpu 03 cnt 0
irq4   <gic0,i4>: cpu 03 cnt 0
irq5   <gic0,i5>: cpu 03 cnt 0
irq6   <gic0,i6>: cpu 00 cnt 0
irq7   <gic0,i7>: cpu 00 cnt 0
irq8   <gic0,i8>: cpu 00 cnt 0
irq9   <gic0,i9>: cpu 00 cnt 0
irq10  <gic0,i10>: cpu 00 cnt 0
irq11  <gic0,i11>: cpu 00 cnt 0
irq12  <gic0,i12>: cpu 00 cnt 0
irq13  <gic0,i13>: cpu 00 cnt 0
irq14  <gic0,i14>: cpu 00 cnt 0
irq15  <gic0,i15>: cpu 00 cnt 0
irq16  <gic0,p0>: cpu 00 cnt 0
irq17  <gic0,p1>: cpu 00 cnt 0
irq18  <gic0,p2>: cpu 03 cnt 411
irq19  <gic0,p3>: cpu 00 cnt 0
irq20  <gic0,p4>: cpu 03 cnt 8643


db> show intrcnt
gic0,p2: vmbus0                         411
gic0,p4:-ric_timer0                     8643
cpu1:ast                                18
cpu0:preempt                            239
cpu1:preempt                            526
cpu1:rendezvous                         2
cpu1:stop hard                          1


db> show intr
swi6: task queue (pid 12) {SOFT}
swi6: Giant taskq (pid 12) {SOFT}
swi5: fast taskq (pid 12) {SOFT}
swi1: netisr 0 (pid 12) {SOFT}
gic0,p4:-ric_timer0 (no thread)
gic0,i0: pmu0 pmu0 (no thread)
gic0,s3: acpi_ged0 (pid 12)
gic0,s1: uart0 (no thread)
swi0: uart uart (pid 12) {SOFT}
gic0,s2: uart1 (no thread)
gic0,p2: vmbus0 (no thread)
>
>Thanks,
>
>Kyle Evans