diff options
Diffstat (limited to 'qemu-kvm.c')
-rw-r--r-- | qemu-kvm.c | 31 |
1 files changed, 30 insertions, 1 deletions
diff --git a/qemu-kvm.c b/qemu-kvm.c index 1a0f6e04d..401c7e12c 100644 --- a/qemu-kvm.c +++ b/qemu-kvm.c @@ -124,6 +124,15 @@ static void get_seg(SegmentCache *lhs, const struct kvm_segment *rhs) | (rhs->avl * DESC_AVL_MASK); } +/* the reset values of qemu are not compatible to SVM + * this function is used to fix the segment descriptor values */ +static void fix_realmode_dataseg(struct kvm_segment *seg) +{ + seg->type = 0x02; + seg->present = 1; + seg->s = 1; +} + static void load_regs(CPUState *env) { struct kvm_regs regs; @@ -182,6 +191,14 @@ static void load_regs(CPUState *env) (sregs.cs.selector & 3); sregs.ss.dpl = sregs.ss.selector & 3; } + + if (!(env->cr[0] & CR0_PG_MASK)) { + fix_realmode_dataseg(&sregs.ds); + fix_realmode_dataseg(&sregs.es); + fix_realmode_dataseg(&sregs.fs); + fix_realmode_dataseg(&sregs.gs); + fix_realmode_dataseg(&sregs.ss); + } } set_seg(&sregs.tr, &env->tr); @@ -408,6 +425,7 @@ void kvm_save_registers(CPUState *env) int kvm_cpu_exec(CPUState *env) { + int r; int pending = (!env->ready_for_interrupt_injection || ((env->interrupt_request & CPU_INTERRUPT_HARD) && (env->eflags & IF_MASK))); @@ -422,7 +440,11 @@ int kvm_cpu_exec(CPUState *env) if (!saved_env[0]) saved_env[0] = env; - kvm_run(kvm_context, 0); + r = kvm_run(kvm_context, 0); + if (r < 0) { + printf("kvm_run returned %d\n", r); + exit(1); + } return 0; } @@ -587,6 +609,12 @@ static int kvm_halt(void *opaque, int vcpu) return 1; } + +static int kvm_shutdown(void *opaque, int vcpu) +{ + qemu_system_reset_request(); + return 1; +} static struct kvm_callbacks qemu_kvm_ops = { .cpuid = kvm_cpuid, @@ -606,6 +634,7 @@ static struct kvm_callbacks qemu_kvm_ops = { .writel = kvm_writel, .writeq = kvm_writeq, .halt = kvm_halt, + .shutdown = kvm_shutdown, .io_window = kvm_io_window, .try_push_interrupts = try_push_interrupts, .post_kvm_run = post_kvm_run, |