提交 83ada031 编写于 作者: L Linus Torvalds

Merge tag 'powerpc-4.15-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux

Pull powerpc fixes from Michael Ellerman:
 "A small batch of fixes, about 50% tagged for stable and the rest for
  recently merged code.

  There's one more fix for the >128T handling on hash. Once a process
  had requested a single mmap above 128T we would then always search
  above 128T. The correct behaviour is to consider the hint address in
  isolation for each mmap request.

  Then a couple of fixes for the IMC PMU, a missing EXPORT_SYMBOL in
  VAS, a fix for STRICT_KERNEL_RWX on 32-bit, and a fix to correctly
  identify P9 DD2.1 but in code that is currently not used by default.

  Thanks to: Aneesh Kumar K.V, Christophe Leroy, Madhavan Srinivasan,
  Sukadev Bhattiprolu"

* tag 'powerpc-4.15-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux:
  powerpc/64s: Fix Power9 DD2.1 logic in DT CPU features
  powerpc/perf: Fix IMC_MAX_PMU macro
  powerpc/perf: Fix pmu_count to count only nest imc pmus
  powerpc: Fix boot on BOOK3S_32 with CONFIG_STRICT_KERNEL_RWX
  powerpc/perf/imc: Use cpu_to_node() not topology_physical_package_id()
  powerpc/vas: Export chip_to_vas_id()
  powerpc/64s/slice: Use addr limit when computing slice mask
...@@ -20,11 +20,6 @@ ...@@ -20,11 +20,6 @@
#include <linux/io.h> #include <linux/io.h>
#include <asm/opal.h> #include <asm/opal.h>
/*
* For static allocation of some of the structures.
*/
#define IMC_MAX_PMUS 32
/* /*
* Compatibility macros for IMC devices * Compatibility macros for IMC devices
*/ */
...@@ -125,4 +120,5 @@ enum { ...@@ -125,4 +120,5 @@ enum {
extern int init_imc_pmu(struct device_node *parent, extern int init_imc_pmu(struct device_node *parent,
struct imc_pmu *pmu_ptr, int pmu_id); struct imc_pmu *pmu_ptr, int pmu_id);
extern void thread_imc_disable(void); extern void thread_imc_disable(void);
extern int get_max_nest_dev(void);
#endif /* __ASM_POWERPC_IMC_PMU_H */ #endif /* __ASM_POWERPC_IMC_PMU_H */
...@@ -735,8 +735,8 @@ static __init void cpufeatures_cpu_quirks(void) ...@@ -735,8 +735,8 @@ static __init void cpufeatures_cpu_quirks(void)
*/ */
if ((version & 0xffffff00) == 0x004e0100) if ((version & 0xffffff00) == 0x004e0100)
cur_cpu_spec->cpu_features |= CPU_FTR_POWER9_DD1; cur_cpu_spec->cpu_features |= CPU_FTR_POWER9_DD1;
else if ((version & 0xffffefff) == 0x004e0200) else if ((version & 0xffffefff) == 0x004e0201)
cur_cpu_spec->cpu_features &= ~CPU_FTR_POWER9_DD2_1; cur_cpu_spec->cpu_features |= CPU_FTR_POWER9_DD2_1;
} }
static void __init cpufeatures_setup_finished(void) static void __init cpufeatures_setup_finished(void)
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/code-patching.h> #include <asm/code-patching.h>
#include <asm/setup.h>
static int __patch_instruction(unsigned int *addr, unsigned int instr) static int __patch_instruction(unsigned int *addr, unsigned int instr)
{ {
...@@ -146,11 +147,8 @@ int patch_instruction(unsigned int *addr, unsigned int instr) ...@@ -146,11 +147,8 @@ int patch_instruction(unsigned int *addr, unsigned int instr)
* During early early boot patch_instruction is called * During early early boot patch_instruction is called
* when text_poke_area is not ready, but we still need * when text_poke_area is not ready, but we still need
* to allow patching. We just do the plain old patching * to allow patching. We just do the plain old patching
* We use slab_is_available and per cpu read * via this_cpu_read
* of text_poke_area. Per-CPU areas might not be up early
* this can create problems with just using this_cpu_read()
*/ */
if (!slab_is_available() || !this_cpu_read(text_poke_area)) if (!this_cpu_read(*PTRRELOC(&text_poke_area)))
return __patch_instruction(addr, instr); return __patch_instruction(addr, instr);
local_irq_save(flags); local_irq_save(flags);
......
...@@ -122,7 +122,8 @@ static int slice_high_has_vma(struct mm_struct *mm, unsigned long slice) ...@@ -122,7 +122,8 @@ static int slice_high_has_vma(struct mm_struct *mm, unsigned long slice)
return !slice_area_is_free(mm, start, end - start); return !slice_area_is_free(mm, start, end - start);
} }
static void slice_mask_for_free(struct mm_struct *mm, struct slice_mask *ret) static void slice_mask_for_free(struct mm_struct *mm, struct slice_mask *ret,
unsigned long high_limit)
{ {
unsigned long i; unsigned long i;
...@@ -133,15 +134,16 @@ static void slice_mask_for_free(struct mm_struct *mm, struct slice_mask *ret) ...@@ -133,15 +134,16 @@ static void slice_mask_for_free(struct mm_struct *mm, struct slice_mask *ret)
if (!slice_low_has_vma(mm, i)) if (!slice_low_has_vma(mm, i))
ret->low_slices |= 1u << i; ret->low_slices |= 1u << i;
if (mm->context.slb_addr_limit <= SLICE_LOW_TOP) if (high_limit <= SLICE_LOW_TOP)
return; return;
for (i = 0; i < GET_HIGH_SLICE_INDEX(mm->context.slb_addr_limit); i++) for (i = 0; i < GET_HIGH_SLICE_INDEX(high_limit); i++)
if (!slice_high_has_vma(mm, i)) if (!slice_high_has_vma(mm, i))
__set_bit(i, ret->high_slices); __set_bit(i, ret->high_slices);
} }
static void slice_mask_for_size(struct mm_struct *mm, int psize, struct slice_mask *ret) static void slice_mask_for_size(struct mm_struct *mm, int psize, struct slice_mask *ret,
unsigned long high_limit)
{ {
unsigned char *hpsizes; unsigned char *hpsizes;
int index, mask_index; int index, mask_index;
...@@ -156,8 +158,11 @@ static void slice_mask_for_size(struct mm_struct *mm, int psize, struct slice_ma ...@@ -156,8 +158,11 @@ static void slice_mask_for_size(struct mm_struct *mm, int psize, struct slice_ma
if (((lpsizes >> (i * 4)) & 0xf) == psize) if (((lpsizes >> (i * 4)) & 0xf) == psize)
ret->low_slices |= 1u << i; ret->low_slices |= 1u << i;
if (high_limit <= SLICE_LOW_TOP)
return;
hpsizes = mm->context.high_slices_psize; hpsizes = mm->context.high_slices_psize;
for (i = 0; i < GET_HIGH_SLICE_INDEX(mm->context.slb_addr_limit); i++) { for (i = 0; i < GET_HIGH_SLICE_INDEX(high_limit); i++) {
mask_index = i & 0x1; mask_index = i & 0x1;
index = i >> 1; index = i >> 1;
if (((hpsizes[index] >> (mask_index * 4)) & 0xf) == psize) if (((hpsizes[index] >> (mask_index * 4)) & 0xf) == psize)
...@@ -169,6 +174,10 @@ static int slice_check_fit(struct mm_struct *mm, ...@@ -169,6 +174,10 @@ static int slice_check_fit(struct mm_struct *mm,
struct slice_mask mask, struct slice_mask available) struct slice_mask mask, struct slice_mask available)
{ {
DECLARE_BITMAP(result, SLICE_NUM_HIGH); DECLARE_BITMAP(result, SLICE_NUM_HIGH);
/*
* Make sure we just do bit compare only to the max
* addr limit and not the full bit map size.
*/
unsigned long slice_count = GET_HIGH_SLICE_INDEX(mm->context.slb_addr_limit); unsigned long slice_count = GET_HIGH_SLICE_INDEX(mm->context.slb_addr_limit);
bitmap_and(result, mask.high_slices, bitmap_and(result, mask.high_slices,
...@@ -472,7 +481,7 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len, ...@@ -472,7 +481,7 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
/* First make up a "good" mask of slices that have the right size /* First make up a "good" mask of slices that have the right size
* already * already
*/ */
slice_mask_for_size(mm, psize, &good_mask); slice_mask_for_size(mm, psize, &good_mask, high_limit);
slice_print_mask(" good_mask", good_mask); slice_print_mask(" good_mask", good_mask);
/* /*
...@@ -497,7 +506,7 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len, ...@@ -497,7 +506,7 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
#ifdef CONFIG_PPC_64K_PAGES #ifdef CONFIG_PPC_64K_PAGES
/* If we support combo pages, we can allow 64k pages in 4k slices */ /* If we support combo pages, we can allow 64k pages in 4k slices */
if (psize == MMU_PAGE_64K) { if (psize == MMU_PAGE_64K) {
slice_mask_for_size(mm, MMU_PAGE_4K, &compat_mask); slice_mask_for_size(mm, MMU_PAGE_4K, &compat_mask, high_limit);
if (fixed) if (fixed)
slice_or_mask(&good_mask, &compat_mask); slice_or_mask(&good_mask, &compat_mask);
} }
...@@ -530,11 +539,11 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len, ...@@ -530,11 +539,11 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
return newaddr; return newaddr;
} }
} }
/*
/* We don't fit in the good mask, check what other slices are * We don't fit in the good mask, check what other slices are
* empty and thus can be converted * empty and thus can be converted
*/ */
slice_mask_for_free(mm, &potential_mask); slice_mask_for_free(mm, &potential_mask, high_limit);
slice_or_mask(&potential_mask, &good_mask); slice_or_mask(&potential_mask, &good_mask);
slice_print_mask(" potential", potential_mask); slice_print_mask(" potential", potential_mask);
...@@ -744,17 +753,18 @@ int is_hugepage_only_range(struct mm_struct *mm, unsigned long addr, ...@@ -744,17 +753,18 @@ int is_hugepage_only_range(struct mm_struct *mm, unsigned long addr,
{ {
struct slice_mask mask, available; struct slice_mask mask, available;
unsigned int psize = mm->context.user_psize; unsigned int psize = mm->context.user_psize;
unsigned long high_limit = mm->context.slb_addr_limit;
if (radix_enabled()) if (radix_enabled())
return 0; return 0;
slice_range_to_mask(addr, len, &mask); slice_range_to_mask(addr, len, &mask);
slice_mask_for_size(mm, psize, &available); slice_mask_for_size(mm, psize, &available, high_limit);
#ifdef CONFIG_PPC_64K_PAGES #ifdef CONFIG_PPC_64K_PAGES
/* We need to account for 4k slices too */ /* We need to account for 4k slices too */
if (psize == MMU_PAGE_64K) { if (psize == MMU_PAGE_64K) {
struct slice_mask compat_mask; struct slice_mask compat_mask;
slice_mask_for_size(mm, MMU_PAGE_4K, &compat_mask); slice_mask_for_size(mm, MMU_PAGE_4K, &compat_mask, high_limit);
slice_or_mask(&available, &compat_mask); slice_or_mask(&available, &compat_mask);
} }
#endif #endif
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
*/ */
static DEFINE_MUTEX(nest_init_lock); static DEFINE_MUTEX(nest_init_lock);
static DEFINE_PER_CPU(struct imc_pmu_ref *, local_nest_imc_refc); static DEFINE_PER_CPU(struct imc_pmu_ref *, local_nest_imc_refc);
static struct imc_pmu *per_nest_pmu_arr[IMC_MAX_PMUS]; static struct imc_pmu **per_nest_pmu_arr;
static cpumask_t nest_imc_cpumask; static cpumask_t nest_imc_cpumask;
struct imc_pmu_ref *nest_imc_refc; struct imc_pmu_ref *nest_imc_refc;
static int nest_pmus; static int nest_pmus;
...@@ -286,13 +286,14 @@ static struct imc_pmu_ref *get_nest_pmu_ref(int cpu) ...@@ -286,13 +286,14 @@ static struct imc_pmu_ref *get_nest_pmu_ref(int cpu)
static void nest_change_cpu_context(int old_cpu, int new_cpu) static void nest_change_cpu_context(int old_cpu, int new_cpu)
{ {
struct imc_pmu **pn = per_nest_pmu_arr; struct imc_pmu **pn = per_nest_pmu_arr;
int i;
if (old_cpu < 0 || new_cpu < 0) if (old_cpu < 0 || new_cpu < 0)
return; return;
for (i = 0; *pn && i < IMC_MAX_PMUS; i++, pn++) while (*pn) {
perf_pmu_migrate_context(&(*pn)->pmu, old_cpu, new_cpu); perf_pmu_migrate_context(&(*pn)->pmu, old_cpu, new_cpu);
pn++;
}
} }
static int ppc_nest_imc_cpu_offline(unsigned int cpu) static int ppc_nest_imc_cpu_offline(unsigned int cpu)
...@@ -467,7 +468,7 @@ static int nest_imc_event_init(struct perf_event *event) ...@@ -467,7 +468,7 @@ static int nest_imc_event_init(struct perf_event *event)
* Nest HW counter memory resides in a per-chip reserve-memory (HOMER). * Nest HW counter memory resides in a per-chip reserve-memory (HOMER).
* Get the base memory addresss for this cpu. * Get the base memory addresss for this cpu.
*/ */
chip_id = topology_physical_package_id(event->cpu); chip_id = cpu_to_chip_id(event->cpu);
pcni = pmu->mem_info; pcni = pmu->mem_info;
do { do {
if (pcni->id == chip_id) { if (pcni->id == chip_id) {
...@@ -524,19 +525,19 @@ static int nest_imc_event_init(struct perf_event *event) ...@@ -524,19 +525,19 @@ static int nest_imc_event_init(struct perf_event *event)
*/ */
static int core_imc_mem_init(int cpu, int size) static int core_imc_mem_init(int cpu, int size)
{ {
int phys_id, rc = 0, core_id = (cpu / threads_per_core); int nid, rc = 0, core_id = (cpu / threads_per_core);
struct imc_mem_info *mem_info; struct imc_mem_info *mem_info;
/* /*
* alloc_pages_node() will allocate memory for core in the * alloc_pages_node() will allocate memory for core in the
* local node only. * local node only.
*/ */
phys_id = topology_physical_package_id(cpu); nid = cpu_to_node(cpu);
mem_info = &core_imc_pmu->mem_info[core_id]; mem_info = &core_imc_pmu->mem_info[core_id];
mem_info->id = core_id; mem_info->id = core_id;
/* We need only vbase for core counters */ /* We need only vbase for core counters */
mem_info->vbase = page_address(alloc_pages_node(phys_id, mem_info->vbase = page_address(alloc_pages_node(nid,
GFP_KERNEL | __GFP_ZERO | __GFP_THISNODE | GFP_KERNEL | __GFP_ZERO | __GFP_THISNODE |
__GFP_NOWARN, get_order(size))); __GFP_NOWARN, get_order(size)));
if (!mem_info->vbase) if (!mem_info->vbase)
...@@ -797,14 +798,14 @@ static int core_imc_event_init(struct perf_event *event) ...@@ -797,14 +798,14 @@ static int core_imc_event_init(struct perf_event *event)
static int thread_imc_mem_alloc(int cpu_id, int size) static int thread_imc_mem_alloc(int cpu_id, int size)
{ {
u64 ldbar_value, *local_mem = per_cpu(thread_imc_mem, cpu_id); u64 ldbar_value, *local_mem = per_cpu(thread_imc_mem, cpu_id);
int phys_id = topology_physical_package_id(cpu_id); int nid = cpu_to_node(cpu_id);
if (!local_mem) { if (!local_mem) {
/* /*
* This case could happen only once at start, since we dont * This case could happen only once at start, since we dont
* free the memory in cpu offline path. * free the memory in cpu offline path.
*/ */
local_mem = page_address(alloc_pages_node(phys_id, local_mem = page_address(alloc_pages_node(nid,
GFP_KERNEL | __GFP_ZERO | __GFP_THISNODE | GFP_KERNEL | __GFP_ZERO | __GFP_THISNODE |
__GFP_NOWARN, get_order(size))); __GFP_NOWARN, get_order(size)));
if (!local_mem) if (!local_mem)
...@@ -1194,6 +1195,7 @@ static void imc_common_cpuhp_mem_free(struct imc_pmu *pmu_ptr) ...@@ -1194,6 +1195,7 @@ static void imc_common_cpuhp_mem_free(struct imc_pmu *pmu_ptr)
kfree(pmu_ptr->attr_groups[IMC_EVENT_ATTR]->attrs); kfree(pmu_ptr->attr_groups[IMC_EVENT_ATTR]->attrs);
kfree(pmu_ptr->attr_groups[IMC_EVENT_ATTR]); kfree(pmu_ptr->attr_groups[IMC_EVENT_ATTR]);
kfree(pmu_ptr); kfree(pmu_ptr);
kfree(per_nest_pmu_arr);
return; return;
} }
...@@ -1218,6 +1220,13 @@ static int imc_mem_init(struct imc_pmu *pmu_ptr, struct device_node *parent, ...@@ -1218,6 +1220,13 @@ static int imc_mem_init(struct imc_pmu *pmu_ptr, struct device_node *parent,
return -ENOMEM; return -ENOMEM;
/* Needed for hotplug/migration */ /* Needed for hotplug/migration */
if (!per_nest_pmu_arr) {
per_nest_pmu_arr = kcalloc(get_max_nest_dev() + 1,
sizeof(struct imc_pmu *),
GFP_KERNEL);
if (!per_nest_pmu_arr)
return -ENOMEM;
}
per_nest_pmu_arr[pmu_index] = pmu_ptr; per_nest_pmu_arr[pmu_index] = pmu_ptr;
break; break;
case IMC_DOMAIN_CORE: case IMC_DOMAIN_CORE:
......
...@@ -153,6 +153,22 @@ static void disable_core_pmu_counters(void) ...@@ -153,6 +153,22 @@ static void disable_core_pmu_counters(void)
put_online_cpus(); put_online_cpus();
} }
int get_max_nest_dev(void)
{
struct device_node *node;
u32 pmu_units = 0, type;
for_each_compatible_node(node, NULL, IMC_DTB_UNIT_COMPAT) {
if (of_property_read_u32(node, "type", &type))
continue;
if (type == IMC_TYPE_CHIP)
pmu_units++;
}
return pmu_units;
}
static int opal_imc_counters_probe(struct platform_device *pdev) static int opal_imc_counters_probe(struct platform_device *pdev)
{ {
struct device_node *imc_dev = pdev->dev.of_node; struct device_node *imc_dev = pdev->dev.of_node;
...@@ -191,9 +207,11 @@ static int opal_imc_counters_probe(struct platform_device *pdev) ...@@ -191,9 +207,11 @@ static int opal_imc_counters_probe(struct platform_device *pdev)
break; break;
} }
if (!imc_pmu_create(imc_dev, pmu_count, domain)) if (!imc_pmu_create(imc_dev, pmu_count, domain)) {
if (domain == IMC_DOMAIN_NEST)
pmu_count++; pmu_count++;
} }
}
return 0; return 0;
} }
......
...@@ -135,6 +135,7 @@ int chip_to_vas_id(int chipid) ...@@ -135,6 +135,7 @@ int chip_to_vas_id(int chipid)
} }
return -1; return -1;
} }
EXPORT_SYMBOL(chip_to_vas_id);
static int vas_probe(struct platform_device *pdev) static int vas_probe(struct platform_device *pdev)
{ {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册