diff options
author | Beth Kon <eak@us.ibm.com> | 2009-07-07 11:50:37 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2009-07-12 16:37:41 +0300 |
commit | f69b3e23bfbfba15ec42c511617a521e90d1e639 (patch) | |
tree | f907ad79a2290b4d45ac94a07383566359101009 /qemu-kvm-x86.c | |
parent | Advertise HPET in ACPI HPET table (diff) | |
download | qemu-kvm-f69b3e23bfbfba15ec42c511617a521e90d1e639.tar.gz qemu-kvm-f69b3e23bfbfba15ec42c511617a521e90d1e639.tar.bz2 qemu-kvm-f69b3e23bfbfba15ec42c511617a521e90d1e639.zip |
HPET support with kvm
The big change here is handling of enabling/disabling of hpet legacy
mode. When hpet enters legacy mode, the spec says that the pit stops
generating interrupts. In practice, we want to stop the pit periodic
timer from running because it is wasteful in a virtual environment.
We also have to worry about the hpet leaving legacy mode (which, at
least in linux, happens only during a shutdown or crash). At this
point, according to the hpet spec, PIT interrupts need to be
reenabled. For us, it means the PIT timer needs to be restarted.
This patch handles this situation better than the earlier versions by
coming closer to just disabling PIT interrupts. It allows the PIT
state to change if the OS modifies it, even while PIT is disabled, but
does not allow a pit timer to start. Then if HPET legacy mode is
disabled, whatever the PIT state is at that point, the PIT timer is
restarted accordingly.
[avi: adjust to kernel header changes]
Signed-off-by: Beth Kon <eak@us.ibm.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'qemu-kvm-x86.c')
-rw-r--r-- | qemu-kvm-x86.c | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/qemu-kvm-x86.c b/qemu-kvm-x86.c index 67aca3288..daf60b6bf 100644 --- a/qemu-kvm-x86.c +++ b/qemu-kvm-x86.c @@ -294,8 +294,46 @@ int kvm_set_pit(kvm_context_t kvm, struct kvm_pit_state *s) return r; } +#ifdef KVM_CAP_PIT_STATE2 +int kvm_get_pit2(kvm_context_t kvm, struct kvm_pit_state2 *ps2) +{ + int r; + if (!kvm->pit_in_kernel) + return 0; + r = ioctl(kvm->vm_fd, KVM_GET_PIT2, ps2); + if (r == -1) { + r = -errno; + perror("kvm_get_pit2"); + } + return r; +} + +int kvm_set_pit2(kvm_context_t kvm, struct kvm_pit_state2 *ps2) +{ + int r; + if (!kvm->pit_in_kernel) + return 0; + r = ioctl(kvm->vm_fd, KVM_SET_PIT2, ps2); + if (r == -1) { + r = -errno; + perror("kvm_set_pit2"); + } + return r; +} + +#endif #endif +int kvm_has_pit_state2(kvm_context_t kvm) +{ + int r = 0; + +#ifdef KVM_CAP_PIT_STATE2 + r = kvm_check_extension(kvm, KVM_CAP_PIT_STATE2); +#endif + return r; +} + void kvm_show_code(kvm_vcpu_context_t vcpu) { #define SHOW_CODE_LEN 50 |