Skip to content

Commit

Permalink
core: riscv: Support Privileged Access Never by CSR status.SUM bit
Browse files Browse the repository at this point in the history
The SUM (Supervisor User Memory access) bit modifies the privilege with
which S-mode loads and stores the user virtual memory. When SUM bit is
0, S-mode accesses to pages whose U bit of corresponding PTE is set will
fault. When SUM bit is 1, these accesses are permitted.

When CFG_PAN is disabled in RISC-V architecture, the status.SUM bit is
initialized as 1 by default. Therefore all accesses to user pages will
succeed. When CFG_PAN is enabled, the status.SUM bit is initialized as
0, and only set to 1 when kernel needs to access user pages.

Signed-off-by: Alvin Chang <alvinga@andestech.com>
Tested-by: Marouene Boubakri <marouene.boubakri@nxp.com>
  • Loading branch information
gagachang committed Aug 30, 2023
1 parent e582101 commit 9a208cb
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 9 deletions.
16 changes: 15 additions & 1 deletion core/arch/riscv/include/kernel/user_access_arch.h
Original file line number Diff line number Diff line change
@@ -1,15 +1,29 @@
/* SPDX-License-Identifier: BSD-2-Clause */
/*
* Copyright (c) 2023 Andes Technology Corporation
* Copyright (c) 2023, Amazon.com Inc. or its affiliates. All rights Reserved.
*/

#ifndef __KERNEL_USER_ACCESS_ARCH_H
#define __KERNEL_USER_ACCESS_ARCH_H

#include <riscv.h>

#ifdef CFG_PAN
/* Enter a section where user mode access is temporarily enabled. */
static inline void enter_user_access(void) {}
static inline void enter_user_access(void)
{
set_csr(CSR_XSTATUS, CSR_XSTATUS_SUM);
}

/* Exit from the section where user mode access was temporarily enabled. */
static inline void exit_user_access(void)
{
clear_csr(CSR_XSTATUS, CSR_XSTATUS_SUM);
}
#else
static inline void enter_user_access(void) {}
static inline void exit_user_access(void) {}
#endif /* CFG_PAN */

#endif /* __KERNEL_USER_ACCESS_ARCH_H */
27 changes: 21 additions & 6 deletions core/arch/riscv/kernel/arch_scall.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <kernel/scall.h>
#include <kernel/thread.h>
#include <kernel/trace_ta.h>
#include <kernel/user_access.h>
#include <kernel/user_ta.h>
#include <mm/vm.h>
#include <riscv.h>
Expand All @@ -23,15 +24,29 @@
static void save_panic_regs_rv_ta(struct thread_specific_data *tsd,
unsigned long *pushed)
{
tsd->abort_regs = (struct thread_abort_regs){
.sp = (unsigned long)pushed,
TEE_Result res = TEE_SUCCESS;
unsigned long s0 = 0;
unsigned long epc = 0;
#if defined(RV32)
.s0 = pushed[2],
.epc = pushed[3],
unsigned long *stack_s0 = &pushed[2];
unsigned long *stack_epc = &pushed[3];
#elif defined(RV64)
.s0 = pushed[0],
.epc = pushed[1],
unsigned long *stack_s0 = &pushed[0];
unsigned long *stack_epc = &pushed[1];
#endif

res = GET_USER_SCALAR(s0, stack_s0);
if (res)
s0 = 0;

res = GET_USER_SCALAR(epc, stack_epc);
if (res)
epc = 0;

tsd->abort_regs = (struct thread_abort_regs){
.sp = (unsigned long)pushed,
.s0 = s0,
.epc = epc,
};
}

Expand Down
7 changes: 6 additions & 1 deletion core/arch/riscv/kernel/thread_arch.c
Original file line number Diff line number Diff line change
Expand Up @@ -565,8 +565,13 @@ void thread_init_per_cpu(void)
* and kernel traps.
*/
write_csr(CSR_XSCRATCH, 0);
/* Allow access to user pages */
#ifndef CFG_PAN
/*
* Allow access to user pages. When CFG_PAN is enabled, the SUM bit will
* be set and clear at runtime when necessary.
*/
set_csr(CSR_XSTATUS, CSR_XSTATUS_SUM);
#endif
}

static void set_ctx_regs(struct thread_ctx_regs *regs, unsigned long a0,
Expand Down
3 changes: 2 additions & 1 deletion mk/config.mk
Original file line number Diff line number Diff line change
Expand Up @@ -929,9 +929,10 @@ endif

# Privileged Access Never (PAN, part of the ARMv8.1 Extensions) can be
# used to restrict accesses to unprivileged memory from privileged mode.
# For RISC-V architecture, CSR {m|s}status.SUM bit is used to implement PAN.
CFG_PAN ?= n

$(eval $(call cfg-depends-all,CFG_PAN,CFG_ARM64_core))
$(eval $(call cfg-depends-one,CFG_PAN,CFG_ARM64_core CFG_RV64_core CFG_RV32_core))

# CFG_CORE_ASYNC_NOTIF is defined by the platform to enable support
# for sending asynchronous notifications to normal world. Note that an
Expand Down

0 comments on commit 9a208cb

Please sign in to comment.