aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc')
-rw-r--r--arch/sparc/include/asm/tsb.h30
-rw-r--r--arch/sparc/mm/init_64.c28
2 files changed, 37 insertions, 21 deletions
diff --git a/arch/sparc/include/asm/tsb.h b/arch/sparc/include/asm/tsb.h
index 2e268b646348..a2f541905715 100644
--- a/arch/sparc/include/asm/tsb.h
+++ b/arch/sparc/include/asm/tsb.h
@@ -256,8 +256,6 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
256 (KERNEL_TSB_SIZE_BYTES / 16) 256 (KERNEL_TSB_SIZE_BYTES / 16)
257#define KERNEL_TSB4M_NENTRIES 4096 257#define KERNEL_TSB4M_NENTRIES 4096
258 258
259#define KTSB_PHYS_SHIFT 15
260
261 /* Do a kernel TSB lookup at tl>0 on VADDR+TAG, branch to OK_LABEL 259 /* Do a kernel TSB lookup at tl>0 on VADDR+TAG, branch to OK_LABEL
262 * on TSB hit. REG1, REG2, REG3, and REG4 are used as temporaries 260 * on TSB hit. REG1, REG2, REG3, and REG4 are used as temporaries
263 * and the found TTE will be left in REG1. REG3 and REG4 must 261 * and the found TTE will be left in REG1. REG3 and REG4 must
@@ -266,17 +264,15 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
266 * VADDR and TAG will be preserved and not clobbered by this macro. 264 * VADDR and TAG will be preserved and not clobbered by this macro.
267 */ 265 */
268#define KERN_TSB_LOOKUP_TL1(VADDR, TAG, REG1, REG2, REG3, REG4, OK_LABEL) \ 266#define KERN_TSB_LOOKUP_TL1(VADDR, TAG, REG1, REG2, REG3, REG4, OK_LABEL) \
269661: sethi %hi(swapper_tsb), REG1; \ 267661: sethi %uhi(swapper_tsb), REG1; \
270 or REG1, %lo(swapper_tsb), REG1; \ 268 sethi %hi(swapper_tsb), REG2; \
269 or REG1, %ulo(swapper_tsb), REG1; \
270 or REG2, %lo(swapper_tsb), REG2; \
271 .section .swapper_tsb_phys_patch, "ax"; \ 271 .section .swapper_tsb_phys_patch, "ax"; \
272 .word 661b; \ 272 .word 661b; \
273 .previous; \ 273 .previous; \
274661: nop; \ 274 sllx REG1, 32, REG1; \
275 .section .tsb_ldquad_phys_patch, "ax"; \ 275 or REG1, REG2, REG1; \
276 .word 661b; \
277 sllx REG1, KTSB_PHYS_SHIFT, REG1; \
278 sllx REG1, KTSB_PHYS_SHIFT, REG1; \
279 .previous; \
280 srlx VADDR, PAGE_SHIFT, REG2; \ 276 srlx VADDR, PAGE_SHIFT, REG2; \
281 and REG2, (KERNEL_TSB_NENTRIES - 1), REG2; \ 277 and REG2, (KERNEL_TSB_NENTRIES - 1), REG2; \
282 sllx REG2, 4, REG2; \ 278 sllx REG2, 4, REG2; \
@@ -291,17 +287,15 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
291 * we can make use of that for the index computation. 287 * we can make use of that for the index computation.
292 */ 288 */
293#define KERN_TSB4M_LOOKUP_TL1(TAG, REG1, REG2, REG3, REG4, OK_LABEL) \ 289#define KERN_TSB4M_LOOKUP_TL1(TAG, REG1, REG2, REG3, REG4, OK_LABEL) \
294661: sethi %hi(swapper_4m_tsb), REG1; \ 290661: sethi %uhi(swapper_4m_tsb), REG1; \
295 or REG1, %lo(swapper_4m_tsb), REG1; \ 291 sethi %hi(swapper_4m_tsb), REG2; \
292 or REG1, %ulo(swapper_4m_tsb), REG1; \
293 or REG2, %lo(swapper_4m_tsb), REG2; \
296 .section .swapper_4m_tsb_phys_patch, "ax"; \ 294 .section .swapper_4m_tsb_phys_patch, "ax"; \
297 .word 661b; \ 295 .word 661b; \
298 .previous; \ 296 .previous; \
299661: nop; \ 297 sllx REG1, 32, REG1; \
300 .section .tsb_ldquad_phys_patch, "ax"; \ 298 or REG1, REG2, REG1; \
301 .word 661b; \
302 sllx REG1, KTSB_PHYS_SHIFT, REG1; \
303 sllx REG1, KTSB_PHYS_SHIFT, REG1; \
304 .previous; \
305 and TAG, (KERNEL_TSB4M_NENTRIES - 1), REG2; \ 299 and TAG, (KERNEL_TSB4M_NENTRIES - 1), REG2; \
306 sllx REG2, 4, REG2; \ 300 sllx REG2, 4, REG2; \
307 add REG1, REG2, REG2; \ 301 add REG1, REG2, REG2; \
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index c241c5723373..35fcc9cb960d 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -1733,19 +1733,41 @@ static void __init tsb_phys_patch(void)
1733static struct hv_tsb_descr ktsb_descr[NUM_KTSB_DESCR]; 1733static struct hv_tsb_descr ktsb_descr[NUM_KTSB_DESCR];
1734extern struct tsb swapper_tsb[KERNEL_TSB_NENTRIES]; 1734extern struct tsb swapper_tsb[KERNEL_TSB_NENTRIES];
1735 1735
1736/* The swapper TSBs are loaded with a base sequence of:
1737 *
1738 * sethi %uhi(SYMBOL), REG1
1739 * sethi %hi(SYMBOL), REG2
1740 * or REG1, %ulo(SYMBOL), REG1
1741 * or REG2, %lo(SYMBOL), REG2
1742 * sllx REG1, 32, REG1
1743 * or REG1, REG2, REG1
1744 *
1745 * When we use physical addressing for the TSB accesses, we patch the
1746 * first four instructions in the above sequence.
1747 */
1748
1736static void patch_one_ktsb_phys(unsigned int *start, unsigned int *end, unsigned long pa) 1749static void patch_one_ktsb_phys(unsigned int *start, unsigned int *end, unsigned long pa)
1737{ 1750{
1738 pa >>= KTSB_PHYS_SHIFT; 1751 unsigned long high_bits, low_bits;
1752
1753 high_bits = (pa >> 32) & 0xffffffff;
1754 low_bits = (pa >> 0) & 0xffffffff;
1739 1755
1740 while (start < end) { 1756 while (start < end) {
1741 unsigned int *ia = (unsigned int *)(unsigned long)*start; 1757 unsigned int *ia = (unsigned int *)(unsigned long)*start;
1742 1758
1743 ia[0] = (ia[0] & ~0x3fffff) | (pa >> 10); 1759 ia[0] = (ia[0] & ~0x3fffff) | (high_bits >> 10);
1744 __asm__ __volatile__("flush %0" : : "r" (ia)); 1760 __asm__ __volatile__("flush %0" : : "r" (ia));
1745 1761
1746 ia[1] = (ia[1] & ~0x3ff) | (pa & 0x3ff); 1762 ia[1] = (ia[1] & ~0x3fffff) | (low_bits >> 10);
1747 __asm__ __volatile__("flush %0" : : "r" (ia + 1)); 1763 __asm__ __volatile__("flush %0" : : "r" (ia + 1));
1748 1764
1765 ia[2] = (ia[2] & ~0x1fff) | (high_bits & 0x3ff);
1766 __asm__ __volatile__("flush %0" : : "r" (ia + 2));
1767
1768 ia[3] = (ia[3] & ~0x1fff) | (low_bits & 0x3ff);
1769 __asm__ __volatile__("flush %0" : : "r" (ia + 3));
1770
1749 start++; 1771 start++;
1750 } 1772 }
1751} 1773}