diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2014-12-04 10:02:24 -0500 |
---|---|---|
committer | Christoffer Dall <christoffer.dall@linaro.org> | 2014-12-13 08:15:52 -0500 |
commit | 6d3cfbe21bef5b66530b50ad16c88fdc71a04c35 (patch) | |
tree | b5f375258f0273acdab23d900ac9b06c642a8e5f /virt | |
parent | 957db105c99792ae8ef61ffc9ae77d910f6471da (diff) |
arm/arm64: KVM: vgic: move reset initialization into vgic_init_maps()
VGIC initialization currently happens in three phases:
(1) kvm_vgic_create() (triggered by userspace GIC creation)
(2) vgic_init_maps() (triggered by userspace GIC register read/write
requests, or from kvm_vgic_init() if not already run)
(3) kvm_vgic_init() (triggered by first VM run)
We were doing initialization of some state to correspond with the
state of a freshly-reset GIC in kvm_vgic_init(); this is too late,
since it will overwrite changes made by userspace using the
register access APIs before the VM is run. Move this initialization
earlier, into the vgic_init_maps() phase.
This fixes a bug where QEMU could successfully restore a saved
VM state snapshot into a VM that had already been run, but could
not restore it "from cold" using the -loadvm command line option
(the symptoms being that the restored VM would run but interrupts
were ignored).
Finally rename vgic_init_maps to vgic_init and renamed kvm_vgic_init to
kvm_vgic_map_resources.
[ This patch is originally written by Peter Maydell, but I have
modified it somewhat heavily, renaming various bits and moving code
around. If something is broken, I am to be blamed. - Christoffer ]
Acked-by: Marc Zyngier <marc.zyngier@arm.com>
Reviewed-by: Eric Auger <eric.auger@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Diffstat (limited to 'virt')
-rw-r--r-- | virt/kvm/arm/vgic.c | 77 |
1 files changed, 32 insertions, 45 deletions
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c index 21e035cc5460..1ce4e364c1e0 100644 --- a/virt/kvm/arm/vgic.c +++ b/virt/kvm/arm/vgic.c | |||
@@ -91,6 +91,7 @@ | |||
91 | #define ACCESS_WRITE_VALUE (3 << 1) | 91 | #define ACCESS_WRITE_VALUE (3 << 1) |
92 | #define ACCESS_WRITE_MASK(x) ((x) & (3 << 1)) | 92 | #define ACCESS_WRITE_MASK(x) ((x) & (3 << 1)) |
93 | 93 | ||
94 | static int vgic_init(struct kvm *kvm); | ||
94 | static void vgic_retire_disabled_irqs(struct kvm_vcpu *vcpu); | 95 | static void vgic_retire_disabled_irqs(struct kvm_vcpu *vcpu); |
95 | static void vgic_retire_lr(int lr_nr, int irq, struct kvm_vcpu *vcpu); | 96 | static void vgic_retire_lr(int lr_nr, int irq, struct kvm_vcpu *vcpu); |
96 | static void vgic_update_state(struct kvm *kvm); | 97 | static void vgic_update_state(struct kvm *kvm); |
@@ -1732,39 +1733,14 @@ static int vgic_vcpu_init_maps(struct kvm_vcpu *vcpu, int nr_irqs) | |||
1732 | 1733 | ||
1733 | int sz = (nr_irqs - VGIC_NR_PRIVATE_IRQS) / 8; | 1734 | int sz = (nr_irqs - VGIC_NR_PRIVATE_IRQS) / 8; |
1734 | vgic_cpu->pending_shared = kzalloc(sz, GFP_KERNEL); | 1735 | vgic_cpu->pending_shared = kzalloc(sz, GFP_KERNEL); |
1735 | vgic_cpu->vgic_irq_lr_map = kzalloc(nr_irqs, GFP_KERNEL); | 1736 | vgic_cpu->vgic_irq_lr_map = kmalloc(nr_irqs, GFP_KERNEL); |
1736 | 1737 | ||
1737 | if (!vgic_cpu->pending_shared || !vgic_cpu->vgic_irq_lr_map) { | 1738 | if (!vgic_cpu->pending_shared || !vgic_cpu->vgic_irq_lr_map) { |
1738 | kvm_vgic_vcpu_destroy(vcpu); | 1739 | kvm_vgic_vcpu_destroy(vcpu); |
1739 | return -ENOMEM; | 1740 | return -ENOMEM; |
1740 | } | 1741 | } |
1741 | 1742 | ||
1742 | return 0; | 1743 | memset(vgic_cpu->vgic_irq_lr_map, LR_EMPTY, nr_irqs); |
1743 | } | ||
1744 | |||
1745 | /** | ||
1746 | * kvm_vgic_vcpu_init - Initialize per-vcpu VGIC state | ||
1747 | * @vcpu: pointer to the vcpu struct | ||
1748 | * | ||
1749 | * Initialize the vgic_cpu struct and vgic_dist struct fields pertaining to | ||
1750 | * this vcpu and enable the VGIC for this VCPU | ||
1751 | */ | ||
1752 | static void kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu) | ||
1753 | { | ||
1754 | struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; | ||
1755 | struct vgic_dist *dist = &vcpu->kvm->arch.vgic; | ||
1756 | int i; | ||
1757 | |||
1758 | for (i = 0; i < dist->nr_irqs; i++) { | ||
1759 | if (i < VGIC_NR_PPIS) | ||
1760 | vgic_bitmap_set_irq_val(&dist->irq_enabled, | ||
1761 | vcpu->vcpu_id, i, 1); | ||
1762 | if (i < VGIC_NR_PRIVATE_IRQS) | ||
1763 | vgic_bitmap_set_irq_val(&dist->irq_cfg, | ||
1764 | vcpu->vcpu_id, i, VGIC_CFG_EDGE); | ||
1765 | |||
1766 | vgic_cpu->vgic_irq_lr_map[i] = LR_EMPTY; | ||
1767 | } | ||
1768 | 1744 | ||
1769 | /* | 1745 | /* |
1770 | * Store the number of LRs per vcpu, so we don't have to go | 1746 | * Store the number of LRs per vcpu, so we don't have to go |
@@ -1773,7 +1749,7 @@ static void kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu) | |||
1773 | */ | 1749 | */ |
1774 | vgic_cpu->nr_lr = vgic->nr_lr; | 1750 | vgic_cpu->nr_lr = vgic->nr_lr; |
1775 | 1751 | ||
1776 | vgic_enable(vcpu); | 1752 | return 0; |
1777 | } | 1753 | } |
1778 | 1754 | ||
1779 | void kvm_vgic_destroy(struct kvm *kvm) | 1755 | void kvm_vgic_destroy(struct kvm *kvm) |
@@ -1810,12 +1786,12 @@ void kvm_vgic_destroy(struct kvm *kvm) | |||
1810 | * Allocate and initialize the various data structures. Must be called | 1786 | * Allocate and initialize the various data structures. Must be called |
1811 | * with kvm->lock held! | 1787 | * with kvm->lock held! |
1812 | */ | 1788 | */ |
1813 | static int vgic_init_maps(struct kvm *kvm) | 1789 | static int vgic_init(struct kvm *kvm) |
1814 | { | 1790 | { |
1815 | struct vgic_dist *dist = &kvm->arch.vgic; | 1791 | struct vgic_dist *dist = &kvm->arch.vgic; |
1816 | struct kvm_vcpu *vcpu; | 1792 | struct kvm_vcpu *vcpu; |
1817 | int nr_cpus, nr_irqs; | 1793 | int nr_cpus, nr_irqs; |
1818 | int ret, i; | 1794 | int ret, i, vcpu_id; |
1819 | 1795 | ||
1820 | if (dist->nr_cpus) /* Already allocated */ | 1796 | if (dist->nr_cpus) /* Already allocated */ |
1821 | return 0; | 1797 | return 0; |
@@ -1865,16 +1841,28 @@ static int vgic_init_maps(struct kvm *kvm) | |||
1865 | if (ret) | 1841 | if (ret) |
1866 | goto out; | 1842 | goto out; |
1867 | 1843 | ||
1868 | kvm_for_each_vcpu(i, vcpu, kvm) { | 1844 | for (i = VGIC_NR_PRIVATE_IRQS; i < dist->nr_irqs; i += 4) |
1845 | vgic_set_target_reg(kvm, 0, i); | ||
1846 | |||
1847 | kvm_for_each_vcpu(vcpu_id, vcpu, kvm) { | ||
1869 | ret = vgic_vcpu_init_maps(vcpu, nr_irqs); | 1848 | ret = vgic_vcpu_init_maps(vcpu, nr_irqs); |
1870 | if (ret) { | 1849 | if (ret) { |
1871 | kvm_err("VGIC: Failed to allocate vcpu memory\n"); | 1850 | kvm_err("VGIC: Failed to allocate vcpu memory\n"); |
1872 | break; | 1851 | break; |
1873 | } | 1852 | } |
1874 | } | ||
1875 | 1853 | ||
1876 | for (i = VGIC_NR_PRIVATE_IRQS; i < dist->nr_irqs; i += 4) | 1854 | for (i = 0; i < dist->nr_irqs; i++) { |
1877 | vgic_set_target_reg(kvm, 0, i); | 1855 | if (i < VGIC_NR_PPIS) |
1856 | vgic_bitmap_set_irq_val(&dist->irq_enabled, | ||
1857 | vcpu->vcpu_id, i, 1); | ||
1858 | if (i < VGIC_NR_PRIVATE_IRQS) | ||
1859 | vgic_bitmap_set_irq_val(&dist->irq_cfg, | ||
1860 | vcpu->vcpu_id, i, | ||
1861 | VGIC_CFG_EDGE); | ||
1862 | } | ||
1863 | |||
1864 | vgic_enable(vcpu); | ||
1865 | } | ||
1878 | 1866 | ||
1879 | out: | 1867 | out: |
1880 | if (ret) | 1868 | if (ret) |
@@ -1884,18 +1872,16 @@ out: | |||
1884 | } | 1872 | } |
1885 | 1873 | ||
1886 | /** | 1874 | /** |
1887 | * kvm_vgic_init - Initialize global VGIC state before running any VCPUs | 1875 | * kvm_vgic_map_resources - Configure global VGIC state before running any VCPUs |
1888 | * @kvm: pointer to the kvm struct | 1876 | * @kvm: pointer to the kvm struct |
1889 | * | 1877 | * |
1890 | * Map the virtual CPU interface into the VM before running any VCPUs. We | 1878 | * Map the virtual CPU interface into the VM before running any VCPUs. We |
1891 | * can't do this at creation time, because user space must first set the | 1879 | * can't do this at creation time, because user space must first set the |
1892 | * virtual CPU interface address in the guest physical address space. Also | 1880 | * virtual CPU interface address in the guest physical address space. |
1893 | * initialize the ITARGETSRn regs to 0 on the emulated distributor. | ||
1894 | */ | 1881 | */ |
1895 | int kvm_vgic_init(struct kvm *kvm) | 1882 | int kvm_vgic_map_resources(struct kvm *kvm) |
1896 | { | 1883 | { |
1897 | struct kvm_vcpu *vcpu; | 1884 | int ret = 0; |
1898 | int ret = 0, i; | ||
1899 | 1885 | ||
1900 | if (!irqchip_in_kernel(kvm)) | 1886 | if (!irqchip_in_kernel(kvm)) |
1901 | return 0; | 1887 | return 0; |
@@ -1912,7 +1898,11 @@ int kvm_vgic_init(struct kvm *kvm) | |||
1912 | goto out; | 1898 | goto out; |
1913 | } | 1899 | } |
1914 | 1900 | ||
1915 | ret = vgic_init_maps(kvm); | 1901 | /* |
1902 | * Initialize the vgic if this hasn't already been done on demand by | ||
1903 | * accessing the vgic state from userspace. | ||
1904 | */ | ||
1905 | ret = vgic_init(kvm); | ||
1916 | if (ret) { | 1906 | if (ret) { |
1917 | kvm_err("Unable to allocate maps\n"); | 1907 | kvm_err("Unable to allocate maps\n"); |
1918 | goto out; | 1908 | goto out; |
@@ -1926,9 +1916,6 @@ int kvm_vgic_init(struct kvm *kvm) | |||
1926 | goto out; | 1916 | goto out; |
1927 | } | 1917 | } |
1928 | 1918 | ||
1929 | kvm_for_each_vcpu(i, vcpu, kvm) | ||
1930 | kvm_vgic_vcpu_init(vcpu); | ||
1931 | |||
1932 | kvm->arch.vgic.ready = true; | 1919 | kvm->arch.vgic.ready = true; |
1933 | out: | 1920 | out: |
1934 | if (ret) | 1921 | if (ret) |
@@ -2173,7 +2160,7 @@ static int vgic_attr_regs_access(struct kvm_device *dev, | |||
2173 | 2160 | ||
2174 | mutex_lock(&dev->kvm->lock); | 2161 | mutex_lock(&dev->kvm->lock); |
2175 | 2162 | ||
2176 | ret = vgic_init_maps(dev->kvm); | 2163 | ret = vgic_init(dev->kvm); |
2177 | if (ret) | 2164 | if (ret) |
2178 | goto out; | 2165 | goto out; |
2179 | 2166 | ||