Hi Eric, On 12/3/20 2:59 PM, Auger Eric wrote: > Hi Alexandru, > On 11/25/20 4:51 PM, Alexandru Elisei wrote: >> The LPI code validates a result similarly to the IPI tests, by checking if >> the target CPU received the interrupt with the expected interrupt number. >> However, the LPI tests invent their own way of checking the test results by >> creating a global struct (lpi_stats), using a separate interrupt handler >> (lpi_handler) and test function (check_lpi_stats). >> >> There are several areas that can be improved in the LPI code, which are >> already covered by the IPI tests: >> >> - check_lpi_stats() doesn't take into account that the target CPU can >> receive the correct interrupt multiple times. >> - check_lpi_stats() doesn't take into the account the scenarios where all >> online CPUs can receive the interrupt, but the target CPU is the last CPU >> that touches lpi_stats.observed. >> - Insufficient or missing memory synchronization. >> >> Instead of duplicating code, let's convert the LPI tests to use >> check_acked() and the same interrupt handler as the IPI tests, which has >> been renamed to irq_handler() to avoid any confusion. >> >> check_lpi_stats() has been replaced with check_acked() which, together with >> using irq_handler(), instantly gives us more correctness checks and proper >> memory synchronization between threads. lpi_stats.expected has been >> replaced by the CPU mask and the expected interrupt number arguments to >> check_acked(), with no change in semantics. >> >> lpi_handler() aborted the test if the interrupt number was not an LPI. This >> was changed in favor of allowing the test to continue, as it will fail in >> check_acked(), but possibly print information useful for debugging. If the >> test receives spurious interrupts, those are reported via report_info() at >> the end of the test for consistency with the IPI tests, which don't treat >> spurious interrupts as critical errors. >> >> In the spirit of code reuse, secondary_lpi_tests() has been replaced with >> ipi_recv() because the two are now identical; ipi_recv() has been renamed >> to irq_recv(), similarly to irq_handler(), to avoid confusion. >> >> CC: Eric Auger <eric.auger@xxxxxxxxxx> >> Signed-off-by: Alexandru Elisei <alexandru.elisei@xxxxxxx> >> --- >> [..] >> @@ -767,13 +700,27 @@ static void test_its_trigger(void) >> >> report_prefix_push("int"); >> >> - lpi_stats_expect(3, 8195); >> + stats_reset(); >> + /* >> + * its_send_int() is missing the synchronization from the GICv3 IPI >> + * trigger functions. >> + */ >> + wmb(); > so don't you want to add it in __its_send_int instead? The memory synchronization in the IPI sender functions make perfect sense, that's how IPIs are used - one CPU kicks the target, the target reads from a shared memory location. I don't think receiving an interrupt from a device is how one would usually expect to do inter-processor communication. However, I did more digging about this ability to trigger interrupts from made-up devices, and it seems to me that this was introduced for testing purposes (please correct me if I'm wrong). With this in mind, I guess it wouldn't be awkward to have the wmb() in its_send_int(), because we are using it just like we would an IPI. And it also reduces the boilerplate code. I'll make the change in the next iteration. Thanks, Alex