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

Merge dev to qemu-cheri #259

Open
wants to merge 20 commits into
base: qemu-cheri
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
b168573
Fix program counter reported for Arm32 instruction tracing
arichardson Jun 18, 2024
90d7e31
Log changes to most Arm32 registers
arichardson May 31, 2024
c785485
Jenkinsfile: Pass unencoded branch name to cheribsdInfo
jrtc27 Jul 17, 2024
f1098ba
Jenkinsfile: Get latest release's version from cheribsdInfo
jrtc27 Jul 17, 2024
4e7686c
Add Thumb instruction tracing for Arm32
arichardson Jun 18, 2024
833dc72
tls: add macros for coroutine-safe TLS variables
stefanhaRH Feb 22, 2022
a3dabe5
rcu: use coroutine TLS macros
stefanhaRH Feb 22, 2022
0d10619
cpus: use coroutine TLS macros for iothread_locked
stefanhaRH Feb 22, 2022
034b9d3
coroutine-ucontext: use QEMU_DEFINE_STATIC_CO_TLS()
stefanhaRH Mar 7, 2022
d799e49
coroutine: use QEMU_DEFINE_STATIC_CO_TLS()
stefanhaRH Mar 7, 2022
6846c33
coroutine-win32: use QEMU_DEFINE_STATIC_CO_TLS()
stefanhaRH Mar 7, 2022
b731976
target/arm: Fix instruction tracing PC + disassembly for plain AArch64
jrtc27 Nov 6, 2024
15fef07
target/arm: Fix PC for AArch64 (including Morello) WFI trapping
jrtc27 Nov 6, 2024
6c09189
target/arm: Honor HCR_E2H and HCR_TGE in ats_write64()
Nov 1, 2022
acdce4e
Jenkinsfile: Add missing def
jrtc27 Dec 3, 2024
2fd35d0
Use upstream 'name' field for CSR names
bsdjhb Sep 3, 2024
8c25f30
riscv: Use all lower-case for SCR names in struct CPURISCVState
bsdjhb Sep 3, 2024
4695ba4
riscv: Rename get_csr to riscv_get_csr and move to cpu.h
bsdjhb Sep 3, 2024
a2452e0
gdb: Expose CHERI SCRs via the GDB stub
bsdjhb Sep 3, 2024
967e7a8
Enable CHERIv9 semantics by default
arichardson Oct 10, 2024
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: 5 additions & 3 deletions Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,13 @@ def addBootJobs(bootJobs, params, String qemuConfig, String architecture, String

def bootCheriBSDForAllArchitectures(params, String qemuConfig, boolean isDebug) {
stage("Boot CheriBSD (${qemuConfig})") {
bootJobs = [failFast: false]
def bootJobs = [failFast: false]
["riscv64", "riscv64-purecap", "aarch64", "morello-purecap"].each { String architecture ->
addBootJobs(bootJobs, params, qemuConfig, architecture, "main")
if (!isDebug) {
// For the non-ASAN build of QEMU we also boot the latest release
addBootJobs(bootJobs, params, qemuConfig, architecture, "releng%252F22.12", "-latest-release")
def latestRelease = cheribsdInfo.getReleasedVersions()[-1]
addBootJobs(bootJobs, params, qemuConfig, architecture, "releng/${latestRelease}", "-latest-release")
}
def targetBranch = env.CHANGE_TARGET ? env.CHANGE_TARGET : env.BRANCH_NAME;
if (targetBranch == 'dev') {
Expand Down Expand Up @@ -106,7 +107,8 @@ def bootCheriBSD(params, String qemuConfig, String stageSuffix, String archSuffi
def compressedDiskImage = "artifacts-${archSuffix}/cheribsd-${archSuffix}.img.xz"
dir (stageSuffix) {
sh "rm -rfv artifacts-${archSuffix}/cheribsd-*.img* artifacts-${archSuffix}/kernel*"
copyArtifacts projectName: "CheriBSD-pipeline/${cheribsdBranch}", filter: "${compressedDiskImage}, ${compressedKernel}",
def jenkinsBranchName = cheribsdBranch.replaceAll('/', '%2F')
copyArtifacts projectName: "CheriBSD-pipeline/${jenkinsBranchName}", filter: "${compressedDiskImage}, ${compressedKernel}",
target: '.', fingerprintArtifacts: false, flatten: false, selector: lastSuccessful()
}
def testExtraArgs = [
Expand Down
165 changes: 165 additions & 0 deletions include/qemu/coroutine-tls.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
/*
* QEMU Thread Local Storage for coroutines
*
* Copyright Red Hat
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
* See the COPYING.LIB file in the top-level directory.
*
* It is forbidden to access Thread Local Storage in coroutines because
* compiler optimizations may cause values to be cached across coroutine
* re-entry. Coroutines can run in more than one thread through the course of
* their life, leading bugs when stale TLS values from the wrong thread are
* used as a result of compiler optimization.
*
* An example is:
*
* ..code-block:: c
* :caption: A coroutine that may see the wrong TLS value
*
* static __thread AioContext *current_aio_context;
* ...
* static void coroutine_fn foo(void)
* {
* aio_notify(current_aio_context);
* qemu_coroutine_yield();
* aio_notify(current_aio_context); // <-- may be stale after yielding!
* }
*
* This header provides macros for safely defining variables in Thread Local
* Storage:
*
* ..code-block:: c
* :caption: A coroutine that safely uses TLS
*
* QEMU_DEFINE_STATIC_CO_TLS(AioContext *, current_aio_context)
* ...
* static void coroutine_fn foo(void)
* {
* aio_notify(get_current_aio_context());
* qemu_coroutine_yield();
* aio_notify(get_current_aio_context()); // <-- safe
* }
*/

#ifndef QEMU_COROUTINE_TLS_H
#define QEMU_COROUTINE_TLS_H

/*
* To stop the compiler from caching TLS values we define accessor functions
* with __attribute__((noinline)) plus asm volatile("") to prevent
* optimizations that override noinline.
*
* The compiler can still analyze noinline code and make optimizations based on
* that knowledge, so an inline asm output operand is used to prevent
* optimizations that make assumptions about the address of the TLS variable.
*
* This is fragile and ultimately needs to be solved by a mechanism that is
* guaranteed to work by the compiler (e.g. stackless coroutines), but for now
* we use this approach to prevent issues.
*/

/**
* QEMU_DECLARE_CO_TLS:
* @type: the variable's C type
* @var: the variable name
*
* Declare an extern variable in Thread Local Storage from a header file:
*
* .. code-block:: c
* :caption: Declaring an extern variable in Thread Local Storage
*
* QEMU_DECLARE_CO_TLS(int, my_count)
* ...
* int c = get_my_count();
* set_my_count(c + 1);
* *get_ptr_my_count() = 0;
*
* This is a coroutine-safe replacement for the __thread keyword and is
* equivalent to the following code:
*
* .. code-block:: c
* :caption: Declaring a TLS variable using __thread
*
* extern __thread int my_count;
* ...
* int c = my_count;
* my_count = c + 1;
* *(&my_count) = 0;
*/
#define QEMU_DECLARE_CO_TLS(type, var) \
__attribute__((noinline)) type get_##var(void); \
__attribute__((noinline)) void set_##var(type v); \
__attribute__((noinline)) type *get_ptr_##var(void);

/**
* QEMU_DEFINE_CO_TLS:
* @type: the variable's C type
* @var: the variable name
*
* Define a variable in Thread Local Storage that was previously declared from
* a header file with QEMU_DECLARE_CO_TLS():
*
* .. code-block:: c
* :caption: Defining a variable in Thread Local Storage
*
* QEMU_DEFINE_CO_TLS(int, my_count)
*
* This is a coroutine-safe replacement for the __thread keyword and is
* equivalent to the following code:
*
* .. code-block:: c
* :caption: Defining a TLS variable using __thread
*
* __thread int my_count;
*/
#define QEMU_DEFINE_CO_TLS(type, var) \
static __thread type co_tls_##var; \
type get_##var(void) { asm volatile(""); return co_tls_##var; } \
void set_##var(type v) { asm volatile(""); co_tls_##var = v; } \
type *get_ptr_##var(void) \
{ type *ptr = &co_tls_##var; asm volatile("" : "+rm" (ptr)); return ptr; }

/**
* QEMU_DEFINE_STATIC_CO_TLS:
* @type: the variable's C type
* @var: the variable name
*
* Define a static variable in Thread Local Storage:
*
* .. code-block:: c
* :caption: Defining a static variable in Thread Local Storage
*
* QEMU_DEFINE_STATIC_CO_TLS(int, my_count)
* ...
* int c = get_my_count();
* set_my_count(c + 1);
* *get_ptr_my_count() = 0;
*
* This is a coroutine-safe replacement for the __thread keyword and is
* equivalent to the following code:
*
* .. code-block:: c
* :caption: Defining a static TLS variable using __thread
*
* static __thread int my_count;
* ...
* int c = my_count;
* my_count = c + 1;
* *(&my_count) = 0;
*/
#define QEMU_DEFINE_STATIC_CO_TLS(type, var) \
static __thread type co_tls_##var; \
static __attribute__((noinline, unused)) \
type get_##var(void) \
{ asm volatile(""); return co_tls_##var; } \
static __attribute__((noinline, unused)) \
void set_##var(type v) \
{ asm volatile(""); co_tls_##var = v; } \
static __attribute__((noinline, unused)) \
type *get_ptr_##var(void) \
{ type *ptr = &co_tls_##var; asm volatile("" : "+rm" (ptr)); return ptr; }

#endif /* QEMU_COROUTINE_TLS_H */
7 changes: 4 additions & 3 deletions include/qemu/rcu.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "qemu/queue.h"
#include "qemu/atomic.h"
#include "qemu/sys_membarrier.h"
#include "qemu/coroutine-tls.h"

#ifdef __cplusplus
extern "C" {
Expand Down Expand Up @@ -68,11 +69,11 @@ struct rcu_reader_data {
QLIST_ENTRY(rcu_reader_data) node;
};

extern __thread struct rcu_reader_data rcu_reader;
QEMU_DECLARE_CO_TLS(struct rcu_reader_data, rcu_reader)

static inline void rcu_read_lock(void)
{
struct rcu_reader_data *p_rcu_reader = &rcu_reader;
struct rcu_reader_data *p_rcu_reader = get_ptr_rcu_reader();
unsigned ctr;

if (p_rcu_reader->depth++ > 0) {
Expand All @@ -88,7 +89,7 @@ static inline void rcu_read_lock(void)

static inline void rcu_read_unlock(void)
{
struct rcu_reader_data *p_rcu_reader = &rcu_reader;
struct rcu_reader_data *p_rcu_reader = get_ptr_rcu_reader();

assert(p_rcu_reader->depth != 0);
if (--p_rcu_reader->depth > 0) {
Expand Down
9 changes: 5 additions & 4 deletions softmmu/cpus.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "monitor/monitor.h"
#include "qemu/coroutine-tls.h"
#include "qapi/error.h"
#include "qapi/qapi-commands-machine.h"
#include "qapi/qapi-commands-misc.h"
Expand Down Expand Up @@ -472,11 +473,11 @@ bool qemu_in_vcpu_thread(void)
return current_cpu && qemu_cpu_is_self(current_cpu);
}

static __thread bool iothread_locked = false;
QEMU_DEFINE_STATIC_CO_TLS(bool, iothread_locked)

bool qemu_mutex_iothread_locked(void)
{
return iothread_locked;
return get_iothread_locked();
}

/*
Expand All @@ -489,13 +490,13 @@ void qemu_mutex_lock_iothread_impl(const char *file, int line)

g_assert(!qemu_mutex_iothread_locked());
bql_lock(&qemu_global_mutex, file, line);
iothread_locked = true;
set_iothread_locked(true);
}

void qemu_mutex_unlock_iothread(void)
{
g_assert(qemu_mutex_iothread_locked());
iothread_locked = false;
set_iothread_locked(false);
qemu_mutex_unlock(&qemu_global_mutex);
}

Expand Down
14 changes: 12 additions & 2 deletions target/arm/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,11 @@ typedef uint64_t AARCH_REG_TYPE;
#define N_BANK_WITH_RESTRICTED 4
#endif

extern const char * const arm32_regnames[16];
#ifdef TARGET_AARCH64
extern const char * const arm64_regnames[32];
#endif

typedef struct CPUARMState {
/* Regs for current mode. */
uint32_t regs[16];
Expand Down Expand Up @@ -3574,6 +3579,7 @@ typedef CPUARMState CPUArchState;
typedef ARMCPU ArchCPU;

#include "exec/cpu-all.h"
#include "exec/log_instr.h"
#include "cpu_cheri.h"
#include "cheri-lazy-capregs.h"

Expand All @@ -3594,11 +3600,15 @@ static inline void arm_set_xreg(CPUARMState *env, int regnum,
#ifdef TARGET_CHERI
update_capreg_to_intval(env, regnum, value);
#else
#ifdef TARGET_AARCH64
if (is_a64(env)) {
env->xregs[regnum] = value;
} else {
env->regs[regnum] = value;
qemu_log_instr_reg(env, arm64_regnames[regnum], value);
return;
}
#endif
env->regs[regnum] = value;
qemu_log_instr_reg(env, arm32_regnames[regnum], value);
#endif
}

Expand Down
38 changes: 30 additions & 8 deletions target/arm/helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -3826,20 +3826,29 @@ static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri,
MMUAccessType access_type = ri->opc2 & 1 ? MMU_DATA_STORE : MMU_DATA_LOAD;
ARMMMUIdx mmu_idx;
int secure = arm_is_secure_below_el3(env);
uint64_t hcr_el2 = arm_hcr_el2_eff(env);
bool regime_e20 = (hcr_el2 & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE);

switch (ri->opc2 & 6) {
case 0:
switch (ri->opc1) {
case 0: /* AT S1E1R, AT S1E1W, AT S1E1RP, AT S1E1WP */
if (ri->crm == 9 && (env->pstate & PSTATE_PAN)) {
mmu_idx = (secure ? ARMMMUIdx_Stage1_SE1_PAN
mmu_idx = regime_e20 ?
(secure ? ARMMMUIdx_SE20_2_PAN
: ARMMMUIdx_E20_2_PAN) :
(secure ? ARMMMUIdx_Stage1_SE1_PAN
: ARMMMUIdx_Stage1_E1_PAN);
} else {
mmu_idx = secure ? ARMMMUIdx_Stage1_SE1 : ARMMMUIdx_Stage1_E1;
mmu_idx = regime_e20 ?
(secure ? ARMMMUIdx_SE20_2 : ARMMMUIdx_E20_2) :
(secure ? ARMMMUIdx_Stage1_SE1 : ARMMMUIdx_Stage1_E1);
}
break;
case 4: /* AT S1E2R, AT S1E2W */
mmu_idx = secure ? ARMMMUIdx_SE2 : ARMMMUIdx_E2;
mmu_idx = hcr_el2 & HCR_E2H ?
(secure ? ARMMMUIdx_SE20_2 : ARMMMUIdx_E20_2) :
(secure ? ARMMMUIdx_SE2 : ARMMMUIdx_E2);
break;
case 6: /* AT S1E3R, AT S1E3W */
mmu_idx = ARMMMUIdx_SE3;
Expand All @@ -3849,13 +3858,19 @@ static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri,
}
break;
case 2: /* AT S1E0R, AT S1E0W */
mmu_idx = secure ? ARMMMUIdx_Stage1_SE0 : ARMMMUIdx_Stage1_E0;
mmu_idx = regime_e20 ?
(secure ? ARMMMUIdx_SE20_0 : ARMMMUIdx_E20_0) :
(secure ? ARMMMUIdx_Stage1_SE0 : ARMMMUIdx_Stage1_E0);
break;
case 4: /* AT S12E1R, AT S12E1W */
mmu_idx = secure ? ARMMMUIdx_SE10_1 : ARMMMUIdx_E10_1;
mmu_idx = regime_e20 ?
(secure ? ARMMMUIdx_SE20_2 : ARMMMUIdx_E20_2) :
(secure ? ARMMMUIdx_SE10_1 : ARMMMUIdx_E10_1);
break;
case 6: /* AT S12E0R, AT S12E0W */
mmu_idx = secure ? ARMMMUIdx_SE10_0 : ARMMMUIdx_E10_0;
mmu_idx = regime_e20 ?
(secure ? ARMMMUIdx_SE20_0 : ARMMMUIdx_E20_0) :
(secure ? ARMMMUIdx_SE10_0 : ARMMMUIdx_E10_0);
break;
default:
g_assert_not_reached();
Expand Down Expand Up @@ -14033,11 +14048,18 @@ void aarch64_sve_change_el(CPUARMState *env, int old_el,
#endif

#ifdef CONFIG_TCG_LOG_INSTR
void HELPER(arm_log_instr)(CPUARMState *env, target_ulong pc, uint32_t opcode)
void HELPER(arm_log_instr)(CPUARMState *env, uint64_t pc, uint32_t opcode,
uint32_t opcode_size)
{
if (qemu_log_instr_enabled(env)) {
qemu_log_instr_asid(env, cpu_get_asid(env, pc));
qemu_log_instr(env, pc, (char *)&opcode, sizeof(opcode));
if (opcode_size == 2) {
uint16_t opcode16 = opcode;
qemu_log_instr(env, pc, (char *)&opcode16, opcode_size);
} else {
tcg_debug_assert(opcode_size == 4);
qemu_log_instr(env, pc, (char *)&opcode, opcode_size);
}
}
}
#endif
2 changes: 1 addition & 1 deletion target/arm/helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -938,7 +938,7 @@ DEF_HELPER_FLAGS_5(neon_sqrdmulh_s, TCG_CALL_NO_RWG,
#endif

#ifdef CONFIG_TCG_LOG_INSTR
DEF_HELPER_FLAGS_3(arm_log_instr, TCG_CALL_NO_WG, void, env, tl, i32)
DEF_HELPER_FLAGS_4(arm_log_instr, TCG_CALL_NO_WG, void, env, i64, i32, i32)
#endif

#ifdef TARGET_CHERI
Expand Down
Loading
Loading