aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSheng Yang <sheng.yang@intel.com>2008-03-03 11:50:59 -0500
committerAvi Kivity <avi@qumranet.com>2008-04-27 05:00:22 -0400
commite0f63cb9277b64850854aee301762beeeb463473 (patch)
treeae10bac92ee6cc1a658b479a311fac67ebd3524c
parent7837699fa6d7adf81f26ab73a5f6897ea1ab9d6a (diff)
KVM: Add save/restore supporting of in kernel PIT
Signed-off-by: Sheng Yang <sheng.yang@intel.com> Signed-off-by: Avi Kivity <avi@qumranet.com>
-rw-r--r--arch/x86/kvm/i8254.c7
-rw-r--r--arch/x86/kvm/i8254.h1
-rw-r--r--arch/x86/kvm/x86.c48
-rw-r--r--include/asm-x86/kvm.h21
-rw-r--r--include/linux/kvm.h2
5 files changed, 79 insertions, 0 deletions
diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c
index c7435093bbee..8642f9d1206a 100644
--- a/arch/x86/kvm/i8254.c
+++ b/arch/x86/kvm/i8254.c
@@ -288,6 +288,13 @@ static void pit_load_count(struct kvm *kvm, int channel, u32 val)
288 } 288 }
289} 289}
290 290
291void kvm_pit_load_count(struct kvm *kvm, int channel, u32 val)
292{
293 mutex_lock(&kvm->arch.vpit->pit_state.lock);
294 pit_load_count(kvm, channel, val);
295 mutex_unlock(&kvm->arch.vpit->pit_state.lock);
296}
297
291static void pit_ioport_write(struct kvm_io_device *this, 298static void pit_ioport_write(struct kvm_io_device *this,
292 gpa_t addr, int len, const void *data) 299 gpa_t addr, int len, const void *data)
293{ 300{
diff --git a/arch/x86/kvm/i8254.h b/arch/x86/kvm/i8254.h
index d77d6b795a1f..fe09eced7783 100644
--- a/arch/x86/kvm/i8254.h
+++ b/arch/x86/kvm/i8254.h
@@ -55,6 +55,7 @@ struct kvm_pit {
55 55
56void kvm_inject_pit_timer_irqs(struct kvm_vcpu *vcpu); 56void kvm_inject_pit_timer_irqs(struct kvm_vcpu *vcpu);
57void kvm_pit_timer_intr_post(struct kvm_vcpu *vcpu, int vec); 57void kvm_pit_timer_intr_post(struct kvm_vcpu *vcpu, int vec);
58void kvm_pit_load_count(struct kvm *kvm, int channel, u32 val);
58struct kvm_pit *kvm_create_pit(struct kvm *kvm); 59struct kvm_pit *kvm_create_pit(struct kvm *kvm);
59void kvm_free_pit(struct kvm *kvm); 60void kvm_free_pit(struct kvm *kvm);
60 61
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index c33a4578132c..621a8e362fe7 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1504,6 +1504,23 @@ static int kvm_vm_ioctl_set_irqchip(struct kvm *kvm, struct kvm_irqchip *chip)
1504 return r; 1504 return r;
1505} 1505}
1506 1506
1507static int kvm_vm_ioctl_get_pit(struct kvm *kvm, struct kvm_pit_state *ps)
1508{
1509 int r = 0;
1510
1511 memcpy(ps, &kvm->arch.vpit->pit_state, sizeof(struct kvm_pit_state));
1512 return r;
1513}
1514
1515static int kvm_vm_ioctl_set_pit(struct kvm *kvm, struct kvm_pit_state *ps)
1516{
1517 int r = 0;
1518
1519 memcpy(&kvm->arch.vpit->pit_state, ps, sizeof(struct kvm_pit_state));
1520 kvm_pit_load_count(kvm, 0, ps->channels[0].count);
1521 return r;
1522}
1523
1507/* 1524/*
1508 * Get (and clear) the dirty memory log for a memory slot. 1525 * Get (and clear) the dirty memory log for a memory slot.
1509 */ 1526 */
@@ -1657,6 +1674,37 @@ long kvm_arch_vm_ioctl(struct file *filp,
1657 r = 0; 1674 r = 0;
1658 break; 1675 break;
1659 } 1676 }
1677 case KVM_GET_PIT: {
1678 struct kvm_pit_state ps;
1679 r = -EFAULT;
1680 if (copy_from_user(&ps, argp, sizeof ps))
1681 goto out;
1682 r = -ENXIO;
1683 if (!kvm->arch.vpit)
1684 goto out;
1685 r = kvm_vm_ioctl_get_pit(kvm, &ps);
1686 if (r)
1687 goto out;
1688 r = -EFAULT;
1689 if (copy_to_user(argp, &ps, sizeof ps))
1690 goto out;
1691 r = 0;
1692 break;
1693 }
1694 case KVM_SET_PIT: {
1695 struct kvm_pit_state ps;
1696 r = -EFAULT;
1697 if (copy_from_user(&ps, argp, sizeof ps))
1698 goto out;
1699 r = -ENXIO;
1700 if (!kvm->arch.vpit)
1701 goto out;
1702 r = kvm_vm_ioctl_set_pit(kvm, &ps);
1703 if (r)
1704 goto out;
1705 r = 0;
1706 break;
1707 }
1660 default: 1708 default:
1661 ; 1709 ;
1662 } 1710 }
diff --git a/include/asm-x86/kvm.h b/include/asm-x86/kvm.h
index 7a71120426a3..12b4b25371d5 100644
--- a/include/asm-x86/kvm.h
+++ b/include/asm-x86/kvm.h
@@ -188,4 +188,25 @@ struct kvm_cpuid2 {
188 struct kvm_cpuid_entry2 entries[0]; 188 struct kvm_cpuid_entry2 entries[0];
189}; 189};
190 190
191/* for KVM_GET_PIT and KVM_SET_PIT */
192struct kvm_pit_channel_state {
193 __u32 count; /* can be 65536 */
194 __u16 latched_count;
195 __u8 count_latched;
196 __u8 status_latched;
197 __u8 status;
198 __u8 read_state;
199 __u8 write_state;
200 __u8 write_latch;
201 __u8 rw_mode;
202 __u8 mode;
203 __u8 bcd;
204 __u8 gate;
205 __s64 count_load_time;
206};
207
208struct kvm_pit_state {
209 struct kvm_pit_channel_state channels[3];
210};
211
191#endif 212#endif
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index cefa9a2c7b89..a2f3274016ee 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -260,6 +260,8 @@ struct kvm_vapic_addr {
260#define KVM_GET_IRQCHIP _IOWR(KVMIO, 0x62, struct kvm_irqchip) 260#define KVM_GET_IRQCHIP _IOWR(KVMIO, 0x62, struct kvm_irqchip)
261#define KVM_SET_IRQCHIP _IOR(KVMIO, 0x63, struct kvm_irqchip) 261#define KVM_SET_IRQCHIP _IOR(KVMIO, 0x63, struct kvm_irqchip)
262#define KVM_CREATE_PIT _IO(KVMIO, 0x64) 262#define KVM_CREATE_PIT _IO(KVMIO, 0x64)
263#define KVM_GET_PIT _IOWR(KVMIO, 0x65, struct kvm_pit_state)
264#define KVM_SET_PIT _IOR(KVMIO, 0x66, struct kvm_pit_state)
263 265
264/* 266/*
265 * ioctls for vcpu fds 267 * ioctls for vcpu fds