From patchwork Tue Nov 27 12:25:26 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Molton X-Patchwork-Id: 202202 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 97F622C0087 for ; Tue, 27 Nov 2012 23:35:30 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id E17494A03F; Tue, 27 Nov 2012 13:35:26 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id YaGzlN0rs4ns; Tue, 27 Nov 2012 13:35:25 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 9705D4A039; Tue, 27 Nov 2012 13:35:25 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 450124A039 for ; Tue, 27 Nov 2012 13:31:33 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id bMNT9GcAH0qY for ; Tue, 27 Nov 2012 13:31:31 +0100 (CET) X-Greylist: delayed 355 seconds by postgrey-1.27 at theia; Tue, 27 Nov 2012 13:31:29 CET X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from ducie-dc1.codethink.co.uk (ducie-dc1.codethink.co.uk [37.128.190.40]) by theia.denx.de (Postfix) with ESMTPS id 0A9D04A02F for ; Tue, 27 Nov 2012 13:31:29 +0100 (CET) Received: from [192.168.24.102] (snark.dyn.ducie.codethink.co.uk [192.168.24.102]) by ducie-dc1.codethink.co.uk (Postfix) with ESMTPSA id 87B8846277D; Tue, 27 Nov 2012 12:25:28 +0000 (GMT) Message-ID: <50B4B136.1020402@codethink.co.uk> Date: Tue, 27 Nov 2012 12:25:26 +0000 From: Ian Molton User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:16.0) Gecko/20121028 Thunderbird/16.0.2 MIME-Version: 1.0 To: u-boot@lists.denx.de X-Mailman-Approved-At: Tue, 27 Nov 2012 13:35:24 +0100 Cc: Marc Zyngier , Christoffer Dall , "Wietzke, Joachim, Prof. Dr." , "Fischer, Clemens" Subject: [U-Boot] RFD: ARM: enable HYP mode on OMAP5 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de Hi folks, My colleague Clemens Fischer, and I were able to bring up the OMAP5 CPU in HYP mode with the following patch to u-boot. Obviously the patch is not production grade yet, but we feel that it would be of use to discuss how best to integrate the code into u-boot. The code wakes up CPU1 before putting CPU0 into HYP mode, and CPU1 goes back to sleep once it has entered HYP mode itself. With this patch, a near-unmodified mainline linux kernel (patched for ARM KVM only) will boot up with HYP mode enabled. Many thanks to Marc and Christoffer for their help getting KVM up and running! Comments are welcome. -Ian From 089b4bfb2965b3146a20aab0abd9337ecce482e7 Mon Sep 17 00:00:00 2001 From: Ian Molton Date: Thu, 1 Nov 2012 16:23:03 +0000 Subject: [PATCH 1/3] Put both OMAP5 cores into HYP mode --- arch/arm/lib/bootm.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index 802e833..bddbff3 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -4,6 +4,8 @@ * Marius Groeger * * Copyright (C) 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) + * HYP entry (c) 2012 Ian Molton + * and Clemens Fischer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,6 +32,36 @@ #include #include +/* A small stack to allow us to safely call the OMAP5 monitor API, in order to + * enable HYP mode. This must be accessible in HYP mode. + */ +unsigned int hyp_primary_stack[11]; + +/* + * function called by cpu 1 after wakeup + */ +extern void __hyp_init_sec(void); + +asm ( + ".pushsection .text\n" + ".global __hyp_init_sec\n" + "__hyp_init_sec:\n" + "ldr r12, =0x102\n" + "mov r0, pc\n" + "smc 0x1\n" + "ldr r1, =0x48281804\n" // AUX_CORE_BOOT_1 + "mov r2, #0\n" + "str r2, [r1]\n" + "isb\n" + "dsb\n" + "1: wfe\n" + "ldr r2, [r1]\n" + "cmp r2, #0\n" + "movne pc, r2\n" + "b 1b\n" + ".popsection\n" +); + DECLARE_GLOBAL_DATA_PTR; #if defined (CONFIG_SETUP_MEMORY_TAGS) || \ @@ -93,6 +125,45 @@ static void announce_and_cleanup(void) cleanup_before_linux(); } +/* + * Enable HYP mode on the OMAP5 CPU + * + * FIXME: this needs to test to make sure its running on an OMAP5 + * + * We wake up CPU1 at __hyp_init_sec which allows us to put it into HYP + * mode. + * + * CPU1 then clears AUX_CORE_BOOT_0 and enters WFE, until the kernel wakes it. + * + * In order to avoid CPU1 continuing execution on just about any event, we + * wait for AUX_CORE_BOOT_0 to contain a non-zero address, at which point + * we continue execution at that address. + * + */ + +void hyp_enable(void) { + /*Wake up CPU1 and enable HYP on CPU0. */ + asm( + "ldr r1, =0x48281800\n" // AUX_CORE_BOOT_1 + "ldr r2, =__hyp_init_sec\n" + "str r2, [r1, #4]\n" + "mov r2, #0x200\n" + "str r2, [r1]\n" // AUX_CORE_BOOT_0 + "isb\n" + "dmb\n" + "dsb\n" + "sev\n" // Wake CPU1 + "ldr r1,=hyp_primary_stack\n" + "ldr r12, =0x102\n" + "mov r0, pc\n" + "stm r1, {r4-r14}\n" + "smc 0x1\n" // CPU0 -> HYP mode + "ldr r1,=hyp_primary_stack\n" + "ldm r1, {r4-r14}\n" + :::"r0", "r1", "r2", "r3", "cc", "memory" + ); +}; + int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) { bd_t *bd = gd->bd; @@ -152,6 +223,8 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) announce_and_cleanup(); + hyp_enable(); + kernel_entry(0, machid, bd->bi_boot_params); /* does not return */ @@ -210,6 +283,8 @@ static int bootm_linux_fdt(int machid, bootm_headers_t *images) announce_and_cleanup(); + hyp_enable(); + kernel_entry(0, machid, *of_flat_tree); /* does not return */ -- 1.7.10.4