From 97885140bf64b43adee76e23179eae9bd1393296 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Fri, 15 Mar 2019 10:14:43 +0100 Subject: pstore/ram: Do not use stack VLA for parity workspace Instead of using a stack VLA for the parity workspace, preallocate a memory region. The preallocation is done to keep from needing to perform allocations during crash dump writing, etc. This also fixes a missed release of librs on free. Signed-off-by: Kees Cook [p.zabel@pengutronix.de: ported to Barebox from Linux commit f2531f1976d9] Signed-off-by: Philipp Zabel Signed-off-by: Sascha Hauer --- include/linux/pstore_ram.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/pstore_ram.h b/include/linux/pstore_ram.h index 5ef823a57b..ecdd229dd4 100644 --- a/include/linux/pstore_ram.h +++ b/include/linux/pstore_ram.h @@ -29,6 +29,7 @@ struct persistent_ram_ecc_info { int ecc_size; int symsize; int poly; + uint16_t *par; }; struct persistent_ram_zone { -- cgit v1.2.3 From 34e46e5863fbf24af9b81bf5330d7301c9f58260 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Fri, 15 Mar 2019 10:14:45 +0100 Subject: pstore/ram: Clarify resource reservation labels When ramoops reserved a memory region in the kernel, it had an unhelpful label of "persistent ram". When reading iomem, it would be repeated many times, did not hint that it was ramoops in particular, and didn't clarify very much about what each was used for: 0x4fdd4000 - 0x4fdf3fff (size 0x00020000) persistent ram 0x4fdf4000 - 0x4fe13fff (size 0x00020000) persistent ram ... 0x4ff74000 - 0x4ff93fff (size 0x00020000) persistent ram 0x4ff94000 - 0x4ffb3fff (size 0x00020000) persistent ram 0x4ffb4000 - 0x4ffd3fff (size 0x00020000) persistent ram Instead, this adds meaningful labels for how the various regions are being used: 0x4fdd4000 - 0x4fdf3fff (size 0x00020000) ramoops:dump(0/12) 0x4fdf4000 - 0x4fe13fff (size 0x00020000) ramoops:dump(1/12) ... 0x4ff74000 - 0x4ff93fff (size 0x00020000) ramoops:console 0x4ff94000 - 0x4ffb3fff (size 0x00020000) ramoops:ftrace 0x4ffb4000 - 0x4ffd3fff (size 0x00020000) ramoops:pmsg Signed-off-by: Kees Cook Reviewed-by: Joel Fernandes (Google) [p.zabel@pengutronix.de: ported to Barebox from Linux commit 1227daa43bce] Signed-off-by: Philipp Zabel Signed-off-by: Sascha Hauer --- Documentation/filesystems/pstore.rst | 44 ++++++++++++++++-------------------- fs/pstore/ram.c | 15 ++++++++++-- fs/pstore/ram_core.c | 8 +++++-- include/linux/pstore_ram.h | 3 ++- 4 files changed, 40 insertions(+), 30 deletions(-) (limited to 'include/linux') diff --git a/Documentation/filesystems/pstore.rst b/Documentation/filesystems/pstore.rst index 22e89b3f1f..6215f2296c 100644 --- a/Documentation/filesystems/pstore.rst +++ b/Documentation/filesystems/pstore.rst @@ -47,35 +47,29 @@ generated by Barebox. You can change these parameters in Barebox menuconfig. The RAMOOPS parameters for the Kernel are stored in the variable global.linux.bootargs.ramoops. -To see where the RAMOOPS area is located, you can execute iomem in Barebox. The -RAMOOPS area is listed as 'persistent ram': +You can adapt the *pstore* parameters in Barebox menuconfig. + +To see where the RAMOOPS area is located, you can execute the ``iomem`` command +in the Barebox shell. The RAMOOPS area is listed as 'persistent ram': .. code-block:: none 0x10000000 - 0x1fffffff (size 0x10000000) ram0 - 0x17e7c0c0 - 0x1fcf817f (size 0x07e7c0c0) malloc space - 0x1fcf8180 - 0x1fcfffff (size 0x00007e80) board data - 0x1fd00000 - 0x1fd6eeff (size 0x0006ef00) barebox - 0x1fd6ef00 - 0x1fd88dff (size 0x00019f00) barebox data - 0x1fd88e00 - 0x1fd8c3db (size 0x000035dc) bss - 0x1fdf4000 - 0x1fe13fff (size 0x00020000) persistent ram - 0x1fe14000 - 0x1fe33fff (size 0x00020000) persistent ram - 0x1fe34000 - 0x1fe53fff (size 0x00020000) persistent ram - 0x1fe54000 - 0x1fe73fff (size 0x00020000) persistent ram - 0x1fe74000 - 0x1fe93fff (size 0x00020000) persistent ram - 0x1fe94000 - 0x1feb3fff (size 0x00020000) persistent ram - 0x1feb4000 - 0x1fed3fff (size 0x00020000) persistent ram - 0x1fed4000 - 0x1fef3fff (size 0x00020000) persistent ram - 0x1fef4000 - 0x1ff13fff (size 0x00020000) persistent ram - 0x1ff14000 - 0x1ff33fff (size 0x00020000) persistent ram - 0x1ff34000 - 0x1ff53fff (size 0x00020000) persistent ram - 0x1ff54000 - 0x1ff73fff (size 0x00020000) persistent ram - 0x1ff74000 - 0x1ff93fff (size 0x00020000) persistent ram - 0x1ff94000 - 0x1ffb3fff (size 0x00020000) persistent ram - 0x1ffb4000 - 0x1ffd3fff (size 0x00020000) persistent ram - 0x1ffd4000 - 0x1fff3fff (size 0x00020000) persistent ram - 0x1fff4000 - 0x1fff7fff (size 0x00004000) ttb - 0x1fff8000 - 0x1fffffff (size 0x00008000) stack + 0x247f59c0 - 0x2fbf59bf (size 0x0b400000) malloc space + 0x2fbf59c0 - 0x2fbffffe (size 0x0000a63f) board data + 0x2fc00000 - 0x2fc8619f (size 0x000861a0) barebox + 0x2fc861a0 - 0x2fca35ef (size 0x0001d450) barebox data + 0x2fca35f0 - 0x2fca9007 (size 0x00005a18) bss + 0x2fdd4000 - 0x2fdf3fff (size 0x00020000) ramoops:dump(0/4) + 0x2fdf4000 - 0x2fe13fff (size 0x00020000) ramoops:dump(1/4) + 0x2fe14000 - 0x2fe33fff (size 0x00020000) ramoops:dump(2/4) + 0x2fe34000 - 0x2fe53fff (size 0x00020000) ramoops:dump(3/4) + 0x2fe54000 - 0x2fe73fff (size 0x00020000) ramoops:dump(4/4) + 0x2fe74000 - 0x2fe93fff (size 0x00020000) ramoops:console + 0x2fe94000 - 0x2feb3fff (size 0x00020000) ramoops:ftrace + 0x2feb4000 - 0x2fed3fff (size 0x00020000) ramoops:pmsg + 0x2fee4000 - 0x2fee7fff (size 0x00004000) ttb + 0x2fee8000 - 0x2feeffff (size 0x00008000) stack All pstore files that could be found are added to the /pstore directory. This is a read-only filesystem. If you disable the Kconfig option FS_PSTORE_RAMOOPS_RO, diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c index d46612fbff..714755bd66 100644 --- a/fs/pstore/ram.c +++ b/fs/pstore/ram.c @@ -334,8 +334,16 @@ static int ramoops_init_przs(const char *name, goto fail; for (i = 0; i < *cnt; i++) { + char *label; + + if (*cnt == 1) + label = basprintf("ramoops:%s", name); + else + label = basprintf("ramoops:%s(%d/%d)", + name, i, *cnt - 1); prz_ar[i] = persistent_ram_new(*paddr, zone_sz, sig, - &cxt->ecc_info, cxt->memtype); + &cxt->ecc_info, + cxt->memtype, label); if (IS_ERR(prz_ar[i])) { err = PTR_ERR(prz_ar[i]); pr_err("failed to request %s mem region (0x%zx@0x%llx): %d\n", @@ -365,6 +373,8 @@ static int ramoops_init_prz(const char *name, struct persistent_ram_zone **prz, phys_addr_t *paddr, size_t sz, u32 sig) { + char *label; + if (!sz) return 0; @@ -375,8 +385,9 @@ static int ramoops_init_prz(const char *name, return -ENOMEM; } + label = basprintf("ramoops:%s", name); *prz = persistent_ram_new(*paddr, sz, sig, &cxt->ecc_info, - cxt->memtype); + cxt->memtype, label); if (IS_ERR(*prz)) { int err = PTR_ERR(*prz); diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c index ed48dcddd5..0f7003f937 100644 --- a/fs/pstore/ram_core.c +++ b/fs/pstore/ram_core.c @@ -346,7 +346,7 @@ void persistent_ram_zap(struct persistent_ram_zone *prz) static int persistent_ram_buffer_map(phys_addr_t start, phys_addr_t size, struct persistent_ram_zone *prz, int memtype) { - prz->res = request_sdram_region("persistent ram", start, size); + prz->res = request_sdram_region(prz->label ?: "ramoops", start, size); if (!prz->res) return -ENOMEM; @@ -409,12 +409,13 @@ void persistent_ram_free(struct persistent_ram_zone *prz) prz->ecc_info.par = NULL; persistent_ram_free_old(prz); + kfree(prz->label); kfree(prz); } 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) + unsigned int memtype, char *label) { struct persistent_ram_zone *prz; int ret = -ENOMEM; @@ -425,6 +426,9 @@ struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size, goto err; } + /* Initialize general buffer state. */ + prz->label = label; + ret = persistent_ram_buffer_map(start, size, prz, memtype); if (ret) goto err; diff --git a/include/linux/pstore_ram.h b/include/linux/pstore_ram.h index ecdd229dd4..de6eaa93f9 100644 --- a/include/linux/pstore_ram.h +++ b/include/linux/pstore_ram.h @@ -35,6 +35,7 @@ struct persistent_ram_ecc_info { struct persistent_ram_zone { phys_addr_t paddr; size_t size; + char *label; struct persistent_ram_buffer *buffer; size_t buffer_size; struct resource *res; @@ -53,7 +54,7 @@ struct persistent_ram_zone { 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); + unsigned int memtype, char *label); void persistent_ram_free(struct persistent_ram_zone *prz); void persistent_ram_zap(struct persistent_ram_zone *prz); -- cgit v1.2.3 From 114d41b69c1e0715fe09b2234559f545eb7721bf Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Fri, 15 Mar 2019 10:14:46 +0100 Subject: pstore: Extract common arguments into structure The read/mkfile pair pass the same arguments and should be cleared between calls. Move to a structure and wipe it after every loop. Signed-off-by: Kees Cook [p.zabel@pengutronix.de: ported to Barebox from Linux commit 9abdcccc3d5f] Signed-off-by: Philipp Zabel Signed-off-by: Sascha Hauer --- fs/pstore/platform.c | 30 +++++++++++++++++------------- include/linux/pstore.h | 15 ++++++++++++++- 2 files changed, 31 insertions(+), 14 deletions(-) (limited to 'include/linux') diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index 963ecafef8..6eebad63de 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -96,13 +96,8 @@ EXPORT_SYMBOL_GPL(pstore_register); void pstore_get_records(int quiet) { struct pstore_info *psi = psinfo; - char *buf = NULL; - ssize_t size; - u64 id; - int count; - enum pstore_type_id type; + struct pstore_record record = { .psi = psi, }; int failed = 0, rc; - bool compressed; int unzipped_len = -1; if (!psi) @@ -112,22 +107,31 @@ void pstore_get_records(int quiet) if (psi->open && psi->open(psi)) goto out; - while ((size = psi->read(&id, &type, &count, &buf, &compressed, - psi)) > 0) { - if (compressed && (type == PSTORE_TYPE_DMESG)) { + while ((record.size = psi->read(&record.id, &record.type, + &record.count, + &record.buf, &record.compressed, + record.psi)) > 0) { + if (record.compressed && + record.type == PSTORE_TYPE_DMESG) { pr_err("barebox does not have ramoops compression support\n"); continue; } - rc = pstore_mkfile(type, psi->name, id, count, buf, - compressed, (size_t)size, psi); + rc = pstore_mkfile(record.type, psi->name, record.id, + record.count, record.buf, + record.compressed, + record.size, + record.psi); if (unzipped_len < 0) { /* Free buffer other than big oops */ - kfree(buf); - buf = NULL; + kfree(record.buf); + record.buf = NULL; } else unzipped_len = -1; if (rc && (rc != -EEXIST || !quiet)) failed++; + + memset(&record, 0, sizeof(record)); + record.psi = psi; } if (psi->close) psi->close(psi); diff --git a/include/linux/pstore.h b/include/linux/pstore.h index a925e14397..23f35570aa 100644 --- a/include/linux/pstore.h +++ b/include/linux/pstore.h @@ -25,6 +25,8 @@ #include #include +struct module; + /* types */ enum pstore_type_id { PSTORE_TYPE_DMESG = 0, @@ -43,7 +45,18 @@ enum kmsg_dump_reason { KMSG_DUMP_UNDEF, }; -struct module; +struct pstore_info; + +struct pstore_record { + struct pstore_info *psi; + enum pstore_type_id type; + u64 id; + char *buf; + int count; + bool compressed; + ssize_t size; + ssize_t ecc_notice_size; +}; struct pstore_info { struct module *owner; -- cgit v1.2.3 From cdce7a569c947878708695bcdc383dbcc192c099 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Fri, 15 Mar 2019 10:14:49 +0100 Subject: pstore: Replace arguments for read() API The argument list for the pstore_read() interface is unwieldy. This changes passes the new struct pstore_record instead. The erst backend was already doing something similar internally. Signed-off-by: Kees Cook Signed-off-by: Sascha Hauer --- fs/pstore/platform.c | 5 +---- fs/pstore/ram.c | 29 +++++++++++++++++------------ include/linux/pstore.h | 4 +--- 3 files changed, 19 insertions(+), 19 deletions(-) (limited to 'include/linux') diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index bad735e574..54fe60bf88 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -181,10 +181,7 @@ void pstore_get_records(int quiet) if (psi->open && psi->open(psi)) goto out; - while ((record.size = psi->read(&record.id, &record.type, - &record.count, - &record.buf, &record.compressed, - record.psi)) > 0) { + while ((record.size = psi->read(&record)) > 0) { if (record.compressed && record.type == PSTORE_TYPE_DMESG) { pr_err("barebox does not have ramoops compression support\n"); diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c index 714755bd66..fcf6b3087c 100644 --- a/fs/pstore/ram.c +++ b/fs/pstore/ram.c @@ -128,27 +128,32 @@ static bool prz_ok(struct persistent_ram_zone *prz) persistent_ram_ecc_string(prz, NULL, 0)); } -static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type, - int *count, char **buf, bool *compressed, - struct pstore_info *psi) +static ssize_t ramoops_pstore_read(struct pstore_record *record) { ssize_t size; ssize_t ecc_notice_size; - struct ramoops_context *cxt = psi->data; + struct ramoops_context *cxt = record->psi->data; struct persistent_ram_zone *prz; + record->compressed = false; + prz = ramoops_get_next_prz(cxt->przs, &cxt->dump_read_cnt, - cxt->max_dump_cnt, id, type, + cxt->max_dump_cnt, &record->id, + &record->type, PSTORE_TYPE_DMESG, 0); if (!prz_ok(prz)) prz = ramoops_get_next_prz(&cxt->cprz, &cxt->console_read_cnt, - 1, id, type, PSTORE_TYPE_CONSOLE, 0); + 1, &record->id, &record->type, + PSTORE_TYPE_CONSOLE, 0); + if (!prz_ok(prz)) prz = ramoops_get_next_prz(&cxt->fprz, &cxt->ftrace_read_cnt, - 1, id, type, PSTORE_TYPE_FTRACE, 0); + 1, &record->id, &record->type, + PSTORE_TYPE_FTRACE, 0); if (!prz_ok(prz)) prz = ramoops_get_next_prz(&cxt->mprz, &cxt->pmsg_read_cnt, - 1, id, type, PSTORE_TYPE_PMSG, 0); + 1, &record->id, &record->type, + PSTORE_TYPE_PMSG, 0); if (!prz_ok(prz)) return 0; @@ -160,12 +165,12 @@ static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type, /* ECC correction notice */ ecc_notice_size = persistent_ram_ecc_string(prz, NULL, 0); - *buf = kmalloc(size + ecc_notice_size + 1, GFP_KERNEL); - if (*buf == NULL) + record->buf = kmalloc(size + ecc_notice_size + 1, GFP_KERNEL); + if (record->buf == NULL) return -ENOMEM; - memcpy(*buf, (char *)persistent_ram_old(prz), size); - persistent_ram_ecc_string(prz, *buf + size, ecc_notice_size + 1); + memcpy(record->buf, (char *)persistent_ram_old(prz), size); + persistent_ram_ecc_string(prz, record->buf + size, ecc_notice_size + 1); return size + ecc_notice_size; } diff --git a/include/linux/pstore.h b/include/linux/pstore.h index 23f35570aa..b136c354b9 100644 --- a/include/linux/pstore.h +++ b/include/linux/pstore.h @@ -66,9 +66,7 @@ struct pstore_info { int flags; int (*open)(struct pstore_info *psi); int (*close)(struct pstore_info *psi); - ssize_t (*read)(u64 *id, enum pstore_type_id *type, - int *count, char **buf, bool *compressed, - struct pstore_info *psi); + ssize_t (*read)(struct pstore_record *record); int (*write)(enum pstore_type_id type, enum kmsg_dump_reason reason, u64 *id, unsigned int part, int count, bool compressed, -- cgit v1.2.3 From da9b86ec0fbec0eb60646e7a3c700076a423717d Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Fri, 15 Mar 2019 10:14:50 +0100 Subject: pstore: Replace arguments for write() API Similar to the pstore_info read() callback, there were too many arguments. This switches to the new struct pstore_record pointer instead. This adds "reason" and "part" to the record structure as well. Signed-off-by: Kees Cook Signed-off-by: Sascha Hauer --- fs/pstore/platform.c | 12 +++++------- include/linux/pstore.h | 12 ++++++------ 2 files changed, 11 insertions(+), 13 deletions(-) (limited to 'include/linux') diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index 54fe60bf88..755363c309 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -115,14 +115,12 @@ static void pstore_register_console(void) static void pstore_register_console(void) {} #endif -static int pstore_write_compat(enum pstore_type_id type, - enum kmsg_dump_reason reason, - u64 *id, unsigned int part, int count, - bool compressed, size_t size, - struct pstore_info *psi) +static int pstore_write_compat(struct pstore_record *record) { - return psi->write_buf(type, reason, id, part, psinfo->buf, compressed, - size, psi); + return record->psi->write_buf(record->type, record->reason, + &record->id, record->part, + psinfo->buf, record->compressed, + record->size, record->psi); } /* diff --git a/include/linux/pstore.h b/include/linux/pstore.h index b136c354b9..15e1e3d6fa 100644 --- a/include/linux/pstore.h +++ b/include/linux/pstore.h @@ -52,10 +52,13 @@ struct pstore_record { enum pstore_type_id type; u64 id; char *buf; - int count; - bool compressed; ssize_t size; ssize_t ecc_notice_size; + + int count; + enum kmsg_dump_reason reason; + unsigned int part; + bool compressed; }; struct pstore_info { @@ -67,10 +70,7 @@ struct pstore_info { int (*open)(struct pstore_info *psi); int (*close)(struct pstore_info *psi); ssize_t (*read)(struct pstore_record *record); - int (*write)(enum pstore_type_id type, - enum kmsg_dump_reason reason, u64 *id, - unsigned int part, int count, bool compressed, - size_t size, struct pstore_info *psi); + int (*write)(struct pstore_record *record); int (*write_buf)(enum pstore_type_id type, enum kmsg_dump_reason reason, u64 *id, unsigned int part, const char *buf, bool compressed, -- cgit v1.2.3