From patchwork Mon Jun 3 12:54:00 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Julien Grall X-Patchwork-Id: 17454 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-yh0-f69.google.com (mail-yh0-f69.google.com [209.85.213.69]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 5EFC823916 for ; Mon, 3 Jun 2013 12:54:13 +0000 (UTC) Received: by mail-yh0-f69.google.com with SMTP id z20sf5498448yhz.8 for ; Mon, 03 Jun 2013 05:54:13 -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=VwKLohVgpW7rA7w9pArYwWLvpu3BPr2fC/8wQxvwoCo=; b=NOp8mx6zhIdAk3wgZNuwrcjzlU2cQ1Oo7GnJK9SmMOvqnwN5UtyxBzicYPbgsklVyp 0ZY9udsxFcdImLooAJeg8Kr/AHr3MPNQK3FfsQ0oNzgr4yzBo4pQHT0NALk8vL94Hnjj b7YVOl7DQnD32mrC36+8UPKyAW8tsCcPvCqOidwUtUYnX6SHqu49q/9BFvSyinCzRCzl C4NiMv+5VeO2x3kS1kzVL7FZevon/oR6Lae3iT6cIvQGaEpW536RI7AK3/XcCGY8wf9j vr1L6CcGVfHBN3HH3ln3bNdB1CGtrugM8YoRjBdOgmUlzU7j1+KHS1PgZqYHWQADNvRZ IsuA== X-Received: by 10.224.3.131 with SMTP id 3mr13949167qan.5.1370264052863; Mon, 03 Jun 2013 05:54:12 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.122.5 with SMTP id lo5ls513778qeb.27.gmail; Mon, 03 Jun 2013 05:54:12 -0700 (PDT) X-Received: by 10.52.159.72 with SMTP id xa8mr14256562vdb.48.1370264052708; Mon, 03 Jun 2013 05:54:12 -0700 (PDT) Received: from mail-vc0-f180.google.com (mail-vc0-f180.google.com [209.85.220.180]) by mx.google.com with ESMTPS id ia10si720457vdb.90.2013.06.03.05.54.12 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 03 Jun 2013 05:54:12 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.220.180 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.220.180; Received: by mail-vc0-f180.google.com with SMTP id gd11so2606854vcb.11 for ; Mon, 03 Jun 2013 05:54:12 -0700 (PDT) X-Received: by 10.220.246.8 with SMTP id lw8mr16602384vcb.8.1370264052541; Mon, 03 Jun 2013 05:54:12 -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.221.10.206 with SMTP id pb14csp77462vcb; Mon, 3 Jun 2013 05:54:11 -0700 (PDT) X-Received: by 10.194.134.73 with SMTP id pi9mr18950772wjb.38.1370264051211; Mon, 03 Jun 2013 05:54:11 -0700 (PDT) Received: from mail-wg0-x22b.google.com (mail-wg0-x22b.google.com [2a00:1450:400c:c00::22b]) by mx.google.com with ESMTPS id o10si9422795wij.81.2013.06.03.05.54.10 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 03 Jun 2013 05:54:11 -0700 (PDT) Received-SPF: neutral (google.com: 2a00:1450:400c:c00::22b is neither permitted nor denied by best guess record for domain of julien.grall@linaro.org) client-ip=2a00:1450:400c:c00::22b; Received: by mail-wg0-f43.google.com with SMTP id x12so3111490wgg.34 for ; Mon, 03 Jun 2013 05:54:10 -0700 (PDT) X-Received: by 10.180.86.38 with SMTP id m6mr12841036wiz.25.1370264050681; Mon, 03 Jun 2013 05:54:10 -0700 (PDT) Received: from belegaer.uk.xensource.com. (firewall.ctxuk.citrix.com. [46.33.159.2]) by mx.google.com with ESMTPSA id fp16sm23274253wic.6.2013.06.03.05.54.08 for (version=TLSv1.2 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 03 Jun 2013 05:54:09 -0700 (PDT) From: Julien Grall To: xen-devel@lists.xen.org Cc: patches@linaro.org, Stefano.Stabellini@eu.citrix.com, ian.campbell@citrix.com, Julien Grall Subject: [PATCH v3] xen/arm: Rework the way to compute dom0 DTB base address Date: Mon, 3 Jun 2013 13:54:00 +0100 Message-Id: <1370264040-22138-1-git-send-email-julien.grall@linaro.org> X-Mailer: git-send-email 1.7.10.4 X-Gm-Message-State: ALoCoQmBuTpT1VT4xYSAJh2OYNAD/wKKCpUPvVyS5YavokFn2JFXONcPSOhEwHO15BriT0qR0zzk X-Original-Sender: julien.grall@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.220.180 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 the 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 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 | 49 +++++++++++++++++++++++++++++++++++++------ xen/arch/arm/kernel.c | 2 ++ xen/arch/arm/kernel.h | 7 +++++++ 3 files changed, 52 insertions(+), 6 deletions(-) diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c index b92c64b..377062c 100644 --- a/xen/arch/arm/domain_build.c +++ b/xen/arch/arm/domain_build.c @@ -477,6 +477,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; @@ -502,17 +503,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 to linux (Linux use + * the space after it to decompress) + * Load the DTB at the end of the first bank, while ensure 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); + /* Aligned the address to 2Mb. Linux only requires to be aligned to 4 bytes */ + 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: @@ -521,10 +531,36 @@ static int prepare_dtb(struct domain *d, struct kernel_info *kinfo) return -EINVAL; } +static void dtb_check_overlap(struct kernel_info *kinfo) +{ + paddr_t zimage_start = kinfo->zimage.load_addr; + paddr_t zimage_end = kinfo->zimage.load_addr + kinfo->zimage.len; + paddr_t dtb_start = kinfo->dtb_paddr; + paddr_t dtb_end = kinfo->dtb_paddr + fdt_totalsize(kinfo->fdt); + + /* + * Check the kernel won't overlap the kernel + * Only when it's a ZIMAGE + */ + if ( kinfo->type != KERNEL_ZIMAGE ) + return; + + 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 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); } @@ -559,10 +595,11 @@ int construct_dom0(struct domain *d) if ( rc < 0 ) return rc; + dtb_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 8f4a60d..f8c8850 100644 --- a/xen/arch/arm/kernel.c +++ b/xen/arch/arm/kernel.c @@ -152,6 +152,7 @@ static int kernel_try_zimage_prepare(struct kernel_info *info, info->entry = info->zimage.load_addr; info->load = kernel_zimage_load; + info->type = KERNEL_ZIMAGE; return 0; } @@ -193,6 +194,7 @@ static int kernel_try_elf_prepare(struct kernel_info *info, */ info->entry = info->elf.parms.virt_entry; info->load = kernel_elf_load; + info->type = KERNEL_ELF; return 0; err: diff --git a/xen/arch/arm/kernel.h b/xen/arch/arm/kernel.h index 1776a4d..b4ecd30 100644 --- a/xen/arch/arm/kernel.h +++ b/xen/arch/arm/kernel.h @@ -9,6 +9,12 @@ #include #include +enum kernel_type +{ + KERNEL_ELF, + KERNEL_ZIMAGE, +}; + struct kernel_info { #ifdef CONFIG_ARM_64 enum domain_type type; @@ -23,6 +29,7 @@ struct kernel_info { void *kernel_img; unsigned kernel_order; + enum kernel_type type; union { struct {