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 339abdccccSKees Cook struct module; 349abdccccSKees 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 509abdccccSKees Cook struct pstore_info; 519abdccccSKees Cook /** 529abdccccSKees Cook * struct pstore_record - details of a pstore record entry 539abdccccSKees Cook * @psi: pstore backend driver information 549abdccccSKees Cook * @type: pstore record type 559abdccccSKees Cook * @id: per-type unique identifier for record 569abdccccSKees Cook * @time: timestamp of the record 579abdccccSKees Cook * @count: for PSTORE_TYPE_DMESG, the Oops count. 589abdccccSKees Cook * @compressed: for PSTORE_TYPE_DMESG, whether the buffer is compressed 599abdccccSKees Cook * @buf: pointer to record contents 609abdccccSKees Cook * @size: size of @buf 619abdccccSKees Cook * @ecc_notice_size: 629abdccccSKees Cook * ECC information for @buf 639abdccccSKees Cook */ 649abdccccSKees Cook struct pstore_record { 659abdccccSKees Cook struct pstore_info *psi; 669abdccccSKees Cook enum pstore_type_id type; 679abdccccSKees Cook u64 id; 689abdccccSKees Cook struct timespec time; 699abdccccSKees Cook int count; 709abdccccSKees Cook bool compressed; 719abdccccSKees Cook char *buf; 729abdccccSKees Cook ssize_t size; 739abdccccSKees Cook ssize_t ecc_notice_size; 749abdccccSKees 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 * 114*125cc42bSKees Cook * @record: 115*125cc42bSKees Cook * pointer to record to populate. @buf should be allocated 116*125cc42bSKees Cook * by the backend and filled. At least @type and @id should 117*125cc42bSKees Cook * be populated, since these are used when creating pstorefs 118*125cc42bSKees Cook * file names. 1190edae0b3SKees Cook * 1200edae0b3SKees Cook * Returns record size on success, zero when no more records are 1210edae0b3SKees Cook * available, or negative on error. 1220edae0b3SKees Cook * 1230edae0b3SKees Cook * @write: 1240edae0b3SKees Cook * Perform a frontend notification of a write to a backend record. The 1250edae0b3SKees Cook * data to be stored has already been written to the registered @buf 1260edae0b3SKees Cook * of the @psi structure. 1270edae0b3SKees Cook * 1280edae0b3SKees Cook * @type: in: pstore record type to write 1290edae0b3SKees Cook * @reason: 1300edae0b3SKees Cook * in: pstore write reason 1310edae0b3SKees Cook * @id: out: unique identifier for the record 1320edae0b3SKees Cook * @part: in: position in a multipart write 1330edae0b3SKees Cook * @count: in: increasing from 0 since boot, the number of this Oops 1340edae0b3SKees Cook * @compressed: 1350edae0b3SKees Cook * in: if the record is compressed 1360edae0b3SKees Cook * @size: in: size of the write 1370edae0b3SKees Cook * @psi: in: pointer to the struct pstore_info for the backend 1380edae0b3SKees Cook * 1390edae0b3SKees Cook * Returns 0 on success, and non-zero on error. 1400edae0b3SKees Cook * 1410edae0b3SKees Cook * @write_buf: 1420edae0b3SKees Cook * Perform a frontend write to a backend record, using a specified 1430edae0b3SKees Cook * buffer. Unlike @write, this does not use the @psi @buf. 1440edae0b3SKees Cook * 1450edae0b3SKees Cook * @type: in: pstore record type to write 1460edae0b3SKees Cook * @reason: 1470edae0b3SKees Cook * in: pstore write reason 1480edae0b3SKees Cook * @id: out: unique identifier for the record 1490edae0b3SKees Cook * @part: in: position in a multipart write 1500edae0b3SKees Cook * @buf: in: pointer to contents to write to backend record 1510edae0b3SKees Cook * @compressed: 1520edae0b3SKees Cook * in: if the record is compressed 1530edae0b3SKees Cook * @size: in: size of the write 1540edae0b3SKees Cook * @psi: in: pointer to the struct pstore_info for the backend 1550edae0b3SKees Cook * 1560edae0b3SKees Cook * Returns 0 on success, and non-zero on error. 1570edae0b3SKees Cook * 1580edae0b3SKees Cook * @write_buf_user: 1590edae0b3SKees Cook * Perform a frontend write to a backend record, using a specified 1600edae0b3SKees Cook * buffer that is coming directly from userspace. 1610edae0b3SKees Cook * 1620edae0b3SKees Cook * @type: in: pstore record type to write 1630edae0b3SKees Cook * @reason: 1640edae0b3SKees Cook * in: pstore write reason 1650edae0b3SKees Cook * @id: out: unique identifier for the record 1660edae0b3SKees Cook * @part: in: position in a multipart write 1670edae0b3SKees Cook * @buf: in: pointer to userspace contents to write to backend record 1680edae0b3SKees Cook * @compressed: 1690edae0b3SKees Cook * in: if the record is compressed 1700edae0b3SKees Cook * @size: in: size of the write 1710edae0b3SKees Cook * @psi: in: pointer to the struct pstore_info for the backend 1720edae0b3SKees Cook * 1730edae0b3SKees Cook * Returns 0 on success, and non-zero on error. 1740edae0b3SKees Cook * 1750edae0b3SKees Cook * @erase: 1760edae0b3SKees Cook * Delete a record from backend storage. Different backends 1770edae0b3SKees Cook * identify records differently, so all possible methods of 1780edae0b3SKees Cook * identification are included to help the backend locate the 1790edae0b3SKees Cook * record to remove. 1800edae0b3SKees Cook * 1810edae0b3SKees Cook * @type: in: pstore record type to write 1820edae0b3SKees Cook * @id: in: per-type unique identifier for the record 1830edae0b3SKees Cook * @count: in: Oops count 1840edae0b3SKees Cook * @time: in: timestamp for the record 1850edae0b3SKees Cook * @psi: in: pointer to the struct pstore_info for the backend 1860edae0b3SKees Cook * 1870edae0b3SKees Cook * Returns 0 on success, and non-zero on error. 1880edae0b3SKees Cook * 1890edae0b3SKees Cook */ 190ca01d6ddSTony Luck struct pstore_info { 191ca01d6ddSTony Luck struct module *owner; 192ca01d6ddSTony Luck char *name; 1930edae0b3SKees Cook 1940edae0b3SKees Cook spinlock_t buf_lock; 195ca01d6ddSTony Luck char *buf; 196ca01d6ddSTony Luck size_t bufsize; 1970edae0b3SKees Cook 1980edae0b3SKees Cook struct mutex read_mutex; 1990edae0b3SKees Cook 200df36ac1bSLuck, Tony int flags; 2010edae0b3SKees Cook void *data; 2020edae0b3SKees Cook 20306cf91b4SChen Gong int (*open)(struct pstore_info *psi); 20406cf91b4SChen Gong int (*close)(struct pstore_info *psi); 205*125cc42bSKees Cook ssize_t (*read)(struct pstore_record *record); 2063d6d8d20SKees Cook int (*write)(enum pstore_type_id type, 2073d6d8d20SKees Cook enum kmsg_dump_reason reason, u64 *id, 208b3b515bbSAruna Balakrishnaiah unsigned int part, int count, bool compressed, 2096bbbca73SAruna Balakrishnaiah size_t size, struct pstore_info *psi); 210897dba02SAnton Vorontsov int (*write_buf)(enum pstore_type_id type, 211897dba02SAnton Vorontsov enum kmsg_dump_reason reason, u64 *id, 212b3b515bbSAruna Balakrishnaiah unsigned int part, const char *buf, bool compressed, 2136bbbca73SAruna Balakrishnaiah size_t size, struct pstore_info *psi); 2145bf6d1b9SMark Salyzyn int (*write_buf_user)(enum pstore_type_id type, 2155bf6d1b9SMark Salyzyn enum kmsg_dump_reason reason, u64 *id, 2165bf6d1b9SMark Salyzyn unsigned int part, const char __user *buf, 2175bf6d1b9SMark Salyzyn bool compressed, size_t size, struct pstore_info *psi); 21856280682SMatthew Garrett int (*erase)(enum pstore_type_id type, u64 id, 219755d4fe4SSeiji Aguchi int count, struct timespec time, 220755d4fe4SSeiji Aguchi struct pstore_info *psi); 221ca01d6ddSTony Luck }; 222ca01d6ddSTony Luck 2230edae0b3SKees Cook /* Supported frontends */ 224c950fd6fSNamhyung Kim #define PSTORE_FLAGS_DMESG (1 << 0) 225c950fd6fSNamhyung Kim #define PSTORE_FLAGS_CONSOLE (1 << 1) 226c950fd6fSNamhyung Kim #define PSTORE_FLAGS_FTRACE (1 << 2) 227c950fd6fSNamhyung Kim #define PSTORE_FLAGS_PMSG (1 << 3) 228c950fd6fSNamhyung Kim 229ca01d6ddSTony Luck extern int pstore_register(struct pstore_info *); 230ee1d2674SGeliang Tang extern void pstore_unregister(struct pstore_info *); 2319f244e9cSSeiji Aguchi extern bool pstore_cannot_block_path(enum kmsg_dump_reason reason); 232ca01d6ddSTony Luck 233fbccdeb8SJoel Fernandes struct pstore_ftrace_record { 234fbccdeb8SJoel Fernandes unsigned long ip; 235fbccdeb8SJoel Fernandes unsigned long parent_ip; 236fbccdeb8SJoel Fernandes u64 ts; 237fbccdeb8SJoel Fernandes }; 238fbccdeb8SJoel Fernandes 239fbccdeb8SJoel Fernandes /* 240fbccdeb8SJoel Fernandes * ftrace related stuff: Both backends and frontends need these so expose 241fbccdeb8SJoel Fernandes * them here. 242fbccdeb8SJoel Fernandes */ 243fbccdeb8SJoel Fernandes 244fbccdeb8SJoel Fernandes #if NR_CPUS <= 2 && defined(CONFIG_ARM_THUMB) 245fbccdeb8SJoel Fernandes #define PSTORE_CPU_IN_IP 0x1 246fbccdeb8SJoel Fernandes #elif NR_CPUS <= 4 && defined(CONFIG_ARM) 247fbccdeb8SJoel Fernandes #define PSTORE_CPU_IN_IP 0x3 248fbccdeb8SJoel Fernandes #endif 249fbccdeb8SJoel Fernandes 250fbccdeb8SJoel Fernandes #define TS_CPU_SHIFT 8 251fbccdeb8SJoel Fernandes #define TS_CPU_MASK (BIT(TS_CPU_SHIFT) - 1) 252fbccdeb8SJoel Fernandes 253fbccdeb8SJoel Fernandes /* 254fbccdeb8SJoel Fernandes * If CPU number can be stored in IP, store it there, otherwise store it in 255fbccdeb8SJoel Fernandes * the time stamp. This means more timestamp resolution is available when 256fbccdeb8SJoel Fernandes * the CPU can be stored in the IP. 257fbccdeb8SJoel Fernandes */ 258fbccdeb8SJoel Fernandes #ifdef PSTORE_CPU_IN_IP 259fbccdeb8SJoel Fernandes static inline void 260fbccdeb8SJoel Fernandes pstore_ftrace_encode_cpu(struct pstore_ftrace_record *rec, unsigned int cpu) 261fbccdeb8SJoel Fernandes { 262fbccdeb8SJoel Fernandes rec->ip |= cpu; 263fbccdeb8SJoel Fernandes } 264fbccdeb8SJoel Fernandes 265fbccdeb8SJoel Fernandes static inline unsigned int 266fbccdeb8SJoel Fernandes pstore_ftrace_decode_cpu(struct pstore_ftrace_record *rec) 267fbccdeb8SJoel Fernandes { 268fbccdeb8SJoel Fernandes return rec->ip & PSTORE_CPU_IN_IP; 269fbccdeb8SJoel Fernandes } 270fbccdeb8SJoel Fernandes 271fbccdeb8SJoel Fernandes static inline u64 272fbccdeb8SJoel Fernandes pstore_ftrace_read_timestamp(struct pstore_ftrace_record *rec) 273fbccdeb8SJoel Fernandes { 274fbccdeb8SJoel Fernandes return rec->ts; 275fbccdeb8SJoel Fernandes } 276fbccdeb8SJoel Fernandes 277fbccdeb8SJoel Fernandes static inline void 278fbccdeb8SJoel Fernandes pstore_ftrace_write_timestamp(struct pstore_ftrace_record *rec, u64 val) 279fbccdeb8SJoel Fernandes { 280fbccdeb8SJoel Fernandes rec->ts = val; 281fbccdeb8SJoel Fernandes } 282fbccdeb8SJoel Fernandes #else 283fbccdeb8SJoel Fernandes static inline void 284fbccdeb8SJoel Fernandes pstore_ftrace_encode_cpu(struct pstore_ftrace_record *rec, unsigned int cpu) 285fbccdeb8SJoel Fernandes { 286fbccdeb8SJoel Fernandes rec->ts &= ~(TS_CPU_MASK); 287fbccdeb8SJoel Fernandes rec->ts |= cpu; 288fbccdeb8SJoel Fernandes } 289fbccdeb8SJoel Fernandes 290fbccdeb8SJoel Fernandes static inline unsigned int 291fbccdeb8SJoel Fernandes pstore_ftrace_decode_cpu(struct pstore_ftrace_record *rec) 292fbccdeb8SJoel Fernandes { 293fbccdeb8SJoel Fernandes return rec->ts & TS_CPU_MASK; 294fbccdeb8SJoel Fernandes } 295fbccdeb8SJoel Fernandes 296fbccdeb8SJoel Fernandes static inline u64 297fbccdeb8SJoel Fernandes pstore_ftrace_read_timestamp(struct pstore_ftrace_record *rec) 298fbccdeb8SJoel Fernandes { 299fbccdeb8SJoel Fernandes return rec->ts >> TS_CPU_SHIFT; 300fbccdeb8SJoel Fernandes } 301fbccdeb8SJoel Fernandes 302fbccdeb8SJoel Fernandes static inline void 303fbccdeb8SJoel Fernandes pstore_ftrace_write_timestamp(struct pstore_ftrace_record *rec, u64 val) 304fbccdeb8SJoel Fernandes { 305fbccdeb8SJoel Fernandes rec->ts = (rec->ts & TS_CPU_MASK) | (val << TS_CPU_SHIFT); 306fbccdeb8SJoel Fernandes } 307fbccdeb8SJoel Fernandes #endif 308fbccdeb8SJoel Fernandes 309ca01d6ddSTony Luck #endif /*_LINUX_PSTORE_H*/ 310