1/* 2 * Copyright (c) 2015, Google Inc. All rights reserved 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining 5 * a copy of this software and associated documentation files 6 * (the "Software"), to deal in the Software without restriction, 7 * including without limitation the rights to use, copy, modify, merge, 8 * publish, distribute, sublicense, and/or sell copies of the Software, 9 * and to permit persons to whom the Software is furnished to do so, 10 * subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be 13 * included in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 */ 23 24#include <asm.h> 25#include <arch/asm_macros.h> 26#include <err.h> 27 28/** 29 * int mmutest_arch_rodata_pnx(void) - Test that rodata section is mapped pnx 30 * 31 * Returns ERR_FAULT if rodata is not executable. 32 * Return 0 if rodata is executable. 33 */ 34.section .rodata 35.align 2 36 set_fault_handler .Lmmutest_fault 37FUNCTION(mmutest_arch_rodata_pnx) 38 mov x0, #0 39 40 ret 41 42/** 43 * int mmutest_arch_data_pnx(void) - Test that data section is mapped pnx 44 * 45 * Returns ERR_FAULT if data is not executable. 46 * Return 0 if data is executable. 47 */ 48.section .data 49.align 2 50 set_fault_handler .Lmmutest_fault 51FUNCTION(mmutest_arch_data_pnx) 52 mov x0, #0 53 54 ret 55.section .text 56 57/** 58 * int mmutest_arch_rodata_ro(void) - Test that rodata section is mapped read-only 59 * 60 * Returns ERR_FAULT if rodata is not writable 61 * Returns 1 if write to rodata is silently dropped 62 * Returns 0 if rodata is writable 63 */ 64FUNCTION(mmutest_arch_rodata_ro) 65 adrl x0, .Ltest_rodata_long 66 67 set_fault_handler .Lmmutest_fault 68 str wzr, [x0] 69 70 ldr w0, [x0] 71 ret 72 73.section .rodata 74.Ltest_rodata_long: 75 .long 0x1 76 77.section .text 78 79/** 80 * int mmutest_arch_store_uint32(uint32_t *ptr, bool user) - Test if ptr is writable 81 * @ptr: Memory location to test 82 * @user: Use unprivileged store 83 * 84 * Returns ERR_FAULT if ptr is not writable 85 * Returns ERR_GENERIC if ptr is not readable 86 * Returns 2 if write does not fault, but data is lost on readback from memory 87 * Returns 1 if write does not fault, but data is lost on readback from cache 88 * Returns 0 if ptr is writable 89 */ 90FUNCTION(mmutest_arch_store_uint32) 91 cbnz x1, .Lmmutest_arch_store_uint32_user 92 93 set_fault_handler .Lmmutest_setup_fault 94 ldr w3, [x0] 95 mvn w3, w3 96 97 set_fault_handler .Lmmutest_fault 98 str w3, [x0] 99 dmb sy 100 ldr w2, [x0] 101 102 b .Lmmutest_arch_store_uint32_str_done 103 104.Lmmutest_arch_store_uint32_user: 105 set_fault_handler .Lmmutest_setup_fault 106 ldtr w3, [x0] 107 mvn w3, w3 108 109 set_fault_handler .Lmmutest_fault 110 sttr w3, [x0] 111 dmb sy 112 ldtr w2, [x0] 113 114.Lmmutest_arch_store_uint32_str_done: 115 116 cmp w3, w2 117 bne .Lmmutest_arch_store_uint32_cache_read_mismatch 118 119 push x0, x1 120 push x3, x30 121 mov x1, #4 122 bl arch_clean_invalidate_cache_range 123 pop x3, x30 124 pop x0, x1 125 126 cbnz x1, .Lmmutest_arch_store_uint32_memory_reload_user 127 128 ldr w2, [x0] 129 b .Lmmutest_arch_store_uint32_memory_reload_done 130 131.Lmmutest_arch_store_uint32_memory_reload_user: 132 ldtr w2, [x0] 133 134.Lmmutest_arch_store_uint32_memory_reload_done: 135 cmp w3, w2 136 bne .Lmmutest_arch_store_uint32_memory_mismatch 137 138 mov x0, xzr 139 ret 140 141.Lmmutest_arch_store_uint32_cache_read_mismatch: 142 mov x0, #1 143 ret 144 145.Lmmutest_arch_store_uint32_memory_mismatch: 146 mov x0, #2 147 ret 148 149/** 150 * int mmutest_arch_nop(int ret) - Return ret 151 * 152 * Returns ret if run from executable page. 153 * Does not return if run from non-executable page. 154 */ 155FUNCTION(mmutest_arch_nop) 156 ret 157FUNCTION(mmutest_arch_nop_end) 158 159.Lmmutest_setup_fault: 160 mov x0, #ERR_GENERIC 161 ret 162 163.Lmmutest_fault: 164 mov x0, #ERR_FAULT 165 ret 166