tsb.c 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. /* arch/sparc64/mm/tsb.c
  2. *
  3. * Copyright (C) 2006 David S. Miller <davem@davemloft.net>
  4. */
  5. #include <linux/kernel.h>
  6. #include <asm/system.h>
  7. #include <asm/page.h>
  8. #include <asm/tlbflush.h>
  9. #include <asm/tlb.h>
  10. #define TSB_ENTRY_ALIGNMENT 16
  11. struct tsb {
  12. unsigned long tag;
  13. unsigned long pte;
  14. } __attribute__((aligned(TSB_ENTRY_ALIGNMENT)));
  15. /* We use an 8K TSB for the whole kernel, this allows to
  16. * handle about 4MB of modules and vmalloc mappings without
  17. * incurring many hash conflicts.
  18. */
  19. #define KERNEL_TSB_SIZE_BYTES 8192
  20. #define KERNEL_TSB_NENTRIES \
  21. (KERNEL_TSB_SIZE_BYTES / sizeof(struct tsb))
  22. extern struct tsb swapper_tsb[KERNEL_TSB_NENTRIES];
  23. static inline unsigned long tsb_hash(unsigned long vaddr)
  24. {
  25. vaddr >>= PAGE_SHIFT;
  26. return vaddr & (KERNEL_TSB_NENTRIES - 1);
  27. }
  28. static inline int tag_compare(struct tsb *entry, unsigned long vaddr, unsigned long context)
  29. {
  30. if (context == ~0UL)
  31. return 1;
  32. return (entry->tag == ((vaddr >> 22) | (context << 48)));
  33. }
  34. /* TSB flushes need only occur on the processor initiating the address
  35. * space modification, not on each cpu the address space has run on.
  36. * Only the TLB flush needs that treatment.
  37. */
  38. void flush_tsb_kernel_range(unsigned long start, unsigned long end)
  39. {
  40. unsigned long v;
  41. for (v = start; v < end; v += PAGE_SIZE) {
  42. struct tsb *ent = &swapper_tsb[tsb_hash(v)];
  43. if (tag_compare(ent, v, 0)) {
  44. ent->tag = 0UL;
  45. membar_storeload_storestore();
  46. }
  47. }
  48. }
  49. void flush_tsb_user(struct mmu_gather *mp)
  50. {
  51. struct mm_struct *mm = mp->mm;
  52. struct tsb *tsb = (struct tsb *) mm->context.sparc64_tsb;
  53. unsigned long ctx = ~0UL;
  54. int i;
  55. if (CTX_VALID(mm->context))
  56. ctx = CTX_HWBITS(mm->context);
  57. for (i = 0; i < mp->tlb_nr; i++) {
  58. unsigned long v = mp->vaddrs[i];
  59. struct tsb *ent;
  60. v &= ~0x1UL;
  61. ent = &tsb[tsb_hash(v)];
  62. if (tag_compare(ent, v, ctx)) {
  63. ent->tag = 0UL;
  64. membar_storeload_storestore();
  65. }
  66. }
  67. }