* [kvm-unit-tests PATCH v2 0/9] arm64: support EL2
@ 2025-05-29 13:55 Joey Gouly
2025-05-29 13:55 ` [kvm-unit-tests PATCH v2 1/9] arm64: drop to EL1 if booted at EL2 Joey Gouly
` (9 more replies)
0 siblings, 10 replies; 13+ messages in thread
From: Joey Gouly @ 2025-05-29 13:55 UTC (permalink / raw)
To: kvm
Cc: alexandru.elisei, joey.gouly, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
Hi all,
This series is for adding support to running the kvm-unit-tests at EL2. These
have been tested with Marc Zyngier's Linux kvm-arm64/nv-next branch [1] and
kvmtool branch arm64/nv-6.13 [2]
The goal is to later extend and add new tests for Nested Virtualisation,
however they should also work with bare metal as well.
Changes since v1[3]:
- Authorship fixed on 2 patches
- Tested and fixed EFI support
- Recactored assembly and added init_el macro
- Clear trap registers, trying to avoid relying on default register
state
- Cleaned up PMU changes
The debug tests fail with --nested, but pass with --nested --e2h0, I
need to investigate this.
Thanks,
Joey
[1] https://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git kvm-arm64/nv-next (commit a35d752b17f4)
[2] https://git.kernel.org/pub/scm/linux/kernel/git/maz/kvmtool.git arm64/nv-6.13 (commit 5b6fe295ea7)
[3] https://lore.kernel.org/kvmarm/20250220141354.2565567-1-joey.gouly@arm.com/
Alexandru Elisei (2):
arm64: micro-bench: use smc when at EL2
arm64: selftest: update test for running at EL2
Joey Gouly (7):
arm64: drop to EL1 if booted at EL2
arm64: efi: initialise SCTLR_ELx fully
arm64: efi: initialise the EL
arm64: timer: use hypervisor timers when at EL2
arm64: micro-bench: fix timer IRQ
arm64: pmu: count EL2 cycles
arm64: run at EL2 if supported
arm/cstart64.S | 56 ++++++++++++++++++++++++++++++++++++--
arm/efi/crt0-efi-aarch64.S | 5 ++++
arm/micro-bench.c | 26 ++++++++++++++++--
arm/pmu.c | 13 ++++++---
arm/selftest.c | 18 ++++++++----
arm/timer.c | 10 +++++--
lib/acpi.h | 2 ++
lib/arm/asm/setup.h | 1 +
lib/arm/asm/timer.h | 11 ++++++++
lib/arm/setup.c | 6 ++++
lib/arm/timer.c | 19 +++++++++++--
lib/arm64/asm/sysreg.h | 19 +++++++++++++
12 files changed, 167 insertions(+), 19 deletions(-)
--
2.25.1
^ permalink raw reply [flat|nested] 13+ messages in thread
* [kvm-unit-tests PATCH v2 1/9] arm64: drop to EL1 if booted at EL2
2025-05-29 13:55 [kvm-unit-tests PATCH v2 0/9] arm64: support EL2 Joey Gouly
@ 2025-05-29 13:55 ` Joey Gouly
2025-05-29 13:55 ` [kvm-unit-tests PATCH v2 2/9] arm64: efi: initialise SCTLR_ELx fully Joey Gouly
` (8 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Joey Gouly @ 2025-05-29 13:55 UTC (permalink / raw)
To: kvm
Cc: alexandru.elisei, joey.gouly, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
EL2 is not currently supported, drop to EL1 to conitnue booting.
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
---
arm/cstart64.S | 47 +++++++++++++++++++++++++++++++++++++++---
lib/arm64/asm/sysreg.h | 14 +++++++++++++
2 files changed, 58 insertions(+), 3 deletions(-)
diff --git a/arm/cstart64.S b/arm/cstart64.S
index 014c9c7b..79b93dd4 100644
--- a/arm/cstart64.S
+++ b/arm/cstart64.S
@@ -15,6 +15,46 @@
#include <asm/thread_info.h>
#include <asm/sysreg.h>
+.macro init_el, tmp
+ mrs \tmp, CurrentEL
+ cmp \tmp, CurrentEL_EL2
+ b.ne 1f
+ /* EL2 setup */
+ mrs \tmp, mpidr_el1
+ msr vmpidr_el2, \tmp
+ mrs \tmp, midr_el1
+ msr vpidr_el2, \tmp
+ /* clear trap registers */
+ mrs \tmp, id_aa64mmfr0_el1
+ ubfx \tmp, \tmp, #ID_AA64MMFR0_EL1_FGT_SHIFT, #4
+ cbz \tmp, .Lskip_fgt_\@
+ mov \tmp, #0
+ msr_s SYS_HFGRTR_EL2, \tmp
+ msr_s SYS_HFGWTR_EL2, \tmp
+ msr_s SYS_HFGITR_EL2, \tmp
+ mrs \tmp, id_aa64mmfr0_el1
+ ubfx \tmp, \tmp, #ID_AA64MMFR0_EL1_FGT_SHIFT, #4
+ cmp \tmp, #ID_AA64MMFR0_EL1_FGT_FGT2
+ bne .Lskip_fgt_\@
+ mov \tmp, #0
+ msr_s SYS_HFGRTR2_EL2, \tmp
+ msr_s SYS_HFGWTR2_EL2, \tmp
+ msr_s SYS_HFGITR2_EL2, \tmp
+.Lskip_fgt_\@:
+ mov \tmp, #0
+ msr cptr_el2, \tmp
+ ldr \tmp, =(INIT_HCR_EL2_EL1_ONLY)
+ msr hcr_el2, \tmp
+ mov \tmp, PSR_MODE_EL1t
+ msr spsr_el2, \tmp
+ adrp \tmp, 1f
+ add \tmp, \tmp, :lo12:1f
+ msr elr_el2, \tmp
+ eret
+1:
+.endm
+
+
#ifdef CONFIG_EFI
#include "efi/crt0-efi-aarch64.S"
#else
@@ -56,15 +96,15 @@ start:
add x6, x6, :lo12:reloc_end
1:
cmp x5, x6
- b.hs 1f
+ b.hs reloc_done
ldr x7, [x5] // r_offset
ldr x8, [x5, #16] // r_addend
add x8, x8, x4 // val = base + r_addend
str x8, [x4, x7] // base[r_offset] = val
add x5, x5, #24
b 1b
-
-1:
+reloc_done:
+ init_el x4
/* zero BSS */
adrp x4, bss
add x4, x4, :lo12:bss
@@ -185,6 +225,7 @@ get_mmu_off:
.globl secondary_entry
secondary_entry:
+ init_el x0
/* enable FP/ASIMD and SVE */
mov x0, #(3 << 20)
orr x0, x0, #(3 << 16)
diff --git a/lib/arm64/asm/sysreg.h b/lib/arm64/asm/sysreg.h
index e537bb46..ed776716 100644
--- a/lib/arm64/asm/sysreg.h
+++ b/lib/arm64/asm/sysreg.h
@@ -77,6 +77,9 @@ asm(
#define ID_AA64ISAR0_EL1_RNDR_SHIFT 60
#define ID_AA64PFR1_EL1_MTE_SHIFT 8
+#define ID_AA64MMFR0_EL1_FGT_SHIFT 56
+#define ID_AA64MMFR0_EL1_FGT_FGT2 0x2
+
#define ICC_PMR_EL1 sys_reg(3, 0, 4, 6, 0)
#define ICC_SGI1R_EL1 sys_reg(3, 0, 12, 11, 5)
#define ICC_IAR1_EL1 sys_reg(3, 0, 12, 12, 0)
@@ -113,6 +116,17 @@ asm(
#define SCTLR_EL1_TCF0_SHIFT 38
#define SCTLR_EL1_TCF0_MASK GENMASK_ULL(39, 38)
+#define HCR_EL2_RW _BITULL(31)
+
+#define INIT_HCR_EL2_EL1_ONLY (HCR_EL2_RW)
+
+#define SYS_HFGRTR_EL2 sys_reg(3, 4, 1, 1, 4)
+#define SYS_HFGWTR_EL2 sys_reg(3, 4, 1, 1, 5)
+#define SYS_HFGITR_EL2 sys_reg(3, 4, 1, 1, 6)
+#define SYS_HFGRTR2_EL2 sys_reg(3, 4, 3, 1, 2)
+#define SYS_HFGWTR2_EL2 sys_reg(3, 4, 3, 1, 3)
+#define SYS_HFGITR2_EL2 sys_reg(3, 4, 3, 1, 7)
+
#define INIT_SCTLR_EL1_MMU_OFF \
(SCTLR_EL1_ITD | SCTLR_EL1_SED | SCTLR_EL1_EOS | \
SCTLR_EL1_TSCXT | SCTLR_EL1_EIS | SCTLR_EL1_SPAN | \
--
2.25.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [kvm-unit-tests PATCH v2 2/9] arm64: efi: initialise SCTLR_ELx fully
2025-05-29 13:55 [kvm-unit-tests PATCH v2 0/9] arm64: support EL2 Joey Gouly
2025-05-29 13:55 ` [kvm-unit-tests PATCH v2 1/9] arm64: drop to EL1 if booted at EL2 Joey Gouly
@ 2025-05-29 13:55 ` Joey Gouly
2025-06-06 10:17 ` Suzuki K Poulose
2025-05-29 13:55 ` [kvm-unit-tests PATCH v2 3/9] arm64: efi: initialise the EL Joey Gouly
` (7 subsequent siblings)
9 siblings, 1 reply; 13+ messages in thread
From: Joey Gouly @ 2025-05-29 13:55 UTC (permalink / raw)
To: kvm
Cc: alexandru.elisei, joey.gouly, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
Don't rely on the value of SCTLR_ELx when booting via EFI.
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
---
lib/arm/setup.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/lib/arm/setup.c b/lib/arm/setup.c
index 67b5db07..0a22dbab 100644
--- a/lib/arm/setup.c
+++ b/lib/arm/setup.c
@@ -349,6 +349,11 @@ efi_status_t setup_efi(efi_bootinfo_t *efi_bootinfo)
{
efi_status_t status;
+
+ // EFI exits boot services with SCTLR_ELx.M=1, so keep
+ // the MMU enabled.
+ write_sysreg(INIT_SCTLR_EL1_MMU_OFF | SCTLR_EL1_M, sctlr_el1);
+
exceptions_init();
memregions_init(arm_mem_regions, NR_MEM_REGIONS);
--
2.25.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [kvm-unit-tests PATCH v2 3/9] arm64: efi: initialise the EL
2025-05-29 13:55 [kvm-unit-tests PATCH v2 0/9] arm64: support EL2 Joey Gouly
2025-05-29 13:55 ` [kvm-unit-tests PATCH v2 1/9] arm64: drop to EL1 if booted at EL2 Joey Gouly
2025-05-29 13:55 ` [kvm-unit-tests PATCH v2 2/9] arm64: efi: initialise SCTLR_ELx fully Joey Gouly
@ 2025-05-29 13:55 ` Joey Gouly
2025-05-29 13:55 ` [kvm-unit-tests PATCH v2 4/9] arm64: timer: use hypervisor timers when at EL2 Joey Gouly
` (6 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Joey Gouly @ 2025-05-29 13:55 UTC (permalink / raw)
To: kvm
Cc: alexandru.elisei, joey.gouly, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
Initialise the exception level, which may include dropping to EL1 from EL2, if
VHE is not supported.
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
---
arm/efi/crt0-efi-aarch64.S | 5 +++++
lib/arm/asm/setup.h | 1 +
lib/arm/setup.c | 1 +
3 files changed, 7 insertions(+)
diff --git a/arm/efi/crt0-efi-aarch64.S b/arm/efi/crt0-efi-aarch64.S
index 71ce2794..5632fee0 100644
--- a/arm/efi/crt0-efi-aarch64.S
+++ b/arm/efi/crt0-efi-aarch64.S
@@ -147,6 +147,11 @@ _start:
0: ldp x29, x30, [sp], #32
ret
+.globl do_init_el
+do_init_el:
+ init_el x16
+ ret
+
.section .data
.balign 65536
diff --git a/lib/arm/asm/setup.h b/lib/arm/asm/setup.h
index 9f8ef82e..6a409b38 100644
--- a/lib/arm/asm/setup.h
+++ b/lib/arm/asm/setup.h
@@ -28,6 +28,7 @@ void setup(const void *fdt, phys_addr_t freemem_start);
#include <efi.h>
+void do_init_el(void);
efi_status_t setup_efi(efi_bootinfo_t *efi_bootinfo);
#endif
diff --git a/lib/arm/setup.c b/lib/arm/setup.c
index 0a22dbab..f49fa8ca 100644
--- a/lib/arm/setup.c
+++ b/lib/arm/setup.c
@@ -349,6 +349,7 @@ efi_status_t setup_efi(efi_bootinfo_t *efi_bootinfo)
{
efi_status_t status;
+ do_init_el();
// EFI exits boot services with SCTLR_ELx.M=1, so keep
// the MMU enabled.
--
2.25.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [kvm-unit-tests PATCH v2 4/9] arm64: timer: use hypervisor timers when at EL2
2025-05-29 13:55 [kvm-unit-tests PATCH v2 0/9] arm64: support EL2 Joey Gouly
` (2 preceding siblings ...)
2025-05-29 13:55 ` [kvm-unit-tests PATCH v2 3/9] arm64: efi: initialise the EL Joey Gouly
@ 2025-05-29 13:55 ` Joey Gouly
2025-05-29 13:55 ` [kvm-unit-tests PATCH v2 5/9] arm64: micro-bench: fix timer IRQ Joey Gouly
` (5 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Joey Gouly @ 2025-05-29 13:55 UTC (permalink / raw)
To: kvm
Cc: alexandru.elisei, joey.gouly, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
At EL2, with VHE:
CNT{P,V}_{TVAL,CTL}_EL0 is forwarded to CNTH{P,V}_{CVAL,TVAL,CTL}_EL0.
Save the hypervisor physical and virtual timer IRQ numbers from the DT/ACPI.
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
arm/timer.c | 10 ++++++++--
lib/acpi.h | 2 ++
lib/arm/asm/timer.h | 11 +++++++++++
lib/arm/timer.c | 19 +++++++++++++++++--
4 files changed, 38 insertions(+), 4 deletions(-)
diff --git a/arm/timer.c b/arm/timer.c
index 2cb80518..c6287ca7 100644
--- a/arm/timer.c
+++ b/arm/timer.c
@@ -347,8 +347,14 @@ static void test_ptimer(void)
static void test_init(void)
{
assert(TIMER_PTIMER_IRQ != -1 && TIMER_VTIMER_IRQ != -1);
- ptimer_info.irq = TIMER_PTIMER_IRQ;
- vtimer_info.irq = TIMER_VTIMER_IRQ;
+ if (current_level() == CurrentEL_EL1) {
+ ptimer_info.irq = TIMER_PTIMER_IRQ;
+ vtimer_info.irq = TIMER_VTIMER_IRQ;
+ } else {
+ assert(TIMER_HPTIMER_IRQ != -1 && TIMER_HVTIMER_IRQ != -1);
+ ptimer_info.irq = TIMER_HPTIMER_IRQ;
+ vtimer_info.irq = TIMER_HVTIMER_IRQ;
+ }
install_exception_handler(EL1H_SYNC, ESR_EL1_EC_UNKNOWN, ptimer_unsupported_handler);
ptimer_info.read_ctl();
diff --git a/lib/acpi.h b/lib/acpi.h
index c330c877..66e3062d 100644
--- a/lib/acpi.h
+++ b/lib/acpi.h
@@ -290,6 +290,8 @@ struct acpi_table_gtdt {
u64 counter_read_block_address;
u32 platform_timer_count;
u32 platform_timer_offset;
+ u32 virtual_el2_timer_interrupt;
+ u32 virtual_el2_timer_flags;
};
/* Reset to default packing */
diff --git a/lib/arm/asm/timer.h b/lib/arm/asm/timer.h
index fd8f7796..0dcebc1c 100644
--- a/lib/arm/asm/timer.h
+++ b/lib/arm/asm/timer.h
@@ -21,12 +21,23 @@ struct timer_state {
u32 irq;
u32 irq_flags;
} vtimer;
+ struct {
+ u32 irq;
+ u32 irq_flags;
+ } hptimer;
+ struct {
+ u32 irq;
+ u32 irq_flags;
+ } hvtimer;
};
extern struct timer_state __timer_state;
#define TIMER_PTIMER_IRQ (__timer_state.ptimer.irq)
#define TIMER_VTIMER_IRQ (__timer_state.vtimer.irq)
+#define TIMER_HPTIMER_IRQ (__timer_state.hptimer.irq)
+#define TIMER_HVTIMER_IRQ (__timer_state.hvtimer.irq)
+
void timer_save_state(void);
#endif /* !__ASSEMBLER__ */
diff --git a/lib/arm/timer.c b/lib/arm/timer.c
index ae702e41..57f504e2 100644
--- a/lib/arm/timer.c
+++ b/lib/arm/timer.c
@@ -38,10 +38,11 @@ static void timer_save_state_fdt(void)
* secure timer irq
* non-secure timer irq (ptimer)
* virtual timer irq (vtimer)
- * hypervisor timer irq
+ * hypervisor timer irq (hptimer)
+ * hypervisor virtual timer irq (hvtimer)
*/
prop = fdt_get_property(fdt, node, "interrupts", &len);
- assert(prop && len == (4 * 3 * sizeof(u32)));
+ assert(prop && len >= (4 * 3 * sizeof(u32)));
data = (u32 *) prop->data;
assert(fdt32_to_cpu(data[3]) == 1 /* PPI */ );
@@ -50,6 +51,14 @@ static void timer_save_state_fdt(void)
assert(fdt32_to_cpu(data[6]) == 1 /* PPI */ );
__timer_state.vtimer.irq = PPI(fdt32_to_cpu(data[7]));
__timer_state.vtimer.irq_flags = fdt32_to_cpu(data[8]);
+ if (len == (5 * 3 * sizeof(u32))) {
+ assert(fdt32_to_cpu(data[9]) == 1 /* PPI */ );
+ __timer_state.hptimer.irq = PPI(fdt32_to_cpu(data[10]));
+ __timer_state.hptimer.irq_flags = fdt32_to_cpu(data[11]);
+ assert(fdt32_to_cpu(data[12]) == 1 /* PPI */ );
+ __timer_state.hvtimer.irq = PPI(fdt32_to_cpu(data[13]));
+ __timer_state.hvtimer.irq_flags = fdt32_to_cpu(data[14]);
+ }
}
#ifdef CONFIG_EFI
@@ -72,6 +81,12 @@ static void timer_save_state_acpi(void)
__timer_state.vtimer.irq = gtdt->virtual_timer_interrupt;
__timer_state.vtimer.irq_flags = gtdt->virtual_timer_flags;
+
+ __timer_state.hptimer.irq = gtdt->non_secure_el2_interrupt;
+ __timer_state.hptimer.irq_flags = gtdt->non_secure_el2_flags;
+
+ __timer_state.hvtimer.irq = gtdt->virtual_el2_timer_interrupt;
+ __timer_state.hvtimer.irq_flags = gtdt->virtual_el2_timer_flags;
}
#else
--
2.25.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [kvm-unit-tests PATCH v2 5/9] arm64: micro-bench: fix timer IRQ
2025-05-29 13:55 [kvm-unit-tests PATCH v2 0/9] arm64: support EL2 Joey Gouly
` (3 preceding siblings ...)
2025-05-29 13:55 ` [kvm-unit-tests PATCH v2 4/9] arm64: timer: use hypervisor timers when at EL2 Joey Gouly
@ 2025-05-29 13:55 ` Joey Gouly
2025-05-29 13:55 ` [kvm-unit-tests PATCH v2 6/9] arm64: micro-bench: use smc when at EL2 Joey Gouly
` (4 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Joey Gouly @ 2025-05-29 13:55 UTC (permalink / raw)
To: kvm
Cc: alexandru.elisei, joey.gouly, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
Enable the correct (hvtimer) IRQ when at EL2.
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>
---
arm/micro-bench.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/arm/micro-bench.c b/arm/micro-bench.c
index 22408955..f47c5fc1 100644
--- a/arm/micro-bench.c
+++ b/arm/micro-bench.c
@@ -42,7 +42,7 @@ static void gic_irq_handler(struct pt_regs *regs)
irq_received = true;
gic_write_eoir(irqstat);
- if (irqstat == TIMER_VTIMER_IRQ) {
+ if (irqstat == TIMER_VTIMER_IRQ || irqstat == TIMER_HVTIMER_IRQ) {
write_sysreg((ARCH_TIMER_CTL_IMASK | ARCH_TIMER_CTL_ENABLE),
cntv_ctl_el0);
isb();
@@ -215,7 +215,11 @@ static bool timer_prep(void)
install_irq_handler(EL1H_IRQ, gic_irq_handler);
local_irq_enable();
- gic_enable_irq(TIMER_VTIMER_IRQ);
+ if (current_level() == CurrentEL_EL1)
+ gic_enable_irq(TIMER_VTIMER_IRQ);
+ else
+ gic_enable_irq(TIMER_HVTIMER_IRQ);
+
write_sysreg(ARCH_TIMER_CTL_IMASK | ARCH_TIMER_CTL_ENABLE, cntv_ctl_el0);
isb();
--
2.25.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [kvm-unit-tests PATCH v2 6/9] arm64: micro-bench: use smc when at EL2
2025-05-29 13:55 [kvm-unit-tests PATCH v2 0/9] arm64: support EL2 Joey Gouly
` (4 preceding siblings ...)
2025-05-29 13:55 ` [kvm-unit-tests PATCH v2 5/9] arm64: micro-bench: fix timer IRQ Joey Gouly
@ 2025-05-29 13:55 ` Joey Gouly
2025-05-29 13:55 ` [kvm-unit-tests PATCH v2 7/9] arm64: selftest: update test for running " Joey Gouly
` (3 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Joey Gouly @ 2025-05-29 13:55 UTC (permalink / raw)
To: kvm
Cc: alexandru.elisei, joey.gouly, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
From: Alexandru Elisei <alexandru.elisei@arm.com>
At EL2, hvc would target the current EL, use smc so that it targets EL3.
Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com>
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
---
arm/micro-bench.c | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/arm/micro-bench.c b/arm/micro-bench.c
index f47c5fc1..32029c5a 100644
--- a/arm/micro-bench.c
+++ b/arm/micro-bench.c
@@ -282,6 +282,11 @@ static bool mmio_read_user_prep(void)
return true;
}
+static void smc_exec(void)
+{
+ asm volatile("mov w0, #0x4b000000; smc #0" ::: "w0");
+}
+
static void mmio_read_user_exec(void)
{
readl(userspace_emulated_addr);
@@ -300,6 +305,8 @@ static void eoi_exec(void)
write_eoir(spurious_id);
}
+static bool exec_select(void);
+
struct exit_test {
const char *name;
bool (*prep)(void);
@@ -310,7 +317,7 @@ struct exit_test {
};
static struct exit_test tests[] = {
- {"hvc", NULL, hvc_exec, NULL, 65536, true},
+ {"hyp_call", exec_select, hvc_exec, NULL, 65536, true},
{"mmio_read_user", mmio_read_user_prep, mmio_read_user_exec, NULL, 65536, true},
{"mmio_read_vgic", NULL, mmio_read_vgic_exec, NULL, 65536, true},
{"eoi", NULL, eoi_exec, NULL, 65536, true},
@@ -320,6 +327,15 @@ static struct exit_test tests[] = {
{"timer_10ms", timer_prep, timer_exec, timer_post, 256, true},
};
+static bool exec_select(void)
+{
+ if (current_level() == CurrentEL_EL2)
+ tests[0].exec = &smc_exec;
+ else
+ tests[0].exec = &hvc_exec;
+ return true;
+}
+
struct ns_time {
uint64_t ns;
uint64_t ns_frac;
--
2.25.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [kvm-unit-tests PATCH v2 7/9] arm64: selftest: update test for running at EL2
2025-05-29 13:55 [kvm-unit-tests PATCH v2 0/9] arm64: support EL2 Joey Gouly
` (5 preceding siblings ...)
2025-05-29 13:55 ` [kvm-unit-tests PATCH v2 6/9] arm64: micro-bench: use smc when at EL2 Joey Gouly
@ 2025-05-29 13:55 ` Joey Gouly
2025-05-29 13:55 ` [kvm-unit-tests PATCH v2 8/9] arm64: pmu: count EL2 cycles Joey Gouly
` (2 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Joey Gouly @ 2025-05-29 13:55 UTC (permalink / raw)
To: kvm
Cc: alexandru.elisei, joey.gouly, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
From: Alexandru Elisei <alexandru.elisei@arm.com>
Remove some hard-coded assumptions that this test is running at EL1.
Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com>
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
---
arm/selftest.c | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)
diff --git a/arm/selftest.c b/arm/selftest.c
index 1553ed8e..01691389 100644
--- a/arm/selftest.c
+++ b/arm/selftest.c
@@ -232,6 +232,7 @@ static void user_psci_system_off(struct pt_regs *regs)
__user_psci_system_off();
}
#elif defined(__aarch64__)
+static unsigned long expected_level;
/*
* Capture the current register state and execute an instruction
@@ -276,8 +277,7 @@ static bool check_regs(struct pt_regs *regs)
{
unsigned i;
- /* exception handlers should always run in EL1 */
- if (current_level() != CurrentEL_EL1)
+ if (current_level() != expected_level)
return false;
for (i = 0; i < ARRAY_SIZE(regs->regs); ++i) {
@@ -301,7 +301,11 @@ static enum vector check_vector_prep(void)
return EL0_SYNC_64;
asm volatile("mrs %0, daif" : "=r" (daif) ::);
- expected_regs.pstate = daif | PSR_MODE_EL1h;
+ expected_regs.pstate = daif;
+ if (current_level() == CurrentEL_EL1)
+ expected_regs.pstate |= PSR_MODE_EL1h;
+ else
+ expected_regs.pstate |= PSR_MODE_EL2h;
return EL1H_SYNC;
}
@@ -317,8 +321,8 @@ static bool check_und(void)
install_exception_handler(v, ESR_EL1_EC_UNKNOWN, unknown_handler);
- /* try to read an el2 sysreg from el0/1 */
- test_exception("", "mrs x0, sctlr_el2", "", "x0");
+ /* try to read an el3 sysreg from el0/1/2 */
+ test_exception("", "mrs x0, sctlr_el3", "", "x0");
install_exception_handler(v, ESR_EL1_EC_UNKNOWN, NULL);
@@ -429,6 +433,10 @@ int main(int argc, char **argv)
if (argc < 2)
report_abort("no test specified");
+#if defined(__aarch64__)
+ expected_level = current_level();
+#endif
+
report_prefix_push(argv[1]);
if (strcmp(argv[1], "setup") == 0) {
--
2.25.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [kvm-unit-tests PATCH v2 8/9] arm64: pmu: count EL2 cycles
2025-05-29 13:55 [kvm-unit-tests PATCH v2 0/9] arm64: support EL2 Joey Gouly
` (6 preceding siblings ...)
2025-05-29 13:55 ` [kvm-unit-tests PATCH v2 7/9] arm64: selftest: update test for running " Joey Gouly
@ 2025-05-29 13:55 ` Joey Gouly
2025-05-29 13:55 ` [kvm-unit-tests PATCH v2 9/9] arm64: run at EL2 if supported Joey Gouly
2025-06-16 12:34 ` [kvm-unit-tests PATCH v2 0/9] arm64: support EL2 Alexandru Elisei
9 siblings, 0 replies; 13+ messages in thread
From: Joey Gouly @ 2025-05-29 13:55 UTC (permalink / raw)
To: kvm
Cc: alexandru.elisei, joey.gouly, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
Count EL2 cycles if that's the EL kvm-unit-tests is running at!
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
---
arm/pmu.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/arm/pmu.c b/arm/pmu.c
index 2dc0822b..e6c0f05b 100644
--- a/arm/pmu.c
+++ b/arm/pmu.c
@@ -121,6 +121,8 @@ static struct pmu pmu;
#define PMINTENCLR __ACCESS_CP15(c9, 0, c14, 2)
#define PMCCNTR64 __ACCESS_CP15_64(0, c9)
+#define PMCCFILTR_EL0_DEFAULT 0
+
static inline uint32_t get_id_dfr0(void) { return read_sysreg(ID_DFR0); }
static inline uint32_t get_pmcr(void) { return read_sysreg(PMCR); }
static inline void set_pmcr(uint32_t v) { write_sysreg(v, PMCR); }
@@ -206,6 +208,9 @@ static void test_overflow_interrupt(bool overflow_at_64bits) {}
#define ID_DFR0_PMU_V3_8_5 0b0110
#define ID_DFR0_PMU_IMPDEF 0b1111
+#define PMCCFILTR_EL0_NSH BIT(27)
+#define PMCCFILTR_EL0_DEFAULT (current_level() == CurrentEL_EL2 ? PMCCFILTR_EL0_NSH : 0)
+
static inline uint32_t get_id_aa64dfr0(void) { return read_sysreg(id_aa64dfr0_el1); }
static inline uint32_t get_pmcr(void) { return read_sysreg(pmcr_el0); }
static inline void set_pmcr(uint32_t v) { write_sysreg(v, pmcr_el0); }
@@ -246,8 +251,7 @@ static inline void precise_instrs_loop(int loop, uint32_t pmcr)
#define PMCNTENSET_EL0 sys_reg(3, 3, 9, 12, 1)
#define PMCNTENCLR_EL0 sys_reg(3, 3, 9, 12, 2)
-#define PMEVTYPER_EXCLUDE_EL1 BIT(31)
-#define PMEVTYPER_EXCLUDE_EL0 BIT(30)
+#define PMEVTYPER_EXCLUDE_EL0 BIT(30) | (current_level() == CurrentEL_EL2 ? BIT(27) : 0)
static bool is_event_supported(uint32_t n, bool warn)
{
@@ -1063,7 +1067,8 @@ static bool check_cycles_increase(void)
/* init before event access, this test only cares about cycle count */
pmu_reset();
set_pmcntenset(1 << PMU_CYCLE_IDX);
- set_pmccfiltr(0); /* count cycles in EL0, EL1, but not EL2 */
+
+ set_pmccfiltr(PMCCFILTR_EL0_DEFAULT);
set_pmcr(get_pmcr() | PMU_PMCR_LC | PMU_PMCR_C | PMU_PMCR_E);
isb();
@@ -1118,7 +1123,7 @@ static bool check_cpi(int cpi)
/* init before event access, this test only cares about cycle count */
pmu_reset();
set_pmcntenset(1 << PMU_CYCLE_IDX);
- set_pmccfiltr(0); /* count cycles in EL0, EL1, but not EL2 */
+ set_pmccfiltr(PMCCFILTR_EL0_DEFAULT);
if (cpi > 0)
printf("Checking for CPI=%d.\n", cpi);
--
2.25.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [kvm-unit-tests PATCH v2 9/9] arm64: run at EL2 if supported
2025-05-29 13:55 [kvm-unit-tests PATCH v2 0/9] arm64: support EL2 Joey Gouly
` (7 preceding siblings ...)
2025-05-29 13:55 ` [kvm-unit-tests PATCH v2 8/9] arm64: pmu: count EL2 cycles Joey Gouly
@ 2025-05-29 13:55 ` Joey Gouly
2025-06-16 12:34 ` [kvm-unit-tests PATCH v2 0/9] arm64: support EL2 Alexandru Elisei
9 siblings, 0 replies; 13+ messages in thread
From: Joey Gouly @ 2025-05-29 13:55 UTC (permalink / raw)
To: kvm
Cc: alexandru.elisei, joey.gouly, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
If VHE is supported, continue booting at EL2, otherwise continue booting at
EL1.
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
---
arm/cstart64.S | 17 +++++++++++++----
lib/arm64/asm/sysreg.h | 5 +++++
2 files changed, 18 insertions(+), 4 deletions(-)
diff --git a/arm/cstart64.S b/arm/cstart64.S
index 79b93dd4..af7c81c1 100644
--- a/arm/cstart64.S
+++ b/arm/cstart64.S
@@ -18,7 +18,7 @@
.macro init_el, tmp
mrs \tmp, CurrentEL
cmp \tmp, CurrentEL_EL2
- b.ne 1f
+ b.ne 2f
/* EL2 setup */
mrs \tmp, mpidr_el1
msr vmpidr_el2, \tmp
@@ -41,17 +41,26 @@
msr_s SYS_HFGWTR2_EL2, \tmp
msr_s SYS_HFGITR2_EL2, \tmp
.Lskip_fgt_\@:
+ /* check VHE is supported */
+ mrs \tmp, ID_AA64MMFR1_EL1
+ ubfx \tmp, \tmp, ID_AA64MMFR1_EL1_VH_SHIFT, #4
+ cbz \tmp, 1f
+ ldr \tmp, =(INIT_HCR_EL2)
+ msr hcr_el2, \tmp
+ isb
+ b 2f
+1:
mov \tmp, #0
msr cptr_el2, \tmp
ldr \tmp, =(INIT_HCR_EL2_EL1_ONLY)
msr hcr_el2, \tmp
mov \tmp, PSR_MODE_EL1t
msr spsr_el2, \tmp
- adrp \tmp, 1f
- add \tmp, \tmp, :lo12:1f
+ adrp \tmp, 2f
+ add \tmp, \tmp, :lo12:2f
msr elr_el2, \tmp
eret
-1:
+2:
.endm
diff --git a/lib/arm64/asm/sysreg.h b/lib/arm64/asm/sysreg.h
index ed776716..f2d05018 100644
--- a/lib/arm64/asm/sysreg.h
+++ b/lib/arm64/asm/sysreg.h
@@ -80,6 +80,8 @@ asm(
#define ID_AA64MMFR0_EL1_FGT_SHIFT 56
#define ID_AA64MMFR0_EL1_FGT_FGT2 0x2
+#define ID_AA64MMFR1_EL1_VH_SHIFT 8
+
#define ICC_PMR_EL1 sys_reg(3, 0, 4, 6, 0)
#define ICC_SGI1R_EL1 sys_reg(3, 0, 12, 11, 5)
#define ICC_IAR1_EL1 sys_reg(3, 0, 12, 12, 0)
@@ -116,9 +118,12 @@ asm(
#define SCTLR_EL1_TCF0_SHIFT 38
#define SCTLR_EL1_TCF0_MASK GENMASK_ULL(39, 38)
+#define HCR_EL2_TGE _BITULL(27)
#define HCR_EL2_RW _BITULL(31)
+#define HCR_EL2_E2H _BITULL(34)
#define INIT_HCR_EL2_EL1_ONLY (HCR_EL2_RW)
+#define INIT_HCR_EL2 (HCR_EL2_TGE | HCR_EL2_E2H | HCR_EL2_RW)
#define SYS_HFGRTR_EL2 sys_reg(3, 4, 1, 1, 4)
#define SYS_HFGWTR_EL2 sys_reg(3, 4, 1, 1, 5)
--
2.25.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [kvm-unit-tests PATCH v2 2/9] arm64: efi: initialise SCTLR_ELx fully
2025-05-29 13:55 ` [kvm-unit-tests PATCH v2 2/9] arm64: efi: initialise SCTLR_ELx fully Joey Gouly
@ 2025-06-06 10:17 ` Suzuki K Poulose
0 siblings, 0 replies; 13+ messages in thread
From: Suzuki K Poulose @ 2025-06-06 10:17 UTC (permalink / raw)
To: Joey Gouly, kvm
Cc: alexandru.elisei, andrew.jones, kvmarm, Marc Zyngier,
Oliver Upton
On 29/05/2025 14:55, Joey Gouly wrote:
> Don't rely on the value of SCTLR_ELx when booting via EFI.
>
> Signed-off-by: Joey Gouly <joey.gouly@arm.com>
> ---
> lib/arm/setup.c | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/lib/arm/setup.c b/lib/arm/setup.c
> index 67b5db07..0a22dbab 100644
> --- a/lib/arm/setup.c
> +++ b/lib/arm/setup.c
> @@ -349,6 +349,11 @@ efi_status_t setup_efi(efi_bootinfo_t *efi_bootinfo)
> {
> efi_status_t status;
>
> +
> + // EFI exits boot services with SCTLR_ELx.M=1, so keep
> + // the MMU enabled.
> + write_sysreg(INIT_SCTLR_EL1_MMU_OFF | SCTLR_EL1_M, sctlr_el1);
minor nit: Given this is in a common file for arm/arm64, may be worth
adding a helper function that does this on arm64. I understand EFI
cannot enabled for arm32, still keeping this file generic would be
cleaner. e.g.,
mmu_on(); or even setup_sctlr();
Suzuki
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [kvm-unit-tests PATCH v2 0/9] arm64: support EL2
2025-05-29 13:55 [kvm-unit-tests PATCH v2 0/9] arm64: support EL2 Joey Gouly
` (8 preceding siblings ...)
2025-05-29 13:55 ` [kvm-unit-tests PATCH v2 9/9] arm64: run at EL2 if supported Joey Gouly
@ 2025-06-16 12:34 ` Alexandru Elisei
2025-06-17 12:49 ` Joey Gouly
9 siblings, 1 reply; 13+ messages in thread
From: Alexandru Elisei @ 2025-06-16 12:34 UTC (permalink / raw)
To: Joey Gouly; +Cc: kvm, andrew.jones, kvmarm, Marc Zyngier, Oliver Upton
Hi Joey,
On Thu, May 29, 2025 at 02:55:48PM +0100, Joey Gouly wrote:
> Hi all,
>
> This series is for adding support to running the kvm-unit-tests at EL2. These
> have been tested with Marc Zyngier's Linux kvm-arm64/nv-next branch [1] and
> kvmtool branch arm64/nv-6.13 [2]
>
> The goal is to later extend and add new tests for Nested Virtualisation,
> however they should also work with bare metal as well.
>
> Changes since v1[3]:
> - Authorship fixed on 2 patches
> - Tested and fixed EFI support
> - Recactored assembly and added init_el macro
> - Clear trap registers, trying to avoid relying on default register
> state
> - Cleaned up PMU changes
>
> The debug tests fail with --nested, but pass with --nested --e2h0, I
> need to investigate this.
That's because the code does not check for the absence of FEAT_E2H0, and it sets
HCR_EL2.E2H to 0 when writing INIT_HCR_EL2_EL1_ONLY even if KVM doesn't support
that.
Have you considered using parts of el2_setup.h as-is instead of rolling out your
own EL2 init code? When I was looking at the init_el macro I was comparing it
with el2_setup.h, and having some of the code shared would make things easier
with updates and fixes too.
Either way, not a deal breaker if you want to write your own init code.
Thanks,
Alex
>
> Thanks,
> Joey
>
> [1] https://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git kvm-arm64/nv-next (commit a35d752b17f4)
> [2] https://git.kernel.org/pub/scm/linux/kernel/git/maz/kvmtool.git arm64/nv-6.13 (commit 5b6fe295ea7)
> [3] https://lore.kernel.org/kvmarm/20250220141354.2565567-1-joey.gouly@arm.com/
>
> Alexandru Elisei (2):
> arm64: micro-bench: use smc when at EL2
> arm64: selftest: update test for running at EL2
>
> Joey Gouly (7):
> arm64: drop to EL1 if booted at EL2
> arm64: efi: initialise SCTLR_ELx fully
> arm64: efi: initialise the EL
> arm64: timer: use hypervisor timers when at EL2
> arm64: micro-bench: fix timer IRQ
> arm64: pmu: count EL2 cycles
> arm64: run at EL2 if supported
>
> arm/cstart64.S | 56 ++++++++++++++++++++++++++++++++++++--
> arm/efi/crt0-efi-aarch64.S | 5 ++++
> arm/micro-bench.c | 26 ++++++++++++++++--
> arm/pmu.c | 13 ++++++---
> arm/selftest.c | 18 ++++++++----
> arm/timer.c | 10 +++++--
> lib/acpi.h | 2 ++
> lib/arm/asm/setup.h | 1 +
> lib/arm/asm/timer.h | 11 ++++++++
> lib/arm/setup.c | 6 ++++
> lib/arm/timer.c | 19 +++++++++++--
> lib/arm64/asm/sysreg.h | 19 +++++++++++++
> 12 files changed, 167 insertions(+), 19 deletions(-)
>
> --
> 2.25.1
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [kvm-unit-tests PATCH v2 0/9] arm64: support EL2
2025-06-16 12:34 ` [kvm-unit-tests PATCH v2 0/9] arm64: support EL2 Alexandru Elisei
@ 2025-06-17 12:49 ` Joey Gouly
0 siblings, 0 replies; 13+ messages in thread
From: Joey Gouly @ 2025-06-17 12:49 UTC (permalink / raw)
To: Alexandru Elisei; +Cc: kvm, andrew.jones, kvmarm, Marc Zyngier, Oliver Upton
On Mon, Jun 16, 2025 at 01:34:17PM +0100, Alexandru Elisei wrote:
> Hi Joey,
>
> On Thu, May 29, 2025 at 02:55:48PM +0100, Joey Gouly wrote:
> > Hi all,
> >
> > This series is for adding support to running the kvm-unit-tests at EL2. These
> > have been tested with Marc Zyngier's Linux kvm-arm64/nv-next branch [1] and
> > kvmtool branch arm64/nv-6.13 [2]
> >
> > The goal is to later extend and add new tests for Nested Virtualisation,
> > however they should also work with bare metal as well.
> >
> > Changes since v1[3]:
> > - Authorship fixed on 2 patches
> > - Tested and fixed EFI support
> > - Recactored assembly and added init_el macro
> > - Clear trap registers, trying to avoid relying on default register
> > state
> > - Cleaned up PMU changes
> >
> > The debug tests fail with --nested, but pass with --nested --e2h0, I
> > need to investigate this.
>
> That's because the code does not check for the absence of FEAT_E2H0, and it sets
> HCR_EL2.E2H to 0 when writing INIT_HCR_EL2_EL1_ONLY even if KVM doesn't support
> that.
INIT_HCR_EL2_EL1_ONLY is only used if VHE is not supported, and if VHE is not
supported it's RES0. Patch 9 adds that.
>
> Have you considered using parts of el2_setup.h as-is instead of rolling out your
> own EL2 init code? When I was looking at the init_el macro I was comparing it
> with el2_setup.h, and having some of the code shared would make things easier
> with updates and fixes too.
>
> Either way, not a deal breaker if you want to write your own init code.
I'll look into it, making our own simplified el2_setup.h based on Linux's.
Thanks,
Joey
>
> Thanks,
> Alex
>
> >
> > Thanks,
> > Joey
> >
> > [1] https://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git kvm-arm64/nv-next (commit a35d752b17f4)
> > [2] https://git.kernel.org/pub/scm/linux/kernel/git/maz/kvmtool.git arm64/nv-6.13 (commit 5b6fe295ea7)
> > [3] https://lore.kernel.org/kvmarm/20250220141354.2565567-1-joey.gouly@arm.com/
> >
> > Alexandru Elisei (2):
> > arm64: micro-bench: use smc when at EL2
> > arm64: selftest: update test for running at EL2
> >
> > Joey Gouly (7):
> > arm64: drop to EL1 if booted at EL2
> > arm64: efi: initialise SCTLR_ELx fully
> > arm64: efi: initialise the EL
> > arm64: timer: use hypervisor timers when at EL2
> > arm64: micro-bench: fix timer IRQ
> > arm64: pmu: count EL2 cycles
> > arm64: run at EL2 if supported
> >
> > arm/cstart64.S | 56 ++++++++++++++++++++++++++++++++++++--
> > arm/efi/crt0-efi-aarch64.S | 5 ++++
> > arm/micro-bench.c | 26 ++++++++++++++++--
> > arm/pmu.c | 13 ++++++---
> > arm/selftest.c | 18 ++++++++----
> > arm/timer.c | 10 +++++--
> > lib/acpi.h | 2 ++
> > lib/arm/asm/setup.h | 1 +
> > lib/arm/asm/timer.h | 11 ++++++++
> > lib/arm/setup.c | 6 ++++
> > lib/arm/timer.c | 19 +++++++++++--
> > lib/arm64/asm/sysreg.h | 19 +++++++++++++
> > 12 files changed, 167 insertions(+), 19 deletions(-)
> >
> > --
> > 2.25.1
> >
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2025-06-17 12:49 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-05-29 13:55 [kvm-unit-tests PATCH v2 0/9] arm64: support EL2 Joey Gouly
2025-05-29 13:55 ` [kvm-unit-tests PATCH v2 1/9] arm64: drop to EL1 if booted at EL2 Joey Gouly
2025-05-29 13:55 ` [kvm-unit-tests PATCH v2 2/9] arm64: efi: initialise SCTLR_ELx fully Joey Gouly
2025-06-06 10:17 ` Suzuki K Poulose
2025-05-29 13:55 ` [kvm-unit-tests PATCH v2 3/9] arm64: efi: initialise the EL Joey Gouly
2025-05-29 13:55 ` [kvm-unit-tests PATCH v2 4/9] arm64: timer: use hypervisor timers when at EL2 Joey Gouly
2025-05-29 13:55 ` [kvm-unit-tests PATCH v2 5/9] arm64: micro-bench: fix timer IRQ Joey Gouly
2025-05-29 13:55 ` [kvm-unit-tests PATCH v2 6/9] arm64: micro-bench: use smc when at EL2 Joey Gouly
2025-05-29 13:55 ` [kvm-unit-tests PATCH v2 7/9] arm64: selftest: update test for running " Joey Gouly
2025-05-29 13:55 ` [kvm-unit-tests PATCH v2 8/9] arm64: pmu: count EL2 cycles Joey Gouly
2025-05-29 13:55 ` [kvm-unit-tests PATCH v2 9/9] arm64: run at EL2 if supported Joey Gouly
2025-06-16 12:34 ` [kvm-unit-tests PATCH v2 0/9] arm64: support EL2 Alexandru Elisei
2025-06-17 12:49 ` Joey Gouly
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).