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
43 #include "libfkvm-common.h"
46 #define reg_size() _reg_size(regs, sregs)
47 #define test_repeat_noop() _test_repeat_noop(insn->prefix == insn_rep_zero, \
49 #define test_repeat_tail() _test_repeat_tail(insn->prefix == insn_rep_zero, \
53 emulate_cr_mov(kvm_context_t kvm
,
54 struct kvm_regs
*regs
,
55 struct kvm_sregs
*sregs
,
61 unsigned int dest_size
;
62 unsigned int src_size
;
66 assert(insn
->prefix
== insn_no_prefix
);
67 assert(insn
->explicit_count
== 2);
69 dest_op
= x86_operand_1st(insn
);
70 src_op
= x86_operand_2nd(insn
);
72 dest_size
= x86_operand_size(dest_op
);
73 src_size
= x86_operand_size(src_op
);
74 assert(dest_size
== src_size
);
76 assert(src_op
->type
== op_register
);
77 assert(dest_op
->type
== op_register
);
83 src_gp_num
= kvm_reg_from_x86_reg(src_op
->data
.reg
.id
);
87 data
= kvm_regs_get(regs
, src_gp_num
);
88 data
= mask_reg(data
, dest_size
);
90 if (dest_op
->data
.reg
.type
!= reg_sys
)
92 dest_cr_num
= cr_num_from_x86_reg(dest_op
->data
.reg
.id
);
93 if (dest_cr_num
!= cr_num
)
96 switch (dest_cr_num
) {
97 case 0: sregs
->cr0
= data
; break;
98 case 2: sregs
->cr2
= data
; break;
99 case 3: sregs
->cr3
= data
; break;
100 case 4: sregs
->cr4
= data
; break;
101 default: EXIT_ERR_PATH();
104 printf("wrote 0x%" PRIx64
" to CR%d\n", data
, dest_cr_num
);
110 if (src_op
->data
.reg
.type
!= reg_sys
)
112 src_cr_num
= cr_num_from_x86_reg(src_op
->data
.reg
.id
);
113 if (src_cr_num
!= cr_num
)
116 switch (src_cr_num
) {
117 case 0: data
= sregs
->cr0
; break;
118 case 2: data
= sregs
->cr2
; break;
119 case 3: data
= sregs
->cr3
; break;
120 case 4: data
= sregs
->cr4
; break;
121 default: EXIT_ERR_PATH();
123 data
= mask_reg(data
, dest_size
);
125 dest_gp_num
= kvm_reg_from_x86_reg(dest_op
->data
.reg
.id
);
126 if (dest_gp_num
== -1)
129 kvm_regs_set(regs
, dest_gp_num
, data
);
136 emulate_cr_lmsw(kvm_context_t kvm
,
137 struct kvm_regs
*regs
,
138 struct kvm_sregs
*sregs
,
145 assert(insn
->prefix
== insn_no_prefix
);
146 assert(insn
->explicit_count
== 1);
148 src_op
= x86_operand_1st(insn
);
149 assert(x86_operand_size(src_op
) == 2);
151 if (src_op
->type
!= op_register
)
154 src_gp_num
= kvm_reg_from_x86_reg(src_op
->data
.reg
.id
);
155 if (src_gp_num
== -1)
158 data
= kvm_regs_get(regs
, src_gp_num
);
160 /* from the manual: LMSW can set CR0.PE, but cannot clear it */
161 if ((data
& 0x1) == 0 && (sregs
->cr0
& 0x1) == 1)
164 sregs
->cr0
= (sregs
->cr0
& 0xFFFFFFFFFFFFFFF0) |
165 (data
& 0x000000000000000F);
171 emulate_cr_clts(kvm_context_t kvm
,
172 struct kvm_regs
*regs
,
173 struct kvm_sregs
*sregs
,
176 assert(insn
->prefix
== insn_no_prefix
);
177 assert(insn
->explicit_count
== 0);
184 emulate_cr(kvm_context_t kvm
,
185 struct kvm_regs
*regs
,
186 struct kvm_sregs
*sregs
,
191 uint64_t loc
, next_rip
;
192 unsigned int insn_size
;
195 libdisasm_init(reg_size());
197 loc
= sregs
->cs
.base
+ regs
->rip
;
198 insn_size
= get_x86_insn(loc
, &insn
);
202 printf("rip: %" PRIx64
"\n", regs
->rip
);
203 printf("loc: %" PRIx64
"\n", loc
);
204 next_rip
= regs
->rip
+ insn_size
;
210 error
= emulate_cr_mov(kvm
, regs
, sregs
, cr_num
, is_write
, &insn
);
215 error
= emulate_cr_lmsw(kvm
, regs
, sregs
, &insn
);
225 error
= emulate_cr_clts(kvm
, regs
, sregs
, &insn
);
228 printf("insn.type = 0x%x\n", insn
.type
);
233 regs
->rip
= next_rip
;