pg-sh4.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. /*
  2. * arch/sh/mm/pg-sh4.c
  3. *
  4. * Copyright (C) 1999, 2000, 2002 Niibe Yutaka
  5. * Copyright (C) 2002 - 2005 Paul Mundt
  6. *
  7. * Released under the terms of the GNU GPL v2.0.
  8. */
  9. #include <linux/mm.h>
  10. #include <linux/mutex.h>
  11. #include <asm/mmu_context.h>
  12. #include <asm/cacheflush.h>
  13. extern struct mutex p3map_mutex[];
  14. #define CACHE_ALIAS (current_cpu_data.dcache.alias_mask)
  15. /*
  16. * clear_user_page
  17. * @to: P1 address
  18. * @address: U0 address to be mapped
  19. * @page: page (virt_to_page(to))
  20. */
  21. void clear_user_page(void *to, unsigned long address, struct page *page)
  22. {
  23. if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0)
  24. clear_page(to);
  25. else {
  26. unsigned long phys_addr = PHYSADDR(to);
  27. unsigned long p3_addr = P3SEG + (address & CACHE_ALIAS);
  28. pgd_t *pgd = pgd_offset_k(p3_addr);
  29. pud_t *pud = pud_offset(pgd, p3_addr);
  30. pmd_t *pmd = pmd_offset(pud, p3_addr);
  31. pte_t *pte = pte_offset_kernel(pmd, p3_addr);
  32. pte_t entry;
  33. unsigned long flags;
  34. entry = pfn_pte(phys_addr >> PAGE_SHIFT, PAGE_KERNEL);
  35. mutex_lock(&p3map_mutex[(address & CACHE_ALIAS)>>12]);
  36. set_pte(pte, entry);
  37. local_irq_save(flags);
  38. flush_tlb_one(get_asid(), p3_addr);
  39. local_irq_restore(flags);
  40. update_mmu_cache(NULL, p3_addr, entry);
  41. __clear_user_page((void *)p3_addr, to);
  42. pte_clear(&init_mm, p3_addr, pte);
  43. mutex_unlock(&p3map_mutex[(address & CACHE_ALIAS)>>12]);
  44. }
  45. }
  46. /*
  47. * copy_user_page
  48. * @to: P1 address
  49. * @from: P1 address
  50. * @address: U0 address to be mapped
  51. * @page: page (virt_to_page(to))
  52. */
  53. void copy_user_page(void *to, void *from, unsigned long address,
  54. struct page *page)
  55. {
  56. if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0)
  57. copy_page(to, from);
  58. else {
  59. unsigned long phys_addr = PHYSADDR(to);
  60. unsigned long p3_addr = P3SEG + (address & CACHE_ALIAS);
  61. pgd_t *pgd = pgd_offset_k(p3_addr);
  62. pud_t *pud = pud_offset(pgd, p3_addr);
  63. pmd_t *pmd = pmd_offset(pud, p3_addr);
  64. pte_t *pte = pte_offset_kernel(pmd, p3_addr);
  65. pte_t entry;
  66. unsigned long flags;
  67. entry = pfn_pte(phys_addr >> PAGE_SHIFT, PAGE_KERNEL);
  68. mutex_lock(&p3map_mutex[(address & CACHE_ALIAS)>>12]);
  69. set_pte(pte, entry);
  70. local_irq_save(flags);
  71. flush_tlb_one(get_asid(), p3_addr);
  72. local_irq_restore(flags);
  73. update_mmu_cache(NULL, p3_addr, entry);
  74. __copy_user_page((void *)p3_addr, from, to);
  75. pte_clear(&init_mm, p3_addr, pte);
  76. mutex_unlock(&p3map_mutex[(address & CACHE_ALIAS)>>12]);
  77. }
  78. }