194742Sobrien// SPDX-License-Identifier: GPL-2.0 294742Sobrien 3146890Speter#include "lkdtm.h" 4146890Speter#include <linux/slab.h> 5179626Speter#include <linux/vmalloc.h> 6240316Seadler#include <asm/mmu.h> 7146890Speter 8146890Speter/* Inserts new slb entries */ 9146890Speterstatic void insert_slb_entry(unsigned long p, int ssize, int page_size) 10146890Speter{ 11146890Speter unsigned long flags; 12146890Speter 13146890Speter flags = SLB_VSID_KERNEL | mmu_psize_defs[page_size].sllp; 14146890Speter preempt_disable(); 15146890Speter 16146890Speter asm volatile("slbmte %0,%1" : 17146890Speter : "r" (mk_vsid_data(p, ssize, flags)), 18146890Speter "r" (mk_esid_data(p, ssize, SLB_NUM_BOLTED)) 19146890Speter : "memory"); 20146890Speter 2194742Sobrien asm volatile("slbmte %0,%1" : 2295253Sru : "r" (mk_vsid_data(p, ssize, flags)), 23159014Sjmg "r" (mk_esid_data(p, ssize, SLB_NUM_BOLTED + 1)) 2496991Srwatson : "memory"); 2596991Srwatson preempt_enable(); 2696991Srwatson} 27102773Srwatson 28102773Srwatson/* Inject slb multihit on vmalloc-ed address i.e 0xD00... */ 29156279Srwatsonstatic int inject_vmalloc_slb_multihit(void) 30156279Srwatson{ 31250778Sadrian char *p; 3294917Simp 33126445Sobrien p = vmalloc(PAGE_SIZE); 34248805Simp if (!p) 35248805Simp return -ENOMEM; 36146933Simp 3794847Sjhb insert_slb_entry((unsigned long)p, MMU_SEGSIZE_1T, mmu_vmalloc_psize); 3894847Sjhb /* 3994847Sjhb * This triggers exception, If handled correctly we must recover 4094915Sken * from this error. 4199607Smjacob */ 4294915Sken p[0] = '!'; 4394915Sken vfree(p); 4494915Sken return 0; 4594915Sken} 4694915Sken 4794915Sken/* Inject slb multihit on kmalloc-ed address i.e 0xC00... */ 4894915Skenstatic int inject_kmalloc_slb_multihit(void) 4994915Sken{ 50169922Sjfv char *p; 51219647Sdavidch 5297611Sbillf p = kmalloc(2048, GFP_KERNEL); 5394918Sgshapiro if (!p) 5494918Sgshapiro return -ENOMEM; 5594918Sgshapiro 5694918Sgshapiro insert_slb_entry((unsigned long)p, MMU_SEGSIZE_1T, mmu_linear_psize); 5794918Sgshapiro /* 58106187Sdes * This triggers exception, If handled correctly we must recover 59106187Sdes * from this error. 6095455Sdes */ 6198750Sdes p[0] = '!'; 62205686Sdes kfree(p); 63205686Sdes return 0; 64205686Sdes} 6596268Sgad 6696268Sgad/* 67250778Sadrian * Few initial SLB entries are bolted. Add a test to inject 6896332Speter * multihit in bolted entry 0. 6996332Speter */ 70100314Srustatic void insert_dup_slb_entry_0(void) 71146921Sru{ 72146921Sru unsigned long test_address = PAGE_OFFSET, *test_ptr; 7397611Sbillf unsigned long esid, vsid; 74190171Srnoland unsigned long i = 0; 75115825Sfanf 76126445Sobrien test_ptr = (unsigned long *)test_address; 77117645Sdwmalone preempt_disable(); 78118204Sbp 79118204Sbp asm volatile("slbmfee %0,%1" : "=r" (esid) : "r" (i)); 80127337Smlaier asm volatile("slbmfev %0,%1" : "=r" (vsid) : "r" (i)); 81126445Sobrien 82146837Sobrien /* for i !=0 we would need to mask out the old entry number */ 83146837Sobrien asm volatile("slbmte %0,%1" : 84146837Sobrien : "r" (vsid), 85146837Sobrien "r" (esid | SLB_NUM_BOLTED) 86133182Spjd : "memory"); 87148779Spjd 88133182Spjd asm volatile("slbmfee %0,%1" : "=r" (esid) : "r" (i)); 89133182Spjd asm volatile("slbmfev %0,%1" : "=r" (vsid) : "r" (i)); 90133182Spjd 91133182Spjd /* for i !=0 we would need to mask out the old entry number */ 92133841Spjd asm volatile("slbmte %0,%1" : 93143521Spjd : "r" (vsid), 94133182Spjd "r" (esid | (SLB_NUM_BOLTED + 1)) 95148779Spjd : "memory"); 96133182Spjd 97168419Spjd pr_info("%s accessing test address 0x%lx: 0x%lx\n", 98132311Salfred __func__, test_address, *test_ptr); 99132311Salfred 100132311Salfred preempt_enable(); 101132268Salfred} 102195405Sflz 103146960Simpstatic void lkdtm_PPC_SLB_MULTIHIT(void) 104148772Scperciva{ 105148871Scperciva if (!radix_enabled()) { 106161748Scperciva pr_info("Injecting SLB multihit errors\n"); 107221900Scperciva /* 108149464Semax * These need not be separate tests, And they do pretty 109149464Semax * much same thing. In any case we must recover from the 110149464Semax * errors introduced by these functions, machine would not 111149464Semax * survive these tests in case of failure to handle. 112149464Semax */ 113151618Sceri inject_vmalloc_slb_multihit(); 114200194Scperciva inject_kmalloc_slb_multihit(); 115200194Scperciva insert_dup_slb_entry_0(); 116204061Sedwin pr_info("Recovered from SLB multihit errors\n"); 117204061Sedwin } else { 118204061Sedwin pr_err("XFAIL: This test is for ppc64 and with hash mode MMU only\n"); 119204061Sedwin } 120204061Sedwin} 121204061Sedwin 122206455Sbmsstatic struct crashtype crashtypes[] = { 123230843Sjimharris CRASHTYPE(PPC_SLB_MULTIHIT), 124241828Seadler}; 125241828Seadler 126241891Seadlerstruct crashtype_category powerpc_crashtypes = { 127241828Seadler .crashtypes = crashtypes, 128247716Sjilles .len = ARRAY_SIZE(crashtypes), 129247716Sjilles}; 130247716Sjilles