ia64/xen-unstable

view xen/arch/ia64/vmx_support.c @ 5797:ca44d2dbb273

Intel's pre-bk->hg transition patches
Signed-off-by Eddie Dong <Eddie.dong@intel.com>
Signed-off-by Anthony Xu <Anthony.xu@intel.com>
Signed-off-by Kevin Tian <Kevin.tian@intel.com>
author djm@kirby.fc.hp.com
date Sat Jul 09 07:58:56 2005 -0700 (2005-07-09)
parents
children a83ac0806d6b
line source
2 /* -*- Mode:C; c-basic-offset:4; tab-width:4; indent-tabs-mode:nil -*- */
3 /*
4 * vmx_support.c: vmx specific support interface.
5 * Copyright (c) 2005, Intel Corporation.
6 * Kun Tian (Kevin Tian) (Kevin.tian@intel.com)
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU General Public License,
10 * version 2, as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19 * Place - Suite 330, Boston, MA 02111-1307 USA.
20 *
21 */
22 #include <xen/config.h>
23 #include <xen/sched.h>
24 #include <public/io/ioreq.h>
25 #include <asm/vmx.h>
26 #include <asm/vmx_vcpu.h>
28 /*
29 * I/O emulation should be atomic from domain point of view. However,
30 * when emulation code is waiting for I/O completion by do_block,
31 * other events like DM interrupt, VBD, etc. may come and unblock
32 * current exection flow. So we have to prepare for re-block if unblocked
33 * by non I/O completion event.
34 */
35 void vmx_wait_io(void)
36 {
37 struct vcpu *v = current;
38 struct domain *d = v->domain;
39 extern void do_block();
41 do {
42 if (!test_bit(IOPACKET_PORT,
43 &d->shared_info->evtchn_pending[0]))
44 do_block();
46 /* Unblocked when some event is coming. Clear pending indication
47 * immediately if deciding to go for io assist
48 */
49 if (test_and_clear_bit(IOPACKET_PORT,
50 &d->shared_info->evtchn_pending[0])) {
51 clear_bit(IOPACKET_PORT>>5, &v->vcpu_info->evtchn_pending_sel);
52 clear_bit(0, &v->vcpu_info->evtchn_upcall_pending);
53 vmx_io_assist(v);
54 }
57 if (test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags)) {
58 /*
59 * Latest event is not I/O completion, so clear corresponding
60 * selector and pending indication, to allow real event coming
61 */
62 clear_bit(0, &v->vcpu_info->evtchn_upcall_pending);
64 /* Here atually one window is leaved before selector is cleared.
65 * However this window only delay the indication to coming event,
66 * nothing losed. Next loop will check I/O channel to fix this
67 * window.
68 */
69 clear_bit(IOPACKET_PORT>>5, &v->vcpu_info->evtchn_pending_sel);
70 }
71 else
72 break;
73 } while (test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags));
74 }
76 /*
77 * Only place to call vmx_io_assist is mmio/legacy_io emulation.
78 * Since I/O emulation is synchronous, it shouldn't be called in
79 * other places. This is not like x86, since IA-64 implements a
80 * per-vp stack without continuation.
81 */
82 void vmx_io_assist(struct vcpu *v)
83 {
84 vcpu_iodata_t *vio;
85 ioreq_t *p;
87 /*
88 * This shared page contains I/O request between emulation code
89 * and device model.
90 */
91 vio = (vcpu_iodata_t *)v->arch.arch_vmx.vmx_platform.shared_page_va;
92 if (!vio)
93 panic("Corruption: bad shared page: %lx\n", (unsigned long)vio);
95 p = &vio->vp_ioreq;
97 if (p->state == STATE_IORESP_HOOK)
98 panic("Not supported: No hook available for DM request\n");
100 if (test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags)) {
101 if (p->state != STATE_IORESP_READY) {
102 /* Can't do_block here, for the same reason as other places to
103 * use vmx_wait_io. Simple return is safe since vmx_wait_io will
104 * try to block again
105 */
106 return;
107 } else
108 p->state = STATE_INVALID;
110 clear_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags);
111 } else
112 return; /* Spurous event? */
113 }
115 /*
116 * VMX domainN has two types of interrupt source: lsapic model within
117 * HV, and device model within domain 0 (service OS). There're another
118 * pending array in share page, manipulated by device model directly.
119 * To conform to VT-i spec, we have to sync pending bits in shared page
120 * into VPD. This has to be done before checking pending interrupt at
121 * resume to guest. For domain 0, all the interrupt sources come from
122 * HV, which then doesn't require this assist.
123 */
124 void vmx_intr_assist(struct vcpu *v)
125 {
126 vcpu_iodata_t *vio;
127 struct domain *d = v->domain;
128 extern void vmx_vcpu_pend_batch_interrupt(VCPU *vcpu,
129 unsigned long *pend_irr);
131 /* I/O emulation is atomic, so it's impossible to see execution flow
132 * out of vmx_wait_io, when guest is still waiting for response.
133 */
134 if (test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags))
135 panic("!!!Bad resume to guest before I/O emulation is done.\n");
137 /* Clear indicator specific to interrupt delivered from DM */
138 if (test_and_clear_bit(IOPACKET_PORT,
139 &d->shared_info->evtchn_pending[0])) {
140 if (!d->shared_info->evtchn_pending[IOPACKET_PORT >> 5])
141 clear_bit(IOPACKET_PORT>>5, &v->vcpu_info->evtchn_pending_sel);
143 if (!v->vcpu_info->evtchn_pending_sel)
144 clear_bit(0, &v->vcpu_info->evtchn_upcall_pending);
145 }
147 /* Even without event pending, we still need to sync pending bits
148 * between DM and vlsapic. The reason is that interrupt delivery
149 * shares same event channel as I/O emulation, with corresponding
150 * indicator possibly cleared when vmx_wait_io().
151 */
152 vio = (vcpu_iodata_t *)v->arch.arch_vmx.vmx_platform.shared_page_va;
153 if (!vio)
154 panic("Corruption: bad shared page: %lx\n", (unsigned long)vio);
156 vmx_vcpu_pend_batch_interrupt(v, &vio->vp_intr[0]);
157 memset(&vio->vp_intr[0], 0, sizeof(vio->vp_intr));
158 return;
159 }