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; 747aaa822eSKees Cook struct timespec64 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 * 88*0eed84ffSKees Cook * @owner: module which is responsible 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 9389d328f6SKees Cook * @bufsize: size of @buf available for crash dump bytes (must match 9489d328f6SKees Cook * smallest number of bytes available for writing to a 9589d328f6SKees Cook * backend entry, since compressed bytes don't take kindly 9689d328f6SKees Cook * to being truncated) 970edae0b3SKees Cook * 980edae0b3SKees Cook * @read_mutex: serializes @open, @read, @close, and @erase callbacks 990edae0b3SKees Cook * @flags: bitfield of frontends the backend can accept writes for 1000edae0b3SKees Cook * @data: backend-private pointer passed back during callbacks 1010edae0b3SKees Cook * 1020edae0b3SKees Cook * Callbacks: 1030edae0b3SKees Cook * 1040edae0b3SKees Cook * @open: 1050edae0b3SKees Cook * Notify backend that pstore is starting a full read of backend 1060edae0b3SKees Cook * records. Followed by one or more @read calls, and a final @close. 1070edae0b3SKees Cook * 1080edae0b3SKees Cook * @psi: in: pointer to the struct pstore_info for the backend 1090edae0b3SKees Cook * 1100edae0b3SKees Cook * Returns 0 on success, and non-zero on error. 1110edae0b3SKees Cook * 1120edae0b3SKees Cook * @close: 1130edae0b3SKees Cook * Notify backend that pstore has finished a full read of backend 1140edae0b3SKees Cook * records. Always preceded by an @open call and one or more @read 1150edae0b3SKees Cook * calls. 1160edae0b3SKees Cook * 1170edae0b3SKees Cook * @psi: in: pointer to the struct pstore_info for the backend 1180edae0b3SKees Cook * 1190edae0b3SKees Cook * Returns 0 on success, and non-zero on error. (Though pstore will 1200edae0b3SKees Cook * ignore the error.) 1210edae0b3SKees Cook * 1220edae0b3SKees Cook * @read: 1230edae0b3SKees Cook * Read next available backend record. Called after a successful 1240edae0b3SKees Cook * @open. 1250edae0b3SKees Cook * 126125cc42bSKees Cook * @record: 127125cc42bSKees Cook * pointer to record to populate. @buf should be allocated 128125cc42bSKees Cook * by the backend and filled. At least @type and @id should 129125cc42bSKees Cook * be populated, since these are used when creating pstorefs 130125cc42bSKees Cook * file names. 1310edae0b3SKees Cook * 1320edae0b3SKees Cook * Returns record size on success, zero when no more records are 1330edae0b3SKees Cook * available, or negative on error. 1340edae0b3SKees Cook * 1350edae0b3SKees Cook * @write: 1364c9ec219SKees Cook * A newly generated record needs to be written to backend storage. 1370edae0b3SKees Cook * 13876cc9580SKees Cook * @record: 1394c9ec219SKees Cook * pointer to record metadata. When @type is PSTORE_TYPE_DMESG, 1404c9ec219SKees Cook * @buf will be pointing to the preallocated @psi.buf, since 1414c9ec219SKees Cook * memory allocation may be broken during an Oops. Regardless, 1424c9ec219SKees Cook * @buf must be proccesed or copied before returning. The 1434c9ec219SKees Cook * backend is also expected to write @id with something that 144c7f3c595SKees Cook * can help identify this record to a future @erase callback. 145c7f3c595SKees Cook * The @time field will be prepopulated with the current time, 146c7f3c595SKees Cook * when available. The @size field will have the size of data 147c7f3c595SKees Cook * in @buf. 1480edae0b3SKees Cook * 1490edae0b3SKees Cook * Returns 0 on success, and non-zero on error. 1500edae0b3SKees Cook * 1514c9ec219SKees Cook * @write_user: 1520edae0b3SKees Cook * Perform a frontend write to a backend record, using a specified 153fdd03118SKees Cook * buffer that is coming directly from userspace, instead of the 154fdd03118SKees Cook * @record @buf. 1550edae0b3SKees Cook * 156fdd03118SKees Cook * @record: pointer to record metadata. 157fdd03118SKees Cook * @buf: pointer to userspace contents to write to backend 1580edae0b3SKees Cook * 1590edae0b3SKees Cook * Returns 0 on success, and non-zero on error. 1600edae0b3SKees Cook * 1610edae0b3SKees Cook * @erase: 1620edae0b3SKees Cook * Delete a record from backend storage. Different backends 163a61072aaSKees Cook * identify records differently, so entire original record is 164a61072aaSKees Cook * passed back to assist in identification of what the backend 165a61072aaSKees Cook * should remove from storage. 1660edae0b3SKees Cook * 167a61072aaSKees Cook * @record: pointer to record metadata. 1680edae0b3SKees Cook * 1690edae0b3SKees Cook * Returns 0 on success, and non-zero on error. 1700edae0b3SKees Cook * 1710edae0b3SKees Cook */ 172ca01d6ddSTony Luck struct pstore_info { 173ca01d6ddSTony Luck struct module *owner; 174ca01d6ddSTony Luck char *name; 1750edae0b3SKees Cook 1760edae0b3SKees Cook spinlock_t buf_lock; 177ca01d6ddSTony Luck char *buf; 178ca01d6ddSTony Luck size_t bufsize; 1790edae0b3SKees Cook 1800edae0b3SKees Cook struct mutex read_mutex; 1810edae0b3SKees Cook 182df36ac1bSLuck, Tony int flags; 1830edae0b3SKees Cook void *data; 1840edae0b3SKees Cook 18506cf91b4SChen Gong int (*open)(struct pstore_info *psi); 18606cf91b4SChen Gong int (*close)(struct pstore_info *psi); 187125cc42bSKees Cook ssize_t (*read)(struct pstore_record *record); 18876cc9580SKees Cook int (*write)(struct pstore_record *record); 1894c9ec219SKees Cook int (*write_user)(struct pstore_record *record, 190fdd03118SKees Cook const char __user *buf); 191a61072aaSKees Cook int (*erase)(struct pstore_record *record); 192ca01d6ddSTony Luck }; 193ca01d6ddSTony Luck 1940edae0b3SKees Cook /* Supported frontends */ 195c950fd6fSNamhyung Kim #define PSTORE_FLAGS_DMESG (1 << 0) 196c950fd6fSNamhyung Kim #define PSTORE_FLAGS_CONSOLE (1 << 1) 197c950fd6fSNamhyung Kim #define PSTORE_FLAGS_FTRACE (1 << 2) 198c950fd6fSNamhyung Kim #define PSTORE_FLAGS_PMSG (1 << 3) 199c950fd6fSNamhyung Kim 200ca01d6ddSTony Luck extern int pstore_register(struct pstore_info *); 201ee1d2674SGeliang Tang extern void pstore_unregister(struct pstore_info *); 2029f244e9cSSeiji Aguchi extern bool pstore_cannot_block_path(enum kmsg_dump_reason reason); 203ca01d6ddSTony Luck 204fbccdeb8SJoel Fernandes struct pstore_ftrace_record { 205fbccdeb8SJoel Fernandes unsigned long ip; 206fbccdeb8SJoel Fernandes unsigned long parent_ip; 207fbccdeb8SJoel Fernandes u64 ts; 208fbccdeb8SJoel Fernandes }; 209fbccdeb8SJoel Fernandes 210fbccdeb8SJoel Fernandes /* 211fbccdeb8SJoel Fernandes * ftrace related stuff: Both backends and frontends need these so expose 212fbccdeb8SJoel Fernandes * them here. 213fbccdeb8SJoel Fernandes */ 214fbccdeb8SJoel Fernandes 215fbccdeb8SJoel Fernandes #if NR_CPUS <= 2 && defined(CONFIG_ARM_THUMB) 216fbccdeb8SJoel Fernandes #define PSTORE_CPU_IN_IP 0x1 217fbccdeb8SJoel Fernandes #elif NR_CPUS <= 4 && defined(CONFIG_ARM) 218fbccdeb8SJoel Fernandes #define PSTORE_CPU_IN_IP 0x3 219fbccdeb8SJoel Fernandes #endif 220fbccdeb8SJoel Fernandes 221fbccdeb8SJoel Fernandes #define TS_CPU_SHIFT 8 222fbccdeb8SJoel Fernandes #define TS_CPU_MASK (BIT(TS_CPU_SHIFT) - 1) 223fbccdeb8SJoel Fernandes 224fbccdeb8SJoel Fernandes /* 225fbccdeb8SJoel Fernandes * If CPU number can be stored in IP, store it there, otherwise store it in 226fbccdeb8SJoel Fernandes * the time stamp. This means more timestamp resolution is available when 227fbccdeb8SJoel Fernandes * the CPU can be stored in the IP. 228fbccdeb8SJoel Fernandes */ 229fbccdeb8SJoel Fernandes #ifdef PSTORE_CPU_IN_IP 230fbccdeb8SJoel Fernandes static inline void 231fbccdeb8SJoel Fernandes pstore_ftrace_encode_cpu(struct pstore_ftrace_record *rec, unsigned int cpu) 232fbccdeb8SJoel Fernandes { 233fbccdeb8SJoel Fernandes rec->ip |= cpu; 234fbccdeb8SJoel Fernandes } 235fbccdeb8SJoel Fernandes 236fbccdeb8SJoel Fernandes static inline unsigned int 237fbccdeb8SJoel Fernandes pstore_ftrace_decode_cpu(struct pstore_ftrace_record *rec) 238fbccdeb8SJoel Fernandes { 239fbccdeb8SJoel Fernandes return rec->ip & PSTORE_CPU_IN_IP; 240fbccdeb8SJoel Fernandes } 241fbccdeb8SJoel Fernandes 242fbccdeb8SJoel Fernandes static inline u64 243fbccdeb8SJoel Fernandes pstore_ftrace_read_timestamp(struct pstore_ftrace_record *rec) 244fbccdeb8SJoel Fernandes { 245fbccdeb8SJoel Fernandes return rec->ts; 246fbccdeb8SJoel Fernandes } 247fbccdeb8SJoel Fernandes 248fbccdeb8SJoel Fernandes static inline void 249fbccdeb8SJoel Fernandes pstore_ftrace_write_timestamp(struct pstore_ftrace_record *rec, u64 val) 250fbccdeb8SJoel Fernandes { 251fbccdeb8SJoel Fernandes rec->ts = val; 252fbccdeb8SJoel Fernandes } 253fbccdeb8SJoel Fernandes #else 254fbccdeb8SJoel Fernandes static inline void 255fbccdeb8SJoel Fernandes pstore_ftrace_encode_cpu(struct pstore_ftrace_record *rec, unsigned int cpu) 256fbccdeb8SJoel Fernandes { 257fbccdeb8SJoel Fernandes rec->ts &= ~(TS_CPU_MASK); 258fbccdeb8SJoel Fernandes rec->ts |= cpu; 259fbccdeb8SJoel Fernandes } 260fbccdeb8SJoel Fernandes 261fbccdeb8SJoel Fernandes static inline unsigned int 262fbccdeb8SJoel Fernandes pstore_ftrace_decode_cpu(struct pstore_ftrace_record *rec) 263fbccdeb8SJoel Fernandes { 264fbccdeb8SJoel Fernandes return rec->ts & TS_CPU_MASK; 265fbccdeb8SJoel Fernandes } 266fbccdeb8SJoel Fernandes 267fbccdeb8SJoel Fernandes static inline u64 268fbccdeb8SJoel Fernandes pstore_ftrace_read_timestamp(struct pstore_ftrace_record *rec) 269fbccdeb8SJoel Fernandes { 270fbccdeb8SJoel Fernandes return rec->ts >> TS_CPU_SHIFT; 271fbccdeb8SJoel Fernandes } 272fbccdeb8SJoel Fernandes 273fbccdeb8SJoel Fernandes static inline void 274fbccdeb8SJoel Fernandes pstore_ftrace_write_timestamp(struct pstore_ftrace_record *rec, u64 val) 275fbccdeb8SJoel Fernandes { 276fbccdeb8SJoel Fernandes rec->ts = (rec->ts & TS_CPU_MASK) | (val << TS_CPU_SHIFT); 277fbccdeb8SJoel Fernandes } 278fbccdeb8SJoel Fernandes #endif 279fbccdeb8SJoel Fernandes 280ca01d6ddSTony Luck #endif /*_LINUX_PSTORE_H*/ 281