[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250217101706.2104498-6-eugen.hristev@linaro.org>
Date: Mon, 17 Feb 2025 12:17:01 +0200
From: Eugen Hristev <eugen.hristev@...aro.org>
To: linux-arm-msm@...r.kernel.org,
linux-hardening@...r.kernel.org,
kees@...nel.org
Cc: linux-kernel@...r.kernel.org,
johannes@...solutions.net,
gregkh@...uxfoundation.org,
rafael@...nel.org,
dakr@...nel.org,
andersson@...nel.org,
konradybcio@...nel.org,
tony.luck@...el.com,
gpiccoli@...lia.com,
pmladek@...e.com,
rostedt@...dmis.org,
john.ogness@...utronix.de,
senozhatsky@...omium.org,
quic_mojha@...cinc.com,
linux-arm-kernel@...ts.infradead.org,
kernel@...cinc.com,
Eugen Hristev <eugen.hristev@...aro.org>
Subject: [RFC][PATCH 05/10] pstore: implement core area registration
Implement core area registration mechanism.
Implement directly mapped zone corespoding to core areas.
Signed-off-by: Eugen Hristev <eugen.hristev@...aro.org>
---
fs/pstore/platform.c | 67 ++++++++++++++++++++++++++++++++++++
fs/pstore/zone.c | 77 ++++++++++++++++++++++++++++++++++++++++++
include/linux/pstore.h | 16 +++++++++
3 files changed, 160 insertions(+)
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
index e20e60b88727..32448d9dd316 100644
--- a/fs/pstore/platform.c
+++ b/fs/pstore/platform.c
@@ -68,6 +68,7 @@ static DECLARE_WORK(pstore_work, pstore_dowork);
* the filesystem mount/unmount routines.
*/
static DEFINE_MUTEX(psinfo_lock);
+static DEFINE_MUTEX(ps_dmr_lock);
struct pstore_info *psinfo;
static char *backend;
@@ -99,6 +100,12 @@ MODULE_PARM_DESC(kmsg_bytes, "amount of kernel log to snapshot (in bytes)");
static void *compress_workspace;
+static LIST_HEAD(rec_list);
+struct rec_list_t {
+ struct pstore_record rec;
+ struct list_head list;
+};
+
/*
* Compression is only used for dmesg output, which consists of low-entropy
* ASCII text, and so we can assume worst-case 60%.
@@ -271,6 +278,66 @@ void pstore_record_init(struct pstore_record *record,
record->time = ns_to_timespec64(ktime_get_real_fast_ns());
}
+int pstore_register_core_area(const char *handle, void *area, size_t size)
+{
+ struct rec_list_t *rec_element = kzalloc(sizeof (*rec_element), GFP_KERNEL);
+ struct pstore_record *record = &rec_element->rec;
+ int ret;
+
+ if (!psinfo || !psinfo->register_dmr) {
+ pr_err("No pstore available ! Bailing out.\n");
+ return -EAGAIN;
+ }
+
+ pstore_record_init(record, psinfo);
+ record->type = PSTORE_TYPE_DMAPPED;
+ record->buf = area;
+ record->size = size;
+
+ if (handle) {
+ record->priv = kmalloc(8, GFP_KERNEL);
+ strncpy(record->priv, handle, 8);
+ }
+
+ mutex_lock(&ps_dmr_lock);
+
+ ret = psinfo->register_dmr(record);
+ if (!ret)
+ list_add(&rec_element->list, &rec_list);
+
+ mutex_unlock(&ps_dmr_lock);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(pstore_register_core_area);
+
+int pstore_unregister_core_area(const char *handle, void *area, size_t size)
+{
+ struct rec_list_t *rec_element, *tmp;
+ int ret;
+
+ if (!psinfo || !psinfo->unregister_dmr)
+ return -EAGAIN;
+
+ mutex_lock(&ps_dmr_lock);
+ list_for_each_entry_safe(rec_element, tmp, &rec_list, list) {
+ struct pstore_record *record;
+
+ record = &rec_element->rec;
+
+ if (record->buf == area) {
+ ret = psinfo->unregister_dmr(record);
+ list_del(&rec_element->list);
+ mutex_unlock(&ps_dmr_lock);
+ return 0;
+ }
+ }
+
+ mutex_unlock(&ps_dmr_lock);
+ return 0;
+
+}
+EXPORT_SYMBOL_GPL(pstore_unregister_core_area);
+
/*
* callback from kmsg_dump. Save as much as we can (up to kmsg_bytes) from the
* end of the buffer.
diff --git a/fs/pstore/zone.c b/fs/pstore/zone.c
index affa4370208c..f9e2dc4252ea 100644
--- a/fs/pstore/zone.c
+++ b/fs/pstore/zone.c
@@ -35,6 +35,7 @@ struct psz_buffer {
uint32_t sig;
atomic_t datalen;
atomic_t start;
+ void *data_ptr;
uint8_t data[];
};
@@ -822,6 +823,38 @@ static int notrace psz_kmsg_write(struct psz_context *cxt,
return 0;
}
+static int notrace psz_register_dmr_record(struct pstore_zone *zone,
+ struct pstore_record *record)
+{
+ struct pstore_zone_info *info = pstore_zone_cxt.pstore_zone_info;
+ int ret;
+
+ if (!info->register_dmr)
+ return -ENOTSUPP;
+
+ zone->buffer->data_ptr = record->buf;
+ atomic_set(&zone->buffer->datalen, record->size);
+
+ ret = info->register_dmr(record->priv, record->id, record->buf,
+ record->size);
+ if (!ret)
+ atomic_set(&zone->dirty, true);
+ return ret;
+}
+
+static int psz_unregister_dmr_zone(struct pstore_zone *zone)
+{
+ struct pstore_zone_info *info = pstore_zone_cxt.pstore_zone_info;
+ if (!info->unregister_dmr)
+ return -ENOTSUPP;
+
+ info->unregister_dmr(zone->buffer->data_ptr,
+ atomic_read(&zone->buffer->datalen));
+
+ atomic_set(&zone->dirty, false);
+ return 0;
+}
+
static int notrace psz_record_write(struct pstore_zone *zone,
struct pstore_record *record)
{
@@ -906,6 +939,48 @@ static int notrace psz_pstore_write(struct pstore_record *record)
}
}
+static int pstore_unregister_dmr(struct pstore_record *record)
+{
+ struct psz_context *cxt = record->psi->data;
+ int c = 0;
+
+ if (!cxt->dmszs)
+ return -ENODEV;
+
+ while (c < cxt->dmapped_max_cnt) {
+ if (!atomic_read(&cxt->dmszs[c]->dirty))
+ continue;
+
+ if (cxt->dmszs[c]->buffer->data_ptr == record->buf)
+ return psz_unregister_dmr_zone(cxt->dmszs[c]);
+ c++;
+ }
+
+ return -ENOENT;
+}
+
+static int pstore_register_dmr(struct pstore_record *record)
+{
+ struct psz_context *cxt = record->psi->data;
+ int c = 0;
+
+ if (!cxt->dmszs)
+ return -ENODEV;
+
+ while (c < cxt->dmapped_max_cnt) {
+ if (!atomic_read(&cxt->dmszs[c]->dirty))
+ break;
+ c++;
+ }
+
+ if (c == cxt->dmapped_max_cnt)
+ return -ENOSPC;
+
+ record->id = c;
+
+ return psz_register_dmr_record(cxt->dmszs[c], record);
+}
+
static struct pstore_zone *psz_read_next_zone(struct psz_context *cxt)
{
struct pstore_zone *zone = NULL;
@@ -1110,6 +1185,8 @@ static struct psz_context pstore_zone_cxt = {
.read = psz_pstore_read,
.write = psz_pstore_write,
.erase = psz_pstore_erase,
+ .register_dmr = pstore_register_dmr,
+ .unregister_dmr = pstore_unregister_dmr,
},
};
diff --git a/include/linux/pstore.h b/include/linux/pstore.h
index 8360d94c96b6..85f3f964b268 100644
--- a/include/linux/pstore.h
+++ b/include/linux/pstore.h
@@ -290,4 +290,20 @@ pstore_ftrace_write_timestamp(struct pstore_ftrace_record *rec, u64 val)
}
#endif
+#ifdef CONFIG_PSTORE
+int pstore_register_core_area(const char *handle, void *area, size_t size);
+int pstore_unregister_core_area(const char *handle, void *area, size_t size);
+#else
+static inline int pstore_register_core_area(const char *handle, void *area,
+ size_t size)
+{
+ return 0;
+}
+static inline int pstore_unregister_core_area(const char *handle, void *area,
+ size_t size)
+{
+ return 0;
+}
+#endif
+
#endif /*_LINUX_PSTORE_H*/
--
2.43.0
Powered by blists - more mailing lists