2010-12-28 14:25:21 -08:00
/*
* Persistent Storage - pstore . h
*
* Copyright ( C ) 2010 Intel Corporation < tony . luck @ intel . com >
*
* This code is the generic layer to export data records from platform
* level persistent storage via a file system .
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
# ifndef _LINUX_PSTORE_H
# define _LINUX_PSTORE_H
2016-09-01 08:13:46 -07:00
# include <linux/compiler.h>
# include <linux/errno.h>
2011-11-17 13:13:29 -08:00
# include <linux/kmsg_dump.h>
2012-07-17 11:37:07 -07:00
# include <linux/mutex.h>
# include <linux/spinlock.h>
2016-09-01 08:13:46 -07:00
# include <linux/time.h>
# include <linux/types.h>
2011-11-17 13:13:29 -08:00
2017-03-03 16:59:29 -08:00
struct module ;
2017-03-03 12:16:16 -08:00
/* pstore record types (see fs/pstore/inode.c for filename templates) */
2010-12-28 14:25:21 -08:00
enum pstore_type_id {
PSTORE_TYPE_DMESG = 0 ,
PSTORE_TYPE_MCE = 1 ,
2012-05-26 06:20:19 -07:00
PSTORE_TYPE_CONSOLE = 2 ,
2012-07-09 17:10:41 -07:00
PSTORE_TYPE_FTRACE = 3 ,
2013-06-06 00:21:44 +05:30
/* PPC64 partition types */
PSTORE_TYPE_PPC_RTAS = 4 ,
2013-06-06 00:22:10 +05:30
PSTORE_TYPE_PPC_OF = 5 ,
2013-06-06 00:22:20 +05:30
PSTORE_TYPE_PPC_COMMON = 6 ,
2015-01-16 16:01:10 -08:00
PSTORE_TYPE_PMSG = 7 ,
2015-02-06 01:06:28 +05:30
PSTORE_TYPE_PPC_OPAL = 8 ,
2010-12-28 14:25:21 -08:00
PSTORE_TYPE_UNKNOWN = 255
} ;
2017-03-03 16:59:29 -08:00
struct pstore_info ;
/**
* struct pstore_record - details of a pstore record entry
* @ psi : pstore backend driver information
* @ type : pstore record type
* @ id : per - type unique identifier for record
* @ time : timestamp of the record
* @ buf : pointer to record contents
* @ size : size of @ buf
* @ ecc_notice_size :
* ECC information for @ buf
2017-03-03 23:28:53 -08:00
*
* Valid for PSTORE_TYPE_DMESG @ type :
*
* @ count : Oops count since boot
* @ reason : kdump reason for notification
* @ part : position in a multipart record
* @ compressed : whether the buffer is compressed
*
2017-03-03 16:59:29 -08:00
*/
struct pstore_record {
struct pstore_info * psi ;
enum pstore_type_id type ;
u64 id ;
struct timespec time ;
char * buf ;
ssize_t size ;
ssize_t ecc_notice_size ;
2017-03-03 23:28:53 -08:00
int count ;
enum kmsg_dump_reason reason ;
unsigned int part ;
bool compressed ;
2017-03-03 16:59:29 -08:00
} ;
2012-07-17 11:37:07 -07:00
2017-03-03 12:16:16 -08:00
/**
* struct pstore_info - backend pstore driver structure
*
* @ owner : module which is repsonsible for this backend driver
* @ name : name of the backend driver
*
* @ buf_lock : spinlock to serialize access to @ buf
* @ buf : preallocated crash dump buffer
* @ bufsize : size of @ buf available for crash dump writes
*
* @ read_mutex : serializes @ open , @ read , @ close , and @ erase callbacks
* @ flags : bitfield of frontends the backend can accept writes for
* @ data : backend - private pointer passed back during callbacks
*
* Callbacks :
*
* @ open :
* Notify backend that pstore is starting a full read of backend
* records . Followed by one or more @ read calls , and a final @ close .
*
* @ psi : in : pointer to the struct pstore_info for the backend
*
* Returns 0 on success , and non - zero on error .
*
* @ close :
* Notify backend that pstore has finished a full read of backend
* records . Always preceded by an @ open call and one or more @ read
* calls .
*
* @ psi : in : pointer to the struct pstore_info for the backend
*
* Returns 0 on success , and non - zero on error . ( Though pstore will
* ignore the error . )
*
* @ read :
* Read next available backend record . Called after a successful
* @ open .
*
2017-03-03 22:09:18 -08:00
* @ record :
* pointer to record to populate . @ buf should be allocated
* by the backend and filled . At least @ type and @ id should
* be populated , since these are used when creating pstorefs
* file names .
2017-03-03 12:16:16 -08:00
*
* Returns record size on success , zero when no more records are
* available , or negative on error .
*
* @ write :
2017-03-05 22:41:10 -08:00
* A newly generated record needs to be written to backend storage .
2017-03-03 12:16:16 -08:00
*
2017-03-03 23:28:53 -08:00
* @ record :
2017-03-05 22:41:10 -08:00
* pointer to record metadata . When @ type is PSTORE_TYPE_DMESG ,
* @ buf will be pointing to the preallocated @ psi . buf , since
* memory allocation may be broken during an Oops . Regardless ,
* @ buf must be proccesed or copied before returning . The
* backend is also expected to write @ id with something that
2017-05-19 15:29:10 -07:00
* can help identify this record to a future @ erase callback .
* The @ time field will be prepopulated with the current time ,
* when available . The @ size field will have the size of data
* in @ buf .
2017-03-03 12:16:16 -08:00
*
* Returns 0 on success , and non - zero on error .
*
2017-03-05 22:41:10 -08:00
* @ write_user :
2017-03-03 12:16:16 -08:00
* Perform a frontend write to a backend record , using a specified
2017-03-05 00:56:38 -08:00
* buffer that is coming directly from userspace , instead of the
* @ record @ buf .
*
* @ record : pointer to record metadata .
* @ buf : pointer to userspace contents to write to backend
2017-03-03 12:16:16 -08:00
*
* Returns 0 on success , and non - zero on error .
*
* @ erase :
* Delete a record from backend storage . Different backends
2017-03-04 23:31:19 -08:00
* identify records differently , so entire original record is
* passed back to assist in identification of what the backend
* should remove from storage .
2017-03-03 12:16:16 -08:00
*
2017-03-04 23:31:19 -08:00
* @ record : pointer to record metadata .
2017-03-03 12:16:16 -08:00
*
* Returns 0 on success , and non - zero on error .
*
*/
2010-12-28 14:25:21 -08:00
struct pstore_info {
struct module * owner ;
char * name ;
2017-03-03 12:16:16 -08:00
spinlock_t buf_lock ;
2010-12-28 14:25:21 -08:00
char * buf ;
size_t bufsize ;
2017-03-03 12:16:16 -08:00
struct mutex read_mutex ;
2013-12-18 15:17:10 -08:00
int flags ;
2017-03-03 12:16:16 -08:00
void * data ;
2011-05-16 11:00:27 -07:00
int ( * open ) ( struct pstore_info * psi ) ;
int ( * close ) ( struct pstore_info * psi ) ;
2017-03-03 22:09:18 -08:00
ssize_t ( * read ) ( struct pstore_record * record ) ;
2017-03-03 23:28:53 -08:00
int ( * write ) ( struct pstore_record * record ) ;
2017-03-05 22:41:10 -08:00
int ( * write_user ) ( struct pstore_record * record ,
const char __user * buf ) ;
2017-03-04 23:31:19 -08:00
int ( * erase ) ( struct pstore_record * record ) ;
2010-12-28 14:25:21 -08:00
} ;
2017-03-03 12:16:16 -08:00
/* Supported frontends */
2016-07-28 00:08:25 +09:00
# define PSTORE_FLAGS_DMESG (1 << 0)
# define PSTORE_FLAGS_CONSOLE (1 << 1)
# define PSTORE_FLAGS_FTRACE (1 << 2)
# define PSTORE_FLAGS_PMSG (1 << 3)
2010-12-28 14:25:21 -08:00
extern int pstore_register ( struct pstore_info * ) ;
2015-10-20 00:39:03 -07:00
extern void pstore_unregister ( struct pstore_info * ) ;
pstore: Avoid deadlock in panic and emergency-restart path
[Issue]
When pstore is in panic and emergency-restart paths, it may be blocked
in those paths because it simply takes spin_lock.
This is an example scenario which pstore may hang up in a panic path:
- cpuA grabs psinfo->buf_lock
- cpuB panics and calls smp_send_stop
- smp_send_stop sends IRQ to cpuA
- after 1 second, cpuB gives up on cpuA and sends an NMI instead
- cpuA is now in an NMI handler while still holding buf_lock
- cpuB is deadlocked
This case may happen if a firmware has a bug and
cpuA is stuck talking with it more than one second.
Also, this is a similar scenario in an emergency-restart path:
- cpuA grabs psinfo->buf_lock and stucks in a firmware
- cpuB kicks emergency-restart via either sysrq-b or hangcheck timer.
And then, cpuB is deadlocked by taking psinfo->buf_lock again.
[Solution]
This patch avoids the deadlocking issues in both panic and emergency_restart
paths by introducing a function, is_non_blocking_path(), to check if a cpu
can be blocked in current path.
With this patch, pstore is not blocked even if another cpu has
taken a spin_lock, in those paths by changing from spin_lock_irqsave
to spin_trylock_irqsave.
In addition, according to a comment of emergency_restart() in kernel/sys.c,
spin_lock shouldn't be taken in an emergency_restart path to avoid
deadlock. This patch fits the comment below.
<snip>
/**
* emergency_restart - reboot the system
*
* Without shutting down any hardware or taking any locks
* reboot the system. This is called when we know we are in
* trouble so this is our best effort to reboot. This is
* safe to call in interrupt context.
*/
void emergency_restart(void)
<snip>
Signed-off-by: Seiji Aguchi <seiji.aguchi@hds.com>
Acked-by: Don Zickus <dzickus@redhat.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
2013-01-11 18:09:41 +00:00
extern bool pstore_cannot_block_path ( enum kmsg_dump_reason reason ) ;
2010-12-28 14:25:21 -08:00
2016-10-20 00:34:05 -07:00
struct pstore_ftrace_record {
unsigned long ip ;
unsigned long parent_ip ;
u64 ts ;
} ;
/*
* ftrace related stuff : Both backends and frontends need these so expose
* them here .
*/
# if NR_CPUS <= 2 && defined(CONFIG_ARM_THUMB)
# define PSTORE_CPU_IN_IP 0x1
# elif NR_CPUS <= 4 && defined(CONFIG_ARM)
# define PSTORE_CPU_IN_IP 0x3
# endif
# define TS_CPU_SHIFT 8
# define TS_CPU_MASK (BIT(TS_CPU_SHIFT) - 1)
/*
* If CPU number can be stored in IP , store it there , otherwise store it in
* the time stamp . This means more timestamp resolution is available when
* the CPU can be stored in the IP .
*/
# ifdef PSTORE_CPU_IN_IP
static inline void
pstore_ftrace_encode_cpu ( struct pstore_ftrace_record * rec , unsigned int cpu )
{
rec - > ip | = cpu ;
}
static inline unsigned int
pstore_ftrace_decode_cpu ( struct pstore_ftrace_record * rec )
{
return rec - > ip & PSTORE_CPU_IN_IP ;
}
static inline u64
pstore_ftrace_read_timestamp ( struct pstore_ftrace_record * rec )
{
return rec - > ts ;
}
static inline void
pstore_ftrace_write_timestamp ( struct pstore_ftrace_record * rec , u64 val )
{
rec - > ts = val ;
}
# else
static inline void
pstore_ftrace_encode_cpu ( struct pstore_ftrace_record * rec , unsigned int cpu )
{
rec - > ts & = ~ ( TS_CPU_MASK ) ;
rec - > ts | = cpu ;
}
static inline unsigned int
pstore_ftrace_decode_cpu ( struct pstore_ftrace_record * rec )
{
return rec - > ts & TS_CPU_MASK ;
}
static inline u64
pstore_ftrace_read_timestamp ( struct pstore_ftrace_record * rec )
{
return rec - > ts > > TS_CPU_SHIFT ;
}
static inline void
pstore_ftrace_write_timestamp ( struct pstore_ftrace_record * rec , u64 val )
{
rec - > ts = ( rec - > ts & TS_CPU_MASK ) | ( val < < TS_CPU_SHIFT ) ;
}
# endif
2010-12-28 14:25:21 -08:00
# endif /*_LINUX_PSTORE_H*/