~ubuntu-branches/ubuntu/hardy/kvm/hardy-backports

« back to all changes in this revision

Viewing changes to qemu/kvm-tpr-opt.c

  • Committer: Bazaar Package Importer
  • Author(s): Soren Hansen
  • Date: 2008-02-26 13:10:57 UTC
  • mfrom: (1.1.18 upstream)
  • Revision ID: james.westby@ubuntu.com-20080226131057-s67x6l89mtjw1x9b
Tags: 1:62+dfsg-0ubuntu1
New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 */
1
8
 
2
9
#include "config.h"
3
10
#include "config-host.h"
98
105
    uint32_t vapic_size;
99
106
    uint32_t vcpu_shift;
100
107
    uint32_t real_tpr;
101
 
    uint32_t set_tpr;
102
 
    uint32_t set_tpr_eax;
103
 
    uint32_t get_tpr[8];
104
 
};
 
108
    struct vapic_patches {
 
109
        uint32_t set_tpr;
 
110
        uint32_t set_tpr_eax;
 
111
        uint32_t get_tpr[8];
 
112
    } __attribute__((packed)) up, mp;
 
113
} __attribute__((packed));
105
114
 
106
115
static struct vapic_bios vapic_bios;
107
116
 
214
223
{
215
224
    struct kvm_sregs sregs;
216
225
 
217
 
    kvm_get_sregs(kvm_context, env->cpu_index, &sregs);
218
 
    sregs.tr.selector = 0xdb + (env->cpu_index << 8);
219
 
    kvm_set_sregs(kvm_context, env->cpu_index, &sregs);
 
226
    if (smp_cpus > 1) {/* uniprocessor doesn't need cpu id */
 
227
        kvm_get_sregs(kvm_context, env->cpu_index, &sregs);
 
228
        sregs.tr.selector = 0xdb + (env->cpu_index << 8);
 
229
        kvm_set_sregs(kvm_context, env->cpu_index, &sregs);
 
230
    }
220
231
 
221
232
    kvm_enable_vapic(kvm_context, env->cpu_index,
222
233
                     vapic_phys + (env->cpu_index << 7));
 
234
    bios_enabled = 1;
 
235
 
223
236
    return 1;
224
237
}
225
238
 
238
251
static void patch_instruction(CPUState *env, uint64_t rip)
239
252
{
240
253
    uint8_t b1, b2;
 
254
    struct vapic_patches *vp;
241
255
 
 
256
    vp = smp_cpus == 1 ? &vapic_bios.up : &vapic_bios.mp;
242
257
    b1 = read_byte_virt(env, rip);
243
258
    b2 = read_byte_virt(env, rip + 1);
244
259
    switch (b1) {
245
260
    case 0x89: /* mov r32 to r/m32 */
246
261
        write_byte_virt(env, rip, 0x50 + modrm_reg(b2));  /* push reg */
247
 
        patch_call(env, rip + 1, vapic_bios.set_tpr);
 
262
        patch_call(env, rip + 1, vp->set_tpr);
248
263
        break;
249
264
    case 0x8b: /* mov r/m32 to r32 */
250
265
        write_byte_virt(env, rip, 0x90);
251
 
        patch_call(env, rip + 1, vapic_bios.get_tpr[modrm_reg(b2)]);
 
266
        patch_call(env, rip + 1, vp->get_tpr[modrm_reg(b2)]);
252
267
        break;
253
268
    case 0xa1: /* mov abs to eax */
254
 
        patch_call(env, rip, vapic_bios.get_tpr[0]);
 
269
        patch_call(env, rip, vp->get_tpr[0]);
255
270
        break;
256
271
    case 0xa3: /* mov eax to abs */
257
 
        patch_call(env, rip, vapic_bios.set_tpr_eax);
 
272
        patch_call(env, rip, vp->set_tpr_eax);
258
273
        break;
259
274
    case 0xc7: /* mov imm32, r/m32 (c7/0) */
260
275
        write_byte_virt(env, rip, 0x68);  /* push imm32 */
262
277
        write_byte_virt(env, rip + 2, read_byte_virt(env, rip+7));
263
278
        write_byte_virt(env, rip + 3, read_byte_virt(env, rip+8));
264
279
        write_byte_virt(env, rip + 4, read_byte_virt(env, rip+9));
265
 
        patch_call(env, rip + 5, vapic_bios.set_tpr);
 
280
        patch_call(env, rip + 5, vp->set_tpr);
266
281
        break;
267
282
    default:
268
283
        printf("funny insn %02x %02x\n", b1, b2);
280
295
    patch_instruction(env, rip);
281
296
}
282
297
 
283
 
void kvm_tpr_opt_setup(CPUState *env)
 
298
void kvm_tpr_vcpu_start(CPUState *env)
284
299
{
285
300
    if (smp_cpus > 1)
286
301
        return;
287
302
    kvm_enable_tpr_access_reporting(kvm_context, env->cpu_index);
288
 
}
 
303
    if (bios_enabled)
 
304
        enable_vapic(env);
 
305
}
 
306
 
 
307
static void tpr_save(QEMUFile *f, void *s)
 
308
{
 
309
    int i;
 
310
 
 
311
    for (i = 0; i < (sizeof vapic_bios) / 4; ++i)
 
312
        qemu_put_be32s(f, &((uint32_t *)&vapic_bios)[i]);
 
313
    qemu_put_be32s(f, &bios_enabled);
 
314
    qemu_put_be32s(f, &real_tpr);
 
315
    qemu_put_be32s(f, &bios_addr);
 
316
    qemu_put_be32s(f, &vapic_phys);
 
317
    qemu_put_be32s(f, &vbios_desc_phys);
 
318
}
 
319
 
 
320
static int tpr_load(QEMUFile *f, void *s, int version_id)
 
321
{
 
322
    int i;
 
323
 
 
324
    if (version_id != 1)
 
325
        return -EINVAL;
 
326
 
 
327
    for (i = 0; i < (sizeof vapic_bios) / 4; ++i)
 
328
        qemu_get_be32s(f, &((uint32_t *)&vapic_bios)[i]);
 
329
    qemu_get_be32s(f, &bios_enabled);
 
330
    qemu_get_be32s(f, &real_tpr);
 
331
    qemu_get_be32s(f, &bios_addr);
 
332
    qemu_get_be32s(f, &vapic_phys);
 
333
    qemu_get_be32s(f, &vbios_desc_phys);
 
334
  
 
335
    if (bios_enabled) {
 
336
        CPUState *env = first_cpu->next_cpu;
 
337
 
 
338
        for (env = first_cpu; env != NULL; env = env->next_cpu)
 
339
            enable_vapic(env);
 
340
    }
 
341
 
 
342
    return 0;
 
343
}
 
344
 
 
345
void kvm_tpr_opt_setup(CPUState *env)
 
346
{
 
347
    register_savevm("kvm-tpr-opt", 0, 1, tpr_save, tpr_load, NULL);
 
348
}
 
349