On Thu, Aug 24, 2017 at 11:26:17AM +1000, Michael Ellerman wrote: > Peter Zijlstra <pet...@infradead.org> writes: > >> diff --git a/kernel/events/core.c b/kernel/events/core.c > >> index d704e23..b991af3 100644 > >> --- a/kernel/events/core.c > >> +++ b/kernel/events/core.c > >> @@ -6027,6 +6033,38 @@ void perf_output_sample(struct perf_output_handle > >> *handle, > >> } > >> } > >> > >> +static u64 perf_virt_to_phys(u64 virt) > >> +{ > >> + u64 phys_addr = 0; > >> + struct page *p = NULL; > >> + > >> + if (!virt) > >> + return 0; > >> + > >> + if (virt >= TASK_SIZE) { > >> + /* If it's vmalloc()d memory, leave phys_addr as 0 */ > >> + if (virt_addr_valid(virt) && > >> + !(virt >= VMALLOC_START && virt < VMALLOC_END)) > >> + phys_addr = (u64)virt_to_phys((void *)(uintptr_t)virt); > >> + } else { > >> + /* > >> + * Walking the pages tables for user address. > >> + * Interrupts are disabled, so it prevents any tear down > >> + * of the page tables. > >> + * Try IRQ-safe __get_user_pages_fast first. > >> + * If failed, leave phys_addr as 0. > >> + */ > >> + if ((current->mm != NULL) && > >> + (__get_user_pages_fast(virt, 1, 0, &p) == 1)) > >> + phys_addr = page_to_phys(p) + virt % PAGE_SIZE; > >> + > >> + if (p) > >> + put_page(p); > >> + } > >> + > >> + return phys_addr; > >> +} > > > > Michael, does this work for PPC as is? > > I think so. > > We have about 8 MMUs and 32-bit and 64-bit so it's a bit hard to say for > sure.
You can limit it to those that include a PMU that supports data->addr, which is book3s, whatever that gets you. > I'm pretty sure virt_addr_valid() will exclude everything except the > linear mapping for us, so the vmalloc check is redundant but that's > fine. So that looks safe AFAICS. > > I'm not an expert on GUP fast, but AFAIK there's nothing special > required for us. Yeah, gup fast should work for you.