xref: /linux-6.15/include/linux/pstore.h (revision 9abdcccc)
1 /*
2  * Persistent Storage - pstore.h
3  *
4  * Copyright (C) 2010 Intel Corporation <[email protected]>
5  *
6  * This code is the generic layer to export data records from platform
7  * level persistent storage via a file system.
8  *
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License version 2 as
11  *  published by the Free Software Foundation.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22 #ifndef _LINUX_PSTORE_H
23 #define _LINUX_PSTORE_H
24 
25 #include <linux/compiler.h>
26 #include <linux/errno.h>
27 #include <linux/kmsg_dump.h>
28 #include <linux/mutex.h>
29 #include <linux/spinlock.h>
30 #include <linux/time.h>
31 #include <linux/types.h>
32 
33 struct module;
34 
35 /* pstore record types (see fs/pstore/inode.c for filename templates) */
36 enum pstore_type_id {
37 	PSTORE_TYPE_DMESG	= 0,
38 	PSTORE_TYPE_MCE		= 1,
39 	PSTORE_TYPE_CONSOLE	= 2,
40 	PSTORE_TYPE_FTRACE	= 3,
41 	/* PPC64 partition types */
42 	PSTORE_TYPE_PPC_RTAS	= 4,
43 	PSTORE_TYPE_PPC_OF	= 5,
44 	PSTORE_TYPE_PPC_COMMON	= 6,
45 	PSTORE_TYPE_PMSG	= 7,
46 	PSTORE_TYPE_PPC_OPAL	= 8,
47 	PSTORE_TYPE_UNKNOWN	= 255
48 };
49 
50 struct pstore_info;
51 /**
52  * struct pstore_record - details of a pstore record entry
53  * @psi:	pstore backend driver information
54  * @type:	pstore record type
55  * @id:		per-type unique identifier for record
56  * @time:	timestamp of the record
57  * @count:	for PSTORE_TYPE_DMESG, the Oops count.
58  * @compressed:	for PSTORE_TYPE_DMESG, whether the buffer is compressed
59  * @buf:	pointer to record contents
60  * @size:	size of @buf
61  * @ecc_notice_size:
62  *		ECC information for @buf
63  */
64 struct pstore_record {
65 	struct pstore_info	*psi;
66 	enum pstore_type_id	type;
67 	u64			id;
68 	struct timespec		time;
69 	int			count;
70 	bool			compressed;
71 	char			*buf;
72 	ssize_t			size;
73 	ssize_t			ecc_notice_size;
74 };
75 
76 /**
77  * struct pstore_info - backend pstore driver structure
78  *
79  * @owner:	module which is repsonsible for this backend driver
80  * @name:	name of the backend driver
81  *
82  * @buf_lock:	spinlock to serialize access to @buf
83  * @buf:	preallocated crash dump buffer
84  * @bufsize:	size of @buf available for crash dump writes
85  *
86  * @read_mutex:	serializes @open, @read, @close, and @erase callbacks
87  * @flags:	bitfield of frontends the backend can accept writes for
88  * @data:	backend-private pointer passed back during callbacks
89  *
90  * Callbacks:
91  *
92  * @open:
93  *	Notify backend that pstore is starting a full read of backend
94  *	records. Followed by one or more @read calls, and a final @close.
95  *
96  *	@psi:	in: pointer to the struct pstore_info for the backend
97  *
98  *	Returns 0 on success, and non-zero on error.
99  *
100  * @close:
101  *	Notify backend that pstore has finished a full read of backend
102  *	records. Always preceded by an @open call and one or more @read
103  *	calls.
104  *
105  *	@psi:	in: pointer to the struct pstore_info for the backend
106  *
107  *	Returns 0 on success, and non-zero on error. (Though pstore will
108  *	ignore the error.)
109  *
110  * @read:
111  *	Read next available backend record. Called after a successful
112  *	@open.
113  *
114  *	@id:	out: unique identifier for the record
115  *	@type:	out: pstore record type
116  *	@count: out: for PSTORE_TYPE_DMESG, the Oops count.
117  *	@time:	out: timestamp for the record
118  *	@buf:	out: kmalloc copy of record contents, to be freed by pstore
119  *	@compressed:
120  *		out: if the record contents are compressed
121  *	@ecc_notice_size:
122  *		out: ECC information
123  *	@psi:	in: pointer to the struct pstore_info for the backend
124  *
125  *	Returns record size on success, zero when no more records are
126  *	available, or negative on error.
127  *
128  * @write:
129  *	Perform a frontend notification of a write to a backend record. The
130  *	data to be stored has already been written to the registered @buf
131  *	of the @psi structure.
132  *
133  *	@type:	in: pstore record type to write
134  *	@reason:
135  *		in: pstore write reason
136  *	@id:	out: unique identifier for the record
137  *	@part:	in: position in a multipart write
138  *	@count:	in: increasing from 0 since boot, the number of this Oops
139  *	@compressed:
140  *		in: if the record is compressed
141  *	@size:	in: size of the write
142  *	@psi:	in: pointer to the struct pstore_info for the backend
143  *
144  *	Returns 0 on success, and non-zero on error.
145  *
146  * @write_buf:
147  *	Perform a frontend write to a backend record, using a specified
148  *	buffer. Unlike @write, this does not use the @psi @buf.
149  *
150  *	@type:	in: pstore record type to write
151  *	@reason:
152  *		in: pstore write reason
153  *	@id:	out: unique identifier for the record
154  *	@part:	in: position in a multipart write
155  *	@buf:	in: pointer to contents to write to backend record
156  *	@compressed:
157  *		in: if the record is compressed
158  *	@size:	in: size of the write
159  *	@psi:	in: pointer to the struct pstore_info for the backend
160  *
161  *	Returns 0 on success, and non-zero on error.
162  *
163  * @write_buf_user:
164  *	Perform a frontend write to a backend record, using a specified
165  *	buffer that is coming directly from userspace.
166  *
167  *	@type:	in: pstore record type to write
168  *	@reason:
169  *		in: pstore write reason
170  *	@id:	out: unique identifier for the record
171  *	@part:	in: position in a multipart write
172  *	@buf:	in: pointer to userspace contents to write to backend record
173  *	@compressed:
174  *		in: if the record is compressed
175  *	@size:	in: size of the write
176  *	@psi:	in: pointer to the struct pstore_info for the backend
177  *
178  *	Returns 0 on success, and non-zero on error.
179  *
180  * @erase:
181  *	Delete a record from backend storage.  Different backends
182  *	identify records differently, so all possible methods of
183  *	identification are included to help the backend locate the
184  *	record to remove.
185  *
186  *	@type:	in: pstore record type to write
187  *	@id:	in: per-type unique identifier for the record
188  *	@count:	in: Oops count
189  *	@time:	in: timestamp for the record
190  *	@psi:	in: pointer to the struct pstore_info for the backend
191  *
192  *	Returns 0 on success, and non-zero on error.
193  *
194  */
195 struct pstore_info {
196 	struct module	*owner;
197 	char		*name;
198 
199 	spinlock_t	buf_lock;
200 	char		*buf;
201 	size_t		bufsize;
202 
203 	struct mutex	read_mutex;
204 
205 	int		flags;
206 	void		*data;
207 
208 	int		(*open)(struct pstore_info *psi);
209 	int		(*close)(struct pstore_info *psi);
210 	ssize_t		(*read)(u64 *id, enum pstore_type_id *type,
211 			int *count, struct timespec *time, char **buf,
212 			bool *compressed, ssize_t *ecc_notice_size,
213 			struct pstore_info *psi);
214 	int		(*write)(enum pstore_type_id type,
215 			enum kmsg_dump_reason reason, u64 *id,
216 			unsigned int part, int count, bool compressed,
217 			size_t size, struct pstore_info *psi);
218 	int		(*write_buf)(enum pstore_type_id type,
219 			enum kmsg_dump_reason reason, u64 *id,
220 			unsigned int part, const char *buf, bool compressed,
221 			size_t size, struct pstore_info *psi);
222 	int		(*write_buf_user)(enum pstore_type_id type,
223 			enum kmsg_dump_reason reason, u64 *id,
224 			unsigned int part, const char __user *buf,
225 			bool compressed, size_t size, struct pstore_info *psi);
226 	int		(*erase)(enum pstore_type_id type, u64 id,
227 			int count, struct timespec time,
228 			struct pstore_info *psi);
229 };
230 
231 /* Supported frontends */
232 #define PSTORE_FLAGS_DMESG	(1 << 0)
233 #define PSTORE_FLAGS_CONSOLE	(1 << 1)
234 #define PSTORE_FLAGS_FTRACE	(1 << 2)
235 #define PSTORE_FLAGS_PMSG	(1 << 3)
236 
237 extern int pstore_register(struct pstore_info *);
238 extern void pstore_unregister(struct pstore_info *);
239 extern bool pstore_cannot_block_path(enum kmsg_dump_reason reason);
240 
241 struct pstore_ftrace_record {
242 	unsigned long ip;
243 	unsigned long parent_ip;
244 	u64 ts;
245 };
246 
247 /*
248  * ftrace related stuff: Both backends and frontends need these so expose
249  * them here.
250  */
251 
252 #if NR_CPUS <= 2 && defined(CONFIG_ARM_THUMB)
253 #define PSTORE_CPU_IN_IP 0x1
254 #elif NR_CPUS <= 4 && defined(CONFIG_ARM)
255 #define PSTORE_CPU_IN_IP 0x3
256 #endif
257 
258 #define TS_CPU_SHIFT 8
259 #define TS_CPU_MASK (BIT(TS_CPU_SHIFT) - 1)
260 
261 /*
262  * If CPU number can be stored in IP, store it there, otherwise store it in
263  * the time stamp. This means more timestamp resolution is available when
264  * the CPU can be stored in the IP.
265  */
266 #ifdef PSTORE_CPU_IN_IP
267 static inline void
268 pstore_ftrace_encode_cpu(struct pstore_ftrace_record *rec, unsigned int cpu)
269 {
270 	rec->ip |= cpu;
271 }
272 
273 static inline unsigned int
274 pstore_ftrace_decode_cpu(struct pstore_ftrace_record *rec)
275 {
276 	return rec->ip & PSTORE_CPU_IN_IP;
277 }
278 
279 static inline u64
280 pstore_ftrace_read_timestamp(struct pstore_ftrace_record *rec)
281 {
282 	return rec->ts;
283 }
284 
285 static inline void
286 pstore_ftrace_write_timestamp(struct pstore_ftrace_record *rec, u64 val)
287 {
288 	rec->ts = val;
289 }
290 #else
291 static inline void
292 pstore_ftrace_encode_cpu(struct pstore_ftrace_record *rec, unsigned int cpu)
293 {
294 	rec->ts &= ~(TS_CPU_MASK);
295 	rec->ts |= cpu;
296 }
297 
298 static inline unsigned int
299 pstore_ftrace_decode_cpu(struct pstore_ftrace_record *rec)
300 {
301 	return rec->ts & TS_CPU_MASK;
302 }
303 
304 static inline u64
305 pstore_ftrace_read_timestamp(struct pstore_ftrace_record *rec)
306 {
307 	return rec->ts >> TS_CPU_SHIFT;
308 }
309 
310 static inline void
311 pstore_ftrace_write_timestamp(struct pstore_ftrace_record *rec, u64 val)
312 {
313 	rec->ts = (rec->ts & TS_CPU_MASK) | (val << TS_CPU_SHIFT);
314 }
315 #endif
316 
317 #endif /*_LINUX_PSTORE_H*/
318