From: Arun Sharma <arun.sharma@intel.com>
To: Ian Pratt <Ian.Pratt@cl.cam.ac.uk>,
Keir Fraser <Keir.Fraser@cl.cam.ac.uk>
Cc: xen-devel@lists.xensource.com
Subject: [PATCH] vmx-io.patch
Date: Fri, 27 May 2005 11:57:08 -0700 [thread overview]
Message-ID: <20050527185708.GA6577@intel.com> (raw)
Fix some of the race conditions that show up when the device models are
running on one CPU and the VMX domain is running on another on a SMP
system.
Signed-off-by: Arun Sharma <arun.sharma@intel.com>
--- 1.58/xen/arch/x86/vmx.c 2005-05-26 19:36:15 -07:00
+++ edited/arch/x86/vmx.c 2005-05-27 11:52:20 -07:00
@@ -465,7 +465,7 @@
set_bit(ARCH_VMX_IO_WAIT, &d->arch.arch_vmx.flags);
p->state = STATE_IOREQ_READY;
evtchn_send(IOPACKET_PORT);
- do_block();
+ vmx_wait_io();
}
enum { COPY_IN = 0, COPY_OUT };
@@ -1266,7 +1266,6 @@
case EXIT_REASON_PENDING_INTERRUPT:
__vmwrite(CPU_BASED_VM_EXEC_CONTROL,
MONITOR_CPU_BASED_EXEC_CONTROLS);
- vmx_intr_assist(ed);
break;
case EXIT_REASON_TASK_SWITCH:
__vmx_bug(®s);
===== arch/x86/vmx_io.c 1.24 vs edited =====
--- 1.24/xen/arch/x86/vmx_io.c 2005-05-16 01:41:48 -07:00
+++ edited/arch/x86/vmx_io.c 2005-05-27 11:53:09 -07:00
@@ -34,9 +34,6 @@
#include <asm/vmx_virpit.h>
#ifdef CONFIG_VMX
-
-extern long do_block();
-
#if defined (__i386__)
static void load_cpu_user_regs(struct cpu_user_regs *regs)
{
@@ -186,7 +183,6 @@
{
vcpu_iodata_t *vio;
ioreq_t *p;
- struct domain *d = ed->domain;
struct cpu_user_regs *regs = guest_cpu_user_regs();
unsigned long old_eax;
int sign;
@@ -196,12 +192,6 @@
mpci_p = &ed->arch.arch_vmx.vmx_platform.mpci;
inst_decoder_regs = mpci_p->inst_decoder_regs;
- /* clear the pending event */
- ed->vcpu_info->evtchn_upcall_pending = 0;
- /* clear the pending bit for port 2 */
- clear_bit(IOPACKET_PORT>>5, &ed->vcpu_info->evtchn_pending_sel);
- clear_bit(IOPACKET_PORT, &d->shared_info->evtchn_pending[0]);
-
vio = (vcpu_iodata_t *) ed->arch.arch_vmx.vmx_platform.shared_page_va;
if (vio == 0) {
VMX_DBG_LOG(DBG_LEVEL_1,
@@ -217,8 +207,8 @@
/* clear IO wait VMX flag */
if (test_bit(ARCH_VMX_IO_WAIT, &ed->arch.arch_vmx.flags)) {
if (p->state != STATE_IORESP_READY) {
- printk("got a false I/O reponse\n");
- do_block();
+ /* An interrupt send event raced us */
+ return;
} else {
p->state = STATE_INVALID;
}
@@ -282,6 +272,51 @@
}
}
+int vmx_clear_pending_io_event(struct exec_domain *ed)
+{
+ struct domain *d = ed->domain;
+
+ /* evtchn_pending is shared by other event channels in 0-31 range */
+ if (!d->shared_info->evtchn_pending[IOPACKET_PORT>>5])
+ clear_bit(IOPACKET_PORT>>5, &ed->vcpu_info->evtchn_pending_sel);
+
+ /* Note: VMX domains may need upcalls as well */
+ if (!ed->vcpu_info->evtchn_pending_sel)
+ ed->vcpu_info->evtchn_upcall_pending = 0;
+
+ /* clear the pending bit for IOPACKET_PORT */
+ return test_and_clear_bit(IOPACKET_PORT,
+ &d->shared_info->evtchn_pending[0]);
+}
+
+/* Because we've cleared the pending events first, we need to guarantee that
+ * all events to be handled by xen for VMX domains are taken care of here.
+ *
+ * interrupts are guaranteed to be checked before resuming guest.
+ * VMX upcalls have been already arranged for if necessary.
+ */
+void vmx_check_events(struct exec_domain *d)
+{
+ /* clear the event *before* checking for work. This should avoid
+ the set-and-check races */
+ if (vmx_clear_pending_io_event(current))
+ vmx_io_assist(d);
+}
+
+/* On exit from vmx_wait_io, we're guaranteed to have a I/O response from
+ the device model */
+void vmx_wait_io()
+{
+ extern void do_block();
+
+ do {
+ do_block();
+ vmx_check_events(current);
+ if (!test_bit(ARCH_VMX_IO_WAIT, ¤t->arch.arch_vmx.flags))
+ break;
+ } while(1);
+}
+
#if defined(__i386__) || defined(__x86_64__)
static inline int __fls(u32 word)
{
@@ -440,22 +475,17 @@
__vmwrite(HOST_ESP, (unsigned long)get_stack_bottom());
if (event_pending(d)) {
- if (test_bit(IOPACKET_PORT, &d->domain->shared_info->evtchn_pending[0]))
- vmx_io_assist(d);
+ vmx_check_events(d);
- else if (test_bit(ARCH_VMX_IO_WAIT, &d->arch.arch_vmx.flags)) {
- printk("got an event while blocked on I/O\n");
- do_block();
- }
-
- /* Assumption: device model will not inject an interrupt
- * while an ioreq_t is pending i.e. the response and
- * interrupt can come together. But an interrupt without
- * a response to ioreq_t is not ok.
- */
+ if (test_bit(ARCH_VMX_IO_WAIT, &d->arch.arch_vmx.flags))
+ vmx_wait_io();
}
- if (!test_bit(ARCH_VMX_IO_WAIT, &d->arch.arch_vmx.flags))
- vmx_intr_assist(d);
+
+ /* We can't resume the guest if we're waiting on I/O */
+ ASSERT(!test_bit(ARCH_VMX_IO_WAIT, &d->arch.arch_vmx.flags));
+
+ /* We always check for interrupts before resuming guest */
+ vmx_intr_assist(d);
}
#endif /* CONFIG_VMX */
===== arch/x86/vmx_platform.c 1.19 vs edited =====
--- 1.19/xen/arch/x86/vmx_platform.c 2005-05-26 20:16:05 -07:00
+++ edited/arch/x86/vmx_platform.c 2005-05-27 11:52:21 -07:00
@@ -470,7 +470,6 @@
struct mi_per_cpu_info *mpci_p;
struct cpu_user_regs *inst_decoder_regs;
extern long evtchn_send(int lport);
- extern long do_block(void);
mpci_p = ¤t->arch.arch_vmx.vmx_platform.mpci;
inst_decoder_regs = mpci_p->inst_decoder_regs;
@@ -520,7 +519,7 @@
#endif
evtchn_send(IOPACKET_PORT);
- do_block();
+ vmx_wait_io();
}
void handle_mmio(unsigned long va, unsigned long gpa)
===== include/asm-x86/vmx_platform.h 1.9 vs edited =====
--- 1.9/xen/include/asm-x86/vmx_platform.h 2005-04-28 07:04:11 -07:00
+++ edited/include/asm-x86/vmx_platform.h 2005-05-27 11:52:21 -07:00
@@ -85,6 +85,7 @@
};
extern void handle_mmio(unsigned long, unsigned long);
+extern void vmx_wait_io(void);
extern int vmx_setup_platform(struct exec_domain *, struct cpu_user_regs *);
// XXX - think about this -- maybe use bit 30 of the mfn to signify an MMIO frame.
reply other threads:[~2005-05-27 18:57 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
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=20050527185708.GA6577@intel.com \
--to=arun.sharma@intel.com \
--cc=Ian.Pratt@cl.cam.ac.uk \
--cc=Keir.Fraser@cl.cam.ac.uk \
--cc=xen-devel@lists.xensource.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.