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.syntax unified
29
30/**
31 * int mmutest_arch_rodata_pnx(void) - Test that rodata section is mapped pnx
32 *
33 * Returns ERR_FAULT if rodata is not executable.
34 * Return 0 if rodata is executable.
35 */
36.section .rodata
37.align 2
38FUNCTION(mmutest_arch_rodata_pnx)
39	set_fault_handler	.Lmmutest_fault
40	mov	r0, #0
41
42	bx	lr
43
44/**
45 * int mmutest_arch_data_pnx(void) - Test that data section is mapped pnx
46 *
47 * Returns ERR_FAULT if data is not executable.
48 * Return 0 if data is executable.
49 */
50.section .data
51.align 2
52FUNCTION(mmutest_arch_data_pnx)
53	set_fault_handler	.Lmmutest_fault
54	mov	r0, #0
55
56	bx	lr
57.section .text
58
59/**
60 * int mmutest_arch_rodata_ro(void) - Test that rodata section is mapped read-only
61 *
62 * Returns ERR_FAULT if rodata is not writeable
63 * Returns 1 if write to rodata is silently dropped
64 * Returns 0 if rodata is writable
65 */
66FUNCTION(mmutest_arch_rodata_ro)
67	ldr	r0, =.Ltest_rodata_long
68	mov	r1, #0
69
70	set_fault_handler	.Lmmutest_fault
71	str	r1, [r0]
72
73	ldr	r0, [r0]
74	bx	lr
75
76.section .rodata
77.Ltest_rodata_long:
78	.long	0x1
79
80.section .text
81
82/**
83 * int mmutest_arch_store_uint32(uint32_t *ptr, bool user) - Test if ptr is writeable
84 * @ptr:  Memory location to test
85 * @user: Use unpriviledged store
86 *
87 * Returns ERR_FAULT if ptr is not writeable
88 * Returns ERR_GENERIC if ptr is not readable
89 * Returns 2 if write does not fault, but data is lost on readback from memory
90 * Returns 1 if write does not fault, but data is lost on readback from cache
91 * Returns 0 if ptr is writable
92 */
93FUNCTION(mmutest_arch_store_uint32)
94	cmp	r1, #0
95
96	set_fault_handler	.Lmmutest_setup_fault
97	ldreq	r1, [r0]
98
99	set_fault_handler	.Lmmutest_setup_fault
100	ldrtne	r1, [r0]
101
102	mvn	r1, r1
103
104	set_fault_handler	.Lmmutest_fault
105	streq	r1, [r0]
106
107	set_fault_handler	.Lmmutest_fault
108	strtne	r1, [r0]
109
110	dmb
111
112	ldr	r2, [r0]
113	cmp	r1, r2
114	movne	r0, #1
115	bxne	lr
116
117	push	{r0, r1, r2, lr}
118	mov	r1, #4
119	blx	arch_clean_invalidate_cache_range
120	pop	{r0, r1, r2, lr}
121
122	ldr	r2, [r0]
123	cmp	r1, r2
124	moveq	r0, #0
125	movne	r0, #2
126
127	bx	lr
128
129/**
130 * int mmutest_arch_nop(int ret) - Return ret
131 *
132 * Returns ret if run from executable page.
133 * Does not return if run from non-executable page.
134 */
135FUNCTION(mmutest_arch_nop)
136	bx	lr
137FUNCTION(mmutest_arch_nop_end)
138
139.Lmmutest_setup_fault:
140	mov	r0, #ERR_GENERIC
141	bx	lr
142
143.Lmmutest_fault:
144	mov	r0, #ERR_FAULT
145	bx	lr
146