diff options
| -rw-r--r-- | arch/x86/xen/mmu.c | 284 | ||||
| -rw-r--r-- | arch/x86/xen/mmu.h | 37 | ||||
| -rw-r--r-- | mm/vmalloc.c | 4 |
3 files changed, 50 insertions, 275 deletions
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 02d752460371..dc708dcc62f1 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c | |||
| @@ -75,67 +75,12 @@ | |||
| 75 | #include "mmu.h" | 75 | #include "mmu.h" |
| 76 | #include "debugfs.h" | 76 | #include "debugfs.h" |
| 77 | 77 | ||
| 78 | #define MMU_UPDATE_HISTO 30 | ||
| 79 | |||
| 80 | /* | 78 | /* |
| 81 | * Protects atomic reservation decrease/increase against concurrent increases. | 79 | * Protects atomic reservation decrease/increase against concurrent increases. |
| 82 | * Also protects non-atomic updates of current_pages and balloon lists. | 80 | * Also protects non-atomic updates of current_pages and balloon lists. |
| 83 | */ | 81 | */ |
| 84 | DEFINE_SPINLOCK(xen_reservation_lock); | 82 | DEFINE_SPINLOCK(xen_reservation_lock); |
| 85 | 83 | ||
| 86 | #ifdef CONFIG_XEN_DEBUG_FS | ||
| 87 | |||
| 88 | static struct { | ||
| 89 | u32 pgd_update; | ||
| 90 | u32 pgd_update_pinned; | ||
| 91 | u32 pgd_update_batched; | ||
| 92 | |||
| 93 | u32 pud_update; | ||
| 94 | u32 pud_update_pinned; | ||
| 95 | u32 pud_update_batched; | ||
| 96 | |||
| 97 | u32 pmd_update; | ||
| 98 | u32 pmd_update_pinned; | ||
| 99 | u32 pmd_update_batched; | ||
| 100 | |||
| 101 | u32 pte_update; | ||
| 102 | u32 pte_update_pinned; | ||
| 103 | u32 pte_update_batched; | ||
| 104 | |||
| 105 | u32 mmu_update; | ||
| 106 | u32 mmu_update_extended; | ||
| 107 | u32 mmu_update_histo[MMU_UPDATE_HISTO]; | ||
| 108 | |||
| 109 | u32 prot_commit; | ||
| 110 | u32 prot_commit_batched; | ||
| 111 | |||
| 112 | u32 set_pte_at; | ||
| 113 | u32 set_pte_at_batched; | ||
| 114 | u32 set_pte_at_pinned; | ||
| 115 | u32 set_pte_at_current; | ||
| 116 | u32 set_pte_at_kernel; | ||
| 117 | } mmu_stats; | ||
| 118 | |||
| 119 | static u8 zero_stats; | ||
| 120 | |||
| 121 | static inline void check_zero(void) | ||
| 122 | { | ||
| 123 | if (unlikely(zero_stats)) { | ||
| 124 | memset(&mmu_stats, 0, sizeof(mmu_stats)); | ||
| 125 | zero_stats = 0; | ||
| 126 | } | ||
| 127 | } | ||
| 128 | |||
| 129 | #define ADD_STATS(elem, val) \ | ||
| 130 | do { check_zero(); mmu_stats.elem += (val); } while(0) | ||
| 131 | |||
| 132 | #else /* !CONFIG_XEN_DEBUG_FS */ | ||
| 133 | |||
| 134 | #define ADD_STATS(elem, val) do { (void)(val); } while(0) | ||
| 135 | |||
| 136 | #endif /* CONFIG_XEN_DEBUG_FS */ | ||
| 137 | |||
| 138 | |||
| 139 | /* | 84 | /* |
| 140 | * Identity map, in addition to plain kernel map. This needs to be | 85 | * Identity map, in addition to plain kernel map. This needs to be |
| 141 | * large enough to allocate page table pages to allocate the rest. | 86 | * large enough to allocate page table pages to allocate the rest. |
| @@ -243,11 +188,6 @@ static bool xen_page_pinned(void *ptr) | |||
| 243 | return PagePinned(page); | 188 | return PagePinned(page); |
| 244 | } | 189 | } |
| 245 | 190 | ||
| 246 | static bool xen_iomap_pte(pte_t pte) | ||
| 247 | { | ||
| 248 | return pte_flags(pte) & _PAGE_IOMAP; | ||
| 249 | } | ||
| 250 | |||
| 251 | void xen_set_domain_pte(pte_t *ptep, pte_t pteval, unsigned domid) | 191 | void xen_set_domain_pte(pte_t *ptep, pte_t pteval, unsigned domid) |
| 252 | { | 192 | { |
| 253 | struct multicall_space mcs; | 193 | struct multicall_space mcs; |
| @@ -257,7 +197,7 @@ void xen_set_domain_pte(pte_t *ptep, pte_t pteval, unsigned domid) | |||
| 257 | u = mcs.args; | 197 | u = mcs.args; |
| 258 | 198 | ||
| 259 | /* ptep might be kmapped when using 32-bit HIGHPTE */ | 199 | /* ptep might be kmapped when using 32-bit HIGHPTE */ |
| 260 | u->ptr = arbitrary_virt_to_machine(ptep).maddr; | 200 | u->ptr = virt_to_machine(ptep).maddr; |
| 261 | u->val = pte_val_ma(pteval); | 201 | u->val = pte_val_ma(pteval); |
| 262 | 202 | ||
| 263 | MULTI_mmu_update(mcs.mc, mcs.args, 1, NULL, domid); | 203 | MULTI_mmu_update(mcs.mc, mcs.args, 1, NULL, domid); |
| @@ -266,11 +206,6 @@ void xen_set_domain_pte(pte_t *ptep, pte_t pteval, unsigned domid) | |||
| 266 | } | 206 | } |
| 267 | EXPORT_SYMBOL_GPL(xen_set_domain_pte); | 207 | EXPORT_SYMBOL_GPL(xen_set_domain_pte); |
| 268 | 208 | ||
| 269 | static void xen_set_iomap_pte(pte_t *ptep, pte_t pteval) | ||
| 270 | { | ||
| 271 | xen_set_domain_pte(ptep, pteval, DOMID_IO); | ||
| 272 | } | ||
| 273 | |||
| 274 | static void xen_extend_mmu_update(const struct mmu_update *update) | 209 | static void xen_extend_mmu_update(const struct mmu_update *update) |
| 275 | { | 210 | { |
| 276 | struct multicall_space mcs; | 211 | struct multicall_space mcs; |
| @@ -279,27 +214,17 @@ static void xen_extend_mmu_update(const struct mmu_update *update) | |||
| 279 | mcs = xen_mc_extend_args(__HYPERVISOR_mmu_update, sizeof(*u)); | 214 | mcs = xen_mc_extend_args(__HYPERVISOR_mmu_update, sizeof(*u)); |
| 280 | 215 | ||
| 281 | if (mcs.mc != NULL) { | 216 | if (mcs.mc != NULL) { |
| 282 | ADD_STATS(mmu_update_extended, 1); | ||
| 283 | ADD_STATS(mmu_update_histo[mcs.mc->args[1]], -1); | ||
| 284 | |||
| 285 | mcs.mc->args[1]++; | 217 | mcs.mc->args[1]++; |
| 286 | |||
| 287 | if (mcs.mc->args[1] < MMU_UPDATE_HISTO) | ||
| 288 | ADD_STATS(mmu_update_histo[mcs.mc->args[1]], 1); | ||
| 289 | else | ||
| 290 | ADD_STATS(mmu_update_histo[0], 1); | ||
| 291 | } else { | 218 | } else { |
| 292 | ADD_STATS(mmu_update, 1); | ||
| 293 | mcs = __xen_mc_entry(sizeof(*u)); | 219 | mcs = __xen_mc_entry(sizeof(*u)); |
| 294 | MULTI_mmu_update(mcs.mc, mcs.args, 1, NULL, DOMID_SELF); | 220 | MULTI_mmu_update(mcs.mc, mcs.args, 1, NULL, DOMID_SELF); |
| 295 | ADD_STATS(mmu_update_histo[1], 1); | ||
| 296 | } | 221 | } |
| 297 | 222 | ||
| 298 | u = mcs.args; | 223 | u = mcs.args; |
| 299 | *u = *update; | 224 | *u = *update; |
| 300 | } | 225 | } |
| 301 | 226 | ||
| 302 | void xen_set_pmd_hyper(pmd_t *ptr, pmd_t val) | 227 | static void xen_set_pmd_hyper(pmd_t *ptr, pmd_t val) |
| 303 | { | 228 | { |
| 304 | struct mmu_update u; | 229 | struct mmu_update u; |
| 305 | 230 | ||
| @@ -312,17 +237,13 @@ void xen_set_pmd_hyper(pmd_t *ptr, pmd_t val) | |||
| 312 | u.val = pmd_val_ma(val); | 237 | u.val = pmd_val_ma(val); |
| 313 | xen_extend_mmu_update(&u); | 238 | xen_extend_mmu_update(&u); |
| 314 | 239 | ||
| 315 | ADD_STATS(pmd_update_batched, paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU); | ||
| 316 | |||
| 317 | xen_mc_issue(PARAVIRT_LAZY_MMU); | 240 | xen_mc_issue(PARAVIRT_LAZY_MMU); |
| 318 | 241 | ||
| 319 | preempt_enable(); | 242 | preempt_enable(); |
| 320 | } | 243 | } |
| 321 | 244 | ||
| 322 | void xen_set_pmd(pmd_t *ptr, pmd_t val) | 245 | static void xen_set_pmd(pmd_t *ptr, pmd_t val) |
| 323 | { | 246 | { |
| 324 | ADD_STATS(pmd_update, 1); | ||
| 325 | |||
| 326 | /* If page is not pinned, we can just update the entry | 247 | /* If page is not pinned, we can just update the entry |
| 327 | directly */ | 248 | directly */ |
| 328 | if (!xen_page_pinned(ptr)) { | 249 | if (!xen_page_pinned(ptr)) { |
| @@ -330,8 +251,6 @@ void xen_set_pmd(pmd_t *ptr, pmd_t val) | |||
| 330 | return; | 251 | return; |
| 331 | } | 252 | } |
| 332 | 253 | ||
| 333 | ADD_STATS(pmd_update_pinned, 1); | ||
| 334 | |||
| 335 | xen_set_pmd_hyper(ptr, val); | 254 | xen_set_pmd_hyper(ptr, val); |
| 336 | } | 255 | } |
| 337 | 256 | ||
| @@ -344,35 +263,34 @@ void set_pte_mfn(unsigned long vaddr, unsigned long mfn, pgprot_t flags) | |||
| 344 | set_pte_vaddr(vaddr, mfn_pte(mfn, flags)); | 263 | set_pte_vaddr(vaddr, mfn_pte(mfn, flags)); |
| 345 | } | 264 | } |
| 346 | 265 | ||
| 347 | void xen_set_pte_at(struct mm_struct *mm, unsigned long addr, | 266 | static bool xen_batched_set_pte(pte_t *ptep, pte_t pteval) |
| 348 | pte_t *ptep, pte_t pteval) | ||
| 349 | { | 267 | { |
| 350 | if (xen_iomap_pte(pteval)) { | 268 | struct mmu_update u; |
| 351 | xen_set_iomap_pte(ptep, pteval); | ||
| 352 | goto out; | ||
| 353 | } | ||
| 354 | 269 | ||
| 355 | ADD_STATS(set_pte_at, 1); | 270 | if (paravirt_get_lazy_mode() != PARAVIRT_LAZY_MMU) |
| 356 | // ADD_STATS(set_pte_at_pinned, xen_page_pinned(ptep)); | 271 | return false; |
| 357 | ADD_STATS(set_pte_at_current, mm == current->mm); | ||
| 358 | ADD_STATS(set_pte_at_kernel, mm == &init_mm); | ||
| 359 | 272 | ||
| 360 | if (mm == current->mm || mm == &init_mm) { | 273 | xen_mc_batch(); |
