Skip to content

Commit

Permalink
core: riscv: Support Privileged Access Never by 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 25, 2023
1 parent e582101 commit ad55610
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 ad55610

Please sign in to comment.