From patchwork Thu Jun 27 17:13:30 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Julien Grall X-Patchwork-Id: 18169 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-vb0-f72.google.com (mail-vb0-f72.google.com [209.85.212.72]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id D003823910 for ; Thu, 27 Jun 2013 17:13:38 +0000 (UTC) Received: by mail-vb0-f72.google.com with SMTP id p12sf1419881vbe.11 for ; Thu, 27 Jun 2013 10:13:38 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=mime-version:x-beenthere:x-forwarded-to:x-forwarded-for :delivered-to:from:to:cc:subject:date:message-id:x-mailer :x-gm-message-state:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :x-google-group-id:list-post:list-help:list-archive:list-unsubscribe; bh=U7jBdjr+tH/YLkz9vkOzjBuotopI0qx/4pa/rCarynA=; b=JcDTt0X9CV27VaX6uY5ORBlC4Obcr6zduFntUDUFDQ68WieT33BT4jyFswZ4a/O/md MpXIplX2iWAlCNj0M7Vi3C0rZafpDV+cyYFXaAX3NzP8id3Um1s1HCjKII3OxwhdaJwM /TCdpNM8Gs2raG+x114YeGl7ErsCDU1dWVxhsK3j/TIzM4JSufBvvnH9e0XShaRi/pZz mB8otL71RB6meKEA03YJg+I/6SbFQ036+jLUNwI8TZXoxeTlJVFdSE9duhQuTc2lk1da 2sYRivmP/czZVFmm2fJowYirku6HwIaDSXxFqdMGXaKtx2CiV3j3d+zcbYj7STjhk+HO FI6Q== X-Received: by 10.224.29.76 with SMTP id p12mr8763853qac.5.1372353218075; Thu, 27 Jun 2013 10:13:38 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.37.229 with SMTP id b5ls966046qek.18.gmail; Thu, 27 Jun 2013 10:13:37 -0700 (PDT) X-Received: by 10.220.167.2 with SMTP id o2mr1387456vcy.61.1372353217926; Thu, 27 Jun 2013 10:13:37 -0700 (PDT) Received: from mail-vb0-f41.google.com (mail-vb0-f41.google.com [209.85.212.41]) by mx.google.com with ESMTPS id ur15si1001205veb.146.2013.06.27.10.13.37 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 27 Jun 2013 10:13:37 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.212.41 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.212.41; Received: by mail-vb0-f41.google.com with SMTP id p13so884519vbe.14 for ; Thu, 27 Jun 2013 10:13:37 -0700 (PDT) X-Received: by 10.58.119.233 with SMTP id kx9mr3986387veb.3.1372353217796; Thu, 27 Jun 2013 10:13:37 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.58.165.8 with SMTP id yu8csp156939veb; Thu, 27 Jun 2013 10:13:36 -0700 (PDT) X-Received: by 10.180.98.231 with SMTP id el7mr12661640wib.33.1372353216219; Thu, 27 Jun 2013 10:13:36 -0700 (PDT) Received: from mail-we0-f180.google.com (mail-we0-f180.google.com [74.125.82.180]) by mx.google.com with ESMTPS id pg8si1366421wjb.133.2013.06.27.10.13.35 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 27 Jun 2013 10:13:36 -0700 (PDT) Received-SPF: neutral (google.com: 74.125.82.180 is neither permitted nor denied by best guess record for domain of julien.grall@linaro.org) client-ip=74.125.82.180; Received: by mail-we0-f180.google.com with SMTP id w56so782966wes.39 for ; Thu, 27 Jun 2013 10:13:35 -0700 (PDT) X-Received: by 10.194.1.226 with SMTP id 2mr7009874wjp.91.1372353215280; Thu, 27 Jun 2013 10:13:35 -0700 (PDT) Received: from belegaer.uk.xensource.com. (firewall.ctxuk.citrix.com. [46.33.159.2]) by mx.google.com with ESMTPSA id cw8sm18647580wib.7.2013.06.27.10.13.33 for (version=TLSv1.2 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 27 Jun 2013 10:13:34 -0700 (PDT) From: Julien Grall To: xen-devel@lists.xen.org Cc: ian.campbell@citrix.com, Stefano.Stabellini@eu.citrix.com, patches@linaro.org, Julien Grall Subject: [PATCH v5] xen/arm: Rework the way to compute dom0 DTB base address Date: Thu, 27 Jun 2013 18:13:30 +0100 Message-Id: <1372353210-12580-1-git-send-email-julien.grall@linaro.org> X-Mailer: git-send-email 1.7.10.4 X-Gm-Message-State: ALoCoQkfZSNrEQyyAbWkf6FBW41WKEYMWMHn10MCsWP8oyPIAZH3SiBHuRtZt+K9S9Jtu8a826fm X-Original-Sender: julien.grall@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.212.41 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , If the DTB is loading right after the kernel, on some setup, Linux will overwrite the DTB during the decompression step. To be sure the DTB won't be overwritten by the decompression stage, load the DTB near the end of the first memory bank and below 4Gib (if memory range is greater). Signed-off-by: Julien Grall --- Changes in v5: - Typoes - Introduce check_overlap callback and implement it when we load a zImage Changes in v4: - Rename type to ktype to avoid clash name on arm64 Changes in v3: - Rework comments - Missing blank line - Transform dtb_check_overlap to a void function - Directly panic in dtb_check_overlap - Use the right formula to check the overlap Changes in v2: - Align the DTB base address to 2Mib - Add dtb_check_overlap to check if the kernel will overlap the DTB - Fix typo --- xen/arch/arm/domain_build.c | 27 +++++++++++++++++++++------ xen/arch/arm/kernel.c | 18 ++++++++++++++++++ xen/arch/arm/kernel.h | 2 ++ 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c index 5809489..192241a 100644 --- a/xen/arch/arm/domain_build.c +++ b/xen/arch/arm/domain_build.c @@ -484,6 +484,7 @@ static int prepare_dtb(struct domain *d, struct kernel_info *kinfo) void *fdt; int new_size; int ret; + paddr_t end; kinfo->unassigned_mem = dom0_mem; @@ -509,17 +510,26 @@ static int prepare_dtb(struct domain *d, struct kernel_info *kinfo) goto err; /* - * Put the device tree at the beginning of the first bank. It - * must be below 4 GiB. + * DTB must be load below 4GiB and far enough from linux (Linux uses + * the space after it to decompress) + * Load the DTB at the end of the first bank, while ensuring it is + * also below 4G */ - kinfo->dtb_paddr = kinfo->mem.bank[0].start + 0x100; - if ( kinfo->dtb_paddr + fdt_totalsize(kinfo->fdt) > (1ull << 32) ) + end = kinfo->mem.bank[0].start + kinfo->mem.bank[0].size; + end = MIN(1ull << 32, end); + kinfo->dtb_paddr = end - fdt_totalsize(kinfo->fdt); + /* Align the address to 2Mb. Linux only requires 4 byte alignment */ + kinfo->dtb_paddr &= ~((2 << 20) - 1); + + if ( fdt_totalsize(kinfo->fdt) > end ) { - printk("Not enough memory below 4 GiB for the device tree."); + printk(XENLOG_ERR "Not enough memory in the first bank for " + "the device tree."); ret = -FDT_ERR_XEN(EINVAL); goto err; } + return 0; err: @@ -532,6 +542,9 @@ static void dtb_load(struct kernel_info *kinfo) { void * __user dtb_virt = (void * __user)(register_t)kinfo->dtb_paddr; + printk("Loading dom0 DTB to 0x%"PRIpaddr"-0x%"PRIpaddr"\n", + kinfo->dtb_paddr, kinfo->dtb_paddr + fdt_totalsize(kinfo->fdt)); + raw_copy_to_guest(dtb_virt, kinfo->fdt, fdt_totalsize(kinfo->fdt)); xfree(kinfo->fdt); } @@ -566,10 +579,12 @@ int construct_dom0(struct domain *d) if ( rc < 0 ) return rc; + if ( kinfo.check_overlap ) + kinfo.check_overlap(&kinfo); + /* The following loads use the domain's p2m */ p2m_load_VTTBR(d); - kinfo.dtb_paddr = kinfo.zimage.load_addr + kinfo.zimage.len; kernel_load(&kinfo); dtb_load(&kinfo); diff --git a/xen/arch/arm/kernel.c b/xen/arch/arm/kernel.c index aba5441..3953f0f 100644 --- a/xen/arch/arm/kernel.c +++ b/xen/arch/arm/kernel.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "kernel.h" @@ -64,6 +65,21 @@ void copy_from_paddr(void *dst, paddr_t paddr, unsigned long len, int attrindx) clear_fixmap(FIXMAP_MISC); } +static void kernel_zimage_check_overlap(struct kernel_info *info) +{ + paddr_t zimage_start = info->zimage.load_addr; + paddr_t zimage_end = info->zimage.load_addr + info->zimage.len; + paddr_t dtb_start = info->dtb_paddr; + paddr_t dtb_end = info->dtb_paddr + fdt_totalsize(info->fdt); + + if ( (dtb_start > zimage_end) || (dtb_end < zimage_start) ) + return; + + panic(XENLOG_ERR "The kernel(0x%"PRIpaddr"-0x%"PRIpaddr + ") is overlapping the DTB(0x%"PRIpaddr"-0x%"PRIpaddr")\n", + zimage_start, zimage_end, dtb_start, dtb_end); +} + static void kernel_zimage_load(struct kernel_info *info) { paddr_t load_addr = info->zimage.load_addr; @@ -152,6 +168,7 @@ static int kernel_try_zimage_prepare(struct kernel_info *info, info->entry = info->zimage.load_addr; info->load = kernel_zimage_load; + info->check_overlap = kernel_zimage_check_overlap; return 0; } @@ -197,6 +214,7 @@ static int kernel_try_elf_prepare(struct kernel_info *info, */ info->entry = info->elf.parms.virt_entry; info->load = kernel_elf_load; + info->check_overlap = NULL; if ( elf_check_broken(&info->elf.elf) ) printk("Xen: warning: ELF kernel broken: %s\n", diff --git a/xen/arch/arm/kernel.h b/xen/arch/arm/kernel.h index 1776a4d..c900e74 100644 --- a/xen/arch/arm/kernel.h +++ b/xen/arch/arm/kernel.h @@ -38,6 +38,8 @@ struct kernel_info { }; void (*load)(struct kernel_info *info); + /* Callback to check overlap between the kernel and the device tree */ + void (*check_overlap)(struct kernel_info *kinfo); int load_attr; };