From patchwork Fri Apr 4 13:28:45 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Campbell X-Patchwork-Id: 27817 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-ig0-f197.google.com (mail-ig0-f197.google.com [209.85.213.197]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 1DF4A20369 for ; Fri, 4 Apr 2014 13:42:31 +0000 (UTC) Received: by mail-ig0-f197.google.com with SMTP id hn18sf2006806igb.4 for ; Fri, 04 Apr 2014 06:42:31 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:date:message-id :mime-version:cc:subject:precedence:list-id:list-unsubscribe :list-post:list-help:list-subscribe:sender:errors-to :x-original-sender:x-original-authentication-results:mailing-list :list-archive:content-type:content-transfer-encoding; bh=Mods1i4mSWjbjKiFojJdRnXcfncZq2ykVIESjwapvTU=; b=Wag413bmGOCN6eKuZez1rtCIXd4Y7YHH0lhHoA+WgaXMk2QuKu0dRV5dJ62bMPwUIE Dqh5yLNv56RAFNu6Fy4aCUszLkAOLYZKCpOWd5MhOeN4JypejPeFwon20s0ZKZMyZejn L7zXmnUWOCgSqggFK5MOYHs/rbObzIKemIG0X2Q3Z+mCOk9QLCUlPTzgxqkuefuN51bf n/3c9esU28wJOvb9GWTdYPs5RVFQDRmaNjXIfukWcJ1tYmOMqNASqcJ9tqigYTxDEnco hycfA4lUBdkJBtuDrv0xcdyM66iormRJWzoUvIBXZ3puBB08pM56bM3C8M73T40gb0qs +Sbg== X-Gm-Message-State: ALoCoQlJ9UrmAsMcLwVw4/j20nz/8waO/A4QMXRAkn5HF9ScllruORcZRjTUYJjdH4UoyCltE21U X-Received: by 10.42.20.197 with SMTP id h5mr7470418icb.33.1396618951526; Fri, 04 Apr 2014 06:42:31 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.80.76 with SMTP id b70ls1029689qgd.97.gmail; Fri, 04 Apr 2014 06:42:31 -0700 (PDT) X-Received: by 10.52.175.166 with SMTP id cb6mr11005608vdc.1.1396618951358; Fri, 04 Apr 2014 06:42:31 -0700 (PDT) Received: from mail-ve0-f169.google.com (mail-ve0-f169.google.com [209.85.128.169]) by mx.google.com with ESMTPS id sq9si1782137vdc.71.2014.04.04.06.42.31 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 04 Apr 2014 06:42:31 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.128.169 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.128.169; Received: by mail-ve0-f169.google.com with SMTP id pa12so1494685veb.0 for ; Fri, 04 Apr 2014 06:42:31 -0700 (PDT) X-Received: by 10.221.40.10 with SMTP id to10mr1743641vcb.22.1396618951231; Fri, 04 Apr 2014 06:42:31 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.220.12.8 with SMTP id v8csp115278vcv; Fri, 4 Apr 2014 06:42:30 -0700 (PDT) X-Received: by 10.224.66.74 with SMTP id m10mr14705319qai.14.1396618950228; Fri, 04 Apr 2014 06:42:30 -0700 (PDT) Received: from lists.xen.org (lists.xen.org. [50.57.142.19]) by mx.google.com with ESMTPS id f33si3520103qgf.100.2014.04.04.06.42.29 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Fri, 04 Apr 2014 06:42:30 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of xen-devel-bounces@lists.xen.org designates 50.57.142.19 as permitted sender) client-ip=50.57.142.19; Received: from localhost ([127.0.0.1] helo=lists.xen.org) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1WW4MB-0005wf-Hl; Fri, 04 Apr 2014 13:40:31 +0000 Received: from mail6.bemta4.messagelabs.com ([85.158.143.247]) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1WW4M9-0005vD-OH for xen-devel@lists.xen.org; Fri, 04 Apr 2014 13:40:30 +0000 Received: from [85.158.143.35:56799] by server-3.bemta-4.messagelabs.com id 5C/11-13602-D46BE335; Fri, 04 Apr 2014 13:40:29 +0000 X-Env-Sender: Ian.Campbell@citrix.com X-Msg-Ref: server-15.tower-21.messagelabs.com!1396618826!6327899!1 X-Originating-IP: [66.165.176.63] X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni42MyA9PiAzMDYwNDg=\n X-StarScan-Received: X-StarScan-Version: 6.11.1; banners=-,-,- X-VirusChecked: Checked Received: (qmail 11483 invoked from network); 4 Apr 2014 13:40:27 -0000 Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63) by server-15.tower-21.messagelabs.com with RC4-SHA encrypted SMTP; 4 Apr 2014 13:40:27 -0000 X-IronPort-AV: E=Sophos;i="4.97,795,1389744000"; d="scan'208";a="116800691" Received: from accessns.citrite.net (HELO FTLPEX01CL03.citrite.net) ([10.9.154.239]) by FTLPIPO02.CITRIX.COM with ESMTP; 04 Apr 2014 13:40:26 +0000 Received: from norwich.cam.xci-test.com (10.80.248.129) by smtprelay.citrix.com (10.13.107.80) with Microsoft SMTP Server id 14.2.342.4; Fri, 4 Apr 2014 09:40:25 -0400 Received: from marilith-n13-p0.uk.xensource.com ([10.80.229.115] helo=marilith-n13.uk.xensource.com.) by norwich.cam.xci-test.com with esmtp (Exim 4.72) (envelope-from ) id 1WW4An-00010W-9W; Fri, 04 Apr 2014 13:28:45 +0000 From: Ian Campbell To: Date: Fri, 4 Apr 2014 14:28:45 +0100 Message-ID: <1396618125-1623-1-git-send-email-ian.campbell@citrix.com> X-Mailer: git-send-email 1.7.10.4 MIME-Version: 1.0 X-DLP: MIA2 Cc: Ian Jackson , julien.grall@linaro.org, tim@xen.org, Ian Campbell , stefano.stabellini@eu.citrix.com Subject: [Xen-devel] [PATCH v2] tools: implement initial ramdisk support for ARM. X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: List-Unsubscribe: , List-Post: , List-Help: , List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: ian.campbell@citrix.com X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.128.169 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 Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Archive: The ramdisk is passed to the kernel as a property in the chosen node of the device tree. This is somewhat tricky since in order to place the ramdisk and dtb in ram we first need to know the size of the dtb. So we initially create a DTB with placeholders for the ramdisk and finalise the value (which doesn't change the size) once we know where everything is. Rename libxl__arch_domain_configure to xl__arch_domain_init_hw_description to better reflect its use and to be consistent with the new libxl__arch_domain_finalise_hw_description. The common xc_dom_build_image() function did not support explicit placement of the ramdisk, instead passing 0 to xc_dom_alloc_segment, meaning "pick somewhere". This change instead passes ramdisk_seg.vstart. If nothing has set vstart then it will be zero because the entire dom struct is zeroed on allocation in xc_dom_allocate(). Therefore there is no change to the behaviour on x86. This is also consistent with how other segments (kernel, dtb) are handled. Furthermore if the ramdisk has been explicitly placed then xc_dom_build_image() assumes that it is not to be decompressed (since that would muck up the sizings used on placement). With all that I'm able to boot a domain using the current Debian Jessie armhf installer initrd and have it complete successfully. The emacs magic in tools/libxc/xc_dom_arm.c was wrong, so I corrected it while I was there. Signed-off-by: Ian Campbell Cc: Ian Jackson Acked-by: Ian Jackson Acked-by: Julien Grall --- v2: - moved comment into header and expanded/reworded a bit - none of the fdt_* calls in libxl__arch_domain_finalise_hw_description can fail, so simplify error handling using assert. I'm considering proposing this for backport to 4.4 since lack of initrd support is at the very least rather inconvenient for many use cases. Also, should we consider (separate from this change) making libxc not decompress the consider ramdisk by default? These days Linux at least can do the decompress itself and supports more algorithmns, like xz. --- tools/libxc/xc_dom.h | 8 ++++++ tools/libxc/xc_dom_arm.c | 65 ++++++++++++++++++++++++++++++++++---------- tools/libxc/xc_dom_core.c | 13 ++++++--- tools/libxl/libxl_arch.h | 11 +++++--- tools/libxl/libxl_arm.c | 66 ++++++++++++++++++++++++++++++++++++++++----- tools/libxl/libxl_dom.c | 8 ++++-- tools/libxl/libxl_x86.c | 13 ++++++--- 7 files changed, 152 insertions(+), 32 deletions(-) diff --git a/tools/libxc/xc_dom.h b/tools/libxc/xc_dom.h index 7099cee..313fd65 100644 --- a/tools/libxc/xc_dom.h +++ b/tools/libxc/xc_dom.h @@ -68,6 +68,14 @@ struct xc_dom_image { /* memory layout */ struct xc_dom_seg kernel_seg; + /* If ramdisk_seg.vstart is non zero then the ramdisk will be + * loaded at that address, otherwise it will automatically placed. + * + * If automatic placement is used and the ramdisk is gzip + * compressed then it will be decompressed as it is loaded. If the + * ramdisk has been explicitly placed then it is loaded as is + * itherwise decompressing risks undoing the manual placement. + */ struct xc_dom_seg ramdisk_seg; struct xc_dom_seg p2m_seg; struct xc_dom_seg pgtables_seg; diff --git a/tools/libxc/xc_dom_arm.c b/tools/libxc/xc_dom_arm.c index a40e04d..3330f12 100644 --- a/tools/libxc/xc_dom_arm.c +++ b/tools/libxc/xc_dom_arm.c @@ -249,6 +249,18 @@ int arch_setup_meminit(struct xc_dom_image *dom) { int rc; xen_pfn_t pfn, allocsz, i; + uint64_t modbase; + + /* Convenient */ + const uint64_t rambase = dom->rambase_pfn << XC_PAGE_SHIFT; + const uint64_t ramend = rambase + ( dom->total_pages << XC_PAGE_SHIFT ); + const uint64_t kernend = ROUNDUP(dom->kernel_seg.vend, 21/*2MB*/); + const uint64_t dtb_size = dom->devicetree_blob ? + ROUNDUP(dom->devicetree_size, XC_PAGE_SHIFT) : 0; + const uint64_t ramdisk_size = dom->ramdisk_blob ? + ROUNDUP(dom->ramdisk_size, XC_PAGE_SHIFT) : 0; + const uint64_t modsize = dtb_size + ramdisk_size; + const uint64_t ram128mb = rambase + (128<<20); rc = set_mode(dom->xch, dom->guest_domid, dom->guest_type); if ( rc ) @@ -278,23 +290,49 @@ int arch_setup_meminit(struct xc_dom_image *dom) 0, 0, &dom->p2m_host[i]); } - if ( dom->devicetree_blob ) + + /* + * Place boot modules at 128MB into RAM if there is enough RAM and + * the kernel does not overlap. Otherwise place them immediately + * after the kernel. If there is no space after the kernel then + * there is insufficient RAM and we fail. + */ + if ( ramend >= ram128mb + modsize && kernend < ram128mb ) + modbase = ram128mb; + else if ( ramend >= kernend + modsize ) + modbase = kernend; + else + return -1; + + DOMPRINTF("%s: placing boot modules at 0x%" PRIx64, __FUNCTION__, modbase); + + /* + * Must map DTB *after* initrd, to satisfy order of calls to + * xc_dom_alloc_segment in xc_dom_build_image, which must map + * things at monotonolically increasing addresses. + */ + if ( ramdisk_size ) { - const uint64_t rambase = dom->rambase_pfn << XC_PAGE_SHIFT; - const uint64_t ramend = rambase + ( dom->total_pages << XC_PAGE_SHIFT ); - const uint64_t dtbsize = ROUNDUP(dom->devicetree_size, XC_PAGE_SHIFT); - - /* Place at 128MB if there is sufficient RAM */ - if ( ramend >= rambase + 128*1024*1024 + dtbsize ) - dom->devicetree_seg.vstart = rambase + 128*1024*1024; - else /* otherwise at top of RAM */ - dom->devicetree_seg.vstart = ramend - dtbsize; - - dom->devicetree_seg.vend = - dom->devicetree_seg.vstart + dom->devicetree_size; + dom->ramdisk_seg.vstart = modbase; + dom->ramdisk_seg.vend = modbase + ramdisk_size; + + DOMPRINTF("%s: ramdisk: 0x%" PRIx64 " -> 0x%" PRIx64 "", + __FUNCTION__, + dom->ramdisk_seg.vstart, dom->ramdisk_seg.vend); + + modbase += ramdisk_size; + } + + if ( dtb_size ) + { + dom->devicetree_seg.vstart = modbase; + dom->devicetree_seg.vend = modbase + dtb_size; + DOMPRINTF("%s: devicetree: 0x%" PRIx64 " -> 0x%" PRIx64 "", __FUNCTION__, dom->devicetree_seg.vstart, dom->devicetree_seg.vend); + + modbase += dtb_size; } return 0; @@ -326,7 +364,6 @@ int xc_dom_feature_translated(struct xc_dom_image *dom) * mode: C * c-file-style: "BSD" * c-basic-offset: 4 - * tab-width: 4 * indent-tabs-mode: nil * End: */ diff --git a/tools/libxc/xc_dom_core.c b/tools/libxc/xc_dom_core.c index b9d1015..baa62a1 100644 --- a/tools/libxc/xc_dom_core.c +++ b/tools/libxc/xc_dom_core.c @@ -955,13 +955,20 @@ int xc_dom_build_image(struct xc_dom_image *dom) size_t unziplen, ramdisklen; void *ramdiskmap; - unziplen = xc_dom_check_gzip(dom->xch, dom->ramdisk_blob, dom->ramdisk_size); - if ( xc_dom_ramdisk_check_size(dom, unziplen) != 0 ) + if ( !dom->ramdisk_seg.vstart ) + { + unziplen = xc_dom_check_gzip(dom->xch, + dom->ramdisk_blob, dom->ramdisk_size); + if ( xc_dom_ramdisk_check_size(dom, unziplen) != 0 ) + unziplen = 0; + } + else unziplen = 0; ramdisklen = unziplen ? unziplen : dom->ramdisk_size; - if ( xc_dom_alloc_segment(dom, &dom->ramdisk_seg, "ramdisk", 0, + if ( xc_dom_alloc_segment(dom, &dom->ramdisk_seg, "ramdisk", + dom->ramdisk_seg.vstart, ramdisklen) != 0 ) goto err; ramdiskmap = xc_dom_seg_to_ptr(dom, &dom->ramdisk_seg); diff --git a/tools/libxl/libxl_arch.h b/tools/libxl/libxl_arch.h index aee0a91..d3bc136 100644 --- a/tools/libxl/libxl_arch.h +++ b/tools/libxl/libxl_arch.h @@ -19,7 +19,12 @@ int libxl__arch_domain_create(libxl__gc *gc, libxl_domain_config *d_config, uint32_t domid); -int libxl__arch_domain_configure(libxl__gc *gc, - libxl_domain_build_info *info, - struct xc_dom_image *dom); +/* setup arch specific hardware description, i.e. DTB on ARM */ +int libxl__arch_domain_init_hw_description(libxl__gc *gc, + libxl_domain_build_info *info, + struct xc_dom_image *dom); +/* finalize arch specific hardware description. */ +int libxl__arch_domain_finalise_hw_description(libxl__gc *gc, + libxl_domain_build_info *info, + struct xc_dom_image *dom); #endif diff --git a/tools/libxl/libxl_arm.c b/tools/libxl/libxl_arm.c index 0cfd0cf..4f0f0e2 100644 --- a/tools/libxl/libxl_arm.c +++ b/tools/libxl/libxl_arm.c @@ -2,6 +2,7 @@ #include "libxl_arch.h" #include +#include #include #include @@ -31,6 +32,9 @@ typedef be32 gic_interrupt[3]; #define ROOT_ADDRESS_CELLS 2 #define ROOT_SIZE_CELLS 2 +#define PROP_INITRD_START "linux,initrd-start" +#define PROP_INITRD_END "linux,initrd-end" + static void set_cell(be32 **cellp, int size, uint64_t val) { int cells = size; @@ -155,7 +159,7 @@ static int make_root_properties(libxl__gc *gc, return 0; } -static int make_chosen_node(libxl__gc *gc, void *fdt, +static int make_chosen_node(libxl__gc *gc, void *fdt, bool ramdisk, const libxl_domain_build_info *info) { int res; @@ -169,6 +173,15 @@ static int make_chosen_node(libxl__gc *gc, void *fdt, if (res) return res; } + if (ramdisk) { + uint64_t dummy = 0; + LOG(DEBUG, "/chosen adding placeholder linux,initrd properties"); + res = fdt_property(fdt, PROP_INITRD_START, &dummy, sizeof(dummy)); + if (res) return res; + res = fdt_property(fdt, PROP_INITRD_END, &dummy, sizeof(dummy)); + if (res) return res; + } + res = fdt_end_node(fdt); if (res) return res; @@ -412,9 +425,9 @@ out: #define FDT_MAX_SIZE (1<<20) -int libxl__arch_domain_configure(libxl__gc *gc, - libxl_domain_build_info *info, - struct xc_dom_image *dom) +int libxl__arch_domain_init_hw_description(libxl__gc *gc, + libxl_domain_build_info *info, + struct xc_dom_image *dom) { void *fdt = NULL; int rc, res; @@ -475,7 +488,7 @@ next_resize: FDT( fdt_begin_node(fdt, "") ); FDT( make_root_properties(gc, vers, fdt) ); - FDT( make_chosen_node(gc, fdt, info) ); + FDT( make_chosen_node(gc, fdt, !!dom->ramdisk_blob, info) ); FDT( make_cpus_node(gc, fdt, info->max_vcpus, ainfo) ); FDT( make_psci_node(gc, fdt) ); @@ -505,10 +518,49 @@ next_resize: goto out; } - debug_dump_fdt(gc, fdt); - rc = 0; out: return rc; } + +int libxl__arch_domain_finalise_hw_description(libxl__gc *gc, + libxl_domain_build_info *info, + struct xc_dom_image *dom) +{ + void *fdt = dom->devicetree_blob; + + const struct xc_dom_seg *ramdisk = dom->ramdisk_blob ? + &dom->ramdisk_seg : NULL; + + if (ramdisk) { + int chosen, res; + uint64_t val; + + /* Neither the fdt_path_offset() nor either of the + * fdt_setprop_inplace() calls can fail. If they do then + * make_chosen_node() (see above) has got something very + * wrong. + */ + chosen = fdt_path_offset(fdt, "/chosen"); + assert(chosen > 0); + + LOG(DEBUG, "/chosen updating initrd properties to cover " + "%"PRIx64"-%"PRIx64, + ramdisk->vstart, ramdisk->vend); + + val = cpu_to_fdt64(ramdisk->vstart); + res = fdt_setprop_inplace(fdt, chosen, PROP_INITRD_START, + &val, sizeof(val)); + assert(!res); + + val = cpu_to_fdt64(ramdisk->vend); + res = fdt_setprop_inplace(fdt, chosen,PROP_INITRD_END, + &val, sizeof(val)); + assert(!res); + } + + debug_dump_fdt(gc, fdt); + + return 0; +} diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c index 36e70b5..c3fa439 100644 --- a/tools/libxl/libxl_dom.c +++ b/tools/libxl/libxl_dom.c @@ -407,8 +407,8 @@ int libxl__build_pv(libxl__gc *gc, uint32_t domid, LOGE(ERROR, "xc_dom_parse_image failed"); goto out; } - if ( (ret = libxl__arch_domain_configure(gc, info, dom)) != 0 ) { - LOGE(ERROR, "libxl__arch_domain_configure failed"); + if ( (ret = libxl__arch_domain_init_hw_description(gc, info, dom)) != 0 ) { + LOGE(ERROR, "libxl__arch_domain_init_hw_description failed"); goto out; } if ( (ret = xc_dom_mem_init(dom, info->target_memkb / 1024)) != 0 ) { @@ -419,6 +419,10 @@ int libxl__build_pv(libxl__gc *gc, uint32_t domid, LOGE(ERROR, "xc_dom_boot_mem_init failed"); goto out; } + if ( (ret = libxl__arch_domain_finalise_hw_description(gc, info, dom)) != 0 ) { + LOGE(ERROR, "libxl__arch_domain_finalise_hw_description failed"); + goto out; + } if ( (ret = xc_dom_build_image(dom)) != 0 ) { LOGE(ERROR, "xc_dom_build_image failed"); goto out; diff --git a/tools/libxl/libxl_x86.c b/tools/libxl/libxl_x86.c index b11d036..7589060 100644 --- a/tools/libxl/libxl_x86.c +++ b/tools/libxl/libxl_x86.c @@ -311,9 +311,16 @@ int libxl__arch_domain_create(libxl__gc *gc, libxl_domain_config *d_config, return ret; } -int libxl__arch_domain_configure(libxl__gc *gc, - libxl_domain_build_info *info, - struct xc_dom_image *dom) +int libxl__arch_domain_init_hw_description(libxl__gc *gc, + libxl_domain_build_info *info, + struct xc_dom_image *dom) +{ + return 0; +} + +int libxl__arch_domain_finalise_hw_description(libxl__gc *gc, + libxl_domain_build_info *info, + struct xc_dom_image *dom) { return 0; }