From patchwork Thu Nov 22 19:45:33 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vojtech Bocek X-Patchwork-Id: 201549 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from chlorine.canonical.com (chlorine.canonical.com [91.189.94.204]) by ozlabs.org (Postfix) with ESMTP id B210F2C0092 for ; Mon, 26 Nov 2012 02:26:43 +1100 (EST) Received: from localhost ([127.0.0.1] helo=chlorine.canonical.com) by chlorine.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1Tce6J-0001PW-2J; Sun, 25 Nov 2012 15:26:31 +0000 Received: from mail-ea0-f177.google.com ([209.85.215.177]) by chlorine.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1Tbcig-0003PO-CX for kernel-team@lists.ubuntu.com; Thu, 22 Nov 2012 19:45:54 +0000 Received: by mail-ea0-f177.google.com with SMTP id c10so1830475eaa.8 for ; Thu, 22 Nov 2012 11:45:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; bh=A99j0jq+quwVxvxL8O4z1PIATm2fHkaKpyTtTDu70OA=; b=fBAuTL5IPVNR5VajgruH4BecD2eY4QxFGdZpOkeTLIGpiJcfo8Iji+KVqXodzD6XBz nzwxfnaGN/bCJVrM4XiLC7F9lngEqGcgNiCzO81iYJBj8kREx8ff8L808hHQrqO4FthJ 37Ul00Dh0hVHKeqdfED3eX0OGSQiU8LCSXjtyqfbXDzpRheRQQr01D/rav+VP3uyjRD9 +NWd2VohVoxVOR0PKxTfYQ1NwKExymmPXH7Xv3ul2zHOi/DtZp30VkihHnjx14OBxHcW sHbk7uVU65/JZuv2AHPQ6CAYpo+iLyVMzMbtSHGQbXkX0CXHB+wsa6QOvcPgZe9cscOp /y0Q== Received: by 10.14.213.134 with SMTP id a6mr4453436eep.45.1353613554155; Thu, 22 Nov 2012 11:45:54 -0800 (PST) Received: from nymeria.cust.nbox.cz (ip4-83-240-110-90.cust.nbox.cz. [83.240.110.90]) by mx.google.com with ESMTPS id o49sm8870267eep.5.2012.11.22.11.45.52 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 22 Nov 2012 11:45:53 -0800 (PST) From: Vojtech Bocek To: kernel-team@lists.ubuntu.com Subject: [PATCH 2/2] UBUNTU: Support copying of atags in the decompressor. Date: Thu, 22 Nov 2012 20:45:33 +0100 Message-Id: <1353613533-15835-3-git-send-email-vbocek@gmail.com> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1353613533-15835-1-git-send-email-vbocek@gmail.com> References: <1353613533-15835-1-git-send-email-vbocek@gmail.com> X-Mailman-Approved-At: Sun, 25 Nov 2012 15:26:29 +0000 Cc: Vojtech Bocek X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.13 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: kernel-team-bounces@lists.ubuntu.com Errors-To: kernel-team-bounces@lists.ubuntu.com OriginalAuthor: Mike Kasick This is needed if this kernel is booted using kexec-hardboot, because atags need to be in direct-mapped region, usually the first 16kB of RAM. Signed-off-by: Vojtech Bocek --- arch/arm/boot/compressed/Makefile | 3 +++ arch/arm/boot/compressed/head.S | 44 ++++++++++++++++++++++++++++++++++++- arch/arm/boot/compressed/misc.c | 22 +++++++++++++++++++ 3 files changed, 68 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index 0c74a6f..7643b37 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -111,6 +111,9 @@ endif ifeq ($(CONFIG_CPU_ENDIAN_BE8),y) LDFLAGS_vmlinux += --be8 endif +ifneq ($(PARAMS_PHYS),) +LDFLAGS_vmlinux += --defsym params_phys=$(PARAMS_PHYS) +endif # ? LDFLAGS_vmlinux += -p # Report unresolved symbol references diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index 401efb4..99fa555 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -134,7 +134,9 @@ start: .word _edata @ zImage end address THUMB( .thumb ) 1: mov r7, r1 @ save architecture ID - mov r8, r2 @ save atags pointer + teq r0, #0 @ Check for kexec_boot_atags. + movne r8, r0 @ Save kexec_boot_tags. + moveq r8, r2 @ save atags pointer #ifndef __ARM_ARCH_2__ /* @@ -349,6 +351,44 @@ not_relocated: mov r0, #0 add r2, sp, #0x10000 @ 64k max mov r3, r7 bl decompress_kernel + +/* Copy the kernel tagged list (atags): + * + * The kernel requires atags to be located in a direct-mapped region, + * usually below the kernel in the first 16 kB of RAM. If they're above + * (the start of) the kernel, they need to be copied to a suitable + * location, e.g., the machine-defined params_phys. + * + * The assumption is that the tags will only be "out of place" if the + * decompressor code is also, so copying is implemented only in the "won't + * overwrite" case (which should be fixed). Still need to make sure that + * the copied tags don't overwrite either the kernel or decompressor code + * (or rather, the remainder of it since everything up to here has already + * been executed). + * + * r4: zreladdr (kernel start) + * r8: atags */ + + /* No need to copy atags if they're already below kernel */ + cmp r8, r4 + blo call_kernel + + /* r1: min(zreladdr, pc) */ + mov r1, pc + cmp r4, r1 + movlo r1, r4 + + /* Compute max space for atags, if max <= 0 don't copy. */ + ldr r0, =params_phys @ dest + subs r2, r1, r0 @ max = min(zreladdr, pc) - dest + bls call_kernel + + /* Copy atags to params_phys. */ + mov r1, r8 @ src + bl copy_atags + mov r8, r0 + +call_kernel: bl cache_clean_flush bl cache_off mov r0, #0 @ must be zero @@ -357,6 +397,8 @@ not_relocated: mov r0, #0 ARM( mov pc, r4 ) @ call kernel THUMB( bx r4 ) @ entry point is always ARM + .ltorg + .align 2 .type LC0, #object LC0: .word LC0 @ r1 diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c index 832d372..c082769 100644 --- a/arch/arm/boot/compressed/misc.c +++ b/arch/arm/boot/compressed/misc.c @@ -25,6 +25,7 @@ unsigned int __machine_arch_type; #include /* for NULL */ #include #include +#include static void putstr(const char *ptr); @@ -192,3 +193,24 @@ decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p, else putstr(" done, booting the kernel.\n"); } + +const struct tag *copy_atags(struct tag *dest, const struct tag *src, size_t max) +{ + struct tag *tag; + size_t size; + + /* Find the last tag (ATAG_NONE). */ + for_each_tag(tag, (struct tag *)src) + continue; + + /* Include the last tag in copy. */ + size = (char *)tag - (char *)src + sizeof(struct tag_header); + + /* If there's not enough room, just use original and hope it works. */ + if (size > max) + return src; + + memcpy(dest, src, size); + + return dest; +}