source: trunk/packages/xen-3.1/xen-3.1/xen/arch/x86/hvm/io.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 18 years ago

Add xen and xen-common

File size: 26.3 KB
Line 
1/*
2 * io.c: Handling I/O and interrupts.
3 *
4 * Copyright (c) 2004, Intel Corporation.
5 * Copyright (c) 2005, International Business Machines Corporation.
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2, as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
18 * Place - Suite 330, Boston, MA 02111-1307 USA.
19 */
20
21#include <xen/config.h>
22#include <xen/init.h>
23#include <xen/mm.h>
24#include <xen/lib.h>
25#include <xen/errno.h>
26#include <xen/trace.h>
27#include <xen/event.h>
28
29#include <xen/hypercall.h>
30#include <asm/current.h>
31#include <asm/cpufeature.h>
32#include <asm/processor.h>
33#include <asm/msr.h>
34#include <asm/apic.h>
35#include <asm/paging.h>
36#include <asm/shadow.h>
37#include <asm/p2m.h>
38#include <asm/hvm/hvm.h>
39#include <asm/hvm/support.h>
40#include <asm/hvm/vpt.h>
41#include <asm/hvm/vpic.h>
42#include <asm/hvm/vlapic.h>
43
44#include <public/sched.h>
45#include <public/hvm/ioreq.h>
46
47#if defined (__i386__)
48static void set_reg_value (int size, int index, int seg, struct cpu_user_regs *regs, long value)
49{
50    switch (size) {
51    case BYTE:
52        switch (index) {
53        case 0:
54            regs->eax &= 0xFFFFFF00;
55            regs->eax |= (value & 0xFF);
56            break;
57        case 1:
58            regs->ecx &= 0xFFFFFF00;
59            regs->ecx |= (value & 0xFF);
60            break;
61        case 2:
62            regs->edx &= 0xFFFFFF00;
63            regs->edx |= (value & 0xFF);
64            break;
65        case 3:
66            regs->ebx &= 0xFFFFFF00;
67            regs->ebx |= (value & 0xFF);
68            break;
69        case 4:
70            regs->eax &= 0xFFFF00FF;
71            regs->eax |= ((value & 0xFF) << 8);
72            break;
73        case 5:
74            regs->ecx &= 0xFFFF00FF;
75            regs->ecx |= ((value & 0xFF) << 8);
76            break;
77        case 6:
78            regs->edx &= 0xFFFF00FF;
79            regs->edx |= ((value & 0xFF) << 8);
80            break;
81        case 7:
82            regs->ebx &= 0xFFFF00FF;
83            regs->ebx |= ((value & 0xFF) << 8);
84            break;
85        default:
86            goto crash;
87        }
88        break;
89    case WORD:
90        switch (index) {
91        case 0:
92            regs->eax &= 0xFFFF0000;
93            regs->eax |= (value & 0xFFFF);
94            break;
95        case 1:
96            regs->ecx &= 0xFFFF0000;
97            regs->ecx |= (value & 0xFFFF);
98            break;
99        case 2:
100            regs->edx &= 0xFFFF0000;
101            regs->edx |= (value & 0xFFFF);
102            break;
103        case 3:
104            regs->ebx &= 0xFFFF0000;
105            regs->ebx |= (value & 0xFFFF);
106            break;
107        case 4:
108            regs->esp &= 0xFFFF0000;
109            regs->esp |= (value & 0xFFFF);
110            break;
111        case 5:
112            regs->ebp &= 0xFFFF0000;
113            regs->ebp |= (value & 0xFFFF);
114            break;
115        case 6:
116            regs->esi &= 0xFFFF0000;
117            regs->esi |= (value & 0xFFFF);
118            break;
119        case 7:
120            regs->edi &= 0xFFFF0000;
121            regs->edi |= (value & 0xFFFF);
122            break;
123        default:
124            goto crash;
125        }
126        break;
127    case LONG:
128        switch (index) {
129        case 0:
130            regs->eax = value;
131            break;
132        case 1:
133            regs->ecx = value;
134            break;
135        case 2:
136            regs->edx = value;
137            break;
138        case 3:
139            regs->ebx = value;
140            break;
141        case 4:
142            regs->esp = value;
143            break;
144        case 5:
145            regs->ebp = value;
146            break;
147        case 6:
148            regs->esi = value;
149            break;
150        case 7:
151            regs->edi = value;
152            break;
153        default:
154            goto crash;
155        }
156        break;
157    default:
158    crash:
159        gdprintk(XENLOG_ERR, "size:%x, index:%x are invalid!\n", size, index);
160        domain_crash_synchronous();
161    }
162}
163#else
164static inline void __set_reg_value(unsigned long *reg, int size, long value)
165{
166    switch (size) {
167    case BYTE_64:
168        *reg &= ~0xFF;
169        *reg |= (value & 0xFF);
170        break;
171    case WORD:
172        *reg &= ~0xFFFF;
173        *reg |= (value & 0xFFFF);
174        break;
175    case LONG:
176        *reg &= ~0xFFFFFFFF;
177        *reg |= (value & 0xFFFFFFFF);
178        break;
179    case QUAD:
180        *reg = value;
181        break;
182    default:
183        gdprintk(XENLOG_ERR, "size:%x is invalid\n", size);
184        domain_crash_synchronous();
185    }
186}
187
188static void set_reg_value (int size, int index, int seg, struct cpu_user_regs *regs, long value)
189{
190    if (size == BYTE) {
191        switch (index) {
192        case 0:
193            regs->rax &= ~0xFF;
194            regs->rax |= (value & 0xFF);
195            break;
196        case 1:
197            regs->rcx &= ~0xFF;
198            regs->rcx |= (value & 0xFF);
199            break;
200        case 2:
201            regs->rdx &= ~0xFF;
202            regs->rdx |= (value & 0xFF);
203            break;
204        case 3:
205            regs->rbx &= ~0xFF;
206            regs->rbx |= (value & 0xFF);
207            break;
208        case 4:
209            regs->rax &= 0xFFFFFFFFFFFF00FF;
210            regs->rax |= ((value & 0xFF) << 8);
211            break;
212        case 5:
213            regs->rcx &= 0xFFFFFFFFFFFF00FF;
214            regs->rcx |= ((value & 0xFF) << 8);
215            break;
216        case 6:
217            regs->rdx &= 0xFFFFFFFFFFFF00FF;
218            regs->rdx |= ((value & 0xFF) << 8);
219            break;
220        case 7:
221            regs->rbx &= 0xFFFFFFFFFFFF00FF;
222            regs->rbx |= ((value & 0xFF) << 8);
223            break;
224        default:
225            gdprintk(XENLOG_ERR, "size:%x, index:%x are invalid!\n",
226                     size, index);
227            domain_crash_synchronous();
228            break;
229        }
230        return;
231    }
232
233    switch (index) {
234    case 0:
235        __set_reg_value(&regs->rax, size, value);
236        break;
237    case 1:
238        __set_reg_value(&regs->rcx, size, value);
239        break;
240    case 2:
241        __set_reg_value(&regs->rdx, size, value);
242        break;
243    case 3:
244        __set_reg_value(&regs->rbx, size, value);
245        break;
246    case 4:
247        __set_reg_value(&regs->rsp, size, value);
248        break;
249    case 5:
250        __set_reg_value(&regs->rbp, size, value);
251        break;
252    case 6:
253        __set_reg_value(&regs->rsi, size, value);
254        break;
255    case 7:
256        __set_reg_value(&regs->rdi, size, value);
257        break;
258    case 8:
259        __set_reg_value(&regs->r8, size, value);
260        break;
261    case 9:
262        __set_reg_value(&regs->r9, size, value);
263        break;
264    case 10:
265        __set_reg_value(&regs->r10, size, value);
266        break;
267    case 11:
268        __set_reg_value(&regs->r11, size, value);
269        break;
270    case 12:
271        __set_reg_value(&regs->r12, size, value);
272        break;
273    case 13:
274        __set_reg_value(&regs->r13, size, value);
275        break;
276    case 14:
277        __set_reg_value(&regs->r14, size, value);
278        break;
279    case 15:
280        __set_reg_value(&regs->r15, size, value);
281        break;
282    default:
283        gdprintk(XENLOG_ERR, "Invalid index\n");
284        domain_crash_synchronous();
285    }
286    return;
287}
288#endif
289
290long get_reg_value(int size, int index, int seg, struct cpu_user_regs *regs);
291
292static inline void set_eflags_CF(int size,
293                                 unsigned int instr,
294                                 unsigned long result,
295                                 unsigned long src,
296                                 unsigned long dst,
297                                 struct cpu_user_regs *regs)
298{
299    unsigned long mask;
300
301    if ( size == BYTE_64 )
302        size = BYTE;
303    ASSERT((size <= sizeof(mask)) && (size > 0));
304
305    mask = ~0UL >> (8 * (sizeof(mask) - size));
306
307    if ( instr == INSTR_ADD )
308    {
309        /* CF=1 <==> result is less than the augend and addend) */
310        if ( (result & mask) < (dst & mask) )
311        {
312            ASSERT((result & mask) < (src & mask));
313            regs->eflags |= X86_EFLAGS_CF;
314        }
315    }
316    else
317    {
318        ASSERT( instr == INSTR_CMP || instr == INSTR_SUB );
319        if ( (src & mask) > (dst & mask) )
320            regs->eflags |= X86_EFLAGS_CF;
321    }
322}
323
324static inline void set_eflags_OF(int size,
325                                 unsigned int instr,
326                                 unsigned long result,
327                                 unsigned long src,
328                                 unsigned long dst,
329                                 struct cpu_user_regs *regs)
330{
331    unsigned long mask;
332
333    if ( size == BYTE_64 )
334        size = BYTE;
335    ASSERT((size <= sizeof(mask)) && (size > 0));
336
337    mask =  1UL << ((8*size) - 1);
338
339    if ( instr == INSTR_ADD )
340    {
341        if ((src ^ result) & (dst ^ result) & mask);
342            regs->eflags |= X86_EFLAGS_OF;
343    }
344    else
345    {
346        ASSERT(instr == INSTR_CMP || instr == INSTR_SUB);
347        if ((dst ^ src) & (dst ^ result) & mask)
348            regs->eflags |= X86_EFLAGS_OF;
349    }
350}
351
352static inline void set_eflags_AF(int size,
353                                 unsigned long result,
354                                 unsigned long src,
355                                 unsigned long dst,
356                                 struct cpu_user_regs *regs)
357{
358    if ((result ^ src ^ dst) & 0x10)
359        regs->eflags |= X86_EFLAGS_AF;
360}
361
362static inline void set_eflags_ZF(int size, unsigned long result,
363                                 struct cpu_user_regs *regs)
364{
365    unsigned long mask;
366
367    if ( size == BYTE_64 )
368        size = BYTE;
369    ASSERT((size <= sizeof(mask)) && (size > 0));
370
371    mask = ~0UL >> (8 * (sizeof(mask) - size));
372
373    if ((result & mask) == 0)
374        regs->eflags |= X86_EFLAGS_ZF;
375}
376
377static inline void set_eflags_SF(int size, unsigned long result,
378                                 struct cpu_user_regs *regs)
379{
380    unsigned long mask;
381
382    if ( size == BYTE_64 )
383        size = BYTE;
384    ASSERT((size <= sizeof(mask)) && (size > 0));
385
386    mask = 1UL << ((8*size) - 1);
387
388    if (result & mask)
389        regs->eflags |= X86_EFLAGS_SF;
390}
391
392static char parity_table[256] = {
393    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
394    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
395    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
396    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
397    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
398    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
399    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
400    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
401    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
402    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
403    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
404    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
405    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
406    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
407    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
408    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1
409};
410
411static inline void set_eflags_PF(int size, unsigned long result,
412                                 struct cpu_user_regs *regs)
413{
414    if (parity_table[result & 0xFF])
415        regs->eflags |= X86_EFLAGS_PF;
416}
417
418static void hvm_pio_assist(struct cpu_user_regs *regs, ioreq_t *p,
419                           struct hvm_io_op *pio_opp)
420{
421    unsigned long old_eax;
422    int sign = p->df ? -1 : 1;
423
424    if ( p->data_is_ptr || (pio_opp->flags & OVERLAP) )
425    {
426        if ( pio_opp->flags & REPZ )
427            regs->ecx -= p->count;
428
429        if ( p->dir == IOREQ_READ )
430        {
431            if ( pio_opp->flags & OVERLAP )
432            {
433                unsigned long addr = pio_opp->addr;
434                if ( hvm_paging_enabled(current) )
435                {
436                    int rv = hvm_copy_to_guest_virt(addr, &p->data, p->size);
437                    if ( rv != 0 )
438                    {
439                        /* Failed on the page-spanning copy.  Inject PF into
440                         * the guest for the address where we failed. */
441                        addr += p->size - rv;
442                        gdprintk(XENLOG_DEBUG, "Pagefault writing non-io side "
443                                 "of a page-spanning PIO: va=%#lx\n", addr);
444                        hvm_inject_exception(TRAP_page_fault,
445                                             PFEC_write_access, addr);
446                        return;
447                    }
448                }
449                else
450                    (void)hvm_copy_to_guest_phys(addr, &p->data, p->size);
451            }
452            regs->edi += sign * p->count * p->size;
453        }
454        else /* p->dir == IOREQ_WRITE */
455        {
456            ASSERT(p->dir == IOREQ_WRITE);
457            regs->esi += sign * p->count * p->size;
458        }
459    }
460    else if ( p->dir == IOREQ_READ )
461    {
462        old_eax = regs->eax;
463        switch ( p->size )
464        {
465        case 1:
466            regs->eax = (old_eax & 0xffffff00) | (p->data & 0xff);
467            break;
468        case 2:
469            regs->eax = (old_eax & 0xffff0000) | (p->data & 0xffff);
470            break;
471        case 4:
472            regs->eax = (p->data & 0xffffffff);
473            break;
474        default:
475            printk("Error: %s unknown port size\n", __FUNCTION__);
476            domain_crash_synchronous();
477        }
478    }
479}
480
481static void hvm_mmio_assist(struct cpu_user_regs *regs, ioreq_t *p,
482                            struct hvm_io_op *mmio_opp)
483{
484    int sign = p->df ? -1 : 1;
485    int size = -1, index = -1;
486    unsigned long value = 0, result = 0;
487    unsigned long src, dst;
488
489    src = mmio_opp->operand[0];
490    dst = mmio_opp->operand[1];
491    size = operand_size(src);
492
493    switch (mmio_opp->instr) {
494    case INSTR_MOV:
495        if (dst & REGISTER) {
496            index = operand_index(dst);
497            set_reg_value(size, index, 0, regs, p->data);
498        }
499        break;
500
501    case INSTR_MOVZX:
502        if (dst & REGISTER) {
503            switch (size) {
504            case BYTE:
505                p->data &= 0xFFULL;
506                break;
507
508            case WORD:
509                p->data &= 0xFFFFULL;
510                break;
511
512            case LONG:
513                p->data &= 0xFFFFFFFFULL;
514                break;
515
516            default:
517                printk("Impossible source operand size of movzx instr: %d\n", size);
518                domain_crash_synchronous();
519            }
520            index = operand_index(dst);
521            set_reg_value(operand_size(dst), index, 0, regs, p->data);
522        }
523        break;
524
525    case INSTR_MOVSX:
526        if (dst & REGISTER) {
527            switch (size) {
528            case BYTE:
529                p->data &= 0xFFULL;
530                if ( p->data & 0x80ULL )
531                    p->data |= 0xFFFFFFFFFFFFFF00ULL;
532                break;
533
534            case WORD:
535                p->data &= 0xFFFFULL;
536                if ( p->data & 0x8000ULL )
537                    p->data |= 0xFFFFFFFFFFFF0000ULL;
538                break;
539
540            case LONG:
541                p->data &= 0xFFFFFFFFULL;
542                if ( p->data & 0x80000000ULL )
543                    p->data |= 0xFFFFFFFF00000000ULL;
544                break;
545
546            default:
547                printk("Impossible source operand size of movsx instr: %d\n", size);
548                domain_crash_synchronous();
549            }
550            index = operand_index(dst);
551            set_reg_value(operand_size(dst), index, 0, regs, p->data);
552        }
553        break;
554
555    case INSTR_MOVS:
556        sign = p->df ? -1 : 1;
557
558        if (mmio_opp->flags & REPZ)
559            regs->ecx -= p->count;
560
561        if ((mmio_opp->flags & OVERLAP) && p->dir == IOREQ_READ) {
562            unsigned long addr = mmio_opp->addr;
563
564            if (hvm_paging_enabled(current))
565            {
566                int rv = hvm_copy_to_guest_virt(addr, &p->data, p->size);
567                if ( rv != 0 )
568                {
569                    /* Failed on the page-spanning copy.  Inject PF into
570                     * the guest for the address where we failed. */
571                    addr += p->size - rv;
572                    gdprintk(XENLOG_DEBUG, "Pagefault writing non-io side of "
573                             "a page-spanning MMIO: va=%#lx\n", addr);
574                    hvm_inject_exception(TRAP_page_fault,
575                                         PFEC_write_access, addr);
576                    return;
577                }
578            }
579            else
580                (void)hvm_copy_to_guest_phys(addr, &p->data, p->size);
581        }
582
583        regs->esi += sign * p->count * p->size;
584        regs->edi += sign * p->count * p->size;
585
586        break;
587
588    case INSTR_STOS:
589        sign = p->df ? -1 : 1;
590        regs->edi += sign * p->count * p->size;
591        if (mmio_opp->flags & REPZ)
592            regs->ecx -= p->count;
593        break;
594
595    case INSTR_LODS:
596        set_reg_value(size, 0, 0, regs, p->data);
597        sign = p->df ? -1 : 1;
598        regs->esi += sign * p->count * p->size;
599        if (mmio_opp->flags & REPZ)
600            regs->ecx -= p->count;
601        break;
602
603    case INSTR_AND:
604        if (src & REGISTER) {
605            index = operand_index(src);
606            value = get_reg_value(size, index, 0, regs);
607            result = (unsigned long) p->data & value;
608        } else if (src & IMMEDIATE) {
609            value = mmio_opp->immediate;
610            result = (unsigned long) p->data & value;
611        } else if (src & MEMORY) {
612            index = operand_index(dst);
613            value = get_reg_value(size, index, 0, regs);
614            result = (unsigned long) p->data & value;
615            set_reg_value(size, index, 0, regs, result);
616        }
617
618        /*
619         * The OF and CF flags are cleared; the SF, ZF, and PF
620         * flags are set according to the result. The state of
621         * the AF flag is undefined.
622         */
623        regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|
624                          X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
625        set_eflags_ZF(size, result, regs);
626        set_eflags_SF(size, result, regs);
627        set_eflags_PF(size, result, regs);
628        break;
629
630    case INSTR_ADD:
631        if (src & REGISTER) {
632            index = operand_index(src);
633            value = get_reg_value(size, index, 0, regs);
634            result = (unsigned long) p->data + value;
635        } else if (src & IMMEDIATE) {
636            value = mmio_opp->immediate;
637            result = (unsigned long) p->data + value;
638        } else if (src & MEMORY) {
639            index = operand_index(dst);
640            value = get_reg_value(size, index, 0, regs);
641            result = (unsigned long) p->data + value;
642            set_reg_value(size, index, 0, regs, result);
643        }
644
645        /*
646         * The CF, OF, SF, ZF, AF, and PF flags are set according
647         * to the result
648         */
649        regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|X86_EFLAGS_AF|
650                          X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
651        set_eflags_CF(size, mmio_opp->instr, result, value,
652                      (unsigned long) p->data, regs);
653        set_eflags_OF(size, mmio_opp->instr, result, value,
654                      (unsigned long) p->data, regs);
655        set_eflags_AF(size, result, value, (unsigned long) p->data, regs);
656        set_eflags_ZF(size, result, regs);
657        set_eflags_SF(size, result, regs);
658        set_eflags_PF(size, result, regs);
659        break;
660
661    case INSTR_OR:
662        if (src & REGISTER) {
663            index = operand_index(src);
664            value = get_reg_value(size, index, 0, regs);
665            result = (unsigned long) p->data | value;
666        } else if (src & IMMEDIATE) {
667            value = mmio_opp->immediate;
668            result = (unsigned long) p->data | value;
669        } else if (src & MEMORY) {
670            index = operand_index(dst);
671            value = get_reg_value(size, index, 0, regs);
672            result = (unsigned long) p->data | value;
673            set_reg_value(size, index, 0, regs, result);
674        }
675
676        /*
677         * The OF and CF flags are cleared; the SF, ZF, and PF
678         * flags are set according to the result. The state of
679         * the AF flag is undefined.
680         */
681        regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|
682                          X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
683        set_eflags_ZF(size, result, regs);
684        set_eflags_SF(size, result, regs);
685        set_eflags_PF(size, result, regs);
686        break;
687
688    case INSTR_XOR:
689        if (src & REGISTER) {
690            index = operand_index(src);
691            value = get_reg_value(size, index, 0, regs);
692            result = (unsigned long) p->data ^ value;
693        } else if (src & IMMEDIATE) {
694            value = mmio_opp->immediate;
695            result = (unsigned long) p->data ^ value;
696        } else if (src & MEMORY) {
697            index = operand_index(dst);
698            value = get_reg_value(size, index, 0, regs);
699            result = (unsigned long) p->data ^ value;
700            set_reg_value(size, index, 0, regs, result);
701        }
702
703        /*
704         * The OF and CF flags are cleared; the SF, ZF, and PF
705         * flags are set according to the result. The state of
706         * the AF flag is undefined.
707         */
708        regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|
709                          X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
710        set_eflags_ZF(size, result, regs);
711        set_eflags_SF(size, result, regs);
712        set_eflags_PF(size, result, regs);
713        break;
714
715    case INSTR_CMP:
716    case INSTR_SUB:
717        if (src & REGISTER) {
718            index = operand_index(src);
719            value = get_reg_value(size, index, 0, regs);
720            result = (unsigned long) p->data - value;
721        } else if (src & IMMEDIATE) {
722            value = mmio_opp->immediate;
723            result = (unsigned long) p->data - value;
724        } else if (src & MEMORY) {
725            index = operand_index(dst);
726            value = get_reg_value(size, index, 0, regs);
727            result = value - (unsigned long) p->data;
728            if ( mmio_opp->instr == INSTR_SUB )
729                set_reg_value(size, index, 0, regs, result);
730        }
731
732        /*
733         * The CF, OF, SF, ZF, AF, and PF flags are set according
734         * to the result
735         */
736        regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|X86_EFLAGS_AF|
737                          X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
738        if ( src & (REGISTER | IMMEDIATE) )
739        {
740            set_eflags_CF(size, mmio_opp->instr, result, value,
741                          (unsigned long) p->data, regs);
742            set_eflags_OF(size, mmio_opp->instr, result, value,
743                          (unsigned long) p->data, regs);
744        }
745        else
746        {
747            set_eflags_CF(size, mmio_opp->instr, result,
748                          (unsigned long) p->data, value, regs);
749            set_eflags_OF(size, mmio_opp->instr, result,
750                          (unsigned long) p->data, value, regs);
751        }
752        set_eflags_AF(size, result, value, (unsigned long) p->data, regs);
753        set_eflags_ZF(size, result, regs);
754        set_eflags_SF(size, result, regs);
755        set_eflags_PF(size, result, regs);
756        break;
757
758    case INSTR_TEST:
759        if (src & REGISTER) {
760            index = operand_index(src);
761            value = get_reg_value(size, index, 0, regs);
762        } else if (src & IMMEDIATE) {
763            value = mmio_opp->immediate;
764        } else if (src & MEMORY) {
765            index = operand_index(dst);
766            value = get_reg_value(size, index, 0, regs);
767        }
768        result = (unsigned long) p->data & value;
769
770        /*
771         * Sets the SF, ZF, and PF status flags. CF and OF are set to 0
772         */
773        regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|
774                          X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
775        set_eflags_ZF(size, result, regs);
776        set_eflags_SF(size, result, regs);
777        set_eflags_PF(size, result, regs);
778        break;
779
780    case INSTR_BT:
781        if ( src & REGISTER )
782        {
783            index = operand_index(src);
784            value = get_reg_value(size, index, 0, regs);
785        }
786        else if ( src & IMMEDIATE )
787            value = mmio_opp->immediate;
788        if (p->data & (1 << (value & ((1 << 5) - 1))))
789            regs->eflags |= X86_EFLAGS_CF;
790        else
791            regs->eflags &= ~X86_EFLAGS_CF;
792
793        break;
794
795    case INSTR_XCHG:
796        if (src & REGISTER) {
797            index = operand_index(src);
798            set_reg_value(size, index, 0, regs, p->data);
799        } else {
800            index = operand_index(dst);
801            set_reg_value(size, index, 0, regs, p->data);
802        }
803        break;
804
805    case INSTR_PUSH:
806        mmio_opp->addr += hvm_get_segment_base(current, x86_seg_ss);
807        {
808            unsigned long addr = mmio_opp->addr;
809            int rv = hvm_copy_to_guest_virt(addr, &p->data, size);
810            if ( rv != 0 )
811            {
812                addr += p->size - rv;
813                gdprintk(XENLOG_DEBUG, "Pagefault emulating PUSH from MMIO:"
814                         " va=%#lx\n", addr);
815                hvm_inject_exception(TRAP_page_fault, PFEC_write_access, addr);
816                return;
817            }
818        }
819        break;
820    }
821}
822
823void hvm_io_assist(void)
824{
825    vcpu_iodata_t *vio;
826    ioreq_t *p;
827    struct cpu_user_regs *regs;
828    struct hvm_io_op *io_opp;
829    unsigned long gmfn;
830    struct vcpu *v = current;
831    struct domain *d = v->domain;
832
833    io_opp = &v->arch.hvm_vcpu.io_op;
834    regs   = &io_opp->io_context;
835    vio    = get_ioreq(v);
836
837    p = &vio->vp_ioreq;
838    if ( p->state != STATE_IORESP_READY )
839    {
840        gdprintk(XENLOG_ERR, "Unexpected HVM iorequest state %d.\n", p->state);
841        domain_crash_synchronous();
842    }
843
844    rmb(); /* see IORESP_READY /then/ read contents of ioreq */
845
846    p->state = STATE_IOREQ_NONE;
847
848    switch ( p->type )
849    {
850    case IOREQ_TYPE_INVALIDATE:
851        goto out;
852    case IOREQ_TYPE_PIO:
853        hvm_pio_assist(regs, p, io_opp);
854        break;
855    default:
856        hvm_mmio_assist(regs, p, io_opp);
857        break;
858    }
859
860    /* Copy register changes back into current guest state. */
861    hvm_load_cpu_guest_regs(v, regs);
862    memcpy(guest_cpu_user_regs(), regs, HVM_CONTEXT_STACK_BYTES);
863
864    /* Has memory been dirtied? */
865    if ( (p->dir == IOREQ_READ) && p->data_is_ptr )
866    {
867        gmfn = get_mfn_from_gpfn(paging_gva_to_gfn(v, p->data));
868        mark_dirty(d, gmfn);
869    }
870
871 out:
872    vcpu_end_shutdown_deferral(v);
873}
874
875/*
876 * Local variables:
877 * mode: C
878 * c-set-style: "BSD"
879 * c-basic-offset: 4
880 * tab-width: 4
881 * indent-tabs-mode: nil
882 * End:
883 */
Note: See TracBrowser for help on using the repository browser.