1  /* SPDX-License-Identifier: GPL-2.0-or-later */
2  #ifndef __ASM_POWERPC_IMC_PMU_H
3  #define __ASM_POWERPC_IMC_PMU_H
4  
5  /*
6   * IMC Nest Performance Monitor counter support.
7   *
8   * Copyright (C) 2017 Madhavan Srinivasan, IBM Corporation.
9   *           (C) 2017 Anju T Sudhakar, IBM Corporation.
10   *           (C) 2017 Hemant K Shaw, IBM Corporation.
11   */
12  
13  #include <linux/perf_event.h>
14  #include <linux/slab.h>
15  #include <linux/of.h>
16  #include <linux/io.h>
17  #include <asm/opal.h>
18  
19  /*
20   * Compatibility macros for IMC devices
21   */
22  #define IMC_DTB_COMPAT			"ibm,opal-in-memory-counters"
23  #define IMC_DTB_UNIT_COMPAT		"ibm,imc-counters"
24  
25  
26  /*
27   * LDBAR: Counter address and Enable/Disable macro.
28   * perf/imc-pmu.c has the LDBAR layout information.
29   */
30  #define THREAD_IMC_LDBAR_MASK           0x0003ffffffffe000ULL
31  #define THREAD_IMC_ENABLE               0x8000000000000000ULL
32  #define TRACE_IMC_ENABLE		0x4000000000000000ULL
33  
34  /*
35   * For debugfs interface for imc-mode and imc-command
36   */
37  #define IMC_CNTL_BLK_OFFSET		0x3FC00
38  #define IMC_CNTL_BLK_CMD_OFFSET		8
39  #define IMC_CNTL_BLK_MODE_OFFSET	32
40  
41  /*
42   * Structure to hold memory address information for imc units.
43   */
44  struct imc_mem_info {
45  	u64 *vbase;
46  	u32 id;
47  };
48  
49  /*
50   * Place holder for nest pmu events and values.
51   */
52  struct imc_events {
53  	u32 value;
54  	char *name;
55  	char *unit;
56  	char *scale;
57  };
58  
59  /*
60   * Trace IMC hardware updates a 64bytes record on
61   * Core Performance Monitoring Counter (CPMC)
62   * overflow. Here is the layout for the trace imc record
63   *
64   * DW 0 : Timebase
65   * DW 1 : Program Counter
66   * DW 2 : PIDR information
67   * DW 3 : CPMC1
68   * DW 4 : CPMC2
69   * DW 5 : CPMC3
70   * Dw 6 : CPMC4
71   * DW 7 : Timebase
72   * .....
73   *
74   * The following is the data structure to hold trace imc data.
75   */
76  struct trace_imc_data {
77  	__be64 tb1;
78  	__be64 ip;
79  	__be64 val;
80  	__be64 cpmc1;
81  	__be64 cpmc2;
82  	__be64 cpmc3;
83  	__be64 cpmc4;
84  	__be64 tb2;
85  };
86  
87  /* Event attribute array index */
88  #define IMC_FORMAT_ATTR		0
89  #define IMC_EVENT_ATTR		1
90  #define IMC_CPUMASK_ATTR	2
91  #define IMC_NULL_ATTR		3
92  
93  /* PMU Format attribute macros */
94  #define IMC_EVENT_OFFSET_MASK	0xffffffffULL
95  
96  /*
97   * Macro to mask bits 0:21 of first double word(which is the timebase) to
98   * compare with 8th double word (timebase) of trace imc record data.
99   */
100  #define IMC_TRACE_RECORD_TB1_MASK      0x3ffffffffffULL
101  
102  /*
103   * Bit 0:1 in third DW of IMC trace record
104   * specifies the MSR[HV PR] values.
105   */
106  #define IMC_TRACE_RECORD_VAL_HVPR(x)	((x) >> 62)
107  
108  /*
109   * Device tree parser code detects IMC pmu support and
110   * registers new IMC pmus. This structure will hold the
111   * pmu functions, events, counter memory information
112   * and attrs for each imc pmu and will be referenced at
113   * the time of pmu registration.
114   */
115  struct imc_pmu {
116  	struct pmu pmu;
117  	struct imc_mem_info *mem_info;
118  	struct imc_events *events;
119  	/*
120  	 * Attribute groups for the PMU. Slot 0 used for
121  	 * format attribute, slot 1 used for cpusmask attribute,
122  	 * slot 2 used for event attribute. Slot 3 keep as
123  	 * NULL.
124  	 */
125  	const struct attribute_group *attr_groups[4];
126  	u32 counter_mem_size;
127  	int domain;
128  	/*
129  	 * flag to notify whether the memory is mmaped
130  	 * or allocated by kernel.
131  	 */
132  	bool imc_counter_mmaped;
133  };
134  
135  /*
136   * Structure to hold id, lock and reference count for the imc events which
137   * are inited.
138   */
139  struct imc_pmu_ref {
140  	spinlock_t lock;
141  	unsigned int id;
142  	int refc;
143  };
144  
145  /*
146   * In-Memory Collection Counters type.
147   * Data comes from Device tree.
148   * Three device type are supported.
149   */
150  
151  enum {
152  	IMC_TYPE_THREAD		= 0x1,
153  	IMC_TYPE_TRACE		= 0x2,
154  	IMC_TYPE_CORE		= 0x4,
155  	IMC_TYPE_CHIP           = 0x10,
156  };
157  
158  /*
159   * Domains for IMC PMUs
160   */
161  #define IMC_DOMAIN_NEST		1
162  #define IMC_DOMAIN_CORE		2
163  #define IMC_DOMAIN_THREAD	3
164  /* For trace-imc the domain is still thread but it operates in trace-mode */
165  #define IMC_DOMAIN_TRACE	4
166  
167  extern int init_imc_pmu(struct device_node *parent,
168  				struct imc_pmu *pmu_ptr, int pmu_id);
169  extern void thread_imc_disable(void);
170  extern int get_max_nest_dev(void);
171  extern void unregister_thread_imc(void);
172  #endif /* __ASM_POWERPC_IMC_PMU_H */
173