diff options
author | Marcelo Tosatti <mtosatt@redhat.com> | 2015-03-16 19:08:56 -0400 |
---|---|---|
committer | Marcelo Tosatti <mtosatti@redhat.com> | 2015-03-16 19:08:56 -0400 |
commit | f710a12d73dfa1c3a5d2417f2482b970f03bb850 (patch) | |
tree | 5e3be52f50fe01bb05ab4371a901cfc6e65108f7 /arch/arm64 | |
parent | 670125bda1d86edfadf81dc56a87582ac7fbd47b (diff) | |
parent | ae705930fca6322600690df9dc1c7d0516145a93 (diff) |
Merge tag 'kvm-arm-fixes-4.0-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm
Fixes for KVM/ARM for 4.0-rc5.
Fixes page refcounting issues in our Stage-2 page table management code,
fixes a missing unlock in a gicv3 error path, and fixes a race that can
cause lost interrupts if signals are pending just prior to entering the
guest.
Diffstat (limited to 'arch/arm64')
-rw-r--r-- | arch/arm64/include/asm/kvm_arm.h | 5 | ||||
-rw-r--r-- | arch/arm64/include/asm/kvm_mmu.h | 48 |
2 files changed, 9 insertions, 44 deletions
diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h index 94674eb7e7bb..54bb4ba97441 100644 --- a/arch/arm64/include/asm/kvm_arm.h +++ b/arch/arm64/include/asm/kvm_arm.h | |||
@@ -129,6 +129,9 @@ | |||
129 | * 40 bits wide (T0SZ = 24). Systems with a PARange smaller than 40 bits are | 129 | * 40 bits wide (T0SZ = 24). Systems with a PARange smaller than 40 bits are |
130 | * not known to exist and will break with this configuration. | 130 | * not known to exist and will break with this configuration. |
131 | * | 131 | * |
132 | * VTCR_EL2.PS is extracted from ID_AA64MMFR0_EL1.PARange at boot time | ||
133 | * (see hyp-init.S). | ||
134 | * | ||
132 | * Note that when using 4K pages, we concatenate two first level page tables | 135 | * Note that when using 4K pages, we concatenate two first level page tables |
133 | * together. | 136 | * together. |
134 | * | 137 | * |
@@ -138,7 +141,6 @@ | |||
138 | #ifdef CONFIG_ARM64_64K_PAGES | 141 | #ifdef CONFIG_ARM64_64K_PAGES |
139 | /* | 142 | /* |
140 | * Stage2 translation configuration: | 143 | * Stage2 translation configuration: |
141 | * 40bits output (PS = 2) | ||
142 | * 40bits input (T0SZ = 24) | 144 | * 40bits input (T0SZ = 24) |
143 | * 64kB pages (TG0 = 1) | 145 | * 64kB pages (TG0 = 1) |
144 | * 2 level page tables (SL = 1) | 146 | * 2 level page tables (SL = 1) |
@@ -150,7 +152,6 @@ | |||
150 | #else | 152 | #else |
151 | /* | 153 | /* |
152 | * Stage2 translation configuration: | 154 | * Stage2 translation configuration: |
153 | * 40bits output (PS = 2) | ||
154 | * 40bits input (T0SZ = 24) | 155 | * 40bits input (T0SZ = 24) |
155 | * 4kB pages (TG0 = 0) | 156 | * 4kB pages (TG0 = 0) |
156 | * 3 level page tables (SL = 1) | 157 | * 3 level page tables (SL = 1) |
diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h index 6458b5373142..bbfb600fa822 100644 --- a/arch/arm64/include/asm/kvm_mmu.h +++ b/arch/arm64/include/asm/kvm_mmu.h | |||
@@ -158,6 +158,8 @@ static inline bool kvm_s2pmd_readonly(pmd_t *pmd) | |||
158 | #define PTRS_PER_S2_PGD (1 << PTRS_PER_S2_PGD_SHIFT) | 158 | #define PTRS_PER_S2_PGD (1 << PTRS_PER_S2_PGD_SHIFT) |
159 | #define S2_PGD_ORDER get_order(PTRS_PER_S2_PGD * sizeof(pgd_t)) | 159 | #define S2_PGD_ORDER get_order(PTRS_PER_S2_PGD * sizeof(pgd_t)) |
160 | 160 | ||
161 | #define kvm_pgd_index(addr) (((addr) >> PGDIR_SHIFT) & (PTRS_PER_S2_PGD - 1)) | ||
162 | |||
161 | /* | 163 | /* |
162 | * If we are concatenating first level stage-2 page tables, we would have less | 164 | * If we are concatenating first level stage-2 page tables, we would have less |
163 | * than or equal to 16 pointers in the fake PGD, because that's what the | 165 | * than or equal to 16 pointers in the fake PGD, because that's what the |
@@ -171,43 +173,6 @@ static inline bool kvm_s2pmd_readonly(pmd_t *pmd) | |||
171 | #define KVM_PREALLOC_LEVEL (0) | 173 | #define KVM_PREALLOC_LEVEL (0) |
172 | #endif | 174 | #endif |
173 | 175 | ||
174 | /** | ||
175 | * kvm_prealloc_hwpgd - allocate inital table for VTTBR | ||
176 | * @kvm: The KVM struct pointer for the VM. | ||
177 | * @pgd: The kernel pseudo pgd | ||
178 | * | ||
179 | * When the kernel uses more levels of page tables than the guest, we allocate | ||
180 | * a fake PGD and pre-populate it to point to the next-level page table, which | ||
181 | * will be the real initial page table pointed to by the VTTBR. | ||
182 | * | ||
183 | * When KVM_PREALLOC_LEVEL==2, we allocate a single page for the PMD and | ||
184 | * the kernel will use folded pud. When KVM_PREALLOC_LEVEL==1, we | ||
185 | * allocate 2 consecutive PUD pages. | ||
186 | */ | ||
187 | static inline int kvm_prealloc_hwpgd(struct kvm *kvm, pgd_t *pgd) | ||
188 | { | ||
189 | unsigned int i; | ||
190 | unsigned long hwpgd; | ||
191 | |||
192 | if (KVM_PREALLOC_LEVEL == 0) | ||
193 | return 0; | ||
194 | |||
195 | hwpgd = __get_free_pages(GFP_KERNEL | __GFP_ZERO, PTRS_PER_S2_PGD_SHIFT); | ||
196 | if (!hwpgd) | ||
197 | return -ENOMEM; | ||
198 | |||
199 | for (i = 0; i < PTRS_PER_S2_PGD; i++) { | ||
200 | if (KVM_PREALLOC_LEVEL == 1) | ||
201 | pgd_populate(NULL, pgd + i, | ||
202 | (pud_t *)hwpgd + i * PTRS_PER_PUD); | ||
203 | else if (KVM_PREALLOC_LEVEL == 2) | ||
204 | pud_populate(NULL, pud_offset(pgd, 0) + i, | ||
205 | (pmd_t *)hwpgd + i * PTRS_PER_PMD); | ||
206 | } | ||
207 | |||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | static inline void *kvm_get_hwpgd(struct kvm *kvm) | 176 | static inline void *kvm_get_hwpgd(struct kvm *kvm) |
212 | { | 177 | { |
213 | pgd_t *pgd = kvm->arch.pgd; | 178 | pgd_t *pgd = kvm->arch.pgd; |
@@ -224,12 +189,11 @@ static inline void *kvm_get_hwpgd(struct kvm *kvm) | |||
224 | return pmd_offset(pud, 0); | 189 | return pmd_offset(pud, 0); |
225 | } | 190 | } |
226 | 191 | ||
227 | static inline void kvm_free_hwpgd(struct kvm *kvm) | 192 | static inline unsigned int kvm_get_hwpgd_size(void) |
228 | { | 193 | { |
229 | if (KVM_PREALLOC_LEVEL > 0) { | 194 | if (KVM_PREALLOC_LEVEL > 0) |
230 | unsigned long hwpgd = (unsigned long)kvm_get_hwpgd(kvm); | 195 | return PTRS_PER_S2_PGD * PAGE_SIZE; |
231 | free_pages(hwpgd, PTRS_PER_S2_PGD_SHIFT); | 196 | return PTRS_PER_S2_PGD * sizeof(pgd_t); |
232 | } | ||
233 | } | 197 | } |
234 | 198 | ||
235 | static inline bool kvm_page_empty(void *ptr) | 199 | static inline bool kvm_page_empty(void *ptr) |