2 * Copyright (c) 2008 Brent Stephens <brents@rice.edu>
3 * Copyright (c) 2008 Diego Ongaro <diego.ongaro@rice.edu>
4 * Copyright (c) 2008 Oleg Pesok <olegpesok@gmail.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41 #include "libfkvm-common.h"
44 #define reg_size() _reg_size(regs, sregs)
45 #define test_repeat_noop() _test_repeat_noop(rep && string, \
47 #define test_repeat_tail() _test_repeat_tail(rep && string, \
50 /* TODO: check return value for kvm->callbacks->in* */
52 emulate_ioio_in(kvm_context_t kvm
,
53 struct kvm_regs
*regs
,
54 struct kvm_sregs
*sregs
,
62 if (test_repeat_noop())
68 kvm
->callbacks
->inb(kvm
->opaque
,
73 kvm
->callbacks
->inw(kvm
->opaque
,
78 kvm
->callbacks
->inl(kvm
->opaque
,
87 regs
->rdi
= mask_reg(regs
->rdi
, reg_size());
89 /* TODO: es limit check */
90 cpu_virtual_memory_rw(sregs
->es
.base
+ regs
->rdi
,
95 if ((regs
->rflags
& RFLAGS_DF_MASK
) != 0)
100 } while (test_repeat_tail());
105 /* TODO: check return value for kvm->callbacks->in* */
107 emulate_ioio_out(kvm_context_t kvm
,
108 struct kvm_regs
*regs
,
109 struct kvm_sregs
*sregs
,
117 if (test_repeat_noop())
125 /* SVM won't tell us whether there's a SEG prefix,
126 * so we need to decode the instruction */
127 struct kvm_segment
*segment
= &sregs
->ds
;
129 unsigned int insn_size
;
131 libdisasm_init(reg_size());
132 insn_size
= get_x86_insn(sregs
->cs
.base
+ regs
->rip
, &insn
);
135 segment
= kvm_seg_from_x86_op(sregs
, x86_operand_2nd(&insn
));
138 regs
->rsi
= mask_reg(regs
->rsi
, reg_size());
140 /* TODO: segment limit check */
141 cpu_virtual_memory_rw(segment
->base
+ regs
->rsi
,
146 if ((regs
->rflags
& RFLAGS_DF_MASK
) != 0)
153 kvm
->callbacks
->outb(kvm
->opaque
,
158 kvm
->callbacks
->outw(kvm
->opaque
,
163 kvm
->callbacks
->outl(kvm
->opaque
,
168 } while (test_repeat_tail());
174 emulate_ioio(kvm_context_t kvm
,
175 struct kvm_regs
*regs
,
176 struct kvm_sregs
*sregs
,
189 printf("emulate_ioio: invalid size (%u)\n", (int) size
);
195 return emulate_ioio_in(kvm
, regs
, sregs
,
196 port
, size
, rep
, string
);
199 return emulate_ioio_out(kvm
, regs
, sregs
,
200 port
, size
, rep
, string
);