brintos

brintos / linux-shallow public Read only

0
0
Text · 3.1 KiB · be38544 Raw
130 lines · c
1// SPDX-License-Identifier: GPL-2.02 3#include "lkdtm.h"4#include <linux/slab.h>5#include <linux/vmalloc.h>6#include <asm/mmu.h>7 8/* Inserts new slb entries */9static void insert_slb_entry(unsigned long p, int ssize, int page_size)10{11	unsigned long flags;12 13	flags = SLB_VSID_KERNEL | mmu_psize_defs[page_size].sllp;14	preempt_disable();15 16	asm volatile("slbmte %0,%1" :17		     : "r" (mk_vsid_data(p, ssize, flags)),18		       "r" (mk_esid_data(p, ssize, SLB_NUM_BOLTED))19		     : "memory");20 21	asm volatile("slbmte %0,%1" :22			: "r" (mk_vsid_data(p, ssize, flags)),23			  "r" (mk_esid_data(p, ssize, SLB_NUM_BOLTED + 1))24			: "memory");25	preempt_enable();26}27 28/* Inject slb multihit on vmalloc-ed address i.e 0xD00... */29static int inject_vmalloc_slb_multihit(void)30{31	char *p;32 33	p = vmalloc(PAGE_SIZE);34	if (!p)35		return -ENOMEM;36 37	insert_slb_entry((unsigned long)p, MMU_SEGSIZE_1T, mmu_vmalloc_psize);38	/*39	 * This triggers exception, If handled correctly we must recover40	 * from this error.41	 */42	p[0] = '!';43	vfree(p);44	return 0;45}46 47/* Inject slb multihit on kmalloc-ed address i.e 0xC00... */48static int inject_kmalloc_slb_multihit(void)49{50	char *p;51 52	p = kmalloc(2048, GFP_KERNEL);53	if (!p)54		return -ENOMEM;55 56	insert_slb_entry((unsigned long)p, MMU_SEGSIZE_1T, mmu_linear_psize);57	/*58	 * This triggers exception, If handled correctly we must recover59	 * from this error.60	 */61	p[0] = '!';62	kfree(p);63	return 0;64}65 66/*67 * Few initial SLB entries are bolted. Add a test to inject68 * multihit in bolted entry 0.69 */70static void insert_dup_slb_entry_0(void)71{72	unsigned long test_address = PAGE_OFFSET, *test_ptr;73	unsigned long esid, vsid;74	unsigned long i = 0;75 76	test_ptr = (unsigned long *)test_address;77	preempt_disable();78 79	asm volatile("slbmfee  %0,%1" : "=r" (esid) : "r" (i));80	asm volatile("slbmfev  %0,%1" : "=r" (vsid) : "r" (i));81 82	/* for i !=0 we would need to mask out the old entry number */83	asm volatile("slbmte %0,%1" :84			: "r" (vsid),85			  "r" (esid | SLB_NUM_BOLTED)86			: "memory");87 88	asm volatile("slbmfee  %0,%1" : "=r" (esid) : "r" (i));89	asm volatile("slbmfev  %0,%1" : "=r" (vsid) : "r" (i));90 91	/* for i !=0 we would need to mask out the old entry number */92	asm volatile("slbmte %0,%1" :93			: "r" (vsid),94			  "r" (esid | (SLB_NUM_BOLTED + 1))95			: "memory");96 97	pr_info("%s accessing test address 0x%lx: 0x%lx\n",98		__func__, test_address, *test_ptr);99 100	preempt_enable();101}102 103static void lkdtm_PPC_SLB_MULTIHIT(void)104{105	if (!radix_enabled()) {106		pr_info("Injecting SLB multihit errors\n");107		/*108		 * These need not be separate tests, And they do pretty109		 * much same thing. In any case we must recover from the110		 * errors introduced by these functions, machine would not111		 * survive these tests in case of failure to handle.112		 */113		inject_vmalloc_slb_multihit();114		inject_kmalloc_slb_multihit();115		insert_dup_slb_entry_0();116		pr_info("Recovered from SLB multihit errors\n");117	} else {118		pr_err("XFAIL: This test is for ppc64 and with hash mode MMU only\n");119	}120}121 122static struct crashtype crashtypes[] = {123	CRASHTYPE(PPC_SLB_MULTIHIT),124};125 126struct crashtype_category powerpc_crashtypes = {127	.crashtypes = crashtypes,128	.len	    = ARRAY_SIZE(crashtypes),129};130