Commit 059c4a34 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'pstore-v6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux

Pull pstore updates from Kees Cook:
 "A small collection of bug fixes, refactorings, and general
  improvements:

   - Reporting improvements and return path fixes (Guilherme G. Piccoli,
     Wang Yufen, Kees Cook)

   - Clean up kmsg_bytes module parameter usage (Guilherme G. Piccoli)

   - Add Guilherme to pstore MAINTAINERS entry

   - Choose friendlier allocation flags (Qiujun Huang, Stephen Boyd)"

* tag 'pstore-v6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux:
  pstore: Avoid kcore oops by vmap()ing with VM_IOREMAP
  pstore/ram: Fix error return code in ramoops_probe()
  pstore: Alert on backend write error
  MAINTAINERS: Update pstore maintainers
  pstore/ram: Set freed addresses to NULL
  pstore/ram: Move internal definitions out of kernel-wide include
  pstore/ram: Move pmsg init earlier
  pstore/ram: Consolidate kfree() paths
  efi: pstore: Follow convention for the efi-pstore backend name
  pstore: Inform unregistered backend names as well
  pstore: Expose kmsg_bytes as a module parameter
  pstore: Improve error reporting in case of backend overlap
  pstore/zone: Use GFP_ATOMIC to allocate zone buffer
parents 3a28c2c8 e6b84274
...@@ -16661,10 +16661,10 @@ F: net/psample ...@@ -16661,10 +16661,10 @@ F: net/psample
PSTORE FILESYSTEM PSTORE FILESYSTEM
M: Kees Cook <keescook@chromium.org> M: Kees Cook <keescook@chromium.org>
M: Anton Vorontsov <anton@enomsg.org> R: Tony Luck <tony.luck@intel.com>
M: Colin Cross <ccross@android.com> R: Guilherme G. Piccoli <gpiccoli@igalia.com>
M: Tony Luck <tony.luck@intel.com> L: linux-hardening@vger.kernel.org
S: Maintained S: Supported
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/pstore T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/pstore
F: Documentation/admin-guide/ramoops.rst F: Documentation/admin-guide/ramoops.rst
F: Documentation/admin-guide/pstore-blk.rst F: Documentation/admin-guide/pstore-blk.rst
......
...@@ -207,7 +207,7 @@ static int efi_pstore_erase(struct pstore_record *record) ...@@ -207,7 +207,7 @@ static int efi_pstore_erase(struct pstore_record *record)
static struct pstore_info efi_pstore_info = { static struct pstore_info efi_pstore_info = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "efi", .name = KBUILD_MODNAME,
.flags = PSTORE_FLAGS_DMESG, .flags = PSTORE_FLAGS_DMESG,
.open = efi_pstore_open, .open = efi_pstore_open,
.close = efi_pstore_close, .close = efi_pstore_close,
......
...@@ -89,6 +89,11 @@ static char *compress = ...@@ -89,6 +89,11 @@ static char *compress =
module_param(compress, charp, 0444); module_param(compress, charp, 0444);
MODULE_PARM_DESC(compress, "compression to use"); MODULE_PARM_DESC(compress, "compression to use");
/* How much of the kernel log to snapshot */
unsigned long kmsg_bytes = CONFIG_PSTORE_DEFAULT_KMSG_BYTES;
module_param(kmsg_bytes, ulong, 0444);
MODULE_PARM_DESC(kmsg_bytes, "amount of kernel log to snapshot (in bytes)");
/* Compression parameters */ /* Compression parameters */
static struct crypto_comp *tfm; static struct crypto_comp *tfm;
...@@ -100,9 +105,6 @@ struct pstore_zbackend { ...@@ -100,9 +105,6 @@ struct pstore_zbackend {
static char *big_oops_buf; static char *big_oops_buf;
static size_t big_oops_buf_sz; static size_t big_oops_buf_sz;
/* How much of the console log to snapshot */
unsigned long kmsg_bytes = CONFIG_PSTORE_DEFAULT_KMSG_BYTES;
void pstore_set_kmsg_bytes(int bytes) void pstore_set_kmsg_bytes(int bytes)
{ {
kmsg_bytes = bytes; kmsg_bytes = bytes;
...@@ -391,6 +393,7 @@ static void pstore_dump(struct kmsg_dumper *dumper, ...@@ -391,6 +393,7 @@ static void pstore_dump(struct kmsg_dumper *dumper,
const char *why; const char *why;
unsigned int part = 1; unsigned int part = 1;
unsigned long flags = 0; unsigned long flags = 0;
int saved_ret = 0;
int ret; int ret;
why = kmsg_dump_reason_str(reason); why = kmsg_dump_reason_str(reason);
...@@ -461,12 +464,21 @@ static void pstore_dump(struct kmsg_dumper *dumper, ...@@ -461,12 +464,21 @@ static void pstore_dump(struct kmsg_dumper *dumper,
if (ret == 0 && reason == KMSG_DUMP_OOPS) { if (ret == 0 && reason == KMSG_DUMP_OOPS) {
pstore_new_entry = 1; pstore_new_entry = 1;
pstore_timer_kick(); pstore_timer_kick();
} else {
/* Preserve only the first non-zero returned value. */
if (!saved_ret)
saved_ret = ret;
} }
total += record.size; total += record.size;
part++; part++;
} }
spin_unlock_irqrestore(&psinfo->buf_lock, flags); spin_unlock_irqrestore(&psinfo->buf_lock, flags);
if (saved_ret) {
pr_err_once("backend (%s) writing error (%d)\n", psinfo->name,
saved_ret);
}
} }
static struct kmsg_dumper pstore_dumper = { static struct kmsg_dumper pstore_dumper = {
...@@ -562,8 +574,9 @@ static int pstore_write_user_compat(struct pstore_record *record, ...@@ -562,8 +574,9 @@ static int pstore_write_user_compat(struct pstore_record *record,
int pstore_register(struct pstore_info *psi) int pstore_register(struct pstore_info *psi)
{ {
if (backend && strcmp(backend, psi->name)) { if (backend && strcmp(backend, psi->name)) {
pr_warn("ignoring unexpected backend '%s'\n", psi->name); pr_warn("backend '%s' already in use: ignoring '%s'\n",
return -EPERM; backend, psi->name);
return -EBUSY;
} }
/* Sanity check flags. */ /* Sanity check flags. */
...@@ -662,6 +675,8 @@ void pstore_unregister(struct pstore_info *psi) ...@@ -662,6 +675,8 @@ void pstore_unregister(struct pstore_info *psi)
psinfo = NULL; psinfo = NULL;
kfree(backend); kfree(backend);
backend = NULL; backend = NULL;
pr_info("Unregistered %s as persistent store backend\n", psi->name);
mutex_unlock(&psinfo_lock); mutex_unlock(&psinfo_lock);
} }
EXPORT_SYMBOL_GPL(pstore_unregister); EXPORT_SYMBOL_GPL(pstore_unregister);
......
...@@ -18,10 +18,11 @@ ...@@ -18,10 +18,11 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/compiler.h> #include <linux/compiler.h>
#include <linux/pstore_ram.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include "internal.h" #include "internal.h"
#include "ram_internal.h"
#define RAMOOPS_KERNMSG_HDR "====" #define RAMOOPS_KERNMSG_HDR "===="
#define MIN_MEM_SIZE 4096UL #define MIN_MEM_SIZE 4096UL
...@@ -451,20 +452,28 @@ static void ramoops_free_przs(struct ramoops_context *cxt) ...@@ -451,20 +452,28 @@ static void ramoops_free_przs(struct ramoops_context *cxt)
{ {
int i; int i;
/* Free pmsg PRZ */
persistent_ram_free(&cxt->mprz);
/* Free console PRZ */
persistent_ram_free(&cxt->cprz);
/* Free dump PRZs */ /* Free dump PRZs */
if (cxt->dprzs) { if (cxt->dprzs) {
for (i = 0; i < cxt->max_dump_cnt; i++) for (i = 0; i < cxt->max_dump_cnt; i++)
persistent_ram_free(cxt->dprzs[i]); persistent_ram_free(&cxt->dprzs[i]);
kfree(cxt->dprzs); kfree(cxt->dprzs);
cxt->dprzs = NULL;
cxt->max_dump_cnt = 0; cxt->max_dump_cnt = 0;
} }
/* Free ftrace PRZs */ /* Free ftrace PRZs */
if (cxt->fprzs) { if (cxt->fprzs) {
for (i = 0; i < cxt->max_ftrace_cnt; i++) for (i = 0; i < cxt->max_ftrace_cnt; i++)
persistent_ram_free(cxt->fprzs[i]); persistent_ram_free(&cxt->fprzs[i]);
kfree(cxt->fprzs); kfree(cxt->fprzs);
cxt->fprzs = NULL;
cxt->max_ftrace_cnt = 0; cxt->max_ftrace_cnt = 0;
} }
} }
...@@ -548,9 +557,10 @@ static int ramoops_init_przs(const char *name, ...@@ -548,9 +557,10 @@ static int ramoops_init_przs(const char *name,
while (i > 0) { while (i > 0) {
i--; i--;
persistent_ram_free(prz_ar[i]); persistent_ram_free(&prz_ar[i]);
} }
kfree(prz_ar); kfree(prz_ar);
prz_ar = NULL;
goto fail; goto fail;
} }
*paddr += zone_sz; *paddr += zone_sz;
...@@ -735,6 +745,7 @@ static int ramoops_probe(struct platform_device *pdev) ...@@ -735,6 +745,7 @@ static int ramoops_probe(struct platform_device *pdev)
/* Make sure we didn't get bogus platform data pointer. */ /* Make sure we didn't get bogus platform data pointer. */
if (!pdata) { if (!pdata) {
pr_err("NULL platform data\n"); pr_err("NULL platform data\n");
err = -EINVAL;
goto fail_out; goto fail_out;
} }
...@@ -742,6 +753,7 @@ static int ramoops_probe(struct platform_device *pdev) ...@@ -742,6 +753,7 @@ static int ramoops_probe(struct platform_device *pdev)
!pdata->ftrace_size && !pdata->pmsg_size)) { !pdata->ftrace_size && !pdata->pmsg_size)) {
pr_err("The memory size and the record/console size must be " pr_err("The memory size and the record/console size must be "
"non-zero\n"); "non-zero\n");
err = -EINVAL;
goto fail_out; goto fail_out;
} }
...@@ -772,12 +784,17 @@ static int ramoops_probe(struct platform_device *pdev) ...@@ -772,12 +784,17 @@ static int ramoops_probe(struct platform_device *pdev)
dump_mem_sz, cxt->record_size, dump_mem_sz, cxt->record_size,
&cxt->max_dump_cnt, 0, 0); &cxt->max_dump_cnt, 0, 0);
if (err) if (err)
goto fail_out; goto fail_init;
err = ramoops_init_prz("console", dev, cxt, &cxt->cprz, &paddr, err = ramoops_init_prz("console", dev, cxt, &cxt->cprz, &paddr,
cxt->console_size, 0); cxt->console_size, 0);
if (err) if (err)
goto fail_init_cprz; goto fail_init;
err = ramoops_init_prz("pmsg", dev, cxt, &cxt->mprz, &paddr,
cxt->pmsg_size, 0);
if (err)
goto fail_init;
cxt->max_ftrace_cnt = (cxt->flags & RAMOOPS_FLAG_FTRACE_PER_CPU) cxt->max_ftrace_cnt = (cxt->flags & RAMOOPS_FLAG_FTRACE_PER_CPU)
? nr_cpu_ids ? nr_cpu_ids
...@@ -788,12 +805,7 @@ static int ramoops_probe(struct platform_device *pdev) ...@@ -788,12 +805,7 @@ static int ramoops_probe(struct platform_device *pdev)
(cxt->flags & RAMOOPS_FLAG_FTRACE_PER_CPU) (cxt->flags & RAMOOPS_FLAG_FTRACE_PER_CPU)
? PRZ_FLAG_NO_LOCK : 0); ? PRZ_FLAG_NO_LOCK : 0);
if (err) if (err)
goto fail_init_fprz; goto fail_init;
err = ramoops_init_prz("pmsg", dev, cxt, &cxt->mprz, &paddr,
cxt->pmsg_size, 0);
if (err)
goto fail_init_mprz;
cxt->pstore.data = cxt; cxt->pstore.data = cxt;
/* /*
...@@ -857,11 +869,7 @@ static int ramoops_probe(struct platform_device *pdev) ...@@ -857,11 +869,7 @@ static int ramoops_probe(struct platform_device *pdev)
kfree(cxt->pstore.buf); kfree(cxt->pstore.buf);
fail_clear: fail_clear:
cxt->pstore.bufsize = 0; cxt->pstore.bufsize = 0;
persistent_ram_free(cxt->mprz); fail_init:
fail_init_mprz:
fail_init_fprz:
persistent_ram_free(cxt->cprz);
fail_init_cprz:
ramoops_free_przs(cxt); ramoops_free_przs(cxt);
fail_out: fail_out:
return err; return err;
...@@ -876,8 +884,6 @@ static int ramoops_remove(struct platform_device *pdev) ...@@ -876,8 +884,6 @@ static int ramoops_remove(struct platform_device *pdev)
kfree(cxt->pstore.buf); kfree(cxt->pstore.buf);
cxt->pstore.bufsize = 0; cxt->pstore.bufsize = 0;
persistent_ram_free(cxt->mprz);
persistent_ram_free(cxt->cprz);
ramoops_free_przs(cxt); ramoops_free_przs(cxt);
return 0; return 0;
......
...@@ -13,13 +13,14 @@ ...@@ -13,13 +13,14 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/memblock.h> #include <linux/memblock.h>
#include <linux/pstore_ram.h>
#include <linux/rslib.h> #include <linux/rslib.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <asm/page.h> #include <asm/page.h>
#include "ram_internal.h"
/** /**
* struct persistent_ram_buffer - persistent circular RAM buffer * struct persistent_ram_buffer - persistent circular RAM buffer
* *
...@@ -439,7 +440,11 @@ static void *persistent_ram_vmap(phys_addr_t start, size_t size, ...@@ -439,7 +440,11 @@ static void *persistent_ram_vmap(phys_addr_t start, size_t size,
phys_addr_t addr = page_start + i * PAGE_SIZE; phys_addr_t addr = page_start + i * PAGE_SIZE;
pages[i] = pfn_to_page(addr >> PAGE_SHIFT); pages[i] = pfn_to_page(addr >> PAGE_SHIFT);
} }
vaddr = vmap(pages, page_count, VM_MAP, prot); /*
* VM_IOREMAP used here to bypass this region during vread()
* and kmap_atomic() (i.e. kcore) to avoid __va() failures.
*/
vaddr = vmap(pages, page_count, VM_MAP | VM_IOREMAP, prot);
kfree(pages); kfree(pages);
/* /*
...@@ -543,8 +548,14 @@ static int persistent_ram_post_init(struct persistent_ram_zone *prz, u32 sig, ...@@ -543,8 +548,14 @@ static int persistent_ram_post_init(struct persistent_ram_zone *prz, u32 sig,
return 0; return 0;
} }
void persistent_ram_free(struct persistent_ram_zone *prz) void persistent_ram_free(struct persistent_ram_zone **_prz)
{ {
struct persistent_ram_zone *prz;
if (!_prz)
return;
prz = *_prz;
if (!prz) if (!prz)
return; return;
...@@ -568,6 +579,7 @@ void persistent_ram_free(struct persistent_ram_zone *prz) ...@@ -568,6 +579,7 @@ void persistent_ram_free(struct persistent_ram_zone *prz)
persistent_ram_free_old(prz); persistent_ram_free_old(prz);
kfree(prz->label); kfree(prz->label);
kfree(prz); kfree(prz);
*_prz = NULL;
} }
struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size, struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size,
...@@ -604,6 +616,6 @@ struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size, ...@@ -604,6 +616,6 @@ struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size,
return prz; return prz;
err: err:
persistent_ram_free(prz); persistent_ram_free(&prz);
return ERR_PTR(ret); return ERR_PTR(ret);
} }
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2010 Marco Stornelli <marco.stornelli@gmail.com>
* Copyright (C) 2011 Kees Cook <keescook@chromium.org>
* Copyright (C) 2011 Google, Inc.
*/
#include <linux/pstore_ram.h>
/*
* Choose whether access to the RAM zone requires locking or not. If a zone
* can be written to from different CPUs like with ftrace for example, then
* PRZ_FLAG_NO_LOCK is used. For all other cases, locking is required.
*/
#define PRZ_FLAG_NO_LOCK BIT(0)
/*
* If a PRZ should only have a single-boot lifetime, this marks it as
* getting wiped after its contents get copied out after boot.
*/
#define PRZ_FLAG_ZAP_OLD BIT(1)
/**
* struct persistent_ram_zone - Details of a persistent RAM zone (PRZ)
* used as a pstore backend
*
* @paddr: physical address of the mapped RAM area
* @size: size of mapping
* @label: unique name of this PRZ
* @type: frontend type for this PRZ
* @flags: holds PRZ_FLAGS_* bits
*
* @buffer_lock:
* locks access to @buffer "size" bytes and "start" offset
* @buffer:
* pointer to actual RAM area managed by this PRZ
* @buffer_size:
* bytes in @buffer->data (not including any trailing ECC bytes)
*
* @par_buffer:
* pointer into @buffer->data containing ECC bytes for @buffer->data
* @par_header:
* pointer into @buffer->data containing ECC bytes for @buffer header
* (i.e. all fields up to @data)
* @rs_decoder:
* RSLIB instance for doing ECC calculations
* @corrected_bytes:
* ECC corrected bytes accounting since boot
* @bad_blocks:
* ECC uncorrectable bytes accounting since boot
* @ecc_info:
* ECC configuration details
*
* @old_log:
* saved copy of @buffer->data prior to most recent wipe
* @old_log_size:
* bytes contained in @old_log
*
*/
struct persistent_ram_zone {
phys_addr_t paddr;
size_t size;
void *vaddr;
char *label;
enum pstore_type_id type;
u32 flags;
raw_spinlock_t buffer_lock;
struct persistent_ram_buffer *buffer;
size_t buffer_size;
char *par_buffer;
char *par_header;
struct rs_control *rs_decoder;
int corrected_bytes;
int bad_blocks;
struct persistent_ram_ecc_info ecc_info;
char *old_log;
size_t old_log_size;
};
struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size,
u32 sig, struct persistent_ram_ecc_info *ecc_info,
unsigned int memtype, u32 flags, char *label);
void persistent_ram_free(struct persistent_ram_zone **_prz);
void persistent_ram_zap(struct persistent_ram_zone *prz);
int persistent_ram_write(struct persistent_ram_zone *prz, const void *s,
unsigned int count);
int persistent_ram_write_user(struct persistent_ram_zone *prz,
const void __user *s, unsigned int count);
void persistent_ram_save_old(struct persistent_ram_zone *prz);
size_t persistent_ram_old_size(struct persistent_ram_zone *prz);
void *persistent_ram_old(struct persistent_ram_zone *prz);
void persistent_ram_free_old(struct persistent_ram_zone *prz);
ssize_t persistent_ram_ecc_string(struct persistent_ram_zone *prz,
char *str, size_t len);
...@@ -761,7 +761,7 @@ static inline int notrace psz_kmsg_write_record(struct psz_context *cxt, ...@@ -761,7 +761,7 @@ static inline int notrace psz_kmsg_write_record(struct psz_context *cxt,
/* avoid destroying old data, allocate a new one */ /* avoid destroying old data, allocate a new one */
len = zone->buffer_size + sizeof(*zone->buffer); len = zone->buffer_size + sizeof(*zone->buffer);
zone->oldbuf = zone->buffer; zone->oldbuf = zone->buffer;
zone->buffer = kzalloc(len, GFP_KERNEL); zone->buffer = kzalloc(len, GFP_ATOMIC);
if (!zone->buffer) { if (!zone->buffer) {
zone->buffer = zone->oldbuf; zone->buffer = zone->oldbuf;
return -ENOMEM; return -ENOMEM;
......
...@@ -8,28 +8,7 @@ ...@@ -8,28 +8,7 @@
#ifndef __LINUX_PSTORE_RAM_H__ #ifndef __LINUX_PSTORE_RAM_H__
#define __LINUX_PSTORE_RAM_H__ #define __LINUX_PSTORE_RAM_H__
#include <linux/compiler.h>
#include <linux/device.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/pstore.h> #include <linux/pstore.h>
#include <linux/types.h>
/*
* Choose whether access to the RAM zone requires locking or not. If a zone
* can be written to from different CPUs like with ftrace for example, then
* PRZ_FLAG_NO_LOCK is used. For all other cases, locking is required.
*/
#define PRZ_FLAG_NO_LOCK BIT(0)
/*
* If a PRZ should only have a single-boot lifetime, this marks it as
* getting wiped after its contents get copied out after boot.
*/
#define PRZ_FLAG_ZAP_OLD BIT(1)
struct persistent_ram_buffer;
struct rs_control;
struct persistent_ram_ecc_info { struct persistent_ram_ecc_info {
int block_size; int block_size;
...@@ -39,84 +18,6 @@ struct persistent_ram_ecc_info { ...@@ -39,84 +18,6 @@ struct persistent_ram_ecc_info {
uint16_t *par; uint16_t *par;
}; };
/**
* struct persistent_ram_zone - Details of a persistent RAM zone (PRZ)
* used as a pstore backend
*
* @paddr: physical address of the mapped RAM area
* @size: size of mapping
* @label: unique name of this PRZ
* @type: frontend type for this PRZ
* @flags: holds PRZ_FLAGS_* bits
*
* @buffer_lock:
* locks access to @buffer "size" bytes and "start" offset
* @buffer:
* pointer to actual RAM area managed by this PRZ
* @buffer_size:
* bytes in @buffer->data (not including any trailing ECC bytes)
*
* @par_buffer:
* pointer into @buffer->data containing ECC bytes for @buffer->data
* @par_header:
* pointer into @buffer->data containing ECC bytes for @buffer header
* (i.e. all fields up to @data)
* @rs_decoder:
* RSLIB instance for doing ECC calculations
* @corrected_bytes:
* ECC corrected bytes accounting since boot
* @bad_blocks:
* ECC uncorrectable bytes accounting since boot
* @ecc_info:
* ECC configuration details
*
* @old_log:
* saved copy of @buffer->data prior to most recent wipe
* @old_log_size:
* bytes contained in @old_log
*
*/
struct persistent_ram_zone {
phys_addr_t paddr;
size_t size;
void *vaddr;
char *label;
enum pstore_type_id type;
u32 flags;
raw_spinlock_t buffer_lock;
struct persistent_ram_buffer *buffer;
size_t buffer_size;
char *par_buffer;
char *par_header;
struct rs_control *rs_decoder;
int corrected_bytes;
int bad_blocks;
struct persistent_ram_ecc_info ecc_info;
char *old_log;
size_t old_log_size;
};
struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size,
u32 sig, struct persistent_ram_ecc_info *ecc_info,
unsigned int memtype, u32 flags, char *label);
void persistent_ram_free(struct persistent_ram_zone *prz);
void persistent_ram_zap(struct persistent_ram_zone *prz);
int persistent_ram_write(struct persistent_ram_zone *prz, const void *s,
unsigned int count);
int persistent_ram_write_user(struct persistent_ram_zone *prz,
const void __user *s, unsigned int count);
void persistent_ram_save_old(struct persistent_ram_zone *prz);
size_t persistent_ram_old_size(struct persistent_ram_zone *prz);
void *persistent_ram_old(struct persistent_ram_zone *prz);
void persistent_ram_free_old(struct persistent_ram_zone *prz);
ssize_t persistent_ram_ecc_string(struct persistent_ram_zone *prz,
char *str, size_t len);
/* /*
* Ramoops platform data * Ramoops platform data
* @mem_size memory size for ramoops * @mem_size memory size for ramoops
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment