Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Starting Xen hypervisor in EL2 coming from EL1? #353

Closed
dirkbehme opened this issue Jan 29, 2016 · 7 comments
Closed

Starting Xen hypervisor in EL2 coming from EL1? #353

dirkbehme opened this issue Jan 29, 2016 · 7 comments
Labels

Comments

@dirkbehme
Copy link

My ARMv8 aarch64 system uses trusted firmware (BL2, BL31 available, too) to start U-Boot. U-Boot is running at EL1, then. Short boot log:

...
NOTICE: BL2: Normal boot

U-Boot 2015.04 (Nov 02 2015 - 10:04:48)
...

With this I'd like to start / run the hypervisor Xen. This has to run at EL2.

If I understood correctly, I load Xen via U-Boot to RAM, e.g. via tftp. Then, in U-Boot at EL1 I have to do a secure monitor call (using e.g. [1]) to enter the trusted firmware at EL3. This has to "call" the Xen hypervisor at EL2, then.

Is this understanding correct? Does the trusted firmware supports this?

If this is supported, how does the smc have to look, then (giving the start address of the Xen image)? Any pointers to code / examples?

Best regards

Dirk

[1] http://git.denx.de/?p=u-boot.git;a=commitdiff;h=a5b9fa30cebd91082f9fea93d7ef33812910da6a

@sandrine-bailleux-arm
Copy link

Hello,

The patch that you've linked [1] adds support for both SMC and HVC calls in U-Boot.
Therefore, I think you should be able to go straight from U-Boot to Xen using a
Hypervisor call, instead of going through the Trusted Firmware first (using an SMC)
then handing over to Xen.

Have you tried that?

Regards,
Sandrine

[1] http://git.denx.de/?p=u-boot.git;a=commitdiff;h=a5b9fa30cebd91082f9fea93d7ef33812910da6a

@danh-arm
Copy link
Contributor

danh-arm commented Feb 2, 2016

This flow Sandrine suggests relies on your Trusted Firmware platform port (in BL2) starting U-Boot at EL2 (to install the HVC functionality), even if U-Boot subsequently drops down to EL1 to load Xen.
Architecturally it would be cleaner if U-Boot remained in EL2 and just handed over control to Xen after loading it. But I don't know enough about U-Boot to say if that's possible.

@dirkbehme
Copy link
Author

Assuming that U-Boot remains in EL1, does the Trusted Firmware supports (a smc call?) to start anything at EL2? I'm thinking on a smc call passing a pointer to an entry address and a target ELx.

@danh-arm
Copy link
Contributor

danh-arm commented Feb 3, 2016

In short, no. Any such SMC would be platform-specific and not supported by the upstream Trusted Firmware. In particular, unless the caller of the SMC were authenticated in some way, this would be a privilege escalation back door.

@athoelke
Copy link

athoelke commented Feb 3, 2016

BL3-1 is currently written so that if the initial non-secure payload requests to start at EL1, then the hypervisor layer is disabled (SCR_EL3.HCE=0) and bypassed. Subsequently starting other CPUs will cause them to do the same - as required by the PSCI specification. Provision of an SMC to support elevation from EL1 execution to EL2 is a security vulnerability as Dan explains, provision of a generic implementation of this would be inadvisable.

The recommended approach is that in this situation the non-secure boot payload runs initially at EL2 (so BL3-1 activates the hypervisor layer), which sets up a simple EL2 exception vector and minimally configures EL2 before continuing U-Boot at EL1. That exception vector supports a single HVC call to return to EL2 to execute the Xen hypervisor (or other loaded image designed to execute at EL2 such as Linux).

@dirkbehme
Copy link
Author

The recommended approach is ...

Many thanks! I'll look into that, we can close this question.

Thanks again!

@dirkbehme
Copy link
Author

Just for the logs as I understood that this isn't allowed to be done (see above: "In particular, unless the caller of the SMC were authenticated in some way, this would be a privilege escalation back door."):

Using a U-Boot patch like

http://lists.denx.de/pipermail/u-boot/2016-June/259177.html

to issue a smc call to get back from U-Boot running at EL1 to EL3 and then a arm trusted firmware hack (hack!) like below [1] would allow to start a hypervisor loaded by U-Boot in the memory.

Dirk

[1]

From a605d32223188a0665783d57b1c17eaf42c27603 Mon Sep 17 00:00:00 2001
From: Dirk Behme <dirk.behme@de.bosch.com>
Date: Tue, 28 Jun 2016 09:34:54 +0200
Subject: [PATCH] Add SMC call to start hypervisor

Add a SMC call to start a hypervisor at EL2 already loaded to
memory before this call.

Signed-off-by: Dirk Behme <dirk.behme@de.bosch.com>
---
 include/bl31/services/std_svc.h  |    1 +
 services/std_svc/std_svc_setup.c |   23 +++++++++++++++++++++++
 2 files changed, 24 insertions(+), 0 deletions(-)

diff --git a/include/bl31/services/std_svc.h b/include/bl31/services/std_svc.h
index cbd5b62..41fe19b 100644
--- a/include/bl31/services/std_svc.h
+++ b/include/bl31/services/std_svc.h
@@ -37,6 +37,7 @@
 #define ARM_STD_SVC_UID            0x8400ff01
 /*                 0x8400ff02 is reserved */
 #define ARM_STD_SVC_VERSION        0x8400ff03
+#define ARM_STD_SVC_CALL_HYPERVISOR    0x8400ff04

 /* ARM Standard Service Calls version numbers */
 #define STD_SVC_VERSION_MAJOR      0x0
diff --git a/services/std_svc/std_svc_setup.c b/services/std_svc/std_svc_setup.c
index 6cb0319..c8b77f0 100644
--- a/services/std_svc/std_svc_setup.c
+++ b/services/std_svc/std_svc_setup.c
@@ -30,6 +30,10 @@

 #include <debug.h>
 #include <psci.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <context_mgmt.h>
+#include <platform.h>
 #include <runtime_svc.h>
 #include <std_svc.h>
 #include <stdint.h>
@@ -63,6 +67,8 @@ uint64_t std_svc_smc_handler(uint32_t smc_fid,
                 void *handle,
                 uint64_t flags)
 {
+   entry_point_info_t *next_image_info;
+
    /*
     * Dispatch PSCI calls to PSCI SMC handler and return its return
     * value
@@ -88,6 +94,23 @@ uint64_t std_svc_smc_handler(uint32_t smc_fid,
        /* Return the version of current implementation */
        SMC_RET2(handle, STD_SVC_VERSION_MAJOR, STD_SVC_VERSION_MINOR);

+   case ARM_STD_SVC_CALL_HYPERVISOR:
+       /*
+        * Call a hypervisor at EL2 already present in memory
+        * Parameters passed to us:
+        * x1: Entry address of the hypervisor (jump target)
+        * x2: argument 0 for the hypervisor, e.g. the device tree address
+        * x3: argument 2 for the hypervisor, e.g. the Linux kernel Image address
+        */
+
+       next_image_info = bl31_plat_get_next_image_ep_info(NON_SECURE);
+       next_image_info->spsr = 0x3C9; /* EL2 */
+       next_image_info->pc = x1;
+       next_image_info->args.arg0 = x2;
+       next_image_info->args.arg2 = x3;
+       cm_init_my_context(next_image_info);
+       SMC_RET0(handle);
+
    default:
        WARN("Unimplemented Standard Service Call: 0x%x \n", smc_fid);
        SMC_RET1(handle, SMC_UNK);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants