summaryrefslogtreecommitdiff
path: root/arch/s390/kernel/perf_cpum_sf.c
diff options
context:
space:
mode:
authorThomas Richter <tmricht@linux.ibm.com>2023-01-13 12:29:55 +0100
committerHeiko Carstens <hca@linux.ibm.com>2023-01-22 18:42:35 +0100
commitd924ecdb703765cdc75be5f28aaa1140b9106f84 (patch)
tree4b97a7250556ac7fbdb799ea09cc092b9073fd3a /arch/s390/kernel/perf_cpum_sf.c
parent78157b4791a3e37659b33388fb639a2defc6e6e9 (diff)
s390/cpum_sf: diagnostic sampling buffer setup to handle virtual addresses
The CPU Measurement Sampling Facility (CPUM_SF) installs large buffers to save samples collected by hardware. These buffers are organized as Sample Data Buffer Tables (SDBT) and Sample Data Buffers (SDB). SDBs contain the samples which are extracted and saved in the perf ring buffer. The SDBTs are chained using real addresses and refer to SDBs using real addresses. The diagnostic sampling setup uses buffers provided by the process which invokes perf_event_open system call. The buffers are memory mapped. The buffers have been allocated by the kernel event subsystem. Add proper virtual to phyiscal address translation to the buffer chaining. The current constraint which requires virtual equals real address layout is removed. Signed-off-by: Thomas Richter <tmricht@linux.ibm.com> Acked-by: Heiko Carstens <hca@linux.ibm.com> Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
Diffstat (limited to 'arch/s390/kernel/perf_cpum_sf.c')
-rw-r--r--arch/s390/kernel/perf_cpum_sf.c14
1 files changed, 6 insertions, 8 deletions
diff --git a/arch/s390/kernel/perf_cpum_sf.c b/arch/s390/kernel/perf_cpum_sf.c
index d7940a7dd7c3..d61cf80511e8 100644
--- a/arch/s390/kernel/perf_cpum_sf.c
+++ b/arch/s390/kernel/perf_cpum_sf.c
@@ -1491,9 +1491,7 @@ static int aux_output_begin(struct perf_output_handle *handle,
struct aux_buffer *aux,
struct cpu_hw_sf *cpuhw)
{
- unsigned long range;
- unsigned long i, range_scan, idx;
- unsigned long head, base, offset;
+ unsigned long range, i, range_scan, idx, head, base, offset;
struct hws_trailer_entry *te;
if (WARN_ON_ONCE(handle->head & ~PAGE_MASK))
@@ -1534,8 +1532,8 @@ static int aux_output_begin(struct perf_output_handle *handle,
head = aux_sdb_index(aux, aux->head);
base = aux->sdbt_index[head / CPUM_SF_SDB_PER_TABLE];
offset = head % CPUM_SF_SDB_PER_TABLE;
- cpuhw->lsctl.tear = base + offset * sizeof(unsigned long);
- cpuhw->lsctl.dear = aux->sdb_index[head];
+ cpuhw->lsctl.tear = virt_to_phys((void *)base) + offset * sizeof(unsigned long);
+ cpuhw->lsctl.dear = virt_to_phys((void *)aux->sdb_index[head]);
debug_sprintf_event(sfdbg, 6, "%s: head %ld alert %ld empty %ld "
"index %ld tear %#lx dear %#lx\n", __func__,
@@ -1845,18 +1843,18 @@ static void *aux_buffer_setup(struct perf_event *event, void **pages,
goto no_sdbt;
aux->sdbt_index[sfb->num_sdbt++] = (unsigned long)new;
/* Link current page to tail of chain */
- *tail = (unsigned long)(void *) new + 1;
+ *tail = virt_to_phys(new) + 1;
tail = new;
}
/* Tail is the entry in a SDBT */
- *tail = (unsigned long)pages[i];
+ *tail = virt_to_phys(pages[i]);
aux->sdb_index[i] = (unsigned long)pages[i];
aux_sdb_init((unsigned long)pages[i]);
}
sfb->num_sdb = nr_pages;
/* Link the last entry in the SDBT to the first SDBT */
- *tail = (unsigned long) sfb->sdbt + 1;
+ *tail = virt_to_phys(sfb->sdbt) + 1;
sfb->tail = tail;
/*