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 * @buf: pointer to record contents 589abdccccSKees Cook * @size: size of @buf 599abdccccSKees Cook * @ecc_notice_size: 609abdccccSKees Cook * ECC information for @buf 6176cc9580SKees Cook * 6276cc9580SKees Cook * Valid for PSTORE_TYPE_DMESG @type: 6376cc9580SKees Cook * 6476cc9580SKees Cook * @count: Oops count since boot 6576cc9580SKees Cook * @reason: kdump reason for notification 6676cc9580SKees Cook * @part: position in a multipart record 6776cc9580SKees Cook * @compressed: whether the buffer is compressed 6876cc9580SKees Cook * 699abdccccSKees Cook */ 709abdccccSKees Cook struct pstore_record { 719abdccccSKees Cook struct pstore_info *psi; 729abdccccSKees Cook enum pstore_type_id type; 739abdccccSKees Cook u64 id; 749abdccccSKees Cook struct timespec time; 759abdccccSKees Cook char *buf; 769abdccccSKees Cook ssize_t size; 779abdccccSKees Cook ssize_t ecc_notice_size; 7876cc9580SKees Cook 7976cc9580SKees Cook int count; 8076cc9580SKees Cook enum kmsg_dump_reason reason; 8176cc9580SKees Cook unsigned int part; 8276cc9580SKees Cook bool compressed; 839abdccccSKees Cook }; 8467a101f5SAnton Vorontsov 850edae0b3SKees Cook /** 860edae0b3SKees Cook * struct pstore_info - backend pstore driver structure 870edae0b3SKees Cook * 880edae0b3SKees Cook * @owner: module which is repsonsible for this backend driver 890edae0b3SKees Cook * @name: name of the backend driver 900edae0b3SKees Cook * 910edae0b3SKees Cook * @buf_lock: spinlock to serialize access to @buf 920edae0b3SKees Cook * @buf: preallocated crash dump buffer 930edae0b3SKees Cook * @bufsize: size of @buf available for crash dump writes 940edae0b3SKees Cook * 950edae0b3SKees Cook * @read_mutex: serializes @open, @read, @close, and @erase callbacks 960edae0b3SKees Cook * @flags: bitfield of frontends the backend can accept writes for 970edae0b3SKees Cook * @data: backend-private pointer passed back during callbacks 980edae0b3SKees Cook * 990edae0b3SKees Cook * Callbacks: 1000edae0b3SKees Cook * 1010edae0b3SKees Cook * @open: 1020edae0b3SKees Cook * Notify backend that pstore is starting a full read of backend 1030edae0b3SKees Cook * records. Followed by one or more @read calls, and a final @close. 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. 1080edae0b3SKees Cook * 1090edae0b3SKees Cook * @close: 1100edae0b3SKees Cook * Notify backend that pstore has finished a full read of backend 1110edae0b3SKees Cook * records. Always preceded by an @open call and one or more @read 1120edae0b3SKees Cook * calls. 1130edae0b3SKees Cook * 1140edae0b3SKees Cook * @psi: in: pointer to the struct pstore_info for the backend 1150edae0b3SKees Cook * 1160edae0b3SKees Cook * Returns 0 on success, and non-zero on error. (Though pstore will 1170edae0b3SKees Cook * ignore the error.) 1180edae0b3SKees Cook * 1190edae0b3SKees Cook * @read: 1200edae0b3SKees Cook * Read next available backend record. Called after a successful 1210edae0b3SKees Cook * @open. 1220edae0b3SKees Cook * 123125cc42bSKees Cook * @record: 124125cc42bSKees Cook * pointer to record to populate. @buf should be allocated 125125cc42bSKees Cook * by the backend and filled. At least @type and @id should 126125cc42bSKees Cook * be populated, since these are used when creating pstorefs 127125cc42bSKees Cook * file names. 1280edae0b3SKees Cook * 1290edae0b3SKees Cook * Returns record size on success, zero when no more records are 1300edae0b3SKees Cook * available, or negative on error. 1310edae0b3SKees Cook * 1320edae0b3SKees Cook * @write: 1330edae0b3SKees Cook * Perform a frontend notification of a write to a backend record. The 1340edae0b3SKees Cook * data to be stored has already been written to the registered @buf 1350edae0b3SKees Cook * of the @psi structure. 1360edae0b3SKees Cook * 13776cc9580SKees Cook * @record: 13876cc9580SKees Cook * pointer to record metadata. Note that @buf is NULL, since 13976cc9580SKees Cook * the @buf registered with @psi is what has been written. The 14076cc9580SKees Cook * backend is expected to update @id. 1410edae0b3SKees Cook * 1420edae0b3SKees Cook * Returns 0 on success, and non-zero on error. 1430edae0b3SKees Cook * 1440edae0b3SKees Cook * @write_buf: 145b10b4711SKees Cook * Perform a frontend write to a backend record. The record contains 146b10b4711SKees Cook * all metadata and the buffer to write to backend storage. (Unlike 147b10b4711SKees Cook * @write, this does not use the @psi @buf.) 1480edae0b3SKees Cook * 149b10b4711SKees Cook * @record: pointer to record metadata. 1500edae0b3SKees Cook * 1510edae0b3SKees Cook * Returns 0 on success, and non-zero on error. 1520edae0b3SKees Cook * 1530edae0b3SKees Cook * @write_buf_user: 1540edae0b3SKees Cook * Perform a frontend write to a backend record, using a specified 155*fdd03118SKees Cook * buffer that is coming directly from userspace, instead of the 156*fdd03118SKees Cook * @record @buf. 1570edae0b3SKees Cook * 158*fdd03118SKees Cook * @record: pointer to record metadata. 159*fdd03118SKees Cook * @buf: pointer to userspace contents to write to backend 1600edae0b3SKees Cook * 1610edae0b3SKees Cook * Returns 0 on success, and non-zero on error. 1620edae0b3SKees Cook * 1630edae0b3SKees Cook * @erase: 1640edae0b3SKees Cook * Delete a record from backend storage. Different backends 165a61072aaSKees Cook * identify records differently, so entire original record is 166a61072aaSKees Cook * passed back to assist in identification of what the backend 167a61072aaSKees Cook * should remove from storage. 1680edae0b3SKees Cook * 169a61072aaSKees Cook * @record: pointer to record metadata. 1700edae0b3SKees Cook * 1710edae0b3SKees Cook * Returns 0 on success, and non-zero on error. 1720edae0b3SKees Cook * 1730edae0b3SKees Cook */ 174ca01d6ddSTony Luck struct pstore_info { 175ca01d6ddSTony Luck struct module *owner; 176ca01d6ddSTony Luck char *name; 1770edae0b3SKees Cook 1780edae0b3SKees Cook spinlock_t buf_lock; 179ca01d6ddSTony Luck char *buf; 180ca01d6ddSTony Luck size_t bufsize; 1810edae0b3SKees Cook 1820edae0b3SKees Cook struct mutex read_mutex; 1830edae0b3SKees Cook 184df36ac1bSLuck, Tony int flags; 1850edae0b3SKees Cook void *data; 1860edae0b3SKees Cook 18706cf91b4SChen Gong int (*open)(struct pstore_info *psi); 18806cf91b4SChen Gong int (*close)(struct pstore_info *psi); 189125cc42bSKees Cook ssize_t (*read)(struct pstore_record *record); 19076cc9580SKees Cook int (*write)(struct pstore_record *record); 191b10b4711SKees Cook int (*write_buf)(struct pstore_record *record); 192*fdd03118SKees Cook int (*write_buf_user)(struct pstore_record *record, 193*fdd03118SKees Cook const char __user *buf); 194a61072aaSKees Cook int (*erase)(struct pstore_record *record); 195ca01d6ddSTony Luck }; 196ca01d6ddSTony Luck 1970edae0b3SKees Cook /* Supported frontends */ 198c950fd6fSNamhyung Kim #define PSTORE_FLAGS_DMESG (1 << 0) 199c950fd6fSNamhyung Kim #define PSTORE_FLAGS_CONSOLE (1 << 1) 200c950fd6fSNamhyung Kim #define PSTORE_FLAGS_FTRACE (1 << 2) 201c950fd6fSNamhyung Kim #define PSTORE_FLAGS_PMSG (1 << 3) 202c950fd6fSNamhyung Kim 203ca01d6ddSTony Luck extern int pstore_register(struct pstore_info *); 204ee1d2674SGeliang Tang extern void pstore_unregister(struct pstore_info *); 2059f244e9cSSeiji Aguchi extern bool pstore_cannot_block_path(enum kmsg_dump_reason reason); 206ca01d6ddSTony Luck 207fbccdeb8SJoel Fernandes struct pstore_ftrace_record { 208fbccdeb8SJoel Fernandes unsigned long ip; 209fbccdeb8SJoel Fernandes unsigned long parent_ip; 210fbccdeb8SJoel Fernandes u64 ts; 211fbccdeb8SJoel Fernandes }; 212fbccdeb8SJoel Fernandes 213fbccdeb8SJoel Fernandes /* 214fbccdeb8SJoel Fernandes * ftrace related stuff: Both backends and frontends need these so expose 215fbccdeb8SJoel Fernandes * them here. 216fbccdeb8SJoel Fernandes */ 217fbccdeb8SJoel Fernandes 218fbccdeb8SJoel Fernandes #if NR_CPUS <= 2 && defined(CONFIG_ARM_THUMB) 219fbccdeb8SJoel Fernandes #define PSTORE_CPU_IN_IP 0x1 220fbccdeb8SJoel Fernandes #elif NR_CPUS <= 4 && defined(CONFIG_ARM) 221fbccdeb8SJoel Fernandes #define PSTORE_CPU_IN_IP 0x3 222fbccdeb8SJoel Fernandes #endif 223fbccdeb8SJoel Fernandes 224fbccdeb8SJoel Fernandes #define TS_CPU_SHIFT 8 225fbccdeb8SJoel Fernandes #define TS_CPU_MASK (BIT(TS_CPU_SHIFT) - 1) 226fbccdeb8SJoel Fernandes 227fbccdeb8SJoel Fernandes /* 228fbccdeb8SJoel Fernandes * If CPU number can be stored in IP, store it there, otherwise store it in 229fbccdeb8SJoel Fernandes * the time stamp. This means more timestamp resolution is available when 230fbccdeb8SJoel Fernandes * the CPU can be stored in the IP. 231fbccdeb8SJoel Fernandes */ 232fbccdeb8SJoel Fernandes #ifdef PSTORE_CPU_IN_IP 233fbccdeb8SJoel Fernandes static inline void 234fbccdeb8SJoel Fernandes pstore_ftrace_encode_cpu(struct pstore_ftrace_record *rec, unsigned int cpu) 235fbccdeb8SJoel Fernandes { 236fbccdeb8SJoel Fernandes rec->ip |= cpu; 237fbccdeb8SJoel Fernandes } 238fbccdeb8SJoel Fernandes 239fbccdeb8SJoel Fernandes static inline unsigned int 240fbccdeb8SJoel Fernandes pstore_ftrace_decode_cpu(struct pstore_ftrace_record *rec) 241fbccdeb8SJoel Fernandes { 242fbccdeb8SJoel Fernandes return rec->ip & PSTORE_CPU_IN_IP; 243fbccdeb8SJoel Fernandes } 244fbccdeb8SJoel Fernandes 245fbccdeb8SJoel Fernandes static inline u64 246fbccdeb8SJoel Fernandes pstore_ftrace_read_timestamp(struct pstore_ftrace_record *rec) 247fbccdeb8SJoel Fernandes { 248fbccdeb8SJoel Fernandes return rec->ts; 249fbccdeb8SJoel Fernandes } 250fbccdeb8SJoel Fernandes 251fbccdeb8SJoel Fernandes static inline void 252fbccdeb8SJoel Fernandes pstore_ftrace_write_timestamp(struct pstore_ftrace_record *rec, u64 val) 253fbccdeb8SJoel Fernandes { 254fbccdeb8SJoel Fernandes rec->ts = val; 255fbccdeb8SJoel Fernandes } 256fbccdeb8SJoel Fernandes #else 257fbccdeb8SJoel Fernandes static inline void 258fbccdeb8SJoel Fernandes pstore_ftrace_encode_cpu(struct pstore_ftrace_record *rec, unsigned int cpu) 259fbccdeb8SJoel Fernandes { 260fbccdeb8SJoel Fernandes rec->ts &= ~(TS_CPU_MASK); 261fbccdeb8SJoel Fernandes rec->ts |= cpu; 262fbccdeb8SJoel Fernandes } 263fbccdeb8SJoel Fernandes 264fbccdeb8SJoel Fernandes static inline unsigned int 265fbccdeb8SJoel Fernandes pstore_ftrace_decode_cpu(struct pstore_ftrace_record *rec) 266fbccdeb8SJoel Fernandes { 267fbccdeb8SJoel Fernandes return rec->ts & TS_CPU_MASK; 268fbccdeb8SJoel Fernandes } 269fbccdeb8SJoel Fernandes 270fbccdeb8SJoel Fernandes static inline u64 271fbccdeb8SJoel Fernandes pstore_ftrace_read_timestamp(struct pstore_ftrace_record *rec) 272fbccdeb8SJoel Fernandes { 273fbccdeb8SJoel Fernandes return rec->ts >> TS_CPU_SHIFT; 274fbccdeb8SJoel Fernandes } 275fbccdeb8SJoel Fernandes 276fbccdeb8SJoel Fernandes static inline void 277fbccdeb8SJoel Fernandes pstore_ftrace_write_timestamp(struct pstore_ftrace_record *rec, u64 val) 278fbccdeb8SJoel Fernandes { 279fbccdeb8SJoel Fernandes rec->ts = (rec->ts & TS_CPU_MASK) | (val << TS_CPU_SHIFT); 280fbccdeb8SJoel Fernandes } 281fbccdeb8SJoel Fernandes #endif 282fbccdeb8SJoel Fernandes 283ca01d6ddSTony Luck #endif /*_LINUX_PSTORE_H*/ 284