aboutsummaryrefslogtreecommitdiffstats
path: root/virt
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2014-07-08 07:09:06 -0400
committerChristoffer Dall <christoffer.dall@linaro.org>2014-09-18 21:48:58 -0400
commit4956f2bc1fdee4bc336532f3f34635a8534cedfd (patch)
treee74ef3916edb9b56c71b69108fe310ee66b265ae /virt
parent5fb66da64064d0cb8dcce4cc8bf4cb1b921b13a0 (diff)
arm/arm64: KVM: vgic: delay vgic allocation until init time
It is now quite easy to delay the allocation of the vgic tables until we actually require it to be up and running (when the first vcpu is kicking around, or someones tries to access the GIC registers). This allow us to allocate memory for the exact number of CPUs we have. As nobody configures the number of interrupts just yet, use a fallback to VGIC_NR_IRQS_LEGACY. Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Diffstat (limited to 'virt')
-rw-r--r--virt/kvm/arm/vgic.c42
1 files changed, 29 insertions, 13 deletions
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 725d829ad1d9..ac2b44d58e60 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1729,15 +1729,12 @@ static int vgic_vcpu_init_maps(struct kvm_vcpu *vcpu, int nr_irqs)
1729 * Initialize the vgic_cpu struct and vgic_dist struct fields pertaining to 1729 * Initialize the vgic_cpu struct and vgic_dist struct fields pertaining to
1730 * this vcpu and enable the VGIC for this VCPU 1730 * this vcpu and enable the VGIC for this VCPU
1731 */ 1731 */
1732int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu) 1732static void kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
1733{ 1733{
1734 struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; 1734 struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
1735 struct vgic_dist *dist = &vcpu->kvm->arch.vgic; 1735 struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
1736 int i; 1736 int i;
1737 1737
1738 if (vcpu->vcpu_id >= dist->nr_cpus)
1739 return -EBUSY;
1740
1741 for (i = 0; i < dist->nr_irqs; i++) { 1738 for (i = 0; i < dist->nr_irqs; i++) {
1742 if (i < VGIC_NR_PPIS) 1739 if (i < VGIC_NR_PPIS)
1743 vgic_bitmap_set_irq_val(&dist->irq_enabled, 1740 vgic_bitmap_set_irq_val(&dist->irq_enabled,
@@ -1757,8 +1754,6 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
1757 vgic_cpu->nr_lr = vgic->nr_lr; 1754 vgic_cpu->nr_lr = vgic->nr_lr;
1758 1755
1759 vgic_enable(vcpu); 1756 vgic_enable(vcpu);
1760
1761 return 0;
1762} 1757}
1763 1758
1764void kvm_vgic_destroy(struct kvm *kvm) 1759void kvm_vgic_destroy(struct kvm *kvm)
@@ -1802,8 +1797,17 @@ static int vgic_init_maps(struct kvm *kvm)
1802 int nr_cpus, nr_irqs; 1797 int nr_cpus, nr_irqs;
1803 int ret, i; 1798 int ret, i;
1804 1799
1805 nr_cpus = dist->nr_cpus = KVM_MAX_VCPUS; 1800 if (dist->nr_cpus) /* Already allocated */
1801 return 0;
1802
1803 nr_cpus = dist->nr_cpus = atomic_read(&kvm->online_vcpus);
1804 if (!nr_cpus) /* No vcpus? Can't be good... */
1805 return -EINVAL;
1806 1806
1807 /*
1808 * If nobody configured the number of interrupts, use the
1809 * legacy one.
1810 */
1807 if (!dist->nr_irqs) 1811 if (!dist->nr_irqs)
1808 dist->nr_irqs = VGIC_NR_IRQS_LEGACY; 1812 dist->nr_irqs = VGIC_NR_IRQS_LEGACY;
1809 1813
@@ -1849,6 +1853,9 @@ static int vgic_init_maps(struct kvm *kvm)
1849 } 1853 }
1850 } 1854 }
1851 1855
1856 for (i = VGIC_NR_PRIVATE_IRQS; i < dist->nr_irqs; i += 4)
1857 vgic_set_target_reg(kvm, 0, i);
1858
1852out: 1859out:
1853 if (ret) 1860 if (ret)
1854 kvm_vgic_destroy(kvm); 1861 kvm_vgic_destroy(kvm);
@@ -1867,6 +1874,7 @@ out:
1867 */ 1874 */
1868int kvm_vgic_init(struct kvm *kvm) 1875int kvm_vgic_init(struct kvm *kvm)
1869{ 1876{
1877 struct kvm_vcpu *vcpu;
1870 int ret = 0, i; 1878 int ret = 0, i;
1871 1879
1872 if (!irqchip_in_kernel(kvm)) 1880 if (!irqchip_in_kernel(kvm))
@@ -1884,6 +1892,12 @@ int kvm_vgic_init(struct kvm *kvm)
1884 goto out; 1892 goto out;
1885 } 1893 }
1886 1894
1895 ret = vgic_init_maps(kvm);
1896 if (ret) {
1897 kvm_err("Unable to allocate maps\n");
1898 goto out;
1899 }
1900
1887 ret = kvm_phys_addr_ioremap(kvm, kvm->arch.vgic.vgic_cpu_base, 1901 ret = kvm_phys_addr_ioremap(kvm, kvm->arch.vgic.vgic_cpu_base,
1888 vgic->vcpu_base, KVM_VGIC_V2_CPU_SIZE); 1902 vgic->vcpu_base, KVM_VGIC_V2_CPU_SIZE);
1889 if (ret) { 1903 if (ret) {
@@ -1891,11 +1905,13 @@ int kvm_vgic_init(struct kvm *kvm)
1891 goto out; 1905 goto out;
1892 } 1906 }
1893 1907
1894 for (i = VGIC_NR_PRIVATE_IRQS; i < kvm->arch.vgic.nr_irqs; i += 4) 1908 kvm_for_each_vcpu(i, vcpu, kvm)
1895 vgic_set_target_reg(kvm, 0, i); 1909 kvm_vgic_vcpu_init(vcpu);
1896 1910
1897 kvm->arch.vgic.ready = true; 1911 kvm->arch.vgic.ready = true;
1898out: 1912out:
1913 if (ret)
1914 kvm_vgic_destroy(kvm);
1899 mutex_unlock(&kvm->lock); 1915 mutex_unlock(&kvm->lock);
1900 return ret; 1916 return ret;
1901} 1917}
@@ -1936,10 +1952,6 @@ int kvm_vgic_create(struct kvm *kvm)
1936 kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF; 1952 kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF;
1937 kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF; 1953 kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF;
1938 1954
1939 ret = vgic_init_maps(kvm);
1940 if (ret)
1941 kvm_err("Unable to allocate maps\n");
1942
1943out_unlock: 1955out_unlock:
1944 for (; vcpu_lock_idx >= 0; vcpu_lock_idx--) { 1956 for (; vcpu_lock_idx >= 0; vcpu_lock_idx--) {
1945 vcpu = kvm_get_vcpu(kvm, vcpu_lock_idx); 1957 vcpu = kvm_get_vcpu(kvm, vcpu_lock_idx);
@@ -2140,6 +2152,10 @@ static int vgic_attr_regs_access(struct kvm_device *dev,
2140 2152
2141 mutex_lock(&dev->kvm->lock); 2153 mutex_lock(&dev->kvm->lock);
2142 2154
2155 ret = vgic_init_maps(dev->kvm);
2156 if (ret)
2157 goto out;
2158
2143 if (cpuid >= atomic_read(&dev->kvm->online_vcpus)) { 2159 if (cpuid >= atomic_read(&dev->kvm->online_vcpus)) {
2144 ret = -EINVAL; 2160 ret = -EINVAL;
2145 goto out; 2161 goto out;