Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 
0003 #include "lkdtm.h"
0004 #include <linux/slab.h>
0005 #include <linux/vmalloc.h>
0006 #include <asm/mmu.h>
0007 
0008 /* Inserts new slb entries */
0009 static void insert_slb_entry(unsigned long p, int ssize, int page_size)
0010 {
0011     unsigned long flags;
0012 
0013     flags = SLB_VSID_KERNEL | mmu_psize_defs[page_size].sllp;
0014     preempt_disable();
0015 
0016     asm volatile("slbmte %0,%1" :
0017              : "r" (mk_vsid_data(p, ssize, flags)),
0018                "r" (mk_esid_data(p, ssize, SLB_NUM_BOLTED))
0019              : "memory");
0020 
0021     asm volatile("slbmte %0,%1" :
0022             : "r" (mk_vsid_data(p, ssize, flags)),
0023               "r" (mk_esid_data(p, ssize, SLB_NUM_BOLTED + 1))
0024             : "memory");
0025     preempt_enable();
0026 }
0027 
0028 /* Inject slb multihit on vmalloc-ed address i.e 0xD00... */
0029 static int inject_vmalloc_slb_multihit(void)
0030 {
0031     char *p;
0032 
0033     p = vmalloc(PAGE_SIZE);
0034     if (!p)
0035         return -ENOMEM;
0036 
0037     insert_slb_entry((unsigned long)p, MMU_SEGSIZE_1T, mmu_vmalloc_psize);
0038     /*
0039      * This triggers exception, If handled correctly we must recover
0040      * from this error.
0041      */
0042     p[0] = '!';
0043     vfree(p);
0044     return 0;
0045 }
0046 
0047 /* Inject slb multihit on kmalloc-ed address i.e 0xC00... */
0048 static int inject_kmalloc_slb_multihit(void)
0049 {
0050     char *p;
0051 
0052     p = kmalloc(2048, GFP_KERNEL);
0053     if (!p)
0054         return -ENOMEM;
0055 
0056     insert_slb_entry((unsigned long)p, MMU_SEGSIZE_1T, mmu_linear_psize);
0057     /*
0058      * This triggers exception, If handled correctly we must recover
0059      * from this error.
0060      */
0061     p[0] = '!';
0062     kfree(p);
0063     return 0;
0064 }
0065 
0066 /*
0067  * Few initial SLB entries are bolted. Add a test to inject
0068  * multihit in bolted entry 0.
0069  */
0070 static void insert_dup_slb_entry_0(void)
0071 {
0072     unsigned long test_address = PAGE_OFFSET, *test_ptr;
0073     unsigned long esid, vsid;
0074     unsigned long i = 0;
0075 
0076     test_ptr = (unsigned long *)test_address;
0077     preempt_disable();
0078 
0079     asm volatile("slbmfee  %0,%1" : "=r" (esid) : "r" (i));
0080     asm volatile("slbmfev  %0,%1" : "=r" (vsid) : "r" (i));
0081 
0082     /* for i !=0 we would need to mask out the old entry number */
0083     asm volatile("slbmte %0,%1" :
0084             : "r" (vsid),
0085               "r" (esid | SLB_NUM_BOLTED)
0086             : "memory");
0087 
0088     asm volatile("slbmfee  %0,%1" : "=r" (esid) : "r" (i));
0089     asm volatile("slbmfev  %0,%1" : "=r" (vsid) : "r" (i));
0090 
0091     /* for i !=0 we would need to mask out the old entry number */
0092     asm volatile("slbmte %0,%1" :
0093             : "r" (vsid),
0094               "r" (esid | (SLB_NUM_BOLTED + 1))
0095             : "memory");
0096 
0097     pr_info("%s accessing test address 0x%lx: 0x%lx\n",
0098         __func__, test_address, *test_ptr);
0099 
0100     preempt_enable();
0101 }
0102 
0103 static void lkdtm_PPC_SLB_MULTIHIT(void)
0104 {
0105     if (!radix_enabled()) {
0106         pr_info("Injecting SLB multihit errors\n");
0107         /*
0108          * These need not be separate tests, And they do pretty
0109          * much same thing. In any case we must recover from the
0110          * errors introduced by these functions, machine would not
0111          * survive these tests in case of failure to handle.
0112          */
0113         inject_vmalloc_slb_multihit();
0114         inject_kmalloc_slb_multihit();
0115         insert_dup_slb_entry_0();
0116         pr_info("Recovered from SLB multihit errors\n");
0117     } else {
0118         pr_err("XFAIL: This test is for ppc64 and with hash mode MMU only\n");
0119     }
0120 }
0121 
0122 static struct crashtype crashtypes[] = {
0123     CRASHTYPE(PPC_SLB_MULTIHIT),
0124 };
0125 
0126 struct crashtype_category powerpc_crashtypes = {
0127     .crashtypes = crashtypes,
0128     .len        = ARRAY_SIZE(crashtypes),
0129 };