maintainer updates for May (testing, plugins)

- expose ~/.cache/qemu to container builds
   - disable debug info in CI
   - allow boot.S to handle target el mode selection
   - new arguments for ips plugin
   - cleanup assets in size_memop
   - fix include guard in gdbstub
   - introduce qGDBServerVersion gdbstub query
   - update gdb aarch64-core.xml to support bitfields
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCgAdFiEEZoWumedRZ7yvyN81+9DbCVqeKkQFAmhEXc4ACgkQ+9DbCVqe
 KkT3vwf9GtMoVDBWqWHwdV6H3rblP0k3mkApY4pTkFFSL93qApDK1gAKoklymPHJ
 6agAWn/MmpqguB7yn7TnBEiJyW9CEq0DeWTz9ivPPh5vfm/2MMaXinVd4yH+GbTL
 uTuJg4EeRcSj8q4N4h+gROSHkH3mVOe+JlyakRKZ/PZChqjY1WRC/Hm2QdHojxlS
 xQBZe4Nip/mafm4yAlnyRVRbaSctmc3/xE/MomkVT+8JMdVt6yWE0HT/nIEFW6/6
 psHoiV4XfROIWj5qMAWHVLekDrsqxJx8uiGv9o3+zKdhDhRZw3Oa5EE5N/oE8KmM
 0s/9usRvtVD0kPh9YTfjEHWHkbPadA==
 =X63M
 -----END PGP SIGNATURE-----

Merge tag 'pull-10.1-maintainer-may-2025-070625-1' of https://gitlab.com/stsquad/qemu into staging

maintainer updates for May (testing, plugins)

  - expose ~/.cache/qemu to container builds
  - disable debug info in CI
  - allow boot.S to handle target el mode selection
  - new arguments for ips plugin
  - cleanup assets in size_memop
  - fix include guard in gdbstub
  - introduce qGDBServerVersion gdbstub query
  - update gdb aarch64-core.xml to support bitfields

# -----BEGIN PGP SIGNATURE-----
#
# iQEzBAABCgAdFiEEZoWumedRZ7yvyN81+9DbCVqeKkQFAmhEXc4ACgkQ+9DbCVqe
# KkT3vwf9GtMoVDBWqWHwdV6H3rblP0k3mkApY4pTkFFSL93qApDK1gAKoklymPHJ
# 6agAWn/MmpqguB7yn7TnBEiJyW9CEq0DeWTz9ivPPh5vfm/2MMaXinVd4yH+GbTL
# uTuJg4EeRcSj8q4N4h+gROSHkH3mVOe+JlyakRKZ/PZChqjY1WRC/Hm2QdHojxlS
# xQBZe4Nip/mafm4yAlnyRVRbaSctmc3/xE/MomkVT+8JMdVt6yWE0HT/nIEFW6/6
# psHoiV4XfROIWj5qMAWHVLekDrsqxJx8uiGv9o3+zKdhDhRZw3Oa5EE5N/oE8KmM
# 0s/9usRvtVD0kPh9YTfjEHWHkbPadA==
# =X63M
# -----END PGP SIGNATURE-----
# gpg: Signature made Sat 07 Jun 2025 11:42:06 EDT
# gpg:                using RSA key 6685AE99E75167BCAFC8DF35FBD0DB095A9E2A44
# gpg: Good signature from "Alex Bennée (Master Work Key) <alex.bennee@linaro.org>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 6685 AE99 E751 67BC AFC8  DF35 FBD0 DB09 5A9E 2A44

* tag 'pull-10.1-maintainer-may-2025-070625-1' of https://gitlab.com/stsquad/qemu:
  gdbstub: update aarch64-core.xml
  gdbstub: Implement qGDBServerVersion packet
  gdbstub: assert earlier in handle_read_all_regs
  include/gdbstub: fix include guard in commands.h
  include/exec: fix assert in size_memop
  contrib/plugins: allow setting of instructions per quantum
  contrib/plugins: add a scaling factor to the ips arg
  tests/qtest: Avoid unaligned access in IGB test
  tests/tcg: make aarch64 boot.S handle different starting modes
  gitlab: disable debug info on CI builds
  tests/docker: expose $HOME/.cache/qemu as docker volume

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Stefan Hajnoczi 2025-06-07 15:08:54 -04:00
commit bc98ffdc75
11 changed files with 300 additions and 20 deletions

View file

@ -24,6 +24,7 @@
- ccache --zero-stats - ccache --zero-stats
- section_start configure "Running configure" - section_start configure "Running configure"
- ../configure --enable-werror --disable-docs --enable-fdt=system - ../configure --enable-werror --disable-docs --enable-fdt=system
--disable-debug-info
${TARGETS:+--target-list="$TARGETS"} ${TARGETS:+--target-list="$TARGETS"}
$CONFIGURE_ARGS || $CONFIGURE_ARGS ||
{ cat config.log meson-logs/meson-log.txt && exit 1; } { cat config.log meson-logs/meson-log.txt && exit 1; }

View file

@ -129,20 +129,62 @@ static void plugin_exit(qemu_plugin_id_t id, void *udata)
qemu_plugin_scoreboard_free(vcpus); qemu_plugin_scoreboard_free(vcpus);
} }
typedef struct {
const char *suffix;
unsigned long multipler;
} ScaleEntry;
/* a bit like units.h but not binary */
static const ScaleEntry scales[] = {
{ "k", 1000 },
{ "m", 1000 * 1000 },
{ "g", 1000 * 1000 * 1000 },
};
QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id, QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id,
const qemu_info_t *info, int argc, const qemu_info_t *info, int argc,
char **argv) char **argv)
{ {
bool ipq_set = false;
for (int i = 0; i < argc; i++) { for (int i = 0; i < argc; i++) {
char *opt = argv[i]; char *opt = argv[i];
g_auto(GStrv) tokens = g_strsplit(opt, "=", 2); g_auto(GStrv) tokens = g_strsplit(opt, "=", 2);
if (g_strcmp0(tokens[0], "ips") == 0) { if (g_strcmp0(tokens[0], "ips") == 0) {
max_insn_per_second = g_ascii_strtoull(tokens[1], NULL, 10); char *endptr = NULL;
max_insn_per_second = g_ascii_strtoull(tokens[1], &endptr, 10);
if (!max_insn_per_second && errno) { if (!max_insn_per_second && errno) {
fprintf(stderr, "%s: couldn't parse %s (%s)\n", fprintf(stderr, "%s: couldn't parse %s (%s)\n",
__func__, tokens[1], g_strerror(errno)); __func__, tokens[1], g_strerror(errno));
return -1; return -1;
} }
if (endptr && *endptr != 0) {
g_autofree gchar *lower = g_utf8_strdown(endptr, -1);
unsigned long scale = 0;
for (int j = 0; j < G_N_ELEMENTS(scales); j++) {
if (g_strcmp0(lower, scales[j].suffix) == 0) {
scale = scales[j].multipler;
break;
}
}
if (scale) {
max_insn_per_second *= scale;
} else {
fprintf(stderr, "bad suffix: %s\n", endptr);
return -1;
}
}
} else if (g_strcmp0(tokens[0], "ipq") == 0) {
max_insn_per_quantum = g_ascii_strtoull(tokens[1], NULL, 10);
if (!max_insn_per_quantum) {
fprintf(stderr, "bad ipq value: %s\n", tokens[0]);
return -1;
}
ipq_set = true;
} else { } else {
fprintf(stderr, "option parsing failed: %s\n", opt); fprintf(stderr, "option parsing failed: %s\n", opt);
return -1; return -1;
@ -150,7 +192,10 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id,
} }
vcpus = qemu_plugin_scoreboard_new(sizeof(vCPUTime)); vcpus = qemu_plugin_scoreboard_new(sizeof(vCPUTime));
if (!ipq_set) {
max_insn_per_quantum = max_insn_per_second / NUM_TIME_UPDATE_PER_SEC; max_insn_per_quantum = max_insn_per_second / NUM_TIME_UPDATE_PER_SEC;
}
if (max_insn_per_quantum == 0) { if (max_insn_per_quantum == 0) {
fprintf(stderr, "minimum of %d instructions per second needed\n", fprintf(stderr, "minimum of %d instructions per second needed\n",

View file

@ -811,6 +811,10 @@ This plugin can limit the number of Instructions Per Second that are executed::
* - ips=N * - ips=N
- Maximum number of instructions per cpu that can be executed in one second. - Maximum number of instructions per cpu that can be executed in one second.
The plugin will sleep when the given number of instructions is reached. The plugin will sleep when the given number of instructions is reached.
* - ipq=N
- Instructions per quantum. How many instructions before we re-calculate time.
The lower the number the more accurate time will be, but the less efficient the plugin.
Defaults to ips/10
Other emulation features Other emulation features
------------------------ ------------------------

View file

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<!-- Copyright (C) 2009-2012 Free Software Foundation, Inc. <!-- Copyright (C) 2009-2025 Free Software Foundation, Inc.
Contributed by ARM Ltd. Contributed by ARM Ltd.
Copying and distribution of this file, with or without modification, Copying and distribution of this file, with or without modification,
@ -42,5 +42,53 @@
<reg name="sp" bitsize="64" type="data_ptr"/> <reg name="sp" bitsize="64" type="data_ptr"/>
<reg name="pc" bitsize="64" type="code_ptr"/> <reg name="pc" bitsize="64" type="code_ptr"/>
<reg name="cpsr" bitsize="32"/>
<flags id="cpsr_flags" size="4">
<!-- Stack Pointer. -->
<field name="SP" start="0" end="0"/>
<!-- Exception Level. -->
<field name="EL" start="2" end="3"/>
<!-- Execution state. -->
<field name="nRW" start="4" end="4"/>
<!-- FIQ interrupt mask. -->
<field name="F" start="6" end="6"/>
<!-- IRQ interrupt mask. -->
<field name="I" start="7" end="7"/>
<!-- SError interrupt mask. -->
<field name="A" start="8" end="8"/>
<!-- Debug exception mask. -->
<field name="D" start="9" end="9"/>
<!-- ARMv8.5-A: Branch Target Identification BTYPE. -->
<field name="BTYPE" start="10" end="11"/>
<!-- ARMv8.0-A: Speculative Store Bypass. -->
<field name="SSBS" start="12" end="12"/>
<!-- Illegal Execution state. -->
<field name="IL" start="20" end="20"/>
<!-- Software Step. -->
<field name="SS" start="21" end="21"/>
<!-- ARMv8.1-A: Privileged Access Never. -->
<field name="PAN" start="22" end="22"/>
<!-- ARMv8.2-A: User Access Override. -->
<field name="UAO" start="23" end="23"/>
<!-- ARMv8.4-A: Data Independent Timing. -->
<field name="DIT" start="24" end="24"/>
<!-- ARMv8.5-A: Tag Check Override. -->
<field name="TCO" start="25" end="25"/>
<!-- Overflow Condition flag. -->
<field name="V" start="28" end="28"/>
<!-- Carry Condition flag. -->
<field name="C" start="29" end="29"/>
<!-- Zero Condition flag. -->
<field name="Z" start="30" end="30"/>
<!-- Negative Condition flag. -->
<field name="N" start="31" end="31"/>
</flags>
<reg name="cpsr" bitsize="32" type="cpsr_flags"/>
</feature> </feature>

View file

@ -28,6 +28,7 @@
#include "qemu/cutils.h" #include "qemu/cutils.h"
#include "qemu/module.h" #include "qemu/module.h"
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "qemu/target-info.h"
#include "trace.h" #include "trace.h"
#include "exec/gdbstub.h" #include "exec/gdbstub.h"
#include "gdbstub/commands.h" #include "gdbstub/commands.h"
@ -1343,8 +1344,8 @@ static void handle_read_all_regs(GArray *params, void *user_ctx)
len += gdb_read_register(gdbserver_state.g_cpu, len += gdb_read_register(gdbserver_state.g_cpu,
gdbserver_state.mem_buf, gdbserver_state.mem_buf,
reg_id); reg_id);
}
g_assert(len == gdbserver_state.mem_buf->len); g_assert(len == gdbserver_state.mem_buf->len);
}
gdb_memtohex(gdbserver_state.str_buf, gdbserver_state.mem_buf->data, len); gdb_memtohex(gdbserver_state.str_buf, gdbserver_state.mem_buf->data, len);
gdb_put_strbuf(); gdb_put_strbuf();
@ -1597,6 +1598,18 @@ static void handle_query_threads(GArray *params, void *user_ctx)
gdbserver_state.query_cpu = gdb_next_attached_cpu(gdbserver_state.query_cpu); gdbserver_state.query_cpu = gdb_next_attached_cpu(gdbserver_state.query_cpu);
} }
static void handle_query_gdb_server_version(GArray *params, void *user_ctx)
{
#if defined(CONFIG_USER_ONLY)
g_string_printf(gdbserver_state.str_buf, "name:qemu-%s;version:%s;",
target_name(), QEMU_VERSION);
#else
g_string_printf(gdbserver_state.str_buf, "name:qemu-system-%s;version:%s;",
target_name(), QEMU_VERSION);
#endif
gdb_put_strbuf();
}
static void handle_query_first_threads(GArray *params, void *user_ctx) static void handle_query_first_threads(GArray *params, void *user_ctx)
{ {
gdbserver_state.query_cpu = gdb_first_attached_cpu(); gdbserver_state.query_cpu = gdb_first_attached_cpu();
@ -1842,6 +1855,10 @@ static const GdbCmdParseEntry gdb_gen_query_table[] = {
.handler = handle_query_threads, .handler = handle_query_threads,
.cmd = "sThreadInfo", .cmd = "sThreadInfo",
}, },
{
.handler = handle_query_gdb_server_version,
.cmd = "GDBServerVersion",
},
{ {
.handler = handle_query_first_threads, .handler = handle_query_first_threads,
.cmd = "fThreadInfo", .cmd = "fThreadInfo",

View file

@ -162,8 +162,8 @@ static inline unsigned memop_size(MemOp op)
static inline MemOp size_memop(unsigned size) static inline MemOp size_memop(unsigned size)
{ {
#ifdef CONFIG_DEBUG_TCG #ifdef CONFIG_DEBUG_TCG
/* Power of 2 up to 8. */ /* Power of 2 up to 1024 */
assert((size & (size - 1)) == 0 && size >= 1 && size <= 8); assert(is_power_of_2(size) && size >= 1 && size <= (1 << MO_SIZE));
#endif #endif
return (MemOp)ctz32(size); return (MemOp)ctz32(size);
} }

View file

@ -1,5 +1,5 @@
#ifndef GDBSTUB_COMMANDS_H #ifndef GDBSTUB_COMMANDS_H
#define GDBSTUB #define GDBSTUB_COMMANDS_H
typedef void (*GdbCmdHandler)(GArray *params, void *user_ctx); typedef void (*GdbCmdHandler)(GArray *params, void *user_ctx);

View file

@ -185,8 +185,10 @@ docker:
docker-help: docker docker-help: docker
# Where QEMU caches build artefacts
DOCKER_QEMU_CACHE_DIR := $$HOME/.cache/qemu
# Use a global constant ccache directory to speed up repetitive builds # Use a global constant ccache directory to speed up repetitive builds
DOCKER_CCACHE_DIR := $$HOME/.cache/qemu-docker-ccache DOCKER_QEMU_CCACHE_DIR := DOCKER_QEMU_CACHE_DIR/docker-ccache
# This rule if for directly running against an arbitrary docker target. # This rule if for directly running against an arbitrary docker target.
# It is called by the expanded docker targets (e.g. make # It is called by the expanded docker targets (e.g. make
@ -195,7 +197,7 @@ DOCKER_CCACHE_DIR := $$HOME/.cache/qemu-docker-ccache
# For example: make docker-run TEST="test-quick" IMAGE="debian:arm64" EXECUTABLE=./aarch64-linux-user/qemu-aarch64 # For example: make docker-run TEST="test-quick" IMAGE="debian:arm64" EXECUTABLE=./aarch64-linux-user/qemu-aarch64
# #
docker-run: docker-qemu-src docker-run: docker-qemu-src
@mkdir -p "$(DOCKER_CCACHE_DIR)" @mkdir -p "$(DOCKER_QEMU_CCACHE_DIR)"
@if test -z "$(IMAGE)" || test -z "$(TEST)"; \ @if test -z "$(IMAGE)" || test -z "$(TEST)"; \
then echo "Invalid target $(IMAGE)/$(TEST)"; exit 1; \ then echo "Invalid target $(IMAGE)/$(TEST)"; exit 1; \
fi fi
@ -222,8 +224,8 @@ docker-run: docker-qemu-src
-e V=$V -e J=$J -e DEBUG=$(DEBUG) \ -e V=$V -e J=$J -e DEBUG=$(DEBUG) \
-e SHOW_ENV=$(SHOW_ENV) \ -e SHOW_ENV=$(SHOW_ENV) \
$(if $(NOUSER),, \ $(if $(NOUSER),, \
-e CCACHE_DIR=/var/tmp/ccache \ -v $(DOCKER_QEMU_CACHE_DIR):$(DOCKER_QEMU_CACHE_DIR) \
-v $(DOCKER_CCACHE_DIR):/var/tmp/ccache:z \ -e CCACHE_DIR=$(DOCKER_QEMU_CCACHE_DIR) \
) \ ) \
-v $$(readlink -e $(DOCKER_SRC_COPY)):/var/tmp/qemu:z$(COMMA)ro \ -v $$(readlink -e $(DOCKER_SRC_COPY)):/var/tmp/qemu:z$(COMMA)ro \
$(IMAGE) \ $(IMAGE) \

View file

@ -104,10 +104,10 @@ static void igb_pci_start_hw(QOSGraphObject *obj)
e1000e_macreg_write(&d->e1000e, E1000_RDT(0), 0); e1000e_macreg_write(&d->e1000e, E1000_RDT(0), 0);
e1000e_macreg_write(&d->e1000e, E1000_RDH(0), 0); e1000e_macreg_write(&d->e1000e, E1000_RDH(0), 0);
e1000e_macreg_write(&d->e1000e, E1000_RA, e1000e_macreg_write(&d->e1000e, E1000_RA,
le32_to_cpu(*(uint32_t *)address)); ldl_le_p(address));
e1000e_macreg_write(&d->e1000e, E1000_RA + 4, e1000e_macreg_write(&d->e1000e, E1000_RA + 4,
E1000_RAH_AV | E1000_RAH_POOL_1 | E1000_RAH_AV | E1000_RAH_POOL_1 |
le16_to_cpu(*(uint16_t *)(address + 4))); lduw_le_p(address + 4));
/* Set supported receive descriptor mode */ /* Set supported receive descriptor mode */
e1000e_macreg_write(&d->e1000e, e1000e_macreg_write(&d->e1000e,

View file

@ -68,7 +68,8 @@ run-plugin-semiconsole-with-%: semiconsole
# vtimer test needs EL2 # vtimer test needs EL2
QEMU_EL2_MACHINE=-machine virt,virtualization=on,gic-version=2 -cpu cortex-a57 -smp 4 QEMU_EL2_MACHINE=-machine virt,virtualization=on,gic-version=2 -cpu cortex-a57 -smp 4
run-vtimer: QEMU_OPTS=$(QEMU_EL2_MACHINE) $(QEMU_BASE_ARGS) -kernel QEMU_EL2_BASE_ARGS=-semihosting-config enable=on,target=native,chardev=output,arg="2"
run-vtimer: QEMU_OPTS=$(QEMU_EL2_MACHINE) $(QEMU_EL2_BASE_ARGS) -kernel
# Simple Record/Replay Test # Simple Record/Replay Test
.PHONY: memory-record .PHONY: memory-record

View file

@ -16,6 +16,7 @@
#define semihosting_call hlt 0xf000 #define semihosting_call hlt 0xf000
#define SYS_WRITEC 0x03 /* character to debug channel */ #define SYS_WRITEC 0x03 /* character to debug channel */
#define SYS_WRITE0 0x04 /* string to debug channel */ #define SYS_WRITE0 0x04 /* string to debug channel */
#define SYS_GET_CMDLINE 0x15 /* get command line */
#define SYS_EXIT 0x18 #define SYS_EXIT 0x18
.align 12 .align 12
@ -70,21 +71,172 @@ lower_a32_sync:
lower_a32_irq: lower_a32_irq:
lower_a32_fiq: lower_a32_fiq:
lower_a32_serror: lower_a32_serror:
adr x1, .unexp_excp
exit_msg:
mov x0, SYS_WRITE0 mov x0, SYS_WRITE0
adr x1, .error
semihosting_call semihosting_call
mov x0, 1 /* EXIT_FAILURE */ mov x0, 1 /* EXIT_FAILURE */
bl _exit bl _exit
/* never returns */ /* never returns */
.section .rodata .section .rodata
.error: .unexp_excp:
.string "Terminated by exception.\n" .string "Unexpected exception.\n"
.high_el_msg:
.string "Started in lower EL than requested.\n"
.unexp_el0:
.string "Started in invalid EL.\n"
.align 8
.get_cmd:
.quad cmdline
.quad 128
.text .text
.align 4 .align 4
.global __start .global __start
__start: __start:
/*
* Initialise the stack for whatever EL we are in before
* anything else, we need it to be able to _exit cleanly.
* It's smaller than the stack we pass to the C code but we
* don't need much.
*/
adrp x0, system_stack_end
add x0, x0, :lo12:system_stack_end
mov sp, x0
/*
* The test can set the semihosting command line to the target
* EL needed for the test. However if no semihosting args are set we will
* end up with -kernel/-append data (see semihosting_arg_fallback).
* Keep the normalised target in w11.
*/
mov x0, SYS_GET_CMDLINE
adr x1, .get_cmd
semihosting_call
adrp x10, cmdline
add x10, x10, :lo12:cmdline
ldrb w11, [x10]
/* sanity check, normalise char to EL, clamp to 1 if outside range */
subs w11, w11, #'0'
b.lt el_default
cmp w11, #3
b.gt el_default
b 1f
el_high:
adr x1, .high_el_msg
b exit_msg
el_default:
mov w11, #1
1:
/* Determine current Exception Level */
mrs x0, CurrentEL
lsr x0, x0, #2 /* CurrentEL[3:2] contains the current EL */
/* Are we already in a lower EL than we want? */
cmp w11, w0
bgt el_high
/* Branch based on current EL */
cmp x0, #3
b.eq setup_el3
cmp x0, #2
b.eq setup_el2
cmp x0, #1
b.eq at_testel /* Already at EL1, skip transition */
/* Should not be at EL0 - error out */
adr x1, .unexp_el0
b exit_msg
setup_el3:
/* Ensure we trap if we get anything wrong */
adr x0, vector_table
msr vbar_el3, x0
/* Does the test want to be at EL3? */
cmp w11, #3
beq at_testel
/* Configure EL3 to for lower states (EL2 or EL1) */
mrs x0, scr_el3
orr x0, x0, #(1 << 10) /* RW = 1: EL2/EL1 execution state is AArch64 */
orr x0, x0, #(1 << 0) /* NS = 1: Non-secure state */
msr scr_el3, x0
/*
* We need to check if EL2 is actually enabled via ID_AA64PFR0_EL1,
* otherwise we should just jump straight to EL1.
*/
mrs x0, id_aa64pfr0_el1
ubfx x0, x0, #8, #4 /* Extract EL2 field (bits 11:8) */
cbz x0, el2_not_present /* If field is 0 no EL2 */
/* Prepare SPSR for exception return to EL2 */
mov x0, #0x3c9 /* DAIF bits and EL2h mode (9) */
msr spsr_el3, x0
/* Set EL2 entry point */
adr x0, setup_el2
msr elr_el3, x0
/* Return to EL2 */
eret
el2_not_present:
/* Initialize SCTLR_EL1 with reset value */
msr sctlr_el1, xzr
/* Set EL1 entry point */
adr x0, at_testel
msr elr_el3, x0
/* Prepare SPSR for exception return to EL1h with interrupts masked */
mov x0, #0x3c5 /* DAIF bits and EL1h mode (5) */
msr spsr_el3, x0
isb /* Synchronization barrier */
eret /* Jump to EL1 */
setup_el2:
/* Ensure we trap if we get anything wrong */
adr x0, vector_table
msr vbar_el2, x0
/* Does the test want to be at EL2? */
cmp w11, #2
beq at_testel
/* Configure EL2 to allow transition to EL1 */
mrs x0, hcr_el2
orr x0, x0, #(1 << 31) /* RW = 1: EL1 execution state is AArch64 */
msr hcr_el2, x0
/* Initialize SCTLR_EL1 with reset value */
msr sctlr_el1, xzr
/* Set EL1 entry point */
adr x0, at_testel
msr elr_el2, x0
/* Prepare SPSR for exception return to EL1 */
mov x0, #(0x5 << 0) /* EL1h (SPx), with interrupts disabled */
msr spsr_el2, x0
/* Return to EL1 */
eret
/*
* At the target EL for the test, usually EL1. Note we still
* set everything up as if we were at EL1.
*/
at_testel:
/* Installs a table of exception vectors to catch and handle all /* Installs a table of exception vectors to catch and handle all
exceptions by terminating the process with a diagnostic. */ exceptions by terminating the process with a diagnostic. */
adr x0, vector_table adr x0, vector_table
@ -198,7 +350,8 @@ __start:
orr x0, x0, #(3 << 16) orr x0, x0, #(3 << 16)
msr cpacr_el1, x0 msr cpacr_el1, x0
/* Setup some stack space and enter the test code. /*
* Setup some stack space before we enter the test code.
* Assume everything except the return value is garbage when we * Assume everything except the return value is garbage when we
* return, we won't need it. * return, we won't need it.
*/ */
@ -233,6 +386,11 @@ __sys_outc:
ret ret
.data .data
.align 8
cmdline:
.space 128, 0
.align 12 .align 12
/* Translation table /* Translation table
@ -246,6 +404,10 @@ ttb_stage2:
.space 4096, 0 .space 4096, 0
.align 12 .align 12
system_stack:
.space 4096, 0
system_stack_end:
stack: stack:
.space 65536, 0 .space 65536, 0
stack_end: stack_end: