xref: /illumos-kvm-cmd/kvm-tpr-opt.c (revision 68396ea9)
1 /*
2  * tpr optimization for qemu/kvm
3  *
4  * Copyright (C) 2007-2008 Qumranet Technologies
5  *
6  * Licensed under the terms of the GNU GPL version 2 or higher.
7  */
8 
9 #include "config.h"
10 #include "config-host.h"
11 
12 #include <string.h>
13 
14 #include "hw/hw.h"
15 #include "hw/isa.h"
16 #include "sysemu.h"
17 #include "kvm.h"
18 #include "cpu.h"
19 
20 #include <stdio.h>
21 
map_addr(CPUState * env,target_ulong virt,unsigned * perms)22 static uint64_t map_addr(CPUState *env, target_ulong virt, unsigned *perms)
23 {
24     uint64_t mask = ((1ull << 48) - 1) & ~4095ull;
25     uint64_t p, pp = 7;
26 
27     p = env->cr[3];
28     if (env->cr[4] & 0x20) {
29 	p &= ~31ull;
30 	p = ldq_phys(p + 8 * (virt >> 30));
31 	if (!(p & 1))
32 	    return -1ull;
33 	p &= mask;
34 	p = ldq_phys(p + 8 * ((virt >> 21) & 511));
35 	if (!(p & 1))
36 	    return -1ull;
37 	pp &= p;
38 	if (p & 128) {
39 	    p += ((virt >> 12) & 511) << 12;
40 	} else {
41 	    p &= mask;
42 	    p = ldq_phys(p + 8 * ((virt >> 12) & 511));
43 	    if (!(p & 1))
44 		return -1ull;
45 	    pp &= p;
46 	}
47     } else {
48 	p &= mask;
49 	p = ldl_phys(p + 4 * ((virt >> 22) & 1023));
50 	if (!(p & 1))
51 	    return -1ull;
52 	pp &= p;
53 	if (p & 128) {
54 	    p += ((virt >> 12) & 1023) << 12;
55 	} else {
56 	    p &= mask;
57 	    p = ldl_phys(p + 4 * ((virt >> 12) & 1023));
58 	    pp &= p;
59 	    if (!(p & 1))
60 		return -1ull;
61 	}
62     }
63     if (perms)
64 	*perms = pp >> 1;
65     p &= mask;
66     return p + (virt & 4095);
67 }
68 
read_byte_virt(CPUState * env,target_ulong virt)69 static uint8_t read_byte_virt(CPUState *env, target_ulong virt)
70 {
71     return ldub_phys(map_addr(env, virt, NULL));
72 }
73 
write_byte_virt(CPUState * env,target_ulong virt,uint8_t b)74 static void write_byte_virt(CPUState *env, target_ulong virt, uint8_t b)
75 {
76     cpu_physical_memory_write_rom(map_addr(env, virt, NULL), &b, 1);
77 }
78 
79 struct vapic_bios {
80     char signature[8];
81     uint32_t virt_base;
82     uint32_t fixup_start;
83     uint32_t fixup_end;
84     uint32_t vapic;
85     uint32_t vapic_size;
86     uint32_t vcpu_shift;
87     uint32_t real_tpr;
88     struct vapic_patches {
89 	uint32_t set_tpr;
90 	uint32_t set_tpr_eax;
91 	uint32_t get_tpr[8];
92         uint32_t get_tpr_stack;
93     } __attribute__((packed)) up, mp;
94 } __attribute__((packed));
95 
96 static struct vapic_bios vapic_bios;
97 
98 static uint32_t real_tpr;
99 static uint32_t bios_addr;
100 static uint32_t vapic_phys;
101 static uint32_t bios_enabled;
102 static uint32_t vbios_desc_phys;
103 static uint32_t vapic_bios_addr;
104 
update_vbios_real_tpr(void)105 static void update_vbios_real_tpr(void)
106 {
107     cpu_physical_memory_rw(vbios_desc_phys, (void *)&vapic_bios, sizeof vapic_bios, 0);
108     vapic_bios.real_tpr = real_tpr;
109     vapic_bios.vcpu_shift = 7;
110     cpu_physical_memory_write_rom(vbios_desc_phys, (void *)&vapic_bios, sizeof vapic_bios);
111 }
112 
modrm_reg(uint8_t modrm)113 static unsigned modrm_reg(uint8_t modrm)
114 {
115     return (modrm >> 3) & 7;
116 }
117 
is_abs_modrm(uint8_t modrm)118 static int is_abs_modrm(uint8_t modrm)
119 {
120     return (modrm & 0xc7) == 0x05;
121 }
122 
instruction_is_ok(CPUState * env,uint64_t rip,int is_write)123 static int instruction_is_ok(CPUState *env, uint64_t rip, int is_write)
124 {
125     uint8_t b1, b2;
126     unsigned addr_offset;
127     uint32_t addr;
128     uint64_t p;
129 
130     if ((rip & 0xf0000000) != 0x80000000 && (rip & 0xf0000000) != 0xe0000000)
131 	return 0;
132     if (env->regs[R_ESP] == 0)
133         return 0;
134     b1 = read_byte_virt(env, rip);
135     b2 = read_byte_virt(env, rip + 1);
136     switch (b1) {
137     case 0xc7: /* mov imm32, r/m32 (c7/0) */
138 	if (modrm_reg(b2) != 0)
139 	    return 0;
140 	/* fall through */
141     case 0x89: /* mov r32 to r/m32 */
142     case 0x8b: /* mov r/m32 to r32 */
143 	if (!is_abs_modrm(b2))
144 	    return 0;
145 	addr_offset = 2;
146 	break;
147     case 0xa1: /* mov abs to eax */
148     case 0xa3: /* mov eax to abs */
149 	addr_offset = 1;
150 	break;
151     case 0xff: /* push r/m32 */
152         if (modrm_reg(b2) != 6 || !is_abs_modrm(b2))
153             return 0;
154         addr_offset = 2;
155     default:
156 	return 0;
157     }
158     p = rip + addr_offset;
159     addr = read_byte_virt(env, p++);
160     addr |= read_byte_virt(env, p++) << 8;
161     addr |= read_byte_virt(env, p++) << 16;
162     addr |= read_byte_virt(env, p++) << 24;
163     if ((addr & 0xfff) != 0x80)
164 	return 0;
165     real_tpr = addr;
166     update_vbios_real_tpr();
167     return 1;
168 }
169 
bios_is_mapped(CPUState * env,uint64_t rip)170 static int bios_is_mapped(CPUState *env, uint64_t rip)
171 {
172     uint32_t probe;
173     uint64_t phys;
174     unsigned perms;
175     uint32_t i;
176     uint32_t offset, fixup, start = vapic_bios_addr ? : 0xe0000;
177     uint32_t patch;
178 
179     if (bios_enabled)
180 	return 1;
181 
182     probe = (rip & 0xf0000000) + start;
183     phys = map_addr(env, probe, &perms);
184     if (phys != start)
185 	return 0;
186     bios_addr = probe;
187     for (i = 0; i < 64; ++i) {
188 	cpu_physical_memory_read(phys, (void *)&vapic_bios, sizeof(vapic_bios));
189 	if (memcmp(vapic_bios.signature, "kvm aPiC", 8) == 0)
190 	    break;
191 	phys += 1024;
192 	bios_addr += 1024;
193     }
194     if (i == 64)
195 	return 0;
196     if (bios_addr == vapic_bios.virt_base)
197 	return 1;
198     vbios_desc_phys = phys;
199     for (i = vapic_bios.fixup_start; i < vapic_bios.fixup_end; i += 4) {
200 	offset = ldl_phys(phys + i - vapic_bios.virt_base);
201 	fixup = phys + offset;
202         patch = ldl_phys(fixup) + bios_addr - vapic_bios.virt_base;
203         cpu_physical_memory_write_rom(fixup, (uint8_t *)&patch, 4);
204     }
205     vapic_phys = vapic_bios.vapic - vapic_bios.virt_base + phys;
206     return 1;
207 }
208 
get_pcr_cpu(CPUState * env)209 static int get_pcr_cpu(CPUState *env)
210 {
211     uint8_t b;
212 
213     cpu_synchronize_state(env);
214 
215     if (cpu_memory_rw_debug(env, env->segs[R_FS].base + 0x51, &b, 1, 0) < 0)
216 	    return -1;
217 
218     return (int)b;
219 }
220 
kvm_tpr_enable_vapic(CPUState * env)221 int kvm_tpr_enable_vapic(CPUState *env)
222 {
223     static uint8_t one = 1;
224     int pcr_cpu = get_pcr_cpu(env);
225 
226     if (pcr_cpu < 0)
227 	    return 0;
228 
229     kvm_enable_vapic(env, vapic_phys + (pcr_cpu << 7));
230     cpu_physical_memory_write_rom(vapic_phys + (pcr_cpu << 7) + 4, &one, 1);
231     env->kvm_vcpu_update_vapic = 0;
232     bios_enabled = 1;
233     return 1;
234 }
235 
patch_call(CPUState * env,uint64_t rip,uint32_t target)236 static void patch_call(CPUState *env, uint64_t rip, uint32_t target)
237 {
238     uint32_t offset;
239 
240     offset = target - vapic_bios.virt_base + bios_addr - rip - 5;
241     write_byte_virt(env, rip, 0xe8); /* call near */
242     write_byte_virt(env, rip + 1, offset);
243     write_byte_virt(env, rip + 2, offset >> 8);
244     write_byte_virt(env, rip + 3, offset >> 16);
245     write_byte_virt(env, rip + 4, offset >> 24);
246 }
247 
patch_instruction(CPUState * env,uint64_t rip)248 static void patch_instruction(CPUState *env, uint64_t rip)
249 {
250     uint8_t b1, b2;
251     struct vapic_patches *vp;
252 
253     vp = smp_cpus == 1 ? &vapic_bios.up : &vapic_bios.mp;
254     b1 = read_byte_virt(env, rip);
255     b2 = read_byte_virt(env, rip + 1);
256     switch (b1) {
257     case 0x89: /* mov r32 to r/m32 */
258 	write_byte_virt(env, rip, 0x50 + modrm_reg(b2));  /* push reg */
259 	patch_call(env, rip + 1, vp->set_tpr);
260 	break;
261     case 0x8b: /* mov r/m32 to r32 */
262 	write_byte_virt(env, rip, 0x90);
263 	patch_call(env, rip + 1, vp->get_tpr[modrm_reg(b2)]);
264 	break;
265     case 0xa1: /* mov abs to eax */
266 	patch_call(env, rip, vp->get_tpr[0]);
267 	break;
268     case 0xa3: /* mov eax to abs */
269 	patch_call(env, rip, vp->set_tpr_eax);
270 	break;
271     case 0xc7: /* mov imm32, r/m32 (c7/0) */
272 	write_byte_virt(env, rip, 0x68);  /* push imm32 */
273 	write_byte_virt(env, rip + 1, read_byte_virt(env, rip+6));
274 	write_byte_virt(env, rip + 2, read_byte_virt(env, rip+7));
275 	write_byte_virt(env, rip + 3, read_byte_virt(env, rip+8));
276 	write_byte_virt(env, rip + 4, read_byte_virt(env, rip+9));
277 	patch_call(env, rip + 5, vp->set_tpr);
278 	break;
279     case 0xff: /* push r/m32 */
280         printf("patching push\n");
281         write_byte_virt(env, rip, 0x50); /* push eax */
282         patch_call(env, rip + 1, vp->get_tpr_stack);
283         break;
284     default:
285 	printf("funny insn %02x %02x\n", b1, b2);
286     }
287 }
288 
kvm_tpr_access_report(CPUState * env,uint64_t rip,int is_write)289 void kvm_tpr_access_report(CPUState *env, uint64_t rip, int is_write)
290 {
291     cpu_synchronize_state(env);
292     if (!instruction_is_ok(env, rip, is_write))
293 	return;
294     if (!bios_is_mapped(env, rip))
295 	return;
296     if (!kvm_tpr_enable_vapic(env))
297 	return;
298     patch_instruction(env, rip);
299 }
300 
tpr_save(QEMUFile * f,void * s)301 static void tpr_save(QEMUFile *f, void *s)
302 {
303     int i;
304 
305     for (i = 0; i < (sizeof vapic_bios) / 4; ++i)
306 	qemu_put_be32s(f, &((uint32_t *)&vapic_bios)[i]);
307     qemu_put_be32s(f, &bios_enabled);
308     qemu_put_be32s(f, &real_tpr);
309     qemu_put_be32s(f, &bios_addr);
310     qemu_put_be32s(f, &vapic_phys);
311     qemu_put_be32s(f, &vbios_desc_phys);
312 }
313 
tpr_load(QEMUFile * f,void * s,int version_id)314 static int tpr_load(QEMUFile *f, void *s, int version_id)
315 {
316     int i;
317 
318     if (version_id != 1)
319 	return -EINVAL;
320 
321     for (i = 0; i < (sizeof vapic_bios) / 4; ++i)
322 	qemu_get_be32s(f, &((uint32_t *)&vapic_bios)[i]);
323     qemu_get_be32s(f, &bios_enabled);
324     qemu_get_be32s(f, &real_tpr);
325     qemu_get_be32s(f, &bios_addr);
326     qemu_get_be32s(f, &vapic_phys);
327     qemu_get_be32s(f, &vbios_desc_phys);
328 
329     if (bios_enabled) {
330         CPUState *env = first_cpu->next_cpu;
331 
332         for (env = first_cpu; env != NULL; env = env->next_cpu)
333             env->kvm_vcpu_update_vapic = 1;
334     }
335 
336     return 0;
337 }
338 
vtpr_ioport_write16(void * opaque,uint32_t addr,uint32_t val)339 static void vtpr_ioport_write16(void *opaque, uint32_t addr, uint32_t val)
340 {
341     CPUState *env = cpu_single_env;
342 
343     cpu_synchronize_state(env);
344 
345     vapic_bios_addr = ((env->segs[R_CS].base + env->eip) & ~(512 - 1)) + val;
346     bios_enabled = 0;
347 }
348 
vtpr_ioport_write(void * opaque,uint32_t addr,uint32_t val)349 static void vtpr_ioport_write(void *opaque, uint32_t addr, uint32_t val)
350 {
351     CPUState *env = cpu_single_env;
352     uint32_t rip;
353 
354     cpu_synchronize_state(env);
355 
356     rip = env->eip - 2;
357     write_byte_virt(env, rip, 0x66);
358     write_byte_virt(env, rip + 1, 0x90);
359     if (bios_enabled)
360 	return;
361     if (!bios_is_mapped(env, rip))
362 	printf("bios not mapped?\n");
363     for (addr = 0xfffff000u; addr >= 0x80000000u; addr -= 4096)
364 	if (map_addr(env, addr, NULL) == 0xfee00000u) {
365 	    real_tpr = addr + 0x80;
366 	    break;
367 	}
368     bios_enabled = 1;
369     update_vbios_real_tpr();
370     kvm_tpr_enable_vapic(env);
371 }
372 
kvm_tpr_opt_setup(void)373 static void kvm_tpr_opt_setup(void)
374 {
375     register_savevm(NULL, "kvm-tpr-opt", 0, 1, tpr_save, tpr_load, NULL);
376     register_ioport_write(0x7e, 1, 1, vtpr_ioport_write, NULL);
377     register_ioport_write(0x7e, 2, 2, vtpr_ioport_write16, NULL);
378 }
379 
380 device_init(kvm_tpr_opt_setup);
381