Commit ff5b56f8 authored by David S. Miller's avatar David S. Miller Committed by Greg Kroah-Hartman

sparc64: Adjust KTSB assembler to support larger physical addresses.

[ Upstream commit 8c82dc0e ]

As currently coded the KTSB accesses in the kernel only support up to
47 bits of physical addressing.

Adjust the instruction and patching sequence in order to support
arbitrary 64 bits addresses.
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Acked-by: default avatarBob Picco <bob.picco@oracle.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent e4d4fab3
...@@ -256,8 +256,6 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end; ...@@ -256,8 +256,6 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
(KERNEL_TSB_SIZE_BYTES / 16) (KERNEL_TSB_SIZE_BYTES / 16)
#define KERNEL_TSB4M_NENTRIES 4096 #define KERNEL_TSB4M_NENTRIES 4096
#define KTSB_PHYS_SHIFT 15
/* Do a kernel TSB lookup at tl>0 on VADDR+TAG, branch to OK_LABEL /* Do a kernel TSB lookup at tl>0 on VADDR+TAG, branch to OK_LABEL
* on TSB hit. REG1, REG2, REG3, and REG4 are used as temporaries * on TSB hit. REG1, REG2, REG3, and REG4 are used as temporaries
* and the found TTE will be left in REG1. REG3 and REG4 must * 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,17 +264,15 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
* VADDR and TAG will be preserved and not clobbered by this macro. * VADDR and TAG will be preserved and not clobbered by this macro.
*/ */
#define KERN_TSB_LOOKUP_TL1(VADDR, TAG, REG1, REG2, REG3, REG4, OK_LABEL) \ #define KERN_TSB_LOOKUP_TL1(VADDR, TAG, REG1, REG2, REG3, REG4, OK_LABEL) \
661: sethi %hi(swapper_tsb), REG1; \ 661: sethi %uhi(swapper_tsb), REG1; \
or REG1, %lo(swapper_tsb), REG1; \ sethi %hi(swapper_tsb), REG2; \
or REG1, %ulo(swapper_tsb), REG1; \
or REG2, %lo(swapper_tsb), REG2; \
.section .swapper_tsb_phys_patch, "ax"; \ .section .swapper_tsb_phys_patch, "ax"; \
.word 661b; \ .word 661b; \
.previous; \ .previous; \
661: nop; \ sllx REG1, 32, REG1; \
.section .tsb_ldquad_phys_patch, "ax"; \ or REG1, REG2, REG1; \
.word 661b; \
sllx REG1, KTSB_PHYS_SHIFT, REG1; \
sllx REG1, KTSB_PHYS_SHIFT, REG1; \
.previous; \
srlx VADDR, PAGE_SHIFT, REG2; \ srlx VADDR, PAGE_SHIFT, REG2; \
and REG2, (KERNEL_TSB_NENTRIES - 1), REG2; \ and REG2, (KERNEL_TSB_NENTRIES - 1), REG2; \
sllx REG2, 4, REG2; \ sllx REG2, 4, REG2; \
...@@ -291,17 +287,15 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end; ...@@ -291,17 +287,15 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
* we can make use of that for the index computation. * we can make use of that for the index computation.
*/ */
#define KERN_TSB4M_LOOKUP_TL1(TAG, REG1, REG2, REG3, REG4, OK_LABEL) \ #define KERN_TSB4M_LOOKUP_TL1(TAG, REG1, REG2, REG3, REG4, OK_LABEL) \
661: sethi %hi(swapper_4m_tsb), REG1; \ 661: sethi %uhi(swapper_4m_tsb), REG1; \
or REG1, %lo(swapper_4m_tsb), REG1; \ sethi %hi(swapper_4m_tsb), REG2; \
or REG1, %ulo(swapper_4m_tsb), REG1; \
or REG2, %lo(swapper_4m_tsb), REG2; \
.section .swapper_4m_tsb_phys_patch, "ax"; \ .section .swapper_4m_tsb_phys_patch, "ax"; \
.word 661b; \ .word 661b; \
.previous; \ .previous; \
661: nop; \ sllx REG1, 32, REG1; \
.section .tsb_ldquad_phys_patch, "ax"; \ or REG1, REG2, REG1; \
.word 661b; \
sllx REG1, KTSB_PHYS_SHIFT, REG1; \
sllx REG1, KTSB_PHYS_SHIFT, REG1; \
.previous; \
and TAG, (KERNEL_TSB4M_NENTRIES - 1), REG2; \ and TAG, (KERNEL_TSB4M_NENTRIES - 1), REG2; \
sllx REG2, 4, REG2; \ sllx REG2, 4, REG2; \
add REG1, REG2, REG2; \ add REG1, REG2, REG2; \
......
...@@ -1732,19 +1732,41 @@ static void __init tsb_phys_patch(void) ...@@ -1732,19 +1732,41 @@ static void __init tsb_phys_patch(void)
static struct hv_tsb_descr ktsb_descr[NUM_KTSB_DESCR]; static struct hv_tsb_descr ktsb_descr[NUM_KTSB_DESCR];
extern struct tsb swapper_tsb[KERNEL_TSB_NENTRIES]; extern struct tsb swapper_tsb[KERNEL_TSB_NENTRIES];
/* The swapper TSBs are loaded with a base sequence of:
*
* sethi %uhi(SYMBOL), REG1
* sethi %hi(SYMBOL), REG2
* or REG1, %ulo(SYMBOL), REG1
* or REG2, %lo(SYMBOL), REG2
* sllx REG1, 32, REG1
* or REG1, REG2, REG1
*
* When we use physical addressing for the TSB accesses, we patch the
* first four instructions in the above sequence.
*/
static void patch_one_ktsb_phys(unsigned int *start, unsigned int *end, unsigned long pa) static void patch_one_ktsb_phys(unsigned int *start, unsigned int *end, unsigned long pa)
{ {
pa >>= KTSB_PHYS_SHIFT; unsigned long high_bits, low_bits;
high_bits = (pa >> 32) & 0xffffffff;
low_bits = (pa >> 0) & 0xffffffff;
while (start < end) { while (start < end) {
unsigned int *ia = (unsigned int *)(unsigned long)*start; unsigned int *ia = (unsigned int *)(unsigned long)*start;
ia[0] = (ia[0] & ~0x3fffff) | (pa >> 10); ia[0] = (ia[0] & ~0x3fffff) | (high_bits >> 10);
__asm__ __volatile__("flush %0" : : "r" (ia)); __asm__ __volatile__("flush %0" : : "r" (ia));
ia[1] = (ia[1] & ~0x3ff) | (pa & 0x3ff); ia[1] = (ia[1] & ~0x3fffff) | (low_bits >> 10);
__asm__ __volatile__("flush %0" : : "r" (ia + 1)); __asm__ __volatile__("flush %0" : : "r" (ia + 1));
ia[2] = (ia[2] & ~0x1fff) | (high_bits & 0x3ff);
__asm__ __volatile__("flush %0" : : "r" (ia + 2));
ia[3] = (ia[3] & ~0x1fff) | (low_bits & 0x3ff);
__asm__ __volatile__("flush %0" : : "r" (ia + 3));
start++; start++;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment