[IA64] Update check_sal_cache_flush to use platform_send_ipi()

check_sal_cache_flush is used to detect broken firmware that drops
pending interrupts.

The old implementation schedules a timer interrupt for itself in
the future by getting the current value of the Interval Timer
Counter + 1000 cycles, waits for the interrupt to be pended, calls
SAL_CACHE_FLUSH, and finally checks to see if the interrupt is
still pending.

This implementation can cause problems for virtual machine code if
the process of scheduling the timer interrupt takes more than 1000
cycles; the virtual machine can end up sleeping for several hundred
years while waiting for the ITC to wrap around.

The fix is to use platform_send_ipi. The processor will still send
an interrupt to itself, using the IA64_IPI_DM_INT delivery mode,
which causes the IPI to look like an external interrupt. The rest
of the SAL_CACHE_FLUSH + checking to see if the interrupt is still
pending remains unchanged.

This fix has been boot tested successfully on:

- intel tiger2
- hp rx6600
- hp rx5670

The rx5670 has known buggy firmware, where SAL_CACHE_FLUSH drops
pending interrupts. A boot test on this machine showed this message
on the console:

SAL: SAL_CACHE_FLUSH drops interrupts; PAL_CACHE_FLUSH will be used instead

Which proves that the self-inflicted IPI approach is viable. And
as expected, the other tested platforms correctly did not display
the warning.

Signed-off-by: Alex Chiang <achiang@hp.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>

authored by Alex Chiang and committed by Tony Luck 3463a93d 83014699

+3 -4
+3 -4
arch/ia64/kernel/sal.c
··· 252 local_irq_save(flags); 253 254 /* 255 - * Schedule a timer interrupt, wait until it's reported, and see if 256 - * SAL_CACHE_FLUSH drops it. 257 */ 258 - ia64_set_itv(IA64_TIMER_VECTOR); 259 - ia64_set_itm(ia64_get_itc() + 1000); 260 261 while (!ia64_get_irr(IA64_TIMER_VECTOR)) 262 cpu_relax();
··· 252 local_irq_save(flags); 253 254 /* 255 + * Send ourselves a timer interrupt, wait until it's reported, and see 256 + * if SAL_CACHE_FLUSH drops it. 257 */ 258 + platform_send_ipi(cpu, IA64_TIMER_VECTOR, IA64_IPI_DM_INT, 0); 259 260 while (!ia64_get_irr(IA64_TIMER_VECTOR)) 261 cpu_relax();