Commit f34b6c72 authored by sukadev@linux.vnet.ibm.com's avatar sukadev@linux.vnet.ibm.com Committed by Michael Ellerman

powerpc/perf/hv-24x7: Use per-cpu page buffer

The 24x7 counters are continuously running and not updated on an
interrupt. So we record the event counts when stopping the event or
deleting it.

But to "read" a single counter in 24x7, we allocate a page and pass it
into the hypervisor (The HV returns the page full of counters from which
we extract the specific counter for this event).

We allocate a page using GFP_USER and when deleting the event, we end up
with the following warning because we are blocking in interrupt context.

  [  698.641709] BUG: scheduling while atomic: swapper/0/0/0x10010000

We could use GFP_ATOMIC but that could result in failures. Pre-allocate
a buffer so we don't have to allocate in interrupt context. Further as
Michael Ellerman suggested, use Per-CPU buffer so we only need to
allocate once per CPU.

Cc: stable@vger.kernel.org
Signed-off-by: default avatarSukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent b123429e
...@@ -217,11 +217,14 @@ static bool is_physical_domain(int domain) ...@@ -217,11 +217,14 @@ static bool is_physical_domain(int domain)
domain == HV_24X7_PERF_DOMAIN_PHYSICAL_CORE; domain == HV_24X7_PERF_DOMAIN_PHYSICAL_CORE;
} }
DEFINE_PER_CPU(char, hv_24x7_reqb[4096]) __aligned(4096);
DEFINE_PER_CPU(char, hv_24x7_resb[4096]) __aligned(4096);
static unsigned long single_24x7_request(u8 domain, u32 offset, u16 ix, static unsigned long single_24x7_request(u8 domain, u32 offset, u16 ix,
u16 lpar, u64 *res, u16 lpar, u64 *res,
bool success_expected) bool success_expected)
{ {
unsigned long ret = -ENOMEM; unsigned long ret;
/* /*
* request_buffer and result_buffer are not required to be 4k aligned, * request_buffer and result_buffer are not required to be 4k aligned,
...@@ -243,13 +246,11 @@ static unsigned long single_24x7_request(u8 domain, u32 offset, u16 ix, ...@@ -243,13 +246,11 @@ static unsigned long single_24x7_request(u8 domain, u32 offset, u16 ix,
BUILD_BUG_ON(sizeof(*request_buffer) > 4096); BUILD_BUG_ON(sizeof(*request_buffer) > 4096);
BUILD_BUG_ON(sizeof(*result_buffer) > 4096); BUILD_BUG_ON(sizeof(*result_buffer) > 4096);
request_buffer = kmem_cache_zalloc(hv_page_cache, GFP_USER); request_buffer = (void *)get_cpu_var(hv_24x7_reqb);
if (!request_buffer) result_buffer = (void *)get_cpu_var(hv_24x7_resb);
goto out;
result_buffer = kmem_cache_zalloc(hv_page_cache, GFP_USER); memset(request_buffer, 0, 4096);
if (!result_buffer) memset(result_buffer, 0, 4096);
goto out_free_request_buffer;
*request_buffer = (struct reqb) { *request_buffer = (struct reqb) {
.buf = { .buf = {
...@@ -278,15 +279,11 @@ static unsigned long single_24x7_request(u8 domain, u32 offset, u16 ix, ...@@ -278,15 +279,11 @@ static unsigned long single_24x7_request(u8 domain, u32 offset, u16 ix,
domain, offset, ix, lpar, ret, ret, domain, offset, ix, lpar, ret, ret,
result_buffer->buf.detailed_rc, result_buffer->buf.detailed_rc,
result_buffer->buf.failing_request_ix); result_buffer->buf.failing_request_ix);
goto out_free_result_buffer; goto out;
} }
*res = be64_to_cpu(result_buffer->result); *res = be64_to_cpu(result_buffer->result);
out_free_result_buffer:
kfree(result_buffer);
out_free_request_buffer:
kfree(request_buffer);
out: out:
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment