ram.c 24.8 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0-only
2 3 4 5
/*
 * RAM Oops/Panic logger
 *
 * Copyright (C) 2010 Marco Stornelli <marco.stornelli@gmail.com>
K
Kees Cook 已提交
6
 * Copyright (C) 2011 Kees Cook <keescook@chromium.org>
7 8
 */

9 10
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

11
#include <linux/kernel.h>
12
#include <linux/err.h>
13
#include <linux/module.h>
14
#include <linux/version.h>
K
Kees Cook 已提交
15
#include <linux/pstore.h>
16 17
#include <linux/io.h>
#include <linux/ioport.h>
18
#include <linux/platform_device.h>
19
#include <linux/slab.h>
20
#include <linux/compiler.h>
21
#include <linux/pstore_ram.h>
22 23
#include <linux/of.h>
#include <linux/of_address.h>
24 25

#define RAMOOPS_KERNMSG_HDR "===="
26
#define MIN_MEM_SIZE 4096UL
27

28 29 30 31
static ulong record_size = MIN_MEM_SIZE;
module_param(record_size, ulong, 0400);
MODULE_PARM_DESC(record_size,
		"size of each dump done on oops/panic");
32

33 34 35 36
static ulong ramoops_console_size = MIN_MEM_SIZE;
module_param_named(console_size, ramoops_console_size, ulong, 0400);
MODULE_PARM_DESC(console_size, "size of kernel console log");

37 38 39 40
static ulong ramoops_ftrace_size = MIN_MEM_SIZE;
module_param_named(ftrace_size, ramoops_ftrace_size, ulong, 0400);
MODULE_PARM_DESC(ftrace_size, "size of ftrace log");

41 42 43 44
static ulong ramoops_pmsg_size = MIN_MEM_SIZE;
module_param_named(pmsg_size, ramoops_pmsg_size, ulong, 0400);
MODULE_PARM_DESC(pmsg_size, "size of user space message log");

45
static unsigned long long mem_address;
46
module_param_hw(mem_address, ullong, other, 0400);
47 48 49 50 51 52 53 54
MODULE_PARM_DESC(mem_address,
		"start of reserved RAM used to store oops/panic logs");

static ulong mem_size;
module_param(mem_size, ulong, 0400);
MODULE_PARM_DESC(mem_size,
		"size of reserved RAM used to store oops/panic logs");

55 56 57 58 59
static unsigned int mem_type;
module_param(mem_type, uint, 0600);
MODULE_PARM_DESC(mem_type,
		"set to 1 to try to use unbuffered memory (default 0)");

60 61 62 63 64
static int dump_oops = 1;
module_param(dump_oops, int, 0600);
MODULE_PARM_DESC(dump_oops,
		"set to 1 to dump oopses, 0 to only dump panics (default 1)");

A
Anton Vorontsov 已提交
65 66 67
static int ramoops_ecc;
module_param_named(ecc, ramoops_ecc, int, 0600);
MODULE_PARM_DESC(ramoops_ecc,
68 69 70
		"if non-zero, the option enables ECC support and specifies "
		"ECC buffer size in bytes (1 is a special value, means 16 "
		"bytes ECC)");
A
Anton Vorontsov 已提交
71

K
Kees Cook 已提交
72
struct ramoops_context {
73 74 75 76
	struct persistent_ram_zone **dprzs;	/* Oops dump zones */
	struct persistent_ram_zone *cprz;	/* Console zone */
	struct persistent_ram_zone **fprzs;	/* Ftrace zones */
	struct persistent_ram_zone *mprz;	/* PMSG zone */
77 78
	phys_addr_t phys_addr;
	unsigned long size;
79
	unsigned int memtype;
K
Kees Cook 已提交
80
	size_t record_size;
81
	size_t console_size;
82
	size_t ftrace_size;
83
	size_t pmsg_size;
84
	int dump_oops;
85
	u32 flags;
86
	struct persistent_ram_ecc_info ecc_info;
87 88
	unsigned int max_dump_cnt;
	unsigned int dump_write_cnt;
89
	/* _read_cnt need clear on ramoops_pstore_open */
90
	unsigned int dump_read_cnt;
91
	unsigned int console_read_cnt;
92
	unsigned int max_ftrace_cnt;
93
	unsigned int ftrace_read_cnt;
94
	unsigned int pmsg_read_cnt;
K
Kees Cook 已提交
95 96
	struct pstore_info pstore;
};
97

98 99
static struct platform_device *dummy;

K
Kees Cook 已提交
100 101 102 103
static int ramoops_pstore_open(struct pstore_info *psi)
{
	struct ramoops_context *cxt = psi->data;

104
	cxt->dump_read_cnt = 0;
105
	cxt->console_read_cnt = 0;
106
	cxt->ftrace_read_cnt = 0;
107
	cxt->pmsg_read_cnt = 0;
K
Kees Cook 已提交
108 109 110
	return 0;
}

111
static struct persistent_ram_zone *
112 113
ramoops_get_next_prz(struct persistent_ram_zone *przs[], int id,
		     struct pstore_record *record)
114 115 116
{
	struct persistent_ram_zone *prz;

117
	/* Give up if we never existed or have hit the end. */
118
	if (!przs)
119 120
		return NULL;

121
	prz = przs[id];
122 123
	if (!prz)
		return NULL;
124

125
	/* Update old/shadowed buffer. */
126
	if (prz->type == PSTORE_TYPE_DMESG)
127
		persistent_ram_save_old(prz);
128 129 130

	if (!persistent_ram_old_size(prz))
		return NULL;
131

132 133
	record->type = prz->type;
	record->id = id;
134 135 136 137

	return prz;
}

138
static int ramoops_read_kmsg_hdr(char *buffer, struct timespec64 *time,
139 140 141
				  bool *compressed)
{
	char data_type;
142
	int header_length = 0;
143

144 145
	if (sscanf(buffer, RAMOOPS_KERNMSG_HDR "%lld.%lu-%c\n%n",
		   (time64_t *)&time->tv_sec, &time->tv_nsec, &data_type,
146
		   &header_length) == 3) {
147 148 149 150
		if (data_type == 'C')
			*compressed = true;
		else
			*compressed = false;
151 152
	} else if (sscanf(buffer, RAMOOPS_KERNMSG_HDR "%lld.%lu\n%n",
			  (time64_t *)&time->tv_sec, &time->tv_nsec,
153 154
			  &header_length) == 2) {
		*compressed = false;
155 156 157 158 159
	} else {
		time->tv_sec = 0;
		time->tv_nsec = 0;
		*compressed = false;
	}
160
	return header_length;
161 162
}

163 164 165 166 167 168
static bool prz_ok(struct persistent_ram_zone *prz)
{
	return !!prz && !!(persistent_ram_old_size(prz) +
			   persistent_ram_ecc_string(prz, NULL, 0));
}

169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
static ssize_t ftrace_log_combine(struct persistent_ram_zone *dest,
				  struct persistent_ram_zone *src)
{
	size_t dest_size, src_size, total, dest_off, src_off;
	size_t dest_idx = 0, src_idx = 0, merged_idx = 0;
	void *merged_buf;
	struct pstore_ftrace_record *drec, *srec, *mrec;
	size_t record_size = sizeof(struct pstore_ftrace_record);

	dest_off = dest->old_log_size % record_size;
	dest_size = dest->old_log_size - dest_off;

	src_off = src->old_log_size % record_size;
	src_size = src->old_log_size - src_off;

	total = dest_size + src_size;
	merged_buf = kmalloc(total, GFP_KERNEL);
	if (!merged_buf)
		return -ENOMEM;

	drec = (struct pstore_ftrace_record *)(dest->old_log + dest_off);
	srec = (struct pstore_ftrace_record *)(src->old_log + src_off);
	mrec = (struct pstore_ftrace_record *)(merged_buf);

	while (dest_size > 0 && src_size > 0) {
		if (pstore_ftrace_read_timestamp(&drec[dest_idx]) <
		    pstore_ftrace_read_timestamp(&srec[src_idx])) {
			mrec[merged_idx++] = drec[dest_idx++];
			dest_size -= record_size;
		} else {
			mrec[merged_idx++] = srec[src_idx++];
			src_size -= record_size;
		}
	}

	while (dest_size > 0) {
		mrec[merged_idx++] = drec[dest_idx++];
		dest_size -= record_size;
	}

	while (src_size > 0) {
		mrec[merged_idx++] = srec[src_idx++];
		src_size -= record_size;
	}

	kfree(dest->old_log);
	dest->old_log = merged_buf;
	dest->old_log_size = total;

	return 0;
}

221
static ssize_t ramoops_pstore_read(struct pstore_record *record)
222
{
223
	ssize_t size = 0;
224
	struct ramoops_context *cxt = record->psi->data;
225 226
	struct persistent_ram_zone *prz = NULL;
	int header_length = 0;
227
	bool free_prz = false;
228

229 230
	/*
	 * Ramoops headers provide time stamps for PSTORE_TYPE_DMESG, but
231 232 233
	 * PSTORE_TYPE_CONSOLE and PSTORE_TYPE_FTRACE don't currently have
	 * valid time stamps, so it is initialized to zero.
	 */
234 235 236
	record->time.tv_sec = 0;
	record->time.tv_nsec = 0;
	record->compressed = false;
237 238 239

	/* Find the next valid persistent_ram_zone for DMESG */
	while (cxt->dump_read_cnt < cxt->max_dump_cnt && !prz) {
240 241
		prz = ramoops_get_next_prz(cxt->dprzs, cxt->dump_read_cnt++,
					   record);
242 243 244
		if (!prz_ok(prz))
			continue;
		header_length = ramoops_read_kmsg_hdr(persistent_ram_old(prz),
245 246
						      &record->time,
						      &record->compressed);
247 248 249 250 251 252 253
		/* Clear and skip this DMESG record if it has no valid header */
		if (!header_length) {
			persistent_ram_free_old(prz);
			persistent_ram_zap(prz);
			prz = NULL;
		}
	}
K
Kees Cook 已提交
254

255 256
	if (!prz_ok(prz) && !cxt->console_read_cnt++)
		prz = ramoops_get_next_prz(&cxt->cprz, 0 /* single */, record);
257

258 259
	if (!prz_ok(prz) && !cxt->pmsg_read_cnt++)
		prz = ramoops_get_next_prz(&cxt->mprz, 0 /* single */, record);
260 261

	/* ftrace is last since it may want to dynamically allocate memory. */
262
	if (!prz_ok(prz)) {
263 264 265 266
		if (!(cxt->flags & RAMOOPS_FLAG_FTRACE_PER_CPU) &&
		    !cxt->ftrace_read_cnt++) {
			prz = ramoops_get_next_prz(cxt->fprzs, 0 /* single */,
						   record);
267 268 269 270 271 272 273 274 275 276 277
		} else {
			/*
			 * Build a new dummy record which combines all the
			 * per-cpu records including metadata and ecc info.
			 */
			struct persistent_ram_zone *tmp_prz, *prz_next;

			tmp_prz = kzalloc(sizeof(struct persistent_ram_zone),
					  GFP_KERNEL);
			if (!tmp_prz)
				return -ENOMEM;
278
			prz = tmp_prz;
279 280 281 282
			free_prz = true;

			while (cxt->ftrace_read_cnt < cxt->max_ftrace_cnt) {
				prz_next = ramoops_get_next_prz(cxt->fprzs,
283
						cxt->ftrace_read_cnt++, record);
284 285 286 287 288 289 290 291 292 293 294 295

				if (!prz_ok(prz_next))
					continue;

				tmp_prz->ecc_info = prz_next->ecc_info;
				tmp_prz->corrected_bytes +=
						prz_next->corrected_bytes;
				tmp_prz->bad_blocks += prz_next->bad_blocks;
				size = ftrace_log_combine(tmp_prz, prz_next);
				if (size)
					goto out;
			}
296
			record->id = 0;
297 298 299
		}
	}

300 301 302 303
	if (!prz_ok(prz)) {
		size = 0;
		goto out;
	}
304

305
	size = persistent_ram_old_size(prz) - header_length;
306 307

	/* ECC correction notice */
308
	record->ecc_notice_size = persistent_ram_ecc_string(prz, NULL, 0);
309

310 311
	record->buf = kmalloc(size + record->ecc_notice_size + 1, GFP_KERNEL);
	if (record->buf == NULL) {
312 313 314
		size = -ENOMEM;
		goto out;
	}
K
Kees Cook 已提交
315

316 317
	memcpy(record->buf, (char *)persistent_ram_old(prz) + header_length,
	       size);
318

319 320
	persistent_ram_ecc_string(prz, record->buf + size,
				  record->ecc_notice_size + 1);
321

322 323 324 325 326 327
out:
	if (free_prz) {
		kfree(prz->old_log);
		kfree(prz);
	}

328
	return size;
K
Kees Cook 已提交
329 330
}

331
static size_t ramoops_write_kmsg_hdr(struct persistent_ram_zone *prz,
332
				     struct pstore_record *record)
333
{
334
	char hdr[36]; /* "===="(4), %lld(20), "."(1), %06lu(6), "-%c\n"(3) */
335 336
	size_t len;

337 338
	len = scnprintf(hdr, sizeof(hdr),
		RAMOOPS_KERNMSG_HDR "%lld.%06lu-%c\n",
339
		(time64_t)record->time.tv_sec,
340 341
		record->time.tv_nsec / 1000,
		record->compressed ? 'C' : 'D');
342 343 344 345 346
	persistent_ram_write(prz, hdr, len);

	return len;
}

K
Kees Cook 已提交
347
static int notrace ramoops_pstore_write(struct pstore_record *record)
K
Kees Cook 已提交
348
{
349
	struct ramoops_context *cxt = record->psi->data;
350
	struct persistent_ram_zone *prz;
351
	size_t size, hlen;
K
Kees Cook 已提交
352

353
	if (record->type == PSTORE_TYPE_CONSOLE) {
354 355
		if (!cxt->cprz)
			return -ENOMEM;
356
		persistent_ram_write(cxt->cprz, record->buf, record->size);
357
		return 0;
358
	} else if (record->type == PSTORE_TYPE_FTRACE) {
359 360 361
		int zonenum;

		if (!cxt->fprzs)
362
			return -ENOMEM;
363 364 365 366 367 368 369 370
		/*
		 * Choose zone by if we're using per-cpu buffers.
		 */
		if (cxt->flags & RAMOOPS_FLAG_FTRACE_PER_CPU)
			zonenum = smp_processor_id();
		else
			zonenum = 0;

371 372
		persistent_ram_write(cxt->fprzs[zonenum], record->buf,
				     record->size);
373
		return 0;
374
	} else if (record->type == PSTORE_TYPE_PMSG) {
375 376
		pr_warn_ratelimited("PMSG shouldn't call %s\n", __func__);
		return -EINVAL;
377 378
	}

379
	if (record->type != PSTORE_TYPE_DMESG)
K
Kees Cook 已提交
380
		return -EINVAL;
381

382 383
	/*
	 * Out of the various dmesg dump types, ramoops is currently designed
K
Kees Cook 已提交
384 385
	 * to only store crash logs, rather than storing general kernel logs.
	 */
386 387
	if (record->reason != KMSG_DUMP_OOPS &&
	    record->reason != KMSG_DUMP_PANIC)
K
Kees Cook 已提交
388
		return -EINVAL;
389

K
Kees Cook 已提交
390
	/* Skip Oopes when configured to do so. */
391
	if (record->reason == KMSG_DUMP_OOPS && !cxt->dump_oops)
K
Kees Cook 已提交
392 393
		return -EINVAL;

394 395
	/*
	 * Explicitly only take the first part of any new crash.
K
Kees Cook 已提交
396 397 398 399
	 * If our buffer is larger than kmsg_bytes, this can never happen,
	 * and if our buffer is smaller than kmsg_bytes, we don't want the
	 * report split across multiple records.
	 */
400
	if (record->part != 1)
K
Kees Cook 已提交
401
		return -ENOSPC;
402

403
	if (!cxt->dprzs)
404 405
		return -ENOSPC;

406
	prz = cxt->dprzs[cxt->dump_write_cnt];
407

408
	/* Build header and append record contents. */
409
	hlen = ramoops_write_kmsg_hdr(prz, record);
410 411 412
	if (!hlen)
		return -ENOMEM;

413
	size = record->size;
414 415
	if (size + hlen > prz->buffer_size)
		size = prz->buffer_size - hlen;
416
	persistent_ram_write(prz, record->buf, size);
417

418
	cxt->dump_write_cnt = (cxt->dump_write_cnt + 1) % cxt->max_dump_cnt;
K
Kees Cook 已提交
419 420 421 422

	return 0;
}

K
Kees Cook 已提交
423 424
static int notrace ramoops_pstore_write_user(struct pstore_record *record,
					     const char __user *buf)
M
Mark Salyzyn 已提交
425
{
426 427
	if (record->type == PSTORE_TYPE_PMSG) {
		struct ramoops_context *cxt = record->psi->data;
M
Mark Salyzyn 已提交
428 429 430

		if (!cxt->mprz)
			return -ENOMEM;
431
		return persistent_ram_write_user(cxt->mprz, buf, record->size);
M
Mark Salyzyn 已提交
432 433 434 435 436
	}

	return -EINVAL;
}

437
static int ramoops_pstore_erase(struct pstore_record *record)
K
Kees Cook 已提交
438
{
439
	struct ramoops_context *cxt = record->psi->data;
440
	struct persistent_ram_zone *prz;
K
Kees Cook 已提交
441

442
	switch (record->type) {
443
	case PSTORE_TYPE_DMESG:
444
		if (record->id >= cxt->max_dump_cnt)
445
			return -EINVAL;
446
		prz = cxt->dprzs[record->id];
447 448 449 450
		break;
	case PSTORE_TYPE_CONSOLE:
		prz = cxt->cprz;
		break;
451
	case PSTORE_TYPE_FTRACE:
452
		if (record->id >= cxt->max_ftrace_cnt)
453
			return -EINVAL;
454
		prz = cxt->fprzs[record->id];
455
		break;
456 457 458
	case PSTORE_TYPE_PMSG:
		prz = cxt->mprz;
		break;
459
	default:
K
Kees Cook 已提交
460
		return -EINVAL;
461
	}
K
Kees Cook 已提交
462

463 464
	persistent_ram_free_old(prz);
	persistent_ram_zap(prz);
K
Kees Cook 已提交
465 466

	return 0;
467 468
}

K
Kees Cook 已提交
469 470 471 472 473 474
static struct ramoops_context oops_cxt = {
	.pstore = {
		.owner	= THIS_MODULE,
		.name	= "ramoops",
		.open	= ramoops_pstore_open,
		.read	= ramoops_pstore_read,
K
Kees Cook 已提交
475 476
		.write	= ramoops_pstore_write,
		.write_user	= ramoops_pstore_write_user,
K
Kees Cook 已提交
477 478 479 480
		.erase	= ramoops_pstore_erase,
	},
};

481 482 483 484
static void ramoops_free_przs(struct ramoops_context *cxt)
{
	int i;

485
	/* Free dump PRZs */
486
	if (cxt->dprzs) {
487
		for (i = 0; i < cxt->max_dump_cnt; i++)
488
			persistent_ram_free(cxt->dprzs[i]);
489

490
		kfree(cxt->dprzs);
491 492
		cxt->max_dump_cnt = 0;
	}
493

494 495 496 497 498 499 500
	/* Free ftrace PRZs */
	if (cxt->fprzs) {
		for (i = 0; i < cxt->max_ftrace_cnt; i++)
			persistent_ram_free(cxt->fprzs[i]);
		kfree(cxt->fprzs);
		cxt->max_ftrace_cnt = 0;
	}
501 502
}

503 504
static int ramoops_init_przs(const char *name,
			     struct device *dev, struct ramoops_context *cxt,
505 506 507 508
			     struct persistent_ram_zone ***przs,
			     phys_addr_t *paddr, size_t mem_sz,
			     ssize_t record_size,
			     unsigned int *cnt, u32 sig, u32 flags)
509 510 511
{
	int err = -ENOMEM;
	int i;
512 513
	size_t zone_sz;
	struct persistent_ram_zone **prz_ar;
514

515 516 517
	/* Allocate nothing for 0 mem_sz or 0 record_size. */
	if (mem_sz == 0 || record_size == 0) {
		*cnt = 0;
518
		return 0;
519 520
	}

521 522 523 524 525 526 527 528 529
	/*
	 * If we have a negative record size, calculate it based on
	 * mem_sz / *cnt. If we have a positive record size, calculate
	 * cnt from mem_sz / record_size.
	 */
	if (record_size < 0) {
		if (*cnt == 0)
			return 0;
		record_size = mem_sz / *cnt;
530 531 532
		if (record_size == 0) {
			dev_err(dev, "%s record size == 0 (%zu / %u)\n",
				name, mem_sz, *cnt);
533
			goto fail;
534
		}
535 536
	} else {
		*cnt = mem_sz / record_size;
537 538 539
		if (*cnt == 0) {
			dev_err(dev, "%s record count == 0 (%zu / %zu)\n",
				name, mem_sz, record_size);
540
			goto fail;
541
		}
542
	}
543

544
	if (*paddr + mem_sz - cxt->phys_addr > cxt->size) {
545 546
		dev_err(dev, "no room for %s mem region (0x%zx@0x%llx) in (0x%lx@0x%llx)\n",
			name,
547 548 549
			mem_sz, (unsigned long long)*paddr,
			cxt->size, (unsigned long long)cxt->phys_addr);
		goto fail;
550 551
	}

552
	zone_sz = mem_sz / *cnt;
553 554
	if (!zone_sz) {
		dev_err(dev, "%s zone size == 0\n", name);
555
		goto fail;
556
	}
557 558 559 560 561 562

	prz_ar = kcalloc(*cnt, sizeof(**przs), GFP_KERNEL);
	if (!prz_ar)
		goto fail;

	for (i = 0; i < *cnt; i++) {
563 564 565 566 567 568 569
		char *label;

		if (*cnt == 1)
			label = kasprintf(GFP_KERNEL, "ramoops:%s", name);
		else
			label = kasprintf(GFP_KERNEL, "ramoops:%s(%d/%d)",
					  name, i, *cnt - 1);
570
		prz_ar[i] = persistent_ram_new(*paddr, zone_sz, sig,
571 572
					       &cxt->ecc_info,
					       cxt->memtype, flags, label);
573 574
		if (IS_ERR(prz_ar[i])) {
			err = PTR_ERR(prz_ar[i]);
575 576 577
			dev_err(dev, "failed to request %s mem region (0x%zx@0x%llx): %d\n",
				name, record_size,
				(unsigned long long)*paddr, err);
578 579 580

			while (i > 0) {
				i--;
581
				persistent_ram_free(prz_ar[i]);
582
			}
583 584
			kfree(prz_ar);
			goto fail;
585
		}
586
		*paddr += zone_sz;
587
		prz_ar[i]->type = pstore_name_to_type(name);
588 589
	}

590
	*przs = prz_ar;
591
	return 0;
592 593 594

fail:
	*cnt = 0;
595 596 597
	return err;
}

598 599
static int ramoops_init_prz(const char *name,
			    struct device *dev, struct ramoops_context *cxt,
600 601
			    struct persistent_ram_zone **prz,
			    phys_addr_t *paddr, size_t sz, u32 sig)
602
{
603 604
	char *label;

605 606 607
	if (!sz)
		return 0;

608
	if (*paddr + sz - cxt->phys_addr > cxt->size) {
609 610
		dev_err(dev, "no room for %s mem region (0x%zx@0x%llx) in (0x%lx@0x%llx)\n",
			name, sz, (unsigned long long)*paddr,
611
			cxt->size, (unsigned long long)cxt->phys_addr);
612
		return -ENOMEM;
613
	}
614

615
	label = kasprintf(GFP_KERNEL, "ramoops:%s", name);
616
	*prz = persistent_ram_new(*paddr, sz, sig, &cxt->ecc_info,
617
				  cxt->memtype, PRZ_FLAG_ZAP_OLD, label);
618 619 620
	if (IS_ERR(*prz)) {
		int err = PTR_ERR(*prz);

621 622
		dev_err(dev, "failed to request %s mem region (0x%zx@0x%llx): %d\n",
			name, sz, (unsigned long long)*paddr, err);
623 624 625 626
		return err;
	}

	*paddr += sz;
627
	(*prz)->type = pstore_name_to_type(name);
628 629 630 631

	return 0;
}

632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657
static int ramoops_parse_dt_size(struct platform_device *pdev,
				 const char *propname, u32 *value)
{
	u32 val32 = 0;
	int ret;

	ret = of_property_read_u32(pdev->dev.of_node, propname, &val32);
	if (ret < 0 && ret != -EINVAL) {
		dev_err(&pdev->dev, "failed to parse property %s: %d\n",
			propname, ret);
		return ret;
	}

	if (val32 > INT_MAX) {
		dev_err(&pdev->dev, "%s %u > INT_MAX\n", propname, val32);
		return -EOVERFLOW;
	}

	*value = val32;
	return 0;
}

static int ramoops_parse_dt(struct platform_device *pdev,
			    struct ramoops_platform_data *pdata)
{
	struct device_node *of_node = pdev->dev.of_node;
658
	struct device_node *parent_node;
659
	struct resource *res;
660 661 662 663 664
	u32 value;
	int ret;

	dev_dbg(&pdev->dev, "using Device Tree\n");

665 666
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
667
		dev_err(&pdev->dev,
668 669
			"failed to locate DT /reserved-memory resource\n");
		return -EINVAL;
670 671
	}

672 673
	pdata->mem_size = resource_size(res);
	pdata->mem_address = res->start;
674 675 676 677 678 679 680 681 682 683 684 685 686 687 688
	pdata->mem_type = of_property_read_bool(of_node, "unbuffered");
	pdata->dump_oops = !of_property_read_bool(of_node, "no-dump-oops");

#define parse_size(name, field) {					\
		ret = ramoops_parse_dt_size(pdev, name, &value);	\
		if (ret < 0)						\
			return ret;					\
		field = value;						\
	}

	parse_size("record-size", pdata->record_size);
	parse_size("console-size", pdata->console_size);
	parse_size("ftrace-size", pdata->ftrace_size);
	parse_size("pmsg-size", pdata->pmsg_size);
	parse_size("ecc-size", pdata->ecc_info.ecc_size);
689
	parse_size("flags", pdata->flags);
690 691 692

#undef parse_size

693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712
	/*
	 * Some old Chromebooks relied on the kernel setting the
	 * console_size and pmsg_size to the record size since that's
	 * what the downstream kernel did.  These same Chromebooks had
	 * "ramoops" straight under the root node which isn't
	 * according to the current upstream bindings (though it was
	 * arguably acceptable under a prior version of the bindings).
	 * Let's make those old Chromebooks work by detecting that
	 * we're not a child of "reserved-memory" and mimicking the
	 * expected behavior.
	 */
	parent_node = of_get_parent(of_node);
	if (!of_node_name_eq(parent_node, "reserved-memory") &&
	    !pdata->console_size && !pdata->ftrace_size &&
	    !pdata->pmsg_size && !pdata->ecc_info.ecc_size) {
		pdata->console_size = pdata->record_size;
		pdata->pmsg_size = pdata->record_size;
	}
	of_node_put(parent_node);

713 714 715
	return 0;
}

716
static int ramoops_probe(struct platform_device *pdev)
717
{
718
	struct device *dev = &pdev->dev;
719
	struct ramoops_platform_data *pdata = dev->platform_data;
720
	struct ramoops_platform_data pdata_local;
721
	struct ramoops_context *cxt = &oops_cxt;
722 723
	size_t dump_mem_sz;
	phys_addr_t paddr;
724 725
	int err = -EINVAL;

726 727
	/*
	 * Only a single ramoops area allowed at a time, so fail extra
K
Kees Cook 已提交
728 729
	 * probes.
	 */
730 731
	if (cxt->max_dump_cnt) {
		pr_err("already initialized\n");
K
Kees Cook 已提交
732
		goto fail_out;
733 734
	}

Y
Yue Hu 已提交
735 736 737 738 739 740 741 742 743
	if (dev_of_node(dev) && !pdata) {
		pdata = &pdata_local;
		memset(pdata, 0, sizeof(*pdata));

		err = ramoops_parse_dt(pdev, pdata);
		if (err < 0)
			goto fail_out;
	}

744 745 746 747 748
	/* Make sure we didn't get bogus platform data pointer. */
	if (!pdata) {
		pr_err("NULL platform data\n");
		goto fail_out;
	}
K
Kees Cook 已提交
749

750
	if (!pdata->mem_size || (!pdata->record_size && !pdata->console_size &&
751
			!pdata->ftrace_size && !pdata->pmsg_size)) {
752
		pr_err("The memory size and the record/console size must be "
753
			"non-zero\n");
K
Kees Cook 已提交
754
		goto fail_out;
755 756
	}

757
	if (pdata->record_size && !is_power_of_2(pdata->record_size))
758
		pdata->record_size = rounddown_pow_of_two(pdata->record_size);
759
	if (pdata->console_size && !is_power_of_2(pdata->console_size))
760
		pdata->console_size = rounddown_pow_of_two(pdata->console_size);
761
	if (pdata->ftrace_size && !is_power_of_2(pdata->ftrace_size))
762
		pdata->ftrace_size = rounddown_pow_of_two(pdata->ftrace_size);
763 764
	if (pdata->pmsg_size && !is_power_of_2(pdata->pmsg_size))
		pdata->pmsg_size = rounddown_pow_of_two(pdata->pmsg_size);
765

766 767
	cxt->size = pdata->mem_size;
	cxt->phys_addr = pdata->mem_address;
768
	cxt->memtype = pdata->mem_type;
769
	cxt->record_size = pdata->record_size;
770
	cxt->console_size = pdata->console_size;
771
	cxt->ftrace_size = pdata->ftrace_size;
772
	cxt->pmsg_size = pdata->pmsg_size;
773
	cxt->dump_oops = pdata->dump_oops;
774
	cxt->flags = pdata->flags;
775
	cxt->ecc_info = pdata->ecc_info;
776

777
	paddr = cxt->phys_addr;
778

779 780
	dump_mem_sz = cxt->size - cxt->console_size - cxt->ftrace_size
			- cxt->pmsg_size;
781
	err = ramoops_init_przs("dmesg", dev, cxt, &cxt->dprzs, &paddr,
782 783
				dump_mem_sz, cxt->record_size,
				&cxt->max_dump_cnt, 0, 0);
784 785 786
	if (err)
		goto fail_out;

787
	err = ramoops_init_prz("console", dev, cxt, &cxt->cprz, &paddr,
788
			       cxt->console_size, 0);
789 790 791
	if (err)
		goto fail_init_cprz;

792 793 794
	cxt->max_ftrace_cnt = (cxt->flags & RAMOOPS_FLAG_FTRACE_PER_CPU)
				? nr_cpu_ids
				: 1;
795 796 797
	err = ramoops_init_przs("ftrace", dev, cxt, &cxt->fprzs, &paddr,
				cxt->ftrace_size, -1,
				&cxt->max_ftrace_cnt, LINUX_VERSION_CODE,
798 799
				(cxt->flags & RAMOOPS_FLAG_FTRACE_PER_CPU)
					? PRZ_FLAG_NO_LOCK : 0);
800 801 802
	if (err)
		goto fail_init_fprz;

803 804
	err = ramoops_init_prz("pmsg", dev, cxt, &cxt->mprz, &paddr,
				cxt->pmsg_size, 0);
805 806 807
	if (err)
		goto fail_init_mprz;

K
Kees Cook 已提交
808
	cxt->pstore.data = cxt;
809
	/*
810 811 812 813
	 * Prepare frontend flags based on which areas are initialized.
	 * For ramoops_init_przs() cases, the "max count" variable tells
	 * if there are regions present. For ramoops_init_prz() cases,
	 * the single region size is how to check.
814
	 */
815 816 817
	cxt->pstore.flags = 0;
	if (cxt->max_dump_cnt)
		cxt->pstore.flags |= PSTORE_FLAGS_DMESG;
818 819
	if (cxt->console_size)
		cxt->pstore.flags |= PSTORE_FLAGS_CONSOLE;
820
	if (cxt->max_ftrace_cnt)
821 822 823
		cxt->pstore.flags |= PSTORE_FLAGS_FTRACE;
	if (cxt->pmsg_size)
		cxt->pstore.flags |= PSTORE_FLAGS_PMSG;
824

825 826 827 828 829 830 831 832 833 834 835 836 837 838 839
	/*
	 * Since bufsize is only used for dmesg crash dumps, it
	 * must match the size of the dprz record (after PRZ header
	 * and ECC bytes have been accounted for).
	 */
	if (cxt->pstore.flags & PSTORE_FLAGS_DMESG) {
		cxt->pstore.bufsize = cxt->dprzs[0]->buffer_size;
		cxt->pstore.buf = kzalloc(cxt->pstore.bufsize, GFP_KERNEL);
		if (!cxt->pstore.buf) {
			pr_err("cannot allocate pstore crash dump buffer\n");
			err = -ENOMEM;
			goto fail_clear;
		}
	}

K
Kees Cook 已提交
840
	err = pstore_register(&cxt->pstore);
841
	if (err) {
K
Kees Cook 已提交
842
		pr_err("registering with pstore failed\n");
843
		goto fail_buf;
844 845
	}

846 847 848 849 850 851 852 853
	/*
	 * Update the module parameter variables as well so they are visible
	 * through /sys/module/ramoops/parameters/
	 */
	mem_size = pdata->mem_size;
	mem_address = pdata->mem_address;
	record_size = pdata->record_size;
	dump_oops = pdata->dump_oops;
854 855 856
	ramoops_console_size = pdata->console_size;
	ramoops_pmsg_size = pdata->pmsg_size;
	ramoops_ftrace_size = pdata->ftrace_size;
857

858
	pr_info("using 0x%lx@0x%llx, ecc: %d\n",
859
		cxt->size, (unsigned long long)cxt->phys_addr,
860
		cxt->ecc_info.ecc_size);
K
Kees Cook 已提交
861

862 863
	return 0;

K
Kees Cook 已提交
864 865 866 867
fail_buf:
	kfree(cxt->pstore.buf);
fail_clear:
	cxt->pstore.bufsize = 0;
868
	persistent_ram_free(cxt->mprz);
869
fail_init_mprz:
870
fail_init_fprz:
871
	persistent_ram_free(cxt->cprz);
872
fail_init_cprz:
873
	ramoops_free_przs(cxt);
K
Kees Cook 已提交
874
fail_out:
875 876 877
	return err;
}

G
Geliang Tang 已提交
878
static int ramoops_remove(struct platform_device *pdev)
879 880 881
{
	struct ramoops_context *cxt = &oops_cxt;

G
Geliang Tang 已提交
882
	pstore_unregister(&cxt->pstore);
K
Kees Cook 已提交
883 884 885 886

	kfree(cxt->pstore.buf);
	cxt->pstore.bufsize = 0;

G
Geliang Tang 已提交
887 888 889 890
	persistent_ram_free(cxt->mprz);
	persistent_ram_free(cxt->cprz);
	ramoops_free_przs(cxt);

891
	return 0;
892 893
}

894 895 896 897 898
static const struct of_device_id dt_match[] = {
	{ .compatible = "ramoops" },
	{}
};

899
static struct platform_driver ramoops_driver = {
900
	.probe		= ramoops_probe,
G
Geliang Tang 已提交
901
	.remove		= ramoops_remove,
902
	.driver		= {
903 904
		.name		= "ramoops",
		.of_match_table	= dt_match,
905 906 907
	},
};

908
static inline void ramoops_unregister_dummy(void)
909
{
910 911 912 913 914 915
	platform_device_unregister(dummy);
	dummy = NULL;
}

static void __init ramoops_register_dummy(void)
{
916 917
	struct ramoops_platform_data pdata;

918 919 920 921 922
	/*
	 * Prepare a dummy platform data structure to carry the module
	 * parameters. If mem_size isn't set, then there are no module
	 * parameters, and we can skip this.
	 */
923 924 925 926 927
	if (!mem_size)
		return;

	pr_info("using module parameters\n");

928 929 930 931 932 933 934 935 936 937
	memset(&pdata, 0, sizeof(pdata));
	pdata.mem_size = mem_size;
	pdata.mem_address = mem_address;
	pdata.mem_type = mem_type;
	pdata.record_size = record_size;
	pdata.console_size = ramoops_console_size;
	pdata.ftrace_size = ramoops_ftrace_size;
	pdata.pmsg_size = ramoops_pmsg_size;
	pdata.dump_oops = dump_oops;
	pdata.flags = RAMOOPS_FLAG_FTRACE_PER_CPU;
938

939 940 941 942
	/*
	 * For backwards compatibility ramoops.ecc=1 means 16 bytes ECC
	 * (using 1 byte for ECC isn't much of use anyway).
	 */
943
	pdata.ecc_info.ecc_size = ramoops_ecc == 1 ? 16 : ramoops_ecc;
944 945

	dummy = platform_device_register_data(NULL, "ramoops", -1,
946
			&pdata, sizeof(pdata));
947 948 949
	if (IS_ERR(dummy)) {
		pr_info("could not create platform device: %ld\n",
			PTR_ERR(dummy));
950 951
		dummy = NULL;
		ramoops_unregister_dummy();
952 953 954 955 956
	}
}

static int __init ramoops_init(void)
{
957 958
	int ret;

959
	ramoops_register_dummy();
960 961 962 963 964
	ret = platform_driver_register(&ramoops_driver);
	if (ret != 0)
		ramoops_unregister_dummy();

	return ret;
965
}
966
postcore_initcall(ramoops_init);
967 968 969 970

static void __exit ramoops_exit(void)
{
	platform_driver_unregister(&ramoops_driver);
971
	ramoops_unregister_dummy();
972
}
973 974 975 976 977
module_exit(ramoops_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Marco Stornelli <marco.stornelli@gmail.com>");
MODULE_DESCRIPTION("RAM Oops/Panic logger/driver");