diff options
author | Jan Kiszka <jan.kiszka@web.de> | 2009-11-11 19:04:25 -0500 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2009-12-03 02:32:25 -0500 |
commit | 3cfc3092f40bc37c57ba556cfd8de4218f2135ab (patch) | |
tree | 562d61febfe7d3c99ea08e376b3f3c016cff613c /arch/x86/kvm/x86.c | |
parent | 65ac7264043740572ba804edca03c374d70427c9 (diff) |
KVM: x86: Add KVM_GET/SET_VCPU_EVENTS
This new IOCTL exports all yet user-invisible states related to
exceptions, interrupts, and NMIs. Together with appropriate user space
changes, this fixes sporadic problems of vmsave/restore, live migration
and system reset.
[avi: future-proof abi by adding a flags field]
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm/x86.c')
-rw-r--r-- | arch/x86/kvm/x86.c | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index ba8958dca3c4..35eea30821d6 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -1342,6 +1342,7 @@ int kvm_dev_ioctl_check_extension(long ext) | |||
1342 | case KVM_CAP_SET_IDENTITY_MAP_ADDR: | 1342 | case KVM_CAP_SET_IDENTITY_MAP_ADDR: |
1343 | case KVM_CAP_XEN_HVM: | 1343 | case KVM_CAP_XEN_HVM: |
1344 | case KVM_CAP_ADJUST_CLOCK: | 1344 | case KVM_CAP_ADJUST_CLOCK: |
1345 | case KVM_CAP_VCPU_EVENTS: | ||
1345 | r = 1; | 1346 | r = 1; |
1346 | break; | 1347 | break; |
1347 | case KVM_CAP_COALESCED_MMIO: | 1348 | case KVM_CAP_COALESCED_MMIO: |
@@ -1883,6 +1884,61 @@ static int kvm_vcpu_ioctl_x86_set_mce(struct kvm_vcpu *vcpu, | |||
1883 | return 0; | 1884 | return 0; |
1884 | } | 1885 | } |
1885 | 1886 | ||
1887 | static void kvm_vcpu_ioctl_x86_get_vcpu_events(struct kvm_vcpu *vcpu, | ||
1888 | struct kvm_vcpu_events *events) | ||
1889 | { | ||
1890 | vcpu_load(vcpu); | ||
1891 | |||
1892 | events->exception.injected = vcpu->arch.exception.pending; | ||
1893 | events->exception.nr = vcpu->arch.exception.nr; | ||
1894 | events->exception.has_error_code = vcpu->arch.exception.has_error_code; | ||
1895 | events->exception.error_code = vcpu->arch.exception.error_code; | ||
1896 | |||
1897 | events->interrupt.injected = vcpu->arch.interrupt.pending; | ||
1898 | events->interrupt.nr = vcpu->arch.interrupt.nr; | ||
1899 | events->interrupt.soft = vcpu->arch.interrupt.soft; | ||
1900 | |||
1901 | events->nmi.injected = vcpu->arch.nmi_injected; | ||
1902 | events->nmi.pending = vcpu->arch.nmi_pending; | ||
1903 | events->nmi.masked = kvm_x86_ops->get_nmi_mask(vcpu); | ||
1904 | |||
1905 | events->sipi_vector = vcpu->arch.sipi_vector; | ||
1906 | |||
1907 | events->flags = 0; | ||
1908 | |||
1909 | vcpu_put(vcpu); | ||
1910 | } | ||
1911 | |||
1912 | static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct kvm_vcpu *vcpu, | ||
1913 | struct kvm_vcpu_events *events) | ||
1914 | { | ||
1915 | if (events->flags) | ||
1916 | return -EINVAL; | ||
1917 | |||
1918 | vcpu_load(vcpu); | ||
1919 | |||
1920 | vcpu->arch.exception.pending = events->exception.injected; | ||
1921 | vcpu->arch.exception.nr = events->exception.nr; | ||
1922 | vcpu->arch.exception.has_error_code = events->exception.has_error_code; | ||
1923 | vcpu->arch.exception.error_code = events->exception.error_code; | ||
1924 | |||
1925 | vcpu->arch.interrupt.pending = events->interrupt.injected; | ||
1926 | vcpu->arch.interrupt.nr = events->interrupt.nr; | ||
1927 | vcpu->arch.interrupt.soft = events->interrupt.soft; | ||
1928 | if (vcpu->arch.interrupt.pending && irqchip_in_kernel(vcpu->kvm)) | ||
1929 | kvm_pic_clear_isr_ack(vcpu->kvm); | ||
1930 | |||
1931 | vcpu->arch.nmi_injected = events->nmi.injected; | ||
1932 | vcpu->arch.nmi_pending = events->nmi.pending; | ||
1933 | kvm_x86_ops->set_nmi_mask(vcpu, events->nmi.masked); | ||
1934 | |||
1935 | vcpu->arch.sipi_vector = events->sipi_vector; | ||
1936 | |||
1937 | vcpu_put(vcpu); | ||
1938 | |||
1939 | return 0; | ||
1940 | } | ||
1941 | |||
1886 | long kvm_arch_vcpu_ioctl(struct file *filp, | 1942 | long kvm_arch_vcpu_ioctl(struct file *filp, |
1887 | unsigned int ioctl, unsigned long arg) | 1943 | unsigned int ioctl, unsigned long arg) |
1888 | { | 1944 | { |
@@ -2040,6 +2096,27 @@ long kvm_arch_vcpu_ioctl(struct file *filp, | |||
2040 | r = kvm_vcpu_ioctl_x86_set_mce(vcpu, &mce); | 2096 | r = kvm_vcpu_ioctl_x86_set_mce(vcpu, &mce); |
2041 | break; | 2097 | break; |
2042 | } | 2098 | } |
2099 | case KVM_GET_VCPU_EVENTS: { | ||
2100 | struct kvm_vcpu_events events; | ||
2101 | |||
2102 | kvm_vcpu_ioctl_x86_get_vcpu_events(vcpu, &events); | ||
2103 | |||
2104 | r = -EFAULT; | ||
2105 | if (copy_to_user(argp, &events, sizeof(struct kvm_vcpu_events))) | ||
2106 | break; | ||
2107 | r = 0; | ||
2108 | break; | ||
2109 | } | ||
2110 | case KVM_SET_VCPU_EVENTS: { | ||
2111 | struct kvm_vcpu_events events; | ||
2112 | |||
2113 | r = -EFAULT; | ||
2114 | if (copy_from_user(&events, argp, sizeof(struct kvm_vcpu_events))) | ||
2115 | break; | ||
2116 | |||
2117 | r = kvm_vcpu_ioctl_x86_set_vcpu_events(vcpu, &events); | ||
2118 | break; | ||
2119 | } | ||
2043 | default: | 2120 | default: |
2044 | r = -EINVAL; | 2121 | r = -EINVAL; |
2045 | } | 2122 | } |