ia64/xen-unstable

view xen/arch/ia64/vmx_support.c @ 6552:a9873d384da4

Merge.
author adsharma@los-vmm.sc.intel.com
date Thu Aug 25 12:24:48 2005 -0700 (2005-08-25)
parents 112d44270733 fa0754a9f64f
children dfaf788ab18c
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();
40 int port = iopacket_port(d);
42 do {
43 if (!test_bit(port,
44 &d->shared_info->evtchn_pending[0]))
45 do_block();
47 /* Unblocked when some event is coming. Clear pending indication
48 * immediately if deciding to go for io assist
49 */
50 if (test_and_clear_bit(port,
51 &d->shared_info->evtchn_pending[0])) {
52 clear_bit(port>>5, &v->vcpu_info->evtchn_pending_sel);
53 clear_bit(0, &v->vcpu_info->evtchn_upcall_pending);
54 vmx_io_assist(v);
55 }
58 if (test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags)) {
59 /*
60 * Latest event is not I/O completion, so clear corresponding
61 * selector and pending indication, to allow real event coming
62 */
63 clear_bit(0, &v->vcpu_info->evtchn_upcall_pending);
65 /* Here atually one window is leaved before selector is cleared.
66 * However this window only delay the indication to coming event,
67 * nothing losed. Next loop will check I/O channel to fix this
68 * window.
69 */
70 clear_bit(port>>5, &v->vcpu_info->evtchn_pending_sel);
71 }
72 else
73 break;
74 } while (test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags));
75 }
77 /*
78 * Only place to call vmx_io_assist is mmio/legacy_io emulation.
79 * Since I/O emulation is synchronous, it shouldn't be called in
80 * other places. This is not like x86, since IA-64 implements a
81 * per-vp stack without continuation.
82 */
83 void vmx_io_assist(struct vcpu *v)
84 {
85 vcpu_iodata_t *vio;
86 ioreq_t *p;
88 /*
89 * This shared page contains I/O request between emulation code
90 * and device model.
91 */
92 vio = get_vio(v->domain, v->vcpu_id);
93 if (!vio)
94 panic("Corruption: bad shared page: %lx\n", (unsigned long)vio);
96 p = &vio->vp_ioreq;
98 if (p->state == STATE_IORESP_HOOK)
99 panic("Not supported: No hook available for DM request\n");
101 if (test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags)) {
102 if (p->state != STATE_IORESP_READY) {
103 /* Can't do_block here, for the same reason as other places to
104 * use vmx_wait_io. Simple return is safe since vmx_wait_io will
105 * try to block again
106 */
107 return;
108 } else
109 p->state = STATE_INVALID;
111 clear_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags);
112 } else
113 return; /* Spurous event? */
114 }
116 /*
117 * VMX domainN has two types of interrupt source: lsapic model within
118 * HV, and device model within domain 0 (service OS). There're another
119 * pending array in share page, manipulated by device model directly.
120 * To conform to VT-i spec, we have to sync pending bits in shared page
121 * into VPD. This has to be done before checking pending interrupt at
122 * resume to guest. For domain 0, all the interrupt sources come from
123 * HV, which then doesn't require this assist.
124 */
125 void vmx_intr_assist(struct vcpu *v)
126 {
127 vcpu_iodata_t *vio;
128 struct domain *d = v->domain;
129 extern void vmx_vcpu_pend_batch_interrupt(VCPU *vcpu,
130 unsigned long *pend_irr);
131 int port = iopacket_port(d);
133 /* I/O emulation is atomic, so it's impossible to see execution flow
134 * out of vmx_wait_io, when guest is still waiting for response.
135 */
136 if (test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags))
137 panic("!!!Bad resume to guest before I/O emulation is done.\n");
139 /* Clear indicator specific to interrupt delivered from DM */
140 if (test_and_clear_bit(port,
141 &d->shared_info->evtchn_pending[0])) {
142 if (!d->shared_info->evtchn_pending[port >> 5])
143 clear_bit(port>>5, &v->vcpu_info->evtchn_pending_sel);
145 if (!v->vcpu_info->evtchn_pending_sel)
146 clear_bit(0, &v->vcpu_info->evtchn_upcall_pending);
147 }
149 /* Even without event pending, we still need to sync pending bits
150 * between DM and vlsapic. The reason is that interrupt delivery
151 * shares same event channel as I/O emulation, with corresponding
152 * indicator possibly cleared when vmx_wait_io().
153 */
154 vio = get_vio(v->domain, v->vcpu_id);
155 if (!vio)
156 panic("Corruption: bad shared page: %lx\n", (unsigned long)vio);
158 #ifdef V_IOSAPIC_READY
159 vlapic_update_ext_irq(v);
160 #else
161 panic("IOSAPIC model is missed in qemu\n");
162 #endif
163 return;
164 }