Save/restore in-kernel KVM PIO state. This is necessary to allow migration with in-progress PIO operation. FIXME: adjust CPUState and VMState version. Signed-off-by: Marcelo Tosatti <mtosatti@xxxxxxxxxx> Index: qemu-kvm/target-i386/cpu.h =================================================================== --- qemu-kvm.orig/target-i386/cpu.h +++ qemu-kvm/target-i386/cpu.h @@ -570,6 +570,18 @@ typedef struct { uint64_t mask; } MTRRVar; +typedef struct { + uint64_t guest_gva; + uint32_t count; + uint32_t cur_count; + uint16_t port; + uint8_t size; + uint8_t in; + uint8_t string; + uint8_t down; + uint8_t rep; +} KVMPIOState; + #define CPU_NB_REGS64 16 #define CPU_NB_REGS32 8 @@ -702,7 +714,9 @@ typedef struct CPUX86State { uint8_t has_error_code; uint32_t sipi_vector; uint32_t cpuid_kvm_features; - + + KVMPIOState kvm_pio; + /* in order to simplify APIC support, we leave this pointer to the user */ struct APICState *apic_state; Index: qemu-kvm/target-i386/kvm.c =================================================================== --- qemu-kvm.orig/target-i386/kvm.c +++ qemu-kvm/target-i386/kvm.c @@ -289,6 +289,7 @@ void kvm_arch_reset_vcpu(CPUState *env) env->interrupt_injected = -1; env->nmi_injected = 0; env->nmi_pending = 0; + memset(&env->kvm_pio, 0, sizeof(KVMPIOState)); } static int kvm_has_msr_star(CPUState *env) @@ -837,6 +838,57 @@ static int kvm_get_vcpu_events(CPUState return 0; } +static int kvm_put_pio(CPUState *env) +{ +#ifdef KVM_CAP_PIO + struct kvm_pio_request pio; + + if (!kvm_has_vcpu_pio()) + return 0; + + pio.count = env->kvm_pio.count; + pio.cur_count = env->kvm_pio.cur_count; + pio.guest_gva = env->kvm_pio.guest_gva; + pio.in = env->kvm_pio.in; + pio.port = env->kvm_pio.port; + pio.size = env->kvm_pio.size; + pio.string = env->kvm_pio.string; + pio.down = env->kvm_pio.down; + pio.rep = env->kvm_pio.rep; + + return kvm_vcpu_ioctl(env, KVM_SET_VCPU_PIO, &pio); +#else + return 0; +#endif +} + +static int kvm_get_pio(CPUState *env) +{ +#ifdef KVM_CAP_PIO + struct kvm_pio_request pio; + int ret; + + if (!kvm_has_vcpu_pio()) + return 0; + + ret = kvm_vcpu_ioctl(env, KVM_GET_VCPU_PIO, &pio); + if (ret < 0) + return ret; + + env->kvm_pio.count = pio.count; + env->kvm_pio.cur_count = pio.cur_count; + env->kvm_pio.guest_gva = pio.guest_gva; + env->kvm_pio.in = pio.in; + env->kvm_pio.port = pio.port; + env->kvm_pio.size = pio.size; + env->kvm_pio.string = pio.string; + env->kvm_pio.down = pio.down; + env->kvm_pio.rep = pio.rep; +#endif + + return 0; +} + int kvm_arch_put_registers(CPUState *env) { int ret; @@ -865,6 +917,10 @@ int kvm_arch_put_registers(CPUState *env if (ret < 0) return ret; + ret = kvm_put_pio(env); + if (ret < 0) + return ret; + return 0; } @@ -896,6 +952,10 @@ int kvm_arch_get_registers(CPUState *env if (ret < 0) return ret; + ret = kvm_get_pio(env); + if (ret < 0) + return ret; + return 0; } Index: qemu-kvm/target-i386/machine.c =================================================================== --- qemu-kvm.orig/target-i386/machine.c +++ qemu-kvm/target-i386/machine.c @@ -62,6 +62,34 @@ static const VMStateDescription vmstate_ #define VMSTATE_MTRR_VARS(_field, _state, _n, _v) \ VMSTATE_STRUCT_ARRAY(_field, _state, _n, _v, vmstate_mtrr_var, MTRRVar) +static const VMStateDescription vmstate_kvm_pio = { + .name = "kvm_pio", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField []) { + VMSTATE_UINT64(guest_gva, KVMPIOState), + VMSTATE_UINT32(count, KVMPIOState), + VMSTATE_UINT32(cur_count, KVMPIOState), + VMSTATE_UINT8(in, KVMPIOState), + VMSTATE_UINT16(port, KVMPIOState), + VMSTATE_UINT8(size, KVMPIOState), + VMSTATE_UINT8(string, KVMPIOState), + VMSTATE_UINT8(down, KVMPIOState), + VMSTATE_UINT8(rep, KVMPIOState), + VMSTATE_END_OF_LIST() + } +}; + +#define VMSTATE_KVM_PIO(_field, _state, _version) { \ + .name = (stringify(_field)), \ + .version_id = _version, \ + .size = sizeof(KVMPIOState), \ + .vmsd = &vmstate_kvm_pio, \ + .flags = VMS_STRUCT, \ + .offset = vmstate_offset_value(_state, _field, KVMPIOState),\ +} + static void put_fpreg_error(QEMUFile *f, void *opaque, size_t size) { fprintf(stderr, "call put_fpreg() with invalid arguments\n"); @@ -464,6 +492,9 @@ static const VMStateDescription vmstate_ /* KVM pvclock msr */ VMSTATE_UINT64_V(system_time_msr, CPUState, 11), VMSTATE_UINT64_V(wall_clock_msr, CPUState, 11), + + VMSTATE_KVM_PIO(kvm_pio, CPUState, 11), + VMSTATE_END_OF_LIST() /* The above list is not sorted /wrt version numbers, watch out! */ } Index: qemu-kvm/kvm.h =================================================================== --- qemu-kvm.orig/kvm.h +++ qemu-kvm/kvm.h @@ -48,6 +48,7 @@ int kvm_set_migration_log(int enable); int kvm_has_sync_mmu(void); int kvm_has_vcpu_events(void); +int kvm_has_vcpu_pio(void); void kvm_setup_guest_memory(void *start, size_t size); Index: qemu-kvm/kvm-all.c =================================================================== --- qemu-kvm.orig/kvm-all.c +++ qemu-kvm/kvm-all.c @@ -881,6 +881,17 @@ int kvm_has_sync_mmu(void) #endif } +int kvm_has_vcpu_pio(void) +{ +#ifdef KVM_CAP_PIO + KVMState *s = kvm_state; + + return kvm_check_extension(s, KVM_CAP_PIO); +#else + return 0; +#endif +} + int kvm_has_vcpu_events(void) { return kvm_state->vcpu_events; -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html