* [RFC v5 5/6] powerpc/mobility: Add lock/unlock device hotplug
From: Michael Bringmann @ 2018-05-21 17:52 UTC (permalink / raw)
To: linuxppc-dev
Cc: Michael Bringmann, Nathan Fontenot, John Allen, Tyrel Datwyler,
Thomas Falcon
In-Reply-To: <6add12e8-acf9-228e-fa04-80e38dbb8f7c@linux.vnet.ibm.com>
powerpc/mobility: Add device lock/unlock to PowerPC 'mobility' operation
to delay the operation of CPU DLPAR work queue operations by the 'readd'
activity until after any changes to the corresponding device-tree
properties have been written.
Signed-off-by: Michael Bringmann <mwb@linux.vnet.ibm.com>
---
arch/powerpc/platforms/pseries/mobility.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c
index 8a8033a..6d98f84 100644
--- a/arch/powerpc/platforms/pseries/mobility.c
+++ b/arch/powerpc/platforms/pseries/mobility.c
@@ -283,6 +283,8 @@ int pseries_devicetree_update(s32 scope)
if (!rtas_buf)
return -ENOMEM;
+ lock_device_hotplug();
+
do {
rc = mobility_rtas_call(update_nodes_token, rtas_buf, scope);
if (rc && rc != 1)
@@ -321,6 +323,7 @@ int pseries_devicetree_update(s32 scope)
} while (rc == 1);
kfree(rtas_buf);
+ unlock_device_hotplug();
return rc;
}
^ permalink raw reply related
* [RFC v5 6/6] migration/memory: Update memory for assoc changes
From: Michael Bringmann @ 2018-05-21 17:52 UTC (permalink / raw)
To: linuxppc-dev
Cc: Michael Bringmann, Nathan Fontenot, John Allen, Tyrel Datwyler,
Thomas Falcon
In-Reply-To: <6add12e8-acf9-228e-fa04-80e38dbb8f7c@linux.vnet.ibm.com>
migration/memory: This patch adds more recognition for changes to
the associativity of memory blocks described by the device-tree
properties and updates local and general kernel data structures to
reflect those changes. These differences may include:
* Evaluating 'ibm,dynamic-memory' properties when processing the
topology of LPARS in Post Migration events. Previous efforts
only recognized whether a memory block's assignment had changed
in the property. Changes here include checking the aa_index
values for each drc_index of the old/new LMBs and to 'readd'
any block for which the setting has changed.
* In an LPAR migration scenario, the "ibm,associativity-lookup-arrays"
property may change. In the event that a row of the array differs,
locate all assigned memory blocks with that 'aa_index' and 're-add'
them to the system memory block data structures. In the process of
the 're-add', the system routines will update the corresponding entry
for the memory in the LMB structures and any other relevant kernel
data structures.
* Extend the previous work for the 'ibm,associativity-lookup-array'
and 'ibm,dynamic-memory' properties to support the property
'ibm,dynamic-memory-v2' by means of the DRMEM LMB interpretation
code.
Signed-off-by: Michael Bringmann <mwb@linux.vnet.ibm.com>
---
Changes in RFC:
-- Simplify code to update memory nodes during mobility checks.
-- Reuse code from DRMEM changes to scan for LMBs when updating
aa_index
-- Combine common code for properties 'ibm,dynamic-memory' and
'ibm,dynamic-memory-v2' after integrating DRMEM features.
-- Rearrange patches to co-locate memory property-related changes.
-- Use new paired list iterator for the drmem info arrays.
-- Use direct calls to add/remove memory from the update drconf
function as those operations are only intended for user DLPAR
ops, and should not occur during Migration reconfig notifier
changes.
-- Correct processing bug in processing of ibm,associativity-lookup-arrays
-- Rebase to 4.17-rc5 kernel
-- Apply minor code cleanups
---
arch/powerpc/platforms/pseries/hotplug-memory.c | 153 ++++++++++++++++++-----
1 file changed, 121 insertions(+), 32 deletions(-)
diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
index c1578f5..ac329aa 100644
--- a/arch/powerpc/platforms/pseries/hotplug-memory.c
+++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
@@ -994,13 +994,11 @@ static int pseries_add_mem_node(struct device_node *np)
return (ret < 0) ? -EINVAL : 0;
}
-static int pseries_update_drconf_memory(struct of_reconfig_data *pr)
+static int pseries_update_drconf_memory(struct drmem_lmb_info *new_dinfo)
{
- struct of_drconf_cell_v1 *new_drmem, *old_drmem;
+ struct drmem_lmb *old_lmb, *new_lmb;
unsigned long memblock_size;
- u32 entries;
- __be32 *p;
- int i, rc = -EINVAL;
+ int rc = 0;
if (rtas_hp_event)
return 0;
@@ -1009,42 +1007,124 @@ static int pseries_update_drconf_memory(struct of_reconfig_data *pr)
if (!memblock_size)
return -EINVAL;
- p = (__be32 *) pr->old_prop->value;
- if (!p)
- return -EINVAL;
+ /* Arrays should have the same size and DRC indexes */
+ for_each_pair_drmem_lmb(drmem_info, old_lmb, new_dinfo, new_lmb) {
- /* The first int of the property is the number of lmb's described
- * by the property. This is followed by an array of of_drconf_cell
- * entries. Get the number of entries and skip to the array of
- * of_drconf_cell's.
- */
- entries = be32_to_cpu(*p++);
- old_drmem = (struct of_drconf_cell_v1 *)p;
-
- p = (__be32 *)pr->prop->value;
- p++;
- new_drmem = (struct of_drconf_cell_v1 *)p;
+ if (new_lmb->drc_index != old_lmb->drc_index)
+ continue;
- for (i = 0; i < entries; i++) {
- if ((be32_to_cpu(old_drmem[i].flags) & DRCONF_MEM_ASSIGNED) &&
- (!(be32_to_cpu(new_drmem[i].flags) & DRCONF_MEM_ASSIGNED))) {
+ if ((old_lmb->flags & DRCONF_MEM_ASSIGNED) &&
+ (!(new_lmb->flags & DRCONF_MEM_ASSIGNED))) {
rc = pseries_remove_memblock(
- be64_to_cpu(old_drmem[i].base_addr),
- memblock_size);
+ old_lmb->base_addr, memblock_size);
break;
- } else if ((!(be32_to_cpu(old_drmem[i].flags) &
- DRCONF_MEM_ASSIGNED)) &&
- (be32_to_cpu(new_drmem[i].flags) &
- DRCONF_MEM_ASSIGNED)) {
- rc = memblock_add(be64_to_cpu(old_drmem[i].base_addr),
- memblock_size);
+ } else if ((!(old_lmb->flags & DRCONF_MEM_ASSIGNED)) &&
+ (new_lmb->flags & DRCONF_MEM_ASSIGNED)) {
+ rc = memblock_add(old_lmb->base_addr,
+ memblock_size);
rc = (rc < 0) ? -EINVAL : 0;
break;
+ } else if ((old_lmb->aa_index != new_lmb->aa_index) &&
+ (new_lmb->flags & DRCONF_MEM_ASSIGNED)) {
+ dlpar_queue_action(PSERIES_HP_ELOG_RESOURCE_MEM,
+ PSERIES_HP_ELOG_ACTION_READD,
+ new_lmb->drc_index);
}
}
return rc;
}
+static void pseries_update_ala_memory_aai(int aa_index)
+{
+ struct drmem_lmb *lmb;
+
+ /* Readd all LMBs which were previously using the
+ * specified aa_index value.
+ */
+ for_each_drmem_lmb(lmb) {
+ if ((lmb->aa_index == aa_index) &&
+ (lmb->flags & DRCONF_MEM_ASSIGNED)) {
+ dlpar_queue_action(PSERIES_HP_ELOG_RESOURCE_MEM,
+ PSERIES_HP_ELOG_ACTION_READD,
+ lmb->drc_index);
+ }
+ }
+}
+
+struct assoc_arrays {
+ u32 n_arrays;
+ u32 array_sz;
+ const __be32 *arrays;
+};
+
+static int pseries_update_ala_memory(struct of_reconfig_data *pr)
+{
+ struct assoc_arrays new_ala, old_ala;
+ __be32 *p;
+ int i, lim;
+
+ if (rtas_hp_event)
+ return 0;
+
+ /*
+ * The layout of the ibm,associativity-lookup-arrays
+ * property is a number N indicating the number of
+ * associativity arrays, followed by a number M
+ * indicating the size of each associativity array,
+ * followed by a list of N associativity arrays.
+ */
+
+ p = (__be32 *) pr->old_prop->value;
+ if (!p)
+ return -EINVAL;
+ old_ala.n_arrays = of_read_number(p++, 1);
+ old_ala.array_sz = of_read_number(p++, 1);
+ old_ala.arrays = p;
+
+ p = (__be32 *) pr->prop->value;
+ if (!p)
+ return -EINVAL;
+ new_ala.n_arrays = of_read_number(p++, 1);
+ new_ala.array_sz = of_read_number(p++, 1);
+ new_ala.arrays = p;
+
+ lim = (new_ala.n_arrays > old_ala.n_arrays) ? old_ala.n_arrays :
+ new_ala.n_arrays;
+
+ if (old_ala.array_sz == new_ala.array_sz) {
+
+ /* Reset any entries where the old and new rows
+ * the array have changed.
+ */
+ for (i = 0; i < lim; i++) {
+ int index = (i * new_ala.array_sz);
+
+ if (!memcmp(&old_ala.arrays[index],
+ &new_ala.arrays[index],
+ new_ala.array_sz))
+ continue;
+
+ pseries_update_ala_memory_aai(i);
+ }
+
+ /* Reset any entries representing the extra rows.
+ * There shouldn't be any, but just in case ...
+ */
+ for (i = lim; i < new_ala.n_arrays; i++)
+ pseries_update_ala_memory_aai(i);
+
+ } else {
+ /* Update all entries representing these rows;
+ * as all rows have different sizes, none can
+ * have equivalent values.
+ */
+ for (i = 0; i < lim; i++)
+ pseries_update_ala_memory_aai(i);
+ }
+
+ return 0;
+}
+
static int pseries_memory_notifier(struct notifier_block *nb,
unsigned long action, void *data)
{
@@ -1059,8 +1139,17 @@ static int pseries_memory_notifier(struct notifier_block *nb,
err = pseries_remove_mem_node(rd->dn);
break;
case OF_RECONFIG_UPDATE_PROPERTY:
- if (!strcmp(rd->prop->name, "ibm,dynamic-memory"))
- err = pseries_update_drconf_memory(rd);
+ if (!strcmp(rd->prop->name, "ibm,dynamic-memory") ||
+ !strcmp(rd->prop->name, "ibm,dynamic-memory-v2")) {
+ struct drmem_lmb_info *dinfo =
+ drmem_lmbs_init(rd->prop);
+ if (!dinfo)
+ return -EINVAL;
+ err = pseries_update_drconf_memory(dinfo);
+ drmem_lmbs_free(dinfo);
+ } else if (!strcmp(rd->prop->name,
+ "ibm,associativity-lookup-arrays"))
+ err = pseries_update_ala_memory(rd);
break;
}
return notifier_from_errno(err);
^ permalink raw reply related
* Re: [PATCH bpf v2 6/6] bpf: fix JITed dump for multi-function programs via syscall
From: Sandipan Das @ 2018-05-21 19:42 UTC (permalink / raw)
To: Daniel Borkmann
Cc: ast, netdev, linuxppc-dev, naveen.n.rao, mpe, jakub.kicinski
In-Reply-To: <654d4424-ad99-2b5e-dcbf-9e352aec75d6@iogearbox.net>
Hi Daniel,
On 05/18/2018 09:21 PM, Daniel Borkmann wrote:
> On 05/18/2018 02:50 PM, Sandipan Das wrote:
>> Currently, for multi-function programs, we cannot get the JITed
>> instructions using the bpf system call's BPF_OBJ_GET_INFO_BY_FD
>> command. Because of this, userspace tools such as bpftool fail
>> to identify a multi-function program as being JITed or not.
>>
>> With the JIT enabled and the test program running, this can be
>> verified as follows:
>>
>> # cat /proc/sys/net/core/bpf_jit_enable
>> 1
>>
>> Before applying this patch:
>>
>> # bpftool prog list
>> 1: kprobe name foo tag b811aab41a39ad3d gpl
>> loaded_at 2018-05-16T11:43:38+0530 uid 0
>> xlated 216B not jited memlock 65536B
>> ...
>>
>> # bpftool prog dump jited id 1
>> no instructions returned
>>
>> After applying this patch:
>>
>> # bpftool prog list
>> 1: kprobe name foo tag b811aab41a39ad3d gpl
>> loaded_at 2018-05-16T12:13:01+0530 uid 0
>> xlated 216B jited 308B memlock 65536B
>> ...
>
> That's really nice! One comment inline below:
>
>> # bpftool prog dump jited id 1
>> 0: nop
>> 4: nop
>> 8: mflr r0
>> c: std r0,16(r1)
>> 10: stdu r1,-112(r1)
>> 14: std r31,104(r1)
>> 18: addi r31,r1,48
>> 1c: li r3,10
>> ...
>>
>> Signed-off-by: Sandipan Das <sandipan@linux.vnet.ibm.com>
>> ---
>> kernel/bpf/syscall.c | 38 ++++++++++++++++++++++++++++++++------
>> 1 file changed, 32 insertions(+), 6 deletions(-)
>>
>> diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
>> index 54a72fafe57c..2430d159078c 100644
>> --- a/kernel/bpf/syscall.c
>> +++ b/kernel/bpf/syscall.c
>> @@ -1896,7 +1896,7 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
>> struct bpf_prog_info info = {};
>> u32 info_len = attr->info.info_len;
>> char __user *uinsns;
>> - u32 ulen;
>> + u32 ulen, i;
>> int err;
>>
>> err = check_uarg_tail_zero(uinfo, sizeof(info), info_len);
>> @@ -1922,7 +1922,6 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
>> ulen = min_t(u32, info.nr_map_ids, ulen);
>> if (ulen) {
>> u32 __user *user_map_ids = u64_to_user_ptr(info.map_ids);
>> - u32 i;
>>
>> for (i = 0; i < ulen; i++)
>> if (put_user(prog->aux->used_maps[i]->id,
>> @@ -1970,13 +1969,41 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
>> * for offload.
>> */
>> ulen = info.jited_prog_len;
>> - info.jited_prog_len = prog->jited_len;
>> + if (prog->aux->func_cnt) {
>> + info.jited_prog_len = 0;
>> + for (i = 0; i < prog->aux->func_cnt; i++)
>> + info.jited_prog_len += prog->aux->func[i]->jited_len;
>> + } else {
>> + info.jited_prog_len = prog->jited_len;
>> + }
>> +
>> if (info.jited_prog_len && ulen) {
>> if (bpf_dump_raw_ok()) {
>> uinsns = u64_to_user_ptr(info.jited_prog_insns);
>> ulen = min_t(u32, info.jited_prog_len, ulen);
>> - if (copy_to_user(uinsns, prog->bpf_func, ulen))
>> - return -EFAULT;
>> +
>> + /* for multi-function programs, copy the JITed
>> + * instructions for all the functions
>> + */
>> + if (prog->aux->func_cnt) {
>> + u32 len, free;
>> + u8 *img;
>> +
>> + free = ulen;
>> + for (i = 0; i < prog->aux->func_cnt; i++) {
>> + len = prog->aux->func[i]->jited_len;
>> + img = (u8 *) prog->aux->func[i]->bpf_func;
>> + if (len > free)
>> + break;
>> + if (copy_to_user(uinsns, img, len))
>> + return -EFAULT;
>> + uinsns += len;
>> + free -= len;
>
> Is there any way we can introduce a delimiter between the different
> images such that they could be more easily correlated with the call
> from the main (or other sub-)program instead of having one contiguous
> dump blob?
>
Can we have another member in bpf_prog_info that points to a list of the lengths of the
JITed images for each subprogram? We can use this information to split up the dump.
- Sandipan
>> + }
>> + } else {
>> + if (copy_to_user(uinsns, prog->bpf_func, ulen))
>> + return -EFAULT;
>> + }
>> } else {
>> info.jited_prog_insns = 0;
>> }
>> @@ -1987,7 +2014,6 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
>> if (info.nr_jited_ksyms && ulen) {
>> u64 __user *user_jited_ksyms = u64_to_user_ptr(info.jited_ksyms);
>> ulong ksym_addr;
>> - u32 i;
>>
>> /* copy the address of the kernel symbol corresponding to
>> * each function
>>
>
>
^ permalink raw reply
* Re: [PATCH v2] powerpc/64s/radix: do not flush TLB when relaxing access
From: kbuild test robot @ 2018-05-21 22:34 UTC (permalink / raw)
To: Nicholas Piggin; +Cc: kbuild-all, linuxppc-dev, Nicholas Piggin
In-Reply-To: <20180520122857.24766-1-npiggin@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 3180 bytes --]
Hi Nicholas,
I love your patch! Yet something to improve:
[auto build test ERROR on v4.17-rc6]
[cannot apply to powerpc/next next-20180517]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Nicholas-Piggin/powerpc-64s-radix-do-not-flush-TLB-when-relaxing-access/20180522-024317
config: powerpc-bamboo_defconfig (attached as .config)
compiler: powerpc-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=powerpc
All errors (new ones prefixed by >>):
arch/powerpc/mm/pgtable.c: In function 'ptep_set_access_flags':
>> arch/powerpc/mm/pgtable.c:246:32: error: 'mm_context_t {aka struct <anonymous>}' has no member named 'copros'
if (atomic_read(&mm->context.copros) > 0)
^
vim +246 arch/powerpc/mm/pgtable.c
209
210 /*
211 * This is called when relaxing access to a PTE. It's also called in the page
212 * fault path when we don't hit any of the major fault cases, ie, a minor
213 * update of _PAGE_ACCESSED, _PAGE_DIRTY, etc... The generic code will have
214 * handled those two for us, we additionally deal with missing execute
215 * permission here on some processors
216 */
217 int ptep_set_access_flags(struct vm_area_struct *vma, unsigned long address,
218 pte_t *ptep, pte_t entry, int dirty)
219 {
220 struct mm_struct *mm = vma->vm_mm;
221 int changed;
222
223 entry = set_access_flags_filter(entry, vma, dirty);
224 changed = !pte_same(*(ptep), entry);
225 if (changed) {
226 if (!is_vm_hugetlb_page(vma))
227 assert_pte_locked(mm, address);
228 __ptep_set_access_flags(mm, ptep, entry, address);
229 if (IS_ENABLED(CONFIG_PPC_BOOK3S_64)) {
230 /*
231 * Book3S does not require a TLB flush when relaxing
232 * access restrictions because the core MMU will reload
233 * the pte after taking an access fault. However the
234 * NMMU on POWER9 does not re-load the pte, so flush
235 * if we have a coprocessor attached to this address
236 * space.
237 *
238 * This could be further refined and pushed out to
239 * NMMU drivers so TLBIEs are only done for NMMU
240 * faults, but this is a more minimal fix. The NMMU
241 * fault handler does a get_user_pages_remote or
242 * similar to bring the page tables in, and this
243 * flush_tlb_page will do a global TLBIE because the
244 * coprocessor is attached to the address space.
245 */
> 246 if (atomic_read(&mm->context.copros) > 0)
247 flush_tlb_page(vma, address);
248 } else {
249 flush_tlb_page(vma, address);
250 }
251 }
252 return changed;
253 }
254
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 10986 bytes --]
^ permalink raw reply
* Re: [PATCH ] powerpc/pkeys: Detach execute_only key on !PROT_EXEC
From: Thiago Jung Bauermann @ 2018-05-22 1:42 UTC (permalink / raw)
To: Ram Pai
Cc: mpe, linuxppc-dev, benh, paulus, aneesh.kumar, bsingharora, hbabu,
mhocko, bauerman, msuchanek, Ulrich.Weigand, dave.hansen,
Shakeel Butt
In-Reply-To: <1525464111-1096-1-git-send-email-linuxram@us.ibm.com>
Ram Pai <linuxram@us.ibm.com> writes:
> Disassociate the exec_key from a VMA if the VMA permission is not
> PROT_EXEC anymore. Otherwise the exec_only key continues to be
> associated with the vma, causing unexpected behavior.
>
> The problem was reported on x86 by Shakeel Butt,
> which is also applicable on powerpc.
>
> cc: Shakeel Butt <shakeelb@google.com>
> Reported-by: Shakeel Butt <shakeelb@google.com>
> Fixes 5586cf6 ("powerpc: introduce execute-only pkey")
^
Missing a colon here.
> Signed-off-by: Ram Pai <linuxram@us.ibm.com>
> ---
> arch/powerpc/mm/pkeys.c | 4 ++--
> 1 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/arch/powerpc/mm/pkeys.c b/arch/powerpc/mm/pkeys.c
> index e81d59e..fdeb9f5 100644
> --- a/arch/powerpc/mm/pkeys.c
> +++ b/arch/powerpc/mm/pkeys.c
> @@ -425,9 +425,9 @@ int __arch_override_mprotect_pkey(struct vm_area_struct *vma, int prot,
> {
> /*
> * If the currently associated pkey is execute-only, but the requested
> - * protection requires read or write, move it back to the default pkey.
> + * protection is not execute-only, move it back to the default pkey.
> */
> - if (vma_is_pkey_exec_only(vma) && (prot & (PROT_READ | PROT_WRITE)))
> + if (vma_is_pkey_exec_only(vma) && (prot != PROT_EXEC))
> return 0;
>
> /*
I think I'm slow today. It took me a while to figure out why this is
buggy. It will leave the VMA with the execute-only pkey if prot = 0.
Other bit combinations work fine IIUC.
Reviewed-by: Thiago Jung Bauermann <bauerman@linux.ibm.com>
--
Thiago Jung Bauermann
IBM Linux Technology Center
^ permalink raw reply
* Re: [PATCH 1/2] powerpc: Detect the presence of big-core with interleaved threads
From: Gautham R Shenoy @ 2018-05-22 4:31 UTC (permalink / raw)
To: Michael Ellerman
Cc: Gautham R Shenoy, Michael Neuling, Benjamin Herrenschmidt,
Vaidyanathan Srinivasan, Akshay Adiga, Shilpasri G Bhat,
Balbir Singh, Oliver O'Halloran, Nicholas Piggin,
linuxppc-dev, linux-kernel
In-Reply-To: <87k1s1xg0z.fsf@concordia.ellerman.id.au>
Hello Michael,
On Fri, May 18, 2018 at 11:14:04PM +1000, Michael Ellerman wrote:
> Gautham R Shenoy <ego@linux.vnet.ibm.com> writes:
> ...
> >> > @@ -565,7 +615,16 @@ void __init smp_setup_cpu_maps(void)
> >> > vdso_data->processorCount = num_present_cpus();
> >> > #endif /* CONFIG_PPC64 */
> >> >
> >> > - /* Initialize CPU <=> thread mapping/
> >> > + dn = of_find_node_by_type(NULL, "cpu");
> >> > + if (dn) {
> >> > + if (check_for_interleaved_big_core(dn)) {
> >> > + has_interleaved_big_core = true;
> >> > + pr_info("Detected interleaved big-cores\n");
> >>
> >> Is there a runtime way to check this also? If the dmesg buffer overflows, we
> >> lose this.
> >
> > Where do you suggest we put this ? Should it be a part of
> > /proc/cpuinfo ?
>
> Hmm, it'd be nice not to pollute it with more junk.
>
> Can you just look at the pir files in sysfs?
Sure Michael. I will explore this option.
If we add a file called l1cache_thread_group, then the siblings of the
big-core that share the L1-cache can be described as follows.
# cd /sys/devices/system/cpu
# grep . cpu[0-7]/l1cache_thread_group
cpu0/l1cache_thread_group:0,2,4,6
cpu1/l1cache_thread_group:1,3,5,7
cpu2/l1cache_thread_group:0,2,4,6
cpu3/l1cache_thread_group:1,3,5,7
cpu4/l1cache_thread_group:0,2,4,6
cpu5/l1cache_thread_group:1,3,5,7
cpu6/l1cache_thread_group:0,2,4,6
cpu7/l1cache_thread_group:1,3,5,7
>
> eg. on a normal system:
>
> # cd /sys/devices/system/cpu
> # grep . cpu[0-7]/pir
> cpu0/pir:20
> cpu1/pir:21
> cpu2/pir:22
> cpu3/pir:23
> cpu4/pir:24
> cpu5/pir:25
> cpu6/pir:26
> cpu7/pir:27
>
>
> cheers
>
^ permalink raw reply
* Re: [PATCH 1/2] powerpc: Detect the presence of big-core with interleaved threads
From: Gautham R Shenoy @ 2018-05-22 4:34 UTC (permalink / raw)
To: Michael Ellerman
Cc: Gautham R. Shenoy, Benjamin Herrenschmidt, Michael Neuling,
Vaidyanathan Srinivasan, Akshay Adiga, Shilpasri G Bhat,
Balbir Singh, Oliver O'Halloran, Nicholas Piggin,
linuxppc-dev, linux-kernel
In-Reply-To: <87h8n5xfot.fsf@concordia.ellerman.id.au>
Hello Michael,
On Fri, May 18, 2018 at 11:21:22PM +1000, Michael Ellerman wrote:
> "Gautham R. Shenoy" <ego@linux.vnet.ibm.com> writes:
>
> > diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
> > index 0af5c11..884dff2 100644
> > --- a/arch/powerpc/kernel/setup-common.c
> > +++ b/arch/powerpc/kernel/setup-common.c
> > @@ -436,8 +438,56 @@ static void __init cpu_init_thread_core_maps(int tpc)
> > printk(KERN_DEBUG " (thread shift is %d)\n", threads_shift);
> > }
> >
> > -
> > u32 *cpu_to_phys_id = NULL;
> > +/*
> > + * check_for_interleaved_big_core - Checks if the core represented by
> > + * dn is a big-core whose threads are interleavings of the
> > + * threads of the component small cores.
> > + *
> > + * @dn: device node corresponding to the core.
> > + *
> > + * Returns true if the core is a interleaved big-core.
> > + * Returns false otherwise.
> > + */
> > +static inline bool check_for_interleaved_big_core(struct device_node *dn)
> > +{
> > + int len, nr_groups, threads_per_group;
> > + const __be32 *thread_groups;
> > + __be32 *thread_list, *first_cpu_idx;
> > + int cur_cpu, next_cpu, i, j;
> > +
> > + thread_groups = of_get_property(dn, "ibm,thread-groups", &len);
> > + if (!thread_groups)
> > + return false;
>
> There are better device tree APIs than bare of_get_property() these
> days, can you try to use those?
Ok, I will use them.
>
> > + nr_groups = be32_to_cpu(*(thread_groups + 1));
> > + if (nr_groups <= 1)
> > + return false;
>
> eg. this would be of_property_read_u32_index()
>
Ok.
> > @@ -565,7 +615,16 @@ void __init smp_setup_cpu_maps(void)
> > vdso_data->processorCount = num_present_cpus();
> > #endif /* CONFIG_PPC64 */
> >
> > - /* Initialize CPU <=> thread mapping/
> > + dn = of_find_node_by_type(NULL, "cpu");
> > + if (dn) {
> > + if (check_for_interleaved_big_core(dn)) {
> > + has_interleaved_big_core = true;
> > + pr_info("Detected interleaved big-cores\n");
> > + }
> > + of_node_put(dn);
> > + }
>
> This is a bit untidy, given how unlikely it is that you would have no
> CPUs :)
This can actually go into the earlier loop where we initialize the
smp_processor_ids(). I have fixed it in the next iteration.
>
> You should be able to do the lookup of the property and the setting of
> has_interleaved_big_core all inside
> check_for_interleaved_big_core().
Yes, that's what I am doing in the next iteration.
>
> cheers
>
^ permalink raw reply
* [PATCH v2] powerpc/32: Implement csum_ipv6_magic in assembly
From: Christophe Leroy @ 2018-05-22 5:33 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
Cc: linux-kernel, linuxppc-dev
The generic csum_ipv6_magic() generates a pretty bad result
00000000 <csum_ipv6_magic>:
0: 81 23 00 00 lwz r9,0(r3)
4: 81 03 00 04 lwz r8,4(r3)
8: 7c e7 4a 14 add r7,r7,r9
c: 7d 29 38 10 subfc r9,r9,r7
10: 7d 4a 51 10 subfe r10,r10,r10
14: 7d 27 42 14 add r9,r7,r8
18: 7d 2a 48 50 subf r9,r10,r9
1c: 80 e3 00 08 lwz r7,8(r3)
20: 7d 08 48 10 subfc r8,r8,r9
24: 7d 4a 51 10 subfe r10,r10,r10
28: 7d 29 3a 14 add r9,r9,r7
2c: 81 03 00 0c lwz r8,12(r3)
30: 7d 2a 48 50 subf r9,r10,r9
34: 7c e7 48 10 subfc r7,r7,r9
38: 7d 4a 51 10 subfe r10,r10,r10
3c: 7d 29 42 14 add r9,r9,r8
40: 7d 2a 48 50 subf r9,r10,r9
44: 80 e4 00 00 lwz r7,0(r4)
48: 7d 08 48 10 subfc r8,r8,r9
4c: 7d 4a 51 10 subfe r10,r10,r10
50: 7d 29 3a 14 add r9,r9,r7
54: 7d 2a 48 50 subf r9,r10,r9
58: 81 04 00 04 lwz r8,4(r4)
5c: 7c e7 48 10 subfc r7,r7,r9
60: 7d 4a 51 10 subfe r10,r10,r10
64: 7d 29 42 14 add r9,r9,r8
68: 7d 2a 48 50 subf r9,r10,r9
6c: 80 e4 00 08 lwz r7,8(r4)
70: 7d 08 48 10 subfc r8,r8,r9
74: 7d 4a 51 10 subfe r10,r10,r10
78: 7d 29 3a 14 add r9,r9,r7
7c: 7d 2a 48 50 subf r9,r10,r9
80: 81 04 00 0c lwz r8,12(r4)
84: 7c e7 48 10 subfc r7,r7,r9
88: 7d 4a 51 10 subfe r10,r10,r10
8c: 7d 29 42 14 add r9,r9,r8
90: 7d 2a 48 50 subf r9,r10,r9
94: 7d 08 48 10 subfc r8,r8,r9
98: 7d 4a 51 10 subfe r10,r10,r10
9c: 7d 29 2a 14 add r9,r9,r5
a0: 7d 2a 48 50 subf r9,r10,r9
a4: 7c a5 48 10 subfc r5,r5,r9
a8: 7c 63 19 10 subfe r3,r3,r3
ac: 7d 29 32 14 add r9,r9,r6
b0: 7d 23 48 50 subf r9,r3,r9
b4: 7c c6 48 10 subfc r6,r6,r9
b8: 7c 63 19 10 subfe r3,r3,r3
bc: 7c 63 48 50 subf r3,r3,r9
c0: 54 6a 80 3e rotlwi r10,r3,16
c4: 7c 63 52 14 add r3,r3,r10
c8: 7c 63 18 f8 not r3,r3
cc: 54 63 84 3e rlwinm r3,r3,16,16,31
d0: 4e 80 00 20 blr
This patch implements it in assembly for PPC32
Link: https://github.com/linuxppc/linux/issues/9
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
v2: Fix number of args in final addze
arch/powerpc/include/asm/checksum.h | 8 ++++++++
arch/powerpc/lib/checksum_32.S | 33 +++++++++++++++++++++++++++++++++
2 files changed, 41 insertions(+)
diff --git a/arch/powerpc/include/asm/checksum.h b/arch/powerpc/include/asm/checksum.h
index 54065caa40b3..c41c280c252f 100644
--- a/arch/powerpc/include/asm/checksum.h
+++ b/arch/powerpc/include/asm/checksum.h
@@ -13,6 +13,7 @@
#include <asm-generic/checksum.h>
#else
#include <linux/bitops.h>
+#include <linux/in6.h>
/*
* Computes the checksum of a memory block at src, length len,
* and adds in "sum" (32-bit), while copying the block to dst.
@@ -211,6 +212,13 @@ static inline __sum16 ip_compute_csum(const void *buff, int len)
return csum_fold(csum_partial(buff, len, 0));
}
+#ifdef CONFIG_PPC32
+#define _HAVE_ARCH_IPV6_CSUM
+__sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+ const struct in6_addr *daddr,
+ __u32 len, __u8 proto, __wsum sum);
+#endif
+
#endif
#endif /* __KERNEL__ */
#endif
diff --git a/arch/powerpc/lib/checksum_32.S b/arch/powerpc/lib/checksum_32.S
index 9a671c774b22..9167ab088f04 100644
--- a/arch/powerpc/lib/checksum_32.S
+++ b/arch/powerpc/lib/checksum_32.S
@@ -293,3 +293,36 @@ dst_error:
EX_TABLE(51b, dst_error);
EXPORT_SYMBOL(csum_partial_copy_generic)
+
+/*
+ * static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+ * const struct in6_addr *daddr,
+ * __u32 len, __u8 proto, __wsum sum)
+ */
+
+_GLOBAL(csum_ipv6_magic)
+ lwz r8, 0(r3)
+ lwz r9, 4(r3)
+ lwz r10, 8(r3)
+ lwz r11, 12(r3)
+ addc r0, r5, r6
+ adde r0, r0, r7
+ adde r0, r0, r8
+ adde r0, r0, r9
+ adde r0, r0, r10
+ adde r0, r0, r11
+ lwz r8, 0(r4)
+ lwz r9, 4(r4)
+ lwz r10, 8(r4)
+ lwz r11, 12(r4)
+ adde r0, r0, r8
+ adde r0, r0, r9
+ adde r0, r0, r10
+ adde r0, r0, r11
+ addze r0, r0
+ rotlwi r3, r0, 16
+ add r3, r0, r3
+ not r3, r3
+ rlwinm r3, r3, 16, 16, 31
+ blr
+EXPORT_SYMBOL(csum_ipv6_magic)
--
2.13.3
^ permalink raw reply related
* [PATCH] selftests/powerpc: Add missing .gitignores
From: Michael Neuling @ 2018-05-22 6:13 UTC (permalink / raw)
To: mpe; +Cc: linuxppc-dev, mikey
Signed-off-by: Michael Neuling <mikey@neuling.org>
---
tools/testing/selftests/powerpc/alignment/.gitignore | 1 +
tools/testing/selftests/powerpc/tm/.gitignore | 1 +
2 files changed, 2 insertions(+)
diff --git a/tools/testing/selftests/powerpc/alignment/.gitignore b/tools/testing/selftests/powerpc/alignment/.gitignore
index 1d980e3d70..9d383073b7 100644
--- a/tools/testing/selftests/powerpc/alignment/.gitignore
+++ b/tools/testing/selftests/powerpc/alignment/.gitignore
@@ -3,3 +3,4 @@ copy_first_unaligned
paste_unaligned
paste_last_unaligned
copy_paste_unaligned_common
+alignment_handler
diff --git a/tools/testing/selftests/powerpc/tm/.gitignore b/tools/testing/selftests/powerpc/tm/.gitignore
index bb90d4b795..c3ee8393da 100644
--- a/tools/testing/selftests/powerpc/tm/.gitignore
+++ b/tools/testing/selftests/powerpc/tm/.gitignore
@@ -14,3 +14,4 @@ tm-signal-context-chk-vsx
tm-vmx-unavail
tm-unavailable
tm-trap
+tm-sigreturn
--
2.17.0
^ permalink raw reply related
* [PATCH 1/2] selftests/powerpc: Add ptrace hw breakpoint test
From: Michael Neuling @ 2018-05-22 6:14 UTC (permalink / raw)
To: mpe; +Cc: linuxppc-dev, mikey
This test the ptrace hw breakpoints via PTRACE_SET_DEBUGREG and
PPC_PTRACE_SETHWDEBUG. This test was use to find the bugs fixed by
these recent commits:
4f7c06e26e powerpc/ptrace: Fix setting 512B aligned breakpoints with PTRACE_SET_DEBUGREG
cd6ef7eebf powerpc/ptrace: Fix enforcement of DAWR constraints
Signed-off-by: Michael Neuling <mikey@neuling.org>
---
This test (and the next) could be expanded to do a bunch more but it's
been sitting out of tree too long, so trying to get them upstream.
---
.../selftests/powerpc/ptrace/.gitignore | 1 +
.../testing/selftests/powerpc/ptrace/Makefile | 2 +-
.../selftests/powerpc/ptrace/ptrace-hwbreak.c | 341 ++++++++++++++++++
3 files changed, 343 insertions(+), 1 deletion(-)
create mode 100644 tools/testing/selftests/powerpc/ptrace/ptrace-hwbreak.c
diff --git a/tools/testing/selftests/powerpc/ptrace/.gitignore b/tools/testing/selftests/powerpc/ptrace/.gitignore
index 349acfafc9..9dcc16ea81 100644
--- a/tools/testing/selftests/powerpc/ptrace/.gitignore
+++ b/tools/testing/selftests/powerpc/ptrace/.gitignore
@@ -8,3 +8,4 @@ ptrace-vsx
ptrace-tm-vsx
ptrace-tm-spd-vsx
ptrace-tm-spr
+ptrace-hwbreak
diff --git a/tools/testing/selftests/powerpc/ptrace/Makefile b/tools/testing/selftests/powerpc/ptrace/Makefile
index 4803052665..0e2f4601d1 100644
--- a/tools/testing/selftests/powerpc/ptrace/Makefile
+++ b/tools/testing/selftests/powerpc/ptrace/Makefile
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
TEST_PROGS := ptrace-gpr ptrace-tm-gpr ptrace-tm-spd-gpr \
ptrace-tar ptrace-tm-tar ptrace-tm-spd-tar ptrace-vsx ptrace-tm-vsx \
- ptrace-tm-spd-vsx ptrace-tm-spr
+ ptrace-tm-spd-vsx ptrace-tm-spr ptrace-hwbreak
include ../../lib.mk
diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-hwbreak.c b/tools/testing/selftests/powerpc/ptrace/ptrace-hwbreak.c
new file mode 100644
index 0000000000..792cdea266
--- /dev/null
+++ b/tools/testing/selftests/powerpc/ptrace/ptrace-hwbreak.c
@@ -0,0 +1,341 @@
+/*
+ * Ptrace test for hw breakpoints
+ *
+ * Based on tools/testing/selftests/breakpoints/breakpoint_test.c
+ *
+ * This test forks and the parent then traces the child doing various
+ * types of ptrace enabled breakpoints
+ *
+ * Copyright (C) 2018 Michael Neuling, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <sys/ptrace.h>
+#include <unistd.h>
+#include <stddef.h>
+#include <sys/user.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include "ptrace.h"
+
+/* Breakpoint access modes */
+enum {
+ BP_X = 1,
+ BP_RW = 2,
+ BP_W = 4,
+};
+
+static pid_t child_pid;
+static struct ppc_debug_info dbginfo;
+
+static void get_dbginfo(void)
+{
+ int ret;
+
+ ret = ptrace(PPC_PTRACE_GETHWDBGINFO, child_pid, NULL, &dbginfo);
+ if (ret) {
+ perror("Can't get breakpoint info\n");
+ exit(-1);
+ }
+}
+
+static bool hwbreak_present(void)
+{
+ return (dbginfo.num_data_bps != 0);
+}
+
+static bool dawr_present(void)
+{
+ return !!(dbginfo.features & PPC_DEBUG_FEATURE_DATA_BP_DAWR);
+}
+
+static void set_breakpoint_addr(void *addr)
+{
+ int ret;
+
+ ret = ptrace(PTRACE_SET_DEBUGREG, child_pid, 0, addr);
+ if (ret) {
+ perror("Can't set breakpoint addr\n");
+ exit(-1);
+ }
+}
+
+static int set_hwbreakpoint_addr(void *addr, int range)
+{
+ int ret;
+
+ struct ppc_hw_breakpoint info;
+
+ info.version = 1;
+ info.trigger_type = PPC_BREAKPOINT_TRIGGER_RW;
+ info.addr_mode = PPC_BREAKPOINT_MODE_EXACT;
+ if (range > 0)
+ info.addr_mode = PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE;
+ info.condition_mode = PPC_BREAKPOINT_CONDITION_NONE;
+ info.addr = (__u64)addr;
+ info.addr2 = (__u64)addr + range;
+ info.condition_value = 0;
+
+ ret = ptrace(PPC_PTRACE_SETHWDEBUG, child_pid, 0, &info);
+ if (ret < 0) {
+ perror("Can't set breakpoint\n");
+ exit(-1);
+ }
+ return ret;
+}
+
+static int del_hwbreakpoint_addr(int watchpoint_handle)
+{
+ int ret;
+
+ ret = ptrace(PPC_PTRACE_DELHWDEBUG, child_pid, 0, watchpoint_handle);
+ if (ret < 0) {
+ perror("Can't delete hw breakpoint\n");
+ exit(-1);
+ }
+ return ret;
+}
+
+#define DAWR_LENGTH_MAX 512
+
+/* Dummy variables to test read/write accesses */
+static unsigned long long dummy_array[DAWR_LENGTH_MAX/sizeof(unsigned long long)] __attribute__ ((aligned (512)));
+static unsigned long long *dummy_var = dummy_array;
+
+static void write_var(int len)
+{
+ char *pcval; short *psval; int *pival; long long *plval;
+
+ switch (len) {
+ case 1:
+ pcval = (char *)dummy_var;
+ *pcval = 0xff;
+ break;
+ case 2:
+ psval = (short *)dummy_var;
+ *psval = 0xffff;
+ break;
+ case 4:
+ pival = (int *)dummy_var;
+ *pival = 0xffffffff;
+ break;
+ case 8:
+ plval = (long long *)dummy_var;
+ *plval = 0xffffffffffffffffLL;
+ break;
+ }
+}
+
+static void read_var(int len)
+{
+ char cval __attribute__((unused));
+ short sval __attribute__((unused));
+ int ival __attribute__((unused));
+ long long lval __attribute__((unused));
+
+ switch (len) {
+ case 1:
+ cval = *(char *)dummy_var;
+ break;
+ case 2:
+ sval = *(short *)dummy_var;
+ break;
+ case 4:
+ ival = *(int *)dummy_var;
+ break;
+ case 8:
+ lval = *(long long *)dummy_var;
+ break;
+ }
+}
+
+/*
+ * Do the r/w accesses to trigger the breakpoints. And run
+ * the usual traps.
+ */
+static void trigger_tests(void)
+{
+ int len, ret;
+
+ ret = ptrace(PTRACE_TRACEME, 0, NULL, 0);
+ if (ret) {
+ perror("Can't be traced?\n");
+ return;
+ }
+
+ /* Wake up father so that it sets up the first test */
+ kill(getpid(), SIGUSR1);
+
+ /* Test write watchpoints */
+ for (len = 1; len <= sizeof(long); len <<= 1)
+ write_var(len);
+
+ /* Test read/write watchpoints (on read accesses) */
+ for (len = 1; len <= sizeof(long); len <<= 1)
+ read_var(len);
+
+ /* Test when breakpoint is unset */
+
+ /* Test write watchpoints */
+ for (len = 1; len <= sizeof(long); len <<= 1)
+ write_var(len);
+
+ /* Test read/write watchpoints (on read accesses) */
+ for (len = 1; len <= sizeof(long); len <<= 1)
+ read_var(len);
+}
+
+static void check_success(const char *msg)
+{
+ const char *msg2;
+ int status;
+
+ /* Wait for the child to SIGTRAP */
+ wait(&status);
+
+ msg2 = "Failed";
+
+ if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
+ msg2 = "Child process hit the breakpoint";
+ }
+
+ printf("%s Result: [%s]\n", msg, msg2);
+}
+
+static void launch_watchpoints(char *buf, int mode, int len,
+ struct ppc_debug_info *dbginfo, bool dawr)
+{
+ const char *mode_str;
+ unsigned long data = (unsigned long)(dummy_var);
+ int wh, range;
+
+ data &= ~0x7UL;
+
+ if (mode == BP_W) {
+ data |= (1UL << 1);
+ mode_str = "write";
+ }
+ else {
+ data |= (1UL << 0);
+ data |= (1UL << 1);
+ mode_str = "read";
+ }
+
+ /* Set DABR_TRANSLATION bit */
+ data |= (1UL << 2);
+
+
+ /* use PTRACE_SET_DEBUGREG breakpoints */
+ set_breakpoint_addr((void *)data);
+ ptrace(PTRACE_CONT, child_pid, NULL, 0);
+ sprintf(buf, "Test %s watchpoint with len: %d ", mode_str, len);
+ check_success(buf);
+ /* Unregister hw brkpoint */
+ set_breakpoint_addr(NULL);
+
+ data = (data & ~7); /* remove dabr control bits */
+
+ /* use PPC_PTRACE_SETHWDEBUG breakpoint */
+ if (!(dbginfo->features & PPC_DEBUG_FEATURE_DATA_BP_RANGE))
+ return; /* not supported */
+ wh = set_hwbreakpoint_addr((void *)data, 0);
+ ptrace(PTRACE_CONT, child_pid, NULL, 0);
+ sprintf(buf, "Test %s watchpoint with len: %d ", mode_str, len);
+ check_success(buf);
+ /* Unregister hw brkpoint */
+ del_hwbreakpoint_addr(wh);
+
+ /* try a wider range */
+ range = 8;
+ if (dawr)
+ range = 512 - ((int)data & (DAWR_LENGTH_MAX - 1));
+ wh = set_hwbreakpoint_addr((void *)data, range);
+ ptrace(PTRACE_CONT, child_pid, NULL, 0);
+ sprintf(buf, "Test %s watchpoint with len: %d ", mode_str, len);
+ check_success(buf);
+ /* Unregister hw brkpoint */
+ del_hwbreakpoint_addr(wh);
+}
+
+/* Set the breakpoints and check the child successfully trigger them */
+static int launch_tests(bool dawr)
+{
+ char buf[1024];
+ int len, i, status;
+
+ struct ppc_debug_info dbginfo;
+
+ i = ptrace(PPC_PTRACE_GETHWDBGINFO, child_pid, NULL, &dbginfo);
+ if (i) {
+ perror("Can't set breakpoint info\n");
+ exit(-1);
+ }
+ if (!(dbginfo.features & PPC_DEBUG_FEATURE_DATA_BP_RANGE))
+ printf("WARNING: Kernel doesn't support PPC_PTRACE_SETHWDEBUG\n");
+
+ /* Write watchpoint */
+ for (len = 1; len <= sizeof(long); len <<= 1)
+ launch_watchpoints(buf, BP_W, len, &dbginfo, dawr);
+
+ /* Read-Write watchpoint */
+ for (len = 1; len <= sizeof(long); len <<= 1)
+ launch_watchpoints(buf, BP_RW, len, &dbginfo, dawr);
+
+ ptrace(PTRACE_CONT, child_pid, NULL, 0);
+
+ /* Now we have unregistered the breakpoint, access by child
+ * should not cause SIGTRAP
+ */
+
+ wait(&status);
+
+ if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
+ printf("FAIL: Child process hit the breakpoint, which is not expected\n");
+ ptrace(PTRACE_CONT, child_pid, NULL, 0);
+ return TEST_FAIL;
+ }
+
+ if (WIFEXITED(status))
+ printf("Child exited normally\n");
+
+ return TEST_PASS;
+}
+
+static int ptrace_hwbreak(void)
+{
+ pid_t pid;
+ int ret;
+ bool dawr;
+
+ pid = fork();
+ if (!pid) {
+ trigger_tests();
+ return 0;
+ }
+
+ wait(NULL);
+
+ child_pid = pid;
+
+ get_dbginfo();
+ SKIP_IF(!hwbreak_present());
+ dawr = dawr_present();
+
+ ret = launch_tests(dawr);
+
+ wait(NULL);
+
+ return ret;
+}
+
+int main(int argc, char **argv, char **envp)
+{
+ return test_harness(ptrace_hwbreak, "ptrace_hwbreak");
+}
--
2.17.0
^ permalink raw reply related
* [PATCH 2/2] selftests/powerpc: Add perf breakpoint test
From: Michael Neuling @ 2018-05-22 6:14 UTC (permalink / raw)
To: mpe; +Cc: linuxppc-dev, mikey
In-Reply-To: <20180522061428.5142-1-mikey@neuling.org>
This tests perf hardware breakpoints (ie PERF_TYPE_BREAKPOINT) on
powerpc.
Signed-off-by: Michael Neuling <mikey@neuling.org>
---
.../selftests/powerpc/ptrace/.gitignore | 1 +
.../testing/selftests/powerpc/ptrace/Makefile | 3 +-
.../selftests/powerpc/ptrace/perf-hwbreak.c | 214 ++++++++++++++++++
3 files changed, 217 insertions(+), 1 deletion(-)
create mode 100644 tools/testing/selftests/powerpc/ptrace/perf-hwbreak.c
diff --git a/tools/testing/selftests/powerpc/ptrace/.gitignore b/tools/testing/selftests/powerpc/ptrace/.gitignore
index 9dcc16ea81..07ec449a27 100644
--- a/tools/testing/selftests/powerpc/ptrace/.gitignore
+++ b/tools/testing/selftests/powerpc/ptrace/.gitignore
@@ -9,3 +9,4 @@ ptrace-tm-vsx
ptrace-tm-spd-vsx
ptrace-tm-spr
ptrace-hwbreak
+perf-hwbreak
diff --git a/tools/testing/selftests/powerpc/ptrace/Makefile b/tools/testing/selftests/powerpc/ptrace/Makefile
index 0e2f4601d1..532f5dda37 100644
--- a/tools/testing/selftests/powerpc/ptrace/Makefile
+++ b/tools/testing/selftests/powerpc/ptrace/Makefile
@@ -1,13 +1,14 @@
# SPDX-License-Identifier: GPL-2.0
TEST_PROGS := ptrace-gpr ptrace-tm-gpr ptrace-tm-spd-gpr \
ptrace-tar ptrace-tm-tar ptrace-tm-spd-tar ptrace-vsx ptrace-tm-vsx \
- ptrace-tm-spd-vsx ptrace-tm-spr ptrace-hwbreak
+ ptrace-tm-spd-vsx ptrace-tm-spr ptrace-hwbreak perf-hwbreak
include ../../lib.mk
all: $(TEST_PROGS)
CFLAGS += -m64 -I../../../../../usr/include -I../tm -mhtm -fno-pie
+LDLIBS += -lpthread
$(TEST_PROGS): ../harness.c ../utils.c ../lib/reg.S ptrace.h
diff --git a/tools/testing/selftests/powerpc/ptrace/perf-hwbreak.c b/tools/testing/selftests/powerpc/ptrace/perf-hwbreak.c
new file mode 100644
index 0000000000..4ab7059029
--- /dev/null
+++ b/tools/testing/selftests/powerpc/ptrace/perf-hwbreak.c
@@ -0,0 +1,214 @@
+/*
+ * perf events self profiling example test case for hw breakpoints.
+ *
+ * Start an number of threads. In each thread setup a breakpoint with
+ * a number of variables:
+ * 1) number of times we loop over it
+ * 2) read, write or read&write match
+ * 3) exclude userspace
+ * setup this breakpoint, then read and write the data a number of times.
+ * Then check the output count from perf is as expected.
+ *
+ * Based on:
+ * http://ozlabs.org/~anton/junkcode/perf_events_example1.c
+ *
+ * Copyright (C) 2018 Michael Neuling, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <unistd.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <pthread.h>
+#include <elf.h>
+#include <sys/syscall.h>
+#include <linux/perf_event.h>
+#include <linux/hw_breakpoint.h>
+#include "utils.h"
+
+int max_loops;
+int num_threads;
+int fail = 0;
+int arraytest;
+
+#define DAWR_LENGTH_MAX ((0x3f + 1) * 8)
+
+static inline int sys_perf_event_open(struct perf_event_attr *attr, pid_t pid,
+ int cpu, int group_fd,
+ unsigned long flags)
+{
+ attr->size = sizeof(*attr);
+ return syscall(__NR_perf_event_open, attr, pid, cpu, group_fd, flags);
+}
+
+static inline bool breakpoint_test(int len)
+{
+ struct perf_event_attr attr;
+ int fd;
+
+ /* setup counters */
+ memset(&attr, 0, sizeof(attr));
+ attr.disabled = 1;
+ attr.type = PERF_TYPE_BREAKPOINT;
+ attr.bp_type = HW_BREAKPOINT_R;
+ /* bp_addr can point anywhere but needs to be aligned */
+ attr.bp_addr = (__u64)(&attr) & 0xfffffffffffff800;
+ attr.bp_len = len;
+ fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
+ if (fd < 0)
+ return false;
+ close(fd);
+ return true;
+}
+
+static inline bool perf_breakpoint_supported(void)
+{
+ return breakpoint_test(4);
+}
+
+static inline bool dawr_supported(void)
+{
+ return breakpoint_test(DAWR_LENGTH_MAX);
+}
+
+/*
+ */
+static void *runtestsingle(void *vptr_args)
+{
+ int i,j;
+ struct perf_event_attr attr;
+ size_t res;
+ unsigned long long breaks, needed;
+ int readint; /* random stacks will give diff addr here */
+ int readintarraybig[2*DAWR_LENGTH_MAX/sizeof(int)];
+ int *readintalign;
+ volatile int *ptr;
+ int break_fd;
+ int loop_num = rand() % max_loops;
+ int readwriteflag = (rand() % 3) + 1; /* needs to be 1-3 */
+ int exclude_user = rand() % 2;
+ volatile int *k;
+
+ /* align to 0x400 boundary as required by DAWR */
+ readintalign = (int *)(((unsigned long)readintarraybig + 0x7ff) & 0xfffffffffffff800);
+
+ ptr = &readint;
+ if (arraytest)
+ ptr = &readintalign[0];
+
+ /* setup counters */
+ memset(&attr, 0, sizeof(attr));
+ attr.disabled = 1;
+ attr.type = PERF_TYPE_BREAKPOINT;
+ attr.bp_type = readwriteflag;
+ attr.bp_addr = (__u64)ptr;
+ attr.bp_len = sizeof(int);
+ if (arraytest)
+ attr.bp_len = DAWR_LENGTH_MAX;
+ attr.exclude_user = exclude_user;
+ break_fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
+ if (break_fd < 0) {
+ perror("sys_perf_event_open");
+ exit(1);
+ }
+
+ /* start counters */
+ ioctl(break_fd, PERF_EVENT_IOC_ENABLE);
+
+ /* Test a bunch of reads and writes */
+ k = &readint;
+ for (i = 0; i < loop_num; i++) {
+ if (arraytest)
+ k = &(readintalign[i % (DAWR_LENGTH_MAX/sizeof(int))]);
+
+ j = *k;
+ *k = j;
+ }
+
+ /* stop counters */
+ ioctl(break_fd, PERF_EVENT_IOC_DISABLE);
+
+ /* read and check counters */
+ res = read(break_fd, &breaks, sizeof(unsigned long long));
+ assert(res == sizeof(unsigned long long));
+ /* we read and write each loop, so subtract the ones we are counting */
+ needed = 0;
+ if (readwriteflag & HW_BREAKPOINT_R)
+ needed += loop_num;
+ if (readwriteflag & HW_BREAKPOINT_W)
+ needed += loop_num;
+ needed = needed * (1 - exclude_user);
+ if (breaks != needed) {
+ printf("FAILED: 0x%lx brks:%lld needed:%lli %i %i %i\n\n",
+ (unsigned long int)ptr, breaks, needed, loop_num, readwriteflag, exclude_user);
+ fail = 1;
+ }
+ close(break_fd);
+
+ return NULL;
+}
+
+void runtest(void)
+{
+ pthread_t *threads;
+ int i;
+
+ if ((threads = malloc(num_threads * sizeof(pthread_t))) == NULL) {
+ perror("pthread malloc");
+ }
+
+ for (i = 0; i < num_threads; i++){
+ if (pthread_create(&threads[i], NULL, runtestsingle, NULL) != 0) {
+ perror("pthreads_create");
+ fail = 1;
+ }
+ }
+
+ for (i = 0; i < num_threads; i++) {
+ pthread_join(threads[i], NULL);
+ }
+}
+
+int check_test(void)
+{
+ printf("threads=%i loops=%i %s test\n", num_threads, max_loops,
+ arraytest?"array":"scalar");
+
+ return fail;
+}
+
+static int perf_hwbreak(void)
+{
+ srand ( time(NULL) );
+ num_threads = sysconf(_SC_NPROCESSORS_ONLN) * 2;
+ max_loops = 1048576;
+
+ SKIP_IF(!perf_breakpoint_supported());
+
+ fail = 0;
+ arraytest = 0;
+ runtest();
+ if (check_test())
+ return 1;
+
+
+ if (!dawr_supported())
+ return 0;
+ fail = 0;
+ arraytest = 1;
+ runtest();
+ return check_test();
+}
+
+
+int main(int argc, char *argv[], char **envp)
+{
+ return test_harness(perf_hwbreak, "perf_hwbreak");
+}
--
2.17.0
^ permalink raw reply related
* Re: [PATCH 00/19] powerpc/ppc32: make W=1 compilation errors free
From: Mathieu Malaterre @ 2018-05-22 6:28 UTC (permalink / raw)
To: Michael Ellerman
Cc: Mathieu Malaterre, Benjamin Herrenschmidt, Paul Mackerras,
linuxppc-dev, LKML, kvm-ppc
In-Reply-To: <20180322202007.23088-1-malat@debian.org>
Any chance this could be applied to powerpc/next ?
On Thu, Mar 22, 2018 at 9:19 PM, Mathieu Malaterre <malat@debian.org> wrote:
> Here is another batch for warnings treated as error on ppc32. Tested with:
>
> $ make ARCH=powerpc ppc32_defconfig
> $ make -j8 ARCH=powerpc CROSS_COMPILE=powerpc-linux-gnu- W=1
>
> Using:
>
> $ powerpc-linux-gnu-gcc --version
> powerpc-linux-gnu-gcc (Debian 6.3.0-18) 6.3.0 20170516
>
> Mathieu Malaterre (19):
> powerpc/powermac: Mark variable x as unused
> powerpc/powermac: Mark variable x as unused
> powerpc: Mark variables as unused
> powerpc/kvm: Mark variable tmp unused
> powerpc/chrp/setup: Add attribute unused and make some functions
> static
> powerpc: Make function btext_initialize static
> powerpc/powermac: Make some functions static
> powerpc/tau: Make some function static
> powerpc/chrp/pci: Make some functions static
> powerpc/chrp/time: Make some functions static, add missing header
> include
> powerpc/powermac: Move pmac_pfunc_base_install prototype to header
> file
> powerpc/powermac: Add missing prototype for note_bootable_part()
> powerpc/52xx: Add missing functions prototypes
> powerpc/altivec: Add missing prototypes for altivec
> powerpc: Add missing prototype
> powerpc/powermac: Add missing include of header pmac.h
> powerpc/32: Add a missing include header
> powerpc: Add a missing include header
> powerpc/tau: Synchronize function prototypes and body
>
> arch/powerpc/include/asm/mpc52xx.h | 6 +++---
> arch/powerpc/include/asm/pmac_pfunc.h | 1 +
> arch/powerpc/include/asm/rheap.h | 3 +++
> arch/powerpc/kernel/btext.c | 2 +-
> arch/powerpc/kernel/irq.c | 2 +-
> arch/powerpc/kernel/kvm.c | 2 +-
> arch/powerpc/kernel/pci_32.c | 1 +
> arch/powerpc/kernel/prom_init.c | 4 ++--
> arch/powerpc/kernel/setup-common.c | 6 ------
> arch/powerpc/kernel/setup.h | 6 ++++++
> arch/powerpc/kernel/tau_6xx.c | 15 +++++++++------
> arch/powerpc/kernel/vecemu.c | 1 +
> arch/powerpc/lib/xor_vmx.h | 14 ++++++++++++++
> arch/powerpc/platforms/chrp/pci.c | 8 ++++----
> arch/powerpc/platforms/chrp/setup.c | 10 +++++-----
> arch/powerpc/platforms/chrp/time.c | 6 ++++--
> arch/powerpc/platforms/powermac/bootx_init.c | 2 +-
> arch/powerpc/platforms/powermac/pci.c | 10 +++++-----
> arch/powerpc/platforms/powermac/setup.c | 1 +
> arch/powerpc/platforms/powermac/smp.c | 1 -
> arch/powerpc/platforms/powermac/time.c | 4 +++-
> arch/powerpc/platforms/powermac/udbg_scc.c | 2 +-
> 22 files changed, 67 insertions(+), 40 deletions(-)
>
> --
> 2.11.0
>
^ permalink raw reply
* [RFC V2] virtio: Add platform specific DMA API translation for virito devices
From: Anshuman Khandual @ 2018-05-22 6:33 UTC (permalink / raw)
To: virtualization, linux-kernel
Cc: linuxppc-dev, aik, robh, joe, elfring, david, jasowang, benh, mpe,
mst, hch
This adds a hook which a platform can define in order to allow it to
force the use of the DMA API for all virtio devices even if they don't
have the VIRTIO_F_IOMMU_PLATFORM flag set. We want to use this to do
bounce-buffering of data on the new secure pSeries platform, currently
under development, where a KVM host cannot access all of the memory
space of a secure KVM guest. The host can only access the pages which
the guest has explicitly requested to be shared with the host, thus
the virtio implementation in the guest has to copy data to and from
shared pages.
With this hook, the platform code in the secure guest can force the
use of swiotlb for virtio buffers, with a back-end for swiotlb which
will use a pool of pre-allocated shared pages. Thus all data being
sent or received by virtio devices will be copied through pages which
the host has access to.
Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
---
Changes in V2:
The arch callback has been enabled through an weak symbol defintion
so that it is enabled only for those architectures subscribing to
this new framework. Clarified the patch description. The primary
objective for this RFC has been to get an in principle agreement
on this approach.
Original V1:
Original RFC and discussions https://patchwork.kernel.org/patch/10324405/
arch/powerpc/include/asm/dma-mapping.h | 6 ++++++
arch/powerpc/platforms/pseries/iommu.c | 11 +++++++++++
drivers/virtio/virtio_ring.c | 10 ++++++++++
3 files changed, 27 insertions(+)
diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h
index 8fa3945..056e578 100644
--- a/arch/powerpc/include/asm/dma-mapping.h
+++ b/arch/powerpc/include/asm/dma-mapping.h
@@ -115,4 +115,10 @@ extern u64 __dma_get_required_mask(struct device *dev);
#define ARCH_HAS_DMA_MMAP_COHERENT
#endif /* __KERNEL__ */
+
+#define platform_forces_virtio_dma platform_forces_virtio_dma
+
+struct virtio_device;
+
+extern bool platform_forces_virtio_dma(struct virtio_device *vdev);
#endif /* _ASM_DMA_MAPPING_H */
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index 06f0296..a2ec15a 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -38,6 +38,7 @@
#include <linux/of.h>
#include <linux/iommu.h>
#include <linux/rculist.h>
+#include <linux/virtio.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/rtas.h>
@@ -1396,3 +1397,13 @@ static int __init disable_multitce(char *str)
__setup("multitce=", disable_multitce);
machine_subsys_initcall_sync(pseries, tce_iommu_bus_notifier_init);
+
+bool platform_forces_virtio_dma(struct virtio_device *vdev)
+{
+ /*
+ * On protected guest platforms, force virtio core to use DMA
+ * MAP API for all virtio devices. But there can also be some
+ * exceptions for individual devices like virtio balloon.
+ */
+ return (of_find_compatible_node(NULL, NULL, "ibm,ultravisor") != NULL);
+}
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 21d464a..47ea6c3 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -141,8 +141,18 @@ struct vring_virtqueue {
* unconditionally on data path.
*/
+#ifndef platform_forces_virtio_dma
+static inline bool platform_forces_virtio_dma(struct virtio_device *vdev)
+{
+ return false;
+}
+#endif
+
static bool vring_use_dma_api(struct virtio_device *vdev)
{
+ if (platform_forces_virtio_dma(vdev))
+ return true;
+
if (!virtio_has_iommu_quirk(vdev))
return true;
--
2.9.3
^ permalink raw reply related
* [PATCH] powerpc: Implement csum_ipv6_magic in assembly
From: Christophe Leroy @ 2018-05-22 6:33 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman, segher
Cc: linux-kernel, linuxppc-dev, netdev
The generic csum_ipv6_magic() generates a pretty bad result
00000000 <csum_ipv6_magic>: (PPC32)
0: 81 23 00 00 lwz r9,0(r3)
4: 81 03 00 04 lwz r8,4(r3)
8: 7c e7 4a 14 add r7,r7,r9
c: 7d 29 38 10 subfc r9,r9,r7
10: 7d 4a 51 10 subfe r10,r10,r10
14: 7d 27 42 14 add r9,r7,r8
18: 7d 2a 48 50 subf r9,r10,r9
1c: 80 e3 00 08 lwz r7,8(r3)
20: 7d 08 48 10 subfc r8,r8,r9
24: 7d 4a 51 10 subfe r10,r10,r10
28: 7d 29 3a 14 add r9,r9,r7
2c: 81 03 00 0c lwz r8,12(r3)
30: 7d 2a 48 50 subf r9,r10,r9
34: 7c e7 48 10 subfc r7,r7,r9
38: 7d 4a 51 10 subfe r10,r10,r10
3c: 7d 29 42 14 add r9,r9,r8
40: 7d 2a 48 50 subf r9,r10,r9
44: 80 e4 00 00 lwz r7,0(r4)
48: 7d 08 48 10 subfc r8,r8,r9
4c: 7d 4a 51 10 subfe r10,r10,r10
50: 7d 29 3a 14 add r9,r9,r7
54: 7d 2a 48 50 subf r9,r10,r9
58: 81 04 00 04 lwz r8,4(r4)
5c: 7c e7 48 10 subfc r7,r7,r9
60: 7d 4a 51 10 subfe r10,r10,r10
64: 7d 29 42 14 add r9,r9,r8
68: 7d 2a 48 50 subf r9,r10,r9
6c: 80 e4 00 08 lwz r7,8(r4)
70: 7d 08 48 10 subfc r8,r8,r9
74: 7d 4a 51 10 subfe r10,r10,r10
78: 7d 29 3a 14 add r9,r9,r7
7c: 7d 2a 48 50 subf r9,r10,r9
80: 81 04 00 0c lwz r8,12(r4)
84: 7c e7 48 10 subfc r7,r7,r9
88: 7d 4a 51 10 subfe r10,r10,r10
8c: 7d 29 42 14 add r9,r9,r8
90: 7d 2a 48 50 subf r9,r10,r9
94: 7d 08 48 10 subfc r8,r8,r9
98: 7d 4a 51 10 subfe r10,r10,r10
9c: 7d 29 2a 14 add r9,r9,r5
a0: 7d 2a 48 50 subf r9,r10,r9
a4: 7c a5 48 10 subfc r5,r5,r9
a8: 7c 63 19 10 subfe r3,r3,r3
ac: 7d 29 32 14 add r9,r9,r6
b0: 7d 23 48 50 subf r9,r3,r9
b4: 7c c6 48 10 subfc r6,r6,r9
b8: 7c 63 19 10 subfe r3,r3,r3
bc: 7c 63 48 50 subf r3,r3,r9
c0: 54 6a 80 3e rotlwi r10,r3,16
c4: 7c 63 52 14 add r3,r3,r10
c8: 7c 63 18 f8 not r3,r3
cc: 54 63 84 3e rlwinm r3,r3,16,16,31
d0: 4e 80 00 20 blr
0000000000000000 <.csum_ipv6_magic>: (PPC64)
0: 81 23 00 00 lwz r9,0(r3)
4: 80 03 00 04 lwz r0,4(r3)
8: 81 63 00 08 lwz r11,8(r3)
c: 7c e7 4a 14 add r7,r7,r9
10: 7f 89 38 40 cmplw cr7,r9,r7
14: 7d 47 02 14 add r10,r7,r0
18: 7d 30 10 26 mfocrf r9,1
1c: 55 29 f7 fe rlwinm r9,r9,30,31,31
20: 7d 4a 4a 14 add r10,r10,r9
24: 7f 80 50 40 cmplw cr7,r0,r10
28: 7d 2a 5a 14 add r9,r10,r11
2c: 80 03 00 0c lwz r0,12(r3)
30: 81 44 00 00 lwz r10,0(r4)
34: 7d 10 10 26 mfocrf r8,1
38: 55 08 f7 fe rlwinm r8,r8,30,31,31
3c: 7d 29 42 14 add r9,r9,r8
40: 81 04 00 04 lwz r8,4(r4)
44: 7f 8b 48 40 cmplw cr7,r11,r9
48: 7d 29 02 14 add r9,r9,r0
4c: 7d 70 10 26 mfocrf r11,1
50: 55 6b f7 fe rlwinm r11,r11,30,31,31
54: 7d 29 5a 14 add r9,r9,r11
58: 7f 80 48 40 cmplw cr7,r0,r9
5c: 7d 29 52 14 add r9,r9,r10
60: 7c 10 10 26 mfocrf r0,1
64: 54 00 f7 fe rlwinm r0,r0,30,31,31
68: 7d 69 02 14 add r11,r9,r0
6c: 7f 8a 58 40 cmplw cr7,r10,r11
70: 7c 0b 42 14 add r0,r11,r8
74: 81 44 00 08 lwz r10,8(r4)
78: 7c f0 10 26 mfocrf r7,1
7c: 54 e7 f7 fe rlwinm r7,r7,30,31,31
80: 7c 00 3a 14 add r0,r0,r7
84: 7f 88 00 40 cmplw cr7,r8,r0
88: 7d 20 52 14 add r9,r0,r10
8c: 80 04 00 0c lwz r0,12(r4)
90: 7d 70 10 26 mfocrf r11,1
94: 55 6b f7 fe rlwinm r11,r11,30,31,31
98: 7d 29 5a 14 add r9,r9,r11
9c: 7f 8a 48 40 cmplw cr7,r10,r9
a0: 7d 29 02 14 add r9,r9,r0
a4: 7d 70 10 26 mfocrf r11,1
a8: 55 6b f7 fe rlwinm r11,r11,30,31,31
ac: 7d 29 5a 14 add r9,r9,r11
b0: 7f 80 48 40 cmplw cr7,r0,r9
b4: 7d 29 2a 14 add r9,r9,r5
b8: 7c 10 10 26 mfocrf r0,1
bc: 54 00 f7 fe rlwinm r0,r0,30,31,31
c0: 7d 29 02 14 add r9,r9,r0
c4: 7f 85 48 40 cmplw cr7,r5,r9
c8: 7c 09 32 14 add r0,r9,r6
cc: 7d 50 10 26 mfocrf r10,1
d0: 55 4a f7 fe rlwinm r10,r10,30,31,31
d4: 7c 00 52 14 add r0,r0,r10
d8: 7f 80 30 40 cmplw cr7,r0,r6
dc: 7d 30 10 26 mfocrf r9,1
e0: 55 29 ef fe rlwinm r9,r9,29,31,31
e4: 7c 09 02 14 add r0,r9,r0
e8: 54 03 80 3e rotlwi r3,r0,16
ec: 7c 03 02 14 add r0,r3,r0
f0: 7c 03 00 f8 not r3,r0
f4: 78 63 84 22 rldicl r3,r3,48,48
f8: 4e 80 00 20 blr
This patch implements it in assembly for both PPC32 and PPC64
Link: https://github.com/linuxppc/linux/issues/9
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
v3: Add support for PPC64 (please review, especially whether instructions order in optimal)
v2: Fix number of args in final addze
arch/powerpc/include/asm/checksum.h | 6 ++++++
arch/powerpc/lib/checksum_32.S | 33 +++++++++++++++++++++++++++++++++
arch/powerpc/lib/checksum_64.S | 28 ++++++++++++++++++++++++++++
3 files changed, 67 insertions(+)
diff --git a/arch/powerpc/include/asm/checksum.h b/arch/powerpc/include/asm/checksum.h
index 54065caa40b3..a78a57e5058d 100644
--- a/arch/powerpc/include/asm/checksum.h
+++ b/arch/powerpc/include/asm/checksum.h
@@ -13,6 +13,7 @@
#include <asm-generic/checksum.h>
#else
#include <linux/bitops.h>
+#include <linux/in6.h>
/*
* Computes the checksum of a memory block at src, length len,
* and adds in "sum" (32-bit), while copying the block to dst.
@@ -211,6 +212,11 @@ static inline __sum16 ip_compute_csum(const void *buff, int len)
return csum_fold(csum_partial(buff, len, 0));
}
+#define _HAVE_ARCH_IPV6_CSUM
+__sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+ const struct in6_addr *daddr,
+ __u32 len, __u8 proto, __wsum sum);
+
#endif
#endif /* __KERNEL__ */
#endif
diff --git a/arch/powerpc/lib/checksum_32.S b/arch/powerpc/lib/checksum_32.S
index 9a671c774b22..9167ab088f04 100644
--- a/arch/powerpc/lib/checksum_32.S
+++ b/arch/powerpc/lib/checksum_32.S
@@ -293,3 +293,36 @@ dst_error:
EX_TABLE(51b, dst_error);
EXPORT_SYMBOL(csum_partial_copy_generic)
+
+/*
+ * static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+ * const struct in6_addr *daddr,
+ * __u32 len, __u8 proto, __wsum sum)
+ */
+
+_GLOBAL(csum_ipv6_magic)
+ lwz r8, 0(r3)
+ lwz r9, 4(r3)
+ lwz r10, 8(r3)
+ lwz r11, 12(r3)
+ addc r0, r5, r6
+ adde r0, r0, r7
+ adde r0, r0, r8
+ adde r0, r0, r9
+ adde r0, r0, r10
+ adde r0, r0, r11
+ lwz r8, 0(r4)
+ lwz r9, 4(r4)
+ lwz r10, 8(r4)
+ lwz r11, 12(r4)
+ adde r0, r0, r8
+ adde r0, r0, r9
+ adde r0, r0, r10
+ adde r0, r0, r11
+ addze r0, r0
+ rotlwi r3, r0, 16
+ add r3, r0, r3
+ not r3, r3
+ rlwinm r3, r3, 16, 16, 31
+ blr
+EXPORT_SYMBOL(csum_ipv6_magic)
diff --git a/arch/powerpc/lib/checksum_64.S b/arch/powerpc/lib/checksum_64.S
index d7f1a966136e..66900baf5600 100644
--- a/arch/powerpc/lib/checksum_64.S
+++ b/arch/powerpc/lib/checksum_64.S
@@ -429,3 +429,31 @@ dstnr; stb r6,0(r4)
stw r6,0(r8)
blr
EXPORT_SYMBOL(csum_partial_copy_generic)
+
+/*
+ * static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+ * const struct in6_addr *daddr,
+ * __u32 len, __u8 proto, __wsum sum)
+ */
+
+_GLOBAL(csum_ipv6_magic)
+ ld r8, 0(r3)
+ ld r9, 8(r3)
+ add r5, r5, r6
+ addc r0, r8, r9
+ ld r10, 0(r4)
+ ld r11, 8(r4)
+ adde r0, r0, r10
+ add r5, r5, r7
+ adde r0, r0, r11
+ adde r0, r0, r5
+ addze r0, r0
+ rotldi r3 ,r0, 32 /* fold two 32 bit halves together */
+ add r3, r0, r3
+ srdi r0, r3, 32
+ rotlwi r3, r0, 16 /* fold two 16 bit halves together */
+ add r3, r0, r3
+ not r3, r3
+ rlwinm r3, r3, 16, 16, 31
+ blr
+EXPORT_SYMBOL(csum_ipv6_magic)
--
2.13.3
^ permalink raw reply related
* [PATCH v3] powerpc: Implement csum_ipv6_magic in assembly
From: Christophe Leroy @ 2018-05-22 6:57 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman, segher
Cc: linux-kernel, linuxppc-dev, netdev
The generic csum_ipv6_magic() generates a pretty bad result
00000000 <csum_ipv6_magic>: (PPC32)
0: 81 23 00 00 lwz r9,0(r3)
4: 81 03 00 04 lwz r8,4(r3)
8: 7c e7 4a 14 add r7,r7,r9
c: 7d 29 38 10 subfc r9,r9,r7
10: 7d 4a 51 10 subfe r10,r10,r10
14: 7d 27 42 14 add r9,r7,r8
18: 7d 2a 48 50 subf r9,r10,r9
1c: 80 e3 00 08 lwz r7,8(r3)
20: 7d 08 48 10 subfc r8,r8,r9
24: 7d 4a 51 10 subfe r10,r10,r10
28: 7d 29 3a 14 add r9,r9,r7
2c: 81 03 00 0c lwz r8,12(r3)
30: 7d 2a 48 50 subf r9,r10,r9
34: 7c e7 48 10 subfc r7,r7,r9
38: 7d 4a 51 10 subfe r10,r10,r10
3c: 7d 29 42 14 add r9,r9,r8
40: 7d 2a 48 50 subf r9,r10,r9
44: 80 e4 00 00 lwz r7,0(r4)
48: 7d 08 48 10 subfc r8,r8,r9
4c: 7d 4a 51 10 subfe r10,r10,r10
50: 7d 29 3a 14 add r9,r9,r7
54: 7d 2a 48 50 subf r9,r10,r9
58: 81 04 00 04 lwz r8,4(r4)
5c: 7c e7 48 10 subfc r7,r7,r9
60: 7d 4a 51 10 subfe r10,r10,r10
64: 7d 29 42 14 add r9,r9,r8
68: 7d 2a 48 50 subf r9,r10,r9
6c: 80 e4 00 08 lwz r7,8(r4)
70: 7d 08 48 10 subfc r8,r8,r9
74: 7d 4a 51 10 subfe r10,r10,r10
78: 7d 29 3a 14 add r9,r9,r7
7c: 7d 2a 48 50 subf r9,r10,r9
80: 81 04 00 0c lwz r8,12(r4)
84: 7c e7 48 10 subfc r7,r7,r9
88: 7d 4a 51 10 subfe r10,r10,r10
8c: 7d 29 42 14 add r9,r9,r8
90: 7d 2a 48 50 subf r9,r10,r9
94: 7d 08 48 10 subfc r8,r8,r9
98: 7d 4a 51 10 subfe r10,r10,r10
9c: 7d 29 2a 14 add r9,r9,r5
a0: 7d 2a 48 50 subf r9,r10,r9
a4: 7c a5 48 10 subfc r5,r5,r9
a8: 7c 63 19 10 subfe r3,r3,r3
ac: 7d 29 32 14 add r9,r9,r6
b0: 7d 23 48 50 subf r9,r3,r9
b4: 7c c6 48 10 subfc r6,r6,r9
b8: 7c 63 19 10 subfe r3,r3,r3
bc: 7c 63 48 50 subf r3,r3,r9
c0: 54 6a 80 3e rotlwi r10,r3,16
c4: 7c 63 52 14 add r3,r3,r10
c8: 7c 63 18 f8 not r3,r3
cc: 54 63 84 3e rlwinm r3,r3,16,16,31
d0: 4e 80 00 20 blr
0000000000000000 <.csum_ipv6_magic>: (PPC64)
0: 81 23 00 00 lwz r9,0(r3)
4: 80 03 00 04 lwz r0,4(r3)
8: 81 63 00 08 lwz r11,8(r3)
c: 7c e7 4a 14 add r7,r7,r9
10: 7f 89 38 40 cmplw cr7,r9,r7
14: 7d 47 02 14 add r10,r7,r0
18: 7d 30 10 26 mfocrf r9,1
1c: 55 29 f7 fe rlwinm r9,r9,30,31,31
20: 7d 4a 4a 14 add r10,r10,r9
24: 7f 80 50 40 cmplw cr7,r0,r10
28: 7d 2a 5a 14 add r9,r10,r11
2c: 80 03 00 0c lwz r0,12(r3)
30: 81 44 00 00 lwz r10,0(r4)
34: 7d 10 10 26 mfocrf r8,1
38: 55 08 f7 fe rlwinm r8,r8,30,31,31
3c: 7d 29 42 14 add r9,r9,r8
40: 81 04 00 04 lwz r8,4(r4)
44: 7f 8b 48 40 cmplw cr7,r11,r9
48: 7d 29 02 14 add r9,r9,r0
4c: 7d 70 10 26 mfocrf r11,1
50: 55 6b f7 fe rlwinm r11,r11,30,31,31
54: 7d 29 5a 14 add r9,r9,r11
58: 7f 80 48 40 cmplw cr7,r0,r9
5c: 7d 29 52 14 add r9,r9,r10
60: 7c 10 10 26 mfocrf r0,1
64: 54 00 f7 fe rlwinm r0,r0,30,31,31
68: 7d 69 02 14 add r11,r9,r0
6c: 7f 8a 58 40 cmplw cr7,r10,r11
70: 7c 0b 42 14 add r0,r11,r8
74: 81 44 00 08 lwz r10,8(r4)
78: 7c f0 10 26 mfocrf r7,1
7c: 54 e7 f7 fe rlwinm r7,r7,30,31,31
80: 7c 00 3a 14 add r0,r0,r7
84: 7f 88 00 40 cmplw cr7,r8,r0
88: 7d 20 52 14 add r9,r0,r10
8c: 80 04 00 0c lwz r0,12(r4)
90: 7d 70 10 26 mfocrf r11,1
94: 55 6b f7 fe rlwinm r11,r11,30,31,31
98: 7d 29 5a 14 add r9,r9,r11
9c: 7f 8a 48 40 cmplw cr7,r10,r9
a0: 7d 29 02 14 add r9,r9,r0
a4: 7d 70 10 26 mfocrf r11,1
a8: 55 6b f7 fe rlwinm r11,r11,30,31,31
ac: 7d 29 5a 14 add r9,r9,r11
b0: 7f 80 48 40 cmplw cr7,r0,r9
b4: 7d 29 2a 14 add r9,r9,r5
b8: 7c 10 10 26 mfocrf r0,1
bc: 54 00 f7 fe rlwinm r0,r0,30,31,31
c0: 7d 29 02 14 add r9,r9,r0
c4: 7f 85 48 40 cmplw cr7,r5,r9
c8: 7c 09 32 14 add r0,r9,r6
cc: 7d 50 10 26 mfocrf r10,1
d0: 55 4a f7 fe rlwinm r10,r10,30,31,31
d4: 7c 00 52 14 add r0,r0,r10
d8: 7f 80 30 40 cmplw cr7,r0,r6
dc: 7d 30 10 26 mfocrf r9,1
e0: 55 29 ef fe rlwinm r9,r9,29,31,31
e4: 7c 09 02 14 add r0,r9,r0
e8: 54 03 80 3e rotlwi r3,r0,16
ec: 7c 03 02 14 add r0,r3,r0
f0: 7c 03 00 f8 not r3,r0
f4: 78 63 84 22 rldicl r3,r3,48,48
f8: 4e 80 00 20 blr
This patch implements it in assembly for both PPC32 and PPC64
Link: https://github.com/linuxppc/linux/issues/9
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
v3: Add support for PPC64 (please review, especially whether instructions order in optimal)
v2: Fix number of args in final addze
arch/powerpc/include/asm/checksum.h | 6 ++++++
arch/powerpc/lib/checksum_32.S | 33 +++++++++++++++++++++++++++++++++
arch/powerpc/lib/checksum_64.S | 28 ++++++++++++++++++++++++++++
3 files changed, 67 insertions(+)
diff --git a/arch/powerpc/include/asm/checksum.h b/arch/powerpc/include/asm/checksum.h
index 54065caa40b3..a78a57e5058d 100644
--- a/arch/powerpc/include/asm/checksum.h
+++ b/arch/powerpc/include/asm/checksum.h
@@ -13,6 +13,7 @@
#include <asm-generic/checksum.h>
#else
#include <linux/bitops.h>
+#include <linux/in6.h>
/*
* Computes the checksum of a memory block at src, length len,
* and adds in "sum" (32-bit), while copying the block to dst.
@@ -211,6 +212,11 @@ static inline __sum16 ip_compute_csum(const void *buff, int len)
return csum_fold(csum_partial(buff, len, 0));
}
+#define _HAVE_ARCH_IPV6_CSUM
+__sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+ const struct in6_addr *daddr,
+ __u32 len, __u8 proto, __wsum sum);
+
#endif
#endif /* __KERNEL__ */
#endif
diff --git a/arch/powerpc/lib/checksum_32.S b/arch/powerpc/lib/checksum_32.S
index 9a671c774b22..9167ab088f04 100644
--- a/arch/powerpc/lib/checksum_32.S
+++ b/arch/powerpc/lib/checksum_32.S
@@ -293,3 +293,36 @@ dst_error:
EX_TABLE(51b, dst_error);
EXPORT_SYMBOL(csum_partial_copy_generic)
+
+/*
+ * static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+ * const struct in6_addr *daddr,
+ * __u32 len, __u8 proto, __wsum sum)
+ */
+
+_GLOBAL(csum_ipv6_magic)
+ lwz r8, 0(r3)
+ lwz r9, 4(r3)
+ lwz r10, 8(r3)
+ lwz r11, 12(r3)
+ addc r0, r5, r6
+ adde r0, r0, r7
+ adde r0, r0, r8
+ adde r0, r0, r9
+ adde r0, r0, r10
+ adde r0, r0, r11
+ lwz r8, 0(r4)
+ lwz r9, 4(r4)
+ lwz r10, 8(r4)
+ lwz r11, 12(r4)
+ adde r0, r0, r8
+ adde r0, r0, r9
+ adde r0, r0, r10
+ adde r0, r0, r11
+ addze r0, r0
+ rotlwi r3, r0, 16
+ add r3, r0, r3
+ not r3, r3
+ rlwinm r3, r3, 16, 16, 31
+ blr
+EXPORT_SYMBOL(csum_ipv6_magic)
diff --git a/arch/powerpc/lib/checksum_64.S b/arch/powerpc/lib/checksum_64.S
index d7f1a966136e..66900baf5600 100644
--- a/arch/powerpc/lib/checksum_64.S
+++ b/arch/powerpc/lib/checksum_64.S
@@ -429,3 +429,31 @@ dstnr; stb r6,0(r4)
stw r6,0(r8)
blr
EXPORT_SYMBOL(csum_partial_copy_generic)
+
+/*
+ * static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+ * const struct in6_addr *daddr,
+ * __u32 len, __u8 proto, __wsum sum)
+ */
+
+_GLOBAL(csum_ipv6_magic)
+ ld r8, 0(r3)
+ ld r9, 8(r3)
+ add r5, r5, r6
+ addc r0, r8, r9
+ ld r10, 0(r4)
+ ld r11, 8(r4)
+ adde r0, r0, r10
+ add r5, r5, r7
+ adde r0, r0, r11
+ adde r0, r0, r5
+ addze r0, r0
+ rotldi r3 ,r0, 32 /* fold two 32 bit halves together */
+ add r3, r0, r3
+ srdi r0, r3, 32
+ rotlwi r3, r0, 16 /* fold two 16 bit halves together */
+ add r3, r0, r3
+ not r3, r3
+ rlwinm r3, r3, 16, 16, 31
+ blr
+EXPORT_SYMBOL(csum_ipv6_magic)
--
2.13.3
^ permalink raw reply related
* Re: [PATCH 6/7 v5] bus: fsl-mc: set coherent dma mask for devices on fsl-mc bus
From: Laurentiu Tudor @ 2018-05-22 7:03 UTC (permalink / raw)
To: Nipun Gupta, robin.murphy@arm.com, will.deacon@arm.com,
robh+dt@kernel.org, robh@kernel.org, mark.rutland@arm.com,
catalin.marinas@arm.com, gregkh@linuxfoundation.org,
bhelgaas@google.com
Cc: hch@lst.de, joro@8bytes.org, m.szyprowski@samsung.com,
shawnguo@kernel.org, frowand.list@gmail.com,
iommu@lists.linux-foundation.org, linux-kernel@vger.kernel.org,
devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
linuxppc-dev@lists.ozlabs.org, linux-pci@vger.kernel.org,
Bharat Bhushan, stuyoder@gmail.com, Leo Li
In-Reply-To: <1526824191-7000-7-git-send-email-nipun.gupta@nxp.com>
On 05/20/2018 04:49 PM, Nipun Gupta wrote:
> of_dma_configure() API expects coherent_dma_mask to be correctly
> set in the devices. This patch does the needful.
>
> Signed-off-by: Nipun Gupta <nipun.gupta@nxp.com>
Acked-by: Laurentiu Tudor <laurentiu.tudor@nxp.com>
---
Best Regards, Laurentiu
> ---
> drivers/bus/fsl-mc/fsl-mc-bus.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-=
bus.c
> index fa43c7d..624828b 100644
> --- a/drivers/bus/fsl-mc/fsl-mc-bus.c
> +++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
> @@ -627,6 +627,7 @@ int fsl_mc_device_add(struct fsl_mc_obj_desc *obj_des=
c,
> mc_dev->icid =3D parent_mc_dev->icid;
> mc_dev->dma_mask =3D FSL_MC_DEFAULT_DMA_MASK;
> mc_dev->dev.dma_mask =3D &mc_dev->dma_mask;
> + mc_dev->dev.coherent_dma_mask =3D mc_dev->dma_mask;
> dev_set_msi_domain(&mc_dev->dev,
> dev_get_msi_domain(&parent_mc_dev->dev));
> }
>=
^ permalink raw reply
* Re: [PATCH] powerpc/xmon: really enable xmon when a breakpoint is set
From: Vaibhav Jain @ 2018-05-22 7:23 UTC (permalink / raw)
To: Michal Suchanek, Benjamin Herrenschmidt, Paul Mackerras,
Michael Ellerman, Balbir Singh, Nicholas Piggin, Breno Leitao,
Naveen N. Rao, Guilherme G. Piccoli, linuxppc-dev, linux-kernel
Cc: Michal Suchanek
In-Reply-To: <20180521132108.7938-1-msuchanek@suse.de>
Thanks for the patch Michal,
Michal Suchanek <msuchanek@suse.de> writes:
> When single-stepping kernel code from xmon without a debug hook enabled
> the kernel crashes. This can happen when kernel starts with xmon on
> crash disabled but xmon is entered using sysrq.
>
> Commit e1368d0c9edb ("powerpc/xmon: Setup debugger hooks when first
> break-point is set") adds force_enable_xmon function that prints
> "xmon: Enabling debugger hooks" but does not enable them.
Debugger hooks are enabled just befores debugger() is entered from
sysrq_handle_xmon(). Thats why force_enable_xmon() simply sets sets
'xmon_on=1' and exits.
The problem you are seeing is probably due to sysrq_handle_xmon()
clearing the debugger hooks on return from debugger() as xmon_on was
never set for the 's' xmon command.
> Add the call to xmon_init to install the debugger hooks in
> force_enable_xmon and also call force_enable_xmon when single-stepping
> in xmon.
Only calling force_enable_xmon() from do_step() should be suffice as on exit
from the debugger() the value of xmon_on is checked and if required the
debugger hooks are kept instead of getting cleared.
> arch/powerpc/xmon/xmon.c | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
> index a0842f1ff72c..504bd1c3d8b0 100644
> --- a/arch/powerpc/xmon/xmon.c
> +++ b/arch/powerpc/xmon/xmon.c
> @@ -1275,6 +1279,7 @@ static inline void force_enable_xmon(void)
> if (!xmon_on) {
> printf("xmon: Enabling debugger hooks\n");
> xmon_on = 1;
> + xmon_init(1);
> }
> }
As mentioned above call to force_enable_xmon() is usually done in context of
sysrq_handle_xmon() which sets the debugger hooks as soon as its
entered. So I think that this hunk is not really needed.
--
Vaibhav Jain <vaibhav@linux.vnet.ibm.com>
Linux Technology Center, IBM India Pvt. Ltd.
^ permalink raw reply
* [PATCH v6 (proposal)] powerpc/cpu: enable nr_cpus for crash kernel
From: Pingfan Liu @ 2018-05-22 8:23 UTC (permalink / raw)
To: linuxppc-dev
Cc: kexec, Benjamin Herrenschmidt, Michael Ellerman, Paul Mackerras,
Mahesh J Salgaonkar, Guilherme G . Piccoli, dyoung
For kexec -p, the boot cpu can be not the cpu0, this causes the problem
to alloc paca[]. In theory, there is no requirement to assign cpu's logical
id as its present seq by device tree. But we have something like
cpu_first_thread_sibling(), which makes assumption on the mapping inside
a core. Hence partially changing the mapping, i.e. unbind the mapping of
core while keep the mapping inside a core. After this patch, the core with
boot-cpu will always be mapped into core 0.
And at present, the code to discovery cpu spreads over two functions:
early_init_dt_scan_cpus() and smp_setup_cpu_maps().
This patch tries to fold smp_setup_cpu_maps() into the "previous" one
Signed-off-by: Pingfan Liu <kernelfans@gmail.com>
---
v5 -> v6:
simplify the loop logic (Hope it can answer Benjamin's concern)
concentrate the cpu recovery code to early stage (Hope it can answer Michael's concern)
Todo: (if this method is accepted)
fold the whole smp_setup_cpu_maps()
arch/powerpc/include/asm/smp.h | 1 +
arch/powerpc/kernel/prom.c | 123 ++++++++++++++++++++++++++++---------
arch/powerpc/kernel/setup-common.c | 58 ++---------------
drivers/of/fdt.c | 2 +-
include/linux/of_fdt.h | 2 +
5 files changed, 103 insertions(+), 83 deletions(-)
diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h
index fac963e..80c7693 100644
--- a/arch/powerpc/include/asm/smp.h
+++ b/arch/powerpc/include/asm/smp.h
@@ -30,6 +30,7 @@
#include <asm/percpu.h>
extern int boot_cpuid;
+extern int threads_in_core;
extern int spinning_secondaries;
extern void cpu_die(void);
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 4922162..2ae0b4a 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -77,7 +77,6 @@ unsigned long tce_alloc_start, tce_alloc_end;
u64 ppc64_rma_size;
#endif
static phys_addr_t first_memblock_size;
-static int __initdata boot_cpu_count;
static int __init early_parse_mem(char *p)
{
@@ -305,6 +304,14 @@ static void __init check_cpu_feature_properties(unsigned long node)
}
}
+struct bootinfo {
+ int boot_thread_id;
+ unsigned int cpu_cnt;
+ int cpu_hwids[NR_CPUS];
+ bool avail[NR_CPUS];
+};
+static struct bootinfo *bt_info;
+
static int __init early_init_dt_scan_cpus(unsigned long node,
const char *uname, int depth,
void *data)
@@ -312,10 +319,12 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
const char *type = of_get_flat_dt_prop(node, "device_type", NULL);
const __be32 *prop;
const __be32 *intserv;
- int i, nthreads;
+ int i, nthreads, maxidx;
int len;
- int found = -1;
- int found_thread = 0;
+ int found_thread = -1;
+ struct bootinfo *info = data;
+ bool avail;
+ int rotate_cnt, id;
/* We are scanning "cpu" nodes only */
if (type == NULL || strcmp(type, "cpu") != 0)
@@ -325,8 +334,15 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
intserv = of_get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s", &len);
if (!intserv)
intserv = of_get_flat_dt_prop(node, "reg", &len);
+ avail = of_fdt_device_is_available(initial_boot_params, node);
+#if 0
+ //todo
+ if (!avail)
+ avail = !of_fdt_property_match_string(node,
+ "enable-method", "spin-table");
+#endif
- nthreads = len / sizeof(int);
+ threads_in_core = nthreads = len / sizeof(int);
/*
* Now see if any of these threads match our boot cpu.
@@ -338,9 +354,10 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
* booted proc.
*/
if (fdt_version(initial_boot_params) >= 2) {
+ info->cpu_hwids[info->cpu_cnt] =
+ be32_to_cpu(intserv[i]);
if (be32_to_cpu(intserv[i]) ==
fdt_boot_cpuid_phys(initial_boot_params)) {
- found = boot_cpu_count;
found_thread = i;
}
} else {
@@ -351,22 +368,37 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
*/
if (of_get_flat_dt_prop(node,
"linux,boot-cpu", NULL) != NULL)
- found = boot_cpu_count;
+ found_thread = info->cpu_cnt;
}
+ info->avail[info->cpu_cnt] = avail;
+
#ifdef CONFIG_SMP
/* logical cpu id is always 0 on UP kernels */
- boot_cpu_count++;
+ info->cpu_cnt++;
#endif
}
/* Not the boot CPU */
- if (found < 0)
+ if (found_thread < 0)
return 0;
- DBG("boot cpu: logical %d physical %d\n", found,
+ /* always mapping boot-core to core 0 to cope with kexec -p */
+ maxidx = info->cpu_cnt - 1;
+ rotate_cnt = nthreads;
+ while (rotate_cnt-- > 0) {
+ avail = info->avail[maxidx];
+ id = info->cpu_hwids[maxidx];
+ for (i = maxidx; i > 0; i--) {
+ info->avail[i] = info->avail[i - 1];
+ info->cpu_hwids[i] = info->cpu_hwids[i - 1];
+ }
+ info->avail[i] = avail;
+ info->cpu_hwids[i] = id;
+ }
+
+ info->boot_thread_id = found_thread;
+ DBG("boot cpu: logical %d physical %d\n", found_thread,
be32_to_cpu(intserv[found_thread]));
- boot_cpuid = found;
- set_hard_smp_processor_id(found, be32_to_cpu(intserv[found_thread]));
/*
* PAPR defines "logical" PVR values for cpus that
@@ -675,6 +707,55 @@ static void __init tm_init(void)
static void tm_init(void) { }
#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
+static void early_setup_cpu_mapping(void)
+{
+ unsigned int cpu, cnt;
+ int nr_cpus_aligned;
+
+ bt_info = __va(memblock_alloc(sizeof(struct bootinfo),
+ sizeof(unsigned long)));
+ memset(bt_info, 0, sizeof(struct bootinfo));
+ bt_info->boot_thread_id = -1;
+ /* Retrieve CPU related informations from the flat tree
+ * (altivec support, boot CPU ID, ...)
+ */
+ of_scan_flat_dt(early_init_dt_scan_cpus, bt_info);
+
+ if (bt_info->boot_thread_id < 0) {
+ pr_err("Failed to identify boot CPU !\n");
+ BUG();
+ }
+
+ boot_cpuid = bt_info->boot_thread_id;
+ /* work around subcore mode */
+ nr_cpus_aligned = _ALIGN_UP(nr_cpu_ids, threads_in_core);
+ if (nr_cpus_aligned != nr_cpu_ids) {
+ pr_info("nr_cpus is forced to be aligned up from: %d to: %d\n",
+ nr_cpu_ids, nr_cpus_aligned);
+ nr_cpu_ids = nr_cpus_aligned;
+ }
+ cnt = (nr_cpu_ids < bt_info->cpu_cnt) ? nr_cpu_ids
+ : bt_info->cpu_cnt;
+
+ allocate_pacas();
+ for (cpu = 0; cpu < cnt; cpu++) {
+ set_cpu_present(cpu, bt_info->avail[cpu]);
+ DBG("set cpu present: %d -> hwid:%d\n",
+ cpu, bt_info->cpu_hwids[cpu]);
+ set_hard_smp_processor_id(cpu, bt_info->cpu_hwids[cpu]);
+ set_cpu_possible(cpu, true);
+ }
+
+#if defined(CONFIG_SMP) && defined(CONFIG_PPC64)
+ /* We'll later wait for secondaries to check in; there are
+ * NCPUS-1 non-boot CPUs :-)
+ */
+ spinning_secondaries = bt_info->cpu_cnt - 1;
+#endif
+ memblock_free(__pa(bt_info), sizeof(struct bootinfo));
+ bt_info = NULL;
+}
+
void __init early_init_devtree(void *params)
{
phys_addr_t limit;
@@ -745,27 +826,11 @@ void __init early_init_devtree(void *params)
* FIXME .. and the initrd too? */
move_device_tree();
- allocate_pacas();
-
DBG("Scanning CPUs ...\n");
dt_cpu_ftrs_scan();
- /* Retrieve CPU related informations from the flat tree
- * (altivec support, boot CPU ID, ...)
- */
- of_scan_flat_dt(early_init_dt_scan_cpus, NULL);
- if (boot_cpuid < 0) {
- printk("Failed to identify boot CPU !\n");
- BUG();
- }
-
-#if defined(CONFIG_SMP) && defined(CONFIG_PPC64)
- /* We'll later wait for secondaries to check in; there are
- * NCPUS-1 non-boot CPUs :-)
- */
- spinning_secondaries = boot_cpu_count - 1;
-#endif
+ early_setup_cpu_mapping();
mmu_early_init_devtree();
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index 66f7cc6..46d034a 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -86,7 +86,9 @@ struct machdep_calls *machine_id;
EXPORT_SYMBOL(machine_id);
int boot_cpuid = -1;
+int threads_in_core = 1;
EXPORT_SYMBOL_GPL(boot_cpuid);
+EXPORT_SYMBOL_GPL(threads_in_core);
/*
* These are used in binfmt_elf.c to put aux entries on the stack
@@ -460,61 +462,11 @@ void __init smp_setup_cpu_maps(void)
{
struct device_node *dn;
int cpu = 0;
- int nthreads = 1;
-
- DBG("smp_setup_cpu_maps()\n");
-
- for_each_node_by_type(dn, "cpu") {
- const __be32 *intserv;
- __be32 cpu_be;
- int j, len;
-
- DBG(" * %pOF...\n", dn);
-
- intserv = of_get_property(dn, "ibm,ppc-interrupt-server#s",
- &len);
- if (intserv) {
- DBG(" ibm,ppc-interrupt-server#s -> %d threads\n",
- nthreads);
- } else {
- DBG(" no ibm,ppc-interrupt-server#s -> 1 thread\n");
- intserv = of_get_property(dn, "reg", &len);
- if (!intserv) {
- cpu_be = cpu_to_be32(cpu);
- intserv = &cpu_be; /* assume logical == phys */
- len = 4;
- }
- }
-
- nthreads = len / sizeof(int);
-
- for (j = 0; j < nthreads && cpu < nr_cpu_ids; j++) {
- bool avail;
-
- DBG(" thread %d -> cpu %d (hard id %d)\n",
- j, cpu, be32_to_cpu(intserv[j]));
-
- avail = of_device_is_available(dn);
- if (!avail)
- avail = !of_property_match_string(dn,
- "enable-method", "spin-table");
-
- set_cpu_present(cpu, avail);
- set_hard_smp_processor_id(cpu, be32_to_cpu(intserv[j]));
- set_cpu_possible(cpu, true);
- cpu++;
- }
-
- if (cpu >= nr_cpu_ids) {
- of_node_put(dn);
- break;
- }
- }
/* If no SMT supported, nthreads is forced to 1 */
if (!cpu_has_feature(CPU_FTR_SMT)) {
DBG(" SMT disabled ! nthreads forced to 1\n");
- nthreads = 1;
+ threads_in_core = 1;
}
#ifdef CONFIG_PPC64
@@ -539,7 +491,7 @@ void __init smp_setup_cpu_maps(void)
/* Double maxcpus for processors which have SMT capability */
if (cpu_has_feature(CPU_FTR_SMT))
- maxcpus *= nthreads;
+ maxcpus *= threads_in_core;
if (maxcpus > nr_cpu_ids) {
printk(KERN_WARNING
@@ -565,7 +517,7 @@ void __init smp_setup_cpu_maps(void)
* every CPU in the system. If that is not the case, then some code
* here will have to be reworked
*/
- cpu_init_thread_core_maps(nthreads);
+ cpu_init_thread_core_maps(threads_in_core);
/* Now that possible cpus are set, set nr_cpu_ids for later use */
setup_nr_cpu_ids();
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 84aa9d6..16d6b02 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -130,7 +130,7 @@ bool of_fdt_is_big_endian(const void *blob, unsigned long node)
return false;
}
-static bool of_fdt_device_is_available(const void *blob, unsigned long node)
+bool of_fdt_device_is_available(const void *blob, unsigned long node)
{
const char *status = fdt_getprop(blob, node, "status", NULL);
diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h
index b9cd9eb..28756c5 100644
--- a/include/linux/of_fdt.h
+++ b/include/linux/of_fdt.h
@@ -30,6 +30,8 @@ extern void *of_fdt_get_property(const void *blob,
int *size);
extern bool of_fdt_is_big_endian(const void *blob,
unsigned long node);
+extern bool of_fdt_device_is_available(const void *blob,
+ unsigned long node);
extern int of_fdt_match(const void *blob, unsigned long node,
const char *const *compat);
extern void *of_fdt_unflatten_tree(const unsigned long *blob,
--
2.7.4
^ permalink raw reply related
* [PATCH] kbuild: rpm-pkg: Disable vmlinux.bz2 for ppc64 and ppc64le
From: Yi Li @ 2018-05-22 8:45 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Yi Li
petitboot bootloader cannot load vmlinux.bz2.
Signed-off-by: Yi Li <liyiadam@gmail.com>
---
scripts/package/mkspec | 2 ++
1 file changed, 2 insertions(+)
diff --git a/scripts/package/mkspec b/scripts/package/mkspec
index e05646d..e4146ec 100755
--- a/scripts/package/mkspec
+++ b/scripts/package/mkspec
@@ -93,8 +93,10 @@ $M make %{?_smp_mflags} INSTALL_MOD_PATH=%{buildroot} KBUILD_SRC= modules_instal
make %{?_smp_mflags} INSTALL_HDR_PATH=%{buildroot}/usr KBUILD_SRC= headers_install
cp System.map %{buildroot}/boot/System.map-$KERNELRELEASE
cp .config %{buildroot}/boot/config-$KERNELRELEASE
+ %ifnarch ppc64 ppc64le
bzip2 -9 --keep vmlinux
mv vmlinux.bz2 %{buildroot}/boot/vmlinux-$KERNELRELEASE.bz2
+ %endif
$S$M rm -f %{buildroot}/lib/modules/$KERNELRELEASE/build
$S$M rm -f %{buildroot}/lib/modules/$KERNELRELEASE/source
$S$M mkdir -p %{buildroot}/usr/src/kernels/$KERNELRELEASE
--
1.8.3.1
^ permalink raw reply related
* Re: [PATCH v6 (proposal)] powerpc/cpu: enable nr_cpus for crash kernel
From: Pingfan Liu @ 2018-05-22 8:49 UTC (permalink / raw)
To: linuxppc-dev
Cc: kexec, Benjamin Herrenschmidt, Michael Ellerman, Paul Mackerras,
Mahesh J Salgaonkar, Guilherme G . Piccoli, Dave Young
In-Reply-To: <1526977424-25243-1-git-send-email-kernelfans@gmail.com>
I had tested this patch for P9/P8/ guest on powerKVM and powerVM. All
of them works fine.
On Tue, May 22, 2018 at 4:23 PM, Pingfan Liu <kernelfans@gmail.com> wrote:
> For kexec -p, the boot cpu can be not the cpu0, this causes the problem
> to alloc paca[]. In theory, there is no requirement to assign cpu's logical
> id as its present seq by device tree. But we have something like
> cpu_first_thread_sibling(), which makes assumption on the mapping inside
> a core. Hence partially changing the mapping, i.e. unbind the mapping of
> core while keep the mapping inside a core. After this patch, the core with
> boot-cpu will always be mapped into core 0.
>
> And at present, the code to discovery cpu spreads over two functions:
> early_init_dt_scan_cpus() and smp_setup_cpu_maps().
> This patch tries to fold smp_setup_cpu_maps() into the "previous" one
>
> Signed-off-by: Pingfan Liu <kernelfans@gmail.com>
> ---
> v5 -> v6:
> simplify the loop logic (Hope it can answer Benjamin's concern)
> concentrate the cpu recovery code to early stage (Hope it can answer Michael's concern)
> Todo: (if this method is accepted)
> fold the whole smp_setup_cpu_maps()
>
> arch/powerpc/include/asm/smp.h | 1 +
> arch/powerpc/kernel/prom.c | 123 ++++++++++++++++++++++++++++---------
> arch/powerpc/kernel/setup-common.c | 58 ++---------------
> drivers/of/fdt.c | 2 +-
> include/linux/of_fdt.h | 2 +
> 5 files changed, 103 insertions(+), 83 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h
> index fac963e..80c7693 100644
> --- a/arch/powerpc/include/asm/smp.h
> +++ b/arch/powerpc/include/asm/smp.h
> @@ -30,6 +30,7 @@
> #include <asm/percpu.h>
>
> extern int boot_cpuid;
> +extern int threads_in_core;
> extern int spinning_secondaries;
>
> extern void cpu_die(void);
> diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
> index 4922162..2ae0b4a 100644
> --- a/arch/powerpc/kernel/prom.c
> +++ b/arch/powerpc/kernel/prom.c
> @@ -77,7 +77,6 @@ unsigned long tce_alloc_start, tce_alloc_end;
> u64 ppc64_rma_size;
> #endif
> static phys_addr_t first_memblock_size;
> -static int __initdata boot_cpu_count;
>
> static int __init early_parse_mem(char *p)
> {
> @@ -305,6 +304,14 @@ static void __init check_cpu_feature_properties(unsigned long node)
> }
> }
>
> +struct bootinfo {
> + int boot_thread_id;
> + unsigned int cpu_cnt;
> + int cpu_hwids[NR_CPUS];
> + bool avail[NR_CPUS];
> +};
> +static struct bootinfo *bt_info;
> +
> static int __init early_init_dt_scan_cpus(unsigned long node,
> const char *uname, int depth,
> void *data)
> @@ -312,10 +319,12 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
> const char *type = of_get_flat_dt_prop(node, "device_type", NULL);
> const __be32 *prop;
> const __be32 *intserv;
> - int i, nthreads;
> + int i, nthreads, maxidx;
> int len;
> - int found = -1;
> - int found_thread = 0;
> + int found_thread = -1;
> + struct bootinfo *info = data;
> + bool avail;
> + int rotate_cnt, id;
>
> /* We are scanning "cpu" nodes only */
> if (type == NULL || strcmp(type, "cpu") != 0)
> @@ -325,8 +334,15 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
> intserv = of_get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s", &len);
> if (!intserv)
> intserv = of_get_flat_dt_prop(node, "reg", &len);
> + avail = of_fdt_device_is_available(initial_boot_params, node);
> +#if 0
> + //todo
> + if (!avail)
> + avail = !of_fdt_property_match_string(node,
> + "enable-method", "spin-table");
> +#endif
>
> - nthreads = len / sizeof(int);
> + threads_in_core = nthreads = len / sizeof(int);
>
> /*
> * Now see if any of these threads match our boot cpu.
> @@ -338,9 +354,10 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
> * booted proc.
> */
> if (fdt_version(initial_boot_params) >= 2) {
> + info->cpu_hwids[info->cpu_cnt] =
> + be32_to_cpu(intserv[i]);
> if (be32_to_cpu(intserv[i]) ==
> fdt_boot_cpuid_phys(initial_boot_params)) {
> - found = boot_cpu_count;
> found_thread = i;
> }
> } else {
> @@ -351,22 +368,37 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
> */
> if (of_get_flat_dt_prop(node,
> "linux,boot-cpu", NULL) != NULL)
> - found = boot_cpu_count;
> + found_thread = info->cpu_cnt;
> }
> + info->avail[info->cpu_cnt] = avail;
> +
> #ifdef CONFIG_SMP
> /* logical cpu id is always 0 on UP kernels */
> - boot_cpu_count++;
> + info->cpu_cnt++;
> #endif
> }
>
> /* Not the boot CPU */
> - if (found < 0)
> + if (found_thread < 0)
> return 0;
>
> - DBG("boot cpu: logical %d physical %d\n", found,
> + /* always mapping boot-core to core 0 to cope with kexec -p */
> + maxidx = info->cpu_cnt - 1;
> + rotate_cnt = nthreads;
> + while (rotate_cnt-- > 0) {
> + avail = info->avail[maxidx];
> + id = info->cpu_hwids[maxidx];
> + for (i = maxidx; i > 0; i--) {
> + info->avail[i] = info->avail[i - 1];
> + info->cpu_hwids[i] = info->cpu_hwids[i - 1];
> + }
> + info->avail[i] = avail;
> + info->cpu_hwids[i] = id;
> + }
> +
> + info->boot_thread_id = found_thread;
> + DBG("boot cpu: logical %d physical %d\n", found_thread,
> be32_to_cpu(intserv[found_thread]));
> - boot_cpuid = found;
> - set_hard_smp_processor_id(found, be32_to_cpu(intserv[found_thread]));
>
> /*
> * PAPR defines "logical" PVR values for cpus that
> @@ -675,6 +707,55 @@ static void __init tm_init(void)
> static void tm_init(void) { }
> #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
>
> +static void early_setup_cpu_mapping(void)
> +{
> + unsigned int cpu, cnt;
> + int nr_cpus_aligned;
> +
> + bt_info = __va(memblock_alloc(sizeof(struct bootinfo),
> + sizeof(unsigned long)));
> + memset(bt_info, 0, sizeof(struct bootinfo));
> + bt_info->boot_thread_id = -1;
> + /* Retrieve CPU related informations from the flat tree
> + * (altivec support, boot CPU ID, ...)
> + */
> + of_scan_flat_dt(early_init_dt_scan_cpus, bt_info);
> +
> + if (bt_info->boot_thread_id < 0) {
> + pr_err("Failed to identify boot CPU !\n");
> + BUG();
> + }
> +
> + boot_cpuid = bt_info->boot_thread_id;
> + /* work around subcore mode */
> + nr_cpus_aligned = _ALIGN_UP(nr_cpu_ids, threads_in_core);
> + if (nr_cpus_aligned != nr_cpu_ids) {
> + pr_info("nr_cpus is forced to be aligned up from: %d to: %d\n",
> + nr_cpu_ids, nr_cpus_aligned);
> + nr_cpu_ids = nr_cpus_aligned;
> + }
> + cnt = (nr_cpu_ids < bt_info->cpu_cnt) ? nr_cpu_ids
> + : bt_info->cpu_cnt;
> +
> + allocate_pacas();
> + for (cpu = 0; cpu < cnt; cpu++) {
> + set_cpu_present(cpu, bt_info->avail[cpu]);
> + DBG("set cpu present: %d -> hwid:%d\n",
> + cpu, bt_info->cpu_hwids[cpu]);
> + set_hard_smp_processor_id(cpu, bt_info->cpu_hwids[cpu]);
> + set_cpu_possible(cpu, true);
> + }
> +
> +#if defined(CONFIG_SMP) && defined(CONFIG_PPC64)
> + /* We'll later wait for secondaries to check in; there are
> + * NCPUS-1 non-boot CPUs :-)
> + */
> + spinning_secondaries = bt_info->cpu_cnt - 1;
> +#endif
> + memblock_free(__pa(bt_info), sizeof(struct bootinfo));
> + bt_info = NULL;
> +}
> +
> void __init early_init_devtree(void *params)
> {
> phys_addr_t limit;
> @@ -745,27 +826,11 @@ void __init early_init_devtree(void *params)
> * FIXME .. and the initrd too? */
> move_device_tree();
>
> - allocate_pacas();
> -
> DBG("Scanning CPUs ...\n");
>
> dt_cpu_ftrs_scan();
>
> - /* Retrieve CPU related informations from the flat tree
> - * (altivec support, boot CPU ID, ...)
> - */
> - of_scan_flat_dt(early_init_dt_scan_cpus, NULL);
> - if (boot_cpuid < 0) {
> - printk("Failed to identify boot CPU !\n");
> - BUG();
> - }
> -
> -#if defined(CONFIG_SMP) && defined(CONFIG_PPC64)
> - /* We'll later wait for secondaries to check in; there are
> - * NCPUS-1 non-boot CPUs :-)
> - */
> - spinning_secondaries = boot_cpu_count - 1;
> -#endif
> + early_setup_cpu_mapping();
>
> mmu_early_init_devtree();
>
> diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
> index 66f7cc6..46d034a 100644
> --- a/arch/powerpc/kernel/setup-common.c
> +++ b/arch/powerpc/kernel/setup-common.c
> @@ -86,7 +86,9 @@ struct machdep_calls *machine_id;
> EXPORT_SYMBOL(machine_id);
>
> int boot_cpuid = -1;
> +int threads_in_core = 1;
> EXPORT_SYMBOL_GPL(boot_cpuid);
> +EXPORT_SYMBOL_GPL(threads_in_core);
>
> /*
> * These are used in binfmt_elf.c to put aux entries on the stack
> @@ -460,61 +462,11 @@ void __init smp_setup_cpu_maps(void)
> {
> struct device_node *dn;
> int cpu = 0;
> - int nthreads = 1;
> -
> - DBG("smp_setup_cpu_maps()\n");
> -
> - for_each_node_by_type(dn, "cpu") {
> - const __be32 *intserv;
> - __be32 cpu_be;
> - int j, len;
> -
> - DBG(" * %pOF...\n", dn);
> -
> - intserv = of_get_property(dn, "ibm,ppc-interrupt-server#s",
> - &len);
> - if (intserv) {
> - DBG(" ibm,ppc-interrupt-server#s -> %d threads\n",
> - nthreads);
> - } else {
> - DBG(" no ibm,ppc-interrupt-server#s -> 1 thread\n");
> - intserv = of_get_property(dn, "reg", &len);
> - if (!intserv) {
> - cpu_be = cpu_to_be32(cpu);
> - intserv = &cpu_be; /* assume logical == phys */
> - len = 4;
> - }
> - }
> -
> - nthreads = len / sizeof(int);
> -
> - for (j = 0; j < nthreads && cpu < nr_cpu_ids; j++) {
> - bool avail;
> -
> - DBG(" thread %d -> cpu %d (hard id %d)\n",
> - j, cpu, be32_to_cpu(intserv[j]));
> -
> - avail = of_device_is_available(dn);
> - if (!avail)
> - avail = !of_property_match_string(dn,
> - "enable-method", "spin-table");
> -
> - set_cpu_present(cpu, avail);
> - set_hard_smp_processor_id(cpu, be32_to_cpu(intserv[j]));
> - set_cpu_possible(cpu, true);
> - cpu++;
> - }
> -
> - if (cpu >= nr_cpu_ids) {
> - of_node_put(dn);
> - break;
> - }
> - }
>
> /* If no SMT supported, nthreads is forced to 1 */
> if (!cpu_has_feature(CPU_FTR_SMT)) {
> DBG(" SMT disabled ! nthreads forced to 1\n");
> - nthreads = 1;
> + threads_in_core = 1;
> }
>
> #ifdef CONFIG_PPC64
> @@ -539,7 +491,7 @@ void __init smp_setup_cpu_maps(void)
>
> /* Double maxcpus for processors which have SMT capability */
> if (cpu_has_feature(CPU_FTR_SMT))
> - maxcpus *= nthreads;
> + maxcpus *= threads_in_core;
>
> if (maxcpus > nr_cpu_ids) {
> printk(KERN_WARNING
> @@ -565,7 +517,7 @@ void __init smp_setup_cpu_maps(void)
> * every CPU in the system. If that is not the case, then some code
> * here will have to be reworked
> */
> - cpu_init_thread_core_maps(nthreads);
> + cpu_init_thread_core_maps(threads_in_core);
>
> /* Now that possible cpus are set, set nr_cpu_ids for later use */
> setup_nr_cpu_ids();
> diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
> index 84aa9d6..16d6b02 100644
> --- a/drivers/of/fdt.c
> +++ b/drivers/of/fdt.c
> @@ -130,7 +130,7 @@ bool of_fdt_is_big_endian(const void *blob, unsigned long node)
> return false;
> }
>
> -static bool of_fdt_device_is_available(const void *blob, unsigned long node)
> +bool of_fdt_device_is_available(const void *blob, unsigned long node)
> {
> const char *status = fdt_getprop(blob, node, "status", NULL);
>
> diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h
> index b9cd9eb..28756c5 100644
> --- a/include/linux/of_fdt.h
> +++ b/include/linux/of_fdt.h
> @@ -30,6 +30,8 @@ extern void *of_fdt_get_property(const void *blob,
> int *size);
> extern bool of_fdt_is_big_endian(const void *blob,
> unsigned long node);
> +extern bool of_fdt_device_is_available(const void *blob,
> + unsigned long node);
> extern int of_fdt_match(const void *blob, unsigned long node,
> const char *const *compat);
> extern void *of_fdt_unflatten_tree(const unsigned long *blob,
> --
> 2.7.4
>
^ permalink raw reply
* Re: [PATCH bpf v2 6/6] bpf: fix JITed dump for multi-function programs via syscall
From: Daniel Borkmann @ 2018-05-22 8:54 UTC (permalink / raw)
To: Sandipan Das; +Cc: ast, netdev, linuxppc-dev, naveen.n.rao, mpe, jakub.kicinski
In-Reply-To: <57a3df63-f533-0dee-3fb8-621c0ba51968@linux.vnet.ibm.com>
On 05/21/2018 09:42 PM, Sandipan Das wrote:
> On 05/18/2018 09:21 PM, Daniel Borkmann wrote:
>> On 05/18/2018 02:50 PM, Sandipan Das wrote:
>>> Currently, for multi-function programs, we cannot get the JITed
>>> instructions using the bpf system call's BPF_OBJ_GET_INFO_BY_FD
>>> command. Because of this, userspace tools such as bpftool fail
>>> to identify a multi-function program as being JITed or not.
>>>
>>> With the JIT enabled and the test program running, this can be
>>> verified as follows:
>>>
>>> # cat /proc/sys/net/core/bpf_jit_enable
>>> 1
>>>
>>> Before applying this patch:
>>>
>>> # bpftool prog list
>>> 1: kprobe name foo tag b811aab41a39ad3d gpl
>>> loaded_at 2018-05-16T11:43:38+0530 uid 0
>>> xlated 216B not jited memlock 65536B
>>> ...
>>>
>>> # bpftool prog dump jited id 1
>>> no instructions returned
>>>
>>> After applying this patch:
>>>
>>> # bpftool prog list
>>> 1: kprobe name foo tag b811aab41a39ad3d gpl
>>> loaded_at 2018-05-16T12:13:01+0530 uid 0
>>> xlated 216B jited 308B memlock 65536B
>>> ...
>>
>> That's really nice! One comment inline below:
>>
>>> # bpftool prog dump jited id 1
>>> 0: nop
>>> 4: nop
>>> 8: mflr r0
>>> c: std r0,16(r1)
>>> 10: stdu r1,-112(r1)
>>> 14: std r31,104(r1)
>>> 18: addi r31,r1,48
>>> 1c: li r3,10
>>> ...
>>>
>>> Signed-off-by: Sandipan Das <sandipan@linux.vnet.ibm.com>
>>> ---
>>> kernel/bpf/syscall.c | 38 ++++++++++++++++++++++++++++++++------
>>> 1 file changed, 32 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
>>> index 54a72fafe57c..2430d159078c 100644
>>> --- a/kernel/bpf/syscall.c
>>> +++ b/kernel/bpf/syscall.c
>>> @@ -1896,7 +1896,7 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
>>> struct bpf_prog_info info = {};
>>> u32 info_len = attr->info.info_len;
>>> char __user *uinsns;
>>> - u32 ulen;
>>> + u32 ulen, i;
>>> int err;
>>>
>>> err = check_uarg_tail_zero(uinfo, sizeof(info), info_len);
>>> @@ -1922,7 +1922,6 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
>>> ulen = min_t(u32, info.nr_map_ids, ulen);
>>> if (ulen) {
>>> u32 __user *user_map_ids = u64_to_user_ptr(info.map_ids);
>>> - u32 i;
>>>
>>> for (i = 0; i < ulen; i++)
>>> if (put_user(prog->aux->used_maps[i]->id,
>>> @@ -1970,13 +1969,41 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
>>> * for offload.
>>> */
>>> ulen = info.jited_prog_len;
>>> - info.jited_prog_len = prog->jited_len;
>>> + if (prog->aux->func_cnt) {
>>> + info.jited_prog_len = 0;
>>> + for (i = 0; i < prog->aux->func_cnt; i++)
>>> + info.jited_prog_len += prog->aux->func[i]->jited_len;
>>> + } else {
>>> + info.jited_prog_len = prog->jited_len;
>>> + }
>>> +
>>> if (info.jited_prog_len && ulen) {
>>> if (bpf_dump_raw_ok()) {
>>> uinsns = u64_to_user_ptr(info.jited_prog_insns);
>>> ulen = min_t(u32, info.jited_prog_len, ulen);
>>> - if (copy_to_user(uinsns, prog->bpf_func, ulen))
>>> - return -EFAULT;
>>> +
>>> + /* for multi-function programs, copy the JITed
>>> + * instructions for all the functions
>>> + */
>>> + if (prog->aux->func_cnt) {
>>> + u32 len, free;
>>> + u8 *img;
>>> +
>>> + free = ulen;
>>> + for (i = 0; i < prog->aux->func_cnt; i++) {
>>> + len = prog->aux->func[i]->jited_len;
>>> + img = (u8 *) prog->aux->func[i]->bpf_func;
>>> + if (len > free)
>>> + break;
>>> + if (copy_to_user(uinsns, img, len))
>>> + return -EFAULT;
>>> + uinsns += len;
>>> + free -= len;
>>
>> Is there any way we can introduce a delimiter between the different
>> images such that they could be more easily correlated with the call
>> from the main (or other sub-)program instead of having one contiguous
>> dump blob?
>
> Can we have another member in bpf_prog_info that points to a list of the lengths of the
> JITed images for each subprogram? We can use this information to split up the dump.
Seems okay to me.
Thanks,
Daniel
^ permalink raw reply
* [PATCH] powerpc/kprobes: Fix build error with kprobes disabled.
From: Aneesh Kumar K.V @ 2018-05-22 9:08 UTC (permalink / raw)
To: benh, paulus, mpe; +Cc: linuxppc-dev, Aneesh Kumar K.V
arch/powerpc/kernel/stacktrace.c: In function ‘save_stack_trace_tsk_reliable’:
arch/powerpc/kernel/stacktrace.c:176:28: error: ‘kretprobe_trampoline’ undeclared (first use in this function); did you mean ‘is_ftrace_trampoline’?
if (ip == (unsigned long)kretprobe_trampoline)
^~~~~~~~~~~~~~~~~~~~
is_ftrace_trampoline
arch/powerpc/kernel/stacktrace.c:176:28: note: each undeclared identifier is reported only once for each function it appears in
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
---
arch/powerpc/kernel/stacktrace.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/kernel/stacktrace.c b/arch/powerpc/kernel/stacktrace.c
index 26a50603177c..8dd6ba0c7d35 100644
--- a/arch/powerpc/kernel/stacktrace.c
+++ b/arch/powerpc/kernel/stacktrace.c
@@ -168,13 +168,14 @@ save_stack_trace_tsk_reliable(struct task_struct *tsk,
* arch-dependent code, they are generic.
*/
ip = ftrace_graph_ret_addr(tsk, &graph_idx, ip, NULL);
-
+#ifdef CONFIG_KPROBES
/*
* Mark stacktraces with kretprobed functions on them
* as unreliable.
*/
if (ip == (unsigned long)kretprobe_trampoline)
return 1;
+#endif
if (!trace->skip)
trace->entries[trace->nr_entries++] = ip;
--
2.17.0
^ permalink raw reply related
* [PATCH] powerpc/mm/hugetlb: Use the correct page size when flushing hugepage tlb
From: Aneesh Kumar K.V @ 2018-05-22 9:12 UTC (permalink / raw)
To: benh, paulus, mpe; +Cc: linuxppc-dev, Aneesh Kumar K.V
We used wrong page size (mmu_virtual_psize) when doing a tlbflush after
pte update. This patch update the flush to use hugetlb page size.
The page size is derived from hugetlb hstate.
Now that ptep_set_access_flags won't be called for hugetlb remove
the is_vm_hugetlb_page() check and add the assert of pte lock
unconditionally.
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
---
arch/powerpc/include/asm/hugetlb.h | 19 +++--------------
arch/powerpc/mm/pgtable.c | 33 ++++++++++++++++++++++++++++--
2 files changed, 34 insertions(+), 18 deletions(-)
diff --git a/arch/powerpc/include/asm/hugetlb.h b/arch/powerpc/include/asm/hugetlb.h
index 78540c074d70..b4404a6da74f 100644
--- a/arch/powerpc/include/asm/hugetlb.h
+++ b/arch/powerpc/include/asm/hugetlb.h
@@ -166,22 +166,9 @@ static inline pte_t huge_pte_wrprotect(pte_t pte)
return pte_wrprotect(pte);
}
-static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
- unsigned long addr, pte_t *ptep,
- pte_t pte, int dirty)
-{
-#ifdef HUGETLB_NEED_PRELOAD
- /*
- * The "return 1" forces a call of update_mmu_cache, which will write a
- * TLB entry. Without this, platforms that don't do a write of the TLB
- * entry in the TLB miss handler asm will fault ad infinitum.
- */
- ptep_set_access_flags(vma, addr, ptep, pte, dirty);
- return 1;
-#else
- return ptep_set_access_flags(vma, addr, ptep, pte, dirty);
-#endif
-}
+extern int huge_ptep_set_access_flags(struct vm_area_struct *vma,
+ unsigned long addr, pte_t *ptep,
+ pte_t pte, int dirty);
static inline pte_t huge_ptep_get(pte_t *ptep)
{
diff --git a/arch/powerpc/mm/pgtable.c b/arch/powerpc/mm/pgtable.c
index 9f361ae571e9..e70af9939379 100644
--- a/arch/powerpc/mm/pgtable.c
+++ b/arch/powerpc/mm/pgtable.c
@@ -221,14 +221,43 @@ int ptep_set_access_flags(struct vm_area_struct *vma, unsigned long address,
entry = set_access_flags_filter(entry, vma, dirty);
changed = !pte_same(*(ptep), entry);
if (changed) {
- if (!is_vm_hugetlb_page(vma))
- assert_pte_locked(vma->vm_mm, address);
+ assert_pte_locked(vma->vm_mm, address);
__ptep_set_access_flags(vma->vm_mm, ptep, entry, address);
flush_tlb_page(vma, address);
}
return changed;
}
+#ifdef CONFIG_HUGETLB_PAGE
+extern int huge_ptep_set_access_flags(struct vm_area_struct *vma,
+ unsigned long addr, pte_t *ptep,
+ pte_t pte, int dirty)
+{
+#ifdef HUGETLB_NEED_PRELOAD
+ /*
+ * The "return 1" forces a call of update_mmu_cache, which will write a
+ * TLB entry. Without this, platforms that don't do a write of the TLB
+ * entry in the TLB miss handler asm will fault ad infinitum.
+ */
+ ptep_set_access_flags(vma, addr, ptep, pte, dirty);
+ return 1;
+#else
+ int changed;
+
+ pte = set_access_flags_filter(pte, vma, dirty);
+ changed = !pte_same(*(ptep), pte);
+ if (changed) {
+#ifdef CONFIG_DEBUG_VM
+ assert_spin_locked(&vma->vm_mm->page_table_lock);
+#endif
+ __ptep_set_access_flags(vma->vm_mm, ptep, pte, addr);
+ flush_hugetlb_page(vma, addr);
+ }
+ return changed;
+#endif
+}
+#endif /* CONFIG_HUGETLB_PAGE */
+
#ifdef CONFIG_DEBUG_VM
void assert_pte_locked(struct mm_struct *mm, unsigned long addr)
{
--
2.17.0
^ permalink raw reply related
* [PATCH v2 0/4] powerpc/perf: IMC Cleanups
From: Anju T Sudhakar @ 2018-05-22 9:12 UTC (permalink / raw)
To: mpe; +Cc: linuxppc-dev, maddy, anju
This patch series includes some cleanups and Unregistration of
thread-imc pmu, if the kernel does not have core-imc registered.
The entire patch set has been verified using the static checker smatch.
Command used:
$ make ARCH=powerpc CHECK="<path>/smatch -p=kernel" C=1 vmlinux | tee warns.txt
Tests Done:
* Fail core-imc at init:
nest-imc - working
cpuhotplug - works as expected
thread-imc - not registered
* Fail thread-imc at init:
nest-imc - works
core-imc - works
cpuhotplug - works
* Fail nest-imc at init
core-imc - works
thread-imc -works
cpuhotplug - works
* Fail only one nest unit (say for mcs23)
Other nest-units - works
core-imc - works
thread-imc - works
cpuhotplug - works.
* Kexec works
The first three patches in this series addresses the comments by Dan Carpenter.
Patch series is based on:
https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git (merge branch)
Anju T Sudhakar (4):
powerpc/perf: Rearrange memory freeing in imc init
powerpc/perf: Replace the direct return with goto statement
powerpc/perf: Return appropriate value for unknown domain
powerpc/perf: Unregister thread-imc if core-imc not supported
arch/powerpc/include/asm/imc-pmu.h | 1 +
arch/powerpc/perf/imc-pmu.c | 64 +++++++++++++++++++------------
arch/powerpc/platforms/powernv/opal-imc.c | 22 +++++++++--
3 files changed, 60 insertions(+), 27 deletions(-)
--
2.7.4
^ permalink raw reply
* [PATCH v2 1/4] powerpc/perf: Rearrange memory freeing in imc init
From: Anju T Sudhakar @ 2018-05-22 9:12 UTC (permalink / raw)
To: mpe; +Cc: linuxppc-dev, maddy, anju
In-Reply-To: <1526980357-25385-1-git-send-email-anju@linux.vnet.ibm.com>
When any of the IMC (In-Memory Collection counter) devices fail
to initialize, imc_common_mem_free() frees set of memory. In doing so,
pmu_ptr pointer is also freed. But pmu_ptr pointer is used in subsequent
function (imc_common_cpuhp_mem_free()) which is wrong. Patch here reorders
the code to avoid such access.
Also free the memory which is dynamically allocated during imc
initialization, wherever required.
Signed-off-by: Anju T Sudhakar <anju@linux.vnet.ibm.com>
Reviewed-by: Madhavan Srinivasan <maddy@linux.vnet.ibm.com>
---
arch/powerpc/perf/imc-pmu.c | 32 ++++++++++++++++---------------
arch/powerpc/platforms/powernv/opal-imc.c | 13 ++++++++++---
2 files changed, 27 insertions(+), 18 deletions(-)
diff --git a/arch/powerpc/perf/imc-pmu.c b/arch/powerpc/perf/imc-pmu.c
index 75fb23c..c1665ff 100644
--- a/arch/powerpc/perf/imc-pmu.c
+++ b/arch/powerpc/perf/imc-pmu.c
@@ -1153,7 +1153,7 @@ static void cleanup_all_core_imc_memory(void)
/* mem_info will never be NULL */
for (i = 0; i < nr_cores; i++) {
if (ptr[i].vbase)
- free_pages((u64)ptr->vbase, get_order(size));
+ free_pages((u64)ptr[i].vbase, get_order(size));
}
kfree(ptr);
@@ -1191,7 +1191,6 @@ static void imc_common_mem_free(struct imc_pmu *pmu_ptr)
if (pmu_ptr->attr_groups[IMC_EVENT_ATTR])
kfree(pmu_ptr->attr_groups[IMC_EVENT_ATTR]->attrs);
kfree(pmu_ptr->attr_groups[IMC_EVENT_ATTR]);
- kfree(pmu_ptr);
}
/*
@@ -1208,6 +1207,7 @@ static void imc_common_cpuhp_mem_free(struct imc_pmu *pmu_ptr)
cpuhp_remove_state(CPUHP_AP_PERF_POWERPC_NEST_IMC_ONLINE);
kfree(nest_imc_refc);
kfree(per_nest_pmu_arr);
+ per_nest_pmu_arr = NULL;
}
if (nest_pmus > 0)
@@ -1319,10 +1319,8 @@ int init_imc_pmu(struct device_node *parent, struct imc_pmu *pmu_ptr, int pmu_id
int ret;
ret = imc_mem_init(pmu_ptr, parent, pmu_idx);
- if (ret) {
- imc_common_mem_free(pmu_ptr);
- return ret;
- }
+ if (ret)
+ goto err_free_mem;
switch (pmu_ptr->domain) {
case IMC_DOMAIN_NEST:
@@ -1337,7 +1335,9 @@ int init_imc_pmu(struct device_node *parent, struct imc_pmu *pmu_ptr, int pmu_id
ret = init_nest_pmu_ref();
if (ret) {
mutex_unlock(&nest_init_lock);
- goto err_free;
+ kfree(per_nest_pmu_arr);
+ per_nest_pmu_arr = NULL;
+ goto err_free_mem;
}
/* Register for cpu hotplug notification. */
ret = nest_pmu_cpumask_init();
@@ -1345,7 +1345,8 @@ int init_imc_pmu(struct device_node *parent, struct imc_pmu *pmu_ptr, int pmu_id
mutex_unlock(&nest_init_lock);
kfree(nest_imc_refc);
kfree(per_nest_pmu_arr);
- goto err_free;
+ per_nest_pmu_arr = NULL;
+ goto err_free_mem;
}
}
nest_pmus++;
@@ -1355,7 +1356,7 @@ int init_imc_pmu(struct device_node *parent, struct imc_pmu *pmu_ptr, int pmu_id
ret = core_imc_pmu_cpumask_init();
if (ret) {
cleanup_all_core_imc_memory();
- return ret;
+ goto err_free_mem;
}
break;
@@ -1363,7 +1364,7 @@ int init_imc_pmu(struct device_node *parent, struct imc_pmu *pmu_ptr, int pmu_id
ret = thread_imc_cpu_init();
if (ret) {
cleanup_all_thread_imc_memory();
- return ret;
+ goto err_free_mem;
}
break;
@@ -1373,23 +1374,24 @@ int init_imc_pmu(struct device_node *parent, struct imc_pmu *pmu_ptr, int pmu_id
ret = update_events_in_group(parent, pmu_ptr);
if (ret)
- goto err_free;
+ goto err_free_cpuhp_mem;
ret = update_pmu_ops(pmu_ptr);
if (ret)
- goto err_free;
+ goto err_free_cpuhp_mem;
ret = perf_pmu_register(&pmu_ptr->pmu, pmu_ptr->pmu.name, -1);
if (ret)
- goto err_free;
+ goto err_free_cpuhp_mem;
pr_info("%s performance monitor hardware support registered\n",
pmu_ptr->pmu.name);
return 0;
-err_free:
- imc_common_mem_free(pmu_ptr);
+err_free_cpuhp_mem:
imc_common_cpuhp_mem_free(pmu_ptr);
+err_free_mem:
+ imc_common_mem_free(pmu_ptr);
return ret;
}
diff --git a/arch/powerpc/platforms/powernv/opal-imc.c b/arch/powerpc/platforms/powernv/opal-imc.c
index 2a14fda..490bb72 100644
--- a/arch/powerpc/platforms/powernv/opal-imc.c
+++ b/arch/powerpc/platforms/powernv/opal-imc.c
@@ -115,8 +115,10 @@ static int imc_get_mem_addr_nest(struct device_node *node,
return -ENOMEM;
chipid_arr = kcalloc(nr_chips, sizeof(*chipid_arr), GFP_KERNEL);
- if (!chipid_arr)
+ if (!chipid_arr) {
+ kfree(base_addr_arr);
return -ENOMEM;
+ }
if (of_property_read_u32_array(node, "chip-id", chipid_arr, nr_chips))
goto error;
@@ -143,7 +145,6 @@ static int imc_get_mem_addr_nest(struct device_node *node,
return 0;
error:
- kfree(pmu_ptr->mem_info);
kfree(base_addr_arr);
kfree(chipid_arr);
return -1;
@@ -183,8 +184,14 @@ static int imc_pmu_create(struct device_node *parent, int pmu_index, int domain)
/* Function to register IMC pmu */
ret = init_imc_pmu(parent, pmu_ptr, pmu_index);
- if (ret)
+ if (ret) {
pr_err("IMC PMU %s Register failed\n", pmu_ptr->pmu.name);
+ kfree(pmu_ptr->pmu.name);
+ if (pmu_ptr->domain == IMC_DOMAIN_NEST)
+ kfree(pmu_ptr->mem_info);
+ kfree(pmu_ptr);
+ return ret;
+ }
return 0;
--
2.7.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox