1ca01d6ddSTony Luck /* 2ca01d6ddSTony Luck * Persistent Storage - pstore.h 3ca01d6ddSTony Luck * 4ca01d6ddSTony Luck * Copyright (C) 2010 Intel Corporation <tony.luck@intel.com> 5ca01d6ddSTony Luck * 6ca01d6ddSTony Luck * This code is the generic layer to export data records from platform 7ca01d6ddSTony Luck * level persistent storage via a file system. 8ca01d6ddSTony Luck * 9ca01d6ddSTony Luck * This program is free software; you can redistribute it and/or modify 10ca01d6ddSTony Luck * it under the terms of the GNU General Public License version 2 as 11ca01d6ddSTony Luck * published by the Free Software Foundation. 12ca01d6ddSTony Luck * 13ca01d6ddSTony Luck * This program is distributed in the hope that it will be useful, 14ca01d6ddSTony Luck * but WITHOUT ANY WARRANTY; without even the implied warranty of 15ca01d6ddSTony Luck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16ca01d6ddSTony Luck * GNU General Public License for more details. 17ca01d6ddSTony Luck * 18ca01d6ddSTony Luck * You should have received a copy of the GNU General Public License 19ca01d6ddSTony Luck * along with this program; if not, write to the Free Software 20ca01d6ddSTony Luck * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21ca01d6ddSTony Luck */ 22ca01d6ddSTony Luck #ifndef _LINUX_PSTORE_H 23ca01d6ddSTony Luck #define _LINUX_PSTORE_H 24ca01d6ddSTony Luck 255bf6d1b9SMark Salyzyn #include <linux/compiler.h> 265bf6d1b9SMark Salyzyn #include <linux/errno.h> 273d6d8d20SKees Cook #include <linux/kmsg_dump.h> 2867a101f5SAnton Vorontsov #include <linux/mutex.h> 2967a101f5SAnton Vorontsov #include <linux/spinlock.h> 305bf6d1b9SMark Salyzyn #include <linux/time.h> 315bf6d1b9SMark Salyzyn #include <linux/types.h> 323d6d8d20SKees Cook 33*9abdccccSKees Cook struct module; 34*9abdccccSKees Cook 350edae0b3SKees Cook /* pstore record types (see fs/pstore/inode.c for filename templates) */ 36ca01d6ddSTony Luck enum pstore_type_id { 37ca01d6ddSTony Luck PSTORE_TYPE_DMESG = 0, 38ca01d6ddSTony Luck PSTORE_TYPE_MCE = 1, 39f29e5956SAnton Vorontsov PSTORE_TYPE_CONSOLE = 2, 40060287b8SAnton Vorontsov PSTORE_TYPE_FTRACE = 3, 4169020eeaSAruna Balakrishnaiah /* PPC64 partition types */ 4269020eeaSAruna Balakrishnaiah PSTORE_TYPE_PPC_RTAS = 4, 43f33f748cSAruna Balakrishnaiah PSTORE_TYPE_PPC_OF = 5, 44a5e4797bSAruna Balakrishnaiah PSTORE_TYPE_PPC_COMMON = 6, 459d5438f4SMark Salyzyn PSTORE_TYPE_PMSG = 7, 46ae011d2eSHari Bathini PSTORE_TYPE_PPC_OPAL = 8, 47ca01d6ddSTony Luck PSTORE_TYPE_UNKNOWN = 255 48ca01d6ddSTony Luck }; 49ca01d6ddSTony Luck 50*9abdccccSKees Cook struct pstore_info; 51*9abdccccSKees Cook /** 52*9abdccccSKees Cook * struct pstore_record - details of a pstore record entry 53*9abdccccSKees Cook * @psi: pstore backend driver information 54*9abdccccSKees Cook * @type: pstore record type 55*9abdccccSKees Cook * @id: per-type unique identifier for record 56*9abdccccSKees Cook * @time: timestamp of the record 57*9abdccccSKees Cook * @count: for PSTORE_TYPE_DMESG, the Oops count. 58*9abdccccSKees Cook * @compressed: for PSTORE_TYPE_DMESG, whether the buffer is compressed 59*9abdccccSKees Cook * @buf: pointer to record contents 60*9abdccccSKees Cook * @size: size of @buf 61*9abdccccSKees Cook * @ecc_notice_size: 62*9abdccccSKees Cook * ECC information for @buf 63*9abdccccSKees Cook */ 64*9abdccccSKees Cook struct pstore_record { 65*9abdccccSKees Cook struct pstore_info *psi; 66*9abdccccSKees Cook enum pstore_type_id type; 67*9abdccccSKees Cook u64 id; 68*9abdccccSKees Cook struct timespec time; 69*9abdccccSKees Cook int count; 70*9abdccccSKees Cook bool compressed; 71*9abdccccSKees Cook char *buf; 72*9abdccccSKees Cook ssize_t size; 73*9abdccccSKees Cook ssize_t ecc_notice_size; 74*9abdccccSKees Cook }; 7567a101f5SAnton Vorontsov 760edae0b3SKees Cook /** 770edae0b3SKees Cook * struct pstore_info - backend pstore driver structure 780edae0b3SKees Cook * 790edae0b3SKees Cook * @owner: module which is repsonsible for this backend driver 800edae0b3SKees Cook * @name: name of the backend driver 810edae0b3SKees Cook * 820edae0b3SKees Cook * @buf_lock: spinlock to serialize access to @buf 830edae0b3SKees Cook * @buf: preallocated crash dump buffer 840edae0b3SKees Cook * @bufsize: size of @buf available for crash dump writes 850edae0b3SKees Cook * 860edae0b3SKees Cook * @read_mutex: serializes @open, @read, @close, and @erase callbacks 870edae0b3SKees Cook * @flags: bitfield of frontends the backend can accept writes for 880edae0b3SKees Cook * @data: backend-private pointer passed back during callbacks 890edae0b3SKees Cook * 900edae0b3SKees Cook * Callbacks: 910edae0b3SKees Cook * 920edae0b3SKees Cook * @open: 930edae0b3SKees Cook * Notify backend that pstore is starting a full read of backend 940edae0b3SKees Cook * records. Followed by one or more @read calls, and a final @close. 950edae0b3SKees Cook * 960edae0b3SKees Cook * @psi: in: pointer to the struct pstore_info for the backend 970edae0b3SKees Cook * 980edae0b3SKees Cook * Returns 0 on success, and non-zero on error. 990edae0b3SKees Cook * 1000edae0b3SKees Cook * @close: 1010edae0b3SKees Cook * Notify backend that pstore has finished a full read of backend 1020edae0b3SKees Cook * records. Always preceded by an @open call and one or more @read 1030edae0b3SKees Cook * calls. 1040edae0b3SKees Cook * 1050edae0b3SKees Cook * @psi: in: pointer to the struct pstore_info for the backend 1060edae0b3SKees Cook * 1070edae0b3SKees Cook * Returns 0 on success, and non-zero on error. (Though pstore will 1080edae0b3SKees Cook * ignore the error.) 1090edae0b3SKees Cook * 1100edae0b3SKees Cook * @read: 1110edae0b3SKees Cook * Read next available backend record. Called after a successful 1120edae0b3SKees Cook * @open. 1130edae0b3SKees Cook * 1140edae0b3SKees Cook * @id: out: unique identifier for the record 1150edae0b3SKees Cook * @type: out: pstore record type 1160edae0b3SKees Cook * @count: out: for PSTORE_TYPE_DMESG, the Oops count. 1170edae0b3SKees Cook * @time: out: timestamp for the record 1180edae0b3SKees Cook * @buf: out: kmalloc copy of record contents, to be freed by pstore 1190edae0b3SKees Cook * @compressed: 1200edae0b3SKees Cook * out: if the record contents are compressed 1210edae0b3SKees Cook * @ecc_notice_size: 1220edae0b3SKees Cook * out: ECC information 1230edae0b3SKees Cook * @psi: in: pointer to the struct pstore_info for the backend 1240edae0b3SKees Cook * 1250edae0b3SKees Cook * Returns record size on success, zero when no more records are 1260edae0b3SKees Cook * available, or negative on error. 1270edae0b3SKees Cook * 1280edae0b3SKees Cook * @write: 1290edae0b3SKees Cook * Perform a frontend notification of a write to a backend record. The 1300edae0b3SKees Cook * data to be stored has already been written to the registered @buf 1310edae0b3SKees Cook * of the @psi structure. 1320edae0b3SKees Cook * 1330edae0b3SKees Cook * @type: in: pstore record type to write 1340edae0b3SKees Cook * @reason: 1350edae0b3SKees Cook * in: pstore write reason 1360edae0b3SKees Cook * @id: out: unique identifier for the record 1370edae0b3SKees Cook * @part: in: position in a multipart write 1380edae0b3SKees Cook * @count: in: increasing from 0 since boot, the number of this Oops 1390edae0b3SKees Cook * @compressed: 1400edae0b3SKees Cook * in: if the record is compressed 1410edae0b3SKees Cook * @size: in: size of the write 1420edae0b3SKees Cook * @psi: in: pointer to the struct pstore_info for the backend 1430edae0b3SKees Cook * 1440edae0b3SKees Cook * Returns 0 on success, and non-zero on error. 1450edae0b3SKees Cook * 1460edae0b3SKees Cook * @write_buf: 1470edae0b3SKees Cook * Perform a frontend write to a backend record, using a specified 1480edae0b3SKees Cook * buffer. Unlike @write, this does not use the @psi @buf. 1490edae0b3SKees Cook * 1500edae0b3SKees Cook * @type: in: pstore record type to write 1510edae0b3SKees Cook * @reason: 1520edae0b3SKees Cook * in: pstore write reason 1530edae0b3SKees Cook * @id: out: unique identifier for the record 1540edae0b3SKees Cook * @part: in: position in a multipart write 1550edae0b3SKees Cook * @buf: in: pointer to contents to write to backend record 1560edae0b3SKees Cook * @compressed: 1570edae0b3SKees Cook * in: if the record is compressed 1580edae0b3SKees Cook * @size: in: size of the write 1590edae0b3SKees Cook * @psi: in: pointer to the struct pstore_info for the backend 1600edae0b3SKees Cook * 1610edae0b3SKees Cook * Returns 0 on success, and non-zero on error. 1620edae0b3SKees Cook * 1630edae0b3SKees Cook * @write_buf_user: 1640edae0b3SKees Cook * Perform a frontend write to a backend record, using a specified 1650edae0b3SKees Cook * buffer that is coming directly from userspace. 1660edae0b3SKees Cook * 1670edae0b3SKees Cook * @type: in: pstore record type to write 1680edae0b3SKees Cook * @reason: 1690edae0b3SKees Cook * in: pstore write reason 1700edae0b3SKees Cook * @id: out: unique identifier for the record 1710edae0b3SKees Cook * @part: in: position in a multipart write 1720edae0b3SKees Cook * @buf: in: pointer to userspace contents to write to backend record 1730edae0b3SKees Cook * @compressed: 1740edae0b3SKees Cook * in: if the record is compressed 1750edae0b3SKees Cook * @size: in: size of the write 1760edae0b3SKees Cook * @psi: in: pointer to the struct pstore_info for the backend 1770edae0b3SKees Cook * 1780edae0b3SKees Cook * Returns 0 on success, and non-zero on error. 1790edae0b3SKees Cook * 1800edae0b3SKees Cook * @erase: 1810edae0b3SKees Cook * Delete a record from backend storage. Different backends 1820edae0b3SKees Cook * identify records differently, so all possible methods of 1830edae0b3SKees Cook * identification are included to help the backend locate the 1840edae0b3SKees Cook * record to remove. 1850edae0b3SKees Cook * 1860edae0b3SKees Cook * @type: in: pstore record type to write 1870edae0b3SKees Cook * @id: in: per-type unique identifier for the record 1880edae0b3SKees Cook * @count: in: Oops count 1890edae0b3SKees Cook * @time: in: timestamp for the record 1900edae0b3SKees Cook * @psi: in: pointer to the struct pstore_info for the backend 1910edae0b3SKees Cook * 1920edae0b3SKees Cook * Returns 0 on success, and non-zero on error. 1930edae0b3SKees Cook * 1940edae0b3SKees Cook */ 195ca01d6ddSTony Luck struct pstore_info { 196ca01d6ddSTony Luck struct module *owner; 197ca01d6ddSTony Luck char *name; 1980edae0b3SKees Cook 1990edae0b3SKees Cook spinlock_t buf_lock; 200ca01d6ddSTony Luck char *buf; 201ca01d6ddSTony Luck size_t bufsize; 2020edae0b3SKees Cook 2030edae0b3SKees Cook struct mutex read_mutex; 2040edae0b3SKees Cook 205df36ac1bSLuck, Tony int flags; 2060edae0b3SKees Cook void *data; 2070edae0b3SKees Cook 20806cf91b4SChen Gong int (*open)(struct pstore_info *psi); 20906cf91b4SChen Gong int (*close)(struct pstore_info *psi); 2108d38d74bSChen Gong ssize_t (*read)(u64 *id, enum pstore_type_id *type, 211755d4fe4SSeiji Aguchi int *count, struct timespec *time, char **buf, 2128cfc8ddcSGeliang Tang bool *compressed, ssize_t *ecc_notice_size, 2138cfc8ddcSGeliang Tang struct pstore_info *psi); 2143d6d8d20SKees Cook int (*write)(enum pstore_type_id type, 2153d6d8d20SKees Cook enum kmsg_dump_reason reason, u64 *id, 216b3b515bbSAruna Balakrishnaiah unsigned int part, int count, bool compressed, 2176bbbca73SAruna Balakrishnaiah size_t size, struct pstore_info *psi); 218897dba02SAnton Vorontsov int (*write_buf)(enum pstore_type_id type, 219897dba02SAnton Vorontsov enum kmsg_dump_reason reason, u64 *id, 220b3b515bbSAruna Balakrishnaiah unsigned int part, const char *buf, bool compressed, 2216bbbca73SAruna Balakrishnaiah size_t size, struct pstore_info *psi); 2225bf6d1b9SMark Salyzyn int (*write_buf_user)(enum pstore_type_id type, 2235bf6d1b9SMark Salyzyn enum kmsg_dump_reason reason, u64 *id, 2245bf6d1b9SMark Salyzyn unsigned int part, const char __user *buf, 2255bf6d1b9SMark Salyzyn bool compressed, size_t size, struct pstore_info *psi); 22656280682SMatthew Garrett int (*erase)(enum pstore_type_id type, u64 id, 227755d4fe4SSeiji Aguchi int count, struct timespec time, 228755d4fe4SSeiji Aguchi struct pstore_info *psi); 229ca01d6ddSTony Luck }; 230ca01d6ddSTony Luck 2310edae0b3SKees Cook /* Supported frontends */ 232c950fd6fSNamhyung Kim #define PSTORE_FLAGS_DMESG (1 << 0) 233c950fd6fSNamhyung Kim #define PSTORE_FLAGS_CONSOLE (1 << 1) 234c950fd6fSNamhyung Kim #define PSTORE_FLAGS_FTRACE (1 << 2) 235c950fd6fSNamhyung Kim #define PSTORE_FLAGS_PMSG (1 << 3) 236c950fd6fSNamhyung Kim 237ca01d6ddSTony Luck extern int pstore_register(struct pstore_info *); 238ee1d2674SGeliang Tang extern void pstore_unregister(struct pstore_info *); 2399f244e9cSSeiji Aguchi extern bool pstore_cannot_block_path(enum kmsg_dump_reason reason); 240ca01d6ddSTony Luck 241fbccdeb8SJoel Fernandes struct pstore_ftrace_record { 242fbccdeb8SJoel Fernandes unsigned long ip; 243fbccdeb8SJoel Fernandes unsigned long parent_ip; 244fbccdeb8SJoel Fernandes u64 ts; 245fbccdeb8SJoel Fernandes }; 246fbccdeb8SJoel Fernandes 247fbccdeb8SJoel Fernandes /* 248fbccdeb8SJoel Fernandes * ftrace related stuff: Both backends and frontends need these so expose 249fbccdeb8SJoel Fernandes * them here. 250fbccdeb8SJoel Fernandes */ 251fbccdeb8SJoel Fernandes 252fbccdeb8SJoel Fernandes #if NR_CPUS <= 2 && defined(CONFIG_ARM_THUMB) 253fbccdeb8SJoel Fernandes #define PSTORE_CPU_IN_IP 0x1 254fbccdeb8SJoel Fernandes #elif NR_CPUS <= 4 && defined(CONFIG_ARM) 255fbccdeb8SJoel Fernandes #define PSTORE_CPU_IN_IP 0x3 256fbccdeb8SJoel Fernandes #endif 257fbccdeb8SJoel Fernandes 258fbccdeb8SJoel Fernandes #define TS_CPU_SHIFT 8 259fbccdeb8SJoel Fernandes #define TS_CPU_MASK (BIT(TS_CPU_SHIFT) - 1) 260fbccdeb8SJoel Fernandes 261fbccdeb8SJoel Fernandes /* 262fbccdeb8SJoel Fernandes * If CPU number can be stored in IP, store it there, otherwise store it in 263fbccdeb8SJoel Fernandes * the time stamp. This means more timestamp resolution is available when 264fbccdeb8SJoel Fernandes * the CPU can be stored in the IP. 265fbccdeb8SJoel Fernandes */ 266fbccdeb8SJoel Fernandes #ifdef PSTORE_CPU_IN_IP 267fbccdeb8SJoel Fernandes static inline void 268fbccdeb8SJoel Fernandes pstore_ftrace_encode_cpu(struct pstore_ftrace_record *rec, unsigned int cpu) 269fbccdeb8SJoel Fernandes { 270fbccdeb8SJoel Fernandes rec->ip |= cpu; 271fbccdeb8SJoel Fernandes } 272fbccdeb8SJoel Fernandes 273fbccdeb8SJoel Fernandes static inline unsigned int 274fbccdeb8SJoel Fernandes pstore_ftrace_decode_cpu(struct pstore_ftrace_record *rec) 275fbccdeb8SJoel Fernandes { 276fbccdeb8SJoel Fernandes return rec->ip & PSTORE_CPU_IN_IP; 277fbccdeb8SJoel Fernandes } 278fbccdeb8SJoel Fernandes 279fbccdeb8SJoel Fernandes static inline u64 280fbccdeb8SJoel Fernandes pstore_ftrace_read_timestamp(struct pstore_ftrace_record *rec) 281fbccdeb8SJoel Fernandes { 282fbccdeb8SJoel Fernandes return rec->ts; 283fbccdeb8SJoel Fernandes } 284fbccdeb8SJoel Fernandes 285fbccdeb8SJoel Fernandes static inline void 286fbccdeb8SJoel Fernandes pstore_ftrace_write_timestamp(struct pstore_ftrace_record *rec, u64 val) 287fbccdeb8SJoel Fernandes { 288fbccdeb8SJoel Fernandes rec->ts = val; 289fbccdeb8SJoel Fernandes } 290fbccdeb8SJoel Fernandes #else 291fbccdeb8SJoel Fernandes static inline void 292fbccdeb8SJoel Fernandes pstore_ftrace_encode_cpu(struct pstore_ftrace_record *rec, unsigned int cpu) 293fbccdeb8SJoel Fernandes { 294fbccdeb8SJoel Fernandes rec->ts &= ~(TS_CPU_MASK); 295fbccdeb8SJoel Fernandes rec->ts |= cpu; 296fbccdeb8SJoel Fernandes } 297fbccdeb8SJoel Fernandes 298fbccdeb8SJoel Fernandes static inline unsigned int 299fbccdeb8SJoel Fernandes pstore_ftrace_decode_cpu(struct pstore_ftrace_record *rec) 300fbccdeb8SJoel Fernandes { 301fbccdeb8SJoel Fernandes return rec->ts & TS_CPU_MASK; 302fbccdeb8SJoel Fernandes } 303fbccdeb8SJoel Fernandes 304fbccdeb8SJoel Fernandes static inline u64 305fbccdeb8SJoel Fernandes pstore_ftrace_read_timestamp(struct pstore_ftrace_record *rec) 306fbccdeb8SJoel Fernandes { 307fbccdeb8SJoel Fernandes return rec->ts >> TS_CPU_SHIFT; 308fbccdeb8SJoel Fernandes } 309fbccdeb8SJoel Fernandes 310fbccdeb8SJoel Fernandes static inline void 311fbccdeb8SJoel Fernandes pstore_ftrace_write_timestamp(struct pstore_ftrace_record *rec, u64 val) 312fbccdeb8SJoel Fernandes { 313fbccdeb8SJoel Fernandes rec->ts = (rec->ts & TS_CPU_MASK) | (val << TS_CPU_SHIFT); 314fbccdeb8SJoel Fernandes } 315fbccdeb8SJoel Fernandes #endif 316fbccdeb8SJoel Fernandes 317ca01d6ddSTony Luck #endif /*_LINUX_PSTORE_H*/ 318