mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-11 03:24:58 -06:00
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:
commit
bc98ffdc75
11 changed files with 300 additions and 20 deletions
|
@ -24,6 +24,7 @@
|
|||
- ccache --zero-stats
|
||||
- section_start configure "Running configure"
|
||||
- ../configure --enable-werror --disable-docs --enable-fdt=system
|
||||
--disable-debug-info
|
||||
${TARGETS:+--target-list="$TARGETS"}
|
||||
$CONFIGURE_ARGS ||
|
||||
{ cat config.log meson-logs/meson-log.txt && exit 1; }
|
||||
|
|
|
@ -129,20 +129,62 @@ static void plugin_exit(qemu_plugin_id_t id, void *udata)
|
|||
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,
|
||||
const qemu_info_t *info, int argc,
|
||||
char **argv)
|
||||
{
|
||||
bool ipq_set = false;
|
||||
|
||||
for (int i = 0; i < argc; i++) {
|
||||
char *opt = argv[i];
|
||||
g_auto(GStrv) tokens = g_strsplit(opt, "=", 2);
|
||||
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) {
|
||||
fprintf(stderr, "%s: couldn't parse %s (%s)\n",
|
||||
__func__, tokens[1], g_strerror(errno));
|
||||
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 {
|
||||
fprintf(stderr, "option parsing failed: %s\n", opt);
|
||||
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));
|
||||
max_insn_per_quantum = max_insn_per_second / NUM_TIME_UPDATE_PER_SEC;
|
||||
|
||||
if (!ipq_set) {
|
||||
max_insn_per_quantum = max_insn_per_second / NUM_TIME_UPDATE_PER_SEC;
|
||||
}
|
||||
|
||||
if (max_insn_per_quantum == 0) {
|
||||
fprintf(stderr, "minimum of %d instructions per second needed\n",
|
||||
|
|
|
@ -811,6 +811,10 @@ This plugin can limit the number of Instructions Per Second that are executed::
|
|||
* - ips=N
|
||||
- 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.
|
||||
* - 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
|
||||
------------------------
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- Copyright (C) 2009-2012 Free Software Foundation, Inc.
|
||||
<!-- Copyright (C) 2009-2025 Free Software Foundation, Inc.
|
||||
Contributed by ARM Ltd.
|
||||
|
||||
Copying and distribution of this file, with or without modification,
|
||||
|
@ -42,5 +42,53 @@
|
|||
<reg name="sp" bitsize="64" type="data_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>
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "qemu/cutils.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/target-info.h"
|
||||
#include "trace.h"
|
||||
#include "exec/gdbstub.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,
|
||||
gdbserver_state.mem_buf,
|
||||
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_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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
gdbserver_state.query_cpu = gdb_first_attached_cpu();
|
||||
|
@ -1842,6 +1855,10 @@ static const GdbCmdParseEntry gdb_gen_query_table[] = {
|
|||
.handler = handle_query_threads,
|
||||
.cmd = "sThreadInfo",
|
||||
},
|
||||
{
|
||||
.handler = handle_query_gdb_server_version,
|
||||
.cmd = "GDBServerVersion",
|
||||
},
|
||||
{
|
||||
.handler = handle_query_first_threads,
|
||||
.cmd = "fThreadInfo",
|
||||
|
|
|
@ -162,8 +162,8 @@ static inline unsigned memop_size(MemOp op)
|
|||
static inline MemOp size_memop(unsigned size)
|
||||
{
|
||||
#ifdef CONFIG_DEBUG_TCG
|
||||
/* Power of 2 up to 8. */
|
||||
assert((size & (size - 1)) == 0 && size >= 1 && size <= 8);
|
||||
/* Power of 2 up to 1024 */
|
||||
assert(is_power_of_2(size) && size >= 1 && size <= (1 << MO_SIZE));
|
||||
#endif
|
||||
return (MemOp)ctz32(size);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef GDBSTUB_COMMANDS_H
|
||||
#define GDBSTUB
|
||||
#define GDBSTUB_COMMANDS_H
|
||||
|
||||
typedef void (*GdbCmdHandler)(GArray *params, void *user_ctx);
|
||||
|
||||
|
|
|
@ -185,8 +185,10 @@ 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
|
||||
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.
|
||||
# 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
|
||||
#
|
||||
docker-run: docker-qemu-src
|
||||
@mkdir -p "$(DOCKER_CCACHE_DIR)"
|
||||
@mkdir -p "$(DOCKER_QEMU_CCACHE_DIR)"
|
||||
@if test -z "$(IMAGE)" || test -z "$(TEST)"; \
|
||||
then echo "Invalid target $(IMAGE)/$(TEST)"; exit 1; \
|
||||
fi
|
||||
|
@ -222,8 +224,8 @@ docker-run: docker-qemu-src
|
|||
-e V=$V -e J=$J -e DEBUG=$(DEBUG) \
|
||||
-e SHOW_ENV=$(SHOW_ENV) \
|
||||
$(if $(NOUSER),, \
|
||||
-e CCACHE_DIR=/var/tmp/ccache \
|
||||
-v $(DOCKER_CCACHE_DIR):/var/tmp/ccache:z \
|
||||
-v $(DOCKER_QEMU_CACHE_DIR):$(DOCKER_QEMU_CACHE_DIR) \
|
||||
-e CCACHE_DIR=$(DOCKER_QEMU_CCACHE_DIR) \
|
||||
) \
|
||||
-v $$(readlink -e $(DOCKER_SRC_COPY)):/var/tmp/qemu:z$(COMMA)ro \
|
||||
$(IMAGE) \
|
||||
|
|
|
@ -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_RDH(0), 0);
|
||||
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,
|
||||
E1000_RAH_AV | E1000_RAH_POOL_1 |
|
||||
le16_to_cpu(*(uint16_t *)(address + 4)));
|
||||
lduw_le_p(address + 4));
|
||||
|
||||
/* Set supported receive descriptor mode */
|
||||
e1000e_macreg_write(&d->e1000e,
|
||||
|
|
|
@ -68,7 +68,8 @@ run-plugin-semiconsole-with-%: semiconsole
|
|||
|
||||
# vtimer test needs EL2
|
||||
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
|
||||
.PHONY: memory-record
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#define semihosting_call hlt 0xf000
|
||||
#define SYS_WRITEC 0x03 /* character to debug channel */
|
||||
#define SYS_WRITE0 0x04 /* string to debug channel */
|
||||
#define SYS_GET_CMDLINE 0x15 /* get command line */
|
||||
#define SYS_EXIT 0x18
|
||||
|
||||
.align 12
|
||||
|
@ -70,21 +71,172 @@ lower_a32_sync:
|
|||
lower_a32_irq:
|
||||
lower_a32_fiq:
|
||||
lower_a32_serror:
|
||||
adr x1, .unexp_excp
|
||||
exit_msg:
|
||||
mov x0, SYS_WRITE0
|
||||
adr x1, .error
|
||||
semihosting_call
|
||||
mov x0, 1 /* EXIT_FAILURE */
|
||||
bl _exit
|
||||
/* never returns */
|
||||
|
||||
.section .rodata
|
||||
.error:
|
||||
.string "Terminated by exception.\n"
|
||||
.unexp_excp:
|
||||
.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
|
||||
.align 4
|
||||
.global __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
|
||||
exceptions by terminating the process with a diagnostic. */
|
||||
adr x0, vector_table
|
||||
|
@ -100,7 +252,7 @@ __start:
|
|||
* maps RAM to the first Gb. The stage2 tables have two 2mb
|
||||
* translation block entries covering a series of adjacent
|
||||
* 4k pages.
|
||||
*/
|
||||
*/
|
||||
|
||||
/* Stage 1 entry: indexed by IA[38:30] */
|
||||
adr x1, . /* phys address */
|
||||
|
@ -198,7 +350,8 @@ __start:
|
|||
orr x0, x0, #(3 << 16)
|
||||
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
|
||||
* return, we won't need it.
|
||||
*/
|
||||
|
@ -233,6 +386,11 @@ __sys_outc:
|
|||
ret
|
||||
|
||||
.data
|
||||
|
||||
.align 8
|
||||
cmdline:
|
||||
.space 128, 0
|
||||
|
||||
.align 12
|
||||
|
||||
/* Translation table
|
||||
|
@ -246,6 +404,10 @@ ttb_stage2:
|
|||
.space 4096, 0
|
||||
|
||||
.align 12
|
||||
system_stack:
|
||||
.space 4096, 0
|
||||
system_stack_end:
|
||||
|
||||
stack:
|
||||
.space 65536, 0
|
||||
stack_end:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue