diff options
-rw-r--r-- | arch/powerpc/include/asm/kvm_ppc.h | 1 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s_64_mmu_hv.c | 37 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s_hv.c | 3 |
3 files changed, 25 insertions, 16 deletions
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h index 96753f3aac6d..941c2a3f231b 100644 --- a/arch/powerpc/include/asm/kvm_ppc.h +++ b/arch/powerpc/include/asm/kvm_ppc.h | |||
@@ -180,6 +180,7 @@ extern void kvm_spapr_tce_release_iommu_group(struct kvm *kvm, | |||
180 | struct iommu_group *grp); | 180 | struct iommu_group *grp); |
181 | extern int kvmppc_switch_mmu_to_hpt(struct kvm *kvm); | 181 | extern int kvmppc_switch_mmu_to_hpt(struct kvm *kvm); |
182 | extern int kvmppc_switch_mmu_to_radix(struct kvm *kvm); | 182 | extern int kvmppc_switch_mmu_to_radix(struct kvm *kvm); |
183 | extern void kvmppc_setup_partition_table(struct kvm *kvm); | ||
183 | 184 | ||
184 | extern long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm, | 185 | extern long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm, |
185 | struct kvm_create_spapr_tce_64 *args); | 186 | struct kvm_create_spapr_tce_64 *args); |
diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c index 235319c2574e..966097232d21 100644 --- a/arch/powerpc/kvm/book3s_64_mmu_hv.c +++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c | |||
@@ -1238,8 +1238,9 @@ static unsigned long resize_hpt_rehash_hpte(struct kvm_resize_hpt *resize, | |||
1238 | unsigned long vpte, rpte, guest_rpte; | 1238 | unsigned long vpte, rpte, guest_rpte; |
1239 | int ret; | 1239 | int ret; |
1240 | struct revmap_entry *rev; | 1240 | struct revmap_entry *rev; |
1241 | unsigned long apsize, psize, avpn, pteg, hash; | 1241 | unsigned long apsize, avpn, pteg, hash; |
1242 | unsigned long new_idx, new_pteg, replace_vpte; | 1242 | unsigned long new_idx, new_pteg, replace_vpte; |
1243 | int pshift; | ||
1243 | 1244 | ||
1244 | hptep = (__be64 *)(old->virt + (idx << 4)); | 1245 | hptep = (__be64 *)(old->virt + (idx << 4)); |
1245 | 1246 | ||
@@ -1298,8 +1299,8 @@ static unsigned long resize_hpt_rehash_hpte(struct kvm_resize_hpt *resize, | |||
1298 | goto out; | 1299 | goto out; |
1299 | 1300 | ||
1300 | rpte = be64_to_cpu(hptep[1]); | 1301 | rpte = be64_to_cpu(hptep[1]); |
1301 | psize = hpte_base_page_size(vpte, rpte); | 1302 | pshift = kvmppc_hpte_base_page_shift(vpte, rpte); |
1302 | avpn = HPTE_V_AVPN_VAL(vpte) & ~((psize - 1) >> 23); | 1303 | avpn = HPTE_V_AVPN_VAL(vpte) & ~(((1ul << pshift) - 1) >> 23); |
1303 | pteg = idx / HPTES_PER_GROUP; | 1304 | pteg = idx / HPTES_PER_GROUP; |
1304 | if (vpte & HPTE_V_SECONDARY) | 1305 | if (vpte & HPTE_V_SECONDARY) |
1305 | pteg = ~pteg; | 1306 | pteg = ~pteg; |
@@ -1311,20 +1312,20 @@ static unsigned long resize_hpt_rehash_hpte(struct kvm_resize_hpt *resize, | |||
1311 | offset = (avpn & 0x1f) << 23; | 1312 | offset = (avpn & 0x1f) << 23; |
1312 | vsid = avpn >> 5; | 1313 | vsid = avpn >> 5; |
1313 | /* We can find more bits from the pteg value */ | 1314 | /* We can find more bits from the pteg value */ |
1314 | if (psize < (1ULL << 23)) | 1315 | if (pshift < 23) |
1315 | offset |= ((vsid ^ pteg) & old_hash_mask) * psize; | 1316 | offset |= ((vsid ^ pteg) & old_hash_mask) << pshift; |
1316 | 1317 | ||
1317 | hash = vsid ^ (offset / psize); | 1318 | hash = vsid ^ (offset >> pshift); |
1318 | } else { | 1319 | } else { |
1319 | unsigned long offset, vsid; | 1320 | unsigned long offset, vsid; |
1320 | 1321 | ||
1321 | /* We only have 40 - 23 bits of seg_off in avpn */ | 1322 | /* We only have 40 - 23 bits of seg_off in avpn */ |
1322 | offset = (avpn & 0x1ffff) << 23; | 1323 | offset = (avpn & 0x1ffff) << 23; |
1323 | vsid = avpn >> 17; | 1324 | vsid = avpn >> 17; |
1324 | if (psize < (1ULL << 23)) | 1325 | if (pshift < 23) |
1325 | offset |= ((vsid ^ (vsid << 25) ^ pteg) & old_hash_mask) * psize; | 1326 | offset |= ((vsid ^ (vsid << 25) ^ pteg) & old_hash_mask) << pshift; |
1326 | 1327 | ||
1327 | hash = vsid ^ (vsid << 25) ^ (offset / psize); | 1328 | hash = vsid ^ (vsid << 25) ^ (offset >> pshift); |
1328 | } | 1329 | } |
1329 | 1330 | ||
1330 | new_pteg = hash & new_hash_mask; | 1331 | new_pteg = hash & new_hash_mask; |
@@ -1801,6 +1802,7 @@ static ssize_t kvm_htab_write(struct file *file, const char __user *buf, | |||
1801 | ssize_t nb; | 1802 | ssize_t nb; |
1802 | long int err, ret; | 1803 | long int err, ret; |
1803 | int mmu_ready; | 1804 | int mmu_ready; |
1805 | int pshift; | ||
1804 | 1806 | ||
1805 | if (!access_ok(VERIFY_READ, buf, count)) | 1807 | if (!access_ok(VERIFY_READ, buf, count)) |
1806 | return -EFAULT; | 1808 | return -EFAULT; |
@@ -1855,6 +1857,9 @@ static ssize_t kvm_htab_write(struct file *file, const char __user *buf, | |||
1855 | err = -EINVAL; | 1857 | err = -EINVAL; |
1856 | if (!(v & HPTE_V_VALID)) | 1858 | if (!(v & HPTE_V_VALID)) |
1857 | goto out; | 1859 | goto out; |
1860 | pshift = kvmppc_hpte_base_page_shift(v, r); | ||
1861 | if (pshift <= 0) | ||
1862 | goto out; | ||
1858 | lbuf += 2; | 1863 | lbuf += 2; |
1859 | nb += HPTE_SIZE; | 1864 | nb += HPTE_SIZE; |
1860 | 1865 | ||
@@ -1869,14 +1874,18 @@ static ssize_t kvm_htab_write(struct file *file, const char __user *buf, | |||
1869 | goto out; | 1874 | goto out; |
1870 | } | 1875 | } |
1871 | if (!mmu_ready && is_vrma_hpte(v)) { | 1876 | if (!mmu_ready && is_vrma_hpte(v)) { |
1872 | unsigned long psize = hpte_base_page_size(v, r); | 1877 | unsigned long senc, lpcr; |
1873 | unsigned long senc = slb_pgsize_encoding(psize); | ||
1874 | unsigned long lpcr; | ||
1875 | 1878 | ||
1879 | senc = slb_pgsize_encoding(1ul << pshift); | ||
1876 | kvm->arch.vrma_slb_v = senc | SLB_VSID_B_1T | | 1880 | kvm->arch.vrma_slb_v = senc | SLB_VSID_B_1T | |
1877 | (VRMA_VSID << SLB_VSID_SHIFT_1T); | 1881 | (VRMA_VSID << SLB_VSID_SHIFT_1T); |
1878 | lpcr = senc << (LPCR_VRMASD_SH - 4); | 1882 | if (!cpu_has_feature(CPU_FTR_ARCH_300)) { |
1879 | kvmppc_update_lpcr(kvm, lpcr, LPCR_VRMASD); | 1883 | lpcr = senc << (LPCR_VRMASD_SH - 4); |
1884 | kvmppc_update_lpcr(kvm, lpcr, | ||
1885 | LPCR_VRMASD); | ||
1886 | } else { | ||
1887 | kvmppc_setup_partition_table(kvm); | ||
1888 | } | ||
1880 | mmu_ready = 1; | 1889 | mmu_ready = 1; |
1881 | } | 1890 | } |
1882 | ++i; | 1891 | ++i; |
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index 79ea3d9269db..2d46037ce936 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c | |||
@@ -120,7 +120,6 @@ MODULE_PARM_DESC(h_ipi_redirect, "Redirect H_IPI wakeup to a free host core"); | |||
120 | 120 | ||
121 | static void kvmppc_end_cede(struct kvm_vcpu *vcpu); | 121 | static void kvmppc_end_cede(struct kvm_vcpu *vcpu); |
122 | static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu); | 122 | static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu); |
123 | static void kvmppc_setup_partition_table(struct kvm *kvm); | ||
124 | 123 | ||
125 | static inline struct kvm_vcpu *next_runnable_thread(struct kvmppc_vcore *vc, | 124 | static inline struct kvm_vcpu *next_runnable_thread(struct kvmppc_vcore *vc, |
126 | int *ip) | 125 | int *ip) |
@@ -3574,7 +3573,7 @@ static void kvmppc_mmu_destroy_hv(struct kvm_vcpu *vcpu) | |||
3574 | return; | 3573 | return; |
3575 | } | 3574 | } |
3576 | 3575 | ||
3577 | static void kvmppc_setup_partition_table(struct kvm *kvm) | 3576 | void kvmppc_setup_partition_table(struct kvm *kvm) |
3578 | { | 3577 | { |
3579 | unsigned long dw0, dw1; | 3578 | unsigned long dw0, dw1; |
3580 | 3579 | ||