From 10f4be4309667ba5fa42c52edbe5132607cbdcbb Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Wed, 29 Apr 2020 09:09:23 +1000 Subject: [PATCH] tests: Add a test for privileged instruction interrupts This adds a test that tries to execute various privileged instructions with MSR[PR] = 1. This also incidentally tests some of the MSR bit manipulations. Signed-off-by: Paul Mackerras --- tests/privileged/Makefile | 3 + tests/privileged/head.S | 91 ++++++++++++++++++ tests/privileged/powerpc.lds | 13 +++ tests/privileged/privileged.c | 152 ++++++++++++++++++++++++++++++ tests/test_privileged.bin | Bin 0 -> 9900 bytes tests/test_privileged.console_out | 6 ++ tests/update_console_tests | 2 +- 7 files changed, 266 insertions(+), 1 deletion(-) create mode 100644 tests/privileged/Makefile create mode 100644 tests/privileged/head.S create mode 100644 tests/privileged/powerpc.lds create mode 100644 tests/privileged/privileged.c create mode 100755 tests/test_privileged.bin create mode 100644 tests/test_privileged.console_out diff --git a/tests/privileged/Makefile b/tests/privileged/Makefile new file mode 100644 index 0000000..7c24998 --- /dev/null +++ b/tests/privileged/Makefile @@ -0,0 +1,3 @@ +TEST=privileged + +include ../Makefile.test diff --git a/tests/privileged/head.S b/tests/privileged/head.S new file mode 100644 index 0000000..9b76234 --- /dev/null +++ b/tests/privileged/head.S @@ -0,0 +1,91 @@ +/* Copyright 2013-2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define STACK_TOP 0x8000 + +/* Load an immediate 64-bit value into a register */ +#define LOAD_IMM64(r, e) \ + lis r,(e)@highest; \ + ori r,r,(e)@higher; \ + rldicr r,r, 32, 31; \ + oris r,r, (e)@h; \ + ori r,r, (e)@l; + + .section ".head","ax" + + /* + * Microwatt currently enters in LE mode at 0x0, so we don't need to + * do any endian fix ups + */ + . = 0 +.global _start +_start: + b boot_entry + +.global boot_entry +boot_entry: + /* setup stack */ + LOAD_IMM64(%r1, STACK_TOP - 0x100) + LOAD_IMM64(%r12, main) + mtctr %r12 + bctrl + attn // terminate on exit + b . + + /* Call a function with a specified MSR value */ + .global call_with_msr +call_with_msr: + mtsrr0 %r4 + mr %r12,%r4 + mtsrr1 %r5 + rfid + +#define EXCEPTION(nr) \ + .= nr ;\ + li %r3,nr ;\ + blr + + EXCEPTION(0x300) + EXCEPTION(0x380) + EXCEPTION(0x400) + EXCEPTION(0x480) + EXCEPTION(0x500) + EXCEPTION(0x600) + EXCEPTION(0x700) + EXCEPTION(0x800) + EXCEPTION(0x900) + EXCEPTION(0x980) + EXCEPTION(0xa00) + EXCEPTION(0xb00) + + /* + * System call - used to exit from tests where MSR[PR] + * may have been set. + */ + . = 0xc00 + blr + + EXCEPTION(0xd00) + EXCEPTION(0xe00) + EXCEPTION(0xe20) + EXCEPTION(0xe40) + EXCEPTION(0xe60) + EXCEPTION(0xe80) + EXCEPTION(0xf00) + EXCEPTION(0xf20) + EXCEPTION(0xf40) + EXCEPTION(0xf60) + EXCEPTION(0xf80) diff --git a/tests/privileged/powerpc.lds b/tests/privileged/powerpc.lds new file mode 100644 index 0000000..8c8c65b --- /dev/null +++ b/tests/privileged/powerpc.lds @@ -0,0 +1,13 @@ +SECTIONS +{ + _start = .; + . = 0; + .head : { + KEEP(*(.head)) + } + . = 0x2000; + .text : { *(.text) } + . = 0x4000; + .data : { *(.data) } + .bss : { *(.bss) } +} diff --git a/tests/privileged/privileged.c b/tests/privileged/privileged.c new file mode 100644 index 0000000..073dc07 --- /dev/null +++ b/tests/privileged/privileged.c @@ -0,0 +1,152 @@ +#include +#include +#include + +#include "console.h" + +#define MSR_EE 0x8000 +#define MSR_PR 0x4000 +#define MSR_IR 0x0020 +#define MSR_DR 0x0010 + +extern int call_with_msr(unsigned long arg, int (*fn)(unsigned long), unsigned long msr); + +#define SRR0 26 +#define SRR1 27 + +static inline unsigned long mfspr(int sprnum) +{ + long val; + + __asm__ volatile("mfspr %0,%1" : "=r" (val) : "i" (sprnum)); + return val; +} + +static inline void mtspr(int sprnum, unsigned long val) +{ + __asm__ volatile("mtspr %0,%1" : : "i" (sprnum), "r" (val)); +} + +void print_string(const char *str) +{ + for (; *str; ++str) + putchar(*str); +} + +void print_hex(unsigned long val, int ndigits) +{ + int i, x; + + for (i = (ndigits - 1) * 4; i >= 0; i -= 4) { + x = (val >> i) & 0xf; + if (x >= 10) + putchar(x + 'a' - 10); + else + putchar(x + '0'); + } +} + +// i < 100 +void print_test_number(int i) +{ + print_string("test "); + putchar(48 + i/10); + putchar(48 + i%10); + putchar(':'); +} + +int priv_fn_1(unsigned long x) +{ + __asm__ volatile("attn"); + __asm__ volatile("li 3,0; sc"); + return 0; +} + +int priv_fn_2(unsigned long x) +{ + __asm__ volatile("mfmsr 3"); + __asm__ volatile("sc"); + return 0; +} + +int priv_fn_3(unsigned long x) +{ + __asm__ volatile("mtmsrd 3"); + __asm__ volatile("li 3,0; sc"); + return 0; +} + +int priv_fn_4(unsigned long x) +{ + __asm__ volatile("rfid"); + __asm__ volatile("li 3,0; sc"); + return 0; +} + +int priv_fn_5(unsigned long x) +{ + __asm__ volatile("mfsrr0 3"); + __asm__ volatile("sc"); + return 0; +} + +int priv_fn_6(unsigned long x) +{ + __asm__ volatile("mtsrr0 3"); + __asm__ volatile("sc"); + return 0; +} + +int priv_test(int (*fn)(unsigned long)) +{ + unsigned long msr; + int vec; + + __asm__ volatile ("mtdec %0" : : "r" (0x7fffffff)); + __asm__ volatile ("mfmsr %0" : "=r" (msr)); + /* this should fail */ + vec = call_with_msr(0, fn, msr | MSR_PR); + if (vec != 0x700) + return vec | 1; + /* SRR1 should be set correctly */ + msr |= MSR_PR | MSR_EE | MSR_IR | MSR_DR; + if (mfspr(SRR1) != (msr | 0x40000)) + return 2; + return 0; +} + +int fail = 0; + +void do_test(int num, int (*fn)(unsigned long)) +{ + int ret; + + print_test_number(num); + ret = priv_test(fn); + if (ret == 0) { + print_string("PASS\r\n"); + } else { + fail = 1; + print_string("FAIL "); + print_hex(ret, 4); + print_string(" SRR0="); + print_hex(mfspr(SRR0), 16); + print_string(" SRR1="); + print_hex(mfspr(SRR1), 16); + print_string("\r\n"); + } +} + +int main(void) +{ + potato_uart_init(); + + do_test(1, priv_fn_1); + do_test(2, priv_fn_2); + do_test(3, priv_fn_3); + do_test(4, priv_fn_4); + do_test(5, priv_fn_5); + do_test(6, priv_fn_6); + + return fail; +} diff --git a/tests/test_privileged.bin b/tests/test_privileged.bin new file mode 100755 index 0000000000000000000000000000000000000000..5b8ce63ab5e843bf8ff40c84d36833ad52abd0ca GIT binary patch literal 9900 zcmeHNUuauZ9RA%TP13B38T6sr>24aqWfY7c<7Ua~z3ZQ)bZBWeCirr*w7B`CxQDdf z^j^bWlst3~z6h>9U3?JnVGjfU5D^A~FMbC>YJlYvDqdJjwny8e$9VpGAolVC|S=;+wA?mYU zCJ*r|V|za|^0AU(d%rNAB|0a(?uVNv?a*a8j88s?`8$kHUC#1%Xxr_< z`a7I|pu_nGJDh*Fv-~ZG@hRji|Gk6Aq28g+=I`WpABR?aKkVVoUVjQ7%wKL3SKGw( zHgT&>eE(uS2J4A7{M*FUHgUa8+-ehl42<29t^%$Ct^%$Ct^%$Ct^%$Ct^%$Ct^%$C zt^%$C9j3r0`{sUxr1c70xo>-ehWI^D{J*a&Xhw)0{e8qH-Dnk?k#vKPX%(-&C(t@> zd*)l#w!N)m5~*n_pHXa2&;XZh##U3{Rr!HMD-xL{qS#;$71abql?Y=KSucO@f%G-> zYfCO!5>aCvXtQ0dwU)~FFBqpH>|(v<%>Xlrj-jR{YTkOtCQj~rXAT8UT#y6txo!## zCg_UNL+`2=DV`ki$1XhZR55oLOO+dOA=ZE4a!kf9r9-rw3eM(~I`-2T`}6igGeM>j zB6e)ZpF4lOR(o>OG!m3kxUW$2ox*y&RqJ#9J(%k*=O%1s%BMN!eE$rv?pO|ZYd)1u9n7Muv`?IKWO(M`ktYyRA^&wXxImy?R=ky_mtbywf zFdrXT3a=AK4v)!*{Uqi&4=hVLQu7~&|105tNBFnU=lKcv7Y~>>pYICx+6Ur&8jfE~ zOW@k8UsK{3$8FC2Mc7Z)Y%lCd*xfbT2m4LfTVgK7bQkPJ*!OC-ANHrPe}OGSXU@}O zU0MhB`tGw^U0BINTi;VumhmnR=_JRqeMCu_;&VZ3VCyMTlN)Ep3(fxl?2f}2OuEL6H5cAl0=8D1h*ui7Z)W)7Dtp4$w7)w~6jaS~No-@_CiqASGe}4C# zyK4$#-==y8R?Yf;P%B@fe*^n%q4W`S+r-WHfwH}SPjj5lGQ$O;_n+?(`SB#r%}>N0 z;map*b@uJ6GTKRPdirpPXiOVF$8C9fYAONsc>4lc9^)4@5tlSSMZUZy_4i1^2Ysph zH)C=&EPR9Le-Gc$2A_)lk4<^!;ahI8}PK&Qw~&y#pUV)M%tzqa|rL zoH(K_jD*6Z-SumSh>jz43-?i+j(MIpio6@1C26!F^NvU*UULoiW#n?a-P|#eJIRY8 zm1KlKoxVh#g+7go_>wfShs$dvkkf~QkK^x~Uj})@e(f$M$n|*@d7mKfW1cq}mcih) JFpU6-=wFGzEoA@z literal 0 HcmV?d00001 diff --git a/tests/test_privileged.console_out b/tests/test_privileged.console_out new file mode 100644 index 0000000..a49bb9b --- /dev/null +++ b/tests/test_privileged.console_out @@ -0,0 +1,6 @@ +test 01:PASS +test 02:PASS +test 03:PASS +test 04:PASS +test 05:PASS +test 06:PASS diff --git a/tests/update_console_tests b/tests/update_console_tests index c17c12b..bd012d9 100755 --- a/tests/update_console_tests +++ b/tests/update_console_tests @@ -3,7 +3,7 @@ # Script to update console related tests from source # -for i in sc illegal decrementer ; do +for i in sc illegal decrementer privileged ; do cd $i make cd -