Regenerate bios for vapic up changes
[qemu-kvm/fedora.git] / kvm-tpr-opt.c
blobc73b8288da3a44f6069dfc925732dcafcead9035
2 #include "config.h"
3 #include "config-host.h"
5 #include <string.h>
7 #include "hw/hw.h"
8 #include "sysemu.h"
9 #include "qemu-kvm.h"
10 #include "cpu.h"
12 #include <stdio.h>
14 extern kvm_context_t kvm_context;
16 static uint64_t map_addr(struct kvm_sregs *sregs, target_ulong virt, unsigned *perms)
18 uint64_t mask = ((1ull << 48) - 1) & ~4095ull;
19 uint64_t p, pp = 7;
21 p = sregs->cr3;
22 if (sregs->cr4 & 0x20) {
23 p &= ~31ull;
24 p = ldq_phys(p + 8 * (virt >> 30));
25 if (!(p & 1))
26 return -1ull;
27 p &= mask;
28 p = ldq_phys(p + 8 * ((virt >> 21) & 511));
29 if (!(p & 1))
30 return -1ull;
31 pp &= p;
32 if (p & 128) {
33 p += ((virt >> 12) & 511) << 12;
34 } else {
35 p &= mask;
36 p = ldq_phys(p + 8 * ((virt >> 12) & 511));
37 if (!(p & 1))
38 return -1ull;
39 pp &= p;
41 } else {
42 p &= mask;
43 p = ldl_phys(p + 4 * ((virt >> 22) & 1023));
44 if (!(p & 1))
45 return -1ull;
46 pp &= p;
47 if (p & 128) {
48 p += ((virt >> 12) & 1023) << 12;
49 } else {
50 p &= mask;
51 p = ldl_phys(p + 4 * ((virt >> 12) & 1023));
52 pp &= p;
53 if (!(p & 1))
54 return -1ull;
57 if (perms)
58 *perms = pp >> 1;
59 p &= mask;
60 return p + (virt & 4095);
63 static uint8_t read_byte_virt(CPUState *env, target_ulong virt)
65 struct kvm_sregs sregs;
67 kvm_get_sregs(kvm_context, env->cpu_index, &sregs);
68 return ldub_phys(map_addr(&sregs, virt, NULL));
71 static void write_byte_virt(CPUState *env, target_ulong virt, uint8_t b)
73 struct kvm_sregs sregs;
75 kvm_get_sregs(kvm_context, env->cpu_index, &sregs);
76 stb_phys(map_addr(&sregs, virt, NULL), b);
79 static uint32_t get_bios_map(CPUState *env, unsigned *perms)
81 uint32_t v;
82 struct kvm_sregs sregs;
84 kvm_get_sregs(kvm_context, env->cpu_index, &sregs);
86 for (v = -4096u; v != 0; v -= 4096)
87 if (map_addr(&sregs, v, perms) == 0xe0000)
88 return v;
89 return -1u;
92 struct vapic_bios {
93 char signature[8];
94 uint32_t virt_base;
95 uint32_t fixup_start;
96 uint32_t fixup_end;
97 uint32_t vapic;
98 uint32_t vapic_size;
99 uint32_t vcpu_shift;
100 uint32_t real_tpr;
101 struct vapic_patches {
102 uint32_t set_tpr;
103 uint32_t set_tpr_eax;
104 uint32_t get_tpr[8];
105 } __attribute__((packed)) up, mp;
106 } __attribute__((packed));
108 static struct vapic_bios vapic_bios;
110 static uint32_t real_tpr;
111 static uint32_t bios_addr;
112 static uint32_t vapic_phys;
113 static int bios_enabled;
114 static uint32_t vbios_desc_phys;
116 void update_vbios_real_tpr()
118 cpu_physical_memory_rw(vbios_desc_phys, (void *)&vapic_bios, sizeof vapic_bios, 0);
119 vapic_bios.real_tpr = real_tpr;
120 vapic_bios.vcpu_shift = 7;
121 cpu_physical_memory_rw(vbios_desc_phys, (void *)&vapic_bios, sizeof vapic_bios, 1);
124 static unsigned modrm_reg(uint8_t modrm)
126 return (modrm >> 3) & 7;
129 static int is_abs_modrm(uint8_t modrm)
131 return (modrm & 0xc7) == 0x05;
134 static int instruction_is_ok(CPUState *env, uint64_t rip, int is_write)
136 uint8_t b1, b2;
137 unsigned addr_offset;
138 uint32_t addr;
139 uint64_t p;
141 if ((rip & 0xf0000000) != 0x80000000 && (rip & 0xf0000000) != 0xe0000000)
142 return 0;
143 b1 = read_byte_virt(env, rip);
144 b2 = read_byte_virt(env, rip + 1);
145 switch (b1) {
146 case 0xc7: /* mov imm32, r/m32 (c7/0) */
147 if (modrm_reg(b2) != 0)
148 return 0;
149 /* fall through */
150 case 0x89: /* mov r32 to r/m32 */
151 case 0x8b: /* mov r/m32 to r32 */
152 if (!is_abs_modrm(b2))
153 return 0;
154 addr_offset = 2;
155 break;
156 case 0xa1: /* mov abs to eax */
157 case 0xa3: /* mov eax to abs */
158 addr_offset = 1;
159 break;
160 default:
161 return 0;
163 p = rip + addr_offset;
164 addr = read_byte_virt(env, p++);
165 addr |= read_byte_virt(env, p++) << 8;
166 addr |= read_byte_virt(env, p++) << 16;
167 addr |= read_byte_virt(env, p++) << 24;
168 if ((addr & 0xfff) != 0x80)
169 return 0;
170 real_tpr = addr;
171 update_vbios_real_tpr();
172 return 1;
175 static int bios_is_mapped(CPUState *env, uint64_t rip)
177 uint32_t probe;
178 uint64_t phys;
179 struct kvm_sregs sregs;
180 unsigned perms;
181 uint32_t i;
182 uint32_t offset, fixup;
184 if (bios_enabled)
185 return 1;
187 kvm_get_sregs(kvm_context, env->cpu_index, &sregs);
189 probe = (rip & 0xf0000000) + 0xe0000;
190 phys = map_addr(&sregs, probe, &perms);
191 if (phys != 0xe0000)
192 return 0;
193 bios_addr = probe;
194 for (i = 0; i < 64; ++i) {
195 cpu_physical_memory_read(phys, (void *)&vapic_bios, sizeof(vapic_bios));
196 if (memcmp(vapic_bios.signature, "kvm aPiC", 8) == 0)
197 break;
198 phys += 1024;
199 bios_addr += 1024;
201 if (i == 64)
202 return 0;
203 if (bios_addr == vapic_bios.virt_base)
204 return 1;
205 vbios_desc_phys = phys;
206 for (i = vapic_bios.fixup_start; i < vapic_bios.fixup_end; i += 4) {
207 offset = ldl_phys(phys + i - vapic_bios.virt_base);
208 fixup = phys + offset;
209 stl_phys(fixup, ldl_phys(fixup) + bios_addr - vapic_bios.virt_base);
211 vapic_phys = vapic_bios.vapic - vapic_bios.virt_base + phys;
212 return 1;
215 static int enable_vapic(CPUState *env)
217 struct kvm_sregs sregs;
219 if (smp_cpus > 1) {/* uniprocessor doesn't need cpu id */
220 kvm_get_sregs(kvm_context, env->cpu_index, &sregs);
221 sregs.tr.selector = 0xdb + (env->cpu_index << 8);
222 kvm_set_sregs(kvm_context, env->cpu_index, &sregs);
225 kvm_enable_vapic(kvm_context, env->cpu_index,
226 vapic_phys + (env->cpu_index << 7));
227 bios_enabled = 1;
229 return 1;
232 static void patch_call(CPUState *env, uint64_t rip, uint32_t target)
234 uint32_t offset;
236 offset = target - vapic_bios.virt_base + bios_addr - rip - 5;
237 write_byte_virt(env, rip, 0xe8); /* call near */
238 write_byte_virt(env, rip + 1, offset);
239 write_byte_virt(env, rip + 2, offset >> 8);
240 write_byte_virt(env, rip + 3, offset >> 16);
241 write_byte_virt(env, rip + 4, offset >> 24);
244 static void patch_instruction(CPUState *env, uint64_t rip)
246 uint8_t b1, b2;
247 struct vapic_patches *vp;
249 vp = smp_cpus == 1 ? &vapic_bios.up : &vapic_bios.mp;
250 b1 = read_byte_virt(env, rip);
251 b2 = read_byte_virt(env, rip + 1);
252 switch (b1) {
253 case 0x89: /* mov r32 to r/m32 */
254 write_byte_virt(env, rip, 0x50 + modrm_reg(b2)); /* push reg */
255 patch_call(env, rip + 1, vp->set_tpr);
256 break;
257 case 0x8b: /* mov r/m32 to r32 */
258 write_byte_virt(env, rip, 0x90);
259 patch_call(env, rip + 1, vp->get_tpr[modrm_reg(b2)]);
260 break;
261 case 0xa1: /* mov abs to eax */
262 patch_call(env, rip, vp->get_tpr[0]);
263 break;
264 case 0xa3: /* mov eax to abs */
265 patch_call(env, rip, vp->set_tpr_eax);
266 break;
267 case 0xc7: /* mov imm32, r/m32 (c7/0) */
268 write_byte_virt(env, rip, 0x68); /* push imm32 */
269 write_byte_virt(env, rip + 1, read_byte_virt(env, rip+6));
270 write_byte_virt(env, rip + 2, read_byte_virt(env, rip+7));
271 write_byte_virt(env, rip + 3, read_byte_virt(env, rip+8));
272 write_byte_virt(env, rip + 4, read_byte_virt(env, rip+9));
273 patch_call(env, rip + 5, vp->set_tpr);
274 break;
275 default:
276 printf("funny insn %02x %02x\n", b1, b2);
280 void kvm_tpr_access_report(CPUState *env, uint64_t rip, int is_write)
282 if (!instruction_is_ok(env, rip, is_write))
283 return;
284 if (!bios_is_mapped(env, rip))
285 return;
286 if (!enable_vapic(env))
287 return;
288 patch_instruction(env, rip);
291 void kvm_tpr_vcpu_start(CPUState *env)
293 if (smp_cpus > 1)
294 return;
295 kvm_enable_tpr_access_reporting(kvm_context, env->cpu_index);
296 if (bios_enabled)
297 enable_vapic(env);
300 static void tpr_save(QEMUFile *f, void *s)
302 int i;
304 for (i = 0; i < (sizeof vapic_bios) / 4; ++i)
305 qemu_put_be32s(f, &((uint32_t *)&vapic_bios)[i]);
306 qemu_put_be32s(f, &bios_enabled);
307 qemu_put_be32s(f, &real_tpr);
308 qemu_put_be32s(f, &bios_addr);
309 qemu_put_be32s(f, &vapic_phys);
310 qemu_put_be32s(f, &vbios_desc_phys);
313 static int tpr_load(QEMUFile *f, void *s, int version_id)
315 int i;
317 if (version_id != 1)
318 return -EINVAL;
320 for (i = 0; i < (sizeof vapic_bios) / 4; ++i)
321 qemu_get_be32s(f, &((uint32_t *)&vapic_bios)[i]);
322 qemu_get_be32s(f, &bios_enabled);
323 qemu_get_be32s(f, &real_tpr);
324 qemu_get_be32s(f, &bios_addr);
325 qemu_get_be32s(f, &vapic_phys);
326 qemu_get_be32s(f, &vbios_desc_phys);
328 return 0;
331 void kvm_tpr_opt_setup(CPUState *env)
333 register_savevm("kvm-tpr-opt", 0, 1, tpr_save, tpr_load, NULL);