diff options
Diffstat (limited to 'arch/sparc')
-rw-r--r-- | arch/sparc/include/asm/tsb.h | 30 | ||||
-rw-r--r-- | arch/sparc/mm/init_64.c | 28 |
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) \ |
269 | 661: sethi %hi(swapper_tsb), REG1; \ | 267 | 661: 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; \ |
274 | 661: 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) \ |
294 | 661: sethi %hi(swapper_4m_tsb), REG1; \ | 290 | 661: 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; \ |
299 | 661: 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) | |||
1733 | static struct hv_tsb_descr ktsb_descr[NUM_KTSB_DESCR]; | 1733 | static struct hv_tsb_descr ktsb_descr[NUM_KTSB_DESCR]; |
1734 | extern struct tsb swapper_tsb[KERNEL_TSB_NENTRIES]; | 1734 | extern 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 | |||
1736 | static void patch_one_ktsb_phys(unsigned int *start, unsigned int *end, unsigned long pa) | 1749 | static 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 | } |