Commit 86c65a7857896b1de99628ad392556965c4841e6

Authored by Linus Torvalds

Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc

* 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc:
  vmlinux.lds: fix .data..init_task output section (fix popwerpc boot)
  powerpc: Fix erroneous lmb->memblock conversions
  powerpc/mm: Add some debug output when hash insertion fails
  powerpc/mm: Fix bugs in huge page hashing
  powerpc/mm: Move around testing of _PAGE_PRESENT in hash code
  powerpc/mm: Handle hypervisor pte insert failure in __hash_page_huge
  powerpc/kexec: Fix boundary case for book-e kexec memory limits

Showing 9 changed files Side-by-side Diff

arch/powerpc/include/asm/kexec.h
... ... @@ -8,9 +8,9 @@
8 8 * On FSL-BookE we setup a 1:1 mapping which covers the first 2GiB of memory
9 9 * and therefore we can only deal with memory within this range
10 10 */
11   -#define KEXEC_SOURCE_MEMORY_LIMIT (2 * 1024 * 1024 * 1024UL)
12   -#define KEXEC_DESTINATION_MEMORY_LIMIT (2 * 1024 * 1024 * 1024UL)
13   -#define KEXEC_CONTROL_MEMORY_LIMIT (2 * 1024 * 1024 * 1024UL)
  11 +#define KEXEC_SOURCE_MEMORY_LIMIT (2 * 1024 * 1024 * 1024UL - 1)
  12 +#define KEXEC_DESTINATION_MEMORY_LIMIT (2 * 1024 * 1024 * 1024UL - 1)
  13 +#define KEXEC_CONTROL_MEMORY_LIMIT (2 * 1024 * 1024 * 1024UL - 1)
14 14  
15 15 #else
16 16  
arch/powerpc/include/asm/mmu-hash64.h
... ... @@ -250,7 +250,9 @@
250 250 int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid,
251 251 pte_t *ptep, unsigned long trap, int local, int ssize,
252 252 unsigned int shift, unsigned int mmu_psize);
253   -
  253 +extern void hash_failure_debug(unsigned long ea, unsigned long access,
  254 + unsigned long vsid, unsigned long trap,
  255 + int ssize, int psize, unsigned long pte);
254 256 extern int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
255 257 unsigned long pstart, unsigned long prot,
256 258 int psize, int ssize);
arch/powerpc/kernel/prom.c
... ... @@ -414,7 +414,7 @@
414 414 u64 base, size, memblock_size;
415 415 unsigned int is_kexec_kdump = 0, rngs;
416 416  
417   - ls = of_get_flat_dt_prop(node, "ibm,memblock-size", &l);
  417 + ls = of_get_flat_dt_prop(node, "ibm,lmb-size", &l);
418 418 if (ls == NULL || l < dt_root_size_cells * sizeof(__be32))
419 419 return 0;
420 420 memblock_size = dt_mem_next_cell(dt_root_size_cells, &ls);
arch/powerpc/mm/hash_low_64.S
... ... @@ -68,9 +68,6 @@
68 68 std r8,STK_PARM(r8)(r1)
69 69 std r9,STK_PARM(r9)(r1)
70 70  
71   - /* Add _PAGE_PRESENT to access */
72   - ori r4,r4,_PAGE_PRESENT
73   -
74 71 /* Save non-volatile registers.
75 72 * r31 will hold "old PTE"
76 73 * r30 is "new PTE"
... ... @@ -347,9 +344,6 @@
347 344 std r8,STK_PARM(r8)(r1)
348 345 std r9,STK_PARM(r9)(r1)
349 346  
350   - /* Add _PAGE_PRESENT to access */
351   - ori r4,r4,_PAGE_PRESENT
352   -
353 347 /* Save non-volatile registers.
354 348 * r31 will hold "old PTE"
355 349 * r30 is "new PTE"
... ... @@ -686,9 +680,6 @@
686 680 std r6,STK_PARM(r6)(r1)
687 681 std r8,STK_PARM(r8)(r1)
688 682 std r9,STK_PARM(r9)(r1)
689   -
690   - /* Add _PAGE_PRESENT to access */
691   - ori r4,r4,_PAGE_PRESENT
692 683  
693 684 /* Save non-volatile registers.
694 685 * r31 will hold "old PTE"
arch/powerpc/mm/hash_utils_64.c
... ... @@ -871,6 +871,18 @@
871 871 }
872 872 #endif
873 873  
  874 +void hash_failure_debug(unsigned long ea, unsigned long access,
  875 + unsigned long vsid, unsigned long trap,
  876 + int ssize, int psize, unsigned long pte)
  877 +{
  878 + if (!printk_ratelimit())
  879 + return;
  880 + pr_info("mm: Hashing failure ! EA=0x%lx access=0x%lx current=%s\n",
  881 + ea, access, current->comm);
  882 + pr_info(" trap=0x%lx vsid=0x%lx ssize=%d psize=%d pte=0x%lx\n",
  883 + trap, vsid, ssize, psize, pte);
  884 +}
  885 +
874 886 /* Result code is:
875 887 * 0 - handled
876 888 * 1 - normal page fault
... ... @@ -955,6 +967,17 @@
955 967 return 1;
956 968 }
957 969  
  970 + /* Add _PAGE_PRESENT to the required access perm */
  971 + access |= _PAGE_PRESENT;
  972 +
  973 + /* Pre-check access permissions (will be re-checked atomically
  974 + * in __hash_page_XX but this pre-check is a fast path
  975 + */
  976 + if (access & ~pte_val(*ptep)) {
  977 + DBG_LOW(" no access !\n");
  978 + return 1;
  979 + }
  980 +
958 981 #ifdef CONFIG_HUGETLB_PAGE
959 982 if (hugeshift)
960 983 return __hash_page_huge(ea, access, vsid, ptep, trap, local,
... ... @@ -967,14 +990,6 @@
967 990 DBG_LOW(" i-pte: %016lx %016lx\n", pte_val(*ptep),
968 991 pte_val(*(ptep + PTRS_PER_PTE)));
969 992 #endif
970   - /* Pre-check access permissions (will be re-checked atomically
971   - * in __hash_page_XX but this pre-check is a fast path
972   - */
973   - if (access & ~pte_val(*ptep)) {
974   - DBG_LOW(" no access !\n");
975   - return 1;
976   - }
977   -
978 993 /* Do actual hashing */
979 994 #ifdef CONFIG_PPC_64K_PAGES
980 995 /* If _PAGE_4K_PFN is set, make sure this is a 4k segment */
... ... @@ -1033,6 +1048,12 @@
1033 1048 local, ssize, spp);
1034 1049 }
1035 1050  
  1051 + /* Dump some info in case of hash insertion failure, they should
  1052 + * never happen so it is really useful to know if/when they do
  1053 + */
  1054 + if (rc == -1)
  1055 + hash_failure_debug(ea, access, vsid, trap, ssize, psize,
  1056 + pte_val(*ptep));
1036 1057 #ifndef CONFIG_PPC_64K_PAGES
1037 1058 DBG_LOW(" o-pte: %016lx\n", pte_val(*ptep));
1038 1059 #else
... ... @@ -1051,8 +1072,7 @@
1051 1072 void *pgdir;
1052 1073 pte_t *ptep;
1053 1074 unsigned long flags;
1054   - int local = 0;
1055   - int ssize;
  1075 + int rc, ssize, local = 0;
1056 1076  
1057 1077 BUG_ON(REGION_ID(ea) != USER_REGION_ID);
1058 1078  
1059 1079  
... ... @@ -1098,11 +1118,18 @@
1098 1118 /* Hash it in */
1099 1119 #ifdef CONFIG_PPC_HAS_HASH_64K
1100 1120 if (mm->context.user_psize == MMU_PAGE_64K)
1101   - __hash_page_64K(ea, access, vsid, ptep, trap, local, ssize);
  1121 + rc = __hash_page_64K(ea, access, vsid, ptep, trap, local, ssize);
1102 1122 else
1103 1123 #endif /* CONFIG_PPC_HAS_HASH_64K */
1104   - __hash_page_4K(ea, access, vsid, ptep, trap, local, ssize,
1105   - subpage_protection(pgdir, ea));
  1124 + rc = __hash_page_4K(ea, access, vsid, ptep, trap, local, ssize,
  1125 + subpage_protection(pgdir, ea));
  1126 +
  1127 + /* Dump some info in case of hash insertion failure, they should
  1128 + * never happen so it is really useful to know if/when they do
  1129 + */
  1130 + if (rc == -1)
  1131 + hash_failure_debug(ea, access, vsid, trap, ssize,
  1132 + mm->context.user_psize, pte_val(*ptep));
1106 1133  
1107 1134 local_irq_restore(flags);
1108 1135 }
arch/powerpc/mm/hugetlbpage-hash64.c
... ... @@ -21,21 +21,13 @@
21 21 unsigned long old_pte, new_pte;
22 22 unsigned long va, rflags, pa, sz;
23 23 long slot;
24   - int err = 1;
25 24  
26 25 BUG_ON(shift != mmu_psize_defs[mmu_psize].shift);
27 26  
28 27 /* Search the Linux page table for a match with va */
29 28 va = hpt_va(ea, vsid, ssize);
30 29  
31   - /*
32   - * Check the user's access rights to the page. If access should be
33   - * prevented then send the problem up to do_page_fault.
34   - */
35   - if (unlikely(access & ~pte_val(*ptep)))
36   - goto out;
37   - /*
38   - * At this point, we have a pte (old_pte) which can be used to build
  30 + /* At this point, we have a pte (old_pte) which can be used to build
39 31 * or update an HPTE. There are 2 cases:
40 32 *
41 33 * 1. There is a valid (present) pte with no associated HPTE (this is
42 34  
... ... @@ -49,9 +41,17 @@
49 41  
50 42 do {
51 43 old_pte = pte_val(*ptep);
52   - if (old_pte & _PAGE_BUSY)
53   - goto out;
  44 + /* If PTE busy, retry the access */
  45 + if (unlikely(old_pte & _PAGE_BUSY))
  46 + return 0;
  47 + /* If PTE permissions don't match, take page fault */
  48 + if (unlikely(access & ~old_pte))
  49 + return 1;
  50 + /* Try to lock the PTE, add ACCESSED and DIRTY if it was
  51 + * a write access */
54 52 new_pte = old_pte | _PAGE_BUSY | _PAGE_ACCESSED;
  53 + if (access & _PAGE_RW)
  54 + new_pte |= _PAGE_DIRTY;
55 55 } while(old_pte != __cmpxchg_u64((unsigned long *)ptep,
56 56 old_pte, new_pte));
57 57  
... ... @@ -121,8 +121,16 @@
121 121 }
122 122 }
123 123  
124   - if (unlikely(slot == -2))
125   - panic("hash_huge_page: pte_insert failed\n");
  124 + /*
  125 + * Hypervisor failure. Restore old pte and return -1
  126 + * similar to __hash_page_*
  127 + */
  128 + if (unlikely(slot == -2)) {
  129 + *ptep = __pte(old_pte);
  130 + hash_failure_debug(ea, access, vsid, trap, ssize,
  131 + mmu_psize, old_pte);
  132 + return -1;
  133 + }
126 134  
127 135 new_pte |= (slot << 12) & (_PAGE_F_SECOND | _PAGE_F_GIX);
128 136 }
... ... @@ -131,10 +139,6 @@
131 139 * No need to use ldarx/stdcx here
132 140 */
133 141 *ptep = __pte(new_pte & ~_PAGE_BUSY);
134   -
135   - err = 0;
136   -
137   - out:
138   - return err;
  142 + return 0;
139 143 }
arch/powerpc/mm/numa.c
... ... @@ -398,15 +398,15 @@
398 398 }
399 399  
400 400 /*
401   - * Retreive and validate the ibm,memblock-size property for drconf memory
  401 + * Retreive and validate the ibm,lmb-size property for drconf memory
402 402 * from the device tree.
403 403 */
404   -static u64 of_get_memblock_size(struct device_node *memory)
  404 +static u64 of_get_lmb_size(struct device_node *memory)
405 405 {
406 406 const u32 *prop;
407 407 u32 len;
408 408  
409   - prop = of_get_property(memory, "ibm,memblock-size", &len);
  409 + prop = of_get_property(memory, "ibm,lmb-size", &len);
410 410 if (!prop || len < sizeof(unsigned int))
411 411 return 0;
412 412  
... ... @@ -562,7 +562,7 @@
562 562 static inline int __init read_usm_ranges(const u32 **usm)
563 563 {
564 564 /*
565   - * For each memblock in ibm,dynamic-memory a corresponding
  565 + * For each lmb in ibm,dynamic-memory a corresponding
566 566 * entry in linux,drconf-usable-memory property contains
567 567 * a counter followed by that many (base, size) duple.
568 568 * read the counter from linux,drconf-usable-memory
... ... @@ -578,7 +578,7 @@
578 578 {
579 579 const u32 *dm, *usm;
580 580 unsigned int n, rc, ranges, is_kexec_kdump = 0;
581   - unsigned long memblock_size, base, size, sz;
  581 + unsigned long lmb_size, base, size, sz;
582 582 int nid;
583 583 struct assoc_arrays aa;
584 584  
... ... @@ -586,8 +586,8 @@
586 586 if (!n)
587 587 return;
588 588  
589   - memblock_size = of_get_memblock_size(memory);
590   - if (!memblock_size)
  589 + lmb_size = of_get_lmb_size(memory);
  590 + if (!lmb_size)
591 591 return;
592 592  
593 593 rc = of_get_assoc_arrays(memory, &aa);
... ... @@ -611,7 +611,7 @@
611 611 continue;
612 612  
613 613 base = drmem.base_addr;
614   - size = memblock_size;
  614 + size = lmb_size;
615 615 ranges = 1;
616 616  
617 617 if (is_kexec_kdump) {
... ... @@ -1072,7 +1072,7 @@
1072 1072 {
1073 1073 const u32 *dm;
1074 1074 unsigned int drconf_cell_cnt, rc;
1075   - unsigned long memblock_size;
  1075 + unsigned long lmb_size;
1076 1076 struct assoc_arrays aa;
1077 1077 int nid = -1;
1078 1078  
... ... @@ -1080,8 +1080,8 @@
1080 1080 if (!drconf_cell_cnt)
1081 1081 return -1;
1082 1082  
1083   - memblock_size = of_get_memblock_size(memory);
1084   - if (!memblock_size)
  1083 + lmb_size = of_get_lmb_size(memory);
  1084 + if (!lmb_size)
1085 1085 return -1;
1086 1086  
1087 1087 rc = of_get_assoc_arrays(memory, &aa);
... ... @@ -1100,7 +1100,7 @@
1100 1100 continue;
1101 1101  
1102 1102 if ((scn_addr < drmem.base_addr)
1103   - || (scn_addr >= (drmem.base_addr + memblock_size)))
  1103 + || (scn_addr >= (drmem.base_addr + lmb_size)))
1104 1104 continue;
1105 1105  
1106 1106 nid = of_drconf_to_nid_single(&drmem, &aa);
arch/powerpc/platforms/pseries/hotplug-memory.c
... ... @@ -69,7 +69,7 @@
69 69 const char *type;
70 70 const unsigned int *regs;
71 71 unsigned long base;
72   - unsigned int memblock_size;
  72 + unsigned int lmb_size;
73 73 int ret = -EINVAL;
74 74  
75 75 /*
76 76  
... ... @@ -87,9 +87,9 @@
87 87 return ret;
88 88  
89 89 base = *(unsigned long *)regs;
90   - memblock_size = regs[3];
  90 + lmb_size = regs[3];
91 91  
92   - ret = pseries_remove_memblock(base, memblock_size);
  92 + ret = pseries_remove_memblock(base, lmb_size);
93 93 return ret;
94 94 }
95 95  
... ... @@ -98,7 +98,7 @@
98 98 const char *type;
99 99 const unsigned int *regs;
100 100 unsigned long base;
101   - unsigned int memblock_size;
  101 + unsigned int lmb_size;
102 102 int ret = -EINVAL;
103 103  
104 104 /*
105 105  
106 106  
107 107  
108 108  
109 109  
... ... @@ -116,36 +116,36 @@
116 116 return ret;
117 117  
118 118 base = *(unsigned long *)regs;
119   - memblock_size = regs[3];
  119 + lmb_size = regs[3];
120 120  
121 121 /*
122 122 * Update memory region to represent the memory add
123 123 */
124   - ret = memblock_add(base, memblock_size);
  124 + ret = memblock_add(base, lmb_size);
125 125 return (ret < 0) ? -EINVAL : 0;
126 126 }
127 127  
128 128 static int pseries_drconf_memory(unsigned long *base, unsigned int action)
129 129 {
130 130 struct device_node *np;
131   - const unsigned long *memblock_size;
  131 + const unsigned long *lmb_size;
132 132 int rc;
133 133  
134 134 np = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
135 135 if (!np)
136 136 return -EINVAL;
137 137  
138   - memblock_size = of_get_property(np, "ibm,memblock-size", NULL);
139   - if (!memblock_size) {
  138 + lmb_size = of_get_property(np, "ibm,lmb-size", NULL);
  139 + if (!lmb_size) {
140 140 of_node_put(np);
141 141 return -EINVAL;
142 142 }
143 143  
144 144 if (action == PSERIES_DRCONF_MEM_ADD) {
145   - rc = memblock_add(*base, *memblock_size);
  145 + rc = memblock_add(*base, *lmb_size);
146 146 rc = (rc < 0) ? -EINVAL : 0;
147 147 } else if (action == PSERIES_DRCONF_MEM_REMOVE) {
148   - rc = pseries_remove_memblock(*base, *memblock_size);
  148 + rc = pseries_remove_memblock(*base, *lmb_size);
149 149 } else {
150 150 rc = -EINVAL;
151 151 }
include/asm-generic/vmlinux.lds.h
... ... @@ -445,7 +445,7 @@
445 445 */
446 446 #define INIT_TASK_DATA_SECTION(align) \
447 447 . = ALIGN(align); \
448   - .data..init_task : { \
  448 + .data..init_task : AT(ADDR(.data..init_task) - LOAD_OFFSET) { \
449 449 INIT_TASK_DATA(align) \
450 450 }
451 451