debuggers.hg

view xen/arch/x86/vmx_io.c @ 3606:002034af24e6

bitkeeper revision 1.1159.231.11 (41f97e1amKuDHSrW5ZWKsTy4ZIfNRA)

Fix the direction flag for string I/O instructions.

Signed-off-by: Jun Nakajima <jun.nakajima@intel.com>
Signed-off-by: Chengyuan Li <chengyuan.li@intel.com>
Signed-off-by: ian.pratt@cl.cam.ac.uk
author iap10@labyrinth.cl.cam.ac.uk
date Thu Jan 27 23:49:46 2005 +0000 (2005-01-27)
parents ec21acd5e1a1
children cd26f113b1b1
line source
1 /*
2 * vmx_io.c: handling I/O, interrupts related VMX entry/exit
3 * Copyright (c) 2004, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
16 * Place - Suite 330, Boston, MA 02111-1307 USA.
17 *
18 */
19 #include <xen/config.h>
20 #include <xen/init.h>
21 #include <xen/mm.h>
22 #include <xen/lib.h>
23 #include <xen/errno.h>
25 #include <asm/cpufeature.h>
26 #include <asm/processor.h>
27 #include <asm/msr.h>
28 #include <asm/vmx.h>
29 #include <asm/vmx_vmcs.h>
30 #include <xen/event.h>
31 #include <public/io/ioreq.h>
33 extern long do_block();
35 void vmx_io_assist(struct exec_domain *ed)
36 {
37 vcpu_iodata_t *vio;
38 ioreq_t *p;
39 struct domain *d = ed->domain;
40 execution_context_t *ec = get_execution_context();
41 unsigned long old_eax;
42 int sign;
44 /* clear the pending event */
45 ed->vcpu_info->evtchn_upcall_pending = 0;
46 /* clear the pending bit for port 2 */
47 clear_bit(IOPACKET_PORT>>5, &ed->vcpu_info->evtchn_pending_sel);
48 clear_bit(IOPACKET_PORT, &d->shared_info->evtchn_pending[0]);
50 vio = (vcpu_iodata_t *) ed->thread.arch_vmx.vmx_platform.shared_page_va;
51 if (vio == 0) {
52 VMX_DBG_LOG(DBG_LEVEL_1,
53 "bad shared page: %lx\n", (unsigned long) vio);
54 domain_crash();
55 }
56 p = &vio->vp_ioreq;
57 /* clear IO wait VMX flag */
58 if (test_bit(ARCH_VMX_IO_WAIT, &ed->thread.arch_vmx.flags)) {
59 if (p->state != STATE_IORESP_READY) {
60 printk("got a false I/O reponse\n");
61 do_block();
62 } else {
63 p->state = STATE_INVALID;
64 }
65 clear_bit(ARCH_VMX_IO_WAIT, &ed->thread.arch_vmx.flags);
66 } else {
67 return;
68 }
70 sign = (p->df) ? -1 : 1;
71 if (p->port_mm) {
72 if (p->pdata_valid) {
73 ec->esi += sign * p->count * p->size;
74 ec->edi += sign * p->count * p->size;
75 } else {
76 if (p->dir == IOREQ_WRITE) {
77 return;
78 }
79 }
80 }
82 if (p->dir == IOREQ_WRITE) {
83 if (p->pdata_valid) {
84 ec->esi += sign * p->count * p->size;
85 ec->ecx -= p->count;
86 }
87 return;
88 } else {
89 if (p->pdata_valid) {
90 ec->edi += sign * p->count * p->size;
91 ec->ecx -= p->count;
92 return;
93 }
94 }
96 old_eax = ec->eax;
98 switch(p->size) {
99 case 1:
100 ec->eax = (old_eax & 0xffffff00) | (p->u.data & 0xff);
101 break;
102 case 2:
103 ec->eax = (old_eax & 0xffff0000) | (p->u.data & 0xffff);
104 break;
105 case 4:
106 ec->eax = (p->u.data & 0xffffffff);
107 break;
108 default:
109 BUG();
110 }
111 }
113 static inline int __fls(unsigned long word)
114 {
115 int bit;
117 __asm__("bsrl %1,%0"
118 :"=r" (bit)
119 :"rm" (word));
120 return word ? bit : -1;
121 }
124 /* Simple minded Local APIC priority implementation. Fix later */
125 static __inline__ int find_highest_irq(unsigned long *pintr)
126 {
127 if (pintr[7])
128 return __fls(pintr[7]) + (256-32*1);
129 if (pintr[6])
130 return __fls(pintr[6]) + (256-32*2);
131 if (pintr[5])
132 return __fls(pintr[5]) + (256-32*3);
133 if (pintr[4])
134 return __fls(pintr[4]) + (256-32*4);
135 if (pintr[3])
136 return __fls(pintr[3]) + (256-32*5);
137 if (pintr[2])
138 return __fls(pintr[2]) + (256-32*6);
139 if (pintr[1])
140 return __fls(pintr[1]) + (256-32*7);
141 return __fls(pintr[0]);
142 }
144 /*
145 * Return 0-255 for pending irq.
146 * -1 when no pending.
147 */
148 static inline int find_highest_pending_irq(struct exec_domain *d)
149 {
150 vcpu_iodata_t *vio;
152 vio = (vcpu_iodata_t *) d->thread.arch_vmx.vmx_platform.shared_page_va;
153 if (vio == 0) {
154 VMX_DBG_LOG(DBG_LEVEL_1,
155 "bad shared page: %lx\n", (unsigned long) vio);
156 domain_crash();
157 }
159 return find_highest_irq(&vio->vp_intr[0]);
160 }
162 static inline void clear_highest_bit(struct exec_domain *d, int vector)
163 {
164 vcpu_iodata_t *vio;
166 vio = (vcpu_iodata_t *) d->thread.arch_vmx.vmx_platform.shared_page_va;
167 if (vio == 0) {
168 VMX_DBG_LOG(DBG_LEVEL_1,
169 "bad shared page: %lx\n", (unsigned long) vio);
170 domain_crash();
171 }
173 clear_bit(vector, &vio->vp_intr[0]);
174 }
176 static inline int irq_masked(unsigned long eflags)
177 {
178 return ((eflags & X86_EFLAGS_IF) == 0);
179 }
181 void vmx_intr_assist(struct exec_domain *d)
182 {
183 int highest_vector = find_highest_pending_irq(d);
184 unsigned long intr_fields, eflags;
186 if (highest_vector == -1)
187 return;
189 __vmread(VM_ENTRY_INTR_INFO_FIELD, &intr_fields);
190 if (intr_fields & INTR_INFO_VALID_MASK) {
191 VMX_DBG_LOG(DBG_LEVEL_1, "vmx_intr_assist: intr_fields: %lx\n",
192 intr_fields);
193 return;
194 }
196 __vmread(GUEST_EFLAGS, &eflags);
197 if (irq_masked(eflags)) {
198 VMX_DBG_LOG(DBG_LEVEL_1, "guesting pending: %x, eflags: %lx\n",
199 highest_vector, eflags);
200 return;
201 }
203 clear_highest_bit(d, highest_vector);
204 intr_fields = (INTR_INFO_VALID_MASK | INTR_TYPE_EXT_INTR | highest_vector);
205 __vmwrite(VM_ENTRY_INTR_INFO_FIELD, intr_fields);
207 __vmwrite(GUEST_INTERRUPTIBILITY_INFO, 0);
209 return;
210 }
212 void vmx_do_resume(struct exec_domain *d)
213 {
214 __vmwrite(HOST_CR3, pagetable_val(d->mm.monitor_table));
215 __vmwrite(GUEST_CR3, pagetable_val(d->mm.shadow_table));
216 __vmwrite(HOST_ESP, (unsigned long) get_stack_top());
218 if (event_pending(d)) {
219 if (test_bit(IOPACKET_PORT, &d->domain->shared_info->evtchn_pending[0]))
220 vmx_io_assist(d);
222 else if (test_bit(ARCH_VMX_IO_WAIT, &d->thread.arch_vmx.flags)) {
223 printk("got an event while blocked on I/O\n");
224 do_block();
225 }
227 /* Assumption: device model will not inject an interrupt
228 * while an ioreq_t is pending i.e. the response and
229 * interrupt can come together. But an interrupt without
230 * a response to ioreq_t is not ok.
231 */
232 }
233 if (!test_bit(ARCH_VMX_IO_WAIT, &d->thread.arch_vmx.flags))
234 vmx_intr_assist(d);
235 }