debuggers.hg

view xen/arch/x86/vmx_io.c @ 3755:ea98f0bb6510

bitkeeper revision 1.1159.212.127 (4208b02bTdSR4AVYRg8diDkKZmIVUg)

General shadow code cleanup.

Fixed compilation problems when SHADOW_DEBUG is enabled.
Fixed compilation problems when CONFIG_VMX is undefined.

Simplified l1pte_write_fault and l1pte_read_fault.
Name change: spfn => smfn (shadow machine frame numbers).

In general, the terms pfn and gpfn now refer to pages in the
guest's idea of physical frames (which diffs for full shadow
guests). mfn always refers to a machine frame number.

One bug fix for check_pagetable():
If we're using writable page tables
along with shadow mode, don't check the currently writable page table
page -- check its snapshot instead.

Signed-off-by: michael.fetterman@cl.cam.ac.uk
author mafetter@fleming.research
date Tue Feb 08 12:27:23 2005 +0000 (2005-02-08)
parents d93748c50893
children f5f2757b3aa2
line source
1 /* -*- Mode:C; c-basic-offset:4; tab-width:4; indent-tabs-mode:nil -*- */
2 /*
3 * vmx_io.c: handling I/O, interrupts related VMX entry/exit
4 * Copyright (c) 2004, Intel Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
17 * Place - Suite 330, Boston, MA 02111-1307 USA.
18 *
19 */
20 #include <xen/config.h>
21 #include <xen/init.h>
22 #include <xen/mm.h>
23 #include <xen/lib.h>
24 #include <xen/errno.h>
26 #include <asm/cpufeature.h>
27 #include <asm/processor.h>
28 #include <asm/msr.h>
29 #include <asm/vmx.h>
30 #include <asm/vmx_vmcs.h>
31 #include <xen/event.h>
32 #include <public/io/ioreq.h>
33 #include <asm/vmx_platform.h>
35 #ifdef CONFIG_VMX
37 extern long do_block();
39 #if defined (__i386__)
40 static void load_xen_regs(struct xen_regs *regs)
41 {
42 /*
43 * Write the guest register value into VMCS
44 */
45 __vmwrite(GUEST_SS_SELECTOR, regs->ss);
46 __vmwrite(GUEST_ESP, regs->esp);
47 __vmwrite(GUEST_EFLAGS, regs->eflags);
48 __vmwrite(GUEST_CS_SELECTOR, regs->cs);
49 __vmwrite(GUEST_EIP, regs->eip);
50 }
52 static void set_reg_value (int size, int index, int seg, struct xen_regs *regs, long value)
53 {
54 switch (size) {
55 case BYTE:
56 switch (index) {
57 case 0:
58 regs->eax &= 0xFFFFFF00;
59 regs->eax |= (value & 0xFF);
60 break;
61 case 1:
62 regs->ecx &= 0xFFFFFF00;
63 regs->ecx |= (value & 0xFF);
64 break;
65 case 2:
66 regs->edx &= 0xFFFFFF00;
67 regs->edx |= (value & 0xFF);
68 break;
69 case 3:
70 regs->ebx &= 0xFFFFFF00;
71 regs->ebx |= (value & 0xFF);
72 break;
73 case 4:
74 regs->eax &= 0xFFFF00FF;
75 regs->eax |= ((value & 0xFF) << 8);
76 break;
77 case 5:
78 regs->ecx &= 0xFFFF00FF;
79 regs->ecx |= ((value & 0xFF) << 8);
80 break;
81 case 6:
82 regs->edx &= 0xFFFF00FF;
83 regs->edx |= ((value & 0xFF) << 8);
84 break;
85 case 7:
86 regs->ebx &= 0xFFFF00FF;
87 regs->ebx |= ((value & 0xFF) << 8);
88 break;
89 default:
90 printk("size:%x, index:%x are invalid!\n", size, index);
91 break;
93 }
94 break;
95 case WORD:
96 switch (index) {
97 case 0:
98 regs->eax &= 0xFFFF0000;
99 regs->eax |= (value & 0xFFFF);
100 break;
101 case 1:
102 regs->ecx &= 0xFFFF0000;
103 regs->ecx |= (value & 0xFFFF);
104 break;
105 case 2:
106 regs->edx &= 0xFFFF0000;
107 regs->edx |= (value & 0xFFFF);
108 break;
109 case 3:
110 regs->ebx &= 0xFFFF0000;
111 regs->ebx |= (value & 0xFFFF);
112 break;
113 case 4:
114 regs->esp &= 0xFFFF0000;
115 regs->esp |= (value & 0xFFFF);
116 break;
118 case 5:
119 regs->ebp &= 0xFFFF0000;
120 regs->ebp |= (value & 0xFFFF);
121 break;
122 case 6:
123 regs->esi &= 0xFFFF0000;
124 regs->esi |= (value & 0xFFFF);
125 break;
126 case 7:
127 regs->edi &= 0xFFFF0000;
128 regs->edi |= (value & 0xFFFF);
129 break;
130 default:
131 printk("size:%x, index:%x are invalid!\n", size, index);
132 break;
133 }
134 break;
135 case LONG:
136 switch (index) {
137 case 0:
138 regs->eax = value;
139 break;
140 case 1:
141 regs->ecx = value;
142 break;
143 case 2:
144 regs->edx = value;
145 break;
146 case 3:
147 regs->ebx = value;
148 break;
149 case 4:
150 regs->esp = value;
151 break;
152 case 5:
153 regs->ebp = value;
154 break;
155 case 6:
156 regs->esi = value;
157 break;
158 case 7:
159 regs->edi = value;
160 break;
161 default:
162 printk("size:%x, index:%x are invalid!\n", size, index);
163 break;
164 }
165 break;
166 default:
167 printk("size:%x, index:%x are invalid!\n", size, index);
168 break;
169 }
170 }
171 #endif
173 void vmx_io_assist(struct exec_domain *ed)
174 {
175 vcpu_iodata_t *vio;
176 ioreq_t *p;
177 struct domain *d = ed->domain;
178 execution_context_t *ec = get_execution_context();
179 unsigned long old_eax;
180 int sign;
181 struct mi_per_cpu_info *mpci_p;
182 struct xen_regs *inst_decoder_regs;
184 mpci_p = &ed->arch.arch_vmx.vmx_platform.mpci;
185 inst_decoder_regs = mpci_p->inst_decoder_regs;
187 /* clear the pending event */
188 ed->vcpu_info->evtchn_upcall_pending = 0;
189 /* clear the pending bit for port 2 */
190 clear_bit(IOPACKET_PORT>>5, &ed->vcpu_info->evtchn_pending_sel);
191 clear_bit(IOPACKET_PORT, &d->shared_info->evtchn_pending[0]);
193 vio = (vcpu_iodata_t *) ed->arch.arch_vmx.vmx_platform.shared_page_va;
194 if (vio == 0) {
195 VMX_DBG_LOG(DBG_LEVEL_1,
196 "bad shared page: %lx\n", (unsigned long) vio);
197 domain_crash();
198 }
199 p = &vio->vp_ioreq;
200 /* clear IO wait VMX flag */
201 if (test_bit(ARCH_VMX_IO_WAIT, &ed->arch.arch_vmx.flags)) {
202 if (p->state != STATE_IORESP_READY) {
203 printk("got a false I/O reponse\n");
204 do_block();
205 } else {
206 p->state = STATE_INVALID;
207 }
208 clear_bit(ARCH_VMX_IO_WAIT, &ed->arch.arch_vmx.flags);
209 } else {
210 return;
211 }
213 sign = (p->df) ? -1 : 1;
214 if (p->port_mm) {
215 if (p->pdata_valid) {
216 ec->esi += sign * p->count * p->size;
217 ec->edi += sign * p->count * p->size;
218 } else {
219 if (p->dir == IOREQ_WRITE) {
220 return;
221 }
222 int size = -1, index = -1;
224 size = operand_size(ed->arch.arch_vmx.vmx_platform.mpci.mmio_target);
225 index = operand_index(ed->arch.arch_vmx.vmx_platform.mpci.mmio_target);
227 if (ed->arch.arch_vmx.vmx_platform.mpci.mmio_target & WZEROEXTEND) {
228 p->u.data = p->u.data & 0xffff;
229 }
230 set_reg_value(size, index, 0, (struct xen_regs *)ec, p->u.data);
232 }
233 load_xen_regs((struct xen_regs *)ec);
234 return;
235 }
237 if (p->dir == IOREQ_WRITE) {
238 if (p->pdata_valid) {
239 ec->esi += sign * p->count * p->size;
240 ec->ecx -= p->count;
241 }
242 return;
243 } else {
244 if (p->pdata_valid) {
245 ec->edi += sign * p->count * p->size;
246 ec->ecx -= p->count;
247 return;
248 }
249 }
251 old_eax = ec->eax;
253 switch(p->size) {
254 case 1:
255 ec->eax = (old_eax & 0xffffff00) | (p->u.data & 0xff);
256 break;
257 case 2:
258 ec->eax = (old_eax & 0xffff0000) | (p->u.data & 0xffff);
259 break;
260 case 4:
261 ec->eax = (p->u.data & 0xffffffff);
262 break;
263 default:
264 BUG();
265 }
266 }
268 static inline int __fls(unsigned long word)
269 {
270 int bit;
272 __asm__("bsrl %1,%0"
273 :"=r" (bit)
274 :"rm" (word));
275 return word ? bit : -1;
276 }
279 /* Simple minded Local APIC priority implementation. Fix later */
280 static __inline__ int find_highest_irq(unsigned long *pintr)
281 {
282 if (pintr[7])
283 return __fls(pintr[7]) + (256-32*1);
284 if (pintr[6])
285 return __fls(pintr[6]) + (256-32*2);
286 if (pintr[5])
287 return __fls(pintr[5]) + (256-32*3);
288 if (pintr[4])
289 return __fls(pintr[4]) + (256-32*4);
290 if (pintr[3])
291 return __fls(pintr[3]) + (256-32*5);
292 if (pintr[2])
293 return __fls(pintr[2]) + (256-32*6);
294 if (pintr[1])
295 return __fls(pintr[1]) + (256-32*7);
296 return __fls(pintr[0]);
297 }
299 /*
300 * Return 0-255 for pending irq.
301 * -1 when no pending.
302 */
303 static inline int find_highest_pending_irq(struct exec_domain *d)
304 {
305 vcpu_iodata_t *vio;
307 vio = (vcpu_iodata_t *) d->arch.arch_vmx.vmx_platform.shared_page_va;
308 if (vio == 0) {
309 VMX_DBG_LOG(DBG_LEVEL_1,
310 "bad shared page: %lx\n", (unsigned long) vio);
311 domain_crash();
312 }
314 return find_highest_irq(&vio->vp_intr[0]);
315 }
317 static inline void clear_highest_bit(struct exec_domain *d, int vector)
318 {
319 vcpu_iodata_t *vio;
321 vio = (vcpu_iodata_t *) d->arch.arch_vmx.vmx_platform.shared_page_va;
322 if (vio == 0) {
323 VMX_DBG_LOG(DBG_LEVEL_1,
324 "bad shared page: %lx\n", (unsigned long) vio);
325 domain_crash();
326 }
328 clear_bit(vector, &vio->vp_intr[0]);
329 }
331 static inline int irq_masked(unsigned long eflags)
332 {
333 return ((eflags & X86_EFLAGS_IF) == 0);
334 }
336 void vmx_intr_assist(struct exec_domain *d)
337 {
338 int highest_vector = find_highest_pending_irq(d);
339 unsigned long intr_fields, eflags;
341 if (highest_vector == -1)
342 return;
344 __vmread(VM_ENTRY_INTR_INFO_FIELD, &intr_fields);
345 if (intr_fields & INTR_INFO_VALID_MASK) {
346 VMX_DBG_LOG(DBG_LEVEL_1, "vmx_intr_assist: intr_fields: %lx\n",
347 intr_fields);
348 return;
349 }
351 __vmread(GUEST_EFLAGS, &eflags);
352 if (irq_masked(eflags)) {
353 VMX_DBG_LOG(DBG_LEVEL_1, "guesting pending: %x, eflags: %lx\n",
354 highest_vector, eflags);
355 return;
356 }
358 clear_highest_bit(d, highest_vector);
359 intr_fields = (INTR_INFO_VALID_MASK | INTR_TYPE_EXT_INTR | highest_vector);
360 __vmwrite(VM_ENTRY_INTR_INFO_FIELD, intr_fields);
362 __vmwrite(GUEST_INTERRUPTIBILITY_INFO, 0);
364 return;
365 }
367 void vmx_do_resume(struct exec_domain *d)
368 {
369 __vmwrite(HOST_CR3, pagetable_val(d->arch.monitor_table));
370 __vmwrite(GUEST_CR3, pagetable_val(d->arch.shadow_table));
371 __vmwrite(HOST_ESP, (unsigned long) get_stack_top());
373 if (event_pending(d)) {
374 if (test_bit(IOPACKET_PORT, &d->domain->shared_info->evtchn_pending[0]))
375 vmx_io_assist(d);
377 else if (test_bit(ARCH_VMX_IO_WAIT, &d->arch.arch_vmx.flags)) {
378 printk("got an event while blocked on I/O\n");
379 do_block();
380 }
382 /* Assumption: device model will not inject an interrupt
383 * while an ioreq_t is pending i.e. the response and
384 * interrupt can come together. But an interrupt without
385 * a response to ioreq_t is not ok.
386 */
387 }
388 if (!test_bit(ARCH_VMX_IO_WAIT, &d->arch.arch_vmx.flags))
389 vmx_intr_assist(d);
390 }
392 #endif /* CONFIG_VMX */