[PATCH 2/6] arm: use propagated hyp stubs

45 views
Skip to first unread message

Ralf Ramsauer

unread,
Jun 12, 2017, 10:41:38 AM6/12/17
to jailho...@googlegroups.com, Jan Kiszka, Ralf Ramsauer
Do no longer use a hvc for getting Linux's hyp-stub vector address. We
now use the address in the hypervisor header.

Signed-off-by: Ralf Ramsauer <ralf.r...@oth-regensburg.de>
---
hypervisor/arch/arm/exception.S | 10 ----------
hypervisor/arch/arm/include/asm/processor.h | 2 --
hypervisor/arch/arm/mmu_hyp.c | 13 +------------
3 files changed, 1 insertion(+), 24 deletions(-)

diff --git a/hypervisor/arch/arm/exception.S b/hypervisor/arch/arm/exception.S
index 3348cecd..8c0ce6a8 100644
--- a/hypervisor/arch/arm/exception.S
+++ b/hypervisor/arch/arm/exception.S
@@ -70,13 +70,3 @@ vmreturn:
/* Restore usr regs */
pop {r0-r12, lr}
eret
-
- /*
- * Hypervisor calling convention follows the AAPCS:
- * r0-r3: arguments
- * r0: return value
- */
- .globl hvc
-hvc:
- hvc #0
- bx lr
diff --git a/hypervisor/arch/arm/include/asm/processor.h b/hypervisor/arch/arm/include/asm/processor.h
index 1ba9e45c..2efac288 100644
--- a/hypervisor/arch/arm/include/asm/processor.h
+++ b/hypervisor/arch/arm/include/asm/processor.h
@@ -39,8 +39,6 @@ struct registers {
#define dsb(domain) asm volatile("dsb " #domain ::: "memory")
#define isb() asm volatile("isb")

-unsigned int hvc(unsigned int r0, ...);
-
static inline void cpu_relax(void)
{
asm volatile("" : : : "memory");
diff --git a/hypervisor/arch/arm/mmu_hyp.c b/hypervisor/arch/arm/mmu_hyp.c
index ef2ec2ae..62fa8ed0 100644
--- a/hypervisor/arch/arm/mmu_hyp.c
+++ b/hypervisor/arch/arm/mmu_hyp.c
@@ -34,9 +34,6 @@ static struct {

extern unsigned long trampoline_start, trampoline_end;

-/* When disabling Jailhouse, we will need to restore the Linux stub */
-static unsigned long saved_vectors = 0;
-
static int set_id_map(int i, unsigned long address, unsigned long size)
{
if (i >= ARRAY_SIZE(id_maps))
@@ -274,14 +271,6 @@ int switch_exception_level(struct per_cpu *cpu_data)
PAGE_DEFAULT_FLAGS);

/*
- * The hypervisor stub allows to fetch its current vector base by doing
- * an HVC with r0 = -1. They will need to be restored when disabling
- * jailhouse.
- */
- if (saved_vectors == 0)
- saved_vectors = hvc(-1);
-
- /*
* paging struct won't be easily accessible when initializing el2, only
* the CPU datas will be readable at their physical address
*/
@@ -363,7 +352,7 @@ void __attribute__((noreturn)) arch_shutdown_mmu(struct per_cpu *cpu_data)
* - reset the vectors
* - return to EL1
*/
- shutdown_fun_phys(regs_phys, saved_vectors);
+ shutdown_fun_phys(regs_phys, hypervisor_header.arm_hyp_info.saved_vector);

__builtin_unreachable();
}
--
2.13.1

Ralf Ramsauer

unread,
Jun 12, 2017, 10:41:38 AM6/12/17
to jailho...@googlegroups.com, Jan Kiszka, Ralf Ramsauer
This is a preparation to choose between ABIs and reimplements the hvc in
inline assembly.

Signed-off-by: Ralf Ramsauer <ralf.r...@oth-regensburg.de>
---
hypervisor/arch/arm/mmu_hyp.c | 28 ++++++++++++++++++----------
1 file changed, 18 insertions(+), 10 deletions(-)

diff --git a/hypervisor/arch/arm/mmu_hyp.c b/hypervisor/arch/arm/mmu_hyp.c
index 62fa8ed0..eabe81c2 100644
--- a/hypervisor/arch/arm/mmu_hyp.c
+++ b/hypervisor/arch/arm/mmu_hyp.c
@@ -34,6 +34,20 @@ static struct {

extern unsigned long trampoline_start, trampoline_end;

+static inline unsigned int hvc(unsigned int r0, unsigned int r1)
+{
+ asm volatile(
+ "mov r0, %1\n\t"
+ "mov r1, %2\n\t"
+ "hvc #0\n\t"
+ "mov %0, r0\n\t"
+ : "=r" (r0)
+ : "r" (r0), "r" (r1)
+ : );
+
+ return r0;
+}
+
static int set_id_map(int i, unsigned long address, unsigned long size)
{
if (i >= ARRAY_SIZE(id_maps))
@@ -91,17 +105,10 @@ static void destroy_id_maps(void)
}

static void __attribute__((naked, noinline))
-cpu_switch_el2(unsigned long phys_bootstrap, virt2phys_t virt2phys)
+cpu_switch_el2(virt2phys_t virt2phys)
{
asm volatile(
/*
- * The linux hyp stub allows to install the vectors with a
- * single hvc. The vector base address is in r0
- * (phys_bootstrap).
- */
- "hvc #0\n\t"
-
- /*
* Now that the bootstrap vectors are installed, call setup_el2
* with the translated physical values of lr and sp as
* arguments.
@@ -122,7 +129,7 @@ cpu_switch_el2(unsigned long phys_bootstrap, virt2phys_t virt2phys)
* list ensures that the compiler uses a decent register for
* hvirt2phys.
*/
- : "cc", "memory", "r0", "r1", "r2", "r3");
+ : "cc", "memory", "r0", "r1", "r2", "r3", "lr");
}

/*
@@ -295,7 +302,8 @@ int switch_exception_level(struct per_cpu *cpu_data)
*/
arm_dcaches_clean_by_sw();

- cpu_switch_el2(phys_bootstrap, virt2phys);
+ hvc(phys_bootstrap, 0);
+ cpu_switch_el2(virt2phys);
/*
* At this point, we are at EL2, and we work with physical addresses.
* The MMU needs to be initialised and execution must go back to virtual
--
2.13.1

Ralf Ramsauer

unread,
Jun 12, 2017, 10:41:38 AM6/12/17
to jailho...@googlegroups.com, Jan Kiszka, Ralf Ramsauer
Same as for arm32, do no longer hvc for getting Linux's hyp-stub vector
address. We now use the address in the Hypervisor header.

For reasons of simplicity, we now restore vbar_el2 in inline assembly.

Signed-off-by: Ralf Ramsauer <ralf.r...@oth-regensburg.de>
---
hypervisor/arch/arm64/asm-defines.c | 1 -
hypervisor/arch/arm64/entry.S | 26 +++++---------------------
hypervisor/arch/arm64/include/asm/percpu.h | 1 -
hypervisor/arch/arm64/setup.c | 4 ++++
4 files changed, 9 insertions(+), 23 deletions(-)

diff --git a/hypervisor/arch/arm64/asm-defines.c b/hypervisor/arch/arm64/asm-defines.c
index 5a92b00a..d850b1aa 100644
--- a/hypervisor/arch/arm64/asm-defines.c
+++ b/hypervisor/arch/arm64/asm-defines.c
@@ -32,7 +32,6 @@ void common(void)
__builtin_offsetof(struct per_cpu, stack) + \
FIELD_SIZEOF(struct per_cpu, stack));
DEFINE(PERCPU_SIZE_SHIFT_ASM, PERCPU_SIZE_SHIFT);
- OFFSET(PERCPU_SAVED_VECTORS, per_cpu, saved_vectors);
BLANK();

DEFINE(DCACHE_CLEAN_ASM, DCACHE_CLEAN);
diff --git a/hypervisor/arch/arm64/entry.S b/hypervisor/arch/arm64/entry.S
index d1377c75..8dfdb249 100644
--- a/hypervisor/arch/arm64/entry.S
+++ b/hypervisor/arch/arm64/entry.S
@@ -18,7 +18,6 @@
#include <asm/percpu.h>
#include <asm/jailhouse_hypercall.h>

-#define LINUX_HVC_GET_VECTORS 0
#define LINUX_HVC_SET_VECTORS 1

/* x11 must contain the virt-to-phys offset */
@@ -45,17 +44,11 @@ arch_entry:
* x13: virtual hypervisor address
* x14: physical UART address
* x15: virtual UART address
- * x16: saved hyp vectors
- * x17: cpuid
- * x18: caller lr
+ * x16: cpuid
+ * x17: caller lr
*/
- mov x17, x0
- mov x18, x30
-
- /* keep the Linux stub EL2 vectors for later */
- mov x0, #LINUX_HVC_GET_VECTORS
- hvc #0
mov x16, x0
+ mov x17, x30

/*
* Access the just updated hypervisor_header prior to turning off the
@@ -128,7 +121,7 @@ el2_entry:
adr x1, hyp_vectors
msr vbar_el2, x1

- mov x0, x17 /* preserved cpuid, will be passed to entry */
+ mov x0, x16 /* preserved cpuid, will be passed to entry */
adrp x1, __page_pool
mov x2, #(1 << PERCPU_SIZE_SHIFT_ASM)
/*
@@ -139,7 +132,7 @@ el2_entry:

/* set up the stack and push the root cell's callee saved registers */
add sp, x1, #PERCPU_STACK_END
- stp x29, x18, [sp, #-16]! /* note: our caller lr is in x18 */
+ stp x29, x17, [sp, #-16]! /* note: our caller lr is in x17 */
stp x27, x28, [sp, #-16]!
stp x25, x26, [sp, #-16]!
stp x23, x24, [sp, #-16]!
@@ -156,10 +149,6 @@ el2_entry:
mov x29, xzr /* reset fp,lr */
mov x30, xzr

- /* save the Linux stub vectors we kept earlier */
- add x2, x1, #PERCPU_SAVED_VECTORS
- str x16, [x2]
-
/* Call entry(cpuid, struct per_cpu*). Should not return. */
bl entry
b .
@@ -189,11 +178,6 @@ shutdown_el2:

msr tpidr_el2, xzr

- /* hand over control of EL2 back to Linux */
- add x1, x0, #PERCPU_SAVED_VECTORS
- ldr x2, [x1]
- msr vbar_el2, x2
-
/* Call vmreturn(guest_registers) */
add x0, x0, #(PERCPU_STACK_END - 32 * 8)
b vmreturn
diff --git a/hypervisor/arch/arm64/include/asm/percpu.h b/hypervisor/arch/arm64/include/asm/percpu.h
index f00b8fb4..5bfece6d 100644
--- a/hypervisor/arch/arm64/include/asm/percpu.h
+++ b/hypervisor/arch/arm64/include/asm/percpu.h
@@ -27,7 +27,6 @@

struct per_cpu {
u8 stack[PAGE_SIZE];
- unsigned long saved_vectors;

/* common fields */
unsigned int cpu_id;
diff --git a/hypervisor/arch/arm64/setup.c b/hypervisor/arch/arm64/setup.c
index 0e49bb09..6ba002a0 100644
--- a/hypervisor/arch/arm64/setup.c
+++ b/hypervisor/arch/arm64/setup.c
@@ -131,6 +131,10 @@ void arch_shutdown_self(struct per_cpu *cpu_data)
arch_paging_flush_cpu_caches(cpu_data, sizeof(*cpu_data));
dsb(ish);

+ /* hand over control of EL2 back to Linux */
+ asm volatile("msr vbar_el2, %0"
+ :: "r" (hypervisor_header.arm_hyp_info.saved_vector) :);
+
/* Return to EL1 */
shutdown_func((struct per_cpu *)paging_hvirt2phys(cpu_data));
}
--
2.13.1

Ralf Ramsauer

unread,
Jun 12, 2017, 10:41:38 AM6/12/17
to jailho...@googlegroups.com, Jan Kiszka, Ralf Ramsauer
Linux's hyp-stub ABI changed since 4.12-rc1. This patch changes the ABI
for 4.12+, and preserves backward compatibility

Signed-off-by: Ralf Ramsauer <ralf.r...@oth-regensburg.de>
---
driver/main.c | 5 +++++
hypervisor/arch/arm/mmu_hyp.c | 11 ++++++++++-
hypervisor/include/jailhouse/header.h | 10 ++++++++++
3 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/driver/main.c b/driver/main.c
index 60ea7b4a..42f2edb0 100644
--- a/driver/main.c
+++ b/driver/main.c
@@ -445,6 +445,11 @@ static int jailhouse_cmd_enable(struct jailhouse_system __user *arg)

#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
header->arm_hyp_info.saved_vector = virt_to_phys(__hyp_stub_vectors);
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(4,11,200)
+ header->arm_hyp_info.version = HYP_STUB_ABI_LEGACY;
+#else
+ header->arm_hyp_info.version = HYP_STUB_ABI_OPCODE;
+#endif
#endif

err = jailhouse_sysfs_core_init(jailhouse_dev, header->core_size);
diff --git a/hypervisor/arch/arm/mmu_hyp.c b/hypervisor/arch/arm/mmu_hyp.c
index eabe81c2..18a8b183 100644
--- a/hypervisor/arch/arm/mmu_hyp.c
+++ b/hypervisor/arch/arm/mmu_hyp.c
@@ -16,6 +16,10 @@
#include <asm/setup.h>
#include <asm/sysregs.h>

+/* This is only used if we use the new hyp-stub ABI that was introduced in
+ * 4.12-rc1 */
+#define LINUX_HVC_SET_VECTOR 0
+
/* functions used for translating addresses during the MMU setup process */
typedef void* (*phys2virt_t)(unsigned long);
typedef unsigned long (*virt2phys_t)(volatile const void *);
@@ -302,7 +306,12 @@ int switch_exception_level(struct per_cpu *cpu_data)
*/
arm_dcaches_clean_by_sw();

- hvc(phys_bootstrap, 0);
+ /* Hyp stub ABI version changed since 4.12-rc1 on ARM */
+ if (hypervisor_header.arm_hyp_info.version == HYP_STUB_ABI_LEGACY)
+ hvc(phys_bootstrap, 0);
+ else
+ hvc(LINUX_HVC_SET_VECTOR, phys_bootstrap);
+
cpu_switch_el2(virt2phys);
/*
* At this point, we are at EL2, and we work with physical addresses.
diff --git a/hypervisor/include/jailhouse/header.h b/hypervisor/include/jailhouse/header.h
index c2332de9..5924af22 100644
--- a/hypervisor/include/jailhouse/header.h
+++ b/hypervisor/include/jailhouse/header.h
@@ -14,6 +14,11 @@

#define JAILHOUSE_SIGNATURE "JAILHOUS"

+#define HYP_STUB_ABI_LEGACY 0
+#define HYP_STUB_ABI_OPCODE 1
+
+#ifndef __ASSEMBLY__
+
/**
* @ingroup Setup
* @{
@@ -79,5 +84,10 @@ struct jailhouse_header {
/** Physical address of Linux's hyp-stubs.
* @note Filled by Linux loader driver before entry. */
unsigned long long saved_vector;
+ /** Denotes hyp-stub ABI for arm and arm64:
+ * @note Filled by Linux loader driver before entry. */
+ unsigned int version;
} arm_hyp_info;
};
+
+#endif
--
2.13.1

Ralf Ramsauer

unread,
Jun 12, 2017, 10:41:38 AM6/12/17
to jailho...@googlegroups.com, Jan Kiszka, Ralf Ramsauer
Linux hyp-stub ABI changed in 4.12. On arm64 Opcodes changed, and arm32
ABI is now the same as for ARM64. Additionaly, the HVC_GET_VECTOR call
was removed.

We need to save those vectors before installing our hypervisor as we
needd to restore them if we disable Jailhouse.

The easiest solution is to export __hyp_stub_vector in Linux and to
propagate it to Jailhouse through the hypervisor header.

Signed-off-by: Ralf Ramsauer <ralf.r...@oth-regensburg.de>
---
driver/main.c | 8 ++++++++
hypervisor/include/jailhouse/header.h | 6 ++++++
2 files changed, 14 insertions(+)

diff --git a/driver/main.c b/driver/main.c
index 1dfe0a6d..60ea7b4a 100644
--- a/driver/main.c
+++ b/driver/main.c
@@ -75,6 +75,10 @@ MODULE_FIRMWARE(JAILHOUSE_FW_NAME);
#endif
MODULE_VERSION(JAILHOUSE_VERSION);

+#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
+extern unsigned int __hyp_stub_vectors[];
+#endif
+
struct console_state {
unsigned int head;
unsigned int last_console_id;
@@ -439,6 +443,10 @@ static int jailhouse_cmd_enable(struct jailhouse_system __user *arg)
header = (struct jailhouse_header *)hypervisor_mem;
header->max_cpus = max_cpus;

+#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
+ header->arm_hyp_info.saved_vector = virt_to_phys(__hyp_stub_vectors);
+#endif
+
err = jailhouse_sysfs_core_init(jailhouse_dev, header->core_size);
if (err)
goto error_unmap;
diff --git a/hypervisor/include/jailhouse/header.h b/hypervisor/include/jailhouse/header.h
index 738389bb..c2332de9 100644
--- a/hypervisor/include/jailhouse/header.h
+++ b/hypervisor/include/jailhouse/header.h
@@ -74,4 +74,10 @@ struct jailhouse_header {
/** Virtual address of the clock gate register (if used).
* @note Filled by Linux loader driver before entry. */
void *debug_clock_reg;
+
+ struct {
+ /** Physical address of Linux's hyp-stubs.
+ * @note Filled by Linux loader driver before entry. */
+ unsigned long long saved_vector;
+ } arm_hyp_info;
};
--
2.13.1

Ralf Ramsauer

unread,
Jun 12, 2017, 10:41:38 AM6/12/17
to jailho...@googlegroups.com, Jan Kiszka, Ralf Ramsauer
[sorry for resend, Google dropped some of my mails]

Hi,

Linux hyp-stub ABI changed upstream. Opcodes were switched for arm64, and arm64
and arm32 now share the same ABI. HVC_GET_VECTOR call was removed. This
series aligns Jailhouse to those changes.

We now need one more Linux Patch for Linux. Find the Linux patch below.

Ralf

Ralf Ramsauer (6):
arm, arm64: propagate __hyp_stub_vector
arm: use propagated hyp stubs
arm64: use propagated vectors
arm: reimplement hvc in inline assembly
arm: support new hyp-stub ABI
arm64: align hyp-stub opcodes

driver/main.c | 13 ++++++++
hypervisor/arch/arm/exception.S | 10 ------
hypervisor/arch/arm/include/asm/processor.h | 2 --
hypervisor/arch/arm/mmu_hyp.c | 48 ++++++++++++++++-------------
hypervisor/arch/arm64/asm-defines.c | 2 +-
hypervisor/arch/arm64/entry.S | 41 +++++++++++-------------
hypervisor/arch/arm64/include/asm/percpu.h | 1 -
hypervisor/arch/arm64/setup.c | 4 +++
hypervisor/include/jailhouse/header.h | 16 ++++++++++
9 files changed, 79 insertions(+), 58 deletions(-)

--
2.13.1


From 321d2d6d5a88d0a3bd11f113300167a85233c356 Mon Sep 17 00:00:00 2001
From: Ralf Ramsauer <ralf.r...@oth-regensburg.de>
Date: Wed, 7 Jun 2017 15:48:43 +0200
Subject: [Linux PATCH] arm, arm64: export __hyp_stub_vectors

HVC_GET_VECTORS got removed. External hypervisors, like Jailhouse, need
this address when they are deactivated, in order to restore original
state.

Signed-off-by: Ralf Ramsauer <ralf.r...@oth-regensburg.de>
---
arch/arm/kernel/hyp-stub.S | 2 ++
arch/arm64/kernel/hyp-stub.S | 2 ++
2 files changed, 4 insertions(+)

diff --git a/arch/arm/kernel/hyp-stub.S b/arch/arm/kernel/hyp-stub.S
index ec7e7377d423..83e65f01ca7f 100644
--- a/arch/arm/kernel/hyp-stub.S
+++ b/arch/arm/kernel/hyp-stub.S
@@ -19,6 +19,7 @@
#include <linux/init.h>
#include <linux/irqchip/arm-gic-v3.h>
#include <linux/linkage.h>
+#include <asm-generic/export.h>
#include <asm/assembler.h>
#include <asm/virt.h>

@@ -281,4 +282,5 @@ __hyp_stub_trap: W(b) __hyp_stub_do_trap
__hyp_stub_irq: W(b) .
__hyp_stub_fiq: W(b) .
ENDPROC(__hyp_stub_vectors)
+EXPORT_SYMBOL_GPL(__hyp_stub_vectors)

diff --git a/arch/arm64/kernel/hyp-stub.S b/arch/arm64/kernel/hyp-stub.S
index e1261fbaa374..061b32ef7c74 100644
--- a/arch/arm64/kernel/hyp-stub.S
+++ b/arch/arm64/kernel/hyp-stub.S
@@ -21,6 +21,7 @@
#include <linux/linkage.h>
#include <linux/irqchip/arm-gic-v3.h>

+#include <asm-generic/export.h>
#include <asm/assembler.h>
#include <asm/kvm_arm.h>
#include <asm/kvm_asm.h>
@@ -51,6 +52,7 @@ ENTRY(__hyp_stub_vectors)
ventry el1_fiq_invalid // FIQ 32-bit EL1
ventry el1_error_invalid // Error 32-bit EL1
ENDPROC(__hyp_stub_vectors)
+EXPORT_SYMBOL_GPL(__hyp_stub_vectors)

.align 11

--
2.13.1

Ralf Ramsauer

unread,
Jun 12, 2017, 10:41:38 AM6/12/17
to jailho...@googlegroups.com, Jan Kiszka, Ralf Ramsauer
Opcodes for arm64 Linux hyp-stub ABI switched since 4.12+. This patch
dynamically uses the correct opcode and preserves backward
compatibility.

Signed-off-by: Ralf Ramsauer <ralf.r...@oth-regensburg.de>
---
hypervisor/arch/arm64/asm-defines.c | 1 +
hypervisor/arch/arm64/entry.S | 15 +++++++++++++--
2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/hypervisor/arch/arm64/asm-defines.c b/hypervisor/arch/arm64/asm-defines.c
index d850b1aa..ff5181ef 100644
--- a/hypervisor/arch/arm64/asm-defines.c
+++ b/hypervisor/arch/arm64/asm-defines.c
@@ -22,6 +22,7 @@ void common(void)
{
OFFSET(HEADER_MAX_CPUS, jailhouse_header, max_cpus);
OFFSET(HEADER_DEBUG_CONSOLE_VIRT, jailhouse_header, debug_console_base);
+ OFFSET(HEADER_HYP_STUB_VERSION, jailhouse_header, arm_hyp_info.version);
OFFSET(SYSCONFIG_DEBUG_CONSOLE_PHYS, jailhouse_system,
debug_console.address);
OFFSET(SYSCONFIG_HYPERVISOR_PHYS, jailhouse_system,
diff --git a/hypervisor/arch/arm64/entry.S b/hypervisor/arch/arm64/entry.S
index 8dfdb249..6f16b326 100644
--- a/hypervisor/arch/arm64/entry.S
+++ b/hypervisor/arch/arm64/entry.S
@@ -17,8 +17,10 @@
#include <asm/paging.h>
#include <asm/percpu.h>
#include <asm/jailhouse_hypercall.h>
+#include <jailhouse/header.h>

-#define LINUX_HVC_SET_VECTORS 1
+#define LINUX_HVC_SET_VECTORS_LEGACY 1
+#define LINUX_HVC_SET_VECTORS 0

/* x11 must contain the virt-to-phys offset */
.macro virt2phys, register
@@ -46,6 +48,7 @@ arch_entry:
* x15: virtual UART address
* x16: cpuid
* x17: caller lr
+ * x18: hyp-stub version
*/
mov x16, x0
mov x17, x30
@@ -56,6 +59,8 @@ arch_entry:
*/
adr x0, hypervisor_header

+ ldr x18, [x0, #HEADER_HYP_STUB_VERSION]
+
ldr x15, =UART_BASE

adrp x1, __page_pool
@@ -93,9 +98,15 @@ arch_entry:
*/

/* install bootstrap_vectors */
- mov x0, #LINUX_HVC_SET_VECTORS
ldr x1, =bootstrap_vectors
virt2phys x1
+
+ /* choose opcode */
+ mov x0, #LINUX_HVC_SET_VECTORS
+ cmp x18, #HYP_STUB_ABI_LEGACY
+ b.ne 1f
+ mov x0, #LINUX_HVC_SET_VECTORS_LEGACY
+1:
hvc #0

hvc #0 /* bootstrap vectors enter EL2 at el2_entry */
--
2.13.1

Jan Kiszka

unread,
Jun 13, 2017, 3:56:46 AM6/13/17
to Ralf Ramsauer, jailho...@googlegroups.com
I think we can postpone the usage of a struct until we have more to
encapsulate. arm_linux_hyp_vectors?

Jan

--
Siemens AG, Corporate Technology, CT RDA ITP SES-DE
Corporate Competence Center Embedded Linux

Jan Kiszka

unread,
Jun 13, 2017, 3:57:04 AM6/13/17
to Ralf Ramsauer, jailho...@googlegroups.com
On 2017-06-12 16:41, Ralf Ramsauer wrote:
> Same as for arm32, do no longer hvc for getting Linux's hyp-stub vector

arm64

Jan

Jan Kiszka

unread,
Jun 13, 2017, 3:57:37 AM6/13/17
to Ralf Ramsauer, jailho...@googlegroups.com
On 2017-06-12 16:41, Ralf Ramsauer wrote:
> This is a preparation to choose between ABIs and reimplements the hvc in
> inline assembly.
>
> Signed-off-by: Ralf Ramsauer <ralf.r...@oth-regensburg.de>
> ---
> hypervisor/arch/arm/mmu_hyp.c | 28 ++++++++++++++++++----------
> 1 file changed, 18 insertions(+), 10 deletions(-)
>
> diff --git a/hypervisor/arch/arm/mmu_hyp.c b/hypervisor/arch/arm/mmu_hyp.c
> index 62fa8ed0..eabe81c2 100644
> --- a/hypervisor/arch/arm/mmu_hyp.c
> +++ b/hypervisor/arch/arm/mmu_hyp.c
> @@ -34,6 +34,20 @@ static struct {
>
> extern unsigned long trampoline_start, trampoline_end;
>
> +static inline unsigned int hvc(unsigned int r0, unsigned int r1)
> +{
> + asm volatile(
> + "mov r0, %1\n\t"
> + "mov r1, %2\n\t"

Look at hypervisor/arch/arm/include/asm/jailhouse_hypercall.h: You may
avoid forcing in these two instructions.
Would be good to either leave a comment on what this hvc is about or use
a symbolic constant for code "0" that is telling enough.

> + cpu_switch_el2(virt2phys);
> /*
> * At this point, we are at EL2, and we work with physical addresses.
> * The MMU needs to be initialised and execution must go back to virtual
>

Breaking up cpu_switch_el2 first looked a bit frightening, but it is
setup_mmu_el2 on that trampoline page which is sensitive towards
refactorings.

Jan

Jan Kiszka

unread,
Jun 13, 2017, 3:59:47 AM6/13/17
to Ralf Ramsauer, jailho...@googlegroups.com
Ah, there will be more in the end. Anyway, that's only temporarily.
Eventually, we will remove the support for older kernels again. What
will remain then is only the saved_vectors.

Ralf Ramsauer

unread,
Jun 13, 2017, 6:23:16 AM6/13/17
to Jan Kiszka, jailho...@googlegroups.com
Ok. Is it OK that those fields are visible for all architectures, even
for x86 where they are unused? CONFIG_ flags are not visible in this header.

Ralf
>
> Jan
>

Ralf Ramsauer

unread,
Jun 13, 2017, 6:23:18 AM6/13/17
to Jan Kiszka, jailho...@googlegroups.com


On 06/13/2017 09:57 AM, Jan Kiszka wrote:
> On 2017-06-12 16:41, Ralf Ramsauer wrote:
>> This is a preparation to choose between ABIs and reimplements the hvc in
>> inline assembly.
>>
>> Signed-off-by: Ralf Ramsauer <ralf.r...@oth-regensburg.de>
>> ---
>> hypervisor/arch/arm/mmu_hyp.c | 28 ++++++++++++++++++----------
>> 1 file changed, 18 insertions(+), 10 deletions(-)
>>
>> diff --git a/hypervisor/arch/arm/mmu_hyp.c b/hypervisor/arch/arm/mmu_hyp.c
>> index 62fa8ed0..eabe81c2 100644
>> --- a/hypervisor/arch/arm/mmu_hyp.c
>> +++ b/hypervisor/arch/arm/mmu_hyp.c
>> @@ -34,6 +34,20 @@ static struct {
>>
>> extern unsigned long trampoline_start, trampoline_end;
>>
>> +static inline unsigned int hvc(unsigned int r0, unsigned int r1)
>> +{
>> + asm volatile(
>> + "mov r0, %1\n\t"
>> + "mov r1, %2\n\t"
>
> Look at hypervisor/arch/arm/include/asm/jailhouse_hypercall.h: You may
> avoid forcing in these two instructions.
In the end, r0 and r1 are already in those two registers. The compiler
will optimise it away in any case.

Pinning the variables to temporary register variables ends up in the
same code, but I can change that.
Oh, this is a fragment that is left over from earlier tries. Let me
check if we can remove lr from the clobber list now.
>> }
>>
>> /*
>> @@ -295,7 +302,8 @@ int switch_exception_level(struct per_cpu *cpu_data)
>> */
>> arm_dcaches_clean_by_sw();
>>
>> - cpu_switch_el2(phys_bootstrap, virt2phys);
>> + hvc(phys_bootstrap, 0);
>
> Would be good to either leave a comment on what this hvc is about or use
> a symbolic constant for code "0" that is telling enough.
Comment is better... There is no particular semantic behind the '0'. The
old ABI does not care about r1, so I simply zeroed it. But in this way,
we can share the hvc functions for both ABIs.
>
>> + cpu_switch_el2(virt2phys);
>> /*
>> * At this point, we are at EL2, and we work with physical addresses.
>> * The MMU needs to be initialised and execution must go back to virtual
>>
>
> Breaking up cpu_switch_el2 first looked a bit frightening, but it is
> setup_mmu_el2 on that trampoline page which is sensitive towards
> refactorings.
Oh yes, it took a while to find a working path :)
Smallest changes lead to undesired behavior...

Ralf
>
> Jan
>

Jan Kiszka

unread,
Jun 13, 2017, 6:29:15 AM6/13/17
to Ralf Ramsauer, jailho...@googlegroups.com
As long as the compiler does not emit pointless

mov rX, #value
mov r0, rX

sequences, I'm fine with either option.

Jan Kiszka

unread,
Jun 13, 2017, 6:29:52 AM6/13/17
to Ralf Ramsauer, jailho...@googlegroups.com
On 2017-06-13 12:23, Ralf Ramsauer wrote:
>
>
Yes, that is harmless padding.

Ralf Ramsauer

unread,
Jun 13, 2017, 8:32:49 AM6/13/17
to jailho...@googlegroups.com, Jan Kiszka


On 06/12/2017 04:41 PM, Ralf Ramsauer wrote:
> Linux's hyp-stub ABI changed since 4.12-rc1. This patch changes the ABI
> for 4.12+, and preserves backward compatibility
>
> Signed-off-by: Ralf Ramsauer <ralf.r...@oth-regensburg.de>
> ---
> driver/main.c | 5 +++++
> hypervisor/arch/arm/mmu_hyp.c | 11 ++++++++++-
> hypervisor/include/jailhouse/header.h | 10 ++++++++++
> 3 files changed, 25 insertions(+), 1 deletion(-)
>
> diff --git a/driver/main.c b/driver/main.c
> index 60ea7b4a..42f2edb0 100644
> --- a/driver/main.c
> +++ b/driver/main.c
> @@ -445,6 +445,11 @@ static int jailhouse_cmd_enable(struct jailhouse_system __user *arg)
>
> #if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
> header->arm_hyp_info.saved_vector = virt_to_phys(__hyp_stub_vectors);
> +#if LINUX_VERSION_CODE <= KERNEL_VERSION(4,11,200)
Is this version check OK?

I check for 4.11.200 as there is no possibility to check for 4.12-rc1.
If I would check for 4.12 then the regression window would be bigger.

Ralf

Jan Kiszka

unread,
Jun 13, 2017, 8:34:38 AM6/13/17
to Ralf Ramsauer, jailho...@googlegroups.com
On 2017-06-13 14:32, Ralf Ramsauer wrote:
>
>
> On 06/12/2017 04:41 PM, Ralf Ramsauer wrote:
>> Linux's hyp-stub ABI changed since 4.12-rc1. This patch changes the ABI
>> for 4.12+, and preserves backward compatibility
>>
>> Signed-off-by: Ralf Ramsauer <ralf.r...@oth-regensburg.de>
>> ---
>> driver/main.c | 5 +++++
>> hypervisor/arch/arm/mmu_hyp.c | 11 ++++++++++-
>> hypervisor/include/jailhouse/header.h | 10 ++++++++++
>> 3 files changed, 25 insertions(+), 1 deletion(-)
>>
>> diff --git a/driver/main.c b/driver/main.c
>> index 60ea7b4a..42f2edb0 100644
>> --- a/driver/main.c
>> +++ b/driver/main.c
>> @@ -445,6 +445,11 @@ static int jailhouse_cmd_enable(struct jailhouse_system __user *arg)
>>
>> #if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
>> header->arm_hyp_info.saved_vector = virt_to_phys(__hyp_stub_vectors);
>> +#if LINUX_VERSION_CODE <= KERNEL_VERSION(4,11,200)
> Is this version check OK?
>
> I check for 4.11.200 as there is no possibility to check for 4.12-rc1.
> If I would check for 4.12 then the regression window would be bigger.

Good point: this has to be (4,12,0) - we are aiming at the final release.

Ralf Ramsauer

unread,
Jun 13, 2017, 10:16:47 AM6/13/17
to jailho...@googlegroups.com, Jan Kiszka, Ralf Ramsauer
Do no longer use a hvc for getting Linux's hyp-stub vector address. We
now use the address in the hypervisor header.

Signed-off-by: Ralf Ramsauer <ralf.r...@oth-regensburg.de>
---
diff --git a/hypervisor/arch/arm/mmu_hyp.c b/hypervisor/arch/arm/mmu_hyp.c
index ef2ec2ae..1fdebfc8 100644
--- a/hypervisor/arch/arm/mmu_hyp.c
+++ b/hypervisor/arch/arm/mmu_hyp.c
@@ -34,9 +34,6 @@ static struct {

extern unsigned long trampoline_start, trampoline_end;

-/* When disabling Jailhouse, we will need to restore the Linux stub */
-static unsigned long saved_vectors = 0;
-
static int set_id_map(int i, unsigned long address, unsigned long size)
{
if (i >= ARRAY_SIZE(id_maps))
@@ -274,14 +271,6 @@ int switch_exception_level(struct per_cpu *cpu_data)
PAGE_DEFAULT_FLAGS);

/*
- * The hypervisor stub allows to fetch its current vector base by doing
- * an HVC with r0 = -1. They will need to be restored when disabling
- * jailhouse.
- */
- if (saved_vectors == 0)
- saved_vectors = hvc(-1);
-
- /*
* paging struct won't be easily accessible when initializing el2, only
* the CPU datas will be readable at their physical address
*/
@@ -363,7 +352,7 @@ void __attribute__((noreturn)) arch_shutdown_mmu(struct per_cpu *cpu_data)
* - reset the vectors
* - return to EL1
*/
- shutdown_fun_phys(regs_phys, saved_vectors);
+ shutdown_fun_phys(regs_phys, hypervisor_header.arm_linux_hyp_vectors);

__builtin_unreachable();
}
--
2.13.1

Ralf Ramsauer

unread,
Jun 13, 2017, 10:16:47 AM6/13/17
to jailho...@googlegroups.com, Jan Kiszka, Ralf Ramsauer
Linux hyp-stub ABI changed in 4.12. On arm64 Opcodes changed, and arm32
ABI is now the same as for ARM64. Additionaly, the HVC_GET_VECTOR call
was removed.

We need to save those vectors before installing our hypervisor as we
needd to restore them if we disable Jailhouse.

The easiest solution is to export __hyp_stub_vector in Linux and to
propagate it to Jailhouse through the hypervisor header.

Signed-off-by: Ralf Ramsauer <ralf.r...@oth-regensburg.de>
---
driver/main.c | 8 ++++++++
hypervisor/include/jailhouse/header.h | 4 ++++
2 files changed, 12 insertions(+)

diff --git a/driver/main.c b/driver/main.c
index 1dfe0a6d..8234b82c 100644
--- a/driver/main.c
+++ b/driver/main.c
@@ -75,6 +75,10 @@ MODULE_FIRMWARE(JAILHOUSE_FW_NAME);
#endif
MODULE_VERSION(JAILHOUSE_VERSION);

+#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
+extern unsigned int __hyp_stub_vectors[];
+#endif
+
struct console_state {
unsigned int head;
unsigned int last_console_id;
@@ -439,6 +443,10 @@ static int jailhouse_cmd_enable(struct jailhouse_system __user *arg)
header = (struct jailhouse_header *)hypervisor_mem;
header->max_cpus = max_cpus;

+#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
+ header->arm_linux_hyp_vectors = virt_to_phys(__hyp_stub_vectors);
+#endif
+
err = jailhouse_sysfs_core_init(jailhouse_dev, header->core_size);
if (err)
goto error_unmap;
diff --git a/hypervisor/include/jailhouse/header.h b/hypervisor/include/jailhouse/header.h
index 738389bb..0a9045b1 100644
--- a/hypervisor/include/jailhouse/header.h
+++ b/hypervisor/include/jailhouse/header.h
@@ -74,4 +74,8 @@ struct jailhouse_header {
/** Virtual address of the clock gate register (if used).
* @note Filled by Linux loader driver before entry. */
void *debug_clock_reg;
+
+ /** Physical address of Linux's hyp-stubs.
+ * @note Filled by Linux loader driver before entry. */
+ unsigned long long arm_linux_hyp_vectors;
};
--
2.13.1

Ralf Ramsauer

unread,
Jun 13, 2017, 10:16:47 AM6/13/17
to jailho...@googlegroups.com, Jan Kiszka, Ralf Ramsauer
Signed-off-by: Ralf Ramsauer <ralf.r...@oth-regensburg.de>
---
hypervisor/arch/arm/mmu_hyp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hypervisor/arch/arm/mmu_hyp.c b/hypervisor/arch/arm/mmu_hyp.c
index 1febad54..ef2ec2ae 100644
--- a/hypervisor/arch/arm/mmu_hyp.c
+++ b/hypervisor/arch/arm/mmu_hyp.c
@@ -44,7 +44,7 @@ static int set_id_map(int i, unsigned long address, unsigned long size)

/* The trampoline code should be contained in one page. */
if ((address & PAGE_MASK) != ((address + size - 1) & PAGE_MASK)) {
- printk("FATAL: Unable to IDmap more than one page at at time.\n");
+ printk("FATAL: Unable to IDmap more than one page at a time.\n");
return -E2BIG;
}

--
2.13.1

Ralf Ramsauer

unread,
Jun 13, 2017, 10:16:47 AM6/13/17
to jailho...@googlegroups.com, Jan Kiszka, Ralf Ramsauer
Hi,

Linux hyp-stub ABI changed upstream. Opcodes were switched for arm64, and arm64
and arm32 now share the same ABI. HVC_GET_VECTOR call was removed. This
series aligns Jailhouse to those changes.

We now need one more Linux Patch for Linux. Find the Linux patch below.

Ralf

since v1:
- address comments
- use register-pinned temporary variables instead of mov's
- no nested structure in hv header
- remove "lr" from clobber list
- KERNEL_VERSION(4, 12, 0)
- add trivial typo fix

Ralf Ramsauer (7):
arm: fix typo
arm, arm64: propagate __hyp_stub_vector
arm: use propagated hyp stubs
arm64: use propagated vectors
arm: reimplement hvc in inline assembly
arm: support new hyp-stub ABI
arm64: align hyp-stub opcodes

driver/main.c | 13 +++++++
hypervisor/arch/arm/exception.S | 10 ------
hypervisor/arch/arm/include/asm/processor.h | 2 --
hypervisor/arch/arm/mmu_hyp.c | 55 ++++++++++++++++++-----------
hypervisor/arch/arm64/asm-defines.c | 2 +-
hypervisor/arch/arm64/entry.S | 41 ++++++++++-----------
hypervisor/arch/arm64/include/asm/percpu.h | 1 -
hypervisor/arch/arm64/setup.c | 4 +++
hypervisor/include/jailhouse/header.h | 14 ++++++++
9 files changed, 84 insertions(+), 58 deletions(-)

--
2.13.1

From 321d2d6d5a88d0a3bd11f113300167a85233c356 Mon Sep 17 00:00:00 2001
From: Ralf Ramsauer <ralf.r...@oth-regensburg.de>
Date: Wed, 7 Jun 2017 15:48:43 +0200
Subject: [Linux PATCH] arm, arm64: export __hyp_stub_vectors

HVC_GET_VECTORS got removed. External hypervisors, like Jailhouse, need
this address when they are deactivated, in order to restore original
state.

Signed-off-by: Ralf Ramsauer <ralf.r...@oth-regensburg.de>
---

Ralf Ramsauer

unread,
Jun 13, 2017, 10:16:48 AM6/13/17
to jailho...@googlegroups.com, Jan Kiszka, Ralf Ramsauer
Opcodes for arm64 Linux hyp-stub ABI switched since 4.12+. This patch
dynamically uses the correct opcode and preserves backward
compatibility.

Signed-off-by: Ralf Ramsauer <ralf.r...@oth-regensburg.de>
---
hypervisor/arch/arm64/asm-defines.c | 1 +
hypervisor/arch/arm64/entry.S | 15 +++++++++++++--
2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/hypervisor/arch/arm64/asm-defines.c b/hypervisor/arch/arm64/asm-defines.c
index d850b1aa..58669a4b 100644
--- a/hypervisor/arch/arm64/asm-defines.c
+++ b/hypervisor/arch/arm64/asm-defines.c
@@ -22,6 +22,7 @@ void common(void)
{
OFFSET(HEADER_MAX_CPUS, jailhouse_header, max_cpus);
OFFSET(HEADER_DEBUG_CONSOLE_VIRT, jailhouse_header, debug_console_base);
+ OFFSET(HEADER_HYP_STUB_VERSION, jailhouse_header, arm_linux_hyp_abi);
OFFSET(SYSCONFIG_DEBUG_CONSOLE_PHYS, jailhouse_system,
debug_console.address);
OFFSET(SYSCONFIG_HYPERVISOR_PHYS, jailhouse_system,
diff --git a/hypervisor/arch/arm64/entry.S b/hypervisor/arch/arm64/entry.S
index 8dfdb249..6f16b326 100644
--- a/hypervisor/arch/arm64/entry.S
+++ b/hypervisor/arch/arm64/entry.S
@@ -17,8 +17,10 @@
#include <asm/paging.h>
#include <asm/percpu.h>
#include <asm/jailhouse_hypercall.h>
+#include <jailhouse/header.h>

-#define LINUX_HVC_SET_VECTORS 1
+#define LINUX_HVC_SET_VECTORS_LEGACY 1
+#define LINUX_HVC_SET_VECTORS 0

/* x11 must contain the virt-to-phys offset */
.macro virt2phys, register
@@ -46,6 +48,7 @@ arch_entry:
* x15: virtual UART address

Ralf Ramsauer

unread,
Jun 13, 2017, 10:16:48 AM6/13/17
to jailho...@googlegroups.com, Jan Kiszka, Ralf Ramsauer
Linux's hyp-stub ABI changed since 4.12-rc1. This patch changes the ABI
for 4.12+, and preserves backward compatibility

Signed-off-by: Ralf Ramsauer <ralf.r...@oth-regensburg.de>
---
driver/main.c | 5 +++++
hypervisor/arch/arm/mmu_hyp.c | 19 +++++++++++++++++--
hypervisor/include/jailhouse/header.h | 10 ++++++++++
3 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/driver/main.c b/driver/main.c
index 8234b82c..732a54a0 100644
--- a/driver/main.c
+++ b/driver/main.c
@@ -445,6 +445,11 @@ static int jailhouse_cmd_enable(struct jailhouse_system __user *arg)

#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
header->arm_linux_hyp_vectors = virt_to_phys(__hyp_stub_vectors);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,12,0)
+ header->arm_linux_hyp_abi = HYP_STUB_ABI_LEGACY;
+#else
+ header->arm_linux_hyp_abi = HYP_STUB_ABI_OPCODE;
+#endif
#endif

err = jailhouse_sysfs_core_init(jailhouse_dev, header->core_size);
diff --git a/hypervisor/arch/arm/mmu_hyp.c b/hypervisor/arch/arm/mmu_hyp.c
index 5528d17b..34afcc1c 100644
--- a/hypervisor/arch/arm/mmu_hyp.c
+++ b/hypervisor/arch/arm/mmu_hyp.c
@@ -16,6 +16,10 @@
#include <asm/setup.h>
#include <asm/sysregs.h>

+/* This is only used if we use the new hyp-stub ABI that was introduced in
+ * 4.12-rc1 */
+#define LINUX_HVC_SET_VECTOR 0
+
/* functions used for translating addresses during the MMU setup process */
typedef void* (*phys2virt_t)(unsigned long);
typedef unsigned long (*virt2phys_t)(volatile const void *);
@@ -302,8 +306,19 @@ int switch_exception_level(struct per_cpu *cpu_data)
*/
arm_dcaches_clean_by_sw();

- /* replace Linux hyp-stubs by our own bootstrap vector table */
- hvc(phys_bootstrap, 0);
+ /* Replace Linux hyp-stubs by our own bootstrap vector table.
+ *
+ * Hyp-stub ABI semantic changed since 4.12-rc1 on ARM. To share the
+ * hvc routine among both versions, we simply zero r1 which is
+ * meaningless for the old ABI. The new ABI expects an opcode in r0 and
+ * an argument in r1. See Linux
+ * Documentation/virtual/kvm/arm/hyp-abi.txt .
+ */
+ if (hypervisor_header.arm_linux_hyp_abi == HYP_STUB_ABI_LEGACY)
+ hvc(phys_bootstrap, 0);
+ else
+ hvc(LINUX_HVC_SET_VECTOR, phys_bootstrap);
+
cpu_switch_el2(virt2phys);
/*
* At this point, we are at EL2, and we work with physical addresses.
diff --git a/hypervisor/include/jailhouse/header.h b/hypervisor/include/jailhouse/header.h
index 0a9045b1..45c69ea9 100644
--- a/hypervisor/include/jailhouse/header.h
+++ b/hypervisor/include/jailhouse/header.h
@@ -14,6 +14,11 @@

#define JAILHOUSE_SIGNATURE "JAILHOUS"

+#define HYP_STUB_ABI_LEGACY 0
+#define HYP_STUB_ABI_OPCODE 1
+
+#ifndef __ASSEMBLY__
+
/**
* @ingroup Setup
* @{
@@ -78,4 +83,9 @@ struct jailhouse_header {
/** Physical address of Linux's hyp-stubs.
* @note Filled by Linux loader driver before entry. */
unsigned long long arm_linux_hyp_vectors;
+ /** Denotes hyp-stub ABI for arm and arm64:
+ * @note Filled by Linux loader driver before entry. */
+ unsigned int arm_linux_hyp_abi;
};
+
+#endif
--
2.13.1

Ralf Ramsauer

unread,
Jun 13, 2017, 10:16:48 AM6/13/17
to jailho...@googlegroups.com, Jan Kiszka, Ralf Ramsauer
Same for arm64, do no longer hvc for getting Linux's hyp-stub vector
address. We now use the address in the Hypervisor header.

For reasons of simplicity, we now restore vbar_el2 in inline assembly.

Signed-off-by: Ralf Ramsauer <ralf.r...@oth-regensburg.de>
---
hypervisor/arch/arm64/asm-defines.c | 1 -
hypervisor/arch/arm64/entry.S | 26 +++++---------------------
hypervisor/arch/arm64/include/asm/percpu.h | 1 -
hypervisor/arch/arm64/setup.c | 4 ++++
4 files changed, 9 insertions(+), 23 deletions(-)

diff --git a/hypervisor/arch/arm64/asm-defines.c b/hypervisor/arch/arm64/asm-defines.c
index 5a92b00a..d850b1aa 100644
--- a/hypervisor/arch/arm64/asm-defines.c
+++ b/hypervisor/arch/arm64/asm-defines.c
@@ -32,7 +32,6 @@ void common(void)
__builtin_offsetof(struct per_cpu, stack) + \
FIELD_SIZEOF(struct per_cpu, stack));
DEFINE(PERCPU_SIZE_SHIFT_ASM, PERCPU_SIZE_SHIFT);
- OFFSET(PERCPU_SAVED_VECTORS, per_cpu, saved_vectors);
BLANK();

DEFINE(DCACHE_CLEAN_ASM, DCACHE_CLEAN);
diff --git a/hypervisor/arch/arm64/entry.S b/hypervisor/arch/arm64/entry.S
index d1377c75..8dfdb249 100644
--- a/hypervisor/arch/arm64/entry.S
+++ b/hypervisor/arch/arm64/entry.S
@@ -18,7 +18,6 @@
#include <asm/percpu.h>
#include <asm/jailhouse_hypercall.h>

-#define LINUX_HVC_GET_VECTORS 0
#define LINUX_HVC_SET_VECTORS 1

/* x11 must contain the virt-to-phys offset */
@@ -45,17 +44,11 @@ arch_entry:
* x13: virtual hypervisor address
* x14: physical UART address
* x15: virtual UART address
index 0e49bb09..82c719fa 100644
--- a/hypervisor/arch/arm64/setup.c
+++ b/hypervisor/arch/arm64/setup.c
@@ -131,6 +131,10 @@ void arch_shutdown_self(struct per_cpu *cpu_data)
arch_paging_flush_cpu_caches(cpu_data, sizeof(*cpu_data));
dsb(ish);

+ /* hand over control of EL2 back to Linux */
+ asm volatile("msr vbar_el2, %0"
+ :: "r" (hypervisor_header.arm_linux_hyp_vectors) :);
+
/* Return to EL1 */
shutdown_func((struct per_cpu *)paging_hvirt2phys(cpu_data));
}
--
2.13.1

Ralf Ramsauer

unread,
Jun 13, 2017, 10:16:48 AM6/13/17
to jailho...@googlegroups.com, Jan Kiszka, Ralf Ramsauer
This is a preparation to choose between ABIs and reimplements the hvc in
inline assembly.

Signed-off-by: Ralf Ramsauer <ralf.r...@oth-regensburg.de>
---
hypervisor/arch/arm/mmu_hyp.c | 27 ++++++++++++++++++---------
1 file changed, 18 insertions(+), 9 deletions(-)

diff --git a/hypervisor/arch/arm/mmu_hyp.c b/hypervisor/arch/arm/mmu_hyp.c
index 1fdebfc8..5528d17b 100644
--- a/hypervisor/arch/arm/mmu_hyp.c
+++ b/hypervisor/arch/arm/mmu_hyp.c
@@ -34,6 +34,20 @@ static struct {

extern unsigned long trampoline_start, trampoline_end;

+static inline unsigned int hvc(unsigned int r0, unsigned int r1)
+{
+ register unsigned int __r0 asm("r0") = r0;
+ register unsigned int __r1 asm("r1") = r1;
+
+ asm volatile(
+ "hvc #0\n\t"
+ : "=r" (__r0)
+ : "r" (__r0), "r" (__r1)
+ : );
+
+ return __r0;
+}
+
static int set_id_map(int i, unsigned long address, unsigned long size)
{
if (i >= ARRAY_SIZE(id_maps))
@@ -91,17 +105,10 @@ static void destroy_id_maps(void)
}

static void __attribute__((naked, noinline))
-cpu_switch_el2(unsigned long phys_bootstrap, virt2phys_t virt2phys)
+cpu_switch_el2(virt2phys_t virt2phys)
{
asm volatile(
/*
- * The linux hyp stub allows to install the vectors with a
- * single hvc. The vector base address is in r0
- * (phys_bootstrap).
- */
- "hvc #0\n\t"
-
- /*
* Now that the bootstrap vectors are installed, call setup_el2
* with the translated physical values of lr and sp as
* arguments.
@@ -295,7 +302,9 @@ int switch_exception_level(struct per_cpu *cpu_data)
*/
arm_dcaches_clean_by_sw();

- cpu_switch_el2(phys_bootstrap, virt2phys);
+ /* replace Linux hyp-stubs by our own bootstrap vector table */
+ hvc(phys_bootstrap, 0);
+ cpu_switch_el2(virt2phys);
/*
* At this point, we are at EL2, and we work with physical addresses.
* The MMU needs to be initialised and execution must go back to virtual
--
2.13.1

Ralf Ramsauer

unread,
Jun 13, 2017, 11:52:59 AM6/13/17
to jailho...@googlegroups.com, Jan Kiszka, Ralf Ramsauer
Hi,

Linux hyp-stub ABI changed upstream. Opcodes were switched for arm64, and arm64
and arm32 now share the same ABI. HVC_GET_VECTOR call was removed. This
series aligns Jailhouse to those changes.

We now need one more Linux Patch for Linux. Find the Linux patch below.

Ralf

Ralf Ramsauer (6):
arm, arm64: propagate __hyp_stub_vector
arm: use propagated hyp stubs
arm64: use propagated vectors
arm: reimplement hvc in inline assembly
arm: support new hyp-stub ABI
arm64: align hyp-stub opcodes

driver/main.c | 13 ++++++++
hypervisor/arch/arm/exception.S | 10 ------
hypervisor/arch/arm/include/asm/processor.h | 2 --
hypervisor/arch/arm/mmu_hyp.c | 48 ++++++++++++++++-------------
hypervisor/arch/arm64/asm-defines.c | 2 +-
hypervisor/arch/arm64/entry.S | 41 +++++++++++-------------
hypervisor/arch/arm64/include/asm/percpu.h | 1 -
hypervisor/arch/arm64/setup.c | 4 +++
hypervisor/include/jailhouse/header.h | 16 ++++++++++
9 files changed, 79 insertions(+), 58 deletions(-)

--
2.13.1


From 321d2d6d5a88d0a3bd11f113300167a85233c356 Mon Sep 17 00:00:00 2001
From: Ralf Ramsauer <ralf.r...@oth-regensburg.de>
Date: Wed, 7 Jun 2017 15:48:43 +0200
Subject: [Linux PATCH] arm, arm64: export __hyp_stub_vectors

HVC_GET_VECTORS got removed. External hypervisors, like Jailhouse, need
this address when they are deactivated, in order to restore original
state.

Signed-off-by: Ralf Ramsauer <ralf.r...@oth-regensburg.de>
---

Ralf Ramsauer

unread,
Jun 13, 2017, 11:52:59 AM6/13/17
to jailho...@googlegroups.com, Ralf Ramsauer
Signed-off-by: Ralf Ramsauer <ralf.r...@oth-regensburg.de>
---
hypervisor/arch/arm/mmu_hyp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hypervisor/arch/arm/mmu_hyp.c b/hypervisor/arch/arm/mmu_hyp.c
index 1febad54..ef2ec2ae 100644
--- a/hypervisor/arch/arm/mmu_hyp.c
+++ b/hypervisor/arch/arm/mmu_hyp.c

Ralf Ramsauer

unread,
Jun 13, 2017, 11:52:59 AM6/13/17
to jailho...@googlegroups.com, Jan Kiszka, Ralf Ramsauer
This is a preparation to choose between ABIs and reimplements the hvc in
inline assembly.

Signed-off-by: Ralf Ramsauer <ralf.r...@oth-regensburg.de>
---
hypervisor/arch/arm/mmu_hyp.c | 28 ++++++++++++++++++----------
1 file changed, 18 insertions(+), 10 deletions(-)

diff --git a/hypervisor/arch/arm/mmu_hyp.c b/hypervisor/arch/arm/mmu_hyp.c
index 62fa8ed0..eabe81c2 100644
--- a/hypervisor/arch/arm/mmu_hyp.c
+++ b/hypervisor/arch/arm/mmu_hyp.c
@@ -34,6 +34,20 @@ static struct {

extern unsigned long trampoline_start, trampoline_end;

+static inline unsigned int hvc(unsigned int r0, unsigned int r1)
+{
+ asm volatile(
+ "mov r0, %1\n\t"
+ "mov r1, %2\n\t"
+ "hvc #0\n\t"
+ "mov %0, r0\n\t"
+ : "=r" (r0)
+ : "r" (r0), "r" (r1)
+ : );
+
+ return r0;
+}
+
static int set_id_map(int i, unsigned long address, unsigned long size)
{
if (i >= ARRAY_SIZE(id_maps))
@@ -91,17 +105,10 @@ static void destroy_id_maps(void)
}

static void __attribute__((naked, noinline))
-cpu_switch_el2(unsigned long phys_bootstrap, virt2phys_t virt2phys)
+cpu_switch_el2(virt2phys_t virt2phys)
{
asm volatile(
/*
- * The linux hyp stub allows to install the vectors with a
- * single hvc. The vector base address is in r0
- * (phys_bootstrap).
- */
- "hvc #0\n\t"
-
- /*
* Now that the bootstrap vectors are installed, call setup_el2
* with the translated physical values of lr and sp as
* arguments.
@@ -122,7 +129,7 @@ cpu_switch_el2(unsigned long phys_bootstrap, virt2phys_t virt2phys)
* list ensures that the compiler uses a decent register for
* hvirt2phys.
*/
- : "cc", "memory", "r0", "r1", "r2", "r3");
+ : "cc", "memory", "r0", "r1", "r2", "r3", "lr");
}

/*
@@ -295,7 +302,8 @@ int switch_exception_level(struct per_cpu *cpu_data)
*/
arm_dcaches_clean_by_sw();

- cpu_switch_el2(phys_bootstrap, virt2phys);

Ralf Ramsauer

unread,
Jun 13, 2017, 11:52:59 AM6/13/17
to jailho...@googlegroups.com, Jan Kiszka, Ralf Ramsauer
Linux hyp-stub ABI changed in 4.12. On arm64 Opcodes changed, and arm32
ABI is now the same as for ARM64. Additionaly, the HVC_GET_VECTOR call
was removed.

We need to save those vectors before installing our hypervisor as we
needd to restore them if we disable Jailhouse.

The easiest solution is to export __hyp_stub_vector in Linux and to
propagate it to Jailhouse through the hypervisor header.

Signed-off-by: Ralf Ramsauer <ralf.r...@oth-regensburg.de>
---
driver/main.c | 8 ++++++++
hypervisor/include/jailhouse/header.h | 6 ++++++
2 files changed, 14 insertions(+)

diff --git a/driver/main.c b/driver/main.c
index 1dfe0a6d..60ea7b4a 100644
--- a/driver/main.c
+++ b/driver/main.c
@@ -75,6 +75,10 @@ MODULE_FIRMWARE(JAILHOUSE_FW_NAME);
#endif
MODULE_VERSION(JAILHOUSE_VERSION);

+#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
+extern unsigned int __hyp_stub_vectors[];
+#endif
+
struct console_state {
unsigned int head;
unsigned int last_console_id;
@@ -439,6 +443,10 @@ static int jailhouse_cmd_enable(struct jailhouse_system __user *arg)
header = (struct jailhouse_header *)hypervisor_mem;
header->max_cpus = max_cpus;

+#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
+ header->arm_hyp_info.saved_vector = virt_to_phys(__hyp_stub_vectors);
+#endif
+
err = jailhouse_sysfs_core_init(jailhouse_dev, header->core_size);
if (err)
goto error_unmap;
diff --git a/hypervisor/include/jailhouse/header.h b/hypervisor/include/jailhouse/header.h
index 738389bb..c2332de9 100644
--- a/hypervisor/include/jailhouse/header.h
+++ b/hypervisor/include/jailhouse/header.h
@@ -74,4 +74,10 @@ struct jailhouse_header {
/** Virtual address of the clock gate register (if used).
* @note Filled by Linux loader driver before entry. */
void *debug_clock_reg;
+
+ struct {
+ /** Physical address of Linux's hyp-stubs.
+ * @note Filled by Linux loader driver before entry. */
+ unsigned long long saved_vector;
+ } arm_hyp_info;
};
--
2.13.1

Jan Kiszka

unread,
Jul 3, 2017, 2:29:18 AM7/3/17
to Ralf Ramsauer, jailho...@googlegroups.com
Thanks, finally merged. I just removed empty clobber sections from
inline assembly.

Ralf Ramsauer

unread,
Jul 10, 2017, 9:51:34 AM7/10/17
to Jan Kiszka, Ralf Ramsauer, jailho...@googlegroups.com
Hi Jan,

should we leave a copy of the Linux patch that I posted in the cover
letter in the jailhouse repository? This patch is required.

Ralf
>
> Jan
>

Jan Kiszka

unread,
Jul 10, 2017, 10:09:36 AM7/10/17
to Ralf Ramsauer, jailho...@googlegroups.com
I've integrated it into my queue on git.kiszka.org, which is kind of a
reference anyway. Hope we have the link documented somewhere.

Ralf Ramsauer

unread,
Jul 10, 2017, 10:22:15 AM7/10/17
to Jan Kiszka, jailho...@googlegroups.com
Thanks. Yes, see Documentation/non-root-linux.txt

Ralf
>
> Jan
>
Reply all
Reply to author
Forward
0 new messages