cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

rtas-fadump.c (16393B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Firmware-Assisted Dump support on POWERVM platform.
      4 *
      5 * Copyright 2011, Mahesh Salgaonkar, IBM Corporation.
      6 * Copyright 2019, Hari Bathini, IBM Corporation.
      7 */
      8
      9#define pr_fmt(fmt) "rtas fadump: " fmt
     10
     11#include <linux/string.h>
     12#include <linux/memblock.h>
     13#include <linux/delay.h>
     14#include <linux/seq_file.h>
     15#include <linux/crash_dump.h>
     16#include <linux/of.h>
     17#include <linux/of_fdt.h>
     18
     19#include <asm/page.h>
     20#include <asm/rtas.h>
     21#include <asm/fadump.h>
     22#include <asm/fadump-internal.h>
     23
     24#include "rtas-fadump.h"
     25
     26static struct rtas_fadump_mem_struct fdm;
     27static const struct rtas_fadump_mem_struct *fdm_active;
     28
     29static void rtas_fadump_update_config(struct fw_dump *fadump_conf,
     30				      const struct rtas_fadump_mem_struct *fdm)
     31{
     32	fadump_conf->boot_mem_dest_addr =
     33		be64_to_cpu(fdm->rmr_region.destination_address);
     34
     35	fadump_conf->fadumphdr_addr = (fadump_conf->boot_mem_dest_addr +
     36				       fadump_conf->boot_memory_size);
     37}
     38
     39/*
     40 * This function is called in the capture kernel to get configuration details
     41 * setup in the first kernel and passed to the f/w.
     42 */
     43static void __init rtas_fadump_get_config(struct fw_dump *fadump_conf,
     44				   const struct rtas_fadump_mem_struct *fdm)
     45{
     46	fadump_conf->boot_mem_addr[0] =
     47		be64_to_cpu(fdm->rmr_region.source_address);
     48	fadump_conf->boot_mem_sz[0] = be64_to_cpu(fdm->rmr_region.source_len);
     49	fadump_conf->boot_memory_size = fadump_conf->boot_mem_sz[0];
     50
     51	fadump_conf->boot_mem_top = fadump_conf->boot_memory_size;
     52	fadump_conf->boot_mem_regs_cnt = 1;
     53
     54	/*
     55	 * Start address of reserve dump area (permanent reservation) for
     56	 * re-registering FADump after dump capture.
     57	 */
     58	fadump_conf->reserve_dump_area_start =
     59		be64_to_cpu(fdm->cpu_state_data.destination_address);
     60
     61	rtas_fadump_update_config(fadump_conf, fdm);
     62}
     63
     64static u64 rtas_fadump_init_mem_struct(struct fw_dump *fadump_conf)
     65{
     66	u64 addr = fadump_conf->reserve_dump_area_start;
     67
     68	memset(&fdm, 0, sizeof(struct rtas_fadump_mem_struct));
     69	addr = addr & PAGE_MASK;
     70
     71	fdm.header.dump_format_version = cpu_to_be32(0x00000001);
     72	fdm.header.dump_num_sections = cpu_to_be16(3);
     73	fdm.header.dump_status_flag = 0;
     74	fdm.header.offset_first_dump_section =
     75		cpu_to_be32((u32)offsetof(struct rtas_fadump_mem_struct,
     76					  cpu_state_data));
     77
     78	/*
     79	 * Fields for disk dump option.
     80	 * We are not using disk dump option, hence set these fields to 0.
     81	 */
     82	fdm.header.dd_block_size = 0;
     83	fdm.header.dd_block_offset = 0;
     84	fdm.header.dd_num_blocks = 0;
     85	fdm.header.dd_offset_disk_path = 0;
     86
     87	/* set 0 to disable an automatic dump-reboot. */
     88	fdm.header.max_time_auto = 0;
     89
     90	/* Kernel dump sections */
     91	/* cpu state data section. */
     92	fdm.cpu_state_data.request_flag =
     93		cpu_to_be32(RTAS_FADUMP_REQUEST_FLAG);
     94	fdm.cpu_state_data.source_data_type =
     95		cpu_to_be16(RTAS_FADUMP_CPU_STATE_DATA);
     96	fdm.cpu_state_data.source_address = 0;
     97	fdm.cpu_state_data.source_len =
     98		cpu_to_be64(fadump_conf->cpu_state_data_size);
     99	fdm.cpu_state_data.destination_address = cpu_to_be64(addr);
    100	addr += fadump_conf->cpu_state_data_size;
    101
    102	/* hpte region section */
    103	fdm.hpte_region.request_flag = cpu_to_be32(RTAS_FADUMP_REQUEST_FLAG);
    104	fdm.hpte_region.source_data_type =
    105		cpu_to_be16(RTAS_FADUMP_HPTE_REGION);
    106	fdm.hpte_region.source_address = 0;
    107	fdm.hpte_region.source_len =
    108		cpu_to_be64(fadump_conf->hpte_region_size);
    109	fdm.hpte_region.destination_address = cpu_to_be64(addr);
    110	addr += fadump_conf->hpte_region_size;
    111
    112	/*
    113	 * Align boot memory area destination address to page boundary to
    114	 * be able to mmap read this area in the vmcore.
    115	 */
    116	addr = PAGE_ALIGN(addr);
    117
    118	/* RMA region section */
    119	fdm.rmr_region.request_flag = cpu_to_be32(RTAS_FADUMP_REQUEST_FLAG);
    120	fdm.rmr_region.source_data_type =
    121		cpu_to_be16(RTAS_FADUMP_REAL_MODE_REGION);
    122	fdm.rmr_region.source_address = cpu_to_be64(0);
    123	fdm.rmr_region.source_len = cpu_to_be64(fadump_conf->boot_memory_size);
    124	fdm.rmr_region.destination_address = cpu_to_be64(addr);
    125	addr += fadump_conf->boot_memory_size;
    126
    127	rtas_fadump_update_config(fadump_conf, &fdm);
    128
    129	return addr;
    130}
    131
    132static u64 rtas_fadump_get_bootmem_min(void)
    133{
    134	return RTAS_FADUMP_MIN_BOOT_MEM;
    135}
    136
    137static int rtas_fadump_register(struct fw_dump *fadump_conf)
    138{
    139	unsigned int wait_time;
    140	int rc, err = -EIO;
    141
    142	/* TODO: Add upper time limit for the delay */
    143	do {
    144		rc =  rtas_call(fadump_conf->ibm_configure_kernel_dump, 3, 1,
    145				NULL, FADUMP_REGISTER, &fdm,
    146				sizeof(struct rtas_fadump_mem_struct));
    147
    148		wait_time = rtas_busy_delay_time(rc);
    149		if (wait_time)
    150			mdelay(wait_time);
    151
    152	} while (wait_time);
    153
    154	switch (rc) {
    155	case 0:
    156		pr_info("Registration is successful!\n");
    157		fadump_conf->dump_registered = 1;
    158		err = 0;
    159		break;
    160	case -1:
    161		pr_err("Failed to register. Hardware Error(%d).\n", rc);
    162		break;
    163	case -3:
    164		if (!is_fadump_boot_mem_contiguous())
    165			pr_err("Can't have holes in boot memory area.\n");
    166		else if (!is_fadump_reserved_mem_contiguous())
    167			pr_err("Can't have holes in reserved memory area.\n");
    168
    169		pr_err("Failed to register. Parameter Error(%d).\n", rc);
    170		err = -EINVAL;
    171		break;
    172	case -9:
    173		pr_err("Already registered!\n");
    174		fadump_conf->dump_registered = 1;
    175		err = -EEXIST;
    176		break;
    177	default:
    178		pr_err("Failed to register. Unknown Error(%d).\n", rc);
    179		break;
    180	}
    181
    182	return err;
    183}
    184
    185static int rtas_fadump_unregister(struct fw_dump *fadump_conf)
    186{
    187	unsigned int wait_time;
    188	int rc;
    189
    190	/* TODO: Add upper time limit for the delay */
    191	do {
    192		rc =  rtas_call(fadump_conf->ibm_configure_kernel_dump, 3, 1,
    193				NULL, FADUMP_UNREGISTER, &fdm,
    194				sizeof(struct rtas_fadump_mem_struct));
    195
    196		wait_time = rtas_busy_delay_time(rc);
    197		if (wait_time)
    198			mdelay(wait_time);
    199	} while (wait_time);
    200
    201	if (rc) {
    202		pr_err("Failed to un-register - unexpected error(%d).\n", rc);
    203		return -EIO;
    204	}
    205
    206	fadump_conf->dump_registered = 0;
    207	return 0;
    208}
    209
    210static int rtas_fadump_invalidate(struct fw_dump *fadump_conf)
    211{
    212	unsigned int wait_time;
    213	int rc;
    214
    215	/* TODO: Add upper time limit for the delay */
    216	do {
    217		rc =  rtas_call(fadump_conf->ibm_configure_kernel_dump, 3, 1,
    218				NULL, FADUMP_INVALIDATE, fdm_active,
    219				sizeof(struct rtas_fadump_mem_struct));
    220
    221		wait_time = rtas_busy_delay_time(rc);
    222		if (wait_time)
    223			mdelay(wait_time);
    224	} while (wait_time);
    225
    226	if (rc) {
    227		pr_err("Failed to invalidate - unexpected error (%d).\n", rc);
    228		return -EIO;
    229	}
    230
    231	fadump_conf->dump_active = 0;
    232	fdm_active = NULL;
    233	return 0;
    234}
    235
    236#define RTAS_FADUMP_GPR_MASK		0xffffff0000000000
    237static inline int rtas_fadump_gpr_index(u64 id)
    238{
    239	char str[3];
    240	int i = -1;
    241
    242	if ((id & RTAS_FADUMP_GPR_MASK) == fadump_str_to_u64("GPR")) {
    243		/* get the digits at the end */
    244		id &= ~RTAS_FADUMP_GPR_MASK;
    245		id >>= 24;
    246		str[2] = '\0';
    247		str[1] = id & 0xff;
    248		str[0] = (id >> 8) & 0xff;
    249		if (kstrtoint(str, 10, &i))
    250			i = -EINVAL;
    251		if (i > 31)
    252			i = -1;
    253	}
    254	return i;
    255}
    256
    257static void __init rtas_fadump_set_regval(struct pt_regs *regs, u64 reg_id, u64 reg_val)
    258{
    259	int i;
    260
    261	i = rtas_fadump_gpr_index(reg_id);
    262	if (i >= 0)
    263		regs->gpr[i] = (unsigned long)reg_val;
    264	else if (reg_id == fadump_str_to_u64("NIA"))
    265		regs->nip = (unsigned long)reg_val;
    266	else if (reg_id == fadump_str_to_u64("MSR"))
    267		regs->msr = (unsigned long)reg_val;
    268	else if (reg_id == fadump_str_to_u64("CTR"))
    269		regs->ctr = (unsigned long)reg_val;
    270	else if (reg_id == fadump_str_to_u64("LR"))
    271		regs->link = (unsigned long)reg_val;
    272	else if (reg_id == fadump_str_to_u64("XER"))
    273		regs->xer = (unsigned long)reg_val;
    274	else if (reg_id == fadump_str_to_u64("CR"))
    275		regs->ccr = (unsigned long)reg_val;
    276	else if (reg_id == fadump_str_to_u64("DAR"))
    277		regs->dar = (unsigned long)reg_val;
    278	else if (reg_id == fadump_str_to_u64("DSISR"))
    279		regs->dsisr = (unsigned long)reg_val;
    280}
    281
    282static struct rtas_fadump_reg_entry* __init
    283rtas_fadump_read_regs(struct rtas_fadump_reg_entry *reg_entry,
    284		      struct pt_regs *regs)
    285{
    286	memset(regs, 0, sizeof(struct pt_regs));
    287
    288	while (be64_to_cpu(reg_entry->reg_id) != fadump_str_to_u64("CPUEND")) {
    289		rtas_fadump_set_regval(regs, be64_to_cpu(reg_entry->reg_id),
    290				       be64_to_cpu(reg_entry->reg_value));
    291		reg_entry++;
    292	}
    293	reg_entry++;
    294	return reg_entry;
    295}
    296
    297/*
    298 * Read CPU state dump data and convert it into ELF notes.
    299 * The CPU dump starts with magic number "REGSAVE". NumCpusOffset should be
    300 * used to access the data to allow for additional fields to be added without
    301 * affecting compatibility. Each list of registers for a CPU starts with
    302 * "CPUSTRT" and ends with "CPUEND". Each register entry is of 16 bytes,
    303 * 8 Byte ASCII identifier and 8 Byte register value. The register entry
    304 * with identifier "CPUSTRT" and "CPUEND" contains 4 byte cpu id as part
    305 * of register value. For more details refer to PAPR document.
    306 *
    307 * Only for the crashing cpu we ignore the CPU dump data and get exact
    308 * state from fadump crash info structure populated by first kernel at the
    309 * time of crash.
    310 */
    311static int __init rtas_fadump_build_cpu_notes(struct fw_dump *fadump_conf)
    312{
    313	struct rtas_fadump_reg_save_area_header *reg_header;
    314	struct fadump_crash_info_header *fdh = NULL;
    315	struct rtas_fadump_reg_entry *reg_entry;
    316	u32 num_cpus, *note_buf;
    317	int i, rc = 0, cpu = 0;
    318	struct pt_regs regs;
    319	unsigned long addr;
    320	void *vaddr;
    321
    322	addr = be64_to_cpu(fdm_active->cpu_state_data.destination_address);
    323	vaddr = __va(addr);
    324
    325	reg_header = vaddr;
    326	if (be64_to_cpu(reg_header->magic_number) !=
    327	    fadump_str_to_u64("REGSAVE")) {
    328		pr_err("Unable to read register save area.\n");
    329		return -ENOENT;
    330	}
    331
    332	pr_debug("--------CPU State Data------------\n");
    333	pr_debug("Magic Number: %llx\n", be64_to_cpu(reg_header->magic_number));
    334	pr_debug("NumCpuOffset: %x\n", be32_to_cpu(reg_header->num_cpu_offset));
    335
    336	vaddr += be32_to_cpu(reg_header->num_cpu_offset);
    337	num_cpus = be32_to_cpu(*((__be32 *)(vaddr)));
    338	pr_debug("NumCpus     : %u\n", num_cpus);
    339	vaddr += sizeof(u32);
    340	reg_entry = (struct rtas_fadump_reg_entry *)vaddr;
    341
    342	rc = fadump_setup_cpu_notes_buf(num_cpus);
    343	if (rc != 0)
    344		return rc;
    345
    346	note_buf = (u32 *)fadump_conf->cpu_notes_buf_vaddr;
    347
    348	if (fadump_conf->fadumphdr_addr)
    349		fdh = __va(fadump_conf->fadumphdr_addr);
    350
    351	for (i = 0; i < num_cpus; i++) {
    352		if (be64_to_cpu(reg_entry->reg_id) !=
    353		    fadump_str_to_u64("CPUSTRT")) {
    354			pr_err("Unable to read CPU state data\n");
    355			rc = -ENOENT;
    356			goto error_out;
    357		}
    358		/* Lower 4 bytes of reg_value contains logical cpu id */
    359		cpu = (be64_to_cpu(reg_entry->reg_value) &
    360		       RTAS_FADUMP_CPU_ID_MASK);
    361		if (fdh && !cpumask_test_cpu(cpu, &fdh->cpu_mask)) {
    362			RTAS_FADUMP_SKIP_TO_NEXT_CPU(reg_entry);
    363			continue;
    364		}
    365		pr_debug("Reading register data for cpu %d...\n", cpu);
    366		if (fdh && fdh->crashing_cpu == cpu) {
    367			regs = fdh->regs;
    368			note_buf = fadump_regs_to_elf_notes(note_buf, &regs);
    369			RTAS_FADUMP_SKIP_TO_NEXT_CPU(reg_entry);
    370		} else {
    371			reg_entry++;
    372			reg_entry = rtas_fadump_read_regs(reg_entry, &regs);
    373			note_buf = fadump_regs_to_elf_notes(note_buf, &regs);
    374		}
    375	}
    376	final_note(note_buf);
    377
    378	if (fdh) {
    379		pr_debug("Updating elfcore header (%llx) with cpu notes\n",
    380			 fdh->elfcorehdr_addr);
    381		fadump_update_elfcore_header(__va(fdh->elfcorehdr_addr));
    382	}
    383	return 0;
    384
    385error_out:
    386	fadump_free_cpu_notes_buf();
    387	return rc;
    388
    389}
    390
    391/*
    392 * Validate and process the dump data stored by firmware before exporting
    393 * it through '/proc/vmcore'.
    394 */
    395static int __init rtas_fadump_process(struct fw_dump *fadump_conf)
    396{
    397	struct fadump_crash_info_header *fdh;
    398	int rc = 0;
    399
    400	if (!fdm_active || !fadump_conf->fadumphdr_addr)
    401		return -EINVAL;
    402
    403	/* Check if the dump data is valid. */
    404	if ((be16_to_cpu(fdm_active->header.dump_status_flag) ==
    405			RTAS_FADUMP_ERROR_FLAG) ||
    406			(fdm_active->cpu_state_data.error_flags != 0) ||
    407			(fdm_active->rmr_region.error_flags != 0)) {
    408		pr_err("Dump taken by platform is not valid\n");
    409		return -EINVAL;
    410	}
    411	if ((fdm_active->rmr_region.bytes_dumped !=
    412			fdm_active->rmr_region.source_len) ||
    413			!fdm_active->cpu_state_data.bytes_dumped) {
    414		pr_err("Dump taken by platform is incomplete\n");
    415		return -EINVAL;
    416	}
    417
    418	/* Validate the fadump crash info header */
    419	fdh = __va(fadump_conf->fadumphdr_addr);
    420	if (fdh->magic_number != FADUMP_CRASH_INFO_MAGIC) {
    421		pr_err("Crash info header is not valid.\n");
    422		return -EINVAL;
    423	}
    424
    425	rc = rtas_fadump_build_cpu_notes(fadump_conf);
    426	if (rc)
    427		return rc;
    428
    429	/*
    430	 * We are done validating dump info and elfcore header is now ready
    431	 * to be exported. set elfcorehdr_addr so that vmcore module will
    432	 * export the elfcore header through '/proc/vmcore'.
    433	 */
    434	elfcorehdr_addr = fdh->elfcorehdr_addr;
    435
    436	return 0;
    437}
    438
    439static void rtas_fadump_region_show(struct fw_dump *fadump_conf,
    440				    struct seq_file *m)
    441{
    442	const struct rtas_fadump_section *cpu_data_section;
    443	const struct rtas_fadump_mem_struct *fdm_ptr;
    444
    445	if (fdm_active)
    446		fdm_ptr = fdm_active;
    447	else
    448		fdm_ptr = &fdm;
    449
    450	cpu_data_section = &(fdm_ptr->cpu_state_data);
    451	seq_printf(m, "CPU :[%#016llx-%#016llx] %#llx bytes, Dumped: %#llx\n",
    452		   be64_to_cpu(cpu_data_section->destination_address),
    453		   be64_to_cpu(cpu_data_section->destination_address) +
    454		   be64_to_cpu(cpu_data_section->source_len) - 1,
    455		   be64_to_cpu(cpu_data_section->source_len),
    456		   be64_to_cpu(cpu_data_section->bytes_dumped));
    457
    458	seq_printf(m, "HPTE:[%#016llx-%#016llx] %#llx bytes, Dumped: %#llx\n",
    459		   be64_to_cpu(fdm_ptr->hpte_region.destination_address),
    460		   be64_to_cpu(fdm_ptr->hpte_region.destination_address) +
    461		   be64_to_cpu(fdm_ptr->hpte_region.source_len) - 1,
    462		   be64_to_cpu(fdm_ptr->hpte_region.source_len),
    463		   be64_to_cpu(fdm_ptr->hpte_region.bytes_dumped));
    464
    465	seq_printf(m, "DUMP: Src: %#016llx, Dest: %#016llx, ",
    466		   be64_to_cpu(fdm_ptr->rmr_region.source_address),
    467		   be64_to_cpu(fdm_ptr->rmr_region.destination_address));
    468	seq_printf(m, "Size: %#llx, Dumped: %#llx bytes\n",
    469		   be64_to_cpu(fdm_ptr->rmr_region.source_len),
    470		   be64_to_cpu(fdm_ptr->rmr_region.bytes_dumped));
    471
    472	/* Dump is active. Show preserved area start address. */
    473	if (fdm_active) {
    474		seq_printf(m, "\nMemory above %#016llx is reserved for saving crash dump\n",
    475			   fadump_conf->boot_mem_top);
    476	}
    477}
    478
    479static void rtas_fadump_trigger(struct fadump_crash_info_header *fdh,
    480				const char *msg)
    481{
    482	/* Call ibm,os-term rtas call to trigger firmware assisted dump */
    483	rtas_os_term((char *)msg);
    484}
    485
    486static struct fadump_ops rtas_fadump_ops = {
    487	.fadump_init_mem_struct		= rtas_fadump_init_mem_struct,
    488	.fadump_get_bootmem_min		= rtas_fadump_get_bootmem_min,
    489	.fadump_register		= rtas_fadump_register,
    490	.fadump_unregister		= rtas_fadump_unregister,
    491	.fadump_invalidate		= rtas_fadump_invalidate,
    492	.fadump_process			= rtas_fadump_process,
    493	.fadump_region_show		= rtas_fadump_region_show,
    494	.fadump_trigger			= rtas_fadump_trigger,
    495};
    496
    497void __init rtas_fadump_dt_scan(struct fw_dump *fadump_conf, u64 node)
    498{
    499	int i, size, num_sections;
    500	const __be32 *sections;
    501	const __be32 *token;
    502
    503	/*
    504	 * Check if Firmware Assisted dump is supported. if yes, check
    505	 * if dump has been initiated on last reboot.
    506	 */
    507	token = of_get_flat_dt_prop(node, "ibm,configure-kernel-dump", NULL);
    508	if (!token)
    509		return;
    510
    511	fadump_conf->ibm_configure_kernel_dump = be32_to_cpu(*token);
    512	fadump_conf->ops		= &rtas_fadump_ops;
    513	fadump_conf->fadump_supported	= 1;
    514
    515	/* Firmware supports 64-bit value for size, align it to pagesize. */
    516	fadump_conf->max_copy_size = ALIGN_DOWN(U64_MAX, PAGE_SIZE);
    517
    518	/*
    519	 * The 'ibm,kernel-dump' rtas node is present only if there is
    520	 * dump data waiting for us.
    521	 */
    522	fdm_active = of_get_flat_dt_prop(node, "ibm,kernel-dump", NULL);
    523	if (fdm_active) {
    524		pr_info("Firmware-assisted dump is active.\n");
    525		fadump_conf->dump_active = 1;
    526		rtas_fadump_get_config(fadump_conf, (void *)__pa(fdm_active));
    527	}
    528
    529	/* Get the sizes required to store dump data for the firmware provided
    530	 * dump sections.
    531	 * For each dump section type supported, a 32bit cell which defines
    532	 * the ID of a supported section followed by two 32 bit cells which
    533	 * gives the size of the section in bytes.
    534	 */
    535	sections = of_get_flat_dt_prop(node, "ibm,configure-kernel-dump-sizes",
    536					&size);
    537
    538	if (!sections)
    539		return;
    540
    541	num_sections = size / (3 * sizeof(u32));
    542
    543	for (i = 0; i < num_sections; i++, sections += 3) {
    544		u32 type = (u32)of_read_number(sections, 1);
    545
    546		switch (type) {
    547		case RTAS_FADUMP_CPU_STATE_DATA:
    548			fadump_conf->cpu_state_data_size =
    549					of_read_ulong(&sections[1], 2);
    550			break;
    551		case RTAS_FADUMP_HPTE_REGION:
    552			fadump_conf->hpte_region_size =
    553					of_read_ulong(&sections[1], 2);
    554			break;
    555		}
    556	}
    557}