From: Jan Kiszka <jan.kiszka@siemens.com>
To: qemu-devel@nongnu.org
Cc: jan.kiszka@web.de
Subject: Re: [Qemu-devel] [PATCH] APIC: add NMI and SMI IPI support
Date: Wed, 20 Feb 2008 18:23:28 +0100 [thread overview]
Message-ID: <47BC6210.4060701@siemens.com> (raw)
In-Reply-To: <13d5f0ea0802190517p5e602b8atc575a351f10595f5@mail.gmail.com>
Robi Yagel wrote:
> Hello,
> Thanks for the patch,
Nice to hear that there is interest in this. :)
> if you can, please advice on the proper place to add
> periodic generation of SMI/NMIs in order to simulate, e.g., a watchdog (and the
> needed parameters - except for CPU_INTERRUPT_NMI...)
Yeah, I also thought about NMI watchdog emulation while adding
CPU_INTERRUPT_NMI, but it took a bit more effort to understand what
pieces are missing. It should be a fairly useful feature for testing NMI
interaction with new kernel code and maybe even catching nasty races
that way (whenever you happen to work on such things, like I do ;) ).
Also, we need NMI delivery for custom hardware emulation here. So there
might be broader use for CPU_INTERRUPT_NMI in the future.
However, find some experimental watchdog-enabler patch below. It allows
to use nmi_watchdog=1 (i.e. the IO-APIC variant) with Linux, without any
visible regression of normal IRQ delivery (but I only lightly tested it
on top of the kvm-userspace qemu, that's why "experimental").
A performance counter based NMI watchdog is surely doable as well, but
it takes a bit more effort. You would have to decide first what
perf-counter features should be emulated and how cleanly, even if you
only want to (mis-)use it for watchdog services. I'm lacking time for
this right now.
Jan
--
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
---
hw/apic.c | 38 +++++++++++++++++++++++++++++++++-----
hw/pc.c | 2 +-
hw/pc.h | 3 +++
3 files changed, 37 insertions(+), 6 deletions(-)
Index: b/hw/apic.c
===================================================================
--- a/hw/apic.c
+++ b/hw/apic.c
@@ -166,6 +166,37 @@ static inline void reset_bit(uint32_t *t
tab[i] &= ~mask;
}
+void apic_local_deliver(CPUState *env, int vector)
+{
+ APICState *s = env->apic_state;
+ uint32_t lvt = s->lvt[vector];
+ int trigger_mode;
+
+ if (lvt & APIC_LVT_MASKED)
+ return;
+
+ switch ((lvt >> 8) & 7) {
+ case APIC_DM_SMI:
+ cpu_interrupt(env, CPU_INTERRUPT_SMI);
+ break;
+
+ case APIC_DM_NMI:
+ cpu_interrupt(env, CPU_INTERRUPT_NMI);
+ break;
+
+ case APIC_DM_EXTINT:
+ cpu_interrupt(env, CPU_INTERRUPT_HARD);
+ break;
+
+ case APIC_DM_FIXED:
+ trigger_mode = APIC_TRIGGER_EDGE;
+ if ((vector == APIC_LVT_LINT0 || vector == APIC_LVT_LINT1) &&
+ (lvt & APIC_LVT_LEVEL_TRIGGER))
+ trigger_mode = APIC_TRIGGER_LEVEL;
+ apic_set_irq(s, lvt & 0xff, trigger_mode);
+ }
+}
+
#define foreach_apic(apic, deliver_bitmask, code) \
{\
int __i, __j, __mask;\
@@ -504,8 +535,7 @@ int apic_accept_pic_intr(CPUState *env)
if (s->id == 0 &&
((s->apicbase & MSR_IA32_APICBASE_ENABLE) == 0 ||
- ((lvt0 & APIC_LVT_MASKED) == 0 &&
- ((lvt0 >> 8) & 0x7) == APIC_DM_EXTINT)))
+ (lvt0 & APIC_LVT_MASKED) == 0))
return 1;
return 0;
@@ -556,9 +586,7 @@ static void apic_timer(void *opaque)
{
APICState *s = opaque;
- if (!(s->lvt[APIC_LVT_TIMER] & APIC_LVT_MASKED)) {
- apic_set_irq(s, s->lvt[APIC_LVT_TIMER] & 0xff, APIC_TRIGGER_EDGE);
- }
+ apic_local_deliver(s->cpu_env, APIC_LVT_TIMER);
apic_timer_update(s, s->next_time);
}
Index: b/hw/pc.c
===================================================================
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -115,7 +115,7 @@ static void pic_irq_request(void *opaque
{
CPUState *env = opaque;
if (level && apic_accept_pic_intr(env))
- cpu_interrupt(env, CPU_INTERRUPT_HARD);
+ apic_local_deliver(env, APIC_LINT0);
}
/* PC cmos mappings */
Index: b/hw/pc.h
===================================================================
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -39,8 +39,11 @@ void irq_info(void);
/* APIC */
typedef struct IOAPICState IOAPICState;
+#define APIC_LINT0 3
+
int apic_init(CPUState *env);
int apic_accept_pic_intr(CPUState *env);
+void apic_local_deliver(CPUState *env, int vector);
int apic_get_interrupt(CPUState *env);
IOAPICState *ioapic_init(void);
void ioapic_set_irq(void *opaque, int vector, int level);
next prev parent reply other threads:[~2008-02-20 17:23 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-02-19 13:17 [Qemu-devel] [PATCH] APIC: add NMI and SMI IPI support Robi Yagel
2008-02-20 17:23 ` Jan Kiszka [this message]
2008-02-20 22:16 ` [Qemu-devel] [PATCH] Rework local IRQ delivery for APICs (was:[PATCH] APIC: add NMI and SMI IPI support) Jan Kiszka
-- strict thread matches above, loose matches on Subject: below --
2008-01-28 20:37 [Qemu-devel] [PATCH] APIC: add NMI and SMI IPI support Jan Kiszka
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=47BC6210.4060701@siemens.com \
--to=jan.kiszka@siemens.com \
--cc=jan.kiszka@web.de \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).