hash_native.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. /*
  2. * native hashtable management.
  3. *
  4. * SMP scalability work:
  5. * Copyright (C) 2001 Anton Blanchard <anton@au.ibm.com>, IBM
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License
  9. * as published by the Free Software Foundation; either version
  10. * 2 of the License, or (at your option) any later version.
  11. */
  12. #include <linux/spinlock.h>
  13. #include <linux/bitops.h>
  14. #include <linux/threads.h>
  15. #include <linux/smp.h>
  16. #include <asm/abs_addr.h>
  17. #include <asm/machdep.h>
  18. #include <asm/mmu.h>
  19. #include <asm/mmu_context.h>
  20. #include <asm/pgtable.h>
  21. #include <asm/tlbflush.h>
  22. #include <asm/tlb.h>
  23. #include <asm/cputable.h>
  24. #define HPTE_LOCK_BIT 3
  25. static DEFINE_SPINLOCK(native_tlbie_lock);
  26. static inline void native_lock_hpte(HPTE *hptep)
  27. {
  28. unsigned long *word = &hptep->dw0.dword0;
  29. while (1) {
  30. if (!test_and_set_bit(HPTE_LOCK_BIT, word))
  31. break;
  32. while(test_bit(HPTE_LOCK_BIT, word))
  33. cpu_relax();
  34. }
  35. }
  36. static inline void native_unlock_hpte(HPTE *hptep)
  37. {
  38. unsigned long *word = &hptep->dw0.dword0;
  39. asm volatile("lwsync":::"memory");
  40. clear_bit(HPTE_LOCK_BIT, word);
  41. }
  42. long native_hpte_insert(unsigned long hpte_group, unsigned long va,
  43. unsigned long prpn, int secondary,
  44. unsigned long hpteflags, int bolted, int large)
  45. {
  46. unsigned long arpn = physRpn_to_absRpn(prpn);
  47. HPTE *hptep = htab_address + hpte_group;
  48. Hpte_dword0 dw0;
  49. HPTE lhpte;
  50. int i;
  51. for (i = 0; i < HPTES_PER_GROUP; i++) {
  52. dw0 = hptep->dw0.dw0;
  53. if (!dw0.v) {
  54. /* retry with lock held */
  55. native_lock_hpte(hptep);
  56. dw0 = hptep->dw0.dw0;
  57. if (!dw0.v)
  58. break;
  59. native_unlock_hpte(hptep);
  60. }
  61. hptep++;
  62. }
  63. if (i == HPTES_PER_GROUP)
  64. return -1;
  65. lhpte.dw1.dword1 = 0;
  66. lhpte.dw1.dw1.rpn = arpn;
  67. lhpte.dw1.flags.flags = hpteflags;
  68. lhpte.dw0.dword0 = 0;
  69. lhpte.dw0.dw0.avpn = va >> 23;
  70. lhpte.dw0.dw0.h = secondary;
  71. lhpte.dw0.dw0.bolted = bolted;
  72. lhpte.dw0.dw0.v = 1;
  73. if (large) {
  74. lhpte.dw0.dw0.l = 1;
  75. lhpte.dw0.dw0.avpn &= ~0x1UL;
  76. }
  77. hptep->dw1.dword1 = lhpte.dw1.dword1;
  78. /* Guarantee the second dword is visible before the valid bit */
  79. __asm__ __volatile__ ("eieio" : : : "memory");
  80. /*
  81. * Now set the first dword including the valid bit
  82. * NOTE: this also unlocks the hpte
  83. */
  84. hptep->dw0.dword0 = lhpte.dw0.dword0;
  85. __asm__ __volatile__ ("ptesync" : : : "memory");
  86. return i | (secondary << 3);
  87. }
  88. static long native_hpte_remove(unsigned long hpte_group)
  89. {
  90. HPTE *hptep;
  91. Hpte_dword0 dw0;
  92. int i;
  93. int slot_offset;
  94. /* pick a random entry to start at */
  95. slot_offset = mftb() & 0x7;
  96. for (i = 0; i < HPTES_PER_GROUP; i++) {
  97. hptep = htab_address + hpte_group + slot_offset;
  98. dw0 = hptep->dw0.dw0;
  99. if (dw0.v && !dw0.bolted) {
  100. /* retry with lock held */
  101. native_lock_hpte(hptep);
  102. dw0 = hptep->dw0.dw0;
  103. if (dw0.v && !dw0.bolted)
  104. break;
  105. native_unlock_hpte(hptep);
  106. }
  107. slot_offset++;
  108. slot_offset &= 0x7;
  109. }
  110. if (i == HPTES_PER_GROUP)
  111. return -1;
  112. /* Invalidate the hpte. NOTE: this also unlocks it */
  113. hptep->dw0.dword0 = 0;
  114. return i;
  115. }
  116. static inline void set_pp_bit(unsigned long pp, HPTE *addr)
  117. {
  118. unsigned long old;
  119. unsigned long *p = &addr->dw1.dword1;
  120. __asm__ __volatile__(
  121. "1: ldarx %0,0,%3\n\
  122. rldimi %0,%2,0,61\n\
  123. stdcx. %0,0,%3\n\
  124. bne 1b"
  125. : "=&r" (old), "=m" (*p)
  126. : "r" (pp), "r" (p), "m" (*p)
  127. : "cc");
  128. }
  129. /*
  130. * Only works on small pages. Yes its ugly to have to check each slot in
  131. * the group but we only use this during bootup.
  132. */
  133. static long native_hpte_find(unsigned long vpn)
  134. {
  135. HPTE *hptep;
  136. unsigned long hash;
  137. unsigned long i, j;
  138. long slot;
  139. Hpte_dword0 dw0;
  140. hash = hpt_hash(vpn, 0);
  141. for (j = 0; j < 2; j++) {
  142. slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
  143. for (i = 0; i < HPTES_PER_GROUP; i++) {
  144. hptep = htab_address + slot;
  145. dw0 = hptep->dw0.dw0;
  146. if ((dw0.avpn == (vpn >> 11)) && dw0.v &&
  147. (dw0.h == j)) {
  148. /* HPTE matches */
  149. if (j)
  150. slot = -slot;
  151. return slot;
  152. }
  153. ++slot;
  154. }
  155. hash = ~hash;
  156. }
  157. return -1;
  158. }
  159. static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
  160. unsigned long va, int large, int local)
  161. {
  162. HPTE *hptep = htab_address + slot;
  163. Hpte_dword0 dw0;
  164. unsigned long avpn = va >> 23;
  165. int ret = 0;
  166. if (large)
  167. avpn &= ~0x1UL;
  168. native_lock_hpte(hptep);
  169. dw0 = hptep->dw0.dw0;
  170. /* Even if we miss, we need to invalidate the TLB */
  171. if ((dw0.avpn != avpn) || !dw0.v) {
  172. native_unlock_hpte(hptep);
  173. ret = -1;
  174. } else {
  175. set_pp_bit(newpp, hptep);
  176. native_unlock_hpte(hptep);
  177. }
  178. /* Ensure it is out of the tlb too */
  179. if (cpu_has_feature(CPU_FTR_TLBIEL) && !large && local) {
  180. tlbiel(va);
  181. } else {
  182. int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE);
  183. if (lock_tlbie)
  184. spin_lock(&native_tlbie_lock);
  185. tlbie(va, large);
  186. if (lock_tlbie)
  187. spin_unlock(&native_tlbie_lock);
  188. }
  189. return ret;
  190. }
  191. /*
  192. * Update the page protection bits. Intended to be used to create
  193. * guard pages for kernel data structures on pages which are bolted
  194. * in the HPT. Assumes pages being operated on will not be stolen.
  195. * Does not work on large pages.
  196. *
  197. * No need to lock here because we should be the only user.
  198. */
  199. static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea)
  200. {
  201. unsigned long vsid, va, vpn, flags = 0;
  202. long slot;
  203. HPTE *hptep;
  204. int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE);
  205. vsid = get_kernel_vsid(ea);
  206. va = (vsid << 28) | (ea & 0x0fffffff);
  207. vpn = va >> PAGE_SHIFT;
  208. slot = native_hpte_find(vpn);
  209. if (slot == -1)
  210. panic("could not find page to bolt\n");
  211. hptep = htab_address + slot;
  212. set_pp_bit(newpp, hptep);
  213. /* Ensure it is out of the tlb too */
  214. if (lock_tlbie)
  215. spin_lock_irqsave(&native_tlbie_lock, flags);
  216. tlbie(va, 0);
  217. if (lock_tlbie)
  218. spin_unlock_irqrestore(&native_tlbie_lock, flags);
  219. }
  220. static void native_hpte_invalidate(unsigned long slot, unsigned long va,
  221. int large, int local)
  222. {
  223. HPTE *hptep = htab_address + slot;
  224. Hpte_dword0 dw0;
  225. unsigned long avpn = va >> 23;
  226. unsigned long flags;
  227. int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE);
  228. if (large)
  229. avpn &= ~0x1UL;
  230. local_irq_save(flags);
  231. native_lock_hpte(hptep);
  232. dw0 = hptep->dw0.dw0;
  233. /* Even if we miss, we need to invalidate the TLB */
  234. if ((dw0.avpn != avpn) || !dw0.v) {
  235. native_unlock_hpte(hptep);
  236. } else {
  237. /* Invalidate the hpte. NOTE: this also unlocks it */
  238. hptep->dw0.dword0 = 0;
  239. }
  240. /* Invalidate the tlb */
  241. if (cpu_has_feature(CPU_FTR_TLBIEL) && !large && local) {
  242. tlbiel(va);
  243. } else {
  244. if (lock_tlbie)
  245. spin_lock(&native_tlbie_lock);
  246. tlbie(va, large);
  247. if (lock_tlbie)
  248. spin_unlock(&native_tlbie_lock);
  249. }
  250. local_irq_restore(flags);
  251. }
  252. static void native_flush_hash_range(unsigned long context,
  253. unsigned long number, int local)
  254. {
  255. unsigned long vsid, vpn, va, hash, secondary, slot, flags, avpn;
  256. int i, j;
  257. HPTE *hptep;
  258. Hpte_dword0 dw0;
  259. struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch);
  260. /* XXX fix for large ptes */
  261. unsigned long large = 0;
  262. local_irq_save(flags);
  263. j = 0;
  264. for (i = 0; i < number; i++) {
  265. if (batch->addr[i] < KERNELBASE)
  266. vsid = get_vsid(context, batch->addr[i]);
  267. else
  268. vsid = get_kernel_vsid(batch->addr[i]);
  269. va = (vsid << 28) | (batch->addr[i] & 0x0fffffff);
  270. batch->vaddr[j] = va;
  271. if (large)
  272. vpn = va >> HPAGE_SHIFT;
  273. else
  274. vpn = va >> PAGE_SHIFT;
  275. hash = hpt_hash(vpn, large);
  276. secondary = (pte_val(batch->pte[i]) & _PAGE_SECONDARY) >> 15;
  277. if (secondary)
  278. hash = ~hash;
  279. slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
  280. slot += (pte_val(batch->pte[i]) & _PAGE_GROUP_IX) >> 12;
  281. hptep = htab_address + slot;
  282. avpn = va >> 23;
  283. if (large)
  284. avpn &= ~0x1UL;
  285. native_lock_hpte(hptep);
  286. dw0 = hptep->dw0.dw0;
  287. /* Even if we miss, we need to invalidate the TLB */
  288. if ((dw0.avpn != avpn) || !dw0.v) {
  289. native_unlock_hpte(hptep);
  290. } else {
  291. /* Invalidate the hpte. NOTE: this also unlocks it */
  292. hptep->dw0.dword0 = 0;
  293. }
  294. j++;
  295. }
  296. if (cpu_has_feature(CPU_FTR_TLBIEL) && !large && local) {
  297. asm volatile("ptesync":::"memory");
  298. for (i = 0; i < j; i++)
  299. __tlbiel(batch->vaddr[i]);
  300. asm volatile("ptesync":::"memory");
  301. } else {
  302. int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE);
  303. if (lock_tlbie)
  304. spin_lock(&native_tlbie_lock);
  305. asm volatile("ptesync":::"memory");
  306. for (i = 0; i < j; i++)
  307. __tlbie(batch->vaddr[i], 0);
  308. asm volatile("eieio; tlbsync; ptesync":::"memory");
  309. if (lock_tlbie)
  310. spin_unlock(&native_tlbie_lock);
  311. }
  312. local_irq_restore(flags);
  313. }
  314. #ifdef CONFIG_PPC_PSERIES
  315. /* Disable TLB batching on nighthawk */
  316. static inline int tlb_batching_enabled(void)
  317. {
  318. struct device_node *root = of_find_node_by_path("/");
  319. int enabled = 1;
  320. if (root) {
  321. const char *model = get_property(root, "model", NULL);
  322. if (model && !strcmp(model, "IBM,9076-N81"))
  323. enabled = 0;
  324. of_node_put(root);
  325. }
  326. return enabled;
  327. }
  328. #else
  329. static inline int tlb_batching_enabled(void)
  330. {
  331. return 1;
  332. }
  333. #endif
  334. void hpte_init_native(void)
  335. {
  336. ppc_md.hpte_invalidate = native_hpte_invalidate;
  337. ppc_md.hpte_updatepp = native_hpte_updatepp;
  338. ppc_md.hpte_updateboltedpp = native_hpte_updateboltedpp;
  339. ppc_md.hpte_insert = native_hpte_insert;
  340. ppc_md.hpte_remove = native_hpte_remove;
  341. if (tlb_batching_enabled())
  342. ppc_md.flush_hash_range = native_flush_hash_range;
  343. htab_finish_init();
  344. }