aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvi Kivity <avi@qumranet.com>2008-01-28 20:07:19 +0200
committerAvi Kivity <avi@qumranet.com>2008-01-31 10:30:45 +0200
commitbacede8b325521774d04a6c1cbf041a30f0fa63d (patch)
tree019d79afc1be1861e88852f286a301110dc689c3 /kvm-tpr-opt.c
parentkvm: bios: separate vapic patch functions for smp and up (diff)
downloadqemu-kvm-bacede8b325521774d04a6c1cbf041a30f0fa63d.tar.gz
qemu-kvm-bacede8b325521774d04a6c1cbf041a30f0fa63d.tar.bz2
qemu-kvm-bacede8b325521774d04a6c1cbf041a30f0fa63d.zip
Adjust vapic for mp/up separation
Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'kvm-tpr-opt.c')
-rw-r--r--kvm-tpr-opt.c30
1 files changed, 18 insertions, 12 deletions
diff --git a/kvm-tpr-opt.c b/kvm-tpr-opt.c
index cbd869244..74ebdcdbd 100644
--- a/kvm-tpr-opt.c
+++ b/kvm-tpr-opt.c
@@ -98,10 +98,12 @@ struct vapic_bios {
uint32_t vapic_size;
uint32_t vcpu_shift;
uint32_t real_tpr;
- uint32_t set_tpr;
- uint32_t set_tpr_eax;
- uint32_t get_tpr[8];
-};
+ struct vapic_patches {
+ uint32_t set_tpr;
+ uint32_t set_tpr_eax;
+ uint32_t get_tpr[8];
+ } __attribute__((packed)) up, mp;
+} __attribute__((packed));
static struct vapic_bios vapic_bios;
@@ -214,9 +216,11 @@ static int enable_vapic(CPUState *env)
{
struct kvm_sregs sregs;
- kvm_get_sregs(kvm_context, env->cpu_index, &sregs);
- sregs.tr.selector = 0xdb + (env->cpu_index << 8);
- kvm_set_sregs(kvm_context, env->cpu_index, &sregs);
+ if (smp_cpus > 1) {/* uniprocessor doesn't need cpu id */
+ kvm_get_sregs(kvm_context, env->cpu_index, &sregs);
+ sregs.tr.selector = 0xdb + (env->cpu_index << 8);
+ kvm_set_sregs(kvm_context, env->cpu_index, &sregs);
+ }
kvm_enable_vapic(kvm_context, env->cpu_index,
vapic_phys + (env->cpu_index << 7));
@@ -238,23 +242,25 @@ static void patch_call(CPUState *env, uint64_t rip, uint32_t target)
static void patch_instruction(CPUState *env, uint64_t rip)
{
uint8_t b1, b2;
+ struct vapic_patches *vp;
+ vp = smp_cpus == 1 ? &vapic_bios.up : &vapic_bios.mp;
b1 = read_byte_virt(env, rip);
b2 = read_byte_virt(env, rip + 1);
switch (b1) {
case 0x89: /* mov r32 to r/m32 */
write_byte_virt(env, rip, 0x50 + modrm_reg(b2)); /* push reg */
- patch_call(env, rip + 1, vapic_bios.set_tpr);
+ patch_call(env, rip + 1, vp->set_tpr);
break;
case 0x8b: /* mov r/m32 to r32 */
write_byte_virt(env, rip, 0x90);
- patch_call(env, rip + 1, vapic_bios.get_tpr[modrm_reg(b2)]);
+ patch_call(env, rip + 1, vp->get_tpr[modrm_reg(b2)]);
break;
case 0xa1: /* mov abs to eax */
- patch_call(env, rip, vapic_bios.get_tpr[0]);
+ patch_call(env, rip, vp->get_tpr[0]);
break;
case 0xa3: /* mov eax to abs */
- patch_call(env, rip, vapic_bios.set_tpr_eax);
+ patch_call(env, rip, vp->set_tpr_eax);
break;
case 0xc7: /* mov imm32, r/m32 (c7/0) */
write_byte_virt(env, rip, 0x68); /* push imm32 */
@@ -262,7 +268,7 @@ static void patch_instruction(CPUState *env, uint64_t rip)
write_byte_virt(env, rip + 2, read_byte_virt(env, rip+7));
write_byte_virt(env, rip + 3, read_byte_virt(env, rip+8));
write_byte_virt(env, rip + 4, read_byte_virt(env, rip+9));
- patch_call(env, rip + 5, vapic_bios.set_tpr);
+ patch_call(env, rip + 5, vp->set_tpr);
break;
default:
printf("funny insn %02x %02x\n", b1, b2);