aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>2013-03-12 23:34:54 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2013-03-16 21:39:06 -0400
commitc60ac5693c47df32a2b4b18af97fca5635def015 (patch)
tree34da014c89f9a941f5c901fc06f4c3f5bca6ad43 /arch/powerpc
parente39d1a471484662620651cd9520250d33843f235 (diff)
powerpc: Update kernel VSID range
This patch change the kernel VSID range so that we limit VSID_BITS to 37. This enables us to support 64TB with 65 bit VA (37+28). Without this patch we have boot hangs on platforms that only support 65 bit VA. With this patch we now have proto vsid generated as below: We first generate a 37-bit "proto-VSID". Proto-VSIDs are generated from mmu context id and effective segment id of the address. For user processes max context id is limited to ((1ul << 19) - 5) for kernel space, we use the top 4 context ids to map address as below 0x7fffc - [ 0xc000000000000000 - 0xc0003fffffffffff ] 0x7fffd - [ 0xd000000000000000 - 0xd0003fffffffffff ] 0x7fffe - [ 0xe000000000000000 - 0xe0003fffffffffff ] 0x7ffff - [ 0xf000000000000000 - 0xf0003fffffffffff ] Acked-by: Paul Mackerras <paulus@samba.org> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> Tested-by: Geoff Levand <geoff@infradead.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> CC: <stable@vger.kernel.org> [v3.8]
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/include/asm/mmu-hash64.h115
-rw-r--r--arch/powerpc/kernel/exceptions-64s.S34
-rw-r--r--arch/powerpc/mm/hash_utils_64.c20
-rw-r--r--arch/powerpc/mm/mmu_context_hash64.c11
-rw-r--r--arch/powerpc/mm/slb_low.S50
-rw-r--r--arch/powerpc/mm/tlb_hash64.c2
6 files changed, 126 insertions, 106 deletions
diff --git a/arch/powerpc/include/asm/mmu-hash64.h b/arch/powerpc/include/asm/mmu-hash64.h
index 5f8c2bd58818..a32461f9d825 100644
--- a/arch/powerpc/include/asm/mmu-hash64.h
+++ b/arch/powerpc/include/asm/mmu-hash64.h
@@ -343,17 +343,16 @@ extern void slb_set_size(u16 size);
343/* 343/*
344 * VSID allocation (256MB segment) 344 * VSID allocation (256MB segment)
345 * 345 *
346 * We first generate a 38-bit "proto-VSID". For kernel addresses this 346 * We first generate a 37-bit "proto-VSID". Proto-VSIDs are generated
347 * is equal to the ESID | 1 << 37, for user addresses it is: 347 * from mmu context id and effective segment id of the address.
348 * (context << USER_ESID_BITS) | (esid & ((1U << USER_ESID_BITS) - 1)
349 * 348 *
350 * This splits the proto-VSID into the below range 349 * For user processes max context id is limited to ((1ul << 19) - 5)
351 * 0 - (2^(CONTEXT_BITS + USER_ESID_BITS) - 1) : User proto-VSID range 350 * for kernel space, we use the top 4 context ids to map address as below
352 * 2^(CONTEXT_BITS + USER_ESID_BITS) - 2^(VSID_BITS) : Kernel proto-VSID range 351 * NOTE: each context only support 64TB now.
353 * 352 * 0x7fffc - [ 0xc000000000000000 - 0xc0003fffffffffff ]
354 * We also have CONTEXT_BITS + USER_ESID_BITS = VSID_BITS - 1 353 * 0x7fffd - [ 0xd000000000000000 - 0xd0003fffffffffff ]
355 * That is, we assign half of the space to user processes and half 354 * 0x7fffe - [ 0xe000000000000000 - 0xe0003fffffffffff ]
356 * to the kernel. 355 * 0x7ffff - [ 0xf000000000000000 - 0xf0003fffffffffff ]
357 * 356 *
358 * The proto-VSIDs are then scrambled into real VSIDs with the 357 * The proto-VSIDs are then scrambled into real VSIDs with the
359 * multiplicative hash: 358 * multiplicative hash:
@@ -363,22 +362,19 @@ extern void slb_set_size(u16 size);
363 * VSID_MULTIPLIER is prime, so in particular it is 362 * VSID_MULTIPLIER is prime, so in particular it is
364 * co-prime to VSID_MODULUS, making this a 1:1 scrambling function. 363 * co-prime to VSID_MODULUS, making this a 1:1 scrambling function.
365 * Because the modulus is 2^n-1 we can compute it efficiently without 364 * Because the modulus is 2^n-1 we can compute it efficiently without
366 * a divide or extra multiply (see below). 365 * a divide or extra multiply (see below). The scramble function gives
367 * 366 * robust scattering in the hash table (at least based on some initial
368 * This scheme has several advantages over older methods: 367 * results).
369 * 368 *
370 * - We have VSIDs allocated for every kernel address 369 * We also consider VSID 0 special. We use VSID 0 for slb entries mapping
371 * (i.e. everything above 0xC000000000000000), except the very top 370 * bad address. This enables us to consolidate bad address handling in
372 * segment, which simplifies several things. 371 * hash_page.
373 * 372 *
374 * - We allow for USER_ESID_BITS significant bits of ESID and 373 * We also need to avoid the last segment of the last context, because that
375 * CONTEXT_BITS bits of context for user addresses. 374 * would give a protovsid of 0x1fffffffff. That will result in a VSID 0
376 * i.e. 64T (46 bits) of address space for up to half a million contexts. 375 * because of the modulo operation in vsid scramble. But the vmemmap
377 * 376 * (which is what uses region 0xf) will never be close to 64TB in size
378 * - The scramble function gives robust scattering in the hash 377 * (it's 56 bytes per page of system memory).
379 * table (at least based on some initial results). The previous
380 * method was more susceptible to pathological cases giving excessive
381 * hash collisions.
382 */ 378 */
383 379
384#define CONTEXT_BITS 19 380#define CONTEXT_BITS 19
@@ -386,15 +382,25 @@ extern void slb_set_size(u16 size);
386#define USER_ESID_BITS_1T 6 382#define USER_ESID_BITS_1T 6
387 383
388/* 384/*
385 * 256MB segment
386 * The proto-VSID space has 2^(CONTEX_BITS + USER_ESID_BITS) - 1 segments
387 * available for user + kernel mapping. The top 4 contexts are used for
388 * kernel mapping. Each segment contains 2^28 bytes. Each
389 * context maps 2^46 bytes (64TB) so we can support 2^19-1 contexts
390 * (19 == 37 + 28 - 46).
391 */
392#define MAX_USER_CONTEXT ((ASM_CONST(1) << CONTEXT_BITS) - 5)
393
394/*
389 * This should be computed such that protovosid * vsid_mulitplier 395 * This should be computed such that protovosid * vsid_mulitplier
390 * doesn't overflow 64 bits. It should also be co-prime to vsid_modulus 396 * doesn't overflow 64 bits. It should also be co-prime to vsid_modulus
391 */ 397 */
392#define VSID_MULTIPLIER_256M ASM_CONST(12538073) /* 24-bit prime */ 398#define VSID_MULTIPLIER_256M ASM_CONST(12538073) /* 24-bit prime */
393#define VSID_BITS_256M (CONTEXT_BITS + USER_ESID_BITS + 1) 399#define VSID_BITS_256M (CONTEXT_BITS + USER_ESID_BITS)
394#define VSID_MODULUS_256M ((1UL<<VSID_BITS_256M)-1) 400#define VSID_MODULUS_256M ((1UL<<VSID_BITS_256M)-1)
395 401
396#define VSID_MULTIPLIER_1T ASM_CONST(12538073) /* 24-bit prime */ 402#define VSID_MULTIPLIER_1T ASM_CONST(12538073) /* 24-bit prime */
397#define VSID_BITS_1T (CONTEXT_BITS + USER_ESID_BITS_1T + 1) 403#define VSID_BITS_1T (CONTEXT_BITS + USER_ESID_BITS_1T)
398#define VSID_MODULUS_1T ((1UL<<VSID_BITS_1T)-1) 404#define VSID_MODULUS_1T ((1UL<<VSID_BITS_1T)-1)
399 405
400 406
@@ -422,7 +428,8 @@ extern void slb_set_size(u16 size);
422 srdi rx,rt,VSID_BITS_##size; \ 428 srdi rx,rt,VSID_BITS_##size; \
423 clrldi rt,rt,(64-VSID_BITS_##size); \ 429 clrldi rt,rt,(64-VSID_BITS_##size); \
424 add rt,rt,rx; /* add high and low bits */ \ 430 add rt,rt,rx; /* add high and low bits */ \
425 /* Now, r3 == VSID (mod 2^36-1), and lies between 0 and \ 431 /* NOTE: explanation based on VSID_BITS_##size = 36 \
432 * Now, r3 == VSID (mod 2^36-1), and lies between 0 and \
426 * 2^36-1+2^28-1. That in particular means that if r3 >= \ 433 * 2^36-1+2^28-1. That in particular means that if r3 >= \
427 * 2^36-1, then r3+1 has the 2^36 bit set. So, if r3+1 has \ 434 * 2^36-1, then r3+1 has the 2^36 bit set. So, if r3+1 has \
428 * the bit clear, r3 already has the answer we want, if it \ 435 * the bit clear, r3 already has the answer we want, if it \
@@ -514,34 +521,6 @@ typedef struct {
514 }) 521 })
515#endif /* 1 */ 522#endif /* 1 */
516 523
517/*
518 * This is only valid for addresses >= PAGE_OFFSET
519 * The proto-VSID space is divided into two class
520 * User: 0 to 2^(CONTEXT_BITS + USER_ESID_BITS) -1
521 * kernel: 2^(CONTEXT_BITS + USER_ESID_BITS) to 2^(VSID_BITS) - 1
522 *
523 * With KERNEL_START at 0xc000000000000000, the proto vsid for
524 * the kernel ends up with 0xc00000000 (36 bits). With 64TB
525 * support we need to have kernel proto-VSID in the
526 * [2^37 to 2^38 - 1] range due to the increased USER_ESID_BITS.
527 */
528static inline unsigned long get_kernel_vsid(unsigned long ea, int ssize)
529{
530 unsigned long proto_vsid;
531 /*
532 * We need to make sure proto_vsid for the kernel is
533 * >= 2^(CONTEXT_BITS + USER_ESID_BITS[_1T])
534 */
535 if (ssize == MMU_SEGSIZE_256M) {
536 proto_vsid = ea >> SID_SHIFT;
537 proto_vsid |= (1UL << (CONTEXT_BITS + USER_ESID_BITS));
538 return vsid_scramble(proto_vsid, 256M);
539 }
540 proto_vsid = ea >> SID_SHIFT_1T;
541 proto_vsid |= (1UL << (CONTEXT_BITS + USER_ESID_BITS_1T));
542 return vsid_scramble(proto_vsid, 1T);
543}
544
545/* Returns the segment size indicator for a user address */ 524/* Returns the segment size indicator for a user address */
546static inline int user_segment_size(unsigned long addr) 525static inline int user_segment_size(unsigned long addr)
547{ 526{
@@ -551,10 +530,15 @@ static inline int user_segment_size(unsigned long addr)
551 return MMU_SEGSIZE_256M; 530 return MMU_SEGSIZE_256M;
552} 531}
553 532
554/* This is only valid for user addresses (which are below 2^44) */
555static inline unsigned long get_vsid(unsigned long context, unsigned long ea, 533static inline unsigned long get_vsid(unsigned long context, unsigned long ea,
556 int ssize) 534 int ssize)
557{ 535{
536 /*
537 * Bad address. We return VSID 0 for that
538 */
539 if ((ea & ~REGION_MASK) >= PGTABLE_RANGE)
540 return 0;
541
558 if (ssize == MMU_SEGSIZE_256M) 542 if (ssize == MMU_SEGSIZE_256M)
559 return vsid_scramble((context << USER_ESID_BITS) 543 return vsid_scramble((context << USER_ESID_BITS)
560 | (ea >> SID_SHIFT), 256M); 544 | (ea >> SID_SHIFT), 256M);
@@ -562,6 +546,25 @@ static inline unsigned long get_vsid(unsigned long context, unsigned long ea,
562 | (ea >> SID_SHIFT_1T), 1T); 546 | (ea >> SID_SHIFT_1T), 1T);
563} 547}
564 548
549/*
550 * This is only valid for addresses >= PAGE_OFFSET
551 *
552 * For kernel space, we use the top 4 context ids to map address as below
553 * 0x7fffc - [ 0xc000000000000000 - 0xc0003fffffffffff ]
554 * 0x7fffd - [ 0xd000000000000000 - 0xd0003fffffffffff ]
555 * 0x7fffe - [ 0xe000000000000000 - 0xe0003fffffffffff ]
556 * 0x7ffff - [ 0xf000000000000000 - 0xf0003fffffffffff ]
557 */
558static inline unsigned long get_kernel_vsid(unsigned long ea, int ssize)
559{
560 unsigned long context;
561
562 /*
563 * kernel take the top 4 context from the available range
564 */
565 context = (MAX_USER_CONTEXT) + ((ea >> 60) - 0xc) + 1;
566 return get_vsid(context, ea, ssize);
567}
565#endif /* __ASSEMBLY__ */ 568#endif /* __ASSEMBLY__ */
566 569
567#endif /* _ASM_POWERPC_MMU_HASH64_H_ */ 570#endif /* _ASM_POWERPC_MMU_HASH64_H_ */
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 87ef8f5ee5bc..b112359ea7a8 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -1452,20 +1452,36 @@ do_ste_alloc:
1452_GLOBAL(do_stab_bolted) 1452_GLOBAL(do_stab_bolted)
1453 stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */ 1453 stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */
1454 std r11,PACA_EXSLB+EX_SRR0(r13) /* save SRR0 in exc. frame */ 1454 std r11,PACA_EXSLB+EX_SRR0(r13) /* save SRR0 in exc. frame */
1455 mfspr r11,SPRN_DAR /* ea */
1455 1456
1457 /*
1458 * check for bad kernel/user address
1459 * (ea & ~REGION_MASK) >= PGTABLE_RANGE
1460 */
1461 rldicr. r9,r11,4,(63 - 46 - 4)
1462 li r9,0 /* VSID = 0 for bad address */
1463 bne- 0f
1464
1465 /*
1466 * Calculate VSID:
1467 * This is the kernel vsid, we take the top for context from
1468 * the range. context = (MAX_USER_CONTEXT) + ((ea >> 60) - 0xc) + 1
1469 * Here we know that (ea >> 60) == 0xc
1470 */
1471 lis r9,(MAX_USER_CONTEXT + 1)@ha
1472 addi r9,r9,(MAX_USER_CONTEXT + 1)@l
1473
1474 srdi r10,r11,SID_SHIFT
1475 rldimi r10,r9,USER_ESID_BITS,0 /* proto vsid */
1476 ASM_VSID_SCRAMBLE(r10, r9, 256M)
1477 rldic r9,r10,12,16 /* r9 = vsid << 12 */
1478
14790:
1456 /* Hash to the primary group */ 1480 /* Hash to the primary group */
1457 ld r10,PACASTABVIRT(r13) 1481 ld r10,PACASTABVIRT(r13)
1458 mfspr r11,SPRN_DAR 1482 srdi r11,r11,SID_SHIFT
1459 srdi r11,r11,28
1460 rldimi r10,r11,7,52 /* r10 = first ste of the group */ 1483 rldimi r10,r11,7,52 /* r10 = first ste of the group */
1461 1484
1462 /* Calculate VSID */
1463 /* This is a kernel address, so protovsid = ESID | 1 << 37 */
1464 li r9,0x1
1465 rldimi r11,r9,(CONTEXT_BITS + USER_ESID_BITS),0
1466 ASM_VSID_SCRAMBLE(r11, r9, 256M)
1467 rldic r9,r11,12,16 /* r9 = vsid << 12 */
1468
1469 /* Search the primary group for a free entry */ 1485 /* Search the primary group for a free entry */
14701: ld r11,0(r10) /* Test valid bit of the current ste */ 14861: ld r11,0(r10) /* Test valid bit of the current ste */
1471 andi. r11,r11,0x80 1487 andi. r11,r11,0x80
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index 6ec6c1997b3a..f410c3e12c1e 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -195,6 +195,11 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
195 unsigned long vpn = hpt_vpn(vaddr, vsid, ssize); 195 unsigned long vpn = hpt_vpn(vaddr, vsid, ssize);
196 unsigned long tprot = prot; 196 unsigned long tprot = prot;
197 197
198 /*
199 * If we hit a bad address return error.
200 */
201 if (!vsid)
202 return -1;
198 /* Make kernel text executable */ 203 /* Make kernel text executable */
199 if (overlaps_kernel_text(vaddr, vaddr + step)) 204 if (overlaps_kernel_text(vaddr, vaddr + step))
200 tprot &= ~HPTE_R_N; 205 tprot &= ~HPTE_R_N;
@@ -924,11 +929,6 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
924 DBG_LOW("hash_page(ea=%016lx, access=%lx, trap=%lx\n", 929 DBG_LOW("hash_page(ea=%016lx, access=%lx, trap=%lx\n",
925 ea, access, trap); 930 ea, access, trap);
926 931
927 if ((ea & ~REGION_MASK) >= PGTABLE_RANGE) {
928 DBG_LOW(" out of pgtable range !\n");
929 return 1;
930 }
931
932 /* Get region & vsid */ 932 /* Get region & vsid */
933 switch (REGION_ID(ea)) { 933 switch (REGION_ID(ea)) {
934 case USER_REGION_ID: 934 case USER_REGION_ID:
@@ -959,6 +959,11 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
959 } 959 }
960 DBG_LOW(" mm=%p, mm->pgdir=%p, vsid=%016lx\n", mm, mm->pgd, vsid); 960 DBG_LOW(" mm=%p, mm->pgdir=%p, vsid=%016lx\n", mm, mm->pgd, vsid);
961 961
962 /* Bad address. */
963 if (!vsid) {
964 DBG_LOW("Bad address!\n");
965 return 1;
966 }
962 /* Get pgdir */ 967 /* Get pgdir */
963 pgdir = mm->pgd; 968 pgdir = mm->pgd;
964 if (pgdir == NULL) 969 if (pgdir == NULL)
@@ -1128,6 +1133,8 @@ void hash_preload(struct mm_struct *mm, unsigned long ea,
1128 /* Get VSID */ 1133 /* Get VSID */
1129 ssize = user_segment_size(ea); 1134 ssize = user_segment_size(ea);
1130 vsid = get_vsid(mm->context.id, ea, ssize); 1135 vsid = get_vsid(mm->context.id, ea, ssize);
1136 if (!vsid)
1137 return;
1131 1138
1132 /* Hash doesn't like irqs */ 1139 /* Hash doesn't like irqs */
1133 local_irq_save(flags); 1140 local_irq_save(flags);
@@ -1235,6 +1242,9 @@ static void kernel_map_linear_page(unsigned long vaddr, unsigned long lmi)
1235 hash = hpt_hash(vpn, PAGE_SHIFT, mmu_kernel_ssize); 1242 hash = hpt_hash(vpn, PAGE_SHIFT, mmu_kernel_ssize);
1236 hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP); 1243 hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP);
1237 1244
1245 /* Don't create HPTE entries for bad address */
1246 if (!vsid)
1247 return;
1238 ret = ppc_md.hpte_insert(hpteg, vpn, __pa(vaddr), 1248 ret = ppc_md.hpte_insert(hpteg, vpn, __pa(vaddr),
1239 mode, HPTE_V_BOLTED, 1249 mode, HPTE_V_BOLTED,
1240 mmu_linear_psize, mmu_kernel_ssize); 1250 mmu_linear_psize, mmu_kernel_ssize);
diff --git a/arch/powerpc/mm/mmu_context_hash64.c b/arch/powerpc/mm/mmu_context_hash64.c
index 40bc5b0ace54..d1d1b92c5b99 100644
--- a/arch/powerpc/mm/mmu_context_hash64.c
+++ b/arch/powerpc/mm/mmu_context_hash64.c
@@ -29,15 +29,6 @@
29static DEFINE_SPINLOCK(mmu_context_lock); 29static DEFINE_SPINLOCK(mmu_context_lock);
30static DEFINE_IDA(mmu_context_ida); 30static DEFINE_IDA(mmu_context_ida);
31 31
32/*
33 * 256MB segment
34 * The proto-VSID space has 2^(CONTEX_BITS + USER_ESID_BITS) - 1 segments
35 * available for user mappings. Each segment contains 2^28 bytes. Each
36 * context maps 2^46 bytes (64TB) so we can support 2^19-1 contexts
37 * (19 == 37 + 28 - 46).
38 */
39#define MAX_CONTEXT ((1UL << CONTEXT_BITS) - 1)
40
41int __init_new_context(void) 32int __init_new_context(void)
42{ 33{
43 int index; 34 int index;
@@ -56,7 +47,7 @@ again:
56 else if (err) 47 else if (err)
57 return err; 48 return err;
58 49
59 if (index > MAX_CONTEXT) { 50 if (index > MAX_USER_CONTEXT) {
60 spin_lock(&mmu_context_lock); 51 spin_lock(&mmu_context_lock);
61 ida_remove(&mmu_context_ida, index); 52 ida_remove(&mmu_context_ida, index);
62 spin_unlock(&mmu_context_lock); 53 spin_unlock(&mmu_context_lock);
diff --git a/arch/powerpc/mm/slb_low.S b/arch/powerpc/mm/slb_low.S
index 1a16ca227757..77aafaa1ab09 100644
--- a/arch/powerpc/mm/slb_low.S
+++ b/arch/powerpc/mm/slb_low.S
@@ -31,10 +31,15 @@
31 * No other registers are examined or changed. 31 * No other registers are examined or changed.
32 */ 32 */
33_GLOBAL(slb_allocate_realmode) 33_GLOBAL(slb_allocate_realmode)
34 /* r3 = faulting address */ 34 /*
35 * check for bad kernel/user address
36 * (ea & ~REGION_MASK) >= PGTABLE_RANGE
37 */
38 rldicr. r9,r3,4,(63 - 46 - 4)
39 bne- 8f
35 40
36 srdi r9,r3,60 /* get region */ 41 srdi r9,r3,60 /* get region */
37 srdi r10,r3,28 /* get esid */ 42 srdi r10,r3,SID_SHIFT /* get esid */
38 cmpldi cr7,r9,0xc /* cmp PAGE_OFFSET for later use */ 43 cmpldi cr7,r9,0xc /* cmp PAGE_OFFSET for later use */
39 44
40 /* r3 = address, r10 = esid, cr7 = <> PAGE_OFFSET */ 45 /* r3 = address, r10 = esid, cr7 = <> PAGE_OFFSET */
@@ -56,12 +61,14 @@ _GLOBAL(slb_allocate_realmode)
56 */ 61 */
57_GLOBAL(slb_miss_kernel_load_linear) 62_GLOBAL(slb_miss_kernel_load_linear)
58 li r11,0 63 li r11,0
59 li r9,0x1
60 /* 64 /*
61 * for 1T we shift 12 bits more. slb_finish_load_1T will do 65 * context = (MAX_USER_CONTEXT) + ((ea >> 60) - 0xc) + 1
62 * the necessary adjustment 66 * r9 = region id.
63 */ 67 */
64 rldimi r10,r9,(CONTEXT_BITS + USER_ESID_BITS),0 68 addis r9,r9,(MAX_USER_CONTEXT - 0xc + 1)@ha
69 addi r9,r9,(MAX_USER_CONTEXT - 0xc + 1)@l
70
71
65BEGIN_FTR_SECTION 72BEGIN_FTR_SECTION
66 b slb_finish_load 73 b slb_finish_load
67END_MMU_FTR_SECTION_IFCLR(MMU_FTR_1T_SEGMENT) 74END_MMU_FTR_SECTION_IFCLR(MMU_FTR_1T_SEGMENT)
@@ -91,24 +98,19 @@ _GLOBAL(slb_miss_kernel_load_vmemmap)
91 _GLOBAL(slb_miss_kernel_load_io) 98 _GLOBAL(slb_miss_kernel_load_io)
92 li r11,0 99 li r11,0
936: 1006:
94 li r9,0x1
95 /* 101 /*
96 * for 1T we shift 12 bits more. slb_finish_load_1T will do 102 * context = (MAX_USER_CONTEXT) + ((ea >> 60) - 0xc) + 1
97 * the necessary adjustment 103 * r9 = region id.
98 */ 104 */
99 rldimi r10,r9,(CONTEXT_BITS + USER_ESID_BITS),0 105 addis r9,r9,(MAX_USER_CONTEXT - 0xc + 1)@ha
106 addi r9,r9,(MAX_USER_CONTEXT - 0xc + 1)@l
107
100BEGIN_FTR_SECTION 108BEGIN_FTR_SECTION
101 b slb_finish_load 109 b slb_finish_load
102END_MMU_FTR_SECTION_IFCLR(MMU_FTR_1T_SEGMENT) 110END_MMU_FTR_SECTION_IFCLR(MMU_FTR_1T_SEGMENT)
103 b slb_finish_load_1T 111 b slb_finish_load_1T
104 112
1050: /* user address: proto-VSID = context << 15 | ESID. First check 1130:
106 * if the address is within the boundaries of the user region
107 */
108 srdi. r9,r10,USER_ESID_BITS
109 bne- 8f /* invalid ea bits set */
110
111
112 /* when using slices, we extract the psize off the slice bitmaps 114 /* when using slices, we extract the psize off the slice bitmaps
113 * and then we need to get the sllp encoding off the mmu_psize_defs 115 * and then we need to get the sllp encoding off the mmu_psize_defs
114 * array. 116 * array.
@@ -164,15 +166,13 @@ END_MMU_FTR_SECTION_IFCLR(MMU_FTR_1T_SEGMENT)
164 ld r9,PACACONTEXTID(r13) 166 ld r9,PACACONTEXTID(r13)
165BEGIN_FTR_SECTION 167BEGIN_FTR_SECTION
166 cmpldi r10,0x1000 168 cmpldi r10,0x1000
167END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
168 rldimi r10,r9,USER_ESID_BITS,0
169BEGIN_FTR_SECTION
170 bge slb_finish_load_1T 169 bge slb_finish_load_1T
171END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT) 170END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
172 b slb_finish_load 171 b slb_finish_load
173 172
1748: /* invalid EA */ 1738: /* invalid EA */
175 li r10,0 /* BAD_VSID */ 174 li r10,0 /* BAD_VSID */
175 li r9,0 /* BAD_VSID */
176 li r11,SLB_VSID_USER /* flags don't much matter */ 176 li r11,SLB_VSID_USER /* flags don't much matter */
177 b slb_finish_load 177 b slb_finish_load
178 178
@@ -221,8 +221,6 @@ _GLOBAL(slb_allocate_user)
221 221
222 /* get context to calculate proto-VSID */ 222 /* get context to calculate proto-VSID */
223 ld r9,PACACONTEXTID(r13) 223 ld r9,PACACONTEXTID(r13)
224 rldimi r10,r9,USER_ESID_BITS,0
225
226 /* fall through slb_finish_load */ 224 /* fall through slb_finish_load */
227 225
228#endif /* __DISABLED__ */ 226#endif /* __DISABLED__ */
@@ -231,9 +229,10 @@ _GLOBAL(slb_allocate_user)
231/* 229/*
232 * Finish loading of an SLB entry and return 230 * Finish loading of an SLB entry and return
233 * 231 *
234 * r3 = EA, r10 = proto-VSID, r11 = flags, clobbers r9, cr7 = <> PAGE_OFFSET 232 * r3 = EA, r9 = context, r10 = ESID, r11 = flags, clobbers r9, cr7 = <> PAGE_OFFSET
235 */ 233 */
236slb_finish_load: 234slb_finish_load:
235 rldimi r10,r9,USER_ESID_BITS,0
237 ASM_VSID_SCRAMBLE(r10,r9,256M) 236 ASM_VSID_SCRAMBLE(r10,r9,256M)
238 /* 237 /*
239 * bits above VSID_BITS_256M need to be ignored from r10 238 * bits above VSID_BITS_256M need to be ignored from r10
@@ -298,10 +297,11 @@ _GLOBAL(slb_compare_rr_to_size)
298/* 297/*
299 * Finish loading of a 1T SLB entry (for the kernel linear mapping) and return. 298 * Finish loading of a 1T SLB entry (for the kernel linear mapping) and return.
300 * 299 *
301 * r3 = EA, r10 = proto-VSID, r11 = flags, clobbers r9 300 * r3 = EA, r9 = context, r10 = ESID(256MB), r11 = flags, clobbers r9
302 */ 301 */
303slb_finish_load_1T: 302slb_finish_load_1T:
304 srdi r10,r10,40-28 /* get 1T ESID */ 303 srdi r10,r10,(SID_SHIFT_1T - SID_SHIFT) /* get 1T ESID */
304 rldimi r10,r9,USER_ESID_BITS_1T,0
305 ASM_VSID_SCRAMBLE(r10,r9,1T) 305 ASM_VSID_SCRAMBLE(r10,r9,1T)
306 /* 306 /*
307 * bits above VSID_BITS_1T need to be ignored from r10 307 * bits above VSID_BITS_1T need to be ignored from r10
diff --git a/arch/powerpc/mm/tlb_hash64.c b/arch/powerpc/mm/tlb_hash64.c
index 0d82ef50dc3f..023ec8a13f38 100644
--- a/arch/powerpc/mm/tlb_hash64.c
+++ b/arch/powerpc/mm/tlb_hash64.c
@@ -82,11 +82,11 @@ void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
82 if (!is_kernel_addr(addr)) { 82 if (!is_kernel_addr(addr)) {
83 ssize = user_segment_size(addr); 83 ssize = user_segment_size(addr);
84 vsid = get_vsid(mm->context.id, addr, ssize); 84 vsid = get_vsid(mm->context.id, addr, ssize);
85 WARN_ON(vsid == 0);
86 } else { 85 } else {
87 vsid = get_kernel_vsid(addr, mmu_kernel_ssize); 86 vsid = get_kernel_vsid(addr, mmu_kernel_ssize);
88 ssize = mmu_kernel_ssize; 87 ssize = mmu_kernel_ssize;
89 } 88 }
89 WARN_ON(vsid == 0);
90 vpn = hpt_vpn(addr, vsid, ssize); 90 vpn = hpt_vpn(addr, vsid, ssize);
91 rpte = __real_pte(__pte(pte), ptep); 91 rpte = __real_pte(__pte(pte), ptep);
92 92