From patchwork Wed Jan 8 11:13:03 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oleksii Kurochko X-Patchwork-Id: 13930560 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 2A687E7719F for ; Wed, 8 Jan 2025 11:13:39 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.867133.1278561 (Exim 4.92) (envelope-from ) id 1tVTzy-0001Jf-Mz; Wed, 08 Jan 2025 11:13:18 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 867133.1278561; Wed, 08 Jan 2025 11:13:18 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1tVTzy-0001Hz-Jz; Wed, 08 Jan 2025 11:13:18 +0000 Received: by outflank-mailman (input) for mailman id 867133; Wed, 08 Jan 2025 11:13:17 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1tVTzx-0001BZ-4A for xen-devel@lists.xenproject.org; Wed, 08 Jan 2025 11:13:17 +0000 Received: from mail-lj1-x231.google.com (mail-lj1-x231.google.com [2a00:1450:4864:20::231]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id 8e912d6c-cdb1-11ef-a0df-8be0dac302b0; Wed, 08 Jan 2025 12:13:15 +0100 (CET) Received: by mail-lj1-x231.google.com with SMTP id 38308e7fff4ca-3003943288bso187518711fa.0 for ; Wed, 08 Jan 2025 03:13:15 -0800 (PST) Received: from fedora.. ([94.75.70.14]) by smtp.gmail.com with ESMTPSA id 38308e7fff4ca-3045ad99d11sm67292171fa.33.2025.01.08.03.13.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 08 Jan 2025 03:13:14 -0800 (PST) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 8e912d6c-cdb1-11ef-a0df-8be0dac302b0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1736334795; x=1736939595; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=khyzmr/9Ez+tN2hOqgwIY9MJyCMCvynyh0dRKtdVRpU=; b=Z9nNzqbwMjGUgeOL+QeXeCGtITB3765me9+wzkX26MB3Ac+dYed9cpocbAPyjSI2rK qX+SHFnoVqKsqtVF/jdgQxhSj/CXZAOe6QYFde5oZz2V2+8KJIqpsz+Zw5nfzvBkoXC1 lfIoQ7ifIWHe1ZWdYymlnIoD0NZeJSHYn+vHTyB0x7UcqPjxbMf1gHO8DmqG38r4t6L/ MNsz+JrTkZ2IH3rAFIbOP8Oy+dd+ekzXBjPuQZaJck8U7QDyiV+DUawuc5Ybf3IGFEKG XpDP5uukPq7Sll4JCj/cI1TLiLVVgzEdtX1Qtvwqps65+2U237rrGrI71WSI6vs8Eykm LyBQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1736334795; x=1736939595; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=khyzmr/9Ez+tN2hOqgwIY9MJyCMCvynyh0dRKtdVRpU=; b=kTzYO/cPDBYlmziP/8oLWbjHA1YS4d/ZwufTYSfY7iCQiBKgznB10Ss456dCebpWMe 1Sf1O5tizCWsdARxrekfCrhIcy+wz34UknGItZQ0SkMwPWsmHoTTKfCTp/isZNq/SNSe /iu8bN7xOIreF24HTHT3VgTV7t7aQp1xWNLyW/k5oIo6Bjuoa+sQuo1FjZqs1mPaHByu Vtm45SZUML4vUP5wZXDcyuoERLQjp3aLZSdy+3avn26QUwzuVJsjdh332gfhaIWgzbOd 8bEwXsQzJxJAWmN5ImIcuUiTi6us8JlWEQmZc0bdopi5LhP3xot1jFK1B6elEuhtJ8K/ CJKQ== X-Gm-Message-State: AOJu0YxTiNonHxkc4fWDfAtMCfE8WJI/KhAaG/aQWZSTc8Yy5C6lqWED 0aRu5pd1PTLAC+hfKajwbBhbPOzj78O4NscKYWF35Y03T+DFZCuKn+WmgxYw X-Gm-Gg: ASbGncsSi0Edu3UhxUWpG5gfhwkgVOCkJSKE5IbSNQcqqRSoNq8aOMBqqoN2pYEIswC VLLb6p/IzYAHT9zEs9xaDryOdHNuhUjoK2DXX+YEYH/vBkcQ177HOu+IC8xtrZA6PFa7UJ+nTjV lEfLGwCtnuWdKI9tAjbM3FFfXdg6ZDWg/ruj05/iHxvY5ZcwQeB+Y210XJfmZSpZFdXtqucX5hd yf9JKVzKmJOm7EQrEYB4A6ltUetDmPLRMdeOfuPhhogIpN72iVfiTLyng== X-Google-Smtp-Source: AGHT+IHzQbhrAIsD8/khEWYTRZbSzjvroSOvz6vYlYUIeTqvwxtRVs75BZuJepoG10lmND9Gkqk+uw== X-Received: by 2002:a2e:bb8e:0:b0:300:1f2d:97a with SMTP id 38308e7fff4ca-305f4547ea2mr4884401fa.16.1736334794385; Wed, 08 Jan 2025 03:13:14 -0800 (PST) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Oleksii Kurochko , Stefano Stabellini , Julien Grall , Bertrand Marquis , Michal Orzel , Volodymyr Babchuk , Andrew Cooper , Anthony PERARD , Jan Beulich , =?utf-8?q?Roger_Pau_Monn=C3=A9?= Subject: [PATCH v1 1/9] xen/common: dom0less: make some parts of Arm's CONFIG_DOM0LESS common Date: Wed, 8 Jan 2025 12:13:03 +0100 Message-ID: <396a60496844c8a86667f4ee57c5bedc9899f5ad.1736334615.git.oleksii.kurochko@gmail.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: References: MIME-Version: 1.0 Unify the API for creating DomUs and checking for Dom0less mode across architectures, including Arm and RISC-V, with potential applicability for PPC. Move dom0less-build.h from the Arm-specific directory to asm-generic as these header is expected to be the same across acrhictectures with some updates: add the following declaration of construct_domU(), arch_xen_domctl_createdomain() and arch_create_domus() as there are some parts which are still architecture-specific. Relocate the CONFIG_DOM0LESS configuration to the common with adding "depends on Arm" to not break builds for architectures which at the moment don't support CONFIG_DOM0LESS config, especically it would be useful to not provide stubs for construct_domU(), arch_xen_domctl_createdomain() and arch_create_domus() in case of *-randconfig which may set CONFIG_DOM0LESS=y. Move is_dom0less_mode() function to the common code, as it depends on boot modules that are already part of the common code. Move create_domUs() function to the common code with some updates: - Add function arch_xen_domctl_createdomain() as structure xen_domctl_createdomain may have some arch-spicific information and initialization. - Add arch_create_domus() to cover parsing of arch-specific features, for example, SVE (Scalar Vector Extension ) exists only in Arm. Signed-off-by: Oleksii Kurochko --- xen/arch/arm/Kconfig | 8 - xen/arch/arm/dom0less-build.c | 270 ++++++---------------- xen/arch/arm/include/asm/Makefile | 1 + xen/arch/arm/include/asm/dom0less-build.h | 32 --- xen/common/Kconfig | 9 + xen/common/device-tree/Makefile | 1 + xen/common/device-tree/dom0less-build.c | 161 +++++++++++++ xen/include/asm-generic/dom0less-build.h | 40 ++++ 8 files changed, 283 insertions(+), 239 deletions(-) delete mode 100644 xen/arch/arm/include/asm/dom0less-build.h create mode 100644 xen/common/device-tree/dom0less-build.c create mode 100644 xen/include/asm-generic/dom0less-build.h diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig index a26d3e1182..eff6ea6b6d 100644 --- a/xen/arch/arm/Kconfig +++ b/xen/arch/arm/Kconfig @@ -117,14 +117,6 @@ config GICV2 Driver for the ARM Generic Interrupt Controller v2. If unsure, say Y -config DOM0LESS_BOOT - bool "Dom0less boot support" if EXPERT - default y - help - Dom0less boot support enables Xen to create and start domU guests during - Xen boot without the need of a control domain (Dom0), which could be - present anyway. - config GICV3 bool "GICv3 driver" depends on !NEW_VGIC diff --git a/xen/arch/arm/dom0less-build.c b/xen/arch/arm/dom0less-build.c index 49d1f14d65..b27747c05c 100644 --- a/xen/arch/arm/dom0less-build.c +++ b/xen/arch/arm/dom0less-build.c @@ -17,38 +17,6 @@ #include #include -bool __init is_dom0less_mode(void) -{ - struct bootmodules *mods = &bootinfo.modules; - struct bootmodule *mod; - unsigned int i; - bool dom0found = false; - bool domUfound = false; - - /* Look into the bootmodules */ - for ( i = 0 ; i < mods->nr_mods ; i++ ) - { - mod = &mods->module[i]; - /* Find if dom0 and domU kernels are present */ - if ( mod->kind == BOOTMOD_KERNEL ) - { - if ( mod->domU == false ) - { - dom0found = true; - break; - } - else - domUfound = true; - } - } - - /* - * If there is no dom0 kernel but at least one domU, then we are in - * dom0less mode - */ - return ( !dom0found && domUfound ); -} - #ifdef CONFIG_VGICV2 static int __init make_gicv2_domU_node(struct kernel_info *kinfo) { @@ -704,8 +672,8 @@ static int __init alloc_xenstore_evtchn(struct domain *d) return 0; } -static int __init construct_domU(struct domain *d, - const struct dt_device_node *node) +int __init construct_domU(struct domain *d, + const struct dt_device_node *node) { struct kernel_info kinfo = KERNEL_INFO_INIT; const char *dom0less_enhanced; @@ -810,188 +778,92 @@ static int __init construct_domU(struct domain *d, return rc; } -void __init create_domUs(void) -{ - struct dt_device_node *node; - const char *dom0less_iommu; - bool iommu = false; - const struct dt_device_node *cpupool_node, - *chosen = dt_find_node_by_path("/chosen"); - const char *llc_colors_str = NULL; - - BUG_ON(chosen == NULL); - dt_for_each_child_node(chosen, node) - { - struct domain *d; - struct xen_domctl_createdomain d_cfg = { - .arch.gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE, - .flags = XEN_DOMCTL_CDF_hvm | XEN_DOMCTL_CDF_hap, - /* - * The default of 1023 should be sufficient for guests because - * on ARM we don't bind physical interrupts to event channels. - * The only use of the evtchn port is inter-domain communications. - * 1023 is also the default value used in libxl. - */ - .max_evtchn_port = 1023, - .max_grant_frames = -1, - .max_maptrack_frames = -1, - .grant_opts = XEN_DOMCTL_GRANT_version(opt_gnttab_max_version), - }; - unsigned int flags = 0U; - uint32_t val; - int rc; - - if ( !dt_device_is_compatible(node, "xen,domain") ) - continue; - if ( (max_init_domid + 1) >= DOMID_FIRST_RESERVED ) - panic("No more domain IDs available\n"); - - if ( dt_find_property(node, "xen,static-mem", NULL) ) - { - if ( llc_coloring_enabled ) - panic("LLC coloring and static memory are incompatible\n"); - - flags |= CDF_staticmem; - } - - if ( dt_property_read_bool(node, "direct-map") ) - { - if ( !(flags & CDF_staticmem) ) - panic("direct-map is not valid for domain %s without static allocation.\n", - dt_node_name(node)); - - flags |= CDF_directmap; - } - - if ( !dt_property_read_u32(node, "cpus", &d_cfg.max_vcpus) ) - panic("Missing property 'cpus' for domain %s\n", - dt_node_name(node)); - - if ( !dt_property_read_string(node, "passthrough", &dom0less_iommu) && - !strcmp(dom0less_iommu, "enabled") ) - iommu = true; +struct xen_domctl_createdomain __init arch_xen_domctl_createdomain(void) +{ + struct xen_domctl_createdomain d_cfg = { + .arch.gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE, + .flags = XEN_DOMCTL_CDF_hvm | XEN_DOMCTL_CDF_hap, + /* + * The default of 1023 should be sufficient for guests because + * on ARM we don't bind physical interrupts to event channels. + * The only use of the evtchn port is inter-domain communications. + * 1023 is also the default value used in libxl. + */ + .max_evtchn_port = 1023, + .max_grant_frames = -1, + .max_maptrack_frames = -1, + .grant_opts = XEN_DOMCTL_GRANT_version(opt_gnttab_max_version), + }; + + return d_cfg; +} - if ( iommu_enabled && - (iommu || dt_find_compatible_node(node, NULL, - "multiboot,device-tree")) ) - d_cfg.flags |= XEN_DOMCTL_CDF_iommu; +void __init arch_create_domus(struct dt_device_node *node, + struct xen_domctl_createdomain *d_cfg, + unsigned int flags) +{ + uint32_t val; - if ( !dt_property_read_u32(node, "nr_spis", &d_cfg.arch.nr_spis) ) - { - int vpl011_virq = GUEST_VPL011_SPI; - - d_cfg.arch.nr_spis = gic_number_lines() - 32; - - /* - * The VPL011 virq is GUEST_VPL011_SPI, unless direct-map is - * set, in which case it'll match the hardware. - * - * Since the domain is not yet created, we can't use - * d->arch.vpl011.irq. So the logic to find the vIRQ has to - * be hardcoded. - * The logic here shall be consistent with the one in - * domain_vpl011_init(). - */ - if ( flags & CDF_directmap ) - { - vpl011_virq = serial_irq(SERHND_DTUART); - if ( vpl011_virq < 0 ) - panic("Error getting IRQ number for this serial port %d\n", - SERHND_DTUART); - } + if ( !dt_property_read_u32(node, "nr_spis", &d_cfg->arch.nr_spis) ) + { + int vpl011_virq = GUEST_VPL011_SPI; - /* - * vpl011 uses one emulated SPI. If vpl011 is requested, make - * sure that we allocate enough SPIs for it. - */ - if ( dt_property_read_bool(node, "vpl011") ) - d_cfg.arch.nr_spis = MAX(d_cfg.arch.nr_spis, - vpl011_virq - 32 + 1); - } + d_cfg->arch.nr_spis = gic_number_lines() - 32; - /* Get the optional property domain-cpupool */ - cpupool_node = dt_parse_phandle(node, "domain-cpupool", 0); - if ( cpupool_node ) + /* + * The VPL011 virq is GUEST_VPL011_SPI, unless direct-map is + * set, in which case it'll match the hardware. + * + * Since the domain is not yet created, we can't use + * d->arch.vpl011.irq. So the logic to find the vIRQ has to + * be hardcoded. + * The logic here shall be consistent with the one in + * domain_vpl011_init(). + */ + if ( flags & CDF_directmap ) { - int pool_id = btcpupools_get_domain_pool_id(cpupool_node); - if ( pool_id < 0 ) - panic("Error getting cpupool id from domain-cpupool (%d)\n", - pool_id); - d_cfg.cpupool_id = pool_id; + vpl011_virq = serial_irq(SERHND_DTUART); + if ( vpl011_virq < 0 ) + panic("Error getting IRQ number for this serial port %d\n", + SERHND_DTUART); } - if ( dt_property_read_u32(node, "max_grant_version", &val) ) - d_cfg.grant_opts = XEN_DOMCTL_GRANT_version(val); + /* + * vpl011 uses one emulated SPI. If vpl011 is requested, make + * sure that we allocate enough SPIs for it. + */ + if ( dt_property_read_bool(node, "vpl011") ) + d_cfg->arch.nr_spis = MAX(d_cfg->arch.nr_spis, + vpl011_virq - 32 + 1); + } - if ( dt_property_read_u32(node, "max_grant_frames", &val) ) - { - if ( val > INT32_MAX ) - panic("max_grant_frames (%"PRIu32") overflow\n", val); - d_cfg.max_grant_frames = val; - } + if ( dt_get_property(node, "sve", &val) ) + { +#ifdef CONFIG_ARM64_SVE + unsigned int sve_vl_bits; + bool ret = false; - if ( dt_property_read_u32(node, "max_maptrack_frames", &val) ) + if ( !val ) { - if ( val > INT32_MAX ) - panic("max_maptrack_frames (%"PRIu32") overflow\n", val); - d_cfg.max_maptrack_frames = val; + /* Property found with no value, means max HW VL supported */ + ret = sve_domctl_vl_param(-1, &sve_vl_bits); } - - if ( dt_get_property(node, "sve", &val) ) + else { -#ifdef CONFIG_ARM64_SVE - unsigned int sve_vl_bits; - bool ret = false; - - if ( !val ) - { - /* Property found with no value, means max HW VL supported */ - ret = sve_domctl_vl_param(-1, &sve_vl_bits); - } + if ( dt_property_read_u32(node, "sve", &val) ) + ret = sve_domctl_vl_param(val, &sve_vl_bits); else - { - if ( dt_property_read_u32(node, "sve", &val) ) - ret = sve_domctl_vl_param(val, &sve_vl_bits); - else - panic("Error reading 'sve' property\n"); - } + panic("Error reading 'sve' property\n"); + } - if ( ret ) - d_cfg.arch.sve_vl = sve_encode_vl(sve_vl_bits); - else - panic("SVE vector length error\n"); + if ( ret ) + d_cfg->arch.sve_vl = sve_encode_vl(sve_vl_bits); + else + panic("SVE vector length error\n"); #else - panic("'sve' property found, but CONFIG_ARM64_SVE not selected\n"); + panic("'sve' property found, but CONFIG_ARM64_SVE not selected\n"); #endif - } - - dt_property_read_string(node, "llc-colors", &llc_colors_str); - if ( !llc_coloring_enabled && llc_colors_str ) - panic("'llc-colors' found, but LLC coloring is disabled\n"); - - /* - * The variable max_init_domid is initialized with zero, so here it's - * very important to use the pre-increment operator to call - * domain_create() with a domid > 0. (domid == 0 is reserved for Dom0) - */ - d = domain_create(++max_init_domid, &d_cfg, flags); - if ( IS_ERR(d) ) - panic("Error creating domain %s (rc = %ld)\n", - dt_node_name(node), PTR_ERR(d)); - - if ( llc_coloring_enabled && - (rc = domain_set_llc_colors_from_str(d, llc_colors_str)) ) - panic("Error initializing LLC coloring for domain %s (rc = %d)\n", - dt_node_name(node), rc); - - d->is_console = true; - dt_device_set_used_by(node, d->domain_id); - - rc = construct_domU(d, node); - if ( rc ) - panic("Could not set up domain %s (rc = %d)\n", - dt_node_name(node), rc); } } diff --git a/xen/arch/arm/include/asm/Makefile b/xen/arch/arm/include/asm/Makefile index 4a4036c951..831c914cce 100644 --- a/xen/arch/arm/include/asm/Makefile +++ b/xen/arch/arm/include/asm/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only generic-y += altp2m.h generic-y += device.h +generic-y += dom0less-build.h generic-y += hardirq.h generic-y += iocap.h generic-y += paging.h diff --git a/xen/arch/arm/include/asm/dom0less-build.h b/xen/arch/arm/include/asm/dom0less-build.h deleted file mode 100644 index 5864944bda..0000000000 --- a/xen/arch/arm/include/asm/dom0less-build.h +++ /dev/null @@ -1,32 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ - -#ifndef __ASM_DOM0LESS_BUILD_H_ -#define __ASM_DOM0LESS_BUILD_H_ - -#include - -#ifdef CONFIG_DOM0LESS_BOOT - -void create_domUs(void); -bool is_dom0less_mode(void); - -#else /* !CONFIG_DOM0LESS_BOOT */ - -static inline void create_domUs(void) {} -static inline bool is_dom0less_mode(void) -{ - return false; -} - -#endif /* CONFIG_DOM0LESS_BOOT */ - -#endif /* __ASM_DOM0LESS_BUILD_H_ */ - -/* - * Local variables: - * mode: C - * c-file-style: "BSD" - * c-basic-offset: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/xen/common/Kconfig b/xen/common/Kconfig index 6166327f4d..099e6e72ad 100644 --- a/xen/common/Kconfig +++ b/xen/common/Kconfig @@ -12,6 +12,15 @@ config CORE_PARKING bool depends on NR_CPUS > 1 +config DOM0LESS_BOOT + bool "Dom0less boot support" if EXPERT + depends on ARM + default ARM + help + Dom0less boot support enables Xen to create and start domU guests during + Xen boot without the need of a control domain (Dom0), which could be + present anyway. + config GRANT_TABLE bool "Grant table support" if EXPERT default y diff --git a/xen/common/device-tree/Makefile b/xen/common/device-tree/Makefile index 7c549be38a..f3dafc9b81 100644 --- a/xen/common/device-tree/Makefile +++ b/xen/common/device-tree/Makefile @@ -1,5 +1,6 @@ obj-y += bootfdt.init.o obj-y += bootinfo.init.o obj-y += device-tree.o +obj-$(CONFIG_DOM0LESS_BOOT) += dom0less-build.o obj-$(CONFIG_OVERLAY_DTB) += dt-overlay.o obj-y += intc.o diff --git a/xen/common/device-tree/dom0less-build.c b/xen/common/device-tree/dom0less-build.c new file mode 100644 index 0000000000..19bfa5e005 --- /dev/null +++ b/xen/common/device-tree/dom0less-build.c @@ -0,0 +1,161 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +bool __init is_dom0less_mode(void) +{ + struct bootmodules *mods = &bootinfo.modules; + struct bootmodule *mod; + unsigned int i; + bool dom0found = false; + bool domUfound = false; + + /* Look into the bootmodules */ + for ( i = 0 ; i < mods->nr_mods ; i++ ) + { + mod = &mods->module[i]; + /* Find if dom0 and domU kernels are present */ + if ( mod->kind == BOOTMOD_KERNEL ) + { + if ( mod->domU == false ) + { + dom0found = true; + break; + } + else + domUfound = true; + } + } + + /* + * If there is no dom0 kernel but at least one domU, then we are in + * dom0less mode + */ + return ( !dom0found && domUfound ); +} + +void __init create_domUs(void) +{ + struct dt_device_node *node; + const char *dom0less_iommu; + bool iommu = false; + const struct dt_device_node *cpupool_node, + *chosen = dt_find_node_by_path("/chosen"); + const char *llc_colors_str = NULL; + + BUG_ON(chosen == NULL); + dt_for_each_child_node(chosen, node) + { + struct domain *d; + struct xen_domctl_createdomain d_cfg = arch_xen_domctl_createdomain(); + unsigned int flags = 0U; + uint32_t val; + int rc; + + if ( !dt_device_is_compatible(node, "xen,domain") ) + continue; + + if ( (max_init_domid + 1) >= DOMID_FIRST_RESERVED ) + panic("No more domain IDs available\n"); + + if ( dt_find_property(node, "xen,static-mem", NULL) ) + { + if ( llc_coloring_enabled ) + panic("LLC coloring and static memory are incompatible\n"); + + flags |= CDF_staticmem; + } + + if ( dt_property_read_bool(node, "direct-map") ) + { + if ( !(flags & CDF_staticmem) ) + panic("direct-map is not valid for domain %s without static allocation.\n", + dt_node_name(node)); + + flags |= CDF_directmap; + } + + if ( !dt_property_read_u32(node, "cpus", &d_cfg.max_vcpus) ) + panic("Missing property 'cpus' for domain %s\n", + dt_node_name(node)); + + if ( !dt_property_read_string(node, "passthrough", &dom0less_iommu) && + !strcmp(dom0less_iommu, "enabled") ) + iommu = true; + + if ( iommu_enabled && + (iommu || dt_find_compatible_node(node, NULL, + "multiboot,device-tree")) ) + d_cfg.flags |= XEN_DOMCTL_CDF_iommu; + + /* Get the optional property domain-cpupool */ + cpupool_node = dt_parse_phandle(node, "domain-cpupool", 0); + if ( cpupool_node ) + { + int pool_id = btcpupools_get_domain_pool_id(cpupool_node); + if ( pool_id < 0 ) + panic("Error getting cpupool id from domain-cpupool (%d)\n", + pool_id); + d_cfg.cpupool_id = pool_id; + } + + if ( dt_property_read_u32(node, "max_grant_version", &val) ) + d_cfg.grant_opts = XEN_DOMCTL_GRANT_version(val); + + if ( dt_property_read_u32(node, "max_grant_frames", &val) ) + { + if ( val > INT32_MAX ) + panic("max_grant_frames (%"PRIu32") overflow\n", val); + d_cfg.max_grant_frames = val; + } + + if ( dt_property_read_u32(node, "max_maptrack_frames", &val) ) + { + if ( val > INT32_MAX ) + panic("max_maptrack_frames (%"PRIu32") overflow\n", val); + d_cfg.max_maptrack_frames = val; + } + + dt_property_read_string(node, "llc-colors", &llc_colors_str); + if ( !llc_coloring_enabled && llc_colors_str ) + panic("'llc-colors' found, but LLC coloring is disabled\n"); + + arch_create_domus(node, &d_cfg, flags); + + /* + * The variable max_init_domid is initialized with zero, so here it's + * very important to use the pre-increment operator to call + * domain_create() with a domid > 0. (domid == 0 is reserved for Dom0) + */ + d = domain_create(++max_init_domid, &d_cfg, flags); + if ( IS_ERR(d) ) + panic("Error creating domain %s (rc = %ld)\n", + dt_node_name(node), PTR_ERR(d)); + + if ( llc_coloring_enabled && + (rc = domain_set_llc_colors_from_str(d, llc_colors_str)) ) + panic("Error initializing LLC coloring for domain %s (rc = %d)\n", + dt_node_name(node), rc); + + d->is_console = true; + dt_device_set_used_by(node, d->domain_id); + + rc = construct_domU(d, node); + if ( rc ) + panic("Could not set up domain %s (rc = %d)\n", + dt_node_name(node), rc); + } +} diff --git a/xen/include/asm-generic/dom0less-build.h b/xen/include/asm-generic/dom0less-build.h new file mode 100644 index 0000000000..a6985bc20a --- /dev/null +++ b/xen/include/asm-generic/dom0less-build.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef __ASM_GENERIC_DOM0LESS_BUILD_H__ +#define __ASM_GENERIC_DOM0LESS_BUILD_H__ + +#include + +#ifdef CONFIG_DOM0LESS_BOOT + +#include + +void create_domUs(void); +bool is_dom0less_mode(void); + +int construct_domU(struct domain *d, const struct dt_device_node *node); + +struct xen_domctl_createdomain arch_xen_domctl_createdomain(void); +void arch_create_domus(struct dt_device_node *node, + struct xen_domctl_createdomain *d_cfg, + unsigned int flags); + +#else /* !CONFIG_DOM0LESS_BOOT */ + +static inline void create_domUs(void) {} +static inline bool is_dom0less_mode(void) +{ + return false; +} + +#endif /* CONFIG_DOM0LESS_BOOT */ + +#endif /* __ASM_GENERIC_DOM0LESS_BUILD_H__ */ + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ From patchwork Wed Jan 8 11:13:04 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oleksii Kurochko X-Patchwork-Id: 13930562 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 0DE51E77188 for ; Wed, 8 Jan 2025 11:13:38 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.867134.1278568 (Exim 4.92) (envelope-from ) id 1tVTzz-0001OT-2q; Wed, 08 Jan 2025 11:13:19 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 867134.1278568; Wed, 08 Jan 2025 11:13:19 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1tVTzy-0001Mv-Sa; Wed, 08 Jan 2025 11:13:18 +0000 Received: by outflank-mailman (input) for mailman id 867134; Wed, 08 Jan 2025 11:13:18 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1tVTzx-0001BZ-SM for xen-devel@lists.xenproject.org; Wed, 08 Jan 2025 11:13:17 +0000 Received: from mail-lj1-x22a.google.com (mail-lj1-x22a.google.com [2a00:1450:4864:20::22a]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id 8ee60536-cdb1-11ef-a0df-8be0dac302b0; Wed, 08 Jan 2025 12:13:16 +0100 (CET) Received: by mail-lj1-x22a.google.com with SMTP id 38308e7fff4ca-304d760f0dfso50250541fa.2 for ; Wed, 08 Jan 2025 03:13:16 -0800 (PST) Received: from fedora.. ([94.75.70.14]) by smtp.gmail.com with ESMTPSA id 38308e7fff4ca-3045ad99d11sm67292171fa.33.2025.01.08.03.13.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 08 Jan 2025 03:13:14 -0800 (PST) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 8ee60536-cdb1-11ef-a0df-8be0dac302b0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1736334796; x=1736939596; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=GR2a/0jnuvbrYQt6CCllwzwGe4JakRFRLxGKEovkNEQ=; b=a9OS8uP9V30NUmR7MKpmh3whzHv36zAtbxa5q/6yCD2Ow+3XrfHvchNBkjHRjobKI9 f8GJmwGs9cvZurgFFnDggsprXpW/9mdONBGLI8NZCHdBpmyNZBuS5EUvP/EjdyQZaI00 sFMKyezmcdkZtxqsWI+to3N43EJTPB95MqnHuYFpPimtK2sY4zxmDWWrNUsZItJcudNY BeKFSYZegI/yrcKG+7LKqslejlzdqjSCG9SPX3uftvFB0fifCBKgUZHN85lAIxt9gtyJ gHjKYBxVx/OOvX8GS5QjzhRDE3GygVw4KdKZeD1083mO8Yk1h8h5BFhWNzE5LJs81foG hmmg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1736334796; x=1736939596; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=GR2a/0jnuvbrYQt6CCllwzwGe4JakRFRLxGKEovkNEQ=; b=Uv00/BseS/srHlaVLT5v72Uut+MLmFWBteFks0Agn9k823OEILjsRM78OuNZOLiwoj 6m+HGiBeSHHLYanwb1PD7yhjoKgieE2PzYvj2hU5Ihri42LGtwtDqEkxYECtOX+by3OE UOx7SNv/m1U4RZguPQx5kAUDAFc9xfHb/6R7vX3GU3pG2ypvxXg7+WEfDkOU+CL5PgUi UDR3dsH1JxMicRg5EqsrwfkWohM+01nebA3+SC4sO1vkSv7yAkUyRhNncpNC1O1z+2XU i9AGE1Ipj5XCnpAz39yLtaTLE8Okp+8UJ41sK1fTYnHbrzwg6sh+8hf4dV/ypYvh9Wiw tNlw== X-Gm-Message-State: AOJu0Yxx+nTTKTPLmPQ9Q4z1aWf+JEHAZied5jkq1YmhW6fiA65LPXa0 fu8N+sV4odw0F31iZR85vCNLRqxrz2gZ7vlDtgssJb34oqX3eTnqxwx0jh/x X-Gm-Gg: ASbGncsvxliWtIMOPCMtQUKFhCt/ZcEaEQw8+/eMM2v7TV7vy5qdQc0ilxoUAZg8OWq b0Nl+f6+BEOCiGOyK6kg3QscNWG7bTe38vYdDRnH9oqfHhxpdQHJEMXxOeSFdLomGwM1onW4Rej SDCkHOFlOsYAFwMgyrOM/Nx8Dk73ccIDYZ1MRf4ChQIqKRxzNrWSIAIAyMcRq8l2yaKytUCC/Sb rEQ4GhWUaiq/Ox5UHoX2rtBsXiR5Vr9WeR3FxNOfjsd/L6zcVJSQB2WJQ== X-Google-Smtp-Source: AGHT+IFsh3iV6x24r1z6bgjQYA4fIvXoEcEueWsf8uvmzjQHvcik8vtonyJEo3Zs4ajaJbZhPgKwEA== X-Received: by 2002:a2e:b887:0:b0:302:1c90:58d9 with SMTP id 38308e7fff4ca-305f458a829mr6956111fa.16.1736334795263; Wed, 08 Jan 2025 03:13:15 -0800 (PST) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Oleksii Kurochko , Stefano Stabellini , Julien Grall , Bertrand Marquis , Michal Orzel , Volodymyr Babchuk , Andrew Cooper , Anthony PERARD , Jan Beulich , =?utf-8?q?Roger_Pau_Monn=C3=A9?= Subject: [PATCH v1 2/9] asm-generic: move parts of Arm's asm/kernel.h to asm-generic Date: Wed, 8 Jan 2025 12:13:04 +0100 Message-ID: <6404cb5ae077909cbfdf3860d38c701c65547b56.1736334615.git.oleksii.kurochko@gmail.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: References: MIME-Version: 1.0 Move the following parts to asm-generic with the following changes: - struct kernel_info: - Create arch_kernel_info for arch specific kernel information. At the moment, it contains domain_type for Arm. - Rename vpl011 to vuart to have more generic name suitable for other archs. - s/phandle_gic/phandle_intc to have more generic name suitable for other archs. - Make text_offset of zimage structure available for RISCV_64. - Wrap by `#ifdef KERNEL_INFO_SHM_MEM_INIT` definition of KERNEL_SHM_MEM_INIT and wrap by `#ifndef KERNEL_INFO_INIT` definition of KERNEL_INFO_INIT to have ability to override KERNEL_INFO_SHM_MEM_INIT for arch in case it doesn't want to use generic one. - All other parts are left as is from Arm's asm/kernel.h Because of the changes in struct kernel_info the correspondent parts of Arm's code are updated. As part of this patch the following clean up happens: - Drop asm/setup.h from asm/kernel.h as nothing depends from it. Add inclusion of asm/setup.h for a code which uses device_tree_get_reg() to avoid compilation issues for CONFIG_STATIC_MEMORY and CONFIG_STATIC_SHM. Signed-off-by: Oleksii Kurochko --- xen/arch/arm/dom0less-build.c | 28 +++--- xen/arch/arm/domain_build.c | 10 +- xen/arch/arm/include/asm/kernel.h | 115 +---------------------- xen/arch/arm/kernel.c | 10 +- xen/arch/arm/static-memory.c | 1 + xen/arch/arm/static-shmem.c | 1 + xen/include/asm-generic/kernel.h | 146 ++++++++++++++++++++++++++++++ 7 files changed, 175 insertions(+), 136 deletions(-) create mode 100644 xen/include/asm-generic/kernel.h diff --git a/xen/arch/arm/dom0less-build.c b/xen/arch/arm/dom0less-build.c index b27747c05c..c4badb4ade 100644 --- a/xen/arch/arm/dom0less-build.c +++ b/xen/arch/arm/dom0less-build.c @@ -57,11 +57,11 @@ static int __init make_gicv2_domU_node(struct kernel_info *kinfo) if (res) return res; - res = fdt_property_cell(fdt, "linux,phandle", kinfo->phandle_gic); + res = fdt_property_cell(fdt, "linux,phandle", kinfo->phandle_intc); if (res) return res; - res = fdt_property_cell(fdt, "phandle", kinfo->phandle_gic); + res = fdt_property_cell(fdt, "phandle", kinfo->phandle_intc); if (res) return res; @@ -128,11 +128,11 @@ static int __init make_gicv3_domU_node(struct kernel_info *kinfo) if (res) return res; - res = fdt_property_cell(fdt, "linux,phandle", kinfo->phandle_gic); + res = fdt_property_cell(fdt, "linux,phandle", kinfo->phandle_intc); if (res) return res; - res = fdt_property_cell(fdt, "phandle", kinfo->phandle_gic); + res = fdt_property_cell(fdt, "phandle", kinfo->phandle_intc); if (res) return res; @@ -193,7 +193,7 @@ static int __init make_vpl011_uart_node(struct kernel_info *kinfo) return res; res = fdt_property_cell(fdt, "interrupt-parent", - kinfo->phandle_gic); + kinfo->phandle_intc); if ( res ) return res; @@ -479,10 +479,10 @@ static int __init domain_handle_dtb_bootmodule(struct domain *d, */ if ( dt_node_cmp(name, "gic") == 0 ) { - uint32_t phandle_gic = fdt_get_phandle(pfdt, node_next); + uint32_t phandle_intc = fdt_get_phandle(pfdt, node_next); - if ( phandle_gic != 0 ) - kinfo->phandle_gic = phandle_gic; + if ( phandle_intc != 0 ) + kinfo->phandle_intc = phandle_intc; continue; } @@ -525,7 +525,7 @@ static int __init prepare_dtb_domU(struct domain *d, struct kernel_info *kinfo) int addrcells, sizecells; int ret, fdt_size = DOMU_DTB_SIZE; - kinfo->phandle_gic = GUEST_PHANDLE_GIC; + kinfo->phandle_intc = GUEST_PHANDLE_GIC; kinfo->gnttab_start = GUEST_GNTTAB_BASE; kinfo->gnttab_size = GUEST_GNTTAB_SIZE; @@ -587,7 +587,7 @@ static int __init prepare_dtb_domU(struct domain *d, struct kernel_info *kinfo) /* * domain_handle_dtb_bootmodule has to be called before the rest of * the device tree is generated because it depends on the value of - * the field phandle_gic. + * the field phandle_intc. */ if ( kinfo->dtb_bootmodule ) { @@ -604,7 +604,7 @@ static int __init prepare_dtb_domU(struct domain *d, struct kernel_info *kinfo) if ( ret ) goto err; - if ( kinfo->vpl011 ) + if ( kinfo->vuart ) { ret = -EINVAL; #ifdef CONFIG_SBSA_VUART_CONSOLE @@ -705,7 +705,7 @@ int __init construct_domU(struct domain *d, printk("*** LOADING DOMU cpus=%u memory=%#"PRIx64"KB ***\n", d->max_vcpus, mem); - kinfo.vpl011 = dt_property_read_bool(node, "vpl011"); + kinfo.vuart = dt_property_read_bool(node, "vpl011"); rc = dt_property_read_string(node, "xen,enhanced", &dom0less_enhanced); if ( rc == -EILSEQ || @@ -733,7 +733,7 @@ int __init construct_domU(struct domain *d, #ifdef CONFIG_ARM_64 /* type must be set before allocate memory */ - d->arch.type = kinfo.type; + d->arch.type = kinfo.arch.type; #endif if ( !dt_find_property(node, "xen,static-mem", NULL) ) allocate_memory(d, &kinfo); @@ -751,7 +751,7 @@ int __init construct_domU(struct domain *d, * tree node in prepare_dtb_domU, so initialization on related variables * shall be done first. */ - if ( kinfo.vpl011 ) + if ( kinfo.vuart ) { rc = domain_vpl011_init(d, NULL); if ( rc < 0 ) diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c index b072a16249..976b03a5df 100644 --- a/xen/arch/arm/domain_build.c +++ b/xen/arch/arm/domain_build.c @@ -747,7 +747,7 @@ static int __init fdt_property_interrupts(const struct kernel_info *kinfo, return res; res = fdt_property_cell(kinfo->fdt, "interrupt-parent", - kinfo->phandle_gic); + kinfo->phandle_intc); return res; } @@ -2026,7 +2026,7 @@ static int __init prepare_dtb_hwdom(struct domain *d, struct kernel_info *kinfo) ASSERT(dt_host && (dt_host->sibling == NULL)); - kinfo->phandle_gic = dt_interrupt_controller->phandle; + kinfo->phandle_intc = dt_interrupt_controller->phandle; fdt = device_tree_flattened; new_size = fdt_totalsize(fdt) + DOM0_FDT_EXTRA_SIZE; @@ -2194,13 +2194,13 @@ int __init construct_domain(struct domain *d, struct kernel_info *kinfo) #ifdef CONFIG_ARM_64 /* if aarch32 mode is not supported at EL1 do not allow 32-bit domain */ - if ( !(cpu_has_el1_32) && kinfo->type == DOMAIN_32BIT ) + if ( !(cpu_has_el1_32) && kinfo->arch.type == DOMAIN_32BIT ) { printk("Platform does not support 32-bit domain\n"); return -EINVAL; } - if ( is_sve_domain(d) && (kinfo->type == DOMAIN_32BIT) ) + if ( is_sve_domain(d) && (kinfo->arch.type == DOMAIN_32BIT) ) { printk("SVE is not available for 32-bit domain\n"); return -EINVAL; @@ -2307,7 +2307,7 @@ static int __init construct_dom0(struct domain *d) #ifdef CONFIG_ARM_64 /* type must be set before allocate_memory */ - d->arch.type = kinfo.type; + d->arch.type = kinfo.arch.type; #endif find_gnttab_region(d, &kinfo); if ( is_domain_direct_mapped(d) ) diff --git a/xen/arch/arm/include/asm/kernel.h b/xen/arch/arm/include/asm/kernel.h index 7e6e3c82a4..4d74f0bcb2 100644 --- a/xen/arch/arm/include/asm/kernel.h +++ b/xen/arch/arm/include/asm/kernel.h @@ -6,125 +6,16 @@ #ifndef __ARCH_ARM_KERNEL_H__ #define __ARCH_ARM_KERNEL_H__ -#include #include -#include -/* - * List of possible features for dom0less domUs - * - * DOM0LESS_ENHANCED_NO_XS: Notify the OS it is running on top of Xen. All the - * default features (excluding Xenstore) will be - * available. Note that an OS *must* not rely on the - * availability of Xen features if this is not set. - * DOM0LESS_XENSTORE: Xenstore will be enabled for the VM. This feature - * can't be enabled without the - * DOM0LESS_ENHANCED_NO_XS. - * DOM0LESS_ENHANCED: Notify the OS it is running on top of Xen. All the - * default features (including Xenstore) will be - * available. Note that an OS *must* not rely on the - * availability of Xen features if this is not set. - */ -#define DOM0LESS_ENHANCED_NO_XS BIT(0, U) -#define DOM0LESS_XENSTORE BIT(1, U) -#define DOM0LESS_ENHANCED (DOM0LESS_ENHANCED_NO_XS | DOM0LESS_XENSTORE) - -struct kernel_info { +struct arch_kernel_info +{ #ifdef CONFIG_ARM_64 enum domain_type type; #endif - - struct domain *d; - - void *fdt; /* flat device tree */ - paddr_t unassigned_mem; /* RAM not (yet) assigned to a bank */ - struct meminfo mem; -#ifdef CONFIG_STATIC_SHM - struct shared_meminfo shm_mem; -#endif - - /* kernel entry point */ - paddr_t entry; - - /* grant table region */ - paddr_t gnttab_start; - paddr_t gnttab_size; - - /* boot blob load addresses */ - const struct bootmodule *kernel_bootmodule, *initrd_bootmodule, *dtb_bootmodule; - const char* cmdline; - paddr_t dtb_paddr; - paddr_t initrd_paddr; - - /* Enable pl011 emulation */ - bool vpl011; - - /* Enable/Disable PV drivers interfaces */ - uint16_t dom0less_feature; - - /* GIC phandle */ - uint32_t phandle_gic; - - /* loader to use for this kernel */ - void (*load)(struct kernel_info *info); - /* loader specific state */ - union { - struct { - paddr_t kernel_addr; - paddr_t len; -#ifdef CONFIG_ARM_64 - paddr_t text_offset; /* 64-bit Image only */ -#endif - paddr_t start; /* Must be 0 for 64-bit Image */ - } zimage; - }; }; -static inline struct membanks *kernel_info_get_mem(struct kernel_info *kinfo) -{ - return container_of(&kinfo->mem.common, struct membanks, common); -} - -static inline const struct membanks * -kernel_info_get_mem_const(const struct kernel_info *kinfo) -{ - return container_of(&kinfo->mem.common, const struct membanks, common); -} - -#ifdef CONFIG_STATIC_SHM -#define KERNEL_INFO_SHM_MEM_INIT .shm_mem.common.max_banks = NR_SHMEM_BANKS, -#else -#define KERNEL_INFO_SHM_MEM_INIT -#endif - -#define KERNEL_INFO_INIT \ -{ \ - .mem.common.max_banks = NR_MEM_BANKS, \ - KERNEL_INFO_SHM_MEM_INIT \ -} - -/* - * Probe the kernel to detemine its type and select a loader. - * - * Sets in info: - * ->type - * ->load hook, and sets loader specific variables ->zimage - */ -int kernel_probe(struct kernel_info *info, const struct dt_device_node *domain); - -/* - * Loads the kernel into guest RAM. - * - * Expects to be set in info when called: - * ->mem - * ->fdt - * - * Sets in info: - * ->entry - * ->dtb_paddr - * ->initrd_paddr - */ -void kernel_load(struct kernel_info *info); +#include #endif /* #ifdef __ARCH_ARM_KERNEL_H__ */ diff --git a/xen/arch/arm/kernel.c b/xen/arch/arm/kernel.c index 80fad8b336..b75bd6a887 100644 --- a/xen/arch/arm/kernel.c +++ b/xen/arch/arm/kernel.c @@ -101,7 +101,7 @@ static paddr_t __init kernel_zimage_place(struct kernel_info *info) paddr_t load_addr; #ifdef CONFIG_ARM_64 - if ( (info->type == DOMAIN_64BIT) && (info->zimage.start == 0) ) + if ( (info->arch.type == DOMAIN_64BIT) && (info->zimage.start == 0) ) return mem->bank[0].start + info->zimage.text_offset; #endif @@ -371,10 +371,10 @@ static int __init kernel_uimage_probe(struct kernel_info *info, switch ( uimage.arch ) { case IH_ARCH_ARM: - info->type = DOMAIN_32BIT; + info->arch.type = DOMAIN_32BIT; break; case IH_ARCH_ARM64: - info->type = DOMAIN_64BIT; + info->arch.type = DOMAIN_64BIT; break; default: printk(XENLOG_ERR "Unsupported uImage arch type %d\n", uimage.arch); @@ -444,7 +444,7 @@ static int __init kernel_zimage64_probe(struct kernel_info *info, info->load = kernel_zimage_load; - info->type = DOMAIN_64BIT; + info->arch.type = DOMAIN_64BIT; return 0; } @@ -496,7 +496,7 @@ static int __init kernel_zimage32_probe(struct kernel_info *info, info->load = kernel_zimage_load; #ifdef CONFIG_ARM_64 - info->type = DOMAIN_32BIT; + info->arch.type = DOMAIN_32BIT; #endif return 0; diff --git a/xen/arch/arm/static-memory.c b/xen/arch/arm/static-memory.c index d4585c5a06..e0f76afcd8 100644 --- a/xen/arch/arm/static-memory.c +++ b/xen/arch/arm/static-memory.c @@ -2,6 +2,7 @@ #include +#include #include static bool __init append_static_memory_to_bank(struct domain *d, diff --git a/xen/arch/arm/static-shmem.c b/xen/arch/arm/static-shmem.c index 66088a4267..aff05d24d1 100644 --- a/xen/arch/arm/static-shmem.c +++ b/xen/arch/arm/static-shmem.c @@ -6,6 +6,7 @@ #include #include +#include #include #include diff --git a/xen/include/asm-generic/kernel.h b/xen/include/asm-generic/kernel.h new file mode 100644 index 0000000000..b2bd04a185 --- /dev/null +++ b/xen/include/asm-generic/kernel.h @@ -0,0 +1,146 @@ +/* + * Kernel image loading. + * + * Copyright (C) 2011 Citrix Systems, Inc. + */ +#ifndef __ASM_GENERIC_KERNEL_H__ +#define __ASM_GENERIC_KERNEL_H__ + +#include +#include +#include +#include + +/* + * List of possible features for dom0less domUs + * + * DOM0LESS_ENHANCED_NO_XS: Notify the OS it is running on top of Xen. All the + * default features (excluding Xenstore) will be + * available. Note that an OS *must* not rely on the + * availability of Xen features if this is not set. + * DOM0LESS_XENSTORE: Xenstore will be enabled for the VM. This feature + * can't be enabled without the + * DOM0LESS_ENHANCED_NO_XS. + * DOM0LESS_ENHANCED: Notify the OS it is running on top of Xen. All the + * default features (including Xenstore) will be + * available. Note that an OS *must* not rely on the + * availability of Xen features if this is not set. + */ +#define DOM0LESS_ENHANCED_NO_XS BIT(0, U) +#define DOM0LESS_XENSTORE BIT(1, U) +#define DOM0LESS_ENHANCED (DOM0LESS_ENHANCED_NO_XS | DOM0LESS_XENSTORE) + +struct kernel_info { + struct domain *d; + + void *fdt; /* flat device tree */ + paddr_t unassigned_mem; /* RAM not (yet) assigned to a bank */ + struct meminfo mem; +#ifdef CONFIG_STATIC_SHM + struct shared_meminfo shm_mem; +#endif + + /* kernel entry point */ + paddr_t entry; + + /* grant table region */ + paddr_t gnttab_start; + paddr_t gnttab_size; + + /* boot blob load addresses */ + const struct bootmodule *kernel_bootmodule, *initrd_bootmodule, *dtb_bootmodule; + const char* cmdline; + paddr_t dtb_paddr; + paddr_t initrd_paddr; + + /* Enable uart emulation */ + bool vuart; + + /* Enable/Disable PV drivers interfaces */ + uint16_t dom0less_feature; + + /* Interrupt controller phandle */ + uint32_t phandle_intc; + + /* loader to use for this kernel */ + void (*load)(struct kernel_info *info); + + /* loader specific state */ + union { + struct { + paddr_t kernel_addr; + paddr_t len; +#if defined(CONFIG_ARM_64) || defined(CONFIG_RISCV_64) + paddr_t text_offset; /* 64-bit Image only */ +#endif + paddr_t start; /* Must be 0 for 64-bit Image */ + } zimage; + }; + + struct arch_kernel_info arch; +}; + +static inline struct membanks *kernel_info_get_mem(struct kernel_info *kinfo) +{ + return container_of(&kinfo->mem.common, struct membanks, common); +} + +static inline const struct membanks * +kernel_info_get_mem_const(const struct kernel_info *kinfo) +{ + return container_of(&kinfo->mem.common, const struct membanks, common); +} + +#ifndef KERNEL_INFO_SHM_MEM_INIT + +#ifdef CONFIG_STATIC_SHM +#define KERNEL_INFO_SHM_MEM_INIT .shm_mem.common.max_banks = NR_SHMEM_BANKS, +#else +#define KERNEL_INFO_SHM_MEM_INIT +#endif + +#endif /* KERNEL_INFO_SHM_MEM_INIT */ + +#ifndef KERNEL_INFO_INIT + +#define KERNEL_INFO_INIT \ +{ \ + .mem.common.max_banks = NR_MEM_BANKS, \ + KERNEL_INFO_SHM_MEM_INIT \ +} + +#endif /* KERNEL_INFO_INIT */ + +/* + * Probe the kernel to detemine its type and select a loader. + * + * Sets in info: + * ->type + * ->load hook, and sets loader specific variables ->zimage + */ +int kernel_probe(struct kernel_info *info, const struct dt_device_node *domain); + +/* + * Loads the kernel into guest RAM. + * + * Expects to be set in info when called: + * ->mem + * ->fdt + * + * Sets in info: + * ->entry + * ->dtb_paddr + * ->initrd_paddr + */ +void kernel_load(struct kernel_info *info); + +#endif /*__ASM_GENERIC_KERNEL_H__ */ + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ From patchwork Wed Jan 8 11:13:05 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oleksii Kurochko X-Patchwork-Id: 13930556 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 5628FE7719E for ; Wed, 8 Jan 2025 11:13:37 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.867135.1278586 (Exim 4.92) (envelope-from ) id 1tVU00-0001sn-F5; Wed, 08 Jan 2025 11:13:20 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 867135.1278586; Wed, 08 Jan 2025 11:13:20 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1tVU00-0001sg-CH; Wed, 08 Jan 2025 11:13:20 +0000 Received: by outflank-mailman (input) for mailman id 867135; Wed, 08 Jan 2025 11:13:19 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1tVTzy-0001BZ-Se for xen-devel@lists.xenproject.org; Wed, 08 Jan 2025 11:13:18 +0000 Received: from mail-lj1-x233.google.com (mail-lj1-x233.google.com [2a00:1450:4864:20::233]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id 8f9e9649-cdb1-11ef-a0df-8be0dac302b0; Wed, 08 Jan 2025 12:13:17 +0100 (CET) Received: by mail-lj1-x233.google.com with SMTP id 38308e7fff4ca-30219437e63so7116531fa.1 for ; Wed, 08 Jan 2025 03:13:17 -0800 (PST) Received: from fedora.. ([94.75.70.14]) by smtp.gmail.com with ESMTPSA id 38308e7fff4ca-3045ad99d11sm67292171fa.33.2025.01.08.03.13.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 08 Jan 2025 03:13:15 -0800 (PST) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 8f9e9649-cdb1-11ef-a0df-8be0dac302b0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1736334796; x=1736939596; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=n3fSG769VnOrM2edhG3O3s3zVRPKLWUvOf5I+6qkAcQ=; b=Z9BbAfDEB7ilbeMgddFjyfE3cB9w5+GgBow/2dgm/PinvNd+C8u35/YtquIcpYtekh wxHuO5X0huuF57V7HGKi1l/2CvS3kmBHjm2gTgcqM4DHXzeYdE4Qtl+N3XCPAC2jp69t +ar8Ee6kPs76wzMzhFrxLJdnCG4CUBNrrHCgvX8NdfqKYx99GG0t6WUgAxMT7irej1Mh 0Ybk0mzO/jt7PTMaRJTh3rh0t7AEwkZgZpf753e/N+rfRJ7JKHsZhA+UnuAvnKf0LU2C XfWRIi9IcnjsyWc3yougW3Dk0gqIrcB0PK9zBrFbfevOmEC128Saq4XbvCm1ZfPnSxId KGxQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1736334796; x=1736939596; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=n3fSG769VnOrM2edhG3O3s3zVRPKLWUvOf5I+6qkAcQ=; b=RUJVNOJyDILEhccO6t0Yj55DPmAJ9vCPyN2WPz3okdYNpyeMVL7kKOH8gkyj3YLuJu OT+S1ORlqnI/PE8zFcxgs2alRDdjh7U0TYItQRzJjoGVMWaaWq1vYpAaF1d8ITOt3qe/ GElfq4BNk7KBXoGMcstaEYsVehdtP11XOPpbAH1bQ3XXdBnJpqHtHvGZgEXbvjPw+Oju pUq64ST4KbtbloyFO/QXjEhx/zg1Zo2ZUSLigUMhLmItvenTD0yLw6X9niM4sfGPj9dK XGpU451FBMhIXEYOTEL/K1WA9hQgiWo5nFM5KjGXj+q57WG6WGuN6yDB1OV3OfZpE5zB 2o/Q== X-Gm-Message-State: AOJu0Yz7V3LQ8xqAr3fJGJednrOrNLIBYJFGvWcFLTHGUstfKjdFzUbY I30tZY5t8nI8FICnVQkBqr4FohIWaXL7j8pUhVbXonEcapNNxVnnZfT2WtTn X-Gm-Gg: ASbGncthSXSzygqlqaZXUXV8sYdle3sfMDAUqE50in5S+RCrf1CfD6cFnZXnF5ti+Kw +pnzbSJR7C2hJ5QVo3LcnOImv78+rsg1dejKDYiBw2aUe3jpt93Bh8y9IdHNSUCY9ZtUspUcVs+ bNp60kn0oOLHLrY0BcPetFmfmxamGCrsIYZqzE1WgUzBgBSr2z0q7xbb9mOdveNCZbpR63eBnLb 0tSMQOa1WcYtStcNUNXozjZG4EHnjLkvRHxJxi5Wb0at3Ey8C4GE40yEQ== X-Google-Smtp-Source: AGHT+IGZlEFSV35bKo9xoDZxbudY5hACznPdX4ioGucTYpB5Vt+XO/BnHvqtlSObDVsALXrcUlVShw== X-Received: by 2002:a2e:bc0c:0:b0:302:23bd:354b with SMTP id 38308e7fff4ca-305eb1ac962mr20794211fa.1.1736334796007; Wed, 08 Jan 2025 03:13:16 -0800 (PST) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Oleksii Kurochko , Stefano Stabellini , Julien Grall , Bertrand Marquis , Michal Orzel , Volodymyr Babchuk Subject: [PATCH v1 3/9] arm/static-shmem.h: drop inclusion of asm/setup.h Date: Wed, 8 Jan 2025 12:13:05 +0100 Message-ID: <2dd4477dd3224d00f43bbabc07f978c4e72f5a0f.1736334615.git.oleksii.kurochko@gmail.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: References: MIME-Version: 1.0 Nothing is dependent from asm/setup.h in asm/static-shmem.h so inclusion of asm/setup.h is droped. After this drop the following compilation error related to impicit declaration of the following functions device_tree_get_reg and map_device_irqs_to_domain, device_tree_get_u32 occur during compilation of dom0less-build.c ( as they are declared in asm/setup.h ). Add inclusion of in dt-overlay.c as it is using handle_device() declared in . Signed-off-by: Oleksii Kurochko --- xen/arch/arm/dom0less-build.c | 1 + xen/arch/arm/include/asm/static-shmem.h | 1 - xen/common/device-tree/dt-overlay.c | 2 ++ 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/xen/arch/arm/dom0less-build.c b/xen/arch/arm/dom0less-build.c index c4badb4ade..259285ddda 100644 --- a/xen/arch/arm/dom0less-build.c +++ b/xen/arch/arm/dom0less-build.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include diff --git a/xen/arch/arm/include/asm/static-shmem.h b/xen/arch/arm/include/asm/static-shmem.h index fd0867c4f2..828c8e5480 100644 --- a/xen/arch/arm/include/asm/static-shmem.h +++ b/xen/arch/arm/include/asm/static-shmem.h @@ -5,7 +5,6 @@ #include #include -#include #ifdef CONFIG_STATIC_SHM diff --git a/xen/common/device-tree/dt-overlay.c b/xen/common/device-tree/dt-overlay.c index 97fb99eaaa..28bb9cf0cf 100644 --- a/xen/common/device-tree/dt-overlay.c +++ b/xen/common/device-tree/dt-overlay.c @@ -13,6 +13,8 @@ #include #include +#include + #define DT_OVERLAY_MAX_SIZE KB(500) static LIST_HEAD(overlay_tracker); From patchwork Wed Jan 8 11:13:06 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oleksii Kurochko X-Patchwork-Id: 13930554 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id C2901E77188 for ; Wed, 8 Jan 2025 11:13:35 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.867137.1278606 (Exim 4.92) (envelope-from ) id 1tVU02-0002Ok-W2; Wed, 08 Jan 2025 11:13:22 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 867137.1278606; Wed, 08 Jan 2025 11:13:22 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1tVU02-0002OZ-SW; Wed, 08 Jan 2025 11:13:22 +0000 Received: by outflank-mailman (input) for mailman id 867137; Wed, 08 Jan 2025 11:13:21 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1tVU01-0001rx-Jg for xen-devel@lists.xenproject.org; Wed, 08 Jan 2025 11:13:21 +0000 Received: from mail-lj1-x229.google.com (mail-lj1-x229.google.com [2a00:1450:4864:20::229]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id 903a0692-cdb1-11ef-99a4-01e77a169b0f; Wed, 08 Jan 2025 12:13:18 +0100 (CET) Received: by mail-lj1-x229.google.com with SMTP id 38308e7fff4ca-30036310158so151006751fa.0 for ; Wed, 08 Jan 2025 03:13:18 -0800 (PST) Received: from fedora.. ([94.75.70.14]) by smtp.gmail.com with ESMTPSA id 38308e7fff4ca-3045ad99d11sm67292171fa.33.2025.01.08.03.13.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 08 Jan 2025 03:13:16 -0800 (PST) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 903a0692-cdb1-11ef-99a4-01e77a169b0f DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1736334798; x=1736939598; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=5OTB8W0BPYwoUOycX2jvVwt68tOgnvevPd13hEZlyfg=; b=OlZmmvttJ3hJkrO4bh2zS8lrbLl8K7i42ezTnZASqKx/P14RPtikJ+L9OhdwiuY4Xj EHp6ZqfKTo/Uzgpkr9jrQqH7KNG61DG8rDoLxy7sbF8slaNekypn/kD82H9Ce6Wfy0O5 v8WNBOMqxCDJfosZiHisVVihdCeeEqAmF6+Ww0PnmY2fhiI4cfho8/DhJLK32GGhRqh8 NZfb3HKp5zF4ryijTwxrkscT+Rr6jPcKPmQGlW6h3mPwqrcaL7Xf+16NQ1+7fpFxpUW6 smXVINo8i4fmce5/6Hl8ygkr41qYca8pt4snOnrfKNG8PStRAIo12NDcWKr8zOESKQmf IF2g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1736334798; x=1736939598; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=5OTB8W0BPYwoUOycX2jvVwt68tOgnvevPd13hEZlyfg=; b=GRUDxxIUPNDyeluPPK4ZwHXTTv+pun4fgKX5h7N2HLyR7DJGdj2sTiU81ftgSAiyMu iyvF98RF80T7okLeFLjmoCyfRzeKCO1i6u/rB6WigUxaANyzZkTjxc7W2SjHoM4lacY+ h92yu6sY3njIy4Tg7RJcBoelUusV/nkJ3kPsEGISo1M2jM1ojslr7lSAiSJSljCK+bcC iBGGEx2XRHwcCHTy3KEE0Eu7y+1tt2EAz79EZSXTmuhMUg2joeEbDy/uTIdM+Ivh9hAj Z5cC7U3QWmto4Gr9QsIDZSSZhgMnrC96fvUJmAvDnyknOnWHTnIxybS8jMF6t/9GKo3D hzXg== X-Gm-Message-State: AOJu0Yy2Ik7KvMniiVXz6YDWr4hDFJ5DSMoPiZ/X268HrIpxkZbu9X10 rmwUm2ukaNr8LNSaxT/St63puv+dcNFqQ6oWJ11eDPCzw3yKqgT7p9h2ciOD X-Gm-Gg: ASbGncusgk4euYE7wGqfrmmBlxHCRoQO1qGIL1iZF1D1tLfcAe2EYwGHQw59HxALxRa GA+BVaJV+/QvskE1TYhVM6/g9Oy7u4r6jJ+Zp3lpJ6egpW9+x1sPWxl8cJreIr2bkneHZl2U+2L BTRSES7QAC2dsM2FG7c846zr0ZwWiRiKzrzWfYGxs41cVGUvxL6Ng6TwHOAD7oVprf3F6LdDRpA zaE5/Wr++XktFFs3IkRxMa1CLE3cpdeo4mX0uSmtjH0ZW3Eq0pW5rIPig== X-Google-Smtp-Source: AGHT+IEaTqsEGhHsauu6PyS2Wl2XkzryajFU0mmd/80nUCa93OHWPftV2OkoGbCkHJ4usuEnaXHXog== X-Received: by 2002:a05:651c:b0f:b0:300:3a15:8f26 with SMTP id 38308e7fff4ca-305f445a592mr6342001fa.0.1736334797579; Wed, 08 Jan 2025 03:13:17 -0800 (PST) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Oleksii Kurochko , Stefano Stabellini , Julien Grall , Bertrand Marquis , Michal Orzel , Volodymyr Babchuk , Andrew Cooper , Anthony PERARD , Jan Beulich , =?utf-8?q?Roger_Pau_Monn=C3=A9?= Subject: [PATCH v1 4/9] asm-generic: move Arm's static-memory.h to asm-generic Date: Wed, 8 Jan 2025 12:13:06 +0100 Message-ID: <3f1f3786ee48b01f1a5c7c7573456da72aa1e1d2.1736334615.git.oleksii.kurochko@gmail.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: References: MIME-Version: 1.0 Except moving Arm's static-memory.h to asm-generic #ifdef header guard is updated: s/__ASM_STATIC_MEMORY_H_/__ASM_GENERIC_STATIC_MEMORY_H__. Update arm/include/asm/Makefile to use asm-generic version of static-memory.h for Arm. Signed-off-by: Oleksii Kurochko --- xen/arch/arm/include/asm/Makefile | 1 + xen/arch/arm/include/asm/static-memory.h | 58 ------------------------ xen/include/asm-generic/static-memory.h | 58 ++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 58 deletions(-) delete mode 100644 xen/arch/arm/include/asm/static-memory.h create mode 100644 xen/include/asm-generic/static-memory.h diff --git a/xen/arch/arm/include/asm/Makefile b/xen/arch/arm/include/asm/Makefile index 831c914cce..ac8208a81f 100644 --- a/xen/arch/arm/include/asm/Makefile +++ b/xen/arch/arm/include/asm/Makefile @@ -8,4 +8,5 @@ generic-y += paging.h generic-y += percpu.h generic-y += random.h generic-y += softirq.h +generic-y += static-memory.h generic-y += vm_event.h diff --git a/xen/arch/arm/include/asm/static-memory.h b/xen/arch/arm/include/asm/static-memory.h deleted file mode 100644 index 804166e541..0000000000 --- a/xen/arch/arm/include/asm/static-memory.h +++ /dev/null @@ -1,58 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ - -#ifndef __ASM_STATIC_MEMORY_H_ -#define __ASM_STATIC_MEMORY_H_ - -#include -#include - -#ifdef CONFIG_STATIC_MEMORY - -static inline void init_staticmem_bank(const struct membank *bank) -{ - mfn_t bank_start = _mfn(PFN_UP(bank->start)); - unsigned long bank_pages = PFN_DOWN(bank->size); - mfn_t bank_end = mfn_add(bank_start, bank_pages); - - if ( mfn_x(bank_end) <= mfn_x(bank_start) ) - return; - - unprepare_staticmem_pages(mfn_to_page(bank_start), bank_pages, false); -} - -void allocate_static_memory(struct domain *d, struct kernel_info *kinfo, - const struct dt_device_node *node); -void assign_static_memory_11(struct domain *d, struct kernel_info *kinfo, - const struct dt_device_node *node); -void init_staticmem_pages(void); - -#else /* !CONFIG_STATIC_MEMORY */ - -static inline void allocate_static_memory(struct domain *d, - struct kernel_info *kinfo, - const struct dt_device_node *node) -{ - ASSERT_UNREACHABLE(); -} - -static inline void assign_static_memory_11(struct domain *d, - struct kernel_info *kinfo, - const struct dt_device_node *node) -{ - ASSERT_UNREACHABLE(); -} - -static inline void init_staticmem_pages(void) {}; - -#endif /* CONFIG_STATIC_MEMORY */ - -#endif /* __ASM_STATIC_MEMORY_H_ */ - -/* - * Local variables: - * mode: C - * c-file-style: "BSD" - * c-basic-offset: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/xen/include/asm-generic/static-memory.h b/xen/include/asm-generic/static-memory.h new file mode 100644 index 0000000000..43b8740d46 --- /dev/null +++ b/xen/include/asm-generic/static-memory.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __ASM_GENERIC_STATIC_MEMORY_H__ +#define __ASM_GENERIC_STATIC_MEMORY_H__ + +#include +#include + +#ifdef CONFIG_STATIC_MEMORY + +static inline void init_staticmem_bank(const struct membank *bank) +{ + mfn_t bank_start = _mfn(PFN_UP(bank->start)); + unsigned long bank_pages = PFN_DOWN(bank->size); + mfn_t bank_end = mfn_add(bank_start, bank_pages); + + if ( mfn_x(bank_end) <= mfn_x(bank_start) ) + return; + + unprepare_staticmem_pages(mfn_to_page(bank_start), bank_pages, false); +} + +void allocate_static_memory(struct domain *d, struct kernel_info *kinfo, + const struct dt_device_node *node); +void assign_static_memory_11(struct domain *d, struct kernel_info *kinfo, + const struct dt_device_node *node); +void init_staticmem_pages(void); + +#else /* !CONFIG_STATIC_MEMORY */ + +static inline void allocate_static_memory(struct domain *d, + struct kernel_info *kinfo, + const struct dt_device_node *node) +{ + ASSERT_UNREACHABLE(); +} + +static inline void assign_static_memory_11(struct domain *d, + struct kernel_info *kinfo, + const struct dt_device_node *node) +{ + ASSERT_UNREACHABLE(); +} + +static inline void init_staticmem_pages(void) {}; + +#endif /* CONFIG_STATIC_MEMORY */ + +#endif /* __ASM_GENERIC_STATIC_MEMORY_H__ */ + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ From patchwork Wed Jan 8 11:13:07 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oleksii Kurochko X-Patchwork-Id: 13930557 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id B47D1E7719B for ; Wed, 8 Jan 2025 11:13:36 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.867138.1278612 (Exim 4.92) (envelope-from ) id 1tVU03-0002Se-Fy; Wed, 08 Jan 2025 11:13:23 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 867138.1278612; Wed, 08 Jan 2025 11:13:23 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1tVU03-0002RA-5c; Wed, 08 Jan 2025 11:13:23 +0000 Received: by outflank-mailman (input) for mailman id 867138; Wed, 08 Jan 2025 11:13:21 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1tVU01-0001rx-Qb for xen-devel@lists.xenproject.org; Wed, 08 Jan 2025 11:13:21 +0000 Received: from mail-lj1-x22c.google.com (mail-lj1-x22c.google.com [2a00:1450:4864:20::22c]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id 90e76a96-cdb1-11ef-99a4-01e77a169b0f; Wed, 08 Jan 2025 12:13:19 +0100 (CET) Received: by mail-lj1-x22c.google.com with SMTP id 38308e7fff4ca-30034ad2ca3so151217771fa.1 for ; Wed, 08 Jan 2025 03:13:19 -0800 (PST) Received: from fedora.. ([94.75.70.14]) by smtp.gmail.com with ESMTPSA id 38308e7fff4ca-3045ad99d11sm67292171fa.33.2025.01.08.03.13.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 08 Jan 2025 03:13:18 -0800 (PST) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 90e76a96-cdb1-11ef-99a4-01e77a169b0f DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1736334799; x=1736939599; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=u2DRwW9ezeHyV+LdRXJNVZEHINyASGcXSyx28i5zUEk=; b=TS5eFIaZWc2uEA8au516hwoLBqp/cAbVptNY/yVs/xQrYI/K1Kzs0doZWyVqYEv8B1 XP1W0t6R1KhPh/5PrsC6xFuLe4LeV6GcKH3adhTlI0aPxyrbp89II8jcniUAenY/5lTQ mLzTnfANXSY6VHPY+4mlV6mAzRVrchgpcCZhb0ruWX54ilWZmRwf5DMwo1nDQddbH9NM S5QrU/RwuJp2VplDm4QgXGcyJ2Gz1W38YF0T8q8gbExtXTnN1yKpYbfrR0CyQdfwhzmb /dyF49jqPOl2TCTTAbaOznZDxwQJBhcNT4FEiQuGAWQyC3tZQLPLL+hqVRvTqWFbj40j hUPA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1736334799; x=1736939599; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=u2DRwW9ezeHyV+LdRXJNVZEHINyASGcXSyx28i5zUEk=; b=GY9oItByxVOdGbIEM06Qz3G+VE1zzDB/Swpbk5F0be5lah/CXkyeLFYLGXeTZcAtBh gVqgxhn1OhLSYluL3WHR4yJYy7s5SvXcbxKJtlSsiRg85q9oBiJXOItjNALU7V1b4aq6 pFWSe2JEdWTPVyc9GQ3bxacogD6pwhmC1dTwGmxBZD19TNNEBDg1k+/245tdsr4Ha++S 3nBcnvQGteOGEoB+ddjh0S9dKd1TE7HCtSiArZOEJMh2DmI5rDasip0GbZkIF4w4/aug 2YIgcE5eJXcJw0F38y/AFTxIxOnc9lpLqI7yRfKmyL/X5DclIWHgnhNqUXPR+IFH/gPS oh1g== X-Gm-Message-State: AOJu0YyyljeKDjuISuJpPKx6+/y2uxXhJ51MI4cnNtEIX1C6YT1So17D 5q3/0QUnRbzA3k3Z6smLXuQmHlWzRV/RP3ZoyYdqbRd36G2SQhg76f8EJAWq X-Gm-Gg: ASbGncsCUMCO6/1QHsrBQwh8ITPPBz+EwoA+IU56HSydVB//QNWzT0085x5RJmMiXBK id2N69RoVDF6u06PauZ09odFP2sfjexkv6THtvrDxhh70xIiInpI9F65JFPsXJ3O5/sJQp1HDw0 j7z4E0qOvbxsTr0r/7Gq/q41OvJqzBVUPoHMEJ3HAt/HXc6+k4YSa/DXfvEvFf9jVhAfn8yhkuC a9voJ2RVaatpqdPIUOh32QF75IHzRNrB1+u+J7FbcihhU8xcKMSuyTcrA== X-Google-Smtp-Source: AGHT+IG+qDjYgt2Gr62pg6Xnv/ZqvLYxmQ5L3XyRVscSUI+HT8/n6r626LNrsrSWfozbDr/qW9BejA== X-Received: by 2002:a2e:bc28:0:b0:302:4171:51f0 with SMTP id 38308e7fff4ca-305f445cc8dmr5983551fa.0.1736334798706; Wed, 08 Jan 2025 03:13:18 -0800 (PST) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Oleksii Kurochko , Stefano Stabellini , Julien Grall , Bertrand Marquis , Michal Orzel , Volodymyr Babchuk , Andrew Cooper , Anthony PERARD , Jan Beulich , =?utf-8?q?Roger_Pau_Monn=C3=A9?= Subject: [PATCH v1 5/9] asm-generic: move Arm's static-shmem.h to asm-generic Date: Wed, 8 Jan 2025 12:13:07 +0100 Message-ID: <0203b98aa6a42aa69e22e7c973320add3ff4bb5d.1736334615.git.oleksii.kurochko@gmail.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: References: MIME-Version: 1.0 Except moving Arm's static-shmem.h to asm-generic #ifdef header guard is updated: s/__ASM_SHMEM_MEMORY_H_/__ASM_GENERIC_SHMEM_MEMORY_H__. Update arm/include/asm/Makefile to use asm-generic version of static-shmem.h for Arm. Signed-off-by: Oleksii Kurochko --- xen/arch/arm/include/asm/Makefile | 1 + xen/arch/arm/include/asm/static-shmem.h | 117 ------------------------ xen/include/asm-generic/static-shmem.h | 117 ++++++++++++++++++++++++ 3 files changed, 118 insertions(+), 117 deletions(-) delete mode 100644 xen/arch/arm/include/asm/static-shmem.h create mode 100644 xen/include/asm-generic/static-shmem.h diff --git a/xen/arch/arm/include/asm/Makefile b/xen/arch/arm/include/asm/Makefile index ac8208a81f..9cec55606e 100644 --- a/xen/arch/arm/include/asm/Makefile +++ b/xen/arch/arm/include/asm/Makefile @@ -9,4 +9,5 @@ generic-y += percpu.h generic-y += random.h generic-y += softirq.h generic-y += static-memory.h +generic-y += static-shmem.h generic-y += vm_event.h diff --git a/xen/arch/arm/include/asm/static-shmem.h b/xen/arch/arm/include/asm/static-shmem.h deleted file mode 100644 index 828c8e5480..0000000000 --- a/xen/arch/arm/include/asm/static-shmem.h +++ /dev/null @@ -1,117 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ - -#ifndef __ASM_STATIC_SHMEM_H_ -#define __ASM_STATIC_SHMEM_H_ - -#include -#include - -#ifdef CONFIG_STATIC_SHM - -/* Worst case /memory node reg element: (addrcells + sizecells) */ -#define DT_MEM_NODE_REG_RANGE_SIZE ((NR_MEM_BANKS + NR_SHMEM_BANKS) * 4) - -int make_resv_memory_node(const struct kernel_info *kinfo, int addrcells, - int sizecells); - -int process_shm(struct domain *d, struct kernel_info *kinfo, - const struct dt_device_node *node); - -static inline int process_shm_chosen(struct domain *d, - struct kernel_info *kinfo) -{ - const struct dt_device_node *node = dt_find_node_by_path("/chosen"); - - return process_shm(d, kinfo, node); -} - -int process_shm_node(const void *fdt, int node, uint32_t address_cells, - uint32_t size_cells); - -void early_print_info_shmem(void); - -void init_sharedmem_pages(void); - -int remove_shm_from_rangeset(const struct kernel_info *kinfo, - struct rangeset *rangeset); - -int remove_shm_holes_for_domU(const struct kernel_info *kinfo, - struct membanks *ext_regions); - -int make_shm_resv_memory_node(const struct kernel_info *kinfo, int addrcells, - int sizecells); - -void shm_mem_node_fill_reg_range(const struct kernel_info *kinfo, __be32 *reg, - int *nr_cells, int addrcells, int sizecells); - -static inline struct membanks * -kernel_info_get_shm_mem(struct kernel_info *kinfo) -{ - return container_of(&kinfo->shm_mem.common, struct membanks, common); -} - -static inline const struct membanks * -kernel_info_get_shm_mem_const(const struct kernel_info *kinfo) -{ - return container_of(&kinfo->shm_mem.common, const struct membanks, common); -} - -#else /* !CONFIG_STATIC_SHM */ - -/* Worst case /memory node reg element: (addrcells + sizecells) */ -#define DT_MEM_NODE_REG_RANGE_SIZE (NR_MEM_BANKS * 4) - -static inline int make_resv_memory_node(const struct kernel_info *kinfo, - int addrcells, int sizecells) -{ - return 0; -} - -static inline int process_shm(struct domain *d, struct kernel_info *kinfo, - const struct dt_device_node *node) -{ - return 0; -} - -static inline int process_shm_chosen(struct domain *d, - struct kernel_info *kinfo) -{ - return 0; -} - -static inline void init_sharedmem_pages(void) {}; - -static inline int remove_shm_from_rangeset(const struct kernel_info *kinfo, - struct rangeset *rangeset) -{ - return 0; -} - -static inline int remove_shm_holes_for_domU(const struct kernel_info *kinfo, - struct membanks *ext_regions) -{ - return 0; -} - -static inline int make_shm_resv_memory_node(const struct kernel_info *kinfo, - int addrcells, int sizecells) -{ - return 0; -} - -static inline void shm_mem_node_fill_reg_range(const struct kernel_info *kinfo, - __be32 *reg, int *nr_cells, - int addrcells, int sizecells) {}; - -#endif /* CONFIG_STATIC_SHM */ - -#endif /* __ASM_STATIC_SHMEM_H_ */ - -/* - * Local variables: - * mode: C - * c-file-style: "BSD" - * c-basic-offset: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/xen/include/asm-generic/static-shmem.h b/xen/include/asm-generic/static-shmem.h new file mode 100644 index 0000000000..7c83cb6195 --- /dev/null +++ b/xen/include/asm-generic/static-shmem.h @@ -0,0 +1,117 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __ASM_GENERIC_STATIC_SHMEM_H__ +#define __ASM_GENERIC_STATIC_SHMEM_H__ + +#include +#include + +#ifdef CONFIG_STATIC_SHM + +/* Worst case /memory node reg element: (addrcells + sizecells) */ +#define DT_MEM_NODE_REG_RANGE_SIZE ((NR_MEM_BANKS + NR_SHMEM_BANKS) * 4) + +int make_resv_memory_node(const struct kernel_info *kinfo, int addrcells, + int sizecells); + +int process_shm(struct domain *d, struct kernel_info *kinfo, + const struct dt_device_node *node); + +static inline int process_shm_chosen(struct domain *d, + struct kernel_info *kinfo) +{ + const struct dt_device_node *node = dt_find_node_by_path("/chosen"); + + return process_shm(d, kinfo, node); +} + +int process_shm_node(const void *fdt, int node, uint32_t address_cells, + uint32_t size_cells); + +void early_print_info_shmem(void); + +void init_sharedmem_pages(void); + +int remove_shm_from_rangeset(const struct kernel_info *kinfo, + struct rangeset *rangeset); + +int remove_shm_holes_for_domU(const struct kernel_info *kinfo, + struct membanks *ext_regions); + +int make_shm_resv_memory_node(const struct kernel_info *kinfo, int addrcells, + int sizecells); + +void shm_mem_node_fill_reg_range(const struct kernel_info *kinfo, __be32 *reg, + int *nr_cells, int addrcells, int sizecells); + +static inline struct membanks * +kernel_info_get_shm_mem(struct kernel_info *kinfo) +{ + return container_of(&kinfo->shm_mem.common, struct membanks, common); +} + +static inline const struct membanks * +kernel_info_get_shm_mem_const(const struct kernel_info *kinfo) +{ + return container_of(&kinfo->shm_mem.common, const struct membanks, common); +} + +#else /* !CONFIG_STATIC_SHM */ + +/* Worst case /memory node reg element: (addrcells + sizecells) */ +#define DT_MEM_NODE_REG_RANGE_SIZE (NR_MEM_BANKS * 4) + +static inline int make_resv_memory_node(const struct kernel_info *kinfo, + int addrcells, int sizecells) +{ + return 0; +} + +static inline int process_shm(struct domain *d, struct kernel_info *kinfo, + const struct dt_device_node *node) +{ + return 0; +} + +static inline int process_shm_chosen(struct domain *d, + struct kernel_info *kinfo) +{ + return 0; +} + +static inline void init_sharedmem_pages(void) {}; + +static inline int remove_shm_from_rangeset(const struct kernel_info *kinfo, + struct rangeset *rangeset) +{ + return 0; +} + +static inline int remove_shm_holes_for_domU(const struct kernel_info *kinfo, + struct membanks *ext_regions) +{ + return 0; +} + +static inline int make_shm_resv_memory_node(const struct kernel_info *kinfo, + int addrcells, int sizecells) +{ + return 0; +} + +static inline void shm_mem_node_fill_reg_range(const struct kernel_info *kinfo, + __be32 *reg, int *nr_cells, + int addrcells, int sizecells) {}; + +#endif /* CONFIG_STATIC_SHM */ + +#endif /* __ASM_GENERIC_STATIC_SHMEM_H__ */ + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ From patchwork Wed Jan 8 11:13:08 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oleksii Kurochko X-Patchwork-Id: 13930555 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 5B239E7719A for ; Wed, 8 Jan 2025 11:13:36 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.867136.1278596 (Exim 4.92) (envelope-from ) id 1tVU01-00028Q-OB; Wed, 08 Jan 2025 11:13:21 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 867136.1278596; Wed, 08 Jan 2025 11:13:21 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1tVU01-00028F-KP; Wed, 08 Jan 2025 11:13:21 +0000 Received: by outflank-mailman (input) for mailman id 867136; Wed, 08 Jan 2025 11:13:21 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1tVU01-0001BZ-5j for xen-devel@lists.xenproject.org; Wed, 08 Jan 2025 11:13:21 +0000 Received: from mail-lj1-x229.google.com (mail-lj1-x229.google.com [2a00:1450:4864:20::229]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id 917c0209-cdb1-11ef-a0df-8be0dac302b0; Wed, 08 Jan 2025 12:13:20 +0100 (CET) Received: by mail-lj1-x229.google.com with SMTP id 38308e7fff4ca-3035046d4bfso149705381fa.0 for ; Wed, 08 Jan 2025 03:13:20 -0800 (PST) Received: from fedora.. ([94.75.70.14]) by smtp.gmail.com with ESMTPSA id 38308e7fff4ca-3045ad99d11sm67292171fa.33.2025.01.08.03.13.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 08 Jan 2025 03:13:19 -0800 (PST) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 917c0209-cdb1-11ef-a0df-8be0dac302b0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1736334800; x=1736939600; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=gjG9qId5djE3f1micVajTt9P6Qgh0I5fxUYbZTHiv9Q=; b=EP9OCOuGshgHmlld/dgJN6uhHb/oW/6akMqbSjJrRhIJihGQrkVIldLiZcBxmS/Zf4 zUKA9JPxNgYwRk9IMejZPpGu96ZdnvKvGSUi0C+s+OqsnP68ktDuIGITKnwRkoTX1ixl +Za5Hy9BcOU9gJB4B258pEH6OZy8c2ivXR732is2IM3w6h6gFspJWFSEwRhZLcjEuhNJ eosfwpe2EJKrHxqXDGPOsNO91pchxRB+0WOabp/kqfPypSO9iy8WsCob7S+7XJ/mZwTN ONmWgO4ccF1MBob4T5yMqFms5JFt/ImnLOOfI9hCoBAbjiBjYwPEDfsOWw51uQDDSPU/ NWpQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1736334800; x=1736939600; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=gjG9qId5djE3f1micVajTt9P6Qgh0I5fxUYbZTHiv9Q=; b=nTIVU9w+Wz8BKZ6ogpTovIjWELRf1LDjhQL+vEANv0JxIhnEK8KDOoxwDh/j8Q024R fKvpAnqy5iALxahYgR4K1yl4Cd7Iwg+Zlm/gEPXlSmmgBYaFH5Ty1zFohvHh82bUK4OW qqHKwWsOSTDUv9MtM7nlPkda/VJakmmsj0pebC8YlEIEWI5Jb98Xl/6UnPD51WpUsZ/I MYISpDW0tn3Jlwyvf6tyEtZeYOK2gI7sMdFVGRWywxQi81WzfykSYjvHNA2B/EZCTLu6 IBpSWO0mLb2qhqnCgU4hqnzzbY+QaUaSW7YSbxWWNc5ClF69eOLfqK1RVf30pBvIqF+V I6Nw== X-Gm-Message-State: AOJu0Yynp0O7qwuihnQrVco+7WbFiIRGQfmGIHvZ86GKzrYLN3qlaQwm R+eg/OB4pZhx1ALovcZcoJG71xA0LifXZSCu9RrgSAWqQuF3ud/y08VbG/om X-Gm-Gg: ASbGncu2bi9gz54ThRfcWBFhP/MM2sPmSnR0gYNRilDCeQX7+oH8jYWtWHlAlzovujv wxOEVzXkFGpGVbh1CgSebDWGzjYlvoUDjosdY9NbCrxY7rtk8gvsJf8SYEwqZOo38f3z5eoskrX wBpCBNdWRMUW+h06WevRjPSV6QcJXeLECDKO2QFnxL9G1yqagSJzQ4AHt50YswwnS8+DYSy9mh3 DBmuhowhmOrd1z4WzuFCM3AuIRdfnBT7Ljc9THNgllvOQBFOJEt2SmJXw== X-Google-Smtp-Source: AGHT+IGWZrRhrHrT3ZUdadlaUlf3iZdqOIAZklSUrdQWysRk2Agd0ISiTq6rO/0UhBn0Dzv/8rhd6w== X-Received: by 2002:a2e:a9a8:0:b0:300:324e:3506 with SMTP id 38308e7fff4ca-305f4575d06mr5892931fa.13.1736334799722; Wed, 08 Jan 2025 03:13:19 -0800 (PST) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Oleksii Kurochko , Stefano Stabellini , Julien Grall , Bertrand Marquis , Michal Orzel , Volodymyr Babchuk , Andrew Cooper , Anthony PERARD , Jan Beulich , =?utf-8?q?Roger_Pau_Monn=C3=A9?= Subject: [PATCH v1 6/9] asm-generic: move some parts of Arm's domain_build.h to asm-generic header Date: Wed, 8 Jan 2025 12:13:08 +0100 Message-ID: X-Mailer: git-send-email 2.47.1 In-Reply-To: References: MIME-Version: 1.0 Nothing changed. Only some functions declaration are moved to asm-generic header as they are expected to be used by common code of domain builing or dom0less. Signed-off-by: Oleksii Kurochko --- xen/arch/arm/include/asm/domain_build.h | 19 ++---------- xen/include/asm-generic/domain-build.h | 41 +++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 17 deletions(-) create mode 100644 xen/include/asm-generic/domain-build.h diff --git a/xen/arch/arm/include/asm/domain_build.h b/xen/arch/arm/include/asm/domain_build.h index 5d77af2e8b..ad5a3ddc37 100644 --- a/xen/arch/arm/include/asm/domain_build.h +++ b/xen/arch/arm/include/asm/domain_build.h @@ -4,28 +4,13 @@ #include #include +#include + typedef __be32 gic_interrupt_t[3]; -typedef bool (*alloc_domheap_mem_cb)(struct domain *d, struct page_info *pg, - unsigned int order, void *extra); -bool allocate_domheap_memory(struct domain *d, paddr_t tot_size, - alloc_domheap_mem_cb cb, void *extra); -bool allocate_bank_memory(struct kernel_info *kinfo, gfn_t sgfn, - paddr_t tot_size); -void allocate_memory(struct domain *d, struct kernel_info *kinfo); -int construct_domain(struct domain *d, struct kernel_info *kinfo); int domain_fdt_begin_node(void *fdt, const char *name, uint64_t unit); -int make_chosen_node(const struct kernel_info *kinfo); -int make_cpus_node(const struct domain *d, void *fdt); -int make_hypervisor_node(struct domain *d, const struct kernel_info *kinfo, - int addrcells, int sizecells); -int make_memory_node(const struct kernel_info *kinfo, int addrcells, - int sizecells, const struct membanks *mem); int make_psci_node(void *fdt); -int make_timer_node(const struct kernel_info *kinfo); void evtchn_allocate(struct domain *d); -unsigned int get_allocation_size(paddr_t size); - /* * handle_device_interrupts retrieves the interrupts configuration from * a device tree node and maps those interrupts to the target domain. diff --git a/xen/include/asm-generic/domain-build.h b/xen/include/asm-generic/domain-build.h new file mode 100644 index 0000000000..237f94d0c3 --- /dev/null +++ b/xen/include/asm-generic/domain-build.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef __ASM_GENERIC_DOMAIN_BUILD_H__ +#define __ASM_GENERIC_DOMAIN_BUILD_H__ + +#include + +struct domain; +struct page_info; +struct kernel_info; +struct membanks; + +typedef bool (*alloc_domheap_mem_cb)(struct domain *d, struct page_info *pg, + unsigned int order, void *extra); +bool allocate_domheap_memory(struct domain *d, paddr_t tot_size, + alloc_domheap_mem_cb cb, void *extra); + +bool allocate_bank_memory(struct kernel_info *kinfo, gfn_t sgfn, + paddr_t tot_size); +void allocate_memory(struct domain *d, struct kernel_info *kinfo); +int construct_domain(struct domain *d, struct kernel_info *kinfo); +int make_chosen_node(const struct kernel_info *kinfo); +int make_cpus_node(const struct domain *d, void *fdt); +int make_hypervisor_node(struct domain *d, const struct kernel_info *kinfo, + int addrcells, int sizecells); +int make_memory_node(const struct kernel_info *kinfo, int addrcells, + int sizecells, const struct membanks *mem); +int make_timer_node(const struct kernel_info *kinfo); + +unsigned int get_allocation_size(paddr_t size); + + +#endif /* __ASM_GENERIC_DOMAIN_BUILD_H__ */ + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ From patchwork Wed Jan 8 11:13:09 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oleksii Kurochko X-Patchwork-Id: 13930559 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id A761CE77199 for ; Wed, 8 Jan 2025 11:13:36 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.867139.1278626 (Exim 4.92) (envelope-from ) id 1tVU04-0002uN-Ub; Wed, 08 Jan 2025 11:13:24 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 867139.1278626; Wed, 08 Jan 2025 11:13:24 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1tVU04-0002tB-NU; Wed, 08 Jan 2025 11:13:24 +0000 Received: by outflank-mailman (input) for mailman id 867139; Wed, 08 Jan 2025 11:13:23 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1tVU03-0001BZ-5F for xen-devel@lists.xenproject.org; Wed, 08 Jan 2025 11:13:23 +0000 Received: from mail-lj1-x234.google.com (mail-lj1-x234.google.com [2a00:1450:4864:20::234]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id 926606e7-cdb1-11ef-a0df-8be0dac302b0; Wed, 08 Jan 2025 12:13:22 +0100 (CET) Received: by mail-lj1-x234.google.com with SMTP id 38308e7fff4ca-30167f4c1e3so105804321fa.3 for ; Wed, 08 Jan 2025 03:13:22 -0800 (PST) Received: from fedora.. ([94.75.70.14]) by smtp.gmail.com with ESMTPSA id 38308e7fff4ca-3045ad99d11sm67292171fa.33.2025.01.08.03.13.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 08 Jan 2025 03:13:20 -0800 (PST) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 926606e7-cdb1-11ef-a0df-8be0dac302b0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1736334801; x=1736939601; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ER/+mxB0CWJe1/Ae6aNRRXYkKAFXe/AIxI0Akw6x6FU=; b=exkvhNymIM0qCE5frP95CnTFiEnGtwy/Q5HbP0SZOcrbrTuGQ6Av1i1TpXEYPY4a4r PbkYKBSRQm60QSe7SmhvE4W7pJRpQOVHvnwG633SvOZxUgbyeHan5bwEOJIIwAB0Yiwe BsJn/T7t2+JZ15A0k0XHe9SWmKJvLUqYI17J6Y2KVP/9qZJWEm2EiuqsQNW9ENQjRC2i fzPblZ9EL4qvt3JOl384rR0GLo5pKsubLbVBH9J4fVDYhAtpJpjrpyjuywsaurJ9iEmA qXQ1PUeqdueSgRsJV9wrOGgcpeMbe95483gQcbaJPCsrRopYqNuVcejKoXEw1Fxp8N2y WxsA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1736334801; x=1736939601; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ER/+mxB0CWJe1/Ae6aNRRXYkKAFXe/AIxI0Akw6x6FU=; b=UXb84zOhp2rcxGPGrwUPlsRPi2Xn32fVCfWBfLrZr7SaRyxSWaYEfZrFVF14O98eTs d4uGJtlbp5Qcl5xzbCDiDj+gCsZK7D+wrOhDxYYp709pcr9oiiVkUrI5M7Y7ThYltoL0 aUcJ23x/mX5xC57G+oa+Nq3RK1GJDRO6wbex0DjcchKC/YZCVVdOkcn3Z27wUMg/+Iph UTKyMQL8Z7zo+1rMPrLPn1R9dWERhXemA9ZFlPpWMhTNSE1UfTqwqyUEXwSezyEb6VWw AiM+md1lqjBGYq1lgHZPLrzDiucjUDnNXM1VOWH+KPgrDQhknvHGFHRH3GjtVq52w1Z+ IqSg== X-Gm-Message-State: AOJu0YwvNNQKeE2GtPbqP8wg2i+eB+9FY2VfDUJ+diahOSxsbYcHakxa HZ7ZQAu8UdEXffAifz9/2zgAaO7cA7EKzeWNQgFpDuGdB9iyY0OoaBZpggKi X-Gm-Gg: ASbGncsrvWAJVJYz6seKock2EyUYATbW8hEeHqYvmDeDST6rCc7eHiT5RxhSPOAs7xP n/MstCzqeKvMCWkRYb36ipanr+fOpOKaU0sC1wdhuQ7u1h9dhKWJdSOdfpmJHsQmIMF3D0b2vuh 0KmU45nXhv618VxPcIRWFq3Ii86fNgSPnD6xMevlvxizisUGZKA+mGXhZWGOd3S9gN29IBqj6Ey gODtilvGgzY4yDKL1QXVirGClduvOG1BhoSMCq/6qN4QV88y4hYnJZ5NQ== X-Google-Smtp-Source: AGHT+IFiEzwr+MI445NGcgyjXXjMGNtN8f9qmcZxlCvs0GDA+OYXgjF+Fuke9f+ZG71rrZIXmAGLfA== X-Received: by 2002:a05:651c:b21:b0:300:94b3:f26 with SMTP id 38308e7fff4ca-305f45db35bmr7736371fa.25.1736334800736; Wed, 08 Jan 2025 03:13:20 -0800 (PST) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Oleksii Kurochko , Stefano Stabellini , Julien Grall , Bertrand Marquis , Michal Orzel , Volodymyr Babchuk , Andrew Cooper , Anthony PERARD , Jan Beulich , =?utf-8?q?Roger_Pau_Monn=C3=A9?= Subject: [PATCH v1 7/9] xen/common: dom0less: introduce common kernel.c Date: Wed, 8 Jan 2025 12:13:09 +0100 Message-ID: <26ae1faf119585ebfb6ceb392918fe6960886e77.1736334615.git.oleksii.kurochko@gmail.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: References: MIME-Version: 1.0 The following functions don't have arch specific things so it is moved to common: - kernel_prboe() - kernel_load() - output_length() Functions necessary for dom0less are only moved. The following changes are done: - Swap __init and return type of kernel_decompress() function to be consistent with defintions of functions in other files. The same for output_length(). - Wrap by "ifdef CONFIG_ARM" the call of kernel_uimage_probe() in kernel_probe() as uImage isn't really used nowadays thereby leave kernel_uimage_probe() call here just for compatability with Arm code. - Introduce kernel_zimage_probe() to cover the case that arch can have different zimage header. - Add ASSERT() for kernel_load() to check that it argument isn't NULL. - Make kernel_uimage_probe() non-static in Arm's code as it is used in common/kernel.c. Introduce CONFIG_DOMAIN_BUILD_HELPERS to not provide stubs for archs which doesn't provice enough functionality to enable it. Select CONFIG_DOMAIN_BUILD_HELPERS for CONFIG_ARM as only Arm supports it, at the moment. Signed-off-by: Oleksii Kurochko --- xen/arch/arm/Kconfig | 1 + xen/arch/arm/kernel.c | 221 +--------------------------- xen/common/Kconfig | 11 +- xen/common/device-tree/Makefile | 1 + xen/common/device-tree/kernel.c | 242 +++++++++++++++++++++++++++++++ xen/include/asm-generic/kernel.h | 13 ++ 6 files changed, 272 insertions(+), 217 deletions(-) create mode 100644 xen/common/device-tree/kernel.c diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig index eff6ea6b6d..8a8681ef3b 100644 --- a/xen/arch/arm/Kconfig +++ b/xen/arch/arm/Kconfig @@ -12,6 +12,7 @@ config ARM_64 config ARM def_bool y + select DOMAIN_BUILD_HELPERS select FUNCTION_ALIGNMENT_4B select GENERIC_UART_INIT select HAS_ALTERNATIVE if HAS_VMAP diff --git a/xen/arch/arm/kernel.c b/xen/arch/arm/kernel.c index b75bd6a887..8e5fd09c75 100644 --- a/xen/arch/arm/kernel.c +++ b/xen/arch/arm/kernel.c @@ -160,105 +160,6 @@ static void __init kernel_zimage_load(struct kernel_info *info) iounmap(kernel); } -static __init uint32_t output_length(char *image, unsigned long image_len) -{ - return *(uint32_t *)&image[image_len - 4]; -} - -static __init int kernel_decompress(struct bootmodule *mod, uint32_t offset) -{ - char *output, *input; - char magic[2]; - int rc; - unsigned int kernel_order_out; - paddr_t output_size; - struct page_info *pages; - mfn_t mfn; - int i; - paddr_t addr = mod->start; - paddr_t size = mod->size; - - if ( size < offset ) - return -EINVAL; - - /* - * It might be that gzip header does not appear at the start address - * (e.g. in case of compressed uImage) so take into account offset to - * gzip header. - */ - addr += offset; - size -= offset; - - if ( size < 2 ) - return -EINVAL; - - copy_from_paddr(magic, addr, sizeof(magic)); - - /* only gzip is supported */ - if ( !gzip_check(magic, size) ) - return -EINVAL; - - input = ioremap_cache(addr, size); - if ( input == NULL ) - return -EFAULT; - - output_size = output_length(input, size); - kernel_order_out = get_order_from_bytes(output_size); - pages = alloc_domheap_pages(NULL, kernel_order_out, 0); - if ( pages == NULL ) - { - iounmap(input); - return -ENOMEM; - } - mfn = page_to_mfn(pages); - output = vmap_contig(mfn, 1 << kernel_order_out); - - rc = perform_gunzip(output, input, size); - clean_dcache_va_range(output, output_size); - iounmap(input); - vunmap(output); - - if ( rc ) - { - free_domheap_pages(pages, kernel_order_out); - return rc; - } - - mod->start = page_to_maddr(pages); - mod->size = output_size; - - /* - * Need to free pages after output_size here because they won't be - * freed by discard_initial_modules - */ - i = PFN_UP(output_size); - for ( ; i < (1 << kernel_order_out); i++ ) - free_domheap_page(pages + i); - - /* - * When using static heap feature, don't give bootmodules memory back to - * the heap allocator - */ - if ( using_static_heap ) - return 0; - - /* - * When freeing the kernel, we need to pass the module start address and - * size as they were before taking an offset to gzip header into account, - * so that the entire region will be freed. - */ - addr -= offset; - size += offset; - - /* - * Free the original kernel, update the pointers to the - * decompressed kernel - */ - fw_unreserved_regions(addr, addr + size, init_domheap_pages, 0); - - return 0; -} - /* * Uimage CPU Architecture Codes */ @@ -271,8 +172,8 @@ static __init int kernel_decompress(struct bootmodule *mod, uint32_t offset) /* * Check if the image is a uImage and setup kernel_info */ -static int __init kernel_uimage_probe(struct kernel_info *info, - struct bootmodule *mod) +int __init kernel_uimage_probe(struct kernel_info *info, + struct bootmodule *mod) { struct { __be32 magic; /* Image Header Magic Number */ @@ -502,130 +403,20 @@ static int __init kernel_zimage32_probe(struct kernel_info *info, return 0; } -int __init kernel_probe(struct kernel_info *info, - const struct dt_device_node *domain) +int __init kernel_zimage_probe(struct kernel_info *info, paddr_t addr, + paddr_t size) { - struct bootmodule *mod = NULL; - struct bootcmdline *cmd = NULL; - struct dt_device_node *node; - u64 kernel_addr, initrd_addr, dtb_addr, size; int rc; - /* - * We need to initialize start to 0. This field may be populated during - * kernel_xxx_probe() if the image has a fixed entry point (for e.g. - * uimage.ep). - * We will use this to determine if the image has a fixed entry point or - * the load address should be used as the start address. - */ - info->entry = 0; - - /* domain is NULL only for the hardware domain */ - if ( domain == NULL ) - { - ASSERT(is_hardware_domain(info->d)); - - mod = boot_module_find_by_kind(BOOTMOD_KERNEL); - - info->kernel_bootmodule = mod; - info->initrd_bootmodule = boot_module_find_by_kind(BOOTMOD_RAMDISK); - - cmd = boot_cmdline_find_by_kind(BOOTMOD_KERNEL); - if ( cmd ) - info->cmdline = &cmd->cmdline[0]; - } - else - { - const char *name = NULL; - - dt_for_each_child_node(domain, node) - { - if ( dt_device_is_compatible(node, "multiboot,kernel") ) - { - u32 len; - const __be32 *val; - - val = dt_get_property(node, "reg", &len); - dt_get_range(&val, node, &kernel_addr, &size); - mod = boot_module_find_by_addr_and_kind( - BOOTMOD_KERNEL, kernel_addr); - info->kernel_bootmodule = mod; - } - else if ( dt_device_is_compatible(node, "multiboot,ramdisk") ) - { - u32 len; - const __be32 *val; - - val = dt_get_property(node, "reg", &len); - dt_get_range(&val, node, &initrd_addr, &size); - info->initrd_bootmodule = boot_module_find_by_addr_and_kind( - BOOTMOD_RAMDISK, initrd_addr); - } - else if ( dt_device_is_compatible(node, "multiboot,device-tree") ) - { - uint32_t len; - const __be32 *val; - - val = dt_get_property(node, "reg", &len); - if ( val == NULL ) - continue; - dt_get_range(&val, node, &dtb_addr, &size); - info->dtb_bootmodule = boot_module_find_by_addr_and_kind( - BOOTMOD_GUEST_DTB, dtb_addr); - } - else - continue; - } - name = dt_node_name(domain); - cmd = boot_cmdline_find_by_name(name); - if ( cmd ) - info->cmdline = &cmd->cmdline[0]; - } - if ( !mod || !mod->size ) - { - printk(XENLOG_ERR "Missing kernel boot module?\n"); - return -ENOENT; - } - - printk("Loading %pd kernel from boot module @ %"PRIpaddr"\n", - info->d, info->kernel_bootmodule->start); - if ( info->initrd_bootmodule ) - printk("Loading ramdisk from boot module @ %"PRIpaddr"\n", - info->initrd_bootmodule->start); - - /* - * uImage header always appears at the top of the image (even compressed), - * so it needs to be probed first. Note that in case of compressed uImage, - * kernel_decompress is called from kernel_uimage_probe making the function - * self-containing (i.e. fall through only in case of a header not found). - */ - rc = kernel_uimage_probe(info, mod); - if ( rc != -ENOENT ) - return rc; - - /* - * If it is a gzip'ed image, 32bit or 64bit, uncompress it. - * At this point, gzip header appears (if at all) at the top of the image, - * so pass 0 as an offset. - */ - rc = kernel_decompress(mod, 0); - if ( rc && rc != -EINVAL ) - return rc; - #ifdef CONFIG_ARM_64 - rc = kernel_zimage64_probe(info, mod->start, mod->size); + rc = kernel_zimage64_probe(info, addr, size); if (rc < 0) #endif - rc = kernel_zimage32_probe(info, mod->start, mod->size); + rc = kernel_zimage32_probe(info, addr, size); return rc; } -void __init kernel_load(struct kernel_info *info) -{ - info->load(info); -} - /* * Local variables: * mode: C diff --git a/xen/common/Kconfig b/xen/common/Kconfig index 099e6e72ad..83f8a8f791 100644 --- a/xen/common/Kconfig +++ b/xen/common/Kconfig @@ -14,13 +14,20 @@ config CORE_PARKING config DOM0LESS_BOOT bool "Dom0less boot support" if EXPERT - depends on ARM - default ARM + depends on DOMAIN_BUILD_HELPERS + default DOMAIN_BUILD_HELPERS help Dom0less boot support enables Xen to create and start domU guests during Xen boot without the need of a control domain (Dom0), which could be present anyway. +config DOMAIN_BUILD_HELPERS + bool + help + Introduce functions necessary for working with domain creation, kernel, + etc. As an examples, these type of functions are going to be used by + CONFIG_DOM0LESS_BOOT. + config GRANT_TABLE bool "Grant table support" if EXPERT default y diff --git a/xen/common/device-tree/Makefile b/xen/common/device-tree/Makefile index f3dafc9b81..e88a4d5799 100644 --- a/xen/common/device-tree/Makefile +++ b/xen/common/device-tree/Makefile @@ -4,3 +4,4 @@ obj-y += device-tree.o obj-$(CONFIG_DOM0LESS_BOOT) += dom0less-build.o obj-$(CONFIG_OVERLAY_DTB) += dt-overlay.o obj-y += intc.o +obj-$(CONFIG_DOMAIN_BUILD_HELPERS) += kernel.o diff --git a/xen/common/device-tree/kernel.c b/xen/common/device-tree/kernel.c new file mode 100644 index 0000000000..bd5d968bfd --- /dev/null +++ b/xen/common/device-tree/kernel.c @@ -0,0 +1,242 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static uint32_t __init output_length(char *image, unsigned long image_len) +{ + return *(uint32_t *)&image[image_len - 4]; +} + +int __init kernel_decompress(struct bootmodule *mod, uint32_t offset) +{ + char *output, *input; + char magic[2]; + int rc; + unsigned int kernel_order_out; + paddr_t output_size; + struct page_info *pages; + mfn_t mfn; + int i; + paddr_t addr = mod->start; + paddr_t size = mod->size; + + if ( size < offset ) + return -EINVAL; + + /* + * It might be that gzip header does not appear at the start address + * (e.g. in case of compressed uImage) so take into account offset to + * gzip header. + */ + addr += offset; + size -= offset; + + if ( size < 2 ) + return -EINVAL; + + copy_from_paddr(magic, addr, sizeof(magic)); + + /* only gzip is supported */ + if ( !gzip_check(magic, size) ) + return -EINVAL; + + input = ioremap_cache(addr, size); + if ( input == NULL ) + return -EFAULT; + + output_size = output_length(input, size); + kernel_order_out = get_order_from_bytes(output_size); + pages = alloc_domheap_pages(NULL, kernel_order_out, 0); + if ( pages == NULL ) + { + iounmap(input); + return -ENOMEM; + } + mfn = page_to_mfn(pages); + output = vmap_contig(mfn, 1 << kernel_order_out); + + rc = perform_gunzip(output, input, size); + clean_dcache_va_range(output, output_size); + iounmap(input); + vunmap(output); + + if ( rc ) + { + free_domheap_pages(pages, kernel_order_out); + return rc; + } + + mod->start = page_to_maddr(pages); + mod->size = output_size; + + /* + * Need to free pages after output_size here because they won't be + * freed by discard_initial_modules + */ + i = PFN_UP(output_size); + for ( ; i < (1 << kernel_order_out); i++ ) + free_domheap_page(pages + i); + + /* + * When using static heap feature, don't give bootmodules memory back to + * the heap allocator + */ + if ( using_static_heap ) + return 0; + + /* + * When freeing the kernel, we need to pass the module start address and + * size as they were before taking an offset to gzip header into account, + * so that the entire region will be freed. + */ + addr -= offset; + size += offset; + + /* + * Free the original kernel, update the pointers to the + * decompressed kernel + */ + fw_unreserved_regions(addr, addr + size, init_domheap_pages, 0); + + return 0; +} + +int __init kernel_probe(struct kernel_info *info, + const struct dt_device_node *domain) +{ + struct bootmodule *mod = NULL; + struct bootcmdline *cmd = NULL; + struct dt_device_node *node; + u64 kernel_addr, initrd_addr, dtb_addr, size; + int rc; + + /* + * We need to initialize start to 0. This field may be populated during + * kernel_xxx_probe() if the image has a fixed entry point (for e.g. + * uimage.ep). + * We will use this to determine if the image has a fixed entry point or + * the load address should be used as the start address. + */ + info->entry = 0; + + /* domain is NULL only for the hardware domain */ + if ( domain == NULL ) + { + ASSERT(is_hardware_domain(info->d)); + + mod = boot_module_find_by_kind(BOOTMOD_KERNEL); + + info->kernel_bootmodule = mod; + info->initrd_bootmodule = boot_module_find_by_kind(BOOTMOD_RAMDISK); + + cmd = boot_cmdline_find_by_kind(BOOTMOD_KERNEL); + if ( cmd ) + info->cmdline = &cmd->cmdline[0]; + } + else + { + const char *name = NULL; + + dt_for_each_child_node(domain, node) + { + if ( dt_device_is_compatible(node, "multiboot,kernel") ) + { + u32 len; + const __be32 *val; + + val = dt_get_property(node, "reg", &len); + dt_get_range(&val, node, &kernel_addr, &size); + mod = boot_module_find_by_addr_and_kind( + BOOTMOD_KERNEL, kernel_addr); + info->kernel_bootmodule = mod; + } + else if ( dt_device_is_compatible(node, "multiboot,ramdisk") ) + { + u32 len; + const __be32 *val; + + val = dt_get_property(node, "reg", &len); + dt_get_range(&val, node, &initrd_addr, &size); + info->initrd_bootmodule = boot_module_find_by_addr_and_kind( + BOOTMOD_RAMDISK, initrd_addr); + } + else if ( dt_device_is_compatible(node, "multiboot,device-tree") ) + { + uint32_t len; + const __be32 *val; + + val = dt_get_property(node, "reg", &len); + if ( val == NULL ) + continue; + dt_get_range(&val, node, &dtb_addr, &size); + info->dtb_bootmodule = boot_module_find_by_addr_and_kind( + BOOTMOD_GUEST_DTB, dtb_addr); + } + else + continue; + } + name = dt_node_name(domain); + cmd = boot_cmdline_find_by_name(name); + if ( cmd ) + info->cmdline = &cmd->cmdline[0]; + } + if ( !mod || !mod->size ) + { + printk(XENLOG_ERR "Missing kernel boot module?\n"); + return -ENOENT; + } + + printk("Loading %pd kernel from boot module @ %"PRIpaddr"\n", + info->d, info->kernel_bootmodule->start); + if ( info->initrd_bootmodule ) + printk("Loading ramdisk from boot module @ %"PRIpaddr"\n", + info->initrd_bootmodule->start); + + /* + * uImage isn't really used nowadays thereby leave kernel_uimage_probe() + * call here just for compatability with Arm code. + */ +#ifdef CONFIG_ARM + /* + * uImage header always appears at the top of the image (even compressed), + * so it needs to be probed first. Note that in case of compressed uImage, + * kernel_decompress is called from kernel_uimage_probe making the function + * self-containing (i.e. fall through only in case of a header not found). + */ + rc = kernel_uimage_probe(info, mod); + if ( rc != -ENOENT ) + return rc; +#endif + + /* + * If it is a gzip'ed image, 32bit or 64bit, uncompress it. + * At this point, gzip header appears (if at all) at the top of the image, + * so pass 0 as an offset. + */ + rc = kernel_decompress(mod, 0); + if ( rc && rc != -EINVAL ) + return rc; + + rc = kernel_zimage_probe(info, mod->start, mod->size); + + return rc; +} + +void __init kernel_load(struct kernel_info *info) +{ + ASSERT(info && info->load); + + info->load(info); +} diff --git a/xen/include/asm-generic/kernel.h b/xen/include/asm-generic/kernel.h index b2bd04a185..d668c7ef4f 100644 --- a/xen/include/asm-generic/kernel.h +++ b/xen/include/asm-generic/kernel.h @@ -134,6 +134,19 @@ int kernel_probe(struct kernel_info *info, const struct dt_device_node *domain); */ void kernel_load(struct kernel_info *info); +int kernel_decompress(struct bootmodule *mod, uint32_t offset); + +int kernel_zimage_probe(struct kernel_info *info, paddr_t addr, paddr_t size); + +/* + * uImage isn't really used nowadays thereby leave kernel_uimage_probe() + * call here just for compatability with Arm code. + */ +#ifdef CONFIG_ARM +struct bootmodule; +int kernel_uimage_probe(struct kernel_info *info, struct bootmodule *mod); +#endif + #endif /*__ASM_GENERIC_KERNEL_H__ */ /* From patchwork Wed Jan 8 11:13:10 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oleksii Kurochko X-Patchwork-Id: 13930563 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 84CF3E7719C for ; Wed, 8 Jan 2025 11:13:39 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.867140.1278635 (Exim 4.92) (envelope-from ) id 1tVU06-0003CX-8m; Wed, 08 Jan 2025 11:13:26 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 867140.1278635; Wed, 08 Jan 2025 11:13:26 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1tVU06-0003BS-4a; Wed, 08 Jan 2025 11:13:26 +0000 Received: by outflank-mailman (input) for mailman id 867140; Wed, 08 Jan 2025 11:13:24 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1tVU04-0001BZ-EW for xen-devel@lists.xenproject.org; Wed, 08 Jan 2025 11:13:24 +0000 Received: from mail-lj1-x22a.google.com (mail-lj1-x22a.google.com [2a00:1450:4864:20::22a]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id 931b7a19-cdb1-11ef-a0df-8be0dac302b0; Wed, 08 Jan 2025 12:13:23 +0100 (CET) Received: by mail-lj1-x22a.google.com with SMTP id 38308e7fff4ca-3003c82c95cso137043991fa.3 for ; Wed, 08 Jan 2025 03:13:23 -0800 (PST) Received: from fedora.. ([94.75.70.14]) by smtp.gmail.com with ESMTPSA id 38308e7fff4ca-3045ad99d11sm67292171fa.33.2025.01.08.03.13.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 08 Jan 2025 03:13:21 -0800 (PST) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 931b7a19-cdb1-11ef-a0df-8be0dac302b0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1736334803; x=1736939603; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=GCRNwIFmqmDzUyPUbfaADvOUBg93q5fcxanayhRIhFo=; b=jaYkFV3h2t9AQUEcFoSPMazvvjKj5WqpI5caWp6Ly2mZ5rlM4+S20d2clNeHJ1uNt7 17+X1Y9/ydhc0kyC0l4nyDw4BtUzxDEyaDbDjPpAznv618Y/cbhcQfcPt/PNPvtpQdXU C2fn0sLA7+GUbbf2Hitd3ol1EggwpQe4jx1Z4N/6f50Yry/v9te29efajK/rUXdCtpAP WtDBTAfHuf/t0rHyAAEDuXeh9elz5s6C9bmsJ2mSTxY/3WQB8tswCnEaGr9OgrsG7AUg dUA5IKhDXWHOrp7MJ2r2jUzNxTql5R4Jlg7QoFsHDK14dBN31vipF4vXWs8ycZsDjqvk 59QA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1736334803; x=1736939603; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=GCRNwIFmqmDzUyPUbfaADvOUBg93q5fcxanayhRIhFo=; b=AC4NrLMkzRb1nGP/OtmBDYYD9WRcwECWKMidbqIWlUE/ZdJ9FS3oE7qAZgHY0cbW37 9P/wF5vP5wqAh5Z9Fj6TNXyFfjx19WeqOmKBuwGhijPaCwyZqe2OUCDchGhvx1eqdCrw byiv0UlDjyqpunWeLxNSkSVdhylGng5J3c3aJ665vRd/tpoIFCiMMKmYUWyZqh/DS7yo R07MLZK/wlokwWCmJVnb7k08aDzeAGiCWx5OChp35SU8bM0j1MAIRAmsaDip+YwAmJN6 Vsu6ZV9AqftZQw+LQLpXTMBo4jyl3UfFMRuBHfRGPpBFUn/KweL2TCDVXLiOy+xzODEf NZoQ== X-Gm-Message-State: AOJu0Yy2AwUPREA7j2RSZdYZVkl+ygZAEVhGkh1oI9UuFNKawOpXEJih H1rKDUtorPpxWz3T+Uy6v+Ka9GVR0yp8w8xCocviBs3yaw3o1okcKjyPcPVc X-Gm-Gg: ASbGncssgZQRazy58hntG+GLAf5RIz/nKIDtSvXk6y/0P0z4TZ9hobFUrsnY48CoZbD vUQVXN8omNJNc0FiHHtz8kCRbu3kouHx1773jliD7h5HxbYWpaVetjS3Nk5wgOXtQZ/FFEX3Ddt Uz9GZPT6fd4BVQC0uYzl13nrgOVECP043hwv9CRtYrATAdUSS5iodA+r8xsZXhcMa7dYSrikwSq VY7ilVx2UK7aJc2a16C//wn1/5vWsy7rG2ykiBqRcv3GjD/6XOAgHbSsw== X-Google-Smtp-Source: AGHT+IG8Cf26ShFn3iyVqP3HxATc+zjwe9ssoFtEuTEVG/VclyY9cvaI5LziOEOTbQD3wOHcNXH8fw== X-Received: by 2002:a2e:b888:0:b0:2fb:597e:28d9 with SMTP id 38308e7fff4ca-305f45855bbmr5999531fa.14.1736334802299; Wed, 08 Jan 2025 03:13:22 -0800 (PST) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Oleksii Kurochko , Stefano Stabellini , Julien Grall , Bertrand Marquis , Michal Orzel , Volodymyr Babchuk , Andrew Cooper , Anthony PERARD , Jan Beulich , =?utf-8?q?Roger_Pau_Monn=C3=A9?= Subject: [PATCH v1 8/9] xen/common: dom0less: introduce common domain-build.c Date: Wed, 8 Jan 2025 12:13:10 +0100 Message-ID: <5d4634ff3d44955d4110ce52c14e0a524cbc4706.1736334615.git.oleksii.kurochko@gmail.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: References: MIME-Version: 1.0 Some functions of Arm's domain_build.c could be reused by dom0less or other features connected to domain construction/build. The following functions are moved to common: - get_allocation_size(). - allocate_domheap_memory(). - guest_map_pages(). - allocate_bank_memory(). - add_hwdom_free_regions(). - find_unallocated_memory(). - allocate_memory(). - dtb_load(). - initrd_load(). Prototype of dtb_load() and initrd_load() is updated to recieve a pointer to copy_to_guest_phys() as some archs require copy_to_guest_phys_fluch_dcache(). Update arm/include/asm/Makefile to generate domain-build.h for Arm as it is used by domain-build.c. Signed-off-by: Oleksii Kurochko --- xen/arch/arm/domain_build.c | 400 +----------------------- xen/arch/arm/include/asm/Makefile | 1 + xen/common/device-tree/Makefile | 1 + xen/common/device-tree/domain-build.c | 405 +++++++++++++++++++++++++ xen/include/asm-generic/domain-build.h | 33 +- 5 files changed, 441 insertions(+), 399 deletions(-) create mode 100644 xen/common/device-tree/domain-build.c diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c index 976b03a5df..e72da272d8 100644 --- a/xen/arch/arm/domain_build.c +++ b/xen/arch/arm/domain_build.c @@ -119,18 +119,6 @@ struct vcpu *__init alloc_dom0_vcpu0(struct domain *dom0) return vcpu_create(dom0, 0); } -unsigned int __init get_allocation_size(paddr_t size) -{ - /* - * get_order_from_bytes returns the order greater than or equal to - * the given size, but we need less than or equal. Adding one to - * the size pushes an evenly aligned size into the next order, so - * we can then unconditionally subtract 1 from the order which is - * returned. - */ - return get_order_from_bytes(size + 1) - 1; -} - /* * Insert the given pages into a memory bank, banks are ordered by address. * @@ -417,98 +405,6 @@ static void __init allocate_memory_11(struct domain *d, } } -bool __init allocate_domheap_memory(struct domain *d, paddr_t tot_size, - alloc_domheap_mem_cb cb, void *extra) -{ - unsigned int max_order = UINT_MAX; - - while ( tot_size > 0 ) - { - unsigned int order = get_allocation_size(tot_size); - struct page_info *pg; - - order = min(max_order, order); - - pg = alloc_domheap_pages(d, order, 0); - if ( !pg ) - { - /* - * If we can't allocate one page, then it is unlikely to - * succeed in the next iteration. So bail out. - */ - if ( !order ) - return false; - - /* - * If we can't allocate memory with order, then it is - * unlikely to succeed in the next iteration. - * Record the order - 1 to avoid re-trying. - */ - max_order = order - 1; - continue; - } - - if ( !cb(d, pg, order, extra) ) - return false; - - tot_size -= (1ULL << (PAGE_SHIFT + order)); - } - - return true; -} - -static bool __init guest_map_pages(struct domain *d, struct page_info *pg, - unsigned int order, void *extra) -{ - gfn_t *sgfn = (gfn_t *)extra; - int res; - - BUG_ON(!sgfn); - res = guest_physmap_add_page(d, *sgfn, page_to_mfn(pg), order); - if ( res ) - { - dprintk(XENLOG_ERR, "Failed map pages to DOMU: %d", res); - return false; - } - - *sgfn = gfn_add(*sgfn, 1UL << order); - - return true; -} - -bool __init allocate_bank_memory(struct kernel_info *kinfo, gfn_t sgfn, - paddr_t tot_size) -{ - struct membanks *mem = kernel_info_get_mem(kinfo); - struct domain *d = kinfo->d; - struct membank *bank; - - /* - * allocate_bank_memory can be called with a tot_size of zero for - * the second memory bank. It is not an error and we can safely - * avoid creating a zero-size memory bank. - */ - if ( tot_size == 0 ) - return true; - - bank = &mem->bank[mem->nr_banks]; - bank->start = gfn_to_gaddr(sgfn); - bank->size = tot_size; - - /* - * Allocate pages from the heap until tot_size is zero and map them to the - * guest using guest_map_pages, passing the starting gfn as extra parameter - * for the map operation. - */ - if ( !allocate_domheap_memory(d, tot_size, guest_map_pages, &sgfn) ) - return false; - - mem->nr_banks++; - kinfo->unassigned_mem -= bank->size; - - return true; -} - /* * When PCI passthrough is available we want to keep the * "linux,pci-domain" in sync for every host bridge. @@ -899,229 +795,6 @@ int __init add_ext_regions(unsigned long s_gfn, unsigned long e_gfn, return 0; } -static int __init add_hwdom_free_regions(unsigned long s_gfn, - unsigned long e_gfn, void *data) -{ - struct membanks *free_regions = data; - paddr_t start, size; - paddr_t s = pfn_to_paddr(s_gfn); - paddr_t e = pfn_to_paddr(e_gfn); - unsigned int i, j; - - if ( free_regions->nr_banks >= free_regions->max_banks ) - return 0; - - /* - * Both start and size of the free region should be 2MB aligned to - * potentially allow superpage mapping. - */ - start = (s + SZ_2M - 1) & ~(SZ_2M - 1); - if ( start > e ) - return 0; - - /* - * e is actually "end-1" because it is called by rangeset functions - * which are inclusive of the last address. - */ - e += 1; - size = (e - start) & ~(SZ_2M - 1); - - /* Find the insert position (descending order). */ - for ( i = 0; i < free_regions->nr_banks ; i++ ) - if ( size > free_regions->bank[i].size ) - break; - - /* Move the other banks to make space. */ - for ( j = free_regions->nr_banks; j > i ; j-- ) - { - free_regions->bank[j].start = free_regions->bank[j - 1].start; - free_regions->bank[j].size = free_regions->bank[j - 1].size; - } - - free_regions->bank[i].start = start; - free_regions->bank[i].size = size; - free_regions->nr_banks++; - - return 0; -} - -/* - * Find unused regions of Host address space which can be exposed to domain - * using the host memory layout. In order to calculate regions we exclude every - * region passed in mem_banks from the Host RAM. - */ -static int __init find_unallocated_memory(const struct kernel_info *kinfo, - const struct membanks *mem_banks[], - unsigned int nr_mem_banks, - struct membanks *free_regions, - int (*cb)(unsigned long s_gfn, - unsigned long e_gfn, - void *data)) -{ - const struct membanks *mem = bootinfo_get_mem(); - struct rangeset *unalloc_mem; - paddr_t start, end; - unsigned int i, j; - int res; - - ASSERT(domain_use_host_layout(kinfo->d)); - - unalloc_mem = rangeset_new(NULL, NULL, 0); - if ( !unalloc_mem ) - return -ENOMEM; - - /* Start with all available RAM */ - for ( i = 0; i < mem->nr_banks; i++ ) - { - start = mem->bank[i].start; - end = mem->bank[i].start + mem->bank[i].size; - res = rangeset_add_range(unalloc_mem, PFN_DOWN(start), - PFN_DOWN(end - 1)); - if ( res ) - { - printk(XENLOG_ERR "Failed to add: %#"PRIpaddr"->%#"PRIpaddr"\n", - start, end); - goto out; - } - } - - /* Remove all regions listed in mem_banks */ - for ( i = 0; i < nr_mem_banks; i++ ) - for ( j = 0; j < mem_banks[i]->nr_banks; j++ ) - { - start = mem_banks[i]->bank[j].start; - - /* Shared memory banks can contain INVALID_PADDR as start */ - if ( INVALID_PADDR == start ) - continue; - - end = mem_banks[i]->bank[j].start + mem_banks[i]->bank[j].size; - res = rangeset_remove_range(unalloc_mem, PFN_DOWN(start), - PFN_DOWN(end - 1)); - if ( res ) - { - printk(XENLOG_ERR - "Failed to add: %#"PRIpaddr"->%#"PRIpaddr", error %d\n", - start, end, res); - goto out; - } - } - - start = 0; - end = (1ULL << p2m_ipa_bits) - 1; - res = rangeset_report_ranges(unalloc_mem, PFN_DOWN(start), PFN_DOWN(end), - cb, free_regions); - if ( res ) - free_regions->nr_banks = 0; - else if ( !free_regions->nr_banks ) - res = -ENOENT; - -out: - rangeset_destroy(unalloc_mem); - - return res; -} - -void __init allocate_memory(struct domain *d, struct kernel_info *kinfo) -{ - struct membanks *mem = kernel_info_get_mem(kinfo); - unsigned int i, nr_banks = GUEST_RAM_BANKS; - struct membanks *hwdom_free_mem = NULL; - - printk(XENLOG_INFO "Allocating mappings totalling %ldMB for %pd:\n", - /* Don't want format this as PRIpaddr (16 digit hex) */ - (unsigned long)(kinfo->unassigned_mem >> 20), d); - - mem->nr_banks = 0; - /* - * Use host memory layout for hwdom. Only case for this is when LLC coloring - * is enabled. - */ - if ( is_hardware_domain(d) ) - { - struct membanks *gnttab = xzalloc_flex_struct(struct membanks, bank, 1); - /* - * Exclude the following regions: - * 1) Remove reserved memory - * 2) Grant table assigned to hwdom - */ - const struct membanks *mem_banks[] = { - bootinfo_get_reserved_mem(), - gnttab, - }; - - if ( !gnttab ) - goto fail; - - gnttab->nr_banks = 1; - gnttab->bank[0].start = kinfo->gnttab_start; - gnttab->bank[0].size = kinfo->gnttab_size; - - hwdom_free_mem = xzalloc_flex_struct(struct membanks, bank, - NR_MEM_BANKS); - if ( !hwdom_free_mem ) - goto fail; - - hwdom_free_mem->max_banks = NR_MEM_BANKS; - - if ( find_unallocated_memory(kinfo, mem_banks, ARRAY_SIZE(mem_banks), - hwdom_free_mem, add_hwdom_free_regions) ) - goto fail; - - nr_banks = hwdom_free_mem->nr_banks; - xfree(gnttab); - } - - for ( i = 0; kinfo->unassigned_mem > 0 && nr_banks > 0; i++, nr_banks-- ) - { - paddr_t bank_start, bank_size; - - if ( is_hardware_domain(d) ) - { - bank_start = hwdom_free_mem->bank[i].start; - bank_size = hwdom_free_mem->bank[i].size; - } - else - { - const uint64_t bankbase[] = GUEST_RAM_BANK_BASES; - const uint64_t banksize[] = GUEST_RAM_BANK_SIZES; - - if ( i >= GUEST_RAM_BANKS ) - goto fail; - - bank_start = bankbase[i]; - bank_size = banksize[i]; - } - - bank_size = MIN(bank_size, kinfo->unassigned_mem); - if ( !allocate_bank_memory(kinfo, gaddr_to_gfn(bank_start), bank_size) ) - goto fail; - } - - if ( kinfo->unassigned_mem ) - goto fail; - - for( i = 0; i < mem->nr_banks; i++ ) - { - printk(XENLOG_INFO "%pd BANK[%d] %#"PRIpaddr"-%#"PRIpaddr" (%ldMB)\n", - d, - i, - mem->bank[i].start, - mem->bank[i].start + mem->bank[i].size, - /* Don't want format this as PRIpaddr (16 digit hex) */ - (unsigned long)(mem->bank[i].size >> 20)); - } - - xfree(hwdom_free_mem); - return; - - fail: - panic("Failed to allocate requested domain memory." - /* Don't want format this as PRIpaddr (16 digit hex) */ - " %ldKB unallocated. Fix the VMs configurations.\n", - (unsigned long)kinfo->unassigned_mem >> 10); -} - static int __init handle_pci_range(const struct dt_device_node *dev, uint64_t addr, uint64_t len, void *data) { @@ -2056,75 +1729,6 @@ static int __init prepare_dtb_hwdom(struct domain *d, struct kernel_info *kinfo) return -EINVAL; } -static void __init dtb_load(struct kernel_info *kinfo) -{ - unsigned long left; - - printk("Loading %pd DTB to 0x%"PRIpaddr"-0x%"PRIpaddr"\n", - kinfo->d, kinfo->dtb_paddr, - kinfo->dtb_paddr + fdt_totalsize(kinfo->fdt)); - - left = copy_to_guest_phys_flush_dcache(kinfo->d, kinfo->dtb_paddr, - kinfo->fdt, - fdt_totalsize(kinfo->fdt)); - - if ( left != 0 ) - panic("Unable to copy the DTB to %pd memory (left = %lu bytes)\n", - kinfo->d, left); - xfree(kinfo->fdt); -} - -static void __init initrd_load(struct kernel_info *kinfo) -{ - const struct bootmodule *mod = kinfo->initrd_bootmodule; - paddr_t load_addr = kinfo->initrd_paddr; - paddr_t paddr, len; - int node; - int res; - __be32 val[2]; - __be32 *cellp; - void __iomem *initrd; - - if ( !mod || !mod->size ) - return; - - paddr = mod->start; - len = mod->size; - - printk("Loading %pd initrd from %"PRIpaddr" to 0x%"PRIpaddr"-0x%"PRIpaddr"\n", - kinfo->d, paddr, load_addr, load_addr + len); - - /* Fix up linux,initrd-start and linux,initrd-end in /chosen */ - node = fdt_path_offset(kinfo->fdt, "/chosen"); - if ( node < 0 ) - panic("Cannot find the /chosen node\n"); - - cellp = (__be32 *)val; - dt_set_cell(&cellp, ARRAY_SIZE(val), load_addr); - res = fdt_setprop_inplace(kinfo->fdt, node, "linux,initrd-start", - val, sizeof(val)); - if ( res ) - panic("Cannot fix up \"linux,initrd-start\" property\n"); - - cellp = (__be32 *)val; - dt_set_cell(&cellp, ARRAY_SIZE(val), load_addr + len); - res = fdt_setprop_inplace(kinfo->fdt, node, "linux,initrd-end", - val, sizeof(val)); - if ( res ) - panic("Cannot fix up \"linux,initrd-end\" property\n"); - - initrd = ioremap_wc(paddr, len); - if ( !initrd ) - panic("Unable to map the hwdom initrd\n"); - - res = copy_to_guest_phys_flush_dcache(kinfo->d, load_addr, - initrd, len); - if ( res != 0 ) - panic("Unable to copy the initrd in the hwdom memory\n"); - - iounmap(initrd); -} - /* * Allocate the event channel PPIs and setup the HVM_PARAM_CALLBACK_IRQ. * The allocated IRQ will be found in d->arch.evtchn_irq. @@ -2217,8 +1821,8 @@ int __init construct_domain(struct domain *d, struct kernel_info *kinfo) */ kernel_load(kinfo); /* initrd_load will fix up the fdt, so call it before dtb_load */ - initrd_load(kinfo); - dtb_load(kinfo); + initrd_load(kinfo, copy_to_guest_phys_flush_dcache); + dtb_load(kinfo, copy_to_guest_phys_flush_dcache); memset(regs, 0, sizeof(*regs)); diff --git a/xen/arch/arm/include/asm/Makefile b/xen/arch/arm/include/asm/Makefile index 9cec55606e..cda29dca6c 100644 --- a/xen/arch/arm/include/asm/Makefile +++ b/xen/arch/arm/include/asm/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only generic-y += altp2m.h generic-y += device.h +generic-y += domain-build.h generic-y += dom0less-build.h generic-y += hardirq.h generic-y += iocap.h diff --git a/xen/common/device-tree/Makefile b/xen/common/device-tree/Makefile index e88a4d5799..831b91399b 100644 --- a/xen/common/device-tree/Makefile +++ b/xen/common/device-tree/Makefile @@ -1,6 +1,7 @@ obj-y += bootfdt.init.o obj-y += bootinfo.init.o obj-y += device-tree.o +obj-$(CONFIG_DOMAIN_BUILD_HELPERS) += domain-build.o obj-$(CONFIG_DOM0LESS_BOOT) += dom0less-build.o obj-$(CONFIG_OVERLAY_DTB) += dt-overlay.o obj-y += intc.o diff --git a/xen/common/device-tree/domain-build.c b/xen/common/device-tree/domain-build.c new file mode 100644 index 0000000000..b4fb67ad9f --- /dev/null +++ b/xen/common/device-tree/domain-build.c @@ -0,0 +1,405 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +bool __init allocate_domheap_memory(struct domain *d, paddr_t tot_size, + alloc_domheap_mem_cb cb, void *extra) +{ + unsigned int max_order = UINT_MAX; + + while ( tot_size > 0 ) + { + unsigned int order = get_allocation_size(tot_size); + struct page_info *pg; + + order = min(max_order, order); + + pg = alloc_domheap_pages(d, order, 0); + if ( !pg ) + { + /* + * If we can't allocate one page, then it is unlikely to + * succeed in the next iteration. So bail out. + */ + if ( !order ) + return false; + + /* + * If we can't allocate memory with order, then it is + * unlikely to succeed in the next iteration. + * Record the order - 1 to avoid re-trying. + */ + max_order = order - 1; + continue; + } + + if ( !cb(d, pg, order, extra) ) + return false; + + tot_size -= (1ULL << (PAGE_SHIFT + order)); + } + + return true; +} + +static bool __init guest_map_pages(struct domain *d, struct page_info *pg, + unsigned int order, void *extra) +{ + gfn_t *sgfn = (gfn_t *)extra; + int res; + + BUG_ON(!sgfn); + res = guest_physmap_add_page(d, *sgfn, page_to_mfn(pg), order); + if ( res ) + { + dprintk(XENLOG_ERR, "Failed map pages to DOMU: %d", res); + return false; + } + + *sgfn = gfn_add(*sgfn, 1UL << order); + + return true; +} + +bool __init allocate_bank_memory(struct kernel_info *kinfo, gfn_t sgfn, + paddr_t tot_size) +{ + struct membanks *mem = kernel_info_get_mem(kinfo); + struct domain *d = kinfo->d; + struct membank *bank; + + /* + * allocate_bank_memory can be called with a tot_size of zero for + * the second memory bank. It is not an error and we can safely + * avoid creating a zero-size memory bank. + */ + if ( tot_size == 0 ) + return true; + + bank = &mem->bank[mem->nr_banks]; + bank->start = gfn_to_gaddr(sgfn); + bank->size = tot_size; + + /* + * Allocate pages from the heap until tot_size is zero and map them to the + * guest using guest_map_pages, passing the starting gfn as extra parameter + * for the map operation. + */ + if ( !allocate_domheap_memory(d, tot_size, guest_map_pages, &sgfn) ) + return false; + + mem->nr_banks++; + kinfo->unassigned_mem -= bank->size; + + return true; +} + +static int __init add_hwdom_free_regions(unsigned long s_gfn, + unsigned long e_gfn, void *data) +{ + struct membanks *free_regions = data; + paddr_t start, size; + paddr_t s = pfn_to_paddr(s_gfn); + paddr_t e = pfn_to_paddr(e_gfn); + unsigned int i, j; + + if ( free_regions->nr_banks >= free_regions->max_banks ) + return 0; + + /* + * Both start and size of the free region should be 2MB aligned to + * potentially allow superpage mapping. + */ + start = (s + SZ_2M - 1) & ~(SZ_2M - 1); + if ( start > e ) + return 0; + + /* + * e is actually "end-1" because it is called by rangeset functions + * which are inclusive of the last address. + */ + e += 1; + size = (e - start) & ~(SZ_2M - 1); + + /* Find the insert position (descending order). */ + for ( i = 0; i < free_regions->nr_banks ; i++ ) + if ( size > free_regions->bank[i].size ) + break; + + /* Move the other banks to make space. */ + for ( j = free_regions->nr_banks; j > i ; j-- ) + { + free_regions->bank[j].start = free_regions->bank[j - 1].start; + free_regions->bank[j].size = free_regions->bank[j - 1].size; + } + + free_regions->bank[i].start = start; + free_regions->bank[i].size = size; + free_regions->nr_banks++; + + return 0; +} + +/* + * Find unused regions of Host address space which can be exposed to domain + * using the host memory layout. In order to calculate regions we exclude every + * region passed in mem_banks from the Host RAM. + */ +int __init find_unallocated_memory(const struct kernel_info *kinfo, + const struct membanks *mem_banks[], + unsigned int nr_mem_banks, + struct membanks *free_regions, + int (*cb)(unsigned long s_gfn, + unsigned long e_gfn, + void *data)) +{ + const struct membanks *mem = bootinfo_get_mem(); + struct rangeset *unalloc_mem; + paddr_t start, end; + unsigned int i, j; + int res; + + ASSERT(domain_use_host_layout(kinfo->d)); + + unalloc_mem = rangeset_new(NULL, NULL, 0); + if ( !unalloc_mem ) + return -ENOMEM; + + /* Start with all available RAM */ + for ( i = 0; i < mem->nr_banks; i++ ) + { + start = mem->bank[i].start; + end = mem->bank[i].start + mem->bank[i].size; + res = rangeset_add_range(unalloc_mem, PFN_DOWN(start), + PFN_DOWN(end - 1)); + if ( res ) + { + printk(XENLOG_ERR "Failed to add: %#"PRIpaddr"->%#"PRIpaddr"\n", + start, end); + goto out; + } + } + + /* Remove all regions listed in mem_banks */ + for ( i = 0; i < nr_mem_banks; i++ ) + for ( j = 0; j < mem_banks[i]->nr_banks; j++ ) + { + start = mem_banks[i]->bank[j].start; + + /* Shared memory banks can contain INVALID_PADDR as start */ + if ( INVALID_PADDR == start ) + continue; + + end = mem_banks[i]->bank[j].start + mem_banks[i]->bank[j].size; + res = rangeset_remove_range(unalloc_mem, PFN_DOWN(start), + PFN_DOWN(end - 1)); + if ( res ) + { + printk(XENLOG_ERR + "Failed to add: %#"PRIpaddr"->%#"PRIpaddr", error %d\n", + start, end, res); + goto out; + } + } + + start = 0; + end = (1ULL << p2m_ipa_bits) - 1; + res = rangeset_report_ranges(unalloc_mem, PFN_DOWN(start), PFN_DOWN(end), + cb, free_regions); + if ( res ) + free_regions->nr_banks = 0; + else if ( !free_regions->nr_banks ) + res = -ENOENT; + +out: + rangeset_destroy(unalloc_mem); + + return res; +} + +void __init allocate_memory(struct domain *d, struct kernel_info *kinfo) +{ + struct membanks *mem = kernel_info_get_mem(kinfo); + unsigned int i, nr_banks = GUEST_RAM_BANKS; + struct membanks *hwdom_free_mem = NULL; + + printk(XENLOG_INFO "Allocating mappings totalling %ldMB for %pd:\n", + /* Don't want format this as PRIpaddr (16 digit hex) */ + (unsigned long)(kinfo->unassigned_mem >> 20), d); + + mem->nr_banks = 0; + /* + * Use host memory layout for hwdom. Only case for this is when LLC coloring + * is enabled. + */ + if ( is_hardware_domain(d) ) + { + struct membanks *gnttab = xzalloc_flex_struct(struct membanks, bank, 1); + /* + * Exclude the following regions: + * 1) Remove reserved memory + * 2) Grant table assigned to hwdom + */ + const struct membanks *mem_banks[] = { + bootinfo_get_reserved_mem(), + gnttab, + }; + + if ( !gnttab ) + goto fail; + + gnttab->nr_banks = 1; + gnttab->bank[0].start = kinfo->gnttab_start; + gnttab->bank[0].size = kinfo->gnttab_size; + + hwdom_free_mem = xzalloc_flex_struct(struct membanks, bank, + NR_MEM_BANKS); + if ( !hwdom_free_mem ) + goto fail; + + hwdom_free_mem->max_banks = NR_MEM_BANKS; + + if ( find_unallocated_memory(kinfo, mem_banks, ARRAY_SIZE(mem_banks), + hwdom_free_mem, add_hwdom_free_regions) ) + goto fail; + + nr_banks = hwdom_free_mem->nr_banks; + xfree(gnttab); + } + + for ( i = 0; kinfo->unassigned_mem > 0 && nr_banks > 0; i++, nr_banks-- ) + { + paddr_t bank_start, bank_size; + + if ( is_hardware_domain(d) ) + { + bank_start = hwdom_free_mem->bank[i].start; + bank_size = hwdom_free_mem->bank[i].size; + } + else + { + const uint64_t bankbase[] = GUEST_RAM_BANK_BASES; + const uint64_t banksize[] = GUEST_RAM_BANK_SIZES; + + if ( i >= GUEST_RAM_BANKS ) + goto fail; + + bank_start = bankbase[i]; + bank_size = banksize[i]; + } + + bank_size = MIN(bank_size, kinfo->unassigned_mem); + if ( !allocate_bank_memory(kinfo, gaddr_to_gfn(bank_start), bank_size) ) + goto fail; + } + + if ( kinfo->unassigned_mem ) + goto fail; + + for( i = 0; i < mem->nr_banks; i++ ) + { + printk(XENLOG_INFO "%pd BANK[%d] %#"PRIpaddr"-%#"PRIpaddr" (%ldMB)\n", + d, + i, + mem->bank[i].start, + mem->bank[i].start + mem->bank[i].size, + /* Don't want format this as PRIpaddr (16 digit hex) */ + (unsigned long)(mem->bank[i].size >> 20)); + } + + xfree(hwdom_free_mem); + return; + + fail: + panic("Failed to allocate requested domain memory." + /* Don't want format this as PRIpaddr (16 digit hex) */ + " %ldKB unallocated. Fix the VMs configurations.\n", + (unsigned long)kinfo->unassigned_mem >> 10); +} + +/* Copy data to guest physical address, then clean the region. */ +typedef unsigned long (*copy_to_guest_phys_cb)(struct domain *d, + paddr_t gpa, + void *buf, + unsigned int len); + +void __init dtb_load(struct kernel_info *kinfo, + copy_to_guest_phys_cb copy_to_guest) +{ + unsigned long left; + + printk("Loading %pd DTB to 0x%"PRIpaddr"-0x%"PRIpaddr"\n", + kinfo->d, kinfo->dtb_paddr, + kinfo->dtb_paddr + fdt_totalsize(kinfo->fdt)); + + left = copy_to_guest(kinfo->d, kinfo->dtb_paddr, + kinfo->fdt, + fdt_totalsize(kinfo->fdt)); + + if ( left != 0 ) + panic("Unable to copy the DTB to %pd memory (left = %lu bytes)\n", + kinfo->d, left); + xfree(kinfo->fdt); +} + +void __init initrd_load(struct kernel_info *kinfo, + copy_to_guest_phys_cb copy_to_guest) +{ + const struct bootmodule *mod = kinfo->initrd_bootmodule; + paddr_t load_addr = kinfo->initrd_paddr; + paddr_t paddr, len; + int node; + int res; + __be32 val[2]; + __be32 *cellp; + void __iomem *initrd; + + if ( !mod || !mod->size ) + return; + + paddr = mod->start; + len = mod->size; + + printk("Loading %pd initrd from %"PRIpaddr" to 0x%"PRIpaddr"-0x%"PRIpaddr"\n", + kinfo->d, paddr, load_addr, load_addr + len); + + /* Fix up linux,initrd-start and linux,initrd-end in /chosen */ + node = fdt_path_offset(kinfo->fdt, "/chosen"); + if ( node < 0 ) + panic("Cannot find the /chosen node\n"); + + cellp = (__be32 *)val; + dt_set_cell(&cellp, ARRAY_SIZE(val), load_addr); + res = fdt_setprop_inplace(kinfo->fdt, node, "linux,initrd-start", + val, sizeof(val)); + if ( res ) + panic("Cannot fix up \"linux,initrd-start\" property\n"); + + cellp = (__be32 *)val; + dt_set_cell(&cellp, ARRAY_SIZE(val), load_addr + len); + res = fdt_setprop_inplace(kinfo->fdt, node, "linux,initrd-end", + val, sizeof(val)); + if ( res ) + panic("Cannot fix up \"linux,initrd-end\" property\n"); + + initrd = ioremap_wc(paddr, len); + if ( !initrd ) + panic("Unable to map the hwdom initrd\n"); + + res = copy_to_guest(kinfo->d, load_addr, + initrd, len); + if ( res != 0 ) + panic("Unable to copy the initrd in the hwdom memory\n"); + + iounmap(initrd); +} diff --git a/xen/include/asm-generic/domain-build.h b/xen/include/asm-generic/domain-build.h index 237f94d0c3..4119d6e329 100644 --- a/xen/include/asm-generic/domain-build.h +++ b/xen/include/asm-generic/domain-build.h @@ -2,6 +2,7 @@ #ifndef __ASM_GENERIC_DOMAIN_BUILD_H__ #define __ASM_GENERIC_DOMAIN_BUILD_H__ +#include #include struct domain; @@ -26,7 +27,37 @@ int make_memory_node(const struct kernel_info *kinfo, int addrcells, int sizecells, const struct membanks *mem); int make_timer_node(const struct kernel_info *kinfo); -unsigned int get_allocation_size(paddr_t size); + +static inline int get_allocation_size(paddr_t size) +{ + /* + * get_order_from_bytes returns the order greater than or equal to + * the given size, but we need less than or equal. Adding one to + * the size pushes an evenly aligned size into the next order, so + * we can then unconditionally subtract 1 from the order which is + * returned. + */ + return get_order_from_bytes(size + 1) - 1; +} + +typedef unsigned long (*copy_to_guest_phys_cb)(struct domain *d, + paddr_t gpa, + void *buf, + unsigned int len); + +void initrd_load(struct kernel_info *kinfo, + copy_to_guest_phys_cb copy_to_guest); + +void dtb_load(struct kernel_info *kinfo, + copy_to_guest_phys_cb copy_to_guest); + +int find_unallocated_memory(const struct kernel_info *kinfo, + const struct membanks *mem_banks[], + unsigned int nr_mem_banks, + struct membanks *free_regions, + int (*cb)(unsigned long s_gfn, + unsigned long e_gfn, + void *data)); #endif /* __ASM_GENERIC_DOMAIN_BUILD_H__ */ From patchwork Wed Jan 8 11:13:11 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oleksii Kurochko X-Patchwork-Id: 13930561 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 49911E7719D for ; Wed, 8 Jan 2025 11:13:37 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.867144.1278645 (Exim 4.92) (envelope-from ) id 1tVU09-0003cO-0G; Wed, 08 Jan 2025 11:13:29 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 867144.1278645; Wed, 08 Jan 2025 11:13:28 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1tVU08-0003bz-Qv; Wed, 08 Jan 2025 11:13:28 +0000 Received: by outflank-mailman (input) for mailman id 867144; Wed, 08 Jan 2025 11:13:27 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1tVU07-0001rx-10 for xen-devel@lists.xenproject.org; Wed, 08 Jan 2025 11:13:27 +0000 Received: from mail-lj1-x236.google.com (mail-lj1-x236.google.com [2a00:1450:4864:20::236]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id 94216569-cdb1-11ef-99a4-01e77a169b0f; Wed, 08 Jan 2025 12:13:25 +0100 (CET) Received: by mail-lj1-x236.google.com with SMTP id 38308e7fff4ca-30229d5b229so172492851fa.0 for ; Wed, 08 Jan 2025 03:13:25 -0800 (PST) Received: from fedora.. ([94.75.70.14]) by smtp.gmail.com with ESMTPSA id 38308e7fff4ca-3045ad99d11sm67292171fa.33.2025.01.08.03.13.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 08 Jan 2025 03:13:22 -0800 (PST) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 94216569-cdb1-11ef-99a4-01e77a169b0f DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1736334804; x=1736939604; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=+MTqGiPQ/jA03tCZq1CRsGrbRyrze3+bn/uXhnqO+fM=; b=OAe50i/Q/20TEGkopy1PIop/MxRAJVFee7LBczppGtEX3RxJ8Q3j7WQ9bNXsp0MMl1 qdMk5gQrNHl15E/VxU6qWho/lwcU9PnjWLLafQIU+R65LwoeM5nCthqPKXizs9ys/aM1 7pQVQ6iyeKqwPCw8NqxRR27EpJenYmc+rAgTjs4fx2+6J5zf1oBGSPU4XbQjNtGxNmuf 2UBuDfOW7obTguJ8fgRuSx4jpWaC5CjUyQdDlX8mYpfJcn3+EjFU/p6oHbX6tUBFjEFK GVxrYC6kHpe8HgoQBZ+Bu2QNdrwEXBbLLJlrZQ7/tgHF0PYzNds8SrA4H5jVQfj5Rr/B 89jw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1736334804; x=1736939604; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=+MTqGiPQ/jA03tCZq1CRsGrbRyrze3+bn/uXhnqO+fM=; b=clav0JC1QfXVE1w1WyVodVJoPmAiwx5AgN9rolsz5iKlupqrOWSciaNvuD/YY+0Mzm VjegiC7oF/XqhyGgC4N+LHLk1qdBTbNauEzbf59m4xCsjJvrwQHkaBkCa24CEucfF6Ke FclW4aK4Si3cXmFY5tgZ3s/cz7epsmlcqptyEcd09WD90GJStAaGie8SxuO9wQun3ZWF MkTBydq2jYbxMNeuOqFhLdPum5BqYfpSpFUU1jww2udt+tl9gbMM7+vWs+bR/9SwjVvN 5e9bauJg+v/vIIXvcMEfjvnxTPqbpO2qAvNhlgHKgZ27aHowBbt2GF7ASp5glCD4wAx5 t6kg== X-Gm-Message-State: AOJu0YzfU7ba2w6l5uBt6lWddXCFbK7mxdbnUXT2lG2YK4axTIAG5uB2 53s716WWklMDvqU15yKz1NQyHP9ttfQ11/AymoOqj1fHmjO7zKOjjAMm0IFj X-Gm-Gg: ASbGncvl8dZphYJRN09kc//qaz5ct8RUa6Gm5tQJQC8zfGDF3Ly4v9d994xnjOyJStM 3+5teguAuwzCtxs/pc0lzckMeFpwIP95AIBf7bFSHH9Fr0lK7Qqys7KEkIo5KDBQsZFeMpmvPM0 bNe2cg1dS+RoNLtfrtSxu5B8lcMFYrJnjGqZZgGoMGaAhKzpwh6HAU2t7l6n1rG0gapuPDOfOtg N/pI1wZepBFSCE2+WSvJViudsZ2DzRHzEvFyw9tpWWai0o62FPBXpduNw== X-Google-Smtp-Source: AGHT+IH6AWgeaLtK63AplG5laI6gBLt4hdb4gnLEWD21Ye6lpR+jTdy1iSbPx8iVl6a2e4fLs1B4Ag== X-Received: by 2002:a05:651c:b0c:b0:2ff:d83d:9155 with SMTP id 38308e7fff4ca-305f4626539mr6587071fa.27.1736334803490; Wed, 08 Jan 2025 03:13:23 -0800 (PST) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Oleksii Kurochko , Stefano Stabellini , Julien Grall , Bertrand Marquis , Michal Orzel , Volodymyr Babchuk , Andrew Cooper , Anthony PERARD , Jan Beulich , =?utf-8?q?Roger_Pau_Monn=C3=A9?= Subject: [PATCH v1 9/9] xen/common: dom0less: introduce common dom0less-build.c Date: Wed, 8 Jan 2025 12:13:11 +0100 Message-ID: <007095f12bfd803df504f10249b5b497bd0529a1.1736334615.git.oleksii.kurochko@gmail.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: References: MIME-Version: 1.0 Part of Arm's dom0less-build.c could be common between architectures which are using device tree files to create guest domains. Thereby move some parts of Arm's dom0less-build.c to common code with minor changes. As a part of theses changes the following changes are introduced: - Introduce make_arch_nodes() to cover arch-specific nodes. For example, in case of Arm, it is PSCI and vpl011 nodes. - Introduce set_domain_type() to abstract a way how setting of domain type happens. For example, RISC-V won't have this member of arch_domain structure as vCPUs will always have the same bitness as hypervisor. In case of Arm, it is possible that Arm64 could create 32-bit and 64-bit domains. - Introduce init_vuart() to cover details of virtual uart initialization. - Introduce init_intc_phandle() to cover some details of interrupt controller phandle initialization. As an example, RISC-V could have different name for interrupt controller node ( APLIC, PLIC, IMSIC, etc ) but the code in domain_handle_dtb_bootmodule() could handle only one interrupt controller node name. - s/make_gic_domU_node/make_intc_domU_node as GIC is Arm specific naming and add prototype of make_intc_domU_node() to dom0less-build.h The following functions are moved to xen/common/device-tree: - Functions which are moved as is: - domain_p2m_pages(). - handle_passthrough_prop(). - handle_prop_pfdt(). - scan_pfdt_node(). - check_partial_fdt(). - Functions which are moved with some minor changes: - alloc_xenstore_evtchn(): - ifdef-ing by CONFIG_HVM accesses to hvm.params. - prepare_dtb_domU(): - ifdef-ing access to gnttab_{start,size} by CONFIG_GRANT_TABLE. - s/make_gic_domU_node/make_intc_domU_node. - Add call of make_arch_nodes(). - domain_handle_dtb_bootmodule(): - hide details of interrupt controller phandle initialization by calling init_intc_phandle(). - Update the comment above init_intc_phandle(): s/gic/interrupt controller. - construct_domU(): - ifdef-ing by CONFIG_HVM accesses to hvm.params. - Call init_vuart() to hide Arm's vpl011_init() details there. - Add call of set_domain_type() instead of setting kinfo->arch.type explicitly. Signed-off-by: Oleksii Kurochko --- xen/arch/arm/dom0less-build.c | 569 ++--------------------- xen/common/device-tree/dom0less-build.c | 559 ++++++++++++++++++++++ xen/include/asm-generic/dom0less-build.h | 14 + 3 files changed, 608 insertions(+), 534 deletions(-) diff --git a/xen/arch/arm/dom0less-build.c b/xen/arch/arm/dom0less-build.c index 259285ddda..872a9437da 100644 --- a/xen/arch/arm/dom0less-build.c +++ b/xen/arch/arm/dom0less-build.c @@ -143,7 +143,7 @@ static int __init make_gicv3_domU_node(struct kernel_info *kinfo) } #endif -static int __init make_gic_domU_node(struct kernel_info *kinfo) +int __init make_intc_domU_node(struct kernel_info *kinfo) { switch ( kinfo->d->arch.vgic.version ) { @@ -209,577 +209,62 @@ static int __init make_vpl011_uart_node(struct kernel_info *kinfo) } #endif -/* - * Scan device tree properties for passthrough specific information. - * Returns < 0 on error - * 0 on success - */ -static int __init handle_passthrough_prop(struct kernel_info *kinfo, - const struct fdt_property *xen_reg, - const struct fdt_property *xen_path, - bool xen_force, - uint32_t address_cells, - uint32_t size_cells) -{ - const __be32 *cell; - unsigned int i, len; - struct dt_device_node *node; - int res; - paddr_t mstart, size, gstart; - - /* xen,reg specifies where to map the MMIO region */ - cell = (const __be32 *)xen_reg->data; - len = fdt32_to_cpu(xen_reg->len) / ((address_cells * 2 + size_cells) * - sizeof(uint32_t)); - - for ( i = 0; i < len; i++ ) - { - device_tree_get_reg(&cell, address_cells, size_cells, - &mstart, &size); - gstart = dt_next_cell(address_cells, &cell); - - if ( gstart & ~PAGE_MASK || mstart & ~PAGE_MASK || size & ~PAGE_MASK ) - { - printk(XENLOG_ERR - "DomU passthrough config has not page aligned addresses/sizes\n"); - return -EINVAL; - } - - res = iomem_permit_access(kinfo->d, paddr_to_pfn(mstart), - paddr_to_pfn(PAGE_ALIGN(mstart + size - 1))); - if ( res ) - { - printk(XENLOG_ERR "Unable to permit to dom%d access to" - " 0x%"PRIpaddr" - 0x%"PRIpaddr"\n", - kinfo->d->domain_id, - mstart & PAGE_MASK, PAGE_ALIGN(mstart + size) - 1); - return res; - } - - res = map_regions_p2mt(kinfo->d, - gaddr_to_gfn(gstart), - PFN_DOWN(size), - maddr_to_mfn(mstart), - p2m_mmio_direct_dev); - if ( res < 0 ) - { - printk(XENLOG_ERR - "Failed to map %"PRIpaddr" to the guest at%"PRIpaddr"\n", - mstart, gstart); - return -EFAULT; - } - } - - /* - * If xen_force, we let the user assign a MMIO region with no - * associated path. - */ - if ( xen_path == NULL ) - return xen_force ? 0 : -EINVAL; - - /* - * xen,path specifies the corresponding node in the host DT. - * Both interrupt mappings and IOMMU settings are based on it, - * as they are done based on the corresponding host DT node. - */ - node = dt_find_node_by_path(xen_path->data); - if ( node == NULL ) - { - printk(XENLOG_ERR "Couldn't find node %s in host_dt!\n", - xen_path->data); - return -EINVAL; - } - - res = map_device_irqs_to_domain(kinfo->d, node, true, NULL); - if ( res < 0 ) - return res; - - res = iommu_add_dt_device(node); - if ( res < 0 ) - return res; - - /* If xen_force, we allow assignment of devices without IOMMU protection. */ - if ( xen_force && !dt_device_is_protected(node) ) - return 0; - - return iommu_assign_dt_device(kinfo->d, node); -} - -static int __init handle_prop_pfdt(struct kernel_info *kinfo, - const void *pfdt, int nodeoff, - uint32_t address_cells, uint32_t size_cells, - bool scan_passthrough_prop) -{ - void *fdt = kinfo->fdt; - int propoff, nameoff, res; - const struct fdt_property *prop, *xen_reg = NULL, *xen_path = NULL; - const char *name; - bool found, xen_force = false; - - for ( propoff = fdt_first_property_offset(pfdt, nodeoff); - propoff >= 0; - propoff = fdt_next_property_offset(pfdt, propoff) ) - { - if ( !(prop = fdt_get_property_by_offset(pfdt, propoff, NULL)) ) - return -FDT_ERR_INTERNAL; - - found = false; - nameoff = fdt32_to_cpu(prop->nameoff); - name = fdt_string(pfdt, nameoff); - - if ( scan_passthrough_prop ) - { - if ( dt_prop_cmp("xen,reg", name) == 0 ) - { - xen_reg = prop; - found = true; - } - else if ( dt_prop_cmp("xen,path", name) == 0 ) - { - xen_path = prop; - found = true; - } - else if ( dt_prop_cmp("xen,force-assign-without-iommu", - name) == 0 ) - { - xen_force = true; - found = true; - } - } - - /* - * Copy properties other than the ones above: xen,reg, xen,path, - * and xen,force-assign-without-iommu. - */ - if ( !found ) - { - res = fdt_property(fdt, name, prop->data, fdt32_to_cpu(prop->len)); - if ( res ) - return res; - } - } - - /* - * Only handle passthrough properties if both xen,reg and xen,path - * are present, or if xen,force-assign-without-iommu is specified. - */ - if ( xen_reg != NULL && (xen_path != NULL || xen_force) ) - { - res = handle_passthrough_prop(kinfo, xen_reg, xen_path, xen_force, - address_cells, size_cells); - if ( res < 0 ) - { - printk(XENLOG_ERR "Failed to assign device to %pd\n", kinfo->d); - return res; - } - } - else if ( (xen_path && !xen_reg) || (xen_reg && !xen_path && !xen_force) ) - { - printk(XENLOG_ERR "xen,reg or xen,path missing for %pd\n", - kinfo->d); - return -EINVAL; - } - - /* FDT_ERR_NOTFOUND => There is no more properties for this node */ - return ( propoff != -FDT_ERR_NOTFOUND ) ? propoff : 0; -} - -static int __init scan_pfdt_node(struct kernel_info *kinfo, const void *pfdt, - int nodeoff, - uint32_t address_cells, uint32_t size_cells, - bool scan_passthrough_prop) -{ - int rc = 0; - void *fdt = kinfo->fdt; - int node_next; - - rc = fdt_begin_node(fdt, fdt_get_name(pfdt, nodeoff, NULL)); - if ( rc ) - return rc; - - rc = handle_prop_pfdt(kinfo, pfdt, nodeoff, address_cells, size_cells, - scan_passthrough_prop); - if ( rc ) - return rc; - - address_cells = device_tree_get_u32(pfdt, nodeoff, "#address-cells", - DT_ROOT_NODE_ADDR_CELLS_DEFAULT); - size_cells = device_tree_get_u32(pfdt, nodeoff, "#size-cells", - DT_ROOT_NODE_SIZE_CELLS_DEFAULT); - - node_next = fdt_first_subnode(pfdt, nodeoff); - while ( node_next > 0 ) - { - rc = scan_pfdt_node(kinfo, pfdt, node_next, address_cells, size_cells, - scan_passthrough_prop); - if ( rc ) - return rc; - - node_next = fdt_next_subnode(pfdt, node_next); - } - - return fdt_end_node(fdt); -} - -static int __init check_partial_fdt(void *pfdt, size_t size) -{ - int res; - - if ( fdt_magic(pfdt) != FDT_MAGIC ) - { - dprintk(XENLOG_ERR, "Partial FDT is not a valid Flat Device Tree"); - return -EINVAL; - } - - res = fdt_check_header(pfdt); - if ( res ) - { - dprintk(XENLOG_ERR, "Failed to check the partial FDT (%d)", res); - return -EINVAL; - } - - if ( fdt_totalsize(pfdt) > size ) - { - dprintk(XENLOG_ERR, "Partial FDT totalsize is too big"); - return -EINVAL; - } - - return 0; -} - -static int __init domain_handle_dtb_bootmodule(struct domain *d, - struct kernel_info *kinfo) +int __init make_arch_nodes(struct kernel_info *kinfo) { - void *pfdt; - int res, node_next; - - pfdt = ioremap_cache(kinfo->dtb_bootmodule->start, - kinfo->dtb_bootmodule->size); - if ( pfdt == NULL ) - return -EFAULT; - - res = check_partial_fdt(pfdt, kinfo->dtb_bootmodule->size); - if ( res < 0 ) - goto out; - - for ( node_next = fdt_first_subnode(pfdt, 0); - node_next > 0; - node_next = fdt_next_subnode(pfdt, node_next) ) - { - const char *name = fdt_get_name(pfdt, node_next, NULL); - - if ( name == NULL ) - continue; - - /* - * Only scan /gic /aliases /passthrough, ignore the rest. - * They don't have to be parsed in order. - * - * Take the GIC phandle value from the special /gic node in the - * DTB fragment. - */ - if ( dt_node_cmp(name, "gic") == 0 ) - { - uint32_t phandle_intc = fdt_get_phandle(pfdt, node_next); - - if ( phandle_intc != 0 ) - kinfo->phandle_intc = phandle_intc; - continue; - } - - if ( dt_node_cmp(name, "aliases") == 0 ) - { - res = scan_pfdt_node(kinfo, pfdt, node_next, - DT_ROOT_NODE_ADDR_CELLS_DEFAULT, - DT_ROOT_NODE_SIZE_CELLS_DEFAULT, - false); - if ( res ) - goto out; - continue; - } - if ( dt_node_cmp(name, "passthrough") == 0 ) - { - res = scan_pfdt_node(kinfo, pfdt, node_next, - DT_ROOT_NODE_ADDR_CELLS_DEFAULT, - DT_ROOT_NODE_SIZE_CELLS_DEFAULT, - true); - if ( res ) - goto out; - continue; - } - } - - out: - iounmap(pfdt); - - return res; -} - -/* - * The max size for DT is 2MB. However, the generated DT is small (not including - * domU passthrough DT nodes whose size we account separately), 4KB are enough - * for now, but we might have to increase it in the future. - */ -#define DOMU_DTB_SIZE 4096 -static int __init prepare_dtb_domU(struct domain *d, struct kernel_info *kinfo) -{ - int addrcells, sizecells; - int ret, fdt_size = DOMU_DTB_SIZE; - - kinfo->phandle_intc = GUEST_PHANDLE_GIC; - kinfo->gnttab_start = GUEST_GNTTAB_BASE; - kinfo->gnttab_size = GUEST_GNTTAB_SIZE; - - addrcells = GUEST_ROOT_ADDRESS_CELLS; - sizecells = GUEST_ROOT_SIZE_CELLS; - - /* Account for domU passthrough DT size */ - if ( kinfo->dtb_bootmodule ) - fdt_size += kinfo->dtb_bootmodule->size; - - /* Cap to max DT size if needed */ - fdt_size = min(fdt_size, SZ_2M); - - kinfo->fdt = xmalloc_bytes(fdt_size); - if ( kinfo->fdt == NULL ) - return -ENOMEM; - - ret = fdt_create(kinfo->fdt, fdt_size); - if ( ret < 0 ) - goto err; - - ret = fdt_finish_reservemap(kinfo->fdt); - if ( ret < 0 ) - goto err; - - ret = fdt_begin_node(kinfo->fdt, ""); - if ( ret < 0 ) - goto err; - - ret = fdt_property_cell(kinfo->fdt, "#address-cells", addrcells); - if ( ret ) - goto err; - - ret = fdt_property_cell(kinfo->fdt, "#size-cells", sizecells); - if ( ret ) - goto err; - - ret = make_chosen_node(kinfo); - if ( ret ) - goto err; + int ret; ret = make_psci_node(kinfo->fdt); if ( ret ) - goto err; - - ret = make_cpus_node(d, kinfo->fdt); - if ( ret ) - goto err; - - ret = make_memory_node(kinfo, addrcells, sizecells, - kernel_info_get_mem(kinfo)); - if ( ret ) - goto err; - - ret = make_resv_memory_node(kinfo, addrcells, sizecells); - if ( ret ) - goto err; - - /* - * domain_handle_dtb_bootmodule has to be called before the rest of - * the device tree is generated because it depends on the value of - * the field phandle_intc. - */ - if ( kinfo->dtb_bootmodule ) - { - ret = domain_handle_dtb_bootmodule(d, kinfo); - if ( ret ) - goto err; - } - - ret = make_gic_domU_node(kinfo); - if ( ret ) - goto err; - - ret = make_timer_node(kinfo); - if ( ret ) - goto err; + return -EINVAL; if ( kinfo->vuart ) { - ret = -EINVAL; #ifdef CONFIG_SBSA_VUART_CONSOLE ret = make_vpl011_uart_node(kinfo); #endif if ( ret ) - goto err; - } - - if ( kinfo->dom0less_feature & DOM0LESS_ENHANCED_NO_XS ) - { - ret = make_hypervisor_node(d, kinfo, addrcells, sizecells); - if ( ret ) - goto err; + return -EINVAL; } - ret = fdt_end_node(kinfo->fdt); - if ( ret < 0 ) - goto err; - - ret = fdt_finish(kinfo->fdt); - if ( ret < 0 ) - goto err; - return 0; - - err: - printk("Device tree generation failed (%d).\n", ret); - xfree(kinfo->fdt); - - return -EINVAL; } -static unsigned long __init domain_p2m_pages(unsigned long maxmem_kb, - unsigned int smp_cpus) +/* TODO: make arch.type generic ? */ +#ifdef CONFIG_ARM_64 +void __init set_domain_type(struct domain *d, struct kernel_info *kinfo) { - /* - * Keep in sync with libxl__get_required_paging_memory(). - * 256 pages (1MB) per vcpu, plus 1 page per MiB of RAM for the P2M map, - * plus 128 pages to cover extended regions. - */ - unsigned long memkb = 4 * (256 * smp_cpus + (maxmem_kb / 1024) + 128); - - BUILD_BUG_ON(PAGE_SIZE != SZ_4K); - - return DIV_ROUND_UP(memkb, 1024) << (20 - PAGE_SHIFT); + /* type must be set before allocate memory */ + d->arch.type = kinfo->arch.type; } - -static int __init alloc_xenstore_evtchn(struct domain *d) +#else +void __init set_domain_type(struct domain *d, struct kernel_info *kinfo) { - evtchn_alloc_unbound_t alloc; - int rc; - - alloc.dom = d->domain_id; - alloc.remote_dom = hardware_domain->domain_id; - rc = evtchn_alloc_unbound(&alloc, 0); - if ( rc ) - { - printk("Failed allocating event channel for domain\n"); - return rc; - } - - d->arch.hvm.params[HVM_PARAM_STORE_EVTCHN] = alloc.port; - - return 0; + /* Nothing to do */ } +#endif -int __init construct_domU(struct domain *d, - const struct dt_device_node *node) +int __init init_vuart(struct domain *d, struct kernel_info *kinfo, + const struct dt_device_node *node) { - struct kernel_info kinfo = KERNEL_INFO_INIT; - const char *dom0less_enhanced; - int rc; - u64 mem; - u32 p2m_mem_mb; - unsigned long p2m_pages; - - rc = dt_property_read_u64(node, "memory", &mem); - if ( !rc ) - { - printk("Error building DomU: cannot read \"memory\" property\n"); - return -EINVAL; - } - kinfo.unassigned_mem = (paddr_t)mem * SZ_1K; - - rc = dt_property_read_u32(node, "xen,domain-p2m-mem-mb", &p2m_mem_mb); - /* If xen,domain-p2m-mem-mb is not specified, use the default value. */ - p2m_pages = rc ? - p2m_mem_mb << (20 - PAGE_SHIFT) : - domain_p2m_pages(mem, d->max_vcpus); - - spin_lock(&d->arch.paging.lock); - rc = p2m_set_allocation(d, p2m_pages, NULL); - spin_unlock(&d->arch.paging.lock); - if ( rc != 0 ) - return rc; - - printk("*** LOADING DOMU cpus=%u memory=%#"PRIx64"KB ***\n", - d->max_vcpus, mem); - - kinfo.vuart = dt_property_read_bool(node, "vpl011"); - - rc = dt_property_read_string(node, "xen,enhanced", &dom0less_enhanced); - if ( rc == -EILSEQ || - rc == -ENODATA || - (rc == 0 && !strcmp(dom0less_enhanced, "enabled")) ) - { - if ( hardware_domain ) - kinfo.dom0less_feature = DOM0LESS_ENHANCED; - else - panic("At the moment, Xenstore support requires dom0 to be present\n"); - } - else if ( rc == 0 && !strcmp(dom0less_enhanced, "no-xenstore") ) - kinfo.dom0less_feature = DOM0LESS_ENHANCED_NO_XS; - - if ( vcpu_create(d, 0) == NULL ) - return -ENOMEM; - - d->max_pages = ((paddr_t)mem * SZ_1K) >> PAGE_SHIFT; - - kinfo.d = d; - - rc = kernel_probe(&kinfo, node); - if ( rc < 0 ) - return rc; - -#ifdef CONFIG_ARM_64 - /* type must be set before allocate memory */ - d->arch.type = kinfo.arch.type; -#endif - if ( !dt_find_property(node, "xen,static-mem", NULL) ) - allocate_memory(d, &kinfo); - else if ( !is_domain_direct_mapped(d) ) - allocate_static_memory(d, &kinfo, node); - else - assign_static_memory_11(d, &kinfo, node); + int rc = 0; - rc = process_shm(d, &kinfo, node); - if ( rc < 0 ) - return rc; + kinfo->vuart = dt_property_read_bool(node, "vpl011"); /* * Base address and irq number are needed when creating vpl011 device * tree node in prepare_dtb_domU, so initialization on related variables * shall be done first. */ - if ( kinfo.vuart ) + if ( kinfo->vuart ) { rc = domain_vpl011_init(d, NULL); if ( rc < 0 ) return rc; } - rc = prepare_dtb_domU(d, &kinfo); - if ( rc < 0 ) - return rc; - - rc = construct_domain(d, &kinfo); - if ( rc < 0 ) - return rc; - - if ( kinfo.dom0less_feature & DOM0LESS_XENSTORE ) - { - ASSERT(hardware_domain); - rc = alloc_xenstore_evtchn(d); - if ( rc < 0 ) - return rc; - d->arch.hvm.params[HVM_PARAM_STORE_PFN] = ~0ULL; - } - return rc; } - struct xen_domctl_createdomain __init arch_xen_domctl_createdomain(void) { struct xen_domctl_createdomain d_cfg = { @@ -868,6 +353,22 @@ void __init arch_create_domus(struct dt_device_node *node, } } +int __init init_intc_phandle(struct kernel_info *kinfo, const char *name, + const int node_next, const void *pfdt) +{ + if ( dt_node_cmp(name, "gic") == 0 ) + { + uint32_t phandle_intc = fdt_get_phandle(pfdt, node_next); + + if ( phandle_intc != 0 ) + kinfo->phandle_intc = phandle_intc; + + return 0; + } + + return 1; +} + /* * Local variables: * mode: C diff --git a/xen/common/device-tree/dom0less-build.c b/xen/common/device-tree/dom0less-build.c index 19bfa5e005..509f825ce6 100644 --- a/xen/common/device-tree/dom0less-build.c +++ b/xen/common/device-tree/dom0less-build.c @@ -3,17 +3,26 @@ #include #include #include +#include #include +#include #include +#include #include +#include #include #include #include +#include #include +#include #include +#include #include +#include +#include bool __init is_dom0less_mode(void) { @@ -159,3 +168,553 @@ void __init create_domUs(void) dt_node_name(node), rc); } } + +/* + * Scan device tree properties for passthrough specific information. + * Returns < 0 on error + * 0 on success + */ +static int __init handle_passthrough_prop(struct kernel_info *kinfo, + const struct fdt_property *xen_reg, + const struct fdt_property *xen_path, + bool xen_force, + uint32_t address_cells, + uint32_t size_cells) +{ + const __be32 *cell; + unsigned int i, len; + struct dt_device_node *node; + int res; + paddr_t mstart, size, gstart; + + /* xen,reg specifies where to map the MMIO region */ + cell = (const __be32 *)xen_reg->data; + len = fdt32_to_cpu(xen_reg->len) / ((address_cells * 2 + size_cells) * + sizeof(uint32_t)); + + for ( i = 0; i < len; i++ ) + { + device_tree_get_reg(&cell, address_cells, size_cells, + &mstart, &size); + gstart = dt_next_cell(address_cells, &cell); + + if ( gstart & ~PAGE_MASK || mstart & ~PAGE_MASK || size & ~PAGE_MASK ) + { + printk(XENLOG_ERR + "DomU passthrough config has not page aligned addresses/sizes\n"); + return -EINVAL; + } + + res = iomem_permit_access(kinfo->d, paddr_to_pfn(mstart), + paddr_to_pfn(PAGE_ALIGN(mstart + size - 1))); + if ( res ) + { + printk(XENLOG_ERR "Unable to permit to dom%d access to" + " 0x%"PRIpaddr" - 0x%"PRIpaddr"\n", + kinfo->d->domain_id, + mstart & PAGE_MASK, PAGE_ALIGN(mstart + size) - 1); + return res; + } + + res = map_regions_p2mt(kinfo->d, + gaddr_to_gfn(gstart), + PFN_DOWN(size), + maddr_to_mfn(mstart), + p2m_mmio_direct_dev); + if ( res < 0 ) + { + printk(XENLOG_ERR + "Failed to map %"PRIpaddr" to the guest at%"PRIpaddr"\n", + mstart, gstart); + return -EFAULT; + } + } + + /* + * If xen_force, we let the user assign a MMIO region with no + * associated path. + */ + if ( xen_path == NULL ) + return xen_force ? 0 : -EINVAL; + + /* + * xen,path specifies the corresponding node in the host DT. + * Both interrupt mappings and IOMMU settings are based on it, + * as they are done based on the corresponding host DT node. + */ + node = dt_find_node_by_path(xen_path->data); + if ( node == NULL ) + { + printk(XENLOG_ERR "Couldn't find node %s in host_dt!\n", + xen_path->data); + return -EINVAL; + } + + res = map_device_irqs_to_domain(kinfo->d, node, true, NULL); + if ( res < 0 ) + return res; + + res = iommu_add_dt_device(node); + if ( res < 0 ) + return res; + + /* If xen_force, we allow assignment of devices without IOMMU protection. */ + if ( xen_force && !dt_device_is_protected(node) ) + return 0; + + return iommu_assign_dt_device(kinfo->d, node); +} + +static int __init handle_prop_pfdt(struct kernel_info *kinfo, + const void *pfdt, int nodeoff, + uint32_t address_cells, uint32_t size_cells, + bool scan_passthrough_prop) +{ + void *fdt = kinfo->fdt; + int propoff, nameoff, res; + const struct fdt_property *prop, *xen_reg = NULL, *xen_path = NULL; + const char *name; + bool found, xen_force = false; + + for ( propoff = fdt_first_property_offset(pfdt, nodeoff); + propoff >= 0; + propoff = fdt_next_property_offset(pfdt, propoff) ) + { + if ( !(prop = fdt_get_property_by_offset(pfdt, propoff, NULL)) ) + return -FDT_ERR_INTERNAL; + + found = false; + nameoff = fdt32_to_cpu(prop->nameoff); + name = fdt_string(pfdt, nameoff); + + if ( scan_passthrough_prop ) + { + if ( dt_prop_cmp("xen,reg", name) == 0 ) + { + xen_reg = prop; + found = true; + } + else if ( dt_prop_cmp("xen,path", name) == 0 ) + { + xen_path = prop; + found = true; + } + else if ( dt_prop_cmp("xen,force-assign-without-iommu", + name) == 0 ) + { + xen_force = true; + found = true; + } + } + + /* + * Copy properties other than the ones above: xen,reg, xen,path, + * and xen,force-assign-without-iommu. + */ + if ( !found ) + { + res = fdt_property(fdt, name, prop->data, fdt32_to_cpu(prop->len)); + if ( res ) + return res; + } + } + + /* + * Only handle passthrough properties if both xen,reg and xen,path + * are present, or if xen,force-assign-without-iommu is specified. + */ + if ( xen_reg != NULL && (xen_path != NULL || xen_force) ) + { + res = handle_passthrough_prop(kinfo, xen_reg, xen_path, xen_force, + address_cells, size_cells); + if ( res < 0 ) + { + printk(XENLOG_ERR "Failed to assign device to %pd\n", kinfo->d); + return res; + } + } + else if ( (xen_path && !xen_reg) || (xen_reg && !xen_path && !xen_force) ) + { + printk(XENLOG_ERR "xen,reg or xen,path missing for %pd\n", + kinfo->d); + return -EINVAL; + } + + /* FDT_ERR_NOTFOUND => There is no more properties for this node */ + return ( propoff != -FDT_ERR_NOTFOUND ) ? propoff : 0; +} + +static int __init scan_pfdt_node(struct kernel_info *kinfo, const void *pfdt, + int nodeoff, + uint32_t address_cells, uint32_t size_cells, + bool scan_passthrough_prop) +{ + int rc = 0; + void *fdt = kinfo->fdt; + int node_next; + + rc = fdt_begin_node(fdt, fdt_get_name(pfdt, nodeoff, NULL)); + if ( rc ) + return rc; + + rc = handle_prop_pfdt(kinfo, pfdt, nodeoff, address_cells, size_cells, + scan_passthrough_prop); + if ( rc ) + return rc; + + address_cells = device_tree_get_u32(pfdt, nodeoff, "#address-cells", + DT_ROOT_NODE_ADDR_CELLS_DEFAULT); + size_cells = device_tree_get_u32(pfdt, nodeoff, "#size-cells", + DT_ROOT_NODE_SIZE_CELLS_DEFAULT); + + node_next = fdt_first_subnode(pfdt, nodeoff); + while ( node_next > 0 ) + { + rc = scan_pfdt_node(kinfo, pfdt, node_next, address_cells, size_cells, + scan_passthrough_prop); + if ( rc ) + return rc; + + node_next = fdt_next_subnode(pfdt, node_next); + } + + return fdt_end_node(fdt); +} + +static int __init check_partial_fdt(void *pfdt, size_t size) +{ + int res; + + if ( fdt_magic(pfdt) != FDT_MAGIC ) + { + dprintk(XENLOG_ERR, "Partial FDT is not a valid Flat Device Tree"); + return -EINVAL; + } + + res = fdt_check_header(pfdt); + if ( res ) + { + dprintk(XENLOG_ERR, "Failed to check the partial FDT (%d)", res); + return -EINVAL; + } + + if ( fdt_totalsize(pfdt) > size ) + { + dprintk(XENLOG_ERR, "Partial FDT totalsize is too big"); + return -EINVAL; + } + + return 0; +} + +static int __init domain_handle_dtb_bootmodule(struct domain *d, + struct kernel_info *kinfo) +{ + void *pfdt; + int res, node_next; + + pfdt = ioremap_cache(kinfo->dtb_bootmodule->start, + kinfo->dtb_bootmodule->size); + if ( pfdt == NULL ) + return -EFAULT; + + res = check_partial_fdt(pfdt, kinfo->dtb_bootmodule->size); + if ( res < 0 ) + goto out; + + for ( node_next = fdt_first_subnode(pfdt, 0); + node_next > 0; + node_next = fdt_next_subnode(pfdt, node_next) ) + { + const char *name = fdt_get_name(pfdt, node_next, NULL); + + if ( name == NULL ) + continue; + + /* + * Only scan /$(interrupt_controller) /aliases /passthrough, + * ignore the rest. + * They don't have to be parsed in order. + * + * Take the interrupt controller phandle value from the special + * interrupt controller node in the DTB fragment. + */ + if ( init_intc_phandle(kinfo, name, node_next, pfdt) == 0 ) + continue; + + if ( dt_node_cmp(name, "aliases") == 0 ) + { + res = scan_pfdt_node(kinfo, pfdt, node_next, + DT_ROOT_NODE_ADDR_CELLS_DEFAULT, + DT_ROOT_NODE_SIZE_CELLS_DEFAULT, + false); + if ( res ) + goto out; + continue; + } + if ( dt_node_cmp(name, "passthrough") == 0 ) + { + res = scan_pfdt_node(kinfo, pfdt, node_next, + DT_ROOT_NODE_ADDR_CELLS_DEFAULT, + DT_ROOT_NODE_SIZE_CELLS_DEFAULT, + true); + if ( res ) + goto out; + continue; + } + } + + out: + iounmap(pfdt); + + return res; +} + +static unsigned long __init domain_p2m_pages(unsigned long maxmem_kb, + unsigned int smp_cpus) +{ + /* + * Keep in sync with libxl__get_required_paging_memory(). + * 256 pages (1MB) per vcpu, plus 1 page per MiB of RAM for the P2M map, + * plus 128 pages to cover extended regions. + */ + unsigned long memkb = 4 * (256 * smp_cpus + (maxmem_kb / 1024) + 128); + + BUILD_BUG_ON(PAGE_SIZE != SZ_4K); + + return DIV_ROUND_UP(memkb, 1024) << (20 - PAGE_SHIFT); +} + +/* + * The max size for DT is 2MB. However, the generated DT is small (not including + * domU passthrough DT nodes whose size we account separately), 4KB are enough + * for now, but we might have to increase it in the future. + */ +#define DOMU_DTB_SIZE 4096 +static int __init prepare_dtb_domU(struct domain *d, struct kernel_info *kinfo) +{ + int addrcells, sizecells; + int ret, fdt_size = DOMU_DTB_SIZE; + + kinfo->phandle_intc = GUEST_PHANDLE_GIC; + +#ifdef CONFIG_GRANT_TABLE + kinfo->gnttab_start = GUEST_GNTTAB_BASE; + kinfo->gnttab_size = GUEST_GNTTAB_SIZE; +#endif + + addrcells = GUEST_ROOT_ADDRESS_CELLS; + sizecells = GUEST_ROOT_SIZE_CELLS; + + /* Account for domU passthrough DT size */ + if ( kinfo->dtb_bootmodule ) + fdt_size += kinfo->dtb_bootmodule->size; + + /* Cap to max DT size if needed */ + fdt_size = min(fdt_size, SZ_2M); + + kinfo->fdt = xmalloc_bytes(fdt_size); + if ( kinfo->fdt == NULL ) + return -ENOMEM; + + ret = fdt_create(kinfo->fdt, fdt_size); + if ( ret < 0 ) + goto err; + + ret = fdt_finish_reservemap(kinfo->fdt); + if ( ret < 0 ) + goto err; + + ret = fdt_begin_node(kinfo->fdt, ""); + if ( ret < 0 ) + goto err; + + ret = fdt_property_cell(kinfo->fdt, "#address-cells", addrcells); + if ( ret ) + goto err; + + ret = fdt_property_cell(kinfo->fdt, "#size-cells", sizecells); + if ( ret ) + goto err; + + ret = make_chosen_node(kinfo); + if ( ret ) + goto err; + + ret = make_cpus_node(d, kinfo->fdt); + if ( ret ) + goto err; + + ret = make_memory_node(kinfo, addrcells, sizecells, + kernel_info_get_mem(kinfo)); + if ( ret ) + goto err; + + ret = make_resv_memory_node(kinfo, addrcells, sizecells); + if ( ret ) + goto err; + + /* + * domain_handle_dtb_bootmodule has to be called before the rest of + * the device tree is generated because it depends on the value of + * the field phandle_intc. + */ + if ( kinfo->dtb_bootmodule ) + { + ret = domain_handle_dtb_bootmodule(d, kinfo); + if ( ret ) + goto err; + } + + ret = make_intc_domU_node(kinfo); + if ( ret ) + goto err; + + ret = make_timer_node(kinfo); + if ( ret ) + goto err; + + if ( kinfo->dom0less_feature & DOM0LESS_ENHANCED_NO_XS ) + { + ret = make_hypervisor_node(d, kinfo, addrcells, sizecells); + if ( ret ) + goto err; + } + + ret = make_arch_nodes(kinfo); + if ( ret ) + goto err; + + ret = fdt_end_node(kinfo->fdt); + if ( ret < 0 ) + goto err; + + ret = fdt_finish(kinfo->fdt); + if ( ret < 0 ) + goto err; + + return 0; + + err: + printk("Device tree generation failed (%d).\n", ret); + xfree(kinfo->fdt); + + return -EINVAL; +} + +static int __init alloc_xenstore_evtchn(struct domain *d) +{ + evtchn_alloc_unbound_t alloc; + int rc; + + alloc.dom = d->domain_id; + alloc.remote_dom = hardware_domain->domain_id; + rc = evtchn_alloc_unbound(&alloc, 0); + if ( rc ) + { + printk("Failed allocating event channel for domain\n"); + return rc; + } + +#ifdef CONFIG_HVM + d->arch.hvm.params[HVM_PARAM_STORE_EVTCHN] = alloc.port; +#endif + + return 0; +} + +int __init construct_domU(struct domain *d, + const struct dt_device_node *node) +{ + struct kernel_info kinfo = KERNEL_INFO_INIT; + const char *dom0less_enhanced; + int rc; + u64 mem; + u32 p2m_mem_mb; + unsigned long p2m_pages; + + rc = dt_property_read_u64(node, "memory", &mem); + if ( !rc ) + { + printk("Error building DomU: cannot read \"memory\" property\n"); + return -EINVAL; + } + kinfo.unassigned_mem = (paddr_t)mem * SZ_1K; + + rc = dt_property_read_u32(node, "xen,domain-p2m-mem-mb", &p2m_mem_mb); + /* If xen,domain-p2m-mem-mb is not specified, use the default value. */ + p2m_pages = rc ? + p2m_mem_mb << (20 - PAGE_SHIFT) : + domain_p2m_pages(mem, d->max_vcpus); + + spin_lock(&d->arch.paging.lock); + rc = p2m_set_allocation(d, p2m_pages, NULL); + spin_unlock(&d->arch.paging.lock); + if ( rc != 0 ) + return rc; + + printk("*** LOADING DOMU cpus=%u memory=%#"PRIx64"KB ***\n", + d->max_vcpus, mem); + + rc = dt_property_read_string(node, "xen,enhanced", &dom0less_enhanced); + if ( rc == -EILSEQ || + rc == -ENODATA || + (rc == 0 && !strcmp(dom0less_enhanced, "enabled")) ) + { + if ( hardware_domain ) + kinfo.dom0less_feature = DOM0LESS_ENHANCED; + else + panic("At the moment, Xenstore support requires dom0 to be present\n"); + } + else if ( rc == 0 && !strcmp(dom0less_enhanced, "no-xenstore") ) + kinfo.dom0less_feature = DOM0LESS_ENHANCED_NO_XS; + + if ( vcpu_create(d, 0) == NULL ) + return -ENOMEM; + + d->max_pages = ((paddr_t)mem * SZ_1K) >> PAGE_SHIFT; + + kinfo.d = d; + + rc = kernel_probe(&kinfo, node); + if ( rc < 0 ) + return rc; + + set_domain_type(d, &kinfo); + + if ( !dt_find_property(node, "xen,static-mem", NULL) ) + allocate_memory(d, &kinfo); + else if ( !is_domain_direct_mapped(d) ) + allocate_static_memory(d, &kinfo, node); + else + assign_static_memory_11(d, &kinfo, node); + + rc = process_shm(d, &kinfo, node); + if ( rc < 0 ) + return rc; + + rc = init_vuart(d, &kinfo, node); + if ( rc < 0 ) + return rc; + + rc = prepare_dtb_domU(d, &kinfo); + if ( rc < 0 ) + return rc; + + rc = construct_domain(d, &kinfo); + if ( rc < 0 ) + return rc; + + if ( kinfo.dom0less_feature & DOM0LESS_XENSTORE ) + { + ASSERT(hardware_domain); + rc = alloc_xenstore_evtchn(d); + if ( rc < 0 ) + return rc; +#ifdef CONFIG_HVM + d->arch.hvm.params[HVM_PARAM_STORE_PFN] = ~0ULL; +#endif + } + + return rc; +} diff --git a/xen/include/asm-generic/dom0less-build.h b/xen/include/asm-generic/dom0less-build.h index a6985bc20a..3e4af9dcce 100644 --- a/xen/include/asm-generic/dom0less-build.h +++ b/xen/include/asm-generic/dom0less-build.h @@ -8,6 +8,9 @@ #include +struct kernel_info; +struct dt_device_node; + void create_domUs(void); bool is_dom0less_mode(void); @@ -18,6 +21,17 @@ void arch_create_domus(struct dt_device_node *node, struct xen_domctl_createdomain *d_cfg, unsigned int flags); +int init_vuart(struct domain *d, struct kernel_info *kinfo, + const struct dt_device_node *node); + +int make_intc_domU_node(struct kernel_info *kinfo); +int make_arch_nodes(struct kernel_info *kinfo); + +void set_domain_type(struct domain *d, struct kernel_info *kinfo); + +int init_intc_phandle(struct kernel_info *kinfo, const char *name, + const int node_next, const void *pfdt); + #else /* !CONFIG_DOM0LESS_BOOT */ static inline void create_domUs(void) {}