Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Backport v3.7-branch] arch: riscv: reset global pointer on exception #81370

Merged
merged 3 commits into from
Nov 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions arch/riscv/core/isr.S
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,14 @@ SECTION_FUNC(exception.entry, _isr_wrapper)
lr t0, ___cpu_t_current_OFFSET(s0)
lr tp, _thread_offset_to_tls(t0)

/* Make sure global pointer is sane */
#ifdef CONFIG_RISCV_GP
.option push
.option norelax
la gp, __global_pointer$
.option pop
#endif /* CONFIG_RISCV_GP */

/* Clear our per-thread usermode flag */
lui t0, %tprel_hi(is_user_mode)
add t0, t0, tp, %tprel_add(is_user_mode)
Expand Down
19 changes: 19 additions & 0 deletions include/zephyr/arch/riscv/reg.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright (c) 2024 Meta Platforms
*
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef ZEPHYR_INCLUDE_ZEPHYR_ARCH_RISCV_REG_H_
#define ZEPHYR_INCLUDE_ZEPHYR_ARCH_RISCV_REG_H_

#define reg_read(reg) \
({ \
register unsigned long __rv; \
__asm__ volatile("mv %0, " STRINGIFY(reg) : "=r"(__rv)); \
__rv; \
})

#define reg_write(reg, val) ({ __asm__("mv " STRINGIFY(reg) ", %0" : : "r"(val)); })

#endif /* ZEPHYR_INCLUDE_ZEPHYR_ARCH_RISCV_REG_H_ */
8 changes: 8 additions & 0 deletions tests/arch/riscv/userspace/riscv_gp/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# SPDX-License-Identifier: Apache-2.0

cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(riscv_gp)

FILE(GLOB app_sources src/*.c)
target_sources(app PRIVATE ${app_sources})
3 changes: 3 additions & 0 deletions tests/arch/riscv/userspace/riscv_gp/prj.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
CONFIG_ZTEST=y
CONFIG_RISCV_GP=y
CONFIG_TEST_USERSPACE=y
47 changes: 47 additions & 0 deletions tests/arch/riscv/userspace/riscv_gp/src/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright (c) 2024 Meta Platforms
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <stdio.h>

#include <zephyr/arch/riscv/reg.h>
#include <zephyr/kernel.h>
#include <zephyr/ztest.h>

#define ROGUE_USER_STACK_SZ 2048

static struct k_thread rogue_user_thread;
static K_THREAD_STACK_DEFINE(rogue_user_stack, ROGUE_USER_STACK_SZ);

static void rogue_user_fn(void *p1, void *p2, void *p3)
{
zassert_true(k_is_user_context());

reg_write(gp, 0xbad);
zassert_equal(reg_read(gp), 0xbad);
}

ZTEST_USER(riscv_gp, test_gp_value)
{
uintptr_t gp_val = reg_read(gp);
k_tid_t th;

zassert_not_equal(gp_val, 0);

th = k_thread_create(&rogue_user_thread, rogue_user_stack, ROGUE_USER_STACK_SZ,
rogue_user_fn, NULL, NULL, NULL, -1, K_USER, K_NO_WAIT);
zassert_ok(k_thread_join(th, K_FOREVER));

zassert_equal(reg_read(gp), gp_val, "`gp` corrupted by user thread");
}

static void *userspace_setup(void)
{
k_thread_access_grant(k_current_get(), &rogue_user_thread, &rogue_user_stack);

return NULL;
}

ZTEST_SUITE(riscv_gp, NULL, userspace_setup, NULL, NULL, NULL);
8 changes: 8 additions & 0 deletions tests/arch/riscv/userspace/riscv_gp/testcase.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
common:
ignore_faults: true
ignore_qemu_crash: true
tags: kernel riscv
platform_allow:
- qemu_riscv64
tests:
arch.riscv64.riscv_gp: {}