2 * tpr optimization for qemu/kvm
4 * Copyright (C) 2007-2008 Qumranet Technologies
6 * Licensed under the terms of the GNU GPL version 2 or higher.
10 #include "config-host.h"
21 extern kvm_context_t kvm_context
;
23 static uint64_t map_addr(struct kvm_sregs
*sregs
, target_ulong virt
, unsigned *perms
)
25 uint64_t mask
= ((1ull << 48) - 1) & ~4095ull;
29 if (sregs
->cr4
& 0x20) {
31 p
= ldq_phys(p
+ 8 * (virt
>> 30));
35 p
= ldq_phys(p
+ 8 * ((virt
>> 21) & 511));
40 p
+= ((virt
>> 12) & 511) << 12;
43 p
= ldq_phys(p
+ 8 * ((virt
>> 12) & 511));
50 p
= ldl_phys(p
+ 4 * ((virt
>> 22) & 1023));
55 p
+= ((virt
>> 12) & 1023) << 12;
58 p
= ldl_phys(p
+ 4 * ((virt
>> 12) & 1023));
67 return p
+ (virt
& 4095);
70 static uint8_t read_byte_virt(CPUState
*env
, target_ulong virt
)
72 struct kvm_sregs sregs
;
74 kvm_get_sregs(kvm_context
, env
->cpu_index
, &sregs
);
75 return ldub_phys(map_addr(&sregs
, virt
, NULL
));
78 static void write_byte_virt(CPUState
*env
, target_ulong virt
, uint8_t b
)
80 struct kvm_sregs sregs
;
82 kvm_get_sregs(kvm_context
, env
->cpu_index
, &sregs
);
83 stb_phys(map_addr(&sregs
, virt
, NULL
), b
);
86 static __u64
kvm_rsp_read(CPUState
*env
)
90 kvm_get_regs(kvm_context
, env
->cpu_index
, ®s
);
103 struct vapic_patches
{
105 uint32_t set_tpr_eax
;
107 uint32_t get_tpr_stack
;
108 } __attribute__((packed
)) up
, mp
;
109 } __attribute__((packed
));
111 static struct vapic_bios vapic_bios
;
113 static uint32_t real_tpr
;
114 static uint32_t bios_addr
;
115 static uint32_t vapic_phys
;
116 static int bios_enabled
;
117 static uint32_t vbios_desc_phys
;
119 void update_vbios_real_tpr()
121 cpu_physical_memory_rw(vbios_desc_phys
, (void *)&vapic_bios
, sizeof vapic_bios
, 0);
122 vapic_bios
.real_tpr
= real_tpr
;
123 vapic_bios
.vcpu_shift
= 7;
124 cpu_physical_memory_rw(vbios_desc_phys
, (void *)&vapic_bios
, sizeof vapic_bios
, 1);
127 static unsigned modrm_reg(uint8_t modrm
)
129 return (modrm
>> 3) & 7;
132 static int is_abs_modrm(uint8_t modrm
)
134 return (modrm
& 0xc7) == 0x05;
137 static int instruction_is_ok(CPUState
*env
, uint64_t rip
, int is_write
)
140 unsigned addr_offset
;
144 if ((rip
& 0xf0000000) != 0x80000000 && (rip
& 0xf0000000) != 0xe0000000)
146 if (kvm_rsp_read(env
) == 0)
148 b1
= read_byte_virt(env
, rip
);
149 b2
= read_byte_virt(env
, rip
+ 1);
151 case 0xc7: /* mov imm32, r/m32 (c7/0) */
152 if (modrm_reg(b2
) != 0)
155 case 0x89: /* mov r32 to r/m32 */
156 case 0x8b: /* mov r/m32 to r32 */
157 if (!is_abs_modrm(b2
))
161 case 0xa1: /* mov abs to eax */
162 case 0xa3: /* mov eax to abs */
165 case 0xff: /* push r/m32 */
166 if (modrm_reg(b2
) != 6 || !is_abs_modrm(b2
))
172 p
= rip
+ addr_offset
;
173 addr
= read_byte_virt(env
, p
++);
174 addr
|= read_byte_virt(env
, p
++) << 8;
175 addr
|= read_byte_virt(env
, p
++) << 16;
176 addr
|= read_byte_virt(env
, p
++) << 24;
177 if ((addr
& 0xfff) != 0x80)
180 update_vbios_real_tpr();
184 static int bios_is_mapped(CPUState
*env
, uint64_t rip
)
188 struct kvm_sregs sregs
;
191 uint32_t offset
, fixup
;
196 kvm_get_sregs(kvm_context
, env
->cpu_index
, &sregs
);
198 probe
= (rip
& 0xf0000000) + 0xe0000;
199 phys
= map_addr(&sregs
, probe
, &perms
);
203 for (i
= 0; i
< 64; ++i
) {
204 cpu_physical_memory_read(phys
, (void *)&vapic_bios
, sizeof(vapic_bios
));
205 if (memcmp(vapic_bios
.signature
, "kvm aPiC", 8) == 0)
212 if (bios_addr
== vapic_bios
.virt_base
)
214 vbios_desc_phys
= phys
;
215 for (i
= vapic_bios
.fixup_start
; i
< vapic_bios
.fixup_end
; i
+= 4) {
216 offset
= ldl_phys(phys
+ i
- vapic_bios
.virt_base
);
217 fixup
= phys
+ offset
;
218 stl_phys(fixup
, ldl_phys(fixup
) + bios_addr
- vapic_bios
.virt_base
);
220 vapic_phys
= vapic_bios
.vapic
- vapic_bios
.virt_base
+ phys
;
224 static int enable_vapic(CPUState
*env
)
226 struct kvm_sregs sregs
;
228 if (smp_cpus
> 1) {/* uniprocessor doesn't need cpu id */
229 kvm_get_sregs(kvm_context
, env
->cpu_index
, &sregs
);
230 sregs
.tr
.selector
= 0xdb + (env
->cpu_index
<< 8);
231 kvm_set_sregs(kvm_context
, env
->cpu_index
, &sregs
);
234 kvm_enable_vapic(kvm_context
, env
->cpu_index
,
235 vapic_phys
+ (env
->cpu_index
<< 7));
241 static void patch_call(CPUState
*env
, uint64_t rip
, uint32_t target
)
245 offset
= target
- vapic_bios
.virt_base
+ bios_addr
- rip
- 5;
246 write_byte_virt(env
, rip
, 0xe8); /* call near */
247 write_byte_virt(env
, rip
+ 1, offset
);
248 write_byte_virt(env
, rip
+ 2, offset
>> 8);
249 write_byte_virt(env
, rip
+ 3, offset
>> 16);
250 write_byte_virt(env
, rip
+ 4, offset
>> 24);
253 static void patch_instruction(CPUState
*env
, uint64_t rip
)
256 struct vapic_patches
*vp
;
258 vp
= smp_cpus
== 1 ? &vapic_bios
.up
: &vapic_bios
.mp
;
259 b1
= read_byte_virt(env
, rip
);
260 b2
= read_byte_virt(env
, rip
+ 1);
262 case 0x89: /* mov r32 to r/m32 */
263 write_byte_virt(env
, rip
, 0x50 + modrm_reg(b2
)); /* push reg */
264 patch_call(env
, rip
+ 1, vp
->set_tpr
);
266 case 0x8b: /* mov r/m32 to r32 */
267 write_byte_virt(env
, rip
, 0x90);
268 patch_call(env
, rip
+ 1, vp
->get_tpr
[modrm_reg(b2
)]);
270 case 0xa1: /* mov abs to eax */
271 patch_call(env
, rip
, vp
->get_tpr
[0]);
273 case 0xa3: /* mov eax to abs */
274 patch_call(env
, rip
, vp
->set_tpr_eax
);
276 case 0xc7: /* mov imm32, r/m32 (c7/0) */
277 write_byte_virt(env
, rip
, 0x68); /* push imm32 */
278 write_byte_virt(env
, rip
+ 1, read_byte_virt(env
, rip
+6));
279 write_byte_virt(env
, rip
+ 2, read_byte_virt(env
, rip
+7));
280 write_byte_virt(env
, rip
+ 3, read_byte_virt(env
, rip
+8));
281 write_byte_virt(env
, rip
+ 4, read_byte_virt(env
, rip
+9));
282 patch_call(env
, rip
+ 5, vp
->set_tpr
);
284 case 0xff: /* push r/m32 */
285 printf("patching push\n");
286 write_byte_virt(env
, rip
, 0x50); /* push eax */
287 patch_call(env
, rip
+ 1, vp
->get_tpr_stack
);
290 printf("funny insn %02x %02x\n", b1
, b2
);
294 void kvm_tpr_access_report(CPUState
*env
, uint64_t rip
, int is_write
)
296 if (!instruction_is_ok(env
, rip
, is_write
))
298 if (!bios_is_mapped(env
, rip
))
300 if (!enable_vapic(env
))
302 patch_instruction(env
, rip
);
305 void kvm_tpr_vcpu_start(CPUState
*env
)
307 kvm_enable_tpr_access_reporting(kvm_context
, env
->cpu_index
);
312 static void tpr_save(QEMUFile
*f
, void *s
)
316 for (i
= 0; i
< (sizeof vapic_bios
) / 4; ++i
)
317 qemu_put_be32s(f
, &((uint32_t *)&vapic_bios
)[i
]);
318 qemu_put_be32s(f
, &bios_enabled
);
319 qemu_put_be32s(f
, &real_tpr
);
320 qemu_put_be32s(f
, &bios_addr
);
321 qemu_put_be32s(f
, &vapic_phys
);
322 qemu_put_be32s(f
, &vbios_desc_phys
);
325 static int tpr_load(QEMUFile
*f
, void *s
, int version_id
)
332 for (i
= 0; i
< (sizeof vapic_bios
) / 4; ++i
)
333 qemu_get_be32s(f
, &((uint32_t *)&vapic_bios
)[i
]);
334 qemu_get_be32s(f
, &bios_enabled
);
335 qemu_get_be32s(f
, &real_tpr
);
336 qemu_get_be32s(f
, &bios_addr
);
337 qemu_get_be32s(f
, &vapic_phys
);
338 qemu_get_be32s(f
, &vbios_desc_phys
);
341 CPUState
*env
= first_cpu
->next_cpu
;
343 for (env
= first_cpu
; env
!= NULL
; env
= env
->next_cpu
)
350 void kvm_tpr_opt_setup(CPUState
*env
)
352 register_savevm("kvm-tpr-opt", 0, 1, tpr_save
, tpr_load
, NULL
);