1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Virtual Processor Dispatch Trace Log
5 * (C) Copyright IBM Corporation 2009
7 * Author: Jeremy Kerr <jk@ozlabs.org>
10 #include <linux/slab.h>
11 #include <linux/spinlock.h>
13 #include <linux/uaccess.h>
14 #include <asm/firmware.h>
15 #include <asm/lppaca.h>
16 #include <asm/debugfs.h>
17 #include <asm/plpar_wrappers.h>
18 #include <asm/machdep.h>
21 struct dtl_entry *buf;
28 static DEFINE_PER_CPU(struct dtl, cpu_dtl);
31 * Dispatch trace log event mask:
32 * 0x7: 0x1: voluntary virtual processor waits
33 * 0x2: time-slice preempts
34 * 0x4: virtual partition memory page faults
36 static u8 dtl_event_mask = 0x7;
40 * Size of per-cpu log buffers. Firmware requires that the buffer does
41 * not cross a 4k boundary.
43 static int dtl_buf_entries = N_DISPATCH_LOG;
45 #ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
48 struct dtl_entry *write_ptr;
49 struct dtl_entry *buf;
50 struct dtl_entry *buf_end;
54 static DEFINE_PER_CPU(struct dtl_ring, dtl_rings);
56 static atomic_t dtl_count;
59 * The cpu accounting code controls the DTL ring buffer, and we get
60 * given entries as they are processed.
62 static void consume_dtle(struct dtl_entry *dtle, u64 index)
64 struct dtl_ring *dtlr = this_cpu_ptr(&dtl_rings);
65 struct dtl_entry *wp = dtlr->write_ptr;
66 struct lppaca *vpa = local_paca->lppaca_ptr;
74 /* check for hypervisor ring buffer overflow, ignore this entry if so */
75 if (index + N_DISPATCH_LOG < be64_to_cpu(vpa->dtl_idx))
79 if (wp == dtlr->buf_end)
83 /* incrementing write_index makes the new entry visible */
88 static int dtl_start(struct dtl *dtl)
90 struct dtl_ring *dtlr = &per_cpu(dtl_rings, dtl->cpu);
93 dtlr->buf_end = dtl->buf + dtl->buf_entries;
94 dtlr->write_index = 0;
96 /* setting write_ptr enables logging into our buffer */
98 dtlr->write_ptr = dtl->buf;
100 /* enable event logging */
101 dtlr->saved_dtl_mask = lppaca_of(dtl->cpu).dtl_enable_mask;
102 lppaca_of(dtl->cpu).dtl_enable_mask |= dtl_event_mask;
104 dtl_consumer = consume_dtle;
105 atomic_inc(&dtl_count);
109 static void dtl_stop(struct dtl *dtl)
111 struct dtl_ring *dtlr = &per_cpu(dtl_rings, dtl->cpu);
113 dtlr->write_ptr = NULL;
118 /* restore dtl_enable_mask */
119 lppaca_of(dtl->cpu).dtl_enable_mask = dtlr->saved_dtl_mask;
121 if (atomic_dec_and_test(&dtl_count))
125 static u64 dtl_current_index(struct dtl *dtl)
127 return per_cpu(dtl_rings, dtl->cpu).write_index;
130 #else /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
132 static int dtl_start(struct dtl *dtl)
137 /* Register our dtl buffer with the hypervisor. The HV expects the
138 * buffer size to be passed in the second word of the buffer */
139 ((u32 *)dtl->buf)[1] = cpu_to_be32(DISPATCH_LOG_BYTES);
141 hwcpu = get_hard_smp_processor_id(dtl->cpu);
142 addr = __pa(dtl->buf);
143 ret = register_dtl(hwcpu, addr);
145 printk(KERN_WARNING "%s: DTL registration for cpu %d (hw %d) "
146 "failed with %d\n", __func__, dtl->cpu, hwcpu, ret);
150 /* set our initial buffer indices */
151 lppaca_of(dtl->cpu).dtl_idx = 0;
153 /* ensure that our updates to the lppaca fields have occurred before
154 * we actually enable the logging */
157 /* enable event logging */
158 lppaca_of(dtl->cpu).dtl_enable_mask = dtl_event_mask;
163 static void dtl_stop(struct dtl *dtl)
165 int hwcpu = get_hard_smp_processor_id(dtl->cpu);
167 lppaca_of(dtl->cpu).dtl_enable_mask = 0x0;
169 unregister_dtl(hwcpu);
172 static u64 dtl_current_index(struct dtl *dtl)
174 return be64_to_cpu(lppaca_of(dtl->cpu).dtl_idx);
176 #endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
178 static int dtl_enable(struct dtl *dtl)
182 struct dtl_entry *buf = NULL;
187 /* only allow one reader */
191 n_entries = dtl_buf_entries;
192 buf = kmem_cache_alloc_node(dtl_cache, GFP_KERNEL, cpu_to_node(dtl->cpu));
194 printk(KERN_WARNING "%s: buffer alloc failed for cpu %d\n",
199 spin_lock(&dtl->lock);
202 /* store the original allocation size for use during read */
203 dtl->buf_entries = n_entries;
210 spin_unlock(&dtl->lock);
213 kmem_cache_free(dtl_cache, buf);
217 static void dtl_disable(struct dtl *dtl)
219 spin_lock(&dtl->lock);
221 kmem_cache_free(dtl_cache, dtl->buf);
223 dtl->buf_entries = 0;
224 spin_unlock(&dtl->lock);
229 static int dtl_file_open(struct inode *inode, struct file *filp)
231 struct dtl *dtl = inode->i_private;
234 rc = dtl_enable(dtl);
238 filp->private_data = dtl;
242 static int dtl_file_release(struct inode *inode, struct file *filp)
244 struct dtl *dtl = inode->i_private;
249 static ssize_t dtl_file_read(struct file *filp, char __user *buf, size_t len,
252 long int rc, n_read, n_req, read_size;
254 u64 cur_idx, last_idx, i;
256 if ((len % sizeof(struct dtl_entry)) != 0)
259 dtl = filp->private_data;
261 /* requested number of entries to read */
262 n_req = len / sizeof(struct dtl_entry);
264 /* actual number of entries read */
267 spin_lock(&dtl->lock);
269 cur_idx = dtl_current_index(dtl);
270 last_idx = dtl->last_idx;
272 if (last_idx + dtl->buf_entries <= cur_idx)
273 last_idx = cur_idx - dtl->buf_entries + 1;
275 if (last_idx + n_req > cur_idx)
276 n_req = cur_idx - last_idx;
279 dtl->last_idx = last_idx + n_req;
281 spin_unlock(&dtl->lock);
286 i = last_idx % dtl->buf_entries;
288 /* read the tail of the buffer if we've wrapped */
289 if (i + n_req > dtl->buf_entries) {
290 read_size = dtl->buf_entries - i;
292 rc = copy_to_user(buf, &dtl->buf[i],
293 read_size * sizeof(struct dtl_entry));
300 buf += read_size * sizeof(struct dtl_entry);
303 /* .. and now the head */
304 rc = copy_to_user(buf, &dtl->buf[i], n_req * sizeof(struct dtl_entry));
310 return n_read * sizeof(struct dtl_entry);
313 static const struct file_operations dtl_fops = {
314 .open = dtl_file_open,
315 .release = dtl_file_release,
316 .read = dtl_file_read,
320 static struct dentry *dtl_dir;
322 static int dtl_setup_file(struct dtl *dtl)
326 sprintf(name, "cpu-%d", dtl->cpu);
328 dtl->file = debugfs_create_file(name, 0400, dtl_dir, dtl, &dtl_fops);
335 static int dtl_init(void)
337 struct dentry *event_mask_file, *buf_entries_file;
340 if (!firmware_has_feature(FW_FEATURE_SPLPAR))
343 /* set up common debugfs structure */
346 dtl_dir = debugfs_create_dir("dtl", powerpc_debugfs_root);
348 printk(KERN_WARNING "%s: can't create dtl root dir\n",
353 event_mask_file = debugfs_create_x8("dtl_event_mask", 0600,
354 dtl_dir, &dtl_event_mask);
355 buf_entries_file = debugfs_create_u32("dtl_buf_entries", 0400,
356 dtl_dir, &dtl_buf_entries);
358 if (!event_mask_file || !buf_entries_file) {
359 printk(KERN_WARNING "%s: can't create dtl files\n", __func__);
363 /* set up the per-cpu log structures */
364 for_each_possible_cpu(i) {
365 struct dtl *dtl = &per_cpu(cpu_dtl, i);
366 spin_lock_init(&dtl->lock);
369 rc = dtl_setup_file(dtl);
377 debugfs_remove_recursive(dtl_dir);
381 machine_arch_initcall(pseries, dtl_init);