Skip to content

Commit 3b066d4

Browse files
Andrew Boieandrewboie
authored andcommitted
tests: userspace: fix 64-bit issues
In addition to not assuming all pointers fit in a u32_t, logic is added to find the privilege mode stack on x86_64 and several error messages now contain more information. Signed-off-by: Andrew Boie <[email protected]>
1 parent 3c456fc commit 3b066d4

File tree

2 files changed

+50
-32
lines changed

2 files changed

+50
-32
lines changed

tests/kernel/mem_protect/userspace/src/main.c

Lines changed: 49 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,18 @@ static void write_control(void)
114114
expect_fault = true;
115115
expected_reason = K_ERR_CPU_EXCEPTION;
116116
BARRIER();
117+
#ifdef CONFIG_X86_64
118+
__asm__ volatile (
119+
"movq $0xFFFFFFFF, %rax;\n\t"
120+
"movq %rax, %cr0;\n\t"
121+
);
122+
#else
117123
__asm__ volatile (
118124
"mov %cr0, %eax;\n\t"
119125
"and $0xfffeffff, %eax;\n\t"
120126
"mov %eax, %cr0;\n\t"
121127
);
128+
#endif
122129
zassert_unreachable("Write to control register did not fault");
123130
#elif defined(CONFIG_ARM)
124131
unsigned int msr_value;
@@ -162,11 +169,19 @@ static void disable_mmu_mpu(void)
162169
expect_fault = true;
163170
expected_reason = K_ERR_CPU_EXCEPTION;
164171
BARRIER();
172+
#ifdef CONFIG_X86_64
173+
__asm__ volatile (
174+
"movq %cr0, %rax;\n\t"
175+
"andq $0x7ffeffff, %rax;\n\t"
176+
"movq %rax, %cr0;\n\t"
177+
);
178+
#else
165179
__asm__ volatile (
166180
"mov %cr0, %eax;\n\t"
167181
"and $0x7ffeffff, %eax;\n\t"
168182
"mov %eax, %cr0;\n\t"
169183
);
184+
#endif
170185
#elif defined(CONFIG_ARM)
171186
expect_fault = true;
172187
expected_reason = K_ERR_CPU_EXCEPTION;
@@ -292,14 +307,8 @@ static void write_kernel_data(void)
292307
/*
293308
* volatile to avoid compiler mischief.
294309
*/
295-
K_APP_DMEM(part0) volatile int *priv_stack_ptr;
296-
#if defined(CONFIG_X86)
297-
/*
298-
* We can't inline this in the code or make it static
299-
* or local without triggering a warning on -Warray-bounds.
300-
*/
301-
K_APP_DMEM(part0) size_t size = MMU_PAGE_SIZE;
302-
#elif defined(CONFIG_ARC)
310+
K_APP_DMEM(part0) volatile char *priv_stack_ptr;
311+
#if defined(CONFIG_ARC)
303312
K_APP_DMEM(part0) s32_t size = (0 - CONFIG_PRIVILEGED_STACK_SIZE -
304313
STACK_GUARD_SIZE);
305314
#endif
@@ -312,21 +321,20 @@ K_APP_DMEM(part0) s32_t size = (0 - CONFIG_PRIVILEGED_STACK_SIZE -
312321
static void read_priv_stack(void)
313322
{
314323
/* Try to read from privileged stack. */
315-
#if defined(CONFIG_X86) || defined(CONFIG_ARC)
324+
#if defined(CONFIG_ARC)
316325
int s[1];
317326

318327
s[0] = 0;
319-
priv_stack_ptr = &s[0];
320-
priv_stack_ptr = (int *)((unsigned char *)priv_stack_ptr - size);
321-
#elif defined(CONFIG_ARM)
328+
priv_stack_ptr = (char *)&s[0] - size;
329+
#elif defined(CONFIG_ARM) || defined(CONFIG_X86)
322330
/* priv_stack_ptr set by test_main() */
323331
#else
324332
#error "Not implemented for this architecture"
325333
#endif
326334
expect_fault = true;
327335
expected_reason = K_ERR_CPU_EXCEPTION;
328336
BARRIER();
329-
printk("%d\n", *priv_stack_ptr);
337+
printk("%c\n", *priv_stack_ptr);
330338
zassert_unreachable("Read from privileged stack did not fault");
331339
}
332340

@@ -338,13 +346,12 @@ static void read_priv_stack(void)
338346
static void write_priv_stack(void)
339347
{
340348
/* Try to write to privileged stack. */
341-
#if defined(CONFIG_X86) || defined(CONFIG_ARC)
349+
#if defined(CONFIG_ARC)
342350
int s[1];
343351

344352
s[0] = 0;
345-
priv_stack_ptr = &s[0];
346-
priv_stack_ptr = (int *)((unsigned char *)priv_stack_ptr - size);
347-
#elif defined(CONFIG_ARM)
353+
priv_stack_ptr = (char *)&s[0] - size;
354+
#elif defined(CONFIG_ARM) || defined(CONFIG_X86)
348355
/* priv_stack_ptr set by test_main() */
349356
#else
350357
#error "Not implemented for this architecture"
@@ -654,8 +661,8 @@ static void access_other_memdomain(void)
654661

655662
#if defined(CONFIG_ARM)
656663
extern u8_t *z_priv_stack_find(void *obj);
657-
extern k_thread_stack_t ztest_thread_stack[];
658664
#endif
665+
extern k_thread_stack_t ztest_thread_stack[];
659666

660667
struct k_mem_domain add_thread_drop_dom;
661668
struct k_mem_domain add_part_drop_dom;
@@ -676,6 +683,8 @@ static void user_half(void *arg1, void *arg2, void *arg3)
676683
if (!expect_fault) {
677684
ztest_test_pass();
678685
} else {
686+
printk("Expecting a fatal error %d but succeeded instead\n",
687+
expected_reason);
679688
ztest_test_fail();
680689
}
681690
}
@@ -784,6 +793,8 @@ static void spawn_user(void)
784793

785794
k_sem_take(&uthread_end_sem, K_FOREVER);
786795
if (expect_fault) {
796+
printk("Expecting a fatal error %d but succeeded instead\n",
797+
expected_reason);
787798
ztest_test_fail();
788799
}
789800
}
@@ -892,18 +903,19 @@ struct foo {
892903

893904
struct foo stest_member_stack;
894905

895-
void z_impl_stack_info_get(u32_t *start_addr, u32_t *size)
906+
void z_impl_stack_info_get(char **start_addr, size_t *size)
896907
{
897-
*start_addr = k_current_get()->stack_info.start;
908+
*start_addr = (char *)k_current_get()->stack_info.start;
898909
*size = k_current_get()->stack_info.size;
899910
}
900911

901-
static inline void z_vrfy_stack_info_get(u32_t *start_addr, u32_t *size)
912+
static inline void z_vrfy_stack_info_get(char **start_addr,
913+
size_t *size)
902914
{
903-
Z_OOPS(Z_SYSCALL_MEMORY_WRITE(start_addr, sizeof(u32_t)));
904-
Z_OOPS(Z_SYSCALL_MEMORY_WRITE(size, sizeof(u32_t)));
915+
Z_OOPS(Z_SYSCALL_MEMORY_WRITE(start_addr, sizeof(uintptr_t)));
916+
Z_OOPS(Z_SYSCALL_MEMORY_WRITE(size, sizeof(size_t)));
905917

906-
z_impl_stack_info_get((u32_t *)start_addr, (u32_t *)size);
918+
z_impl_stack_info_get(start_addr, size);
907919
}
908920
#include <syscalls/stack_info_get_mrsh.c>
909921

@@ -927,10 +939,8 @@ void stack_buffer_scenarios(k_thread_stack_t *stack_obj, size_t obj_size)
927939

928940
expect_fault = false;
929941

930-
931942
/* Dump interesting information */
932-
933-
stack_info_get((u32_t *)&stack_start, (u32_t *)&stack_size);
943+
stack_info_get(&stack_start, &stack_size);
934944
printk(" - Thread reports buffer %p size %zu\n", stack_start,
935945
stack_size);
936946

@@ -987,9 +997,11 @@ void stack_buffer_scenarios(k_thread_stack_t *stack_obj, size_t obj_size)
987997
* and not the buffer.
988998
*/
989999
zassert_true(check_perms(obj_start - 1, 1, 0),
990-
"user mode access to memory before start of stack object");
1000+
"user mode access to memory %p before start of stack object",
1001+
obj_start - 1);
9911002
zassert_true(check_perms(obj_end, 1, 0),
992-
"user mode access past end of stack object");
1003+
"user mode access to memory %p past end of stack object",
1004+
obj_end);
9931005
}
9941006

9951007

@@ -1001,7 +1013,8 @@ void stack_buffer_scenarios(k_thread_stack_t *stack_obj, size_t obj_size)
10011013

10021014
if (arch_is_user_context()) {
10031015
zassert_true(stack_size <= obj_size - K_THREAD_STACK_RESERVED,
1004-
"bad stack size in thread struct");
1016+
"bad stack size %zu in thread struct",
1017+
stack_size);
10051018
}
10061019

10071020

@@ -1149,8 +1162,13 @@ void test_main(void)
11491162
k_mem_domain_add_thread(&dom0, k_current_get());
11501163

11511164
#if defined(CONFIG_ARM)
1152-
priv_stack_ptr = (int *)z_priv_stack_find(ztest_thread_stack);
1165+
priv_stack_ptr = (char *)z_priv_stack_find(ztest_thread_stack);
1166+
#elif defined(CONFIG_X86)
1167+
struct z_x86_thread_stack_header *hdr;
11531168

1169+
hdr = ((struct z_x86_thread_stack_header *)ztest_thread_stack);
1170+
priv_stack_ptr = (((char *)&hdr->privilege_stack) +
1171+
(sizeof(hdr->privilege_stack) - 1));
11541172
#endif
11551173
k_thread_access_grant(k_current_get(),
11561174
&kthread_thread, &kthread_stack,

tests/kernel/mem_protect/userspace/src/test_syscall.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#ifndef USERSPACE_TEST_SYSCALL_H
88
#define USERSPACE_TEST_SYSCALL_H
99

10-
__syscall void stack_info_get(u32_t *start_addr, u32_t *size);
10+
__syscall void stack_info_get(char **start_addr, size_t *size);
1111
__syscall int check_perms(void *addr, size_t size, int write);
1212
__syscall void missing_syscall(void);
1313

0 commit comments

Comments
 (0)