diff options
Diffstat (limited to 'include/asm-powerpc/pgtable.h')
| -rw-r--r-- | include/asm-powerpc/pgtable.h | 60 | 
1 files changed, 16 insertions, 44 deletions
| diff --git a/include/asm-powerpc/pgtable.h b/include/asm-powerpc/pgtable.h index 10f52743f4ff..19edb6982b81 100644 --- a/include/asm-powerpc/pgtable.h +++ b/include/asm-powerpc/pgtable.h | |||
| @@ -272,7 +272,10 @@ static inline pte_t pte_mkhuge(pte_t pte) { | |||
| 272 | return pte; } | 272 | return pte; } | 
| 273 | 273 | ||
| 274 | /* Atomic PTE updates */ | 274 | /* Atomic PTE updates */ | 
| 275 | static inline unsigned long pte_update(pte_t *p, unsigned long clr) | 275 | static inline unsigned long pte_update(struct mm_struct *mm, | 
| 276 | unsigned long addr, | ||
| 277 | pte_t *ptep, unsigned long clr, | ||
| 278 | int huge) | ||
| 276 | { | 279 | { | 
| 277 | unsigned long old, tmp; | 280 | unsigned long old, tmp; | 
| 278 | 281 | ||
| @@ -283,20 +286,15 @@ static inline unsigned long pte_update(pte_t *p, unsigned long clr) | |||
| 283 | andc %1,%0,%4 \n\ | 286 | andc %1,%0,%4 \n\ | 
| 284 | stdcx. %1,0,%3 \n\ | 287 | stdcx. %1,0,%3 \n\ | 
| 285 | bne- 1b" | 288 | bne- 1b" | 
| 286 | : "=&r" (old), "=&r" (tmp), "=m" (*p) | 289 | : "=&r" (old), "=&r" (tmp), "=m" (*ptep) | 
| 287 | : "r" (p), "r" (clr), "m" (*p), "i" (_PAGE_BUSY) | 290 | : "r" (ptep), "r" (clr), "m" (*ptep), "i" (_PAGE_BUSY) | 
| 288 | : "cc" ); | 291 | : "cc" ); | 
| 292 | |||
| 293 | if (old & _PAGE_HASHPTE) | ||
| 294 | hpte_need_flush(mm, addr, ptep, old, huge); | ||
| 289 | return old; | 295 | return old; | 
| 290 | } | 296 | } | 
| 291 | 297 | ||
| 292 | /* PTE updating functions, this function puts the PTE in the | ||
| 293 | * batch, doesn't actually triggers the hash flush immediately, | ||
| 294 | * you need to call flush_tlb_pending() to do that. | ||
| 295 | * Pass -1 for "normal" size (4K or 64K) | ||
| 296 | */ | ||
| 297 | extern void hpte_update(struct mm_struct *mm, unsigned long addr, | ||
| 298 | pte_t *ptep, unsigned long pte, int huge); | ||
| 299 | |||
| 300 | static inline int __ptep_test_and_clear_young(struct mm_struct *mm, | 298 | static inline int __ptep_test_and_clear_young(struct mm_struct *mm, | 
| 301 | unsigned long addr, pte_t *ptep) | 299 | unsigned long addr, pte_t *ptep) | 
| 302 | { | 300 | { | 
| @@ -304,11 +302,7 @@ static inline int __ptep_test_and_clear_young(struct mm_struct *mm, | |||
| 304 | 302 | ||
| 305 | if ((pte_val(*ptep) & (_PAGE_ACCESSED | _PAGE_HASHPTE)) == 0) | 303 | if ((pte_val(*ptep) & (_PAGE_ACCESSED | _PAGE_HASHPTE)) == 0) | 
| 306 | return 0; | 304 | return 0; | 
| 307 | old = pte_update(ptep, _PAGE_ACCESSED); | 305 | old = pte_update(mm, addr, ptep, _PAGE_ACCESSED, 0); | 
| 308 | if (old & _PAGE_HASHPTE) { | ||
| 309 | hpte_update(mm, addr, ptep, old, 0); | ||
| 310 | flush_tlb_pending(); | ||
| 311 | } | ||
| 312 | return (old & _PAGE_ACCESSED) != 0; | 306 | return (old & _PAGE_ACCESSED) != 0; | 
| 313 | } | 307 | } | 
| 314 | #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG | 308 | #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG | 
| @@ -331,9 +325,7 @@ static inline int __ptep_test_and_clear_dirty(struct mm_struct *mm, | |||
| 331 | 325 | ||
| 332 | if ((pte_val(*ptep) & _PAGE_DIRTY) == 0) | 326 | if ((pte_val(*ptep) & _PAGE_DIRTY) == 0) | 
| 333 | return 0; | 327 | return 0; | 
| 334 | old = pte_update(ptep, _PAGE_DIRTY); | 328 | old = pte_update(mm, addr, ptep, _PAGE_DIRTY, 0); | 
| 335 | if (old & _PAGE_HASHPTE) | ||
| 336 | hpte_update(mm, addr, ptep, old, 0); | ||
| 337 | return (old & _PAGE_DIRTY) != 0; | 329 | return (old & _PAGE_DIRTY) != 0; | 
| 338 | } | 330 | } | 
| 339 | #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY | 331 | #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY | 
| @@ -352,9 +344,7 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, | |||
| 352 | 344 | ||
| 353 | if ((pte_val(*ptep) & _PAGE_RW) == 0) | 345 | if ((pte_val(*ptep) & _PAGE_RW) == 0) | 
| 354 | return; | 346 | return; | 
| 355 | old = pte_update(ptep, _PAGE_RW); | 347 | old = pte_update(mm, addr, ptep, _PAGE_RW, 0); | 
| 356 | if (old & _PAGE_HASHPTE) | ||
| 357 | hpte_update(mm, addr, ptep, old, 0); | ||
| 358 | } | 348 | } | 
| 359 | 349 | ||
| 360 | /* | 350 | /* | 
| @@ -378,7 +368,6 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, | |||
| 378 | ({ \ | 368 | ({ \ | 
| 379 | int __dirty = __ptep_test_and_clear_dirty((__vma)->vm_mm, __address, \ | 369 | int __dirty = __ptep_test_and_clear_dirty((__vma)->vm_mm, __address, \ | 
| 380 | __ptep); \ | 370 | __ptep); \ | 
| 381 | flush_tlb_page(__vma, __address); \ | ||
| 382 | __dirty; \ | 371 | __dirty; \ | 
| 383 | }) | 372 | }) | 
| 384 | 373 | ||
| @@ -386,20 +375,14 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, | |||
| 386 | static inline pte_t ptep_get_and_clear(struct mm_struct *mm, | 375 | static inline pte_t ptep_get_and_clear(struct mm_struct *mm, | 
| 387 | unsigned long addr, pte_t *ptep) | 376 | unsigned long addr, pte_t *ptep) | 
| 388 | { | 377 | { | 
| 389 | unsigned long old = pte_update(ptep, ~0UL); | 378 | unsigned long old = pte_update(mm, addr, ptep, ~0UL, 0); | 
| 390 | |||
| 391 | if (old & _PAGE_HASHPTE) | ||
| 392 | hpte_update(mm, addr, ptep, old, 0); | ||
| 393 | return __pte(old); | 379 | return __pte(old); | 
| 394 | } | 380 | } | 
| 395 | 381 | ||
| 396 | static inline void pte_clear(struct mm_struct *mm, unsigned long addr, | 382 | static inline void pte_clear(struct mm_struct *mm, unsigned long addr, | 
| 397 | pte_t * ptep) | 383 | pte_t * ptep) | 
| 398 | { | 384 | { | 
| 399 | unsigned long old = pte_update(ptep, ~0UL); | 385 | pte_update(mm, addr, ptep, ~0UL, 0); | 
| 400 | |||
| 401 | if (old & _PAGE_HASHPTE) | ||
| 402 | hpte_update(mm, addr, ptep, old, 0); | ||
| 403 | } | 386 | } | 
| 404 | 387 | ||
| 405 | /* | 388 | /* | 
| @@ -408,10 +391,8 @@ static inline void pte_clear(struct mm_struct *mm, unsigned long addr, | |||
| 408 | static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, | 391 | static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, | 
| 409 | pte_t *ptep, pte_t pte) | 392 | pte_t *ptep, pte_t pte) | 
| 410 | { | 393 | { | 
| 411 | if (pte_present(*ptep)) { | 394 | if (pte_present(*ptep)) | 
| 412 | pte_clear(mm, addr, ptep); | 395 | pte_clear(mm, addr, ptep); | 
| 413 | flush_tlb_pending(); | ||
| 414 | } | ||
| 415 | pte = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS); | 396 | pte = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS); | 
| 416 | *ptep = pte; | 397 | *ptep = pte; | 
| 417 | } | 398 | } | 
| @@ -467,16 +448,6 @@ extern pgd_t swapper_pg_dir[]; | |||
| 467 | 448 | ||
| 468 | extern void paging_init(void); | 449 | extern void paging_init(void); | 
| 469 | 450 | ||
| 470 | /* | ||
| 471 | * This gets called at the end of handling a page fault, when | ||
| 472 | * the kernel has put a new PTE into the page table for the process. | ||
| 473 | * We use it to put a corresponding HPTE into the hash table | ||
| 474 | * ahead of time, instead of waiting for the inevitable extra | ||
| 475 | * hash-table miss exception. | ||
| 476 | */ | ||
| 477 | struct vm_area_struct; | ||
| 478 | extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t); | ||
| 479 | |||
| 480 | /* Encode and de-code a swap entry */ | 451 | /* Encode and de-code a swap entry */ | 
| 481 | #define __swp_type(entry) (((entry).val >> 1) & 0x3f) | 452 | #define __swp_type(entry) (((entry).val >> 1) & 0x3f) | 
| 482 | #define __swp_offset(entry) ((entry).val >> 8) | 453 | #define __swp_offset(entry) ((entry).val >> 8) | 
| @@ -522,6 +493,7 @@ void pgtable_cache_init(void); | |||
| 522 | return pt; | 493 | return pt; | 
| 523 | } | 494 | } | 
| 524 | 495 | ||
| 496 | |||
| 525 | #include <asm-generic/pgtable.h> | 497 | #include <asm-generic/pgtable.h> | 
| 526 | 498 | ||
| 527 | #endif /* __ASSEMBLY__ */ | 499 | #endif /* __ASSEMBLY__ */ | 
