#include <irq_vectors.h>
#include <xen/kexec.h>
#include <asm/guest.h>
+#include <asm/nmi.h>
#include <asm/time.h>
static bool __read_mostly tdt_enabled;
{
/*
* Check if this is a vectored interrupt (most likely, as this is probably
- * a request to dump local CPU state). Vectored interrupts are ACKed;
- * spurious interrupts are not.
+ * a request to dump local CPU state or to continue NMI handling).
+ * Vectored interrupts are ACKed; spurious interrupts are not.
*/
if (apic_isr_read(SPURIOUS_APIC_VECTOR)) {
+ bool is_spurious;
+
ack_APIC_irq();
+ is_spurious = !nmi_check_continuation();
if (this_cpu(state_dump_pending)) {
this_cpu(state_dump_pending) = false;
dump_execstate(regs);
- return;
+ is_spurious = false;
}
+
+ if ( !is_spurious )
+ return;
}
/* see sw-dev-man vol 3, chapter 7.4.13.5 */
void send_IPI_self_legacy(uint8_t vector)
{
+ /* NMI continuation handling relies on using a shorthand here. */
send_IPI_shortcut(APIC_DEST_SELF, vector, APIC_DEST_PHYSICAL);
}
#include <public/hvm/params.h>
#include <asm/cpuid.h>
#include <xsm/xsm.h>
+#include <asm/mach-default/irq_vectors.h>
#include <asm/pv/traps.h>
#include <asm/pv/mm.h>
nmi_callback = dummy_nmi_callback;
}
+bool nmi_check_continuation(void)
+{
+ bool ret = false;
+
+ return ret;
+}
+
+void trigger_nmi_continuation(void)
+{
+ /*
+ * Issue a self-IPI. Handling is done in spurious_interrupt().
+ * NMI could have happened in IPI sequence, so wait for ICR being idle
+ * again before leaving NMI handler.
+ * This relies on self-IPI using a simple shorthand, thus avoiding any
+ * use of locking or percpu cpumasks.
+ */
+ send_IPI_self(SPURIOUS_APIC_VECTOR);
+ apic_wait_icr_idle();
+}
+
void do_device_not_available(struct cpu_user_regs *regs)
{
#ifdef CONFIG_PV
void unset_nmi_callback(void);
DECLARE_PER_CPU(unsigned int, nmi_count);
-
+
+/**
+ * trigger_nmi_continuation
+ *
+ * Schedule continuation to be started in interrupt context after NMI handling.
+ */
+void trigger_nmi_continuation(void);
+
+/* Check for NMI continuation pending. */
+bool nmi_check_continuation(void);
#endif /* ASM_NMI_H */