From patchwork Wed Jul 3 10:42:47 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oleksii Kurochko X-Patchwork-Id: 13721968 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 58593C3271E for ; Wed, 3 Jul 2024 10:43:14 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.752890.1161132 (Exim 4.92) (envelope-from ) id 1sOxS0-000404-Ow; Wed, 03 Jul 2024 10:43:00 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 752890.1161132; Wed, 03 Jul 2024 10:43:00 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1sOxS0-0003zw-Ly; Wed, 03 Jul 2024 10:43:00 +0000 Received: by outflank-mailman (input) for mailman id 752890; Wed, 03 Jul 2024 10:42:59 +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 1sOxRz-0003lU-Kk for xen-devel@lists.xenproject.org; Wed, 03 Jul 2024 10:42:59 +0000 Received: from mail-ej1-x635.google.com (mail-ej1-x635.google.com [2a00:1450:4864:20::635]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id 02af6d02-3929-11ef-bbf9-fd08da9f4363; Wed, 03 Jul 2024 12:42:57 +0200 (CEST) Received: by mail-ej1-x635.google.com with SMTP id a640c23a62f3a-a7527afa23cso385213866b.2 for ; Wed, 03 Jul 2024 03:42:57 -0700 (PDT) Received: from fedora.. ([94.75.70.14]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a72b92985desm414590066b.78.2024.07.03.03.42.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 03 Jul 2024 03:42:55 -0700 (PDT) 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: 02af6d02-3929-11ef-bbf9-fd08da9f4363 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1720003376; x=1720608176; 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=xuAQ+9rgv2lGpU1y0rgNrIbtbNMzynV4e2QZTX1RPRg=; b=hsS1/cwp3F0ifoDFJ7mKiW73nYcVKeM9ULcZjBCOvER0hqsJxlTzzJwQl1/puMsxVm a5Nw2vQTNY64nkkYH5gRY+4pOwIrF6fokOBcVKNhTuwqUhWeSrdqowVfrD1DqL/sPqsG gERK5xToD0JAbUld/bNXp12BWhPEeayta9d9kby9p2DHfw4rcXPqKpxBD+YWhOdyWS/Z jcTJoTMgC8w+N392qp2VG+GsnmI4jMpRecAcmM6WBWeyD1sRGXzl3vjNSU5DfRPBECnm 34aRxpwe41z7pMsxZZsJtEfWY/LhR4I0RhNZeHRDbcx13NMyiGKh/8GOs8uRJuDXYeh3 pLqg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1720003376; x=1720608176; 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=xuAQ+9rgv2lGpU1y0rgNrIbtbNMzynV4e2QZTX1RPRg=; b=k0G4PQSALwPYGZYDxR2XPiI/gt5niBDAQL2O5Zz6zEGbpq5v9uRPxjYB48m+xzj4X2 TE0en1bF7iBnpqDIfp2OkqsvZPk9a+FB/u65pQBzt3b+WSpX5sJJKQHBeqh7grzduffD jBNiev82D2yVVmbO6Q4D0ITHhXmirWkOTUDbYahvNGqGPq+IiqLlXLxnsDtc/3l2Eo98 /TvikR/yocEQ94DB8Pnrl08kLdwxZ9F37q0xijQucs7h66x9JigAqGZNCJ2uZB+jIeu6 UZTXEDi9NFOgki6ojzi/tQOql6smni0Hlspt/QnDj0Efp7pH7BuFAcoMmSfjICUPgM+a sJLQ== X-Gm-Message-State: AOJu0YyK9xE9HmGHQ+JaQ/hxHuZ/pPPMdADbx/00iBzDp4kmCMH+Q5KG KrzwkmCjhEqR5DLiY9Q2y1S1ZUrq3rYW9E6FzE3Ubcf18rCVtBw7fUqKaTdC X-Google-Smtp-Source: AGHT+IHyzEpNXkLx/qcyOkqo7H9v4TlEh+u9QQnhx/g9aH4FLGjNPWl2yGb4sTuXKSG5F3BNRxIOqw== X-Received: by 2002:a17:906:81cd:b0:a6f:5f8f:6c43 with SMTP id a640c23a62f3a-a751451373bmr878552966b.56.1720003376101; Wed, 03 Jul 2024 03:42:56 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Shawn Anastasio , Andrew Cooper , Jan Beulich , Julien Grall , Stefano Stabellini , Bertrand Marquis , Michal Orzel , Volodymyr Babchuk , "Daniel P. Smith" , Oleksii Kurochko Subject: [PATCH v1 1/5] xen/device-tree: Move Arm's setup.c bootinfo functions to common Date: Wed, 3 Jul 2024 12:42:47 +0200 Message-ID: X-Mailer: git-send-email 2.45.2 In-Reply-To: References: MIME-Version: 1.0 From: Shawn Anastasio Arm's setup.c contains a collection of functions for parsing memory map and other boot information from a device tree. Since these routines are generally useful on any architecture that supports device tree booting, move them into xen/common/device-tree. Suggested-by: Julien Grall Signed-off-by: Shawn Anastasio Signed-off-by: Oleksii Kurochko --- Changes in V5: - add xen/include/xen/bootfdt.h to MAINTAINERS file. - drop message "Early device tree parsing and". - After rebase on top of the current staging the following changes were done: - init bootinfo variable in with BOOTINFO_INIT; - update the code of dt_unreserved_regions(): CONFIG_STATIC_SHM related changes and getting of reserved_mem bootinfo_get_shmem() ?? - update the code of meminfo_overlap_check(): add check ( INVALID_PADDR == bank_start ) to if case. - update the code of check_reserved_regions_overlap(): CONFIG_STATIC_SHM related changes. - struct bootinfo was updated ( CONFIG_STATIC_SHM changes ) - add shared_meminfo ( because of CONFIG_STATIC_SHM ) - struct struct membanks was update with __struct group so is neeeded to be included in bootfdt.h - move BOOTINFO_ACPI_INIT, BOOTINFO_SHMEM_INIT, BOOTINFO_INIT to generic bootfdt.h - bootinfo_get_reserved_mem(), bootinfo_get_mem(), bootinfo_get_acpi(), bootinfo_get_shmem() and bootinfo_get_shmem_extra() were moved to xen/bootfdt.h - s/arm32/CONFIG_SEPARATE_XENHEAP/ - add inclusion of because there are function in which are using container_of(). --- Changes in v4: - create new xen/include/bootinfo.h rather than relying on arch's asm/setup.h to provide required definitions for bootinfo.c - build bootinfo.c as .init.o - clean up and sort bootinfo.c's #includes - use CONFIG_SEPARATE_XENHEAP rather than CONFIG_ARM_32 to guard xenheap-specific behavior of populate_boot_allocator - (MAINTAINERS) include all of common/device-tree rather than just bootinfo.c --- MAINTAINERS | 2 + xen/arch/arm/include/asm/setup.h | 187 +----------- xen/arch/arm/setup.c | 432 ---------------------------- xen/common/Makefile | 1 + xen/common/device-tree/Makefile | 1 + xen/common/device-tree/bootinfo.c | 459 ++++++++++++++++++++++++++++++ xen/include/xen/bootfdt.h | 196 +++++++++++++ 7 files changed, 660 insertions(+), 618 deletions(-) create mode 100644 xen/common/device-tree/Makefile create mode 100644 xen/common/device-tree/bootinfo.c create mode 100644 xen/include/xen/bootfdt.h diff --git a/MAINTAINERS b/MAINTAINERS index 2b0c894527..505915b6b6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -295,9 +295,11 @@ M: Stefano Stabellini M: Julien Grall S: Supported F: xen/common/libfdt/ +F: xen/common/device-tree/ F: xen/common/device_tree.c F: xen/common/dt-overlay.c F: xen/include/xen/libfdt/ +F: xen/include/xen/bootfdt.h F: xen/include/xen/device_tree.h F: xen/drivers/passthrough/device_tree.c diff --git a/xen/arch/arm/include/asm/setup.h b/xen/arch/arm/include/asm/setup.h index c34179da93..051e796716 100644 --- a/xen/arch/arm/include/asm/setup.h +++ b/xen/arch/arm/include/asm/setup.h @@ -3,159 +3,9 @@ #include #include +#include #include -#define MIN_FDT_ALIGN 8 -#define MAX_FDT_SIZE SZ_2M - -#define NR_MEM_BANKS 256 -#define NR_SHMEM_BANKS 32 - -#define MAX_MODULES 32 /* Current maximum useful modules */ - -typedef enum { - BOOTMOD_XEN, - BOOTMOD_FDT, - BOOTMOD_KERNEL, - BOOTMOD_RAMDISK, - BOOTMOD_XSM, - BOOTMOD_GUEST_DTB, - BOOTMOD_UNKNOWN -} bootmodule_kind; - -enum membank_type { - /* - * The MEMBANK_DEFAULT type refers to either reserved memory for the - * device/firmware (when the bank is in 'reserved_mem') or any RAM (when - * the bank is in 'mem'). - */ - MEMBANK_DEFAULT, - /* - * The MEMBANK_STATIC_DOMAIN type is used to indicate whether the memory - * bank is bound to a static Xen domain. It is only valid when the bank - * is in reserved_mem. - */ - MEMBANK_STATIC_DOMAIN, - /* - * The MEMBANK_STATIC_HEAP type is used to indicate whether the memory - * bank is reserved as static heap. It is only valid when the bank is - * in reserved_mem. - */ - MEMBANK_STATIC_HEAP, - /* - * The MEMBANK_FDT_RESVMEM type is used to indicate whether the memory - * bank is from the FDT reserve map. - */ - MEMBANK_FDT_RESVMEM, -}; - -/* Indicates the maximum number of characters(\0 included) for shm_id */ -#define MAX_SHM_ID_LENGTH 16 - -struct shmem_membank_extra { - char shm_id[MAX_SHM_ID_LENGTH]; - unsigned int nr_shm_borrowers; -}; - -struct membank { - paddr_t start; - paddr_t size; - union { - enum membank_type type; -#ifdef CONFIG_STATIC_SHM - struct shmem_membank_extra *shmem_extra; -#endif - }; -}; - -struct membanks { - __struct_group(membanks_hdr, common, , - unsigned int nr_banks; - unsigned int max_banks; - ); - struct membank bank[]; -}; - -struct meminfo { - struct membanks_hdr common; - struct membank bank[NR_MEM_BANKS]; -}; - -struct shared_meminfo { - struct membanks_hdr common; - struct membank bank[NR_SHMEM_BANKS]; - struct shmem_membank_extra extra[NR_SHMEM_BANKS]; -}; - -/* - * The domU flag is set for kernels and ramdisks of "xen,domain" nodes. - * The purpose of the domU flag is to avoid getting confused in - * kernel_probe, where we try to guess which is the dom0 kernel and - * initrd to be compatible with all versions of the multiboot spec. - */ -#define BOOTMOD_MAX_CMDLINE 1024 -struct bootmodule { - bootmodule_kind kind; - bool domU; - paddr_t start; - paddr_t size; -}; - -/* DT_MAX_NAME is the node name max length according the DT spec */ -#define DT_MAX_NAME 41 -struct bootcmdline { - bootmodule_kind kind; - bool domU; - paddr_t start; - char dt_name[DT_MAX_NAME]; - char cmdline[BOOTMOD_MAX_CMDLINE]; -}; - -struct bootmodules { - int nr_mods; - struct bootmodule module[MAX_MODULES]; -}; - -struct bootcmdlines { - unsigned int nr_mods; - struct bootcmdline cmdline[MAX_MODULES]; -}; - -struct bootinfo { - struct meminfo mem; - /* The reserved regions are only used when booting using Device-Tree */ - struct meminfo reserved_mem; - struct bootmodules modules; - struct bootcmdlines cmdlines; -#ifdef CONFIG_ACPI - struct meminfo acpi; -#endif -#ifdef CONFIG_STATIC_SHM - struct shared_meminfo shmem; -#endif - bool static_heap; -}; - -#ifdef CONFIG_ACPI -#define BOOTINFO_ACPI_INIT .acpi.common.max_banks = NR_MEM_BANKS, -#else -#define BOOTINFO_ACPI_INIT -#endif - -#ifdef CONFIG_STATIC_SHM -#define BOOTINFO_SHMEM_INIT .shmem.common.max_banks = NR_SHMEM_BANKS, -#else -#define BOOTINFO_SHMEM_INIT -#endif - -#define BOOTINFO_INIT \ -{ \ - .mem.common.max_banks = NR_MEM_BANKS, \ - .reserved_mem.common.max_banks = NR_MEM_BANKS, \ - BOOTINFO_ACPI_INIT \ - BOOTINFO_SHMEM_INIT \ -} - struct map_range_data { struct domain *d; @@ -167,39 +17,8 @@ struct map_range_data struct rangeset *irq_ranges; }; -extern struct bootinfo bootinfo; - extern domid_t max_init_domid; -static inline struct membanks *bootinfo_get_mem(void) -{ - return container_of(&bootinfo.mem.common, struct membanks, common); -} - -static inline struct membanks *bootinfo_get_reserved_mem(void) -{ - return container_of(&bootinfo.reserved_mem.common, struct membanks, common); -} - -#ifdef CONFIG_ACPI -static inline struct membanks *bootinfo_get_acpi(void) -{ - return container_of(&bootinfo.acpi.common, struct membanks, common); -} -#endif - -#ifdef CONFIG_STATIC_SHM -static inline struct membanks *bootinfo_get_shmem(void) -{ - return container_of(&bootinfo.shmem.common, struct membanks, common); -} - -static inline struct shmem_membank_extra *bootinfo_get_shmem_extra(void) -{ - return bootinfo.shmem.extra; -} -#endif - void copy_from_paddr(void *dst, paddr_t paddr, unsigned long len); size_t estimate_efi_size(unsigned int mem_nr_banks); @@ -220,9 +39,6 @@ void fw_unreserved_regions(paddr_t s, paddr_t e, void (*cb)(paddr_t ps, paddr_t pe), unsigned int first); -size_t boot_fdt_info(const void *fdt, paddr_t paddr); -const char *boot_fdt_cmdline(const void *fdt); - bool check_reserved_regions_overlap(paddr_t region_start, paddr_t region_size); struct bootmodule *add_boot_module(bootmodule_kind kind, @@ -237,7 +53,6 @@ struct bootcmdline * boot_cmdline_find_by_name(const char *name); const char *boot_module_kind_as_string(bootmodule_kind kind); void init_pdx(void); -void populate_boot_allocator(void); void setup_mm(void); extern uint32_t hyp_traps_vector[]; diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c index 0c2fdaceaf..cb2c0a16b8 100644 --- a/xen/arch/arm/setup.c +++ b/xen/arch/arm/setup.c @@ -48,8 +48,6 @@ #include #include -struct bootinfo __initdata bootinfo = BOOTINFO_INIT; - /* * Sanitized version of cpuinfo containing only features available on all * cores (only on arm64 as there is no sanitization support on arm32). @@ -203,321 +201,6 @@ static void __init processor_id(void) processor_setup(); } -static void __init dt_unreserved_regions(paddr_t s, paddr_t e, - void (*cb)(paddr_t ps, paddr_t pe), - unsigned int first) -{ - const struct membanks *reserved_mem = bootinfo_get_reserved_mem(); -#ifdef CONFIG_STATIC_SHM - const struct membanks *shmem = bootinfo_get_shmem(); - unsigned int offset; -#endif - unsigned int i; - - /* - * i is the current bootmodule we are evaluating across all possible - * kinds. - */ - for ( i = first; i < reserved_mem->nr_banks; i++ ) - { - paddr_t r_s = reserved_mem->bank[i].start; - paddr_t r_e = r_s + reserved_mem->bank[i].size; - - if ( s < r_e && r_s < e ) - { - dt_unreserved_regions(r_e, e, cb, i + 1); - dt_unreserved_regions(s, r_s, cb, i + 1); - return; - } - } - -#ifdef CONFIG_STATIC_SHM - /* - * When retrieving the corresponding shared memory addresses - * below, we need to index the shmem->bank starting from 0, hence - * we need to use i - reserved_mem->nr_banks. - */ - offset = reserved_mem->nr_banks; - for ( ; i - offset < shmem->nr_banks; i++ ) - { - paddr_t r_s, r_e; - - r_s = shmem->bank[i - offset].start; - - /* Shared memory banks can contain INVALID_PADDR as start */ - if ( INVALID_PADDR == r_s ) - continue; - - r_e = r_s + shmem->bank[i - offset].size; - - if ( s < r_e && r_s < e ) - { - dt_unreserved_regions(r_e, e, cb, i + 1); - dt_unreserved_regions(s, r_s, cb, i + 1); - return; - } - } -#endif - - cb(s, e); -} - -/* - * TODO: '*_end' could be 0 if the bank/region is at the end of the physical - * address space. This is for now not handled as it requires more rework. - */ -static bool __init meminfo_overlap_check(const struct membanks *mem, - paddr_t region_start, - paddr_t region_size) -{ - paddr_t bank_start = INVALID_PADDR, bank_end = 0; - paddr_t region_end = region_start + region_size; - unsigned int i, bank_num = mem->nr_banks; - - for ( i = 0; i < bank_num; i++ ) - { - bank_start = mem->bank[i].start; - bank_end = bank_start + mem->bank[i].size; - - if ( INVALID_PADDR == bank_start || region_end <= bank_start || - region_start >= bank_end ) - continue; - else - { - printk("Region: [%#"PRIpaddr", %#"PRIpaddr") overlapping with bank[%u]: [%#"PRIpaddr", %#"PRIpaddr")\n", - region_start, region_end, i, bank_start, bank_end); - return true; - } - } - - return false; -} - -/* - * TODO: '*_end' could be 0 if the module/region is at the end of the physical - * address space. This is for now not handled as it requires more rework. - */ -static bool __init bootmodules_overlap_check(struct bootmodules *bootmodules, - paddr_t region_start, - paddr_t region_size) -{ - paddr_t mod_start = INVALID_PADDR, mod_end = 0; - paddr_t region_end = region_start + region_size; - unsigned int i, mod_num = bootmodules->nr_mods; - - for ( i = 0; i < mod_num; i++ ) - { - mod_start = bootmodules->module[i].start; - mod_end = mod_start + bootmodules->module[i].size; - - if ( region_end <= mod_start || region_start >= mod_end ) - continue; - else - { - printk("Region: [%#"PRIpaddr", %#"PRIpaddr") overlapping with mod[%u]: [%#"PRIpaddr", %#"PRIpaddr")\n", - region_start, region_end, i, mod_start, mod_end); - return true; - } - } - - return false; -} - -void __init fw_unreserved_regions(paddr_t s, paddr_t e, - void (*cb)(paddr_t ps, paddr_t pe), - unsigned int first) -{ - if ( acpi_disabled ) - dt_unreserved_regions(s, e, cb, first); - else - cb(s, e); -} - -/* - * Given an input physical address range, check if this range is overlapping - * with the existing reserved memory regions defined in bootinfo. - * Return true if the input physical address range is overlapping with any - * existing reserved memory regions, otherwise false. - */ -bool __init check_reserved_regions_overlap(paddr_t region_start, - paddr_t region_size) -{ - const struct membanks *mem_banks[] = { - bootinfo_get_reserved_mem(), -#ifdef CONFIG_ACPI - bootinfo_get_acpi(), -#endif -#ifdef CONFIG_STATIC_SHM - bootinfo_get_shmem(), -#endif - }; - unsigned int i; - - /* - * Check if input region is overlapping with reserved memory banks or - * ACPI EfiACPIReclaimMemory (when ACPI feature is enabled) or static - * shared memory banks (when static shared memory feature is enabled) - */ - for ( i = 0; i < ARRAY_SIZE(mem_banks); i++ ) - if ( meminfo_overlap_check(mem_banks[i], region_start, region_size) ) - return true; - - /* Check if input region is overlapping with bootmodules */ - if ( bootmodules_overlap_check(&bootinfo.modules, - region_start, region_size) ) - return true; - - return false; -} - -struct bootmodule __init *add_boot_module(bootmodule_kind kind, - paddr_t start, paddr_t size, - bool domU) -{ - struct bootmodules *mods = &bootinfo.modules; - struct bootmodule *mod; - unsigned int i; - - if ( mods->nr_mods == MAX_MODULES ) - { - printk("Ignoring %s boot module at %"PRIpaddr"-%"PRIpaddr" (too many)\n", - boot_module_kind_as_string(kind), start, start + size); - return NULL; - } - - if ( check_reserved_regions_overlap(start, size) ) - return NULL; - - for ( i = 0 ; i < mods->nr_mods ; i++ ) - { - mod = &mods->module[i]; - if ( mod->kind == kind && mod->start == start ) - { - if ( !domU ) - mod->domU = false; - return mod; - } - } - - mod = &mods->module[mods->nr_mods++]; - mod->kind = kind; - mod->start = start; - mod->size = size; - mod->domU = domU; - - return mod; -} - -/* - * boot_module_find_by_kind can only be used to return Xen modules (e.g - * XSM, DTB) or Dom0 modules. This is not suitable for looking up guest - * modules. - */ -struct bootmodule * __init boot_module_find_by_kind(bootmodule_kind kind) -{ - struct bootmodules *mods = &bootinfo.modules; - struct bootmodule *mod; - int i; - for (i = 0 ; i < mods->nr_mods ; i++ ) - { - mod = &mods->module[i]; - if ( mod->kind == kind && !mod->domU ) - return mod; - } - return NULL; -} - -void __init add_boot_cmdline(const char *name, const char *cmdline, - bootmodule_kind kind, paddr_t start, bool domU) -{ - struct bootcmdlines *cmds = &bootinfo.cmdlines; - struct bootcmdline *cmd; - - if ( cmds->nr_mods == MAX_MODULES ) - { - printk("Ignoring %s cmdline (too many)\n", name); - return; - } - - cmd = &cmds->cmdline[cmds->nr_mods++]; - cmd->kind = kind; - cmd->domU = domU; - cmd->start = start; - - ASSERT(strlen(name) <= DT_MAX_NAME); - safe_strcpy(cmd->dt_name, name); - - if ( strlen(cmdline) > BOOTMOD_MAX_CMDLINE ) - panic("module %s command line too long\n", name); - safe_strcpy(cmd->cmdline, cmdline); -} - -/* - * boot_cmdline_find_by_kind can only be used to return Xen modules (e.g - * XSM, DTB) or Dom0 modules. This is not suitable for looking up guest - * modules. - */ -struct bootcmdline * __init boot_cmdline_find_by_kind(bootmodule_kind kind) -{ - struct bootcmdlines *cmds = &bootinfo.cmdlines; - struct bootcmdline *cmd; - int i; - - for ( i = 0 ; i < cmds->nr_mods ; i++ ) - { - cmd = &cmds->cmdline[i]; - if ( cmd->kind == kind && !cmd->domU ) - return cmd; - } - return NULL; -} - -struct bootcmdline * __init boot_cmdline_find_by_name(const char *name) -{ - struct bootcmdlines *mods = &bootinfo.cmdlines; - struct bootcmdline *mod; - unsigned int i; - - for (i = 0 ; i < mods->nr_mods ; i++ ) - { - mod = &mods->cmdline[i]; - if ( strcmp(mod->dt_name, name) == 0 ) - return mod; - } - return NULL; -} - -struct bootmodule * __init boot_module_find_by_addr_and_kind(bootmodule_kind kind, - paddr_t start) -{ - struct bootmodules *mods = &bootinfo.modules; - struct bootmodule *mod; - unsigned int i; - - for (i = 0 ; i < mods->nr_mods ; i++ ) - { - mod = &mods->module[i]; - if ( mod->kind == kind && mod->start == start ) - return mod; - } - return NULL; -} - -const char * __init boot_module_kind_as_string(bootmodule_kind kind) -{ - switch ( kind ) - { - case BOOTMOD_XEN: return "Xen"; - case BOOTMOD_FDT: return "Device Tree"; - case BOOTMOD_KERNEL: return "Kernel"; - case BOOTMOD_RAMDISK: return "Ramdisk"; - case BOOTMOD_XSM: return "XSM"; - case BOOTMOD_GUEST_DTB: return "DTB"; - case BOOTMOD_UNKNOWN: return "Unknown"; - default: BUG(); - } -} - void __init discard_initial_modules(void) { struct bootmodules *mi = &bootinfo.modules; @@ -556,40 +239,6 @@ static void * __init relocate_fdt(paddr_t dtb_paddr, size_t dtb_size) return fdt; } -/* - * Return the end of the non-module region starting at s. In other - * words return s the start of the next modules after s. - * - * On input *end is the end of the region which should be considered - * and it is updated to reflect the end of the module, clipped to the - * end of the region if it would run over. - */ -static paddr_t __init next_module(paddr_t s, paddr_t *end) -{ - struct bootmodules *mi = &bootinfo.modules; - paddr_t lowest = ~(paddr_t)0; - int i; - - for ( i = 0; i < mi->nr_mods; i++ ) - { - paddr_t mod_s = mi->module[i].start; - paddr_t mod_e = mod_s + mi->module[i].size; - - if ( !mi->module[i].size ) - continue; - - if ( mod_s < s ) - continue; - if ( mod_s > lowest ) - continue; - if ( mod_s > *end ) - continue; - lowest = mod_s; - *end = min(*end, mod_e); - } - return lowest; -} - void __init init_pdx(void) { const struct membanks *mem = bootinfo_get_mem(); @@ -635,87 +284,6 @@ void __init init_pdx(void) } } -/* - * Populate the boot allocator. - * If a static heap was not provided by the admin, all the RAM but the - * following regions will be added: - * - Modules (e.g., Xen, Kernel) - * - Reserved regions - * - Xenheap (arm32 only) - * If a static heap was provided by the admin, populate the boot - * allocator with the corresponding regions only, but with Xenheap excluded - * on arm32. - */ -void __init populate_boot_allocator(void) -{ - unsigned int i; - const struct membanks *banks = bootinfo_get_mem(); - const struct membanks *reserved_mem = bootinfo_get_reserved_mem(); - paddr_t s, e; - - if ( bootinfo.static_heap ) - { - for ( i = 0 ; i < reserved_mem->nr_banks; i++ ) - { - if ( reserved_mem->bank[i].type != MEMBANK_STATIC_HEAP ) - continue; - - s = reserved_mem->bank[i].start; - e = s + reserved_mem->bank[i].size; -#ifdef CONFIG_ARM_32 - /* Avoid the xenheap, note that the xenheap cannot across a bank */ - if ( s <= mfn_to_maddr(directmap_mfn_start) && - e >= mfn_to_maddr(directmap_mfn_end) ) - { - init_boot_pages(s, mfn_to_maddr(directmap_mfn_start)); - init_boot_pages(mfn_to_maddr(directmap_mfn_end), e); - } - else -#endif - init_boot_pages(s, e); - } - - return; - } - - for ( i = 0; i < banks->nr_banks; i++ ) - { - const struct membank *bank = &banks->bank[i]; - paddr_t bank_end = bank->start + bank->size; - - s = bank->start; - while ( s < bank_end ) - { - paddr_t n = bank_end; - - e = next_module(s, &n); - - if ( e == ~(paddr_t)0 ) - e = n = bank_end; - - /* - * Module in a RAM bank other than the one which we are - * not dealing with here. - */ - if ( e > bank_end ) - e = bank_end; - -#ifdef CONFIG_ARM_32 - /* Avoid the xenheap */ - if ( s < mfn_to_maddr(directmap_mfn_end) && - mfn_to_maddr(directmap_mfn_start) < e ) - { - e = mfn_to_maddr(directmap_mfn_start); - n = mfn_to_maddr(directmap_mfn_end); - } -#endif - - fw_unreserved_regions(s, e, init_boot_pages, 0); - s = n; - } - } -} - size_t __read_mostly dcache_line_bytes; /* C entry point for boot CPU */ diff --git a/xen/common/Makefile b/xen/common/Makefile index f12a474d40..21359bab02 100644 --- a/xen/common/Makefile +++ b/xen/common/Makefile @@ -77,6 +77,7 @@ obj-$(CONFIG_UBSAN) += ubsan/ obj-$(CONFIG_NEEDS_LIBELF) += libelf/ obj-$(CONFIG_HAS_DEVICE_TREE) += libfdt/ +obj-$(CONFIG_HAS_DEVICE_TREE) += device-tree/ CONF_FILE := $(if $(patsubst /%,,$(KCONFIG_CONFIG)),$(objtree)/)$(KCONFIG_CONFIG) $(obj)/config.gz: $(CONF_FILE) diff --git a/xen/common/device-tree/Makefile b/xen/common/device-tree/Makefile new file mode 100644 index 0000000000..947bad979c --- /dev/null +++ b/xen/common/device-tree/Makefile @@ -0,0 +1 @@ +obj-y += bootinfo.init.o diff --git a/xen/common/device-tree/bootinfo.c b/xen/common/device-tree/bootinfo.c new file mode 100644 index 0000000000..dcac9a40a0 --- /dev/null +++ b/xen/common/device-tree/bootinfo.c @@ -0,0 +1,459 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Derived from $xen/arch/arm/setup.c. + * + * bookkeeping routines. + * + * Tim Deegan + * Copyright (c) 2011 Citrix Systems. + * Copyright (c) 2024 Raptor Engineering LLC + */ + +#include +#include +#include +#include +#include +#include +#include + +struct bootinfo __initdata bootinfo = BOOTINFO_INIT; + +const char * __init boot_module_kind_as_string(bootmodule_kind kind) +{ + switch ( kind ) + { + case BOOTMOD_XEN: return "Xen"; + case BOOTMOD_FDT: return "Device Tree"; + case BOOTMOD_KERNEL: return "Kernel"; + case BOOTMOD_RAMDISK: return "Ramdisk"; + case BOOTMOD_XSM: return "XSM"; + case BOOTMOD_GUEST_DTB: return "DTB"; + case BOOTMOD_UNKNOWN: return "Unknown"; + default: BUG(); + } +} + +static void __init dt_unreserved_regions(paddr_t s, paddr_t e, + void (*cb)(paddr_t ps, paddr_t pe), + unsigned int first) +{ + const struct membanks *reserved_mem = bootinfo_get_reserved_mem(); +#ifdef CONFIG_STATIC_SHM + const struct membanks *shmem = bootinfo_get_shmem(); + unsigned int offset; +#endif + unsigned int i; + + /* + * i is the current bootmodule we are evaluating across all possible + * kinds. + */ + for ( i = first; i < reserved_mem->nr_banks; i++ ) + { + paddr_t r_s = reserved_mem->bank[i].start; + paddr_t r_e = r_s + reserved_mem->bank[i].size; + + if ( s < r_e && r_s < e ) + { + dt_unreserved_regions(r_e, e, cb, i + 1); + dt_unreserved_regions(s, r_s, cb, i + 1); + return; + } + } + +#ifdef CONFIG_STATIC_SHM + /* + * When retrieving the corresponding shared memory addresses + * below, we need to index the shmem->bank starting from 0, hence + * we need to use i - reserved_mem->nr_banks. + */ + offset = reserved_mem->nr_banks; + for ( ; i - offset < shmem->nr_banks; i++ ) + { + paddr_t r_s, r_e; + + r_s = shmem->bank[i - offset].start; + + /* Shared memory banks can contain INVALID_PADDR as start */ + if ( INVALID_PADDR == r_s ) + continue; + + r_e = r_s + shmem->bank[i - offset].size; + + if ( s < r_e && r_s < e ) + { + dt_unreserved_regions(r_e, e, cb, i + 1); + dt_unreserved_regions(s, r_s, cb, i + 1); + return; + } + } +#endif + + cb(s, e); +} + +/* + * TODO: '*_end' could be 0 if the bank/region is at the end of the physical + * address space. This is for now not handled as it requires more rework. + */ +static bool __init meminfo_overlap_check(const struct membanks *mem, + paddr_t region_start, + paddr_t region_size) +{ + paddr_t bank_start = INVALID_PADDR, bank_end = 0; + paddr_t region_end = region_start + region_size; + unsigned int i, bank_num = mem->nr_banks; + + for ( i = 0; i < bank_num; i++ ) + { + bank_start = mem->bank[i].start; + bank_end = bank_start + mem->bank[i].size; + + if ( INVALID_PADDR == bank_start || region_end <= bank_start || + region_start >= bank_end ) + continue; + else + { + printk("Region: [%#"PRIpaddr", %#"PRIpaddr") overlapping with bank[%u]: [%#"PRIpaddr", %#"PRIpaddr")\n", + region_start, region_end, i, bank_start, bank_end); + return true; + } + } + + return false; +} + +/* + * TODO: '*_end' could be 0 if the module/region is at the end of the physical + * address space. This is for now not handled as it requires more rework. + */ +static bool __init bootmodules_overlap_check(struct bootmodules *bootmodules, + paddr_t region_start, + paddr_t region_size) +{ + paddr_t mod_start = INVALID_PADDR, mod_end = 0; + paddr_t region_end = region_start + region_size; + unsigned int i, mod_num = bootmodules->nr_mods; + + for ( i = 0; i < mod_num; i++ ) + { + mod_start = bootmodules->module[i].start; + mod_end = mod_start + bootmodules->module[i].size; + + if ( region_end <= mod_start || region_start >= mod_end ) + continue; + else + { + printk("Region: [%#"PRIpaddr", %#"PRIpaddr") overlapping with mod[%u]: [%#"PRIpaddr", %#"PRIpaddr")\n", + region_start, region_end, i, mod_start, mod_end); + return true; + } + } + + return false; +} + +void __init fw_unreserved_regions(paddr_t s, paddr_t e, + void (*cb)(paddr_t ps, paddr_t pe), + unsigned int first) +{ + if ( acpi_disabled ) + dt_unreserved_regions(s, e, cb, first); + else + cb(s, e); +} + +/* + * Given an input physical address range, check if this range is overlapping + * with the existing reserved memory regions defined in bootinfo. + * Return true if the input physical address range is overlapping with any + * existing reserved memory regions, otherwise false. + */ +bool __init check_reserved_regions_overlap(paddr_t region_start, + paddr_t region_size) +{ + const struct membanks *mem_banks[] = { + bootinfo_get_reserved_mem(), +#ifdef CONFIG_ACPI + bootinfo_get_acpi(), +#endif +#ifdef CONFIG_STATIC_SHM + bootinfo_get_shmem(), +#endif + }; + unsigned int i; + + /* + * Check if input region is overlapping with reserved memory banks or + * ACPI EfiACPIReclaimMemory (when ACPI feature is enabled) or static + * shared memory banks (when static shared memory feature is enabled) + */ + for ( i = 0; i < ARRAY_SIZE(mem_banks); i++ ) + if ( meminfo_overlap_check(mem_banks[i], region_start, region_size) ) + return true; + + /* Check if input region is overlapping with bootmodules */ + if ( bootmodules_overlap_check(&bootinfo.modules, + region_start, region_size) ) + return true; + + return false; +} + +struct bootmodule __init *add_boot_module(bootmodule_kind kind, + paddr_t start, paddr_t size, + bool domU) +{ + struct bootmodules *mods = &bootinfo.modules; + struct bootmodule *mod; + unsigned int i; + + if ( mods->nr_mods == MAX_MODULES ) + { + printk("Ignoring %s boot module at %"PRIpaddr"-%"PRIpaddr" (too many)\n", + boot_module_kind_as_string(kind), start, start + size); + return NULL; + } + + if ( check_reserved_regions_overlap(start, size) ) + return NULL; + + for ( i = 0 ; i < mods->nr_mods ; i++ ) + { + mod = &mods->module[i]; + if ( mod->kind == kind && mod->start == start ) + { + if ( !domU ) + mod->domU = false; + return mod; + } + } + + mod = &mods->module[mods->nr_mods++]; + mod->kind = kind; + mod->start = start; + mod->size = size; + mod->domU = domU; + + return mod; +} + +/* + * boot_module_find_by_kind can only be used to return Xen modules (e.g + * XSM, DTB) or Dom0 modules. This is not suitable for looking up guest + * modules. + */ +struct bootmodule * __init boot_module_find_by_kind(bootmodule_kind kind) +{ + struct bootmodules *mods = &bootinfo.modules; + struct bootmodule *mod; + int i; + for (i = 0 ; i < mods->nr_mods ; i++ ) + { + mod = &mods->module[i]; + if ( mod->kind == kind && !mod->domU ) + return mod; + } + return NULL; +} + +void __init add_boot_cmdline(const char *name, const char *cmdline, + bootmodule_kind kind, paddr_t start, bool domU) +{ + struct bootcmdlines *cmds = &bootinfo.cmdlines; + struct bootcmdline *cmd; + + if ( cmds->nr_mods == MAX_MODULES ) + { + printk("Ignoring %s cmdline (too many)\n", name); + return; + } + + cmd = &cmds->cmdline[cmds->nr_mods++]; + cmd->kind = kind; + cmd->domU = domU; + cmd->start = start; + + ASSERT(strlen(name) <= DT_MAX_NAME); + safe_strcpy(cmd->dt_name, name); + + if ( strlen(cmdline) > BOOTMOD_MAX_CMDLINE ) + panic("module %s command line too long\n", name); + safe_strcpy(cmd->cmdline, cmdline); +} + +/* + * boot_cmdline_find_by_kind can only be used to return Xen modules (e.g + * XSM, DTB) or Dom0 modules. This is not suitable for looking up guest + * modules. + */ +struct bootcmdline * __init boot_cmdline_find_by_kind(bootmodule_kind kind) +{ + struct bootcmdlines *cmds = &bootinfo.cmdlines; + struct bootcmdline *cmd; + int i; + + for ( i = 0 ; i < cmds->nr_mods ; i++ ) + { + cmd = &cmds->cmdline[i]; + if ( cmd->kind == kind && !cmd->domU ) + return cmd; + } + return NULL; +} + +struct bootcmdline * __init boot_cmdline_find_by_name(const char *name) +{ + struct bootcmdlines *mods = &bootinfo.cmdlines; + struct bootcmdline *mod; + unsigned int i; + + for (i = 0 ; i < mods->nr_mods ; i++ ) + { + mod = &mods->cmdline[i]; + if ( strcmp(mod->dt_name, name) == 0 ) + return mod; + } + return NULL; +} + +struct bootmodule * __init boot_module_find_by_addr_and_kind(bootmodule_kind kind, + paddr_t start) +{ + struct bootmodules *mods = &bootinfo.modules; + struct bootmodule *mod; + unsigned int i; + + for (i = 0 ; i < mods->nr_mods ; i++ ) + { + mod = &mods->module[i]; + if ( mod->kind == kind && mod->start == start ) + return mod; + } + return NULL; +} + +/* + * Return the end of the non-module region starting at s. In other + * words return s the start of the next modules after s. + * + * On input *end is the end of the region which should be considered + * and it is updated to reflect the end of the module, clipped to the + * end of the region if it would run over. + */ +static paddr_t __init next_module(paddr_t s, paddr_t *end) +{ + struct bootmodules *mi = &bootinfo.modules; + paddr_t lowest = ~(paddr_t)0; + int i; + + for ( i = 0; i < mi->nr_mods; i++ ) + { + paddr_t mod_s = mi->module[i].start; + paddr_t mod_e = mod_s + mi->module[i].size; + + if ( !mi->module[i].size ) + continue; + + if ( mod_s < s ) + continue; + if ( mod_s > lowest ) + continue; + if ( mod_s > *end ) + continue; + lowest = mod_s; + *end = min(*end, mod_e); + } + return lowest; +} + +/* + * Populate the boot allocator. + * If a static heap was not provided by the admin, all the RAM but the + * following regions will be added: + * - Modules (e.g., Xen, Kernel) + * - Reserved regions + * - Xenheap (CONFIG_SEPARATE_XENHEAP only) + * If a static heap was provided by the admin, populate the boot + * allocator with the corresponding regions only, but with Xenheap excluded + * on CONFIG_SEPARATE_XENHEAP. + */ +void __init populate_boot_allocator(void) +{ + unsigned int i; + const struct membanks *banks = bootinfo_get_mem(); + const struct membanks *reserved_mem = bootinfo_get_reserved_mem(); + paddr_t s, e; + + if ( bootinfo.static_heap ) + { + for ( i = 0 ; i < reserved_mem->nr_banks; i++ ) + { + if ( reserved_mem->bank[i].type != MEMBANK_STATIC_HEAP ) + continue; + + s = reserved_mem->bank[i].start; + e = s + reserved_mem->bank[i].size; +#ifdef CONFIG_SEPARATE_XENHEAP + /* Avoid the xenheap, note that the xenheap cannot across a bank */ + if ( s <= mfn_to_maddr(directmap_mfn_start) && + e >= mfn_to_maddr(directmap_mfn_end) ) + { + init_boot_pages(s, mfn_to_maddr(directmap_mfn_start)); + init_boot_pages(mfn_to_maddr(directmap_mfn_end), e); + } + else +#endif + init_boot_pages(s, e); + } + + return; + } + + for ( i = 0; i < banks->nr_banks; i++ ) + { + const struct membank *bank = &banks->bank[i]; + paddr_t bank_end = bank->start + bank->size; + + s = bank->start; + while ( s < bank_end ) + { + paddr_t n = bank_end; + + e = next_module(s, &n); + + if ( e == ~(paddr_t)0 ) + e = n = bank_end; + + /* + * Module in a RAM bank other than the one which we are + * not dealing with here. + */ + if ( e > bank_end ) + e = bank_end; + +#ifdef CONFIG_SEPARATE_XENHEAP + /* Avoid the xenheap */ + if ( s < mfn_to_maddr(directmap_mfn_end) && + mfn_to_maddr(directmap_mfn_start) < e ) + { + e = mfn_to_maddr(directmap_mfn_start); + n = mfn_to_maddr(directmap_mfn_end); + } +#endif + + fw_unreserved_regions(s, e, init_boot_pages, 0); + s = n; + } + } +} + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/include/xen/bootfdt.h b/xen/include/xen/bootfdt.h new file mode 100644 index 0000000000..7cd45b3d4b --- /dev/null +++ b/xen/include/xen/bootfdt.h @@ -0,0 +1,196 @@ +#ifndef __XEN_BOOTFDT_H__ +#define __XEN_BOOTFDT_H__ + +#include +#include +#include + +#define MIN_FDT_ALIGN 8 +#define MAX_FDT_SIZE SZ_2M + +#define NR_MEM_BANKS 256 +#define NR_SHMEM_BANKS 32 + +#define MAX_MODULES 32 /* Current maximum useful modules */ + +typedef enum { + BOOTMOD_XEN, + BOOTMOD_FDT, + BOOTMOD_KERNEL, + BOOTMOD_RAMDISK, + BOOTMOD_XSM, + BOOTMOD_GUEST_DTB, + BOOTMOD_UNKNOWN +} bootmodule_kind; + +enum membank_type { + /* + * The MEMBANK_DEFAULT type refers to either reserved memory for the + * device/firmware (when the bank is in 'reserved_mem') or any RAM (when + * the bank is in 'mem'). + */ + MEMBANK_DEFAULT, + /* + * The MEMBANK_STATIC_DOMAIN type is used to indicate whether the memory + * bank is bound to a static Xen domain. It is only valid when the bank + * is in reserved_mem. + */ + MEMBANK_STATIC_DOMAIN, + /* + * The MEMBANK_STATIC_HEAP type is used to indicate whether the memory + * bank is reserved as static heap. It is only valid when the bank is + * in reserved_mem. + */ + MEMBANK_STATIC_HEAP, + /* + * The MEMBANK_FDT_RESVMEM type is used to indicate whether the memory + * bank is from the FDT reserve map. + */ + MEMBANK_FDT_RESVMEM, +}; + +/* Indicates the maximum number of characters(\0 included) for shm_id */ +#define MAX_SHM_ID_LENGTH 16 + +struct shmem_membank_extra { + char shm_id[MAX_SHM_ID_LENGTH]; + unsigned int nr_shm_borrowers; +}; + +struct membank { + paddr_t start; + paddr_t size; + union { + enum membank_type type; +#ifdef CONFIG_STATIC_SHM + struct shmem_membank_extra *shmem_extra; +#endif + }; +}; + +struct membanks { + __struct_group(membanks_hdr, common, , + unsigned int nr_banks; + unsigned int max_banks; + ); + struct membank bank[]; +}; + +struct meminfo { + struct membanks_hdr common; + struct membank bank[NR_MEM_BANKS]; +}; + +struct shared_meminfo { + struct membanks_hdr common; + struct membank bank[NR_SHMEM_BANKS]; + struct shmem_membank_extra extra[NR_SHMEM_BANKS]; +}; + +/* + * The domU flag is set for kernels and ramdisks of "xen,domain" nodes. + * The purpose of the domU flag is to avoid getting confused in + * kernel_probe, where we try to guess which is the dom0 kernel and + * initrd to be compatible with all versions of the multiboot spec. + */ +#define BOOTMOD_MAX_CMDLINE 1024 +struct bootmodule { + bootmodule_kind kind; + bool domU; + paddr_t start; + paddr_t size; +}; + +/* DT_MAX_NAME is the node name max length according the DT spec */ +#define DT_MAX_NAME 41 +struct bootcmdline { + bootmodule_kind kind; + bool domU; + paddr_t start; + char dt_name[DT_MAX_NAME]; + char cmdline[BOOTMOD_MAX_CMDLINE]; +}; + +struct bootmodules { + int nr_mods; + struct bootmodule module[MAX_MODULES]; +}; + +struct bootcmdlines { + unsigned int nr_mods; + struct bootcmdline cmdline[MAX_MODULES]; +}; + +struct bootinfo { + struct meminfo mem; + /* The reserved regions are only used when booting using Device-Tree */ + struct meminfo reserved_mem; + struct bootmodules modules; + struct bootcmdlines cmdlines; +#ifdef CONFIG_ACPI + struct meminfo acpi; +#endif +#ifdef CONFIG_STATIC_SHM + struct shared_meminfo shmem; +#endif + bool static_heap; +}; + +#ifdef CONFIG_ACPI +#define BOOTINFO_ACPI_INIT .acpi.common.max_banks = NR_MEM_BANKS, +#else +#define BOOTINFO_ACPI_INIT +#endif + +#ifdef CONFIG_STATIC_SHM +#define BOOTINFO_SHMEM_INIT .shmem.common.max_banks = NR_SHMEM_BANKS, +#else +#define BOOTINFO_SHMEM_INIT +#endif + +#define BOOTINFO_INIT \ +{ \ + .mem.common.max_banks = NR_MEM_BANKS, \ + .reserved_mem.common.max_banks = NR_MEM_BANKS, \ + BOOTINFO_ACPI_INIT \ + BOOTINFO_SHMEM_INIT \ +} + +extern struct bootinfo bootinfo; + +void populate_boot_allocator(void); + +size_t boot_fdt_info(const void *fdt, paddr_t paddr); + +const char *boot_fdt_cmdline(const void *fdt); + +static inline struct membanks *bootinfo_get_reserved_mem(void) +{ + return container_of(&bootinfo.reserved_mem.common, struct membanks, common); +} + +static inline struct membanks *bootinfo_get_mem(void) +{ + return container_of(&bootinfo.mem.common, struct membanks, common); +} + +#ifdef CONFIG_ACPI +static inline struct membanks *bootinfo_get_acpi(void) +{ + return container_of(&bootinfo.acpi.common, struct membanks, common); +} +#endif + +#ifdef CONFIG_STATIC_SHM +static inline struct membanks *bootinfo_get_shmem(void) +{ + return container_of(&bootinfo.shmem.common, struct membanks, common); +} + +static inline struct shmem_membank_extra *bootinfo_get_shmem_extra(void) +{ + return bootinfo.shmem.extra; +} +#endif + +#endif /* __XEN_BOOTFDT_H__ */ From patchwork Wed Jul 3 10:42:48 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oleksii Kurochko X-Patchwork-Id: 13721969 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 5855AC2BD09 for ; Wed, 3 Jul 2024 10:43:14 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.752893.1161154 (Exim 4.92) (envelope-from ) id 1sOxS3-0004Oo-Nx; Wed, 03 Jul 2024 10:43:03 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 752893.1161154; Wed, 03 Jul 2024 10:43:03 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1sOxS3-0004OA-J8; Wed, 03 Jul 2024 10:43:03 +0000 Received: by outflank-mailman (input) for mailman id 752893; Wed, 03 Jul 2024 10:43:01 +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 1sOxS1-0003lU-HK for xen-devel@lists.xenproject.org; Wed, 03 Jul 2024 10:43:01 +0000 Received: from mail-ej1-x62a.google.com (mail-ej1-x62a.google.com [2a00:1450:4864:20::62a]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id 034d3f08-3929-11ef-bbf9-fd08da9f4363; Wed, 03 Jul 2024 12:42:58 +0200 (CEST) Received: by mail-ej1-x62a.google.com with SMTP id a640c23a62f3a-a72510ebc3fso779356966b.2 for ; Wed, 03 Jul 2024 03:42:58 -0700 (PDT) Received: from fedora.. ([94.75.70.14]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a72b92985desm414590066b.78.2024.07.03.03.42.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 03 Jul 2024 03:42:56 -0700 (PDT) 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: 034d3f08-3929-11ef-bbf9-fd08da9f4363 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1720003377; x=1720608177; 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=S+mmgGHkom1l7cI0McTp9fFuVf4sNnNnUkwvunhTG0Y=; b=ZvsTNERvTIZLc3ib+aZSYJeXNty4K0fT3HQe+e57LUCZttucm8WDeel1S8JcehvmW/ iiK5jWOZIWE08J6vOWjua8z9wgKSv5tpj/xewnuVUcP/le662RNzRb/NTRlDzll7cMSx 8lZxKruRF3UAM9YP8oq6FTOhq2OJi2tLDJCzzSNzHlMIwTDK1+BNdAXjE5dgrNBQsap6 UJOh2IaTqmLvjj6qux/biV8HeOucw3VLdcHOoVgWWV8+Wenn0YPG2dNJj7p9T3/oZzpM IOFzI+35VPRnzTQy7sZgZsVJNMwMFLsZpL1NO6925HSliBkasKODZ/S8iJucf//eJo0q qbqQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1720003377; x=1720608177; 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=S+mmgGHkom1l7cI0McTp9fFuVf4sNnNnUkwvunhTG0Y=; b=X6/mJuIxXWIdXnTbOQO2Os0mCelkNDparRzUvDKqqkKmwRV5olzwWiN5t2TbQWmhII zHr61UuM4ys7IcE4sfng0jPGNARnpI+b/yn9QNf6FVZo1Y/DNxvRHgaSZO64m4u4pMpa VI3Vwz4Ae2gw4aENRr9Uq+Ip+JFofmQBZrhMC8+tDy1hbzjz/LWfG5Dxb6hJtnUpoOHr 1BQ7iPVYwmSTmE14CytpQGO84/wgL14VWX9VFZ+BZEFosLkd4z3fUORMN1YnepKiPljy SnHN+x4LT3yZLKreKZRDOka7rfD4iRhP8bMdVbzLQrXdmDrFhrDPyd8Wu+JkFIirkTmj 6BfA== X-Gm-Message-State: AOJu0YwKJFh045ScFjOaO6pF9LtSAW0IxIL3EybdFbRpgf5kWCDMkvZ+ TnQ2I1cobYcNNaVFf25mK0mZLQi3clZgivNJgjkL0PIf8/ozeKYDZU17iol1 X-Google-Smtp-Source: AGHT+IHo5wfe88NVcKg1QTI0+ivZkcs5iviIbnSNAj5T6oz5egI7thHfnYgeJ3GbwNv0rlRSFNNaBw== X-Received: by 2002:a17:907:7242:b0:a69:67e3:57f6 with SMTP id a640c23a62f3a-a751443c678mr881716566b.5.1720003377078; Wed, 03 Jul 2024 03:42:57 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Shawn Anastasio , Stefano Stabellini , Julien Grall , Bertrand Marquis , Michal Orzel , Volodymyr Babchuk , "Daniel P. Smith" , Oleksii Kurochko Subject: [PATCH v1 2/5] xen/common: Move Arm's bootfdt.c to common Date: Wed, 3 Jul 2024 12:42:48 +0200 Message-ID: X-Mailer: git-send-email 2.45.2 In-Reply-To: References: MIME-Version: 1.0 From: Shawn Anastasio Move Arm's bootfdt.c to xen/common so that it can be used by other device tree architectures like PPC and RISCV. Suggested-by: Julien Grall Signed-off-by: Shawn Anastasio Acked-by: Julien Grall Signed-off-by: Oleksii Kurochko --- Changes in v5: - add guard #ifdef CONFIG_STATIC_SHM around inclusion of in common/device-tree/bootfdt.c. - add stub for process_shm_node() in case CONFIG_STATIC_SHM isn't enabled. - add guard around #ifdef CONFIG_STATIC_SHM aroud early_print_info_shmem() in early_print_info(). --- Changes in v4: - move function prototypes to patch 2's xen/include/bootfdt.h - clean up #includes --- xen/arch/arm/Makefile | 1 - xen/arch/arm/bootfdt.c | 622 ------------------------------ xen/arch/arm/include/asm/setup.h | 13 - xen/common/device-tree/Makefile | 1 + xen/common/device-tree/bootfdt.c | 635 +++++++++++++++++++++++++++++++ xen/include/xen/bootfdt.h | 14 + 6 files changed, 650 insertions(+), 636 deletions(-) delete mode 100644 xen/arch/arm/bootfdt.c create mode 100644 xen/common/device-tree/bootfdt.c diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile index 45dc29ea53..da9c979dc4 100644 --- a/xen/arch/arm/Makefile +++ b/xen/arch/arm/Makefile @@ -10,7 +10,6 @@ obj-$(CONFIG_TEE) += tee/ obj-$(CONFIG_HAS_VPCI) += vpci.o obj-$(CONFIG_HAS_ALTERNATIVE) += alternative.o -obj-y += bootfdt.init.o obj-y += cpuerrata.o obj-y += cpufeature.o obj-y += decode.o diff --git a/xen/arch/arm/bootfdt.c b/xen/arch/arm/bootfdt.c deleted file mode 100644 index 6e060111d9..0000000000 --- a/xen/arch/arm/bootfdt.c +++ /dev/null @@ -1,622 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Early Device Tree - * - * Copyright (C) 2012-2014 Citrix Systems, Inc. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static void __init __maybe_unused build_assertions(void) -{ - /* - * Check that no padding is between struct membanks "bank" flexible array - * member and struct meminfo "bank" member - */ - BUILD_BUG_ON((offsetof(struct membanks, bank) != - offsetof(struct meminfo, bank))); - /* Ensure "struct membanks" is 8-byte aligned */ - BUILD_BUG_ON(alignof(struct membanks) != 8); -} - -static bool __init device_tree_node_is_available(const void *fdt, int node) -{ - const char *status; - int len; - - status = fdt_getprop(fdt, node, "status", &len); - if ( !status ) - return true; - - if ( len > 0 ) - { - if ( !strcmp(status, "ok") || !strcmp(status, "okay") ) - return true; - } - - return false; -} - -static bool __init device_tree_node_matches(const void *fdt, int node, - const char *match) -{ - const char *name; - size_t match_len; - - name = fdt_get_name(fdt, node, NULL); - match_len = strlen(match); - - /* Match both "match" and "match@..." patterns but not - "match-foo". */ - return strncmp(name, match, match_len) == 0 - && (name[match_len] == '@' || name[match_len] == '\0'); -} - -static bool __init device_tree_node_compatible(const void *fdt, int node, - const char *match) -{ - int len, l; - const void *prop; - - prop = fdt_getprop(fdt, node, "compatible", &len); - if ( prop == NULL ) - return false; - - while ( len > 0 ) { - if ( !dt_compat_cmp(prop, match) ) - return true; - l = strlen(prop) + 1; - prop += l; - len -= l; - } - - return false; -} - -void __init device_tree_get_reg(const __be32 **cell, uint32_t address_cells, - uint32_t size_cells, paddr_t *start, - paddr_t *size) -{ - uint64_t dt_start, dt_size; - - /* - * dt_next_cell will return uint64_t whereas paddr_t may not be 64-bit. - * Thus, there is an implicit cast from uint64_t to paddr_t. - */ - dt_start = dt_next_cell(address_cells, cell); - dt_size = dt_next_cell(size_cells, cell); - - if ( dt_start != (paddr_t)dt_start ) - { - printk("Physical address greater than max width supported\n"); - WARN(); - } - - if ( dt_size != (paddr_t)dt_size ) - { - printk("Physical size greater than max width supported\n"); - WARN(); - } - - /* - * Xen will truncate the address/size if it is greater than the maximum - * supported width and it will give an appropriate warning. - */ - *start = dt_start; - *size = dt_size; -} - -static int __init device_tree_get_meminfo(const void *fdt, int node, - const char *prop_name, - u32 address_cells, u32 size_cells, - struct membanks *mem, - enum membank_type type) -{ - const struct fdt_property *prop; - unsigned int i, banks; - const __be32 *cell; - u32 reg_cells = address_cells + size_cells; - paddr_t start, size; - - if ( !device_tree_node_is_available(fdt, node) ) - return 0; - - if ( address_cells < 1 || size_cells < 1 ) - { - printk("fdt: property `%s': invalid #address-cells or #size-cells", - prop_name); - return -EINVAL; - } - - prop = fdt_get_property(fdt, node, prop_name, NULL); - if ( !prop ) - return -ENOENT; - - cell = (const __be32 *)prop->data; - banks = fdt32_to_cpu(prop->len) / (reg_cells * sizeof (u32)); - - for ( i = 0; i < banks && mem->nr_banks < mem->max_banks; i++ ) - { - device_tree_get_reg(&cell, address_cells, size_cells, &start, &size); - if ( mem == bootinfo_get_reserved_mem() && - check_reserved_regions_overlap(start, size) ) - return -EINVAL; - /* Some DT may describe empty bank, ignore them */ - if ( !size ) - continue; - mem->bank[mem->nr_banks].start = start; - mem->bank[mem->nr_banks].size = size; - mem->bank[mem->nr_banks].type = type; - mem->nr_banks++; - } - - if ( i < banks ) - { - printk("Warning: Max number of supported memory regions reached.\n"); - return -ENOSPC; - } - - return 0; -} - -u32 __init device_tree_get_u32(const void *fdt, int node, - const char *prop_name, u32 dflt) -{ - const struct fdt_property *prop; - - prop = fdt_get_property(fdt, node, prop_name, NULL); - if ( !prop || prop->len < sizeof(u32) ) - return dflt; - - return fdt32_to_cpu(*(uint32_t*)prop->data); -} - -/** - * device_tree_for_each_node - iterate over all device tree sub-nodes - * @fdt: flat device tree. - * @node: parent node to start the search from - * @func: function to call for each sub-node. - * @data: data to pass to @func. - * - * Any nodes nested at DEVICE_TREE_MAX_DEPTH or deeper are ignored. - * - * Returns 0 if all nodes were iterated over successfully. If @func - * returns a value different from 0, that value is returned immediately. - */ -int __init device_tree_for_each_node(const void *fdt, int node, - device_tree_node_func func, - void *data) -{ - /* - * We only care about relative depth increments, assume depth of - * node is 0 for simplicity. - */ - int depth = 0; - const int first_node = node; - u32 address_cells[DEVICE_TREE_MAX_DEPTH]; - u32 size_cells[DEVICE_TREE_MAX_DEPTH]; - int ret; - - do { - const char *name = fdt_get_name(fdt, node, NULL); - u32 as, ss; - - if ( depth >= DEVICE_TREE_MAX_DEPTH ) - { - printk("Warning: device tree node `%s' is nested too deep\n", - name); - continue; - } - - as = depth > 0 ? address_cells[depth-1] : DT_ROOT_NODE_ADDR_CELLS_DEFAULT; - ss = depth > 0 ? size_cells[depth-1] : DT_ROOT_NODE_SIZE_CELLS_DEFAULT; - - address_cells[depth] = device_tree_get_u32(fdt, node, - "#address-cells", as); - size_cells[depth] = device_tree_get_u32(fdt, node, - "#size-cells", ss); - - /* skip the first node */ - if ( node != first_node ) - { - ret = func(fdt, node, name, depth, as, ss, data); - if ( ret != 0 ) - return ret; - } - - node = fdt_next_node(fdt, node, &depth); - } while ( node >= 0 && depth > 0 ); - - return 0; -} - -static int __init process_memory_node(const void *fdt, int node, - const char *name, int depth, - u32 address_cells, u32 size_cells, - struct membanks *mem) -{ - return device_tree_get_meminfo(fdt, node, "reg", address_cells, size_cells, - mem, MEMBANK_DEFAULT); -} - -static int __init process_reserved_memory_node(const void *fdt, int node, - const char *name, int depth, - u32 address_cells, - u32 size_cells, - void *data) -{ - int rc = process_memory_node(fdt, node, name, depth, address_cells, - size_cells, data); - - if ( rc == -ENOSPC ) - panic("Max number of supported reserved-memory regions reached.\n"); - else if ( rc != -ENOENT ) - return rc; - return 0; -} - -static int __init process_reserved_memory(const void *fdt, int node, - const char *name, int depth, - u32 address_cells, u32 size_cells) -{ - return device_tree_for_each_node(fdt, node, - process_reserved_memory_node, - bootinfo_get_reserved_mem()); -} - -static void __init process_multiboot_node(const void *fdt, int node, - const char *name, - u32 address_cells, u32 size_cells) -{ - static int __initdata kind_guess = 0; - const struct fdt_property *prop; - const __be32 *cell; - bootmodule_kind kind; - paddr_t start, size; - int len; - /* sizeof("/chosen/") + DT_MAX_NAME + '/' + DT_MAX_NAME + '/0' => 92 */ - char path[92]; - int parent_node, ret; - bool domU; - - parent_node = fdt_parent_offset(fdt, node); - ASSERT(parent_node >= 0); - - /* Check that the node is under "/chosen" (first 7 chars of path) */ - ret = fdt_get_path(fdt, node, path, sizeof (path)); - if ( ret != 0 || strncmp(path, "/chosen", 7) ) - return; - - prop = fdt_get_property(fdt, node, "reg", &len); - if ( !prop ) - panic("node %s missing `reg' property\n", name); - - if ( len < dt_cells_to_size(address_cells + size_cells) ) - panic("fdt: node `%s': `reg` property length is too short\n", - name); - - cell = (const __be32 *)prop->data; - device_tree_get_reg(&cell, address_cells, size_cells, &start, &size); - - if ( fdt_node_check_compatible(fdt, node, "xen,linux-zimage") == 0 || - fdt_node_check_compatible(fdt, node, "multiboot,kernel") == 0 ) - kind = BOOTMOD_KERNEL; - else if ( fdt_node_check_compatible(fdt, node, "xen,linux-initrd") == 0 || - fdt_node_check_compatible(fdt, node, "multiboot,ramdisk") == 0 ) - kind = BOOTMOD_RAMDISK; - else if ( fdt_node_check_compatible(fdt, node, "xen,xsm-policy") == 0 ) - kind = BOOTMOD_XSM; - else if ( fdt_node_check_compatible(fdt, node, "multiboot,device-tree") == 0 ) - kind = BOOTMOD_GUEST_DTB; - else - kind = BOOTMOD_UNKNOWN; - - /** - * Guess the kind of these first two unknowns respectively: - * (1) The first unknown must be kernel. - * (2) Detect the XSM Magic from the 2nd unknown: - * a. If it's XSM, set the kind as XSM, and that also means we - * won't load ramdisk; - * b. if it's not XSM, set the kind as ramdisk. - * So if user want to load ramdisk, it must be the 2nd unknown. - * We also detect the XSM Magic for the following unknowns, - * then set its kind according to the return value of has_xsm_magic. - */ - if ( kind == BOOTMOD_UNKNOWN ) - { - switch ( kind_guess++ ) - { - case 0: kind = BOOTMOD_KERNEL; break; - case 1: kind = BOOTMOD_RAMDISK; break; - default: break; - } - if ( kind_guess > 1 && has_xsm_magic(start) ) - kind = BOOTMOD_XSM; - } - - domU = fdt_node_check_compatible(fdt, parent_node, "xen,domain") == 0; - add_boot_module(kind, start, size, domU); - - prop = fdt_get_property(fdt, node, "bootargs", &len); - if ( !prop ) - return; - add_boot_cmdline(fdt_get_name(fdt, parent_node, &len), prop->data, - kind, start, domU); -} - -static int __init process_chosen_node(const void *fdt, int node, - const char *name, - u32 address_cells, u32 size_cells) -{ - const struct fdt_property *prop; - paddr_t start, end; - int len; - - if ( fdt_get_property(fdt, node, "xen,static-heap", NULL) ) - { - int rc; - - printk("Checking for static heap in /chosen\n"); - - rc = device_tree_get_meminfo(fdt, node, "xen,static-heap", - address_cells, size_cells, - bootinfo_get_reserved_mem(), - MEMBANK_STATIC_HEAP); - if ( rc ) - return rc; - - bootinfo.static_heap = true; - } - - printk("Checking for initrd in /chosen\n"); - - prop = fdt_get_property(fdt, node, "linux,initrd-start", &len); - if ( !prop ) - /* No initrd present. */ - return 0; - if ( len != sizeof(u32) && len != sizeof(u64) ) - { - printk("linux,initrd-start property has invalid length %d\n", len); - return -EINVAL; - } - start = dt_read_paddr((const void *)&prop->data, dt_size_to_cells(len)); - - prop = fdt_get_property(fdt, node, "linux,initrd-end", &len); - if ( !prop ) - { - printk("linux,initrd-end not present but -start was\n"); - return -EINVAL; - } - if ( len != sizeof(u32) && len != sizeof(u64) ) - { - printk("linux,initrd-end property has invalid length %d\n", len); - return -EINVAL; - } - end = dt_read_paddr((const void *)&prop->data, dt_size_to_cells(len)); - - if ( start >= end ) - { - printk("linux,initrd limits invalid: %"PRIpaddr" >= %"PRIpaddr"\n", - start, end); - return -EINVAL; - } - - printk("Initrd %"PRIpaddr"-%"PRIpaddr"\n", start, end); - - add_boot_module(BOOTMOD_RAMDISK, start, end-start, false); - - return 0; -} - -static int __init process_domain_node(const void *fdt, int node, - const char *name, - u32 address_cells, u32 size_cells) -{ - const struct fdt_property *prop; - - printk("Checking for \"xen,static-mem\" in domain node\n"); - - prop = fdt_get_property(fdt, node, "xen,static-mem", NULL); - if ( !prop ) - /* No "xen,static-mem" present. */ - return 0; - - return device_tree_get_meminfo(fdt, node, "xen,static-mem", address_cells, - size_cells, bootinfo_get_reserved_mem(), - MEMBANK_STATIC_DOMAIN); -} - -static int __init early_scan_node(const void *fdt, - int node, const char *name, int depth, - u32 address_cells, u32 size_cells, - void *data) -{ - int rc = 0; - - /* - * If Xen has been booted via UEFI, the memory banks are - * populated. So we should skip the parsing. - */ - if ( !efi_enabled(EFI_BOOT) && - device_tree_node_matches(fdt, node, "memory") ) - rc = process_memory_node(fdt, node, name, depth, - address_cells, size_cells, bootinfo_get_mem()); - else if ( depth == 1 && !dt_node_cmp(name, "reserved-memory") ) - rc = process_reserved_memory(fdt, node, name, depth, - address_cells, size_cells); - else if ( depth <= 3 && (device_tree_node_compatible(fdt, node, "xen,multiboot-module" ) || - device_tree_node_compatible(fdt, node, "multiboot,module" ))) - process_multiboot_node(fdt, node, name, address_cells, size_cells); - else if ( depth == 1 && device_tree_node_matches(fdt, node, "chosen") ) - rc = process_chosen_node(fdt, node, name, address_cells, size_cells); - else if ( depth == 2 && device_tree_node_compatible(fdt, node, "xen,domain") ) - rc = process_domain_node(fdt, node, name, address_cells, size_cells); - else if ( depth <= 3 && device_tree_node_compatible(fdt, node, "xen,domain-shared-memory-v1") ) - rc = process_shm_node(fdt, node, address_cells, size_cells); - - if ( rc < 0 ) - printk("fdt: node `%s': parsing failed\n", name); - return rc; -} - -static void __init early_print_info(void) -{ - const struct membanks *mi = bootinfo_get_mem(); - const struct membanks *mem_resv = bootinfo_get_reserved_mem(); - struct bootmodules *mods = &bootinfo.modules; - struct bootcmdlines *cmds = &bootinfo.cmdlines; - unsigned int i; - - for ( i = 0; i < mi->nr_banks; i++ ) - printk("RAM: %"PRIpaddr" - %"PRIpaddr"\n", - mi->bank[i].start, - mi->bank[i].start + mi->bank[i].size - 1); - printk("\n"); - for ( i = 0 ; i < mods->nr_mods; i++ ) - printk("MODULE[%d]: %"PRIpaddr" - %"PRIpaddr" %-12s\n", - i, - mods->module[i].start, - mods->module[i].start + mods->module[i].size, - boot_module_kind_as_string(mods->module[i].kind)); - - for ( i = 0; i < mem_resv->nr_banks; i++ ) - { - printk(" RESVD[%u]: %"PRIpaddr" - %"PRIpaddr"\n", i, - mem_resv->bank[i].start, - mem_resv->bank[i].start + mem_resv->bank[i].size - 1); - } - early_print_info_shmem(); - printk("\n"); - for ( i = 0 ; i < cmds->nr_mods; i++ ) - printk("CMDLINE[%"PRIpaddr"]:%s %s\n", cmds->cmdline[i].start, - cmds->cmdline[i].dt_name, - &cmds->cmdline[i].cmdline[0]); - printk("\n"); -} - -/* This function assumes that memory regions are not overlapped */ -static int __init cmp_memory_node(const void *key, const void *elem) -{ - const struct membank *handler0 = key; - const struct membank *handler1 = elem; - - if ( handler0->start < handler1->start ) - return -1; - - if ( handler0->start >= (handler1->start + handler1->size) ) - return 1; - - return 0; -} - -static void __init swap_memory_node(void *_a, void *_b, size_t size) -{ - struct membank *a = _a, *b = _b; - - SWAP(*a, *b); -} - -/** - * boot_fdt_info - initialize bootinfo from a DTB - * @fdt: flattened device tree binary - * - * Returns the size of the DTB. - */ -size_t __init boot_fdt_info(const void *fdt, paddr_t paddr) -{ - struct membanks *reserved_mem = bootinfo_get_reserved_mem(); - struct membanks *mem = bootinfo_get_mem(); - unsigned int i; - int nr_rsvd; - int ret; - - ret = fdt_check_header(fdt); - if ( ret < 0 ) - panic("No valid device tree\n"); - - add_boot_module(BOOTMOD_FDT, paddr, fdt_totalsize(fdt), false); - - nr_rsvd = fdt_num_mem_rsv(fdt); - if ( nr_rsvd < 0 ) - panic("Parsing FDT memory reserve map failed (%d)\n", nr_rsvd); - - for ( i = 0; i < nr_rsvd; i++ ) - { - struct membank *bank; - paddr_t s, sz; - - if ( fdt_get_mem_rsv_paddr(device_tree_flattened, i, &s, &sz) < 0 ) - continue; - - if ( reserved_mem->nr_banks < reserved_mem->max_banks ) - { - bank = &reserved_mem->bank[reserved_mem->nr_banks]; - bank->start = s; - bank->size = sz; - bank->type = MEMBANK_FDT_RESVMEM; - reserved_mem->nr_banks++; - } - else - panic("Cannot allocate reserved memory bank\n"); - } - - ret = device_tree_for_each_node(fdt, 0, early_scan_node, NULL); - if ( ret ) - panic("Early FDT parsing failed (%d)\n", ret); - - /* - * On Arm64 setup_directmap_mappings() expects to be called with the lowest - * bank in memory first. There is no requirement that the DT will provide - * the banks sorted in ascending order. So sort them through. - */ - sort(mem->bank, mem->nr_banks, sizeof(struct membank), - cmp_memory_node, swap_memory_node); - - early_print_info(); - - return fdt_totalsize(fdt); -} - -const __init char *boot_fdt_cmdline(const void *fdt) -{ - int node; - const struct fdt_property *prop; - - node = fdt_path_offset(fdt, "/chosen"); - if ( node < 0 ) - return NULL; - - prop = fdt_get_property(fdt, node, "xen,xen-bootargs", NULL); - if ( prop == NULL ) - { - struct bootcmdline *dom0_cmdline = - boot_cmdline_find_by_kind(BOOTMOD_KERNEL); - - if (fdt_get_property(fdt, node, "xen,dom0-bootargs", NULL) || - ( dom0_cmdline && dom0_cmdline->cmdline[0] ) ) - prop = fdt_get_property(fdt, node, "bootargs", NULL); - } - if ( prop == NULL ) - return NULL; - - return prop->data; -} - -/* - * Local variables: - * mode: C - * c-file-style: "BSD" - * c-basic-offset: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/xen/arch/arm/include/asm/setup.h b/xen/arch/arm/include/asm/setup.h index 051e796716..5ee690aeb2 100644 --- a/xen/arch/arm/include/asm/setup.h +++ b/xen/arch/arm/include/asm/setup.h @@ -39,19 +39,6 @@ void fw_unreserved_regions(paddr_t s, paddr_t e, void (*cb)(paddr_t ps, paddr_t pe), unsigned int first); -bool check_reserved_regions_overlap(paddr_t region_start, paddr_t region_size); - -struct bootmodule *add_boot_module(bootmodule_kind kind, - paddr_t start, paddr_t size, bool domU); -struct bootmodule *boot_module_find_by_kind(bootmodule_kind kind); -struct bootmodule * boot_module_find_by_addr_and_kind(bootmodule_kind kind, - paddr_t start); -void add_boot_cmdline(const char *name, const char *cmdline, - bootmodule_kind kind, paddr_t start, bool domU); -struct bootcmdline *boot_cmdline_find_by_kind(bootmodule_kind kind); -struct bootcmdline * boot_cmdline_find_by_name(const char *name); -const char *boot_module_kind_as_string(bootmodule_kind kind); - void init_pdx(void); void setup_mm(void); diff --git a/xen/common/device-tree/Makefile b/xen/common/device-tree/Makefile index 947bad979c..ff2de71c96 100644 --- a/xen/common/device-tree/Makefile +++ b/xen/common/device-tree/Makefile @@ -1 +1,2 @@ +obj-y += bootfdt.init.o obj-y += bootinfo.init.o diff --git a/xen/common/device-tree/bootfdt.c b/xen/common/device-tree/bootfdt.c new file mode 100644 index 0000000000..748b5f7c69 --- /dev/null +++ b/xen/common/device-tree/bootfdt.c @@ -0,0 +1,635 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Early Device Tree + * + * Copyright (C) 2012-2014 Citrix Systems, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_STATIC_SHM +#include +#endif + +static void __init __maybe_unused build_assertions(void) +{ + /* + * Check that no padding is between struct membanks "bank" flexible array + * member and struct meminfo "bank" member + */ + BUILD_BUG_ON((offsetof(struct membanks, bank) != + offsetof(struct meminfo, bank))); + /* Ensure "struct membanks" is 8-byte aligned */ + BUILD_BUG_ON(alignof(struct membanks) != 8); +} + +static bool __init device_tree_node_is_available(const void *fdt, int node) +{ + const char *status; + int len; + + status = fdt_getprop(fdt, node, "status", &len); + if ( !status ) + return true; + + if ( len > 0 ) + { + if ( !strcmp(status, "ok") || !strcmp(status, "okay") ) + return true; + } + + return false; +} + +static bool __init device_tree_node_matches(const void *fdt, int node, + const char *match) +{ + const char *name; + size_t match_len; + + name = fdt_get_name(fdt, node, NULL); + match_len = strlen(match); + + /* Match both "match" and "match@..." patterns but not + "match-foo". */ + return strncmp(name, match, match_len) == 0 + && (name[match_len] == '@' || name[match_len] == '\0'); +} + +static bool __init device_tree_node_compatible(const void *fdt, int node, + const char *match) +{ + int len, l; + const void *prop; + + prop = fdt_getprop(fdt, node, "compatible", &len); + if ( prop == NULL ) + return false; + + while ( len > 0 ) { + if ( !dt_compat_cmp(prop, match) ) + return true; + l = strlen(prop) + 1; + prop += l; + len -= l; + } + + return false; +} + +void __init device_tree_get_reg(const __be32 **cell, uint32_t address_cells, + uint32_t size_cells, paddr_t *start, + paddr_t *size) +{ + uint64_t dt_start, dt_size; + + /* + * dt_next_cell will return uint64_t whereas paddr_t may not be 64-bit. + * Thus, there is an implicit cast from uint64_t to paddr_t. + */ + dt_start = dt_next_cell(address_cells, cell); + dt_size = dt_next_cell(size_cells, cell); + + if ( dt_start != (paddr_t)dt_start ) + { + printk("Physical address greater than max width supported\n"); + WARN(); + } + + if ( dt_size != (paddr_t)dt_size ) + { + printk("Physical size greater than max width supported\n"); + WARN(); + } + + /* + * Xen will truncate the address/size if it is greater than the maximum + * supported width and it will give an appropriate warning. + */ + *start = dt_start; + *size = dt_size; +} + +static int __init device_tree_get_meminfo(const void *fdt, int node, + const char *prop_name, + u32 address_cells, u32 size_cells, + struct membanks *mem, + enum membank_type type) +{ + const struct fdt_property *prop; + unsigned int i, banks; + const __be32 *cell; + u32 reg_cells = address_cells + size_cells; + paddr_t start, size; + + if ( !device_tree_node_is_available(fdt, node) ) + return 0; + + if ( address_cells < 1 || size_cells < 1 ) + { + printk("fdt: property `%s': invalid #address-cells or #size-cells", + prop_name); + return -EINVAL; + } + + prop = fdt_get_property(fdt, node, prop_name, NULL); + if ( !prop ) + return -ENOENT; + + cell = (const __be32 *)prop->data; + banks = fdt32_to_cpu(prop->len) / (reg_cells * sizeof (u32)); + + for ( i = 0; i < banks && mem->nr_banks < mem->max_banks; i++ ) + { + device_tree_get_reg(&cell, address_cells, size_cells, &start, &size); + if ( mem == bootinfo_get_reserved_mem() && + check_reserved_regions_overlap(start, size) ) + return -EINVAL; + /* Some DT may describe empty bank, ignore them */ + if ( !size ) + continue; + mem->bank[mem->nr_banks].start = start; + mem->bank[mem->nr_banks].size = size; + mem->bank[mem->nr_banks].type = type; + mem->nr_banks++; + } + + if ( i < banks ) + { + printk("Warning: Max number of supported memory regions reached.\n"); + return -ENOSPC; + } + + return 0; +} + +u32 __init device_tree_get_u32(const void *fdt, int node, + const char *prop_name, u32 dflt) +{ + const struct fdt_property *prop; + + prop = fdt_get_property(fdt, node, prop_name, NULL); + if ( !prop || prop->len < sizeof(u32) ) + return dflt; + + return fdt32_to_cpu(*(uint32_t*)prop->data); +} + +/** + * device_tree_for_each_node - iterate over all device tree sub-nodes + * @fdt: flat device tree. + * @node: parent node to start the search from + * @func: function to call for each sub-node. + * @data: data to pass to @func. + * + * Any nodes nested at DEVICE_TREE_MAX_DEPTH or deeper are ignored. + * + * Returns 0 if all nodes were iterated over successfully. If @func + * returns a value different from 0, that value is returned immediately. + */ +int __init device_tree_for_each_node(const void *fdt, int node, + device_tree_node_func func, + void *data) +{ + /* + * We only care about relative depth increments, assume depth of + * node is 0 for simplicity. + */ + int depth = 0; + const int first_node = node; + u32 address_cells[DEVICE_TREE_MAX_DEPTH]; + u32 size_cells[DEVICE_TREE_MAX_DEPTH]; + int ret; + + do { + const char *name = fdt_get_name(fdt, node, NULL); + u32 as, ss; + + if ( depth >= DEVICE_TREE_MAX_DEPTH ) + { + printk("Warning: device tree node `%s' is nested too deep\n", + name); + continue; + } + + as = depth > 0 ? address_cells[depth-1] : DT_ROOT_NODE_ADDR_CELLS_DEFAULT; + ss = depth > 0 ? size_cells[depth-1] : DT_ROOT_NODE_SIZE_CELLS_DEFAULT; + + address_cells[depth] = device_tree_get_u32(fdt, node, + "#address-cells", as); + size_cells[depth] = device_tree_get_u32(fdt, node, + "#size-cells", ss); + + /* skip the first node */ + if ( node != first_node ) + { + ret = func(fdt, node, name, depth, as, ss, data); + if ( ret != 0 ) + return ret; + } + + node = fdt_next_node(fdt, node, &depth); + } while ( node >= 0 && depth > 0 ); + + return 0; +} + +static int __init process_memory_node(const void *fdt, int node, + const char *name, int depth, + u32 address_cells, u32 size_cells, + struct membanks *mem) +{ + return device_tree_get_meminfo(fdt, node, "reg", address_cells, size_cells, + mem, MEMBANK_DEFAULT); +} + +static int __init process_reserved_memory_node(const void *fdt, int node, + const char *name, int depth, + u32 address_cells, + u32 size_cells, + void *data) +{ + int rc = process_memory_node(fdt, node, name, depth, address_cells, + size_cells, data); + + if ( rc == -ENOSPC ) + panic("Max number of supported reserved-memory regions reached.\n"); + else if ( rc != -ENOENT ) + return rc; + return 0; +} + +static int __init process_reserved_memory(const void *fdt, int node, + const char *name, int depth, + u32 address_cells, u32 size_cells) +{ + return device_tree_for_each_node(fdt, node, + process_reserved_memory_node, + bootinfo_get_reserved_mem()); +} + +static void __init process_multiboot_node(const void *fdt, int node, + const char *name, + u32 address_cells, u32 size_cells) +{ + static int __initdata kind_guess = 0; + const struct fdt_property *prop; + const __be32 *cell; + bootmodule_kind kind; + paddr_t start, size; + int len; + /* sizeof("/chosen/") + DT_MAX_NAME + '/' + DT_MAX_NAME + '/0' => 92 */ + char path[92]; + int parent_node, ret; + bool domU; + + parent_node = fdt_parent_offset(fdt, node); + ASSERT(parent_node >= 0); + + /* Check that the node is under "/chosen" (first 7 chars of path) */ + ret = fdt_get_path(fdt, node, path, sizeof (path)); + if ( ret != 0 || strncmp(path, "/chosen", 7) ) + return; + + prop = fdt_get_property(fdt, node, "reg", &len); + if ( !prop ) + panic("node %s missing `reg' property\n", name); + + if ( len < dt_cells_to_size(address_cells + size_cells) ) + panic("fdt: node `%s': `reg` property length is too short\n", + name); + + cell = (const __be32 *)prop->data; + device_tree_get_reg(&cell, address_cells, size_cells, &start, &size); + + if ( fdt_node_check_compatible(fdt, node, "xen,linux-zimage") == 0 || + fdt_node_check_compatible(fdt, node, "multiboot,kernel") == 0 ) + kind = BOOTMOD_KERNEL; + else if ( fdt_node_check_compatible(fdt, node, "xen,linux-initrd") == 0 || + fdt_node_check_compatible(fdt, node, "multiboot,ramdisk") == 0 ) + kind = BOOTMOD_RAMDISK; + else if ( fdt_node_check_compatible(fdt, node, "xen,xsm-policy") == 0 ) + kind = BOOTMOD_XSM; + else if ( fdt_node_check_compatible(fdt, node, "multiboot,device-tree") == 0 ) + kind = BOOTMOD_GUEST_DTB; + else + kind = BOOTMOD_UNKNOWN; + + /** + * Guess the kind of these first two unknowns respectively: + * (1) The first unknown must be kernel. + * (2) Detect the XSM Magic from the 2nd unknown: + * a. If it's XSM, set the kind as XSM, and that also means we + * won't load ramdisk; + * b. if it's not XSM, set the kind as ramdisk. + * So if user want to load ramdisk, it must be the 2nd unknown. + * We also detect the XSM Magic for the following unknowns, + * then set its kind according to the return value of has_xsm_magic. + */ + if ( kind == BOOTMOD_UNKNOWN ) + { + switch ( kind_guess++ ) + { + case 0: kind = BOOTMOD_KERNEL; break; + case 1: kind = BOOTMOD_RAMDISK; break; + default: break; + } + if ( kind_guess > 1 && has_xsm_magic(start) ) + kind = BOOTMOD_XSM; + } + + domU = fdt_node_check_compatible(fdt, parent_node, "xen,domain") == 0; + add_boot_module(kind, start, size, domU); + + prop = fdt_get_property(fdt, node, "bootargs", &len); + if ( !prop ) + return; + add_boot_cmdline(fdt_get_name(fdt, parent_node, &len), prop->data, + kind, start, domU); +} + +static int __init process_chosen_node(const void *fdt, int node, + const char *name, + u32 address_cells, u32 size_cells) +{ + const struct fdt_property *prop; + paddr_t start, end; + int len; + + if ( fdt_get_property(fdt, node, "xen,static-heap", NULL) ) + { + int rc; + + printk("Checking for static heap in /chosen\n"); + + rc = device_tree_get_meminfo(fdt, node, "xen,static-heap", + address_cells, size_cells, + bootinfo_get_reserved_mem(), + MEMBANK_STATIC_HEAP); + if ( rc ) + return rc; + + bootinfo.static_heap = true; + } + + printk("Checking for initrd in /chosen\n"); + + prop = fdt_get_property(fdt, node, "linux,initrd-start", &len); + if ( !prop ) + /* No initrd present. */ + return 0; + if ( len != sizeof(u32) && len != sizeof(u64) ) + { + printk("linux,initrd-start property has invalid length %d\n", len); + return -EINVAL; + } + start = dt_read_paddr((const void *)&prop->data, dt_size_to_cells(len)); + + prop = fdt_get_property(fdt, node, "linux,initrd-end", &len); + if ( !prop ) + { + printk("linux,initrd-end not present but -start was\n"); + return -EINVAL; + } + if ( len != sizeof(u32) && len != sizeof(u64) ) + { + printk("linux,initrd-end property has invalid length %d\n", len); + return -EINVAL; + } + end = dt_read_paddr((const void *)&prop->data, dt_size_to_cells(len)); + + if ( start >= end ) + { + printk("linux,initrd limits invalid: %"PRIpaddr" >= %"PRIpaddr"\n", + start, end); + return -EINVAL; + } + + printk("Initrd %"PRIpaddr"-%"PRIpaddr"\n", start, end); + + add_boot_module(BOOTMOD_RAMDISK, start, end-start, false); + + return 0; +} + +static int __init process_domain_node(const void *fdt, int node, + const char *name, + u32 address_cells, u32 size_cells) +{ + const struct fdt_property *prop; + + printk("Checking for \"xen,static-mem\" in domain node\n"); + + prop = fdt_get_property(fdt, node, "xen,static-mem", NULL); + if ( !prop ) + /* No "xen,static-mem" present. */ + return 0; + + return device_tree_get_meminfo(fdt, node, "xen,static-mem", address_cells, + size_cells, bootinfo_get_reserved_mem(), + MEMBANK_STATIC_DOMAIN); +} + +#ifndef CONFIG_STATIC_SHM +static inline int process_shm_node(const void *fdt, int node, + uint32_t address_cells, uint32_t size_cells) +{ + printk("CONFIG_STATIC_SHM must be enabled for parsing static shared" + " memory nodes\n"); + return -EINVAL; +} +#endif + +static int __init early_scan_node(const void *fdt, + int node, const char *name, int depth, + u32 address_cells, u32 size_cells, + void *data) +{ + int rc = 0; + + /* + * If Xen has been booted via UEFI, the memory banks are + * populated. So we should skip the parsing. + */ + if ( !efi_enabled(EFI_BOOT) && + device_tree_node_matches(fdt, node, "memory") ) + rc = process_memory_node(fdt, node, name, depth, + address_cells, size_cells, bootinfo_get_mem()); + else if ( depth == 1 && !dt_node_cmp(name, "reserved-memory") ) + rc = process_reserved_memory(fdt, node, name, depth, + address_cells, size_cells); + else if ( depth <= 3 && (device_tree_node_compatible(fdt, node, "xen,multiboot-module" ) || + device_tree_node_compatible(fdt, node, "multiboot,module" ))) + process_multiboot_node(fdt, node, name, address_cells, size_cells); + else if ( depth == 1 && device_tree_node_matches(fdt, node, "chosen") ) + rc = process_chosen_node(fdt, node, name, address_cells, size_cells); + else if ( depth == 2 && device_tree_node_compatible(fdt, node, "xen,domain") ) + rc = process_domain_node(fdt, node, name, address_cells, size_cells); + else if ( depth <= 3 && device_tree_node_compatible(fdt, node, "xen,domain-shared-memory-v1") ) + rc = process_shm_node(fdt, node, address_cells, size_cells); + + if ( rc < 0 ) + printk("fdt: node `%s': parsing failed\n", name); + return rc; +} + +static void __init early_print_info(void) +{ + const struct membanks *mi = bootinfo_get_mem(); + const struct membanks *mem_resv = bootinfo_get_reserved_mem(); + struct bootmodules *mods = &bootinfo.modules; + struct bootcmdlines *cmds = &bootinfo.cmdlines; + unsigned int i; + + for ( i = 0; i < mi->nr_banks; i++ ) + printk("RAM: %"PRIpaddr" - %"PRIpaddr"\n", + mi->bank[i].start, + mi->bank[i].start + mi->bank[i].size - 1); + printk("\n"); + for ( i = 0 ; i < mods->nr_mods; i++ ) + printk("MODULE[%d]: %"PRIpaddr" - %"PRIpaddr" %-12s\n", + i, + mods->module[i].start, + mods->module[i].start + mods->module[i].size, + boot_module_kind_as_string(mods->module[i].kind)); + + for ( i = 0; i < mem_resv->nr_banks; i++ ) + { + printk(" RESVD[%u]: %"PRIpaddr" - %"PRIpaddr"\n", i, + mem_resv->bank[i].start, + mem_resv->bank[i].start + mem_resv->bank[i].size - 1); + } +#ifdef CONFIG_STATIC_SHM + early_print_info_shmem(); +#endif + printk("\n"); + for ( i = 0 ; i < cmds->nr_mods; i++ ) + printk("CMDLINE[%"PRIpaddr"]:%s %s\n", cmds->cmdline[i].start, + cmds->cmdline[i].dt_name, + &cmds->cmdline[i].cmdline[0]); + printk("\n"); +} + +/* This function assumes that memory regions are not overlapped */ +static int __init cmp_memory_node(const void *key, const void *elem) +{ + const struct membank *handler0 = key; + const struct membank *handler1 = elem; + + if ( handler0->start < handler1->start ) + return -1; + + if ( handler0->start >= (handler1->start + handler1->size) ) + return 1; + + return 0; +} + +static void __init swap_memory_node(void *_a, void *_b, size_t size) +{ + struct membank *a = _a, *b = _b; + + SWAP(*a, *b); +} + +/** + * boot_fdt_info - initialize bootinfo from a DTB + * @fdt: flattened device tree binary + * + * Returns the size of the DTB. + */ +size_t __init boot_fdt_info(const void *fdt, paddr_t paddr) +{ + struct membanks *reserved_mem = bootinfo_get_reserved_mem(); + struct membanks *mem = bootinfo_get_mem(); + unsigned int i; + int nr_rsvd; + int ret; + + ret = fdt_check_header(fdt); + if ( ret < 0 ) + panic("No valid device tree\n"); + + add_boot_module(BOOTMOD_FDT, paddr, fdt_totalsize(fdt), false); + + nr_rsvd = fdt_num_mem_rsv(fdt); + if ( nr_rsvd < 0 ) + panic("Parsing FDT memory reserve map failed (%d)\n", nr_rsvd); + + for ( i = 0; i < nr_rsvd; i++ ) + { + struct membank *bank; + paddr_t s, sz; + + if ( fdt_get_mem_rsv_paddr(device_tree_flattened, i, &s, &sz) < 0 ) + continue; + + if ( reserved_mem->nr_banks < reserved_mem->max_banks ) + { + bank = &reserved_mem->bank[reserved_mem->nr_banks]; + bank->start = s; + bank->size = sz; + bank->type = MEMBANK_FDT_RESVMEM; + reserved_mem->nr_banks++; + } + else + panic("Cannot allocate reserved memory bank\n"); + } + + ret = device_tree_for_each_node(fdt, 0, early_scan_node, NULL); + if ( ret ) + panic("Early FDT parsing failed (%d)\n", ret); + + /* + * On Arm64 setup_directmap_mappings() expects to be called with the lowest + * bank in memory first. There is no requirement that the DT will provide + * the banks sorted in ascending order. So sort them through. + */ + sort(mem->bank, mem->nr_banks, sizeof(struct membank), + cmp_memory_node, swap_memory_node); + + early_print_info(); + + return fdt_totalsize(fdt); +} + +const __init char *boot_fdt_cmdline(const void *fdt) +{ + int node; + const struct fdt_property *prop; + + node = fdt_path_offset(fdt, "/chosen"); + if ( node < 0 ) + return NULL; + + prop = fdt_get_property(fdt, node, "xen,xen-bootargs", NULL); + if ( prop == NULL ) + { + struct bootcmdline *dom0_cmdline = + boot_cmdline_find_by_kind(BOOTMOD_KERNEL); + + if (fdt_get_property(fdt, node, "xen,dom0-bootargs", NULL) || + ( dom0_cmdline && dom0_cmdline->cmdline[0] ) ) + prop = fdt_get_property(fdt, node, "bootargs", NULL); + } + if ( prop == NULL ) + return NULL; + + return prop->data; +} + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/include/xen/bootfdt.h b/xen/include/xen/bootfdt.h index 7cd45b3d4b..5943bc5fe3 100644 --- a/xen/include/xen/bootfdt.h +++ b/xen/include/xen/bootfdt.h @@ -158,6 +158,20 @@ struct bootinfo { extern struct bootinfo bootinfo; +bool check_reserved_regions_overlap(paddr_t region_start, + paddr_t region_size); + +struct bootmodule *add_boot_module(bootmodule_kind kind, + paddr_t start, paddr_t size, bool domU); +struct bootmodule *boot_module_find_by_kind(bootmodule_kind kind); +struct bootmodule * boot_module_find_by_addr_and_kind(bootmodule_kind kind, + paddr_t start); +void add_boot_cmdline(const char *name, const char *cmdline, + bootmodule_kind kind, paddr_t start, bool domU); +struct bootcmdline *boot_cmdline_find_by_kind(bootmodule_kind kind); +struct bootcmdline * boot_cmdline_find_by_name(const char *name); +const char *boot_module_kind_as_string(bootmodule_kind kind); + void populate_boot_allocator(void); size_t boot_fdt_info(const void *fdt, paddr_t paddr); From patchwork Wed Jul 3 10:42:49 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oleksii Kurochko X-Patchwork-Id: 13721966 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 7F621C30653 for ; Wed, 3 Jul 2024 10:43:12 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.752891.1161142 (Exim 4.92) (envelope-from ) id 1sOxS3-0004Fs-3o; Wed, 03 Jul 2024 10:43:03 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 752891.1161142; Wed, 03 Jul 2024 10:43:03 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1sOxS3-0004Fl-0y; Wed, 03 Jul 2024 10:43:03 +0000 Received: by outflank-mailman (input) for mailman id 752891; Wed, 03 Jul 2024 10:43:01 +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 1sOxS1-0003zy-0H for xen-devel@lists.xenproject.org; Wed, 03 Jul 2024 10:43:01 +0000 Received: from mail-ej1-x62f.google.com (mail-ej1-x62f.google.com [2a00:1450:4864:20::62f]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id 0391a4ad-3929-11ef-8776-851b0ebba9a2; Wed, 03 Jul 2024 12:42:59 +0200 (CEST) Received: by mail-ej1-x62f.google.com with SMTP id a640c23a62f3a-a70c0349b64so684727366b.1 for ; Wed, 03 Jul 2024 03:42:58 -0700 (PDT) Received: from fedora.. ([94.75.70.14]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a72b92985desm414590066b.78.2024.07.03.03.42.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 03 Jul 2024 03:42:57 -0700 (PDT) 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: 0391a4ad-3929-11ef-8776-851b0ebba9a2 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1720003378; x=1720608178; 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=/G/A7NPWRh6mPuP+ZzOUK2A1wKjvppqVXw3/IEnVJxs=; b=ak0tmmX/ZQjBL43Gvuil5z1AQUKmCbHBd+EiPiJGmMW+rD2czkAm1kBE2H8LE6mo9O IcroTJ2MA9ni0HdxvZBzsp54pw+XllDChjw1guzTAytis3iFxwlEaYmCd+7Dw0s31KQW uGxpkHCD9GxAzLrro75gzeS6GxeCvb5fdm4vbQMLK7O0As9Ceq80W+KOap4tL1HJrXCL dtMVcYaUQ1dYGd5+KaIsNdb2M7GCTiHRDLZQGvjTJg0yyhuwKbv0VqrU+2WBZ6LhmUix tUMSnT9DHPQf1W7sha7Vm7n76pSmaN9eaytxsYzILRoDzbMrDhXX9FDiuQlJThpBJeLW zaIA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1720003378; x=1720608178; 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=/G/A7NPWRh6mPuP+ZzOUK2A1wKjvppqVXw3/IEnVJxs=; b=qfRYYmUQP7jJwFnpTJdBZMeIR43NjoTsDAFt/fVJ+8wX7UgfFNmD7SX2/EDZJygxZI W+DOsy0yE8QA7c44mgp6pGTiQJuZWSNOpqYnNNpf8JUjBGkstYQjz4CYV0kdZ8UFwfJc XTJgcNYMBXeA5cdp2+YtPAuXibln1wWA4S3WiYLZFhXx4c7yG8OA3V0LJxY9o9Piypql /EBCfi8cZAILuDEOO5+yCiahBAKwmbShDKyaLu6BuWUe5425wmIFL2ERpjLBiffktVEQ qHzBnU4SZuxqSPs4AzpOGwU8DmlN+oJwpaKX/b4F8wL8U4A55YOxfPG1CaFZP90F68He hRxQ== X-Gm-Message-State: AOJu0YzTqR3LEqHrLr0eyAhysexhjSF/1AHOuRkbvurpHau0STCJQ0B/ QdY/wIRVPBbY81aD5vcGty/1J5aLJRWtxrGE/W/i7LUXPHrWZ85kt4SKIQXK X-Google-Smtp-Source: AGHT+IF0e8OlBOffvF4PdyITNIFA1vPC47T7cI8Tz6isT4NspLNQ0rQK8izoqHNJIJNzCDw7uMtKsw== X-Received: by 2002:a17:907:6e9f:b0:a72:7d5c:ace0 with SMTP id a640c23a62f3a-a751440bbaemr799692866b.11.1720003377862; Wed, 03 Jul 2024 03:42:57 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Oleksii Kurochko , Alistair Francis , Bob Eshleman , Connor Davis , Andrew Cooper , Jan Beulich , Julien Grall , Stefano Stabellini Subject: [PATCH v1 3/5] xen/riscv: enable CONFIG_HAS_DEVICE_TREE Date: Wed, 3 Jul 2024 12:42:49 +0200 Message-ID: <8861be6624f50c927a8dadbcf056aff2dc0576ab.1720002425.git.oleksii.kurochko@gmail.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: References: MIME-Version: 1.0 Signed-off-by: Oleksii Kurochko --- xen/arch/riscv/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/xen/arch/riscv/Kconfig b/xen/arch/riscv/Kconfig index 74ad019fe7..1863a5d117 100644 --- a/xen/arch/riscv/Kconfig +++ b/xen/arch/riscv/Kconfig @@ -5,6 +5,7 @@ config RISCV config RISCV_64 def_bool y select 64BIT + select HAS_DEVICE_TREE select GENERIC_BUG_FRAME config ARCH_DEFCONFIG From patchwork Wed Jul 3 10:42:50 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oleksii Kurochko X-Patchwork-Id: 13721964 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 25A4FC2BD09 for ; Wed, 3 Jul 2024 10:43:11 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.752892.1161146 (Exim 4.92) (envelope-from ) id 1sOxS3-0004JR-EA; Wed, 03 Jul 2024 10:43:03 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 752892.1161146; Wed, 03 Jul 2024 10:43:03 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1sOxS3-0004I8-9l; Wed, 03 Jul 2024 10:43:03 +0000 Received: by outflank-mailman (input) for mailman id 752892; Wed, 03 Jul 2024 10:43:01 +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 1sOxS1-0003zy-Lw for xen-devel@lists.xenproject.org; Wed, 03 Jul 2024 10:43:01 +0000 Received: from mail-ed1-x52e.google.com (mail-ed1-x52e.google.com [2a00:1450:4864:20::52e]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id 03f34818-3929-11ef-8776-851b0ebba9a2; Wed, 03 Jul 2024 12:42:59 +0200 (CEST) Received: by mail-ed1-x52e.google.com with SMTP id 4fb4d7f45d1cf-58ba3e38028so2460041a12.0 for ; Wed, 03 Jul 2024 03:42:59 -0700 (PDT) Received: from fedora.. ([94.75.70.14]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a72b92985desm414590066b.78.2024.07.03.03.42.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 03 Jul 2024 03:42:58 -0700 (PDT) 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: 03f34818-3929-11ef-8776-851b0ebba9a2 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1720003379; x=1720608179; 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=tu9SsKtiznAxphg8ImBUJ4LDe0odH7NePw+yOiQLnos=; b=TTRBC95WAVrH0I7uCBpXqM+UR19zPGL/AusvlzwnmULEZSMJmUlbldye7GWB4CWVVo sump2aF68JRVZV99vyHmesDAvbpfcnXPN1RpgBRehLiAb/6RfS4YXaISunN+gGx2R+vV krh87V23Y7syC+q6Hbxb+BXxlEVcZoR49bro2+7ZdWMVn5scjiQ5tbNI24s4ah6wLsCU XYHXmngcPRBzrYW7jRM+AdQZVFedpokTMpHPYgnGj3agRddTHZ2x9m5LHB2lglGlPIVg 66iD0aLvD/Xpwvp8UYFXecs3jjbonTzyp0QoZ4u1Azxh0uqNwUSgC+nR9kqKGmB5hmoT Se8g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1720003379; x=1720608179; 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=tu9SsKtiznAxphg8ImBUJ4LDe0odH7NePw+yOiQLnos=; b=Jk1vMJCKNeuc+DAVyDdZdIC3R8de/n0MqtzVGPZjE4M42H63xMosnQOQJniKDIT1DY ZaEfPQwQpz4c+Edm9lbZOFxQcvehB2k9WzxtXP+ml199RyXtlqpEZwHSBme7prAYtGuq 7k5DmjgOljH0UNgHREvRhyKtpX2964YCn03aFM+ywosIzrhmXBTFtMhoUQ8srWwxTdD8 HYDetBLGN/Lbl9LXXPMePmZN5T1Ie6grqRXZcmQ1GD/kB34FMgTLg9RUJ37QpwFk0Ts2 b9Y6e2J3yP0kQlDhWqGQO+vpNkwS1qFw3pI6ub+wfTmz+cxAMvPU06qG+IGXyrSTj5Mv lcJg== X-Gm-Message-State: AOJu0YzXN1yorC277OrfAy/xuApBmHvcYgH3whSrOyZvSSJKh2LoWeep cwyYrzY71xps8kwrppJy6TXntwIfcLhovI0g+qlUTWhtdAqoKAVEfb9g0/Iv X-Google-Smtp-Source: AGHT+IGHFzWtbpQR0TiayLGdPj8/iujdHG2bgkx0p85h3ZkZ5gOHJEfMVe9W00emubq6I0kI9BvLEg== X-Received: by 2002:a17:906:d9c6:b0:a6f:b400:4751 with SMTP id a640c23a62f3a-a751447b06cmr635791366b.22.1720003378604; Wed, 03 Jul 2024 03:42:58 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Oleksii Kurochko , Alistair Francis , Bob Eshleman , Connor Davis , Andrew Cooper , Jan Beulich , Julien Grall , Stefano Stabellini Subject: [PATCH v1 4/5] xen/riscv: introduce device tree maping function Date: Wed, 3 Jul 2024 12:42:50 +0200 Message-ID: X-Mailer: git-send-email 2.45.2 In-Reply-To: References: MIME-Version: 1.0 Signed-off-by: Oleksii Kurochko --- xen/arch/riscv/include/asm/config.h | 6 +++++ xen/arch/riscv/include/asm/mm.h | 2 ++ xen/arch/riscv/mm.c | 37 +++++++++++++++++++++++++---- 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/xen/arch/riscv/include/asm/config.h b/xen/arch/riscv/include/asm/config.h index 50583aafdc..2395bafb91 100644 --- a/xen/arch/riscv/include/asm/config.h +++ b/xen/arch/riscv/include/asm/config.h @@ -74,6 +74,9 @@ #error "unsupported RV_STAGE1_MODE" #endif +#define XEN_SIZE MB(2) +#define XEN_VIRT_END (XEN_VIRT_START + XEN_SIZE) + #define DIRECTMAP_SLOT_END 509 #define DIRECTMAP_SLOT_START 200 #define DIRECTMAP_VIRT_START SLOTN(DIRECTMAP_SLOT_START) @@ -99,6 +102,9 @@ #define VMAP_VIRT_START SLOTN(VMAP_SLOT_START) #define VMAP_VIRT_SIZE GB(1) +#define BOOT_FDT_VIRT_START XEN_VIRT_END +#define BOOT_FDT_VIRT_SIZE MB(4) + #else #error "RV32 isn't supported" #endif diff --git a/xen/arch/riscv/include/asm/mm.h b/xen/arch/riscv/include/asm/mm.h index 25af9e1aaa..d1db7ce098 100644 --- a/xen/arch/riscv/include/asm/mm.h +++ b/xen/arch/riscv/include/asm/mm.h @@ -255,4 +255,6 @@ static inline unsigned int arch_get_dma_bitsize(void) return 32; /* TODO */ } +void* early_fdt_map(paddr_t fdt_paddr); + #endif /* _ASM_RISCV_MM_H */ diff --git a/xen/arch/riscv/mm.c b/xen/arch/riscv/mm.c index 7d09e781bf..ccc91f9a01 100644 --- a/xen/arch/riscv/mm.c +++ b/xen/arch/riscv/mm.c @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ +#include #include #include #include @@ -7,7 +8,9 @@ #include #include #include +#include #include +#include #include #include @@ -20,7 +23,7 @@ struct mmu_desc { unsigned int pgtbl_count; pte_t *next_pgtbl; pte_t *pgtbl_base; -}; +} mmu_desc = { CONFIG_PAGING_LEVELS, 0, NULL, 0 }; static unsigned long __ro_after_init phys_offset; @@ -39,9 +42,11 @@ static unsigned long __ro_after_init phys_offset; * isn't 2 MB aligned. * * CONFIG_PAGING_LEVELS page tables are needed for the identity mapping, - * except that the root page table is shared with the initial mapping + * except that the root page table is shared with the initial mapping. + * + * CONFIG_PAGING_LEVELS page tables are needed for device tree mapping. */ -#define PGTBL_INITIAL_COUNT ((CONFIG_PAGING_LEVELS - 1) * 2 + 1) +#define PGTBL_INITIAL_COUNT ((CONFIG_PAGING_LEVELS - 1) * 3 + 1 + 1) pte_t __section(".bss.page_aligned") __aligned(PAGE_SIZE) stage1_pgtbl_root[PAGETABLE_ENTRIES]; @@ -207,8 +212,6 @@ static bool __init check_pgtbl_mode_support(struct mmu_desc *mmu_desc, */ void __init setup_initial_pagetables(void) { - struct mmu_desc mmu_desc = { CONFIG_PAGING_LEVELS, 0, NULL, NULL }; - /* * Access to _start, _end is always PC-relative thereby when access * them we will get load adresses of start and end of Xen. @@ -296,6 +299,30 @@ unsigned long __init calc_phys_offset(void) return phys_offset; } +void* __init early_fdt_map(paddr_t fdt_paddr) +{ + unsigned long dt_phys_base = fdt_paddr; + unsigned long dt_virt_base; + unsigned long dt_virt_size; + + BUILD_BUG_ON(MIN_FDT_ALIGN < 8); + if ( !fdt_paddr || fdt_paddr % MIN_FDT_ALIGN || fdt_paddr % SZ_2M || + fdt_totalsize(fdt_paddr) > BOOT_FDT_VIRT_SIZE ) + return NULL; + + BUILD_BUG_ON(BOOT_FDT_VIRT_START % SZ_2M); + + dt_virt_base = BOOT_FDT_VIRT_START; + dt_virt_size = BOOT_FDT_VIRT_SIZE; + + /* Map device tree */ + setup_initial_mapping(&mmu_desc, dt_virt_base, + dt_virt_base + dt_virt_size, + dt_phys_base); + + return (void *)dt_virt_base; +} + void put_page(struct page_info *page) { BUG_ON("unimplemented"); From patchwork Wed Jul 3 10:42:51 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oleksii Kurochko X-Patchwork-Id: 13721965 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 C2F49C31D97 for ; Wed, 3 Jul 2024 10:43:11 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.752894.1161164 (Exim 4.92) (envelope-from ) id 1sOxS4-0004hb-G1; Wed, 03 Jul 2024 10:43:04 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 752894.1161164; Wed, 03 Jul 2024 10:43:04 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1sOxS4-0004fz-80; Wed, 03 Jul 2024 10:43:04 +0000 Received: by outflank-mailman (input) for mailman id 752894; Wed, 03 Jul 2024 10:43:02 +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 1sOxS2-0003zy-MD for xen-devel@lists.xenproject.org; Wed, 03 Jul 2024 10:43:02 +0000 Received: from mail-ej1-x630.google.com (mail-ej1-x630.google.com [2a00:1450:4864:20::630]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id 04cf92dc-3929-11ef-8776-851b0ebba9a2; Wed, 03 Jul 2024 12:43:01 +0200 (CEST) Received: by mail-ej1-x630.google.com with SMTP id a640c23a62f3a-a7241b2fe79so575648766b.1 for ; Wed, 03 Jul 2024 03:43:01 -0700 (PDT) Received: from fedora.. ([94.75.70.14]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a72b92985desm414590066b.78.2024.07.03.03.42.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 03 Jul 2024 03:42:59 -0700 (PDT) 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: 04cf92dc-3929-11ef-8776-851b0ebba9a2 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1720003380; x=1720608180; 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=+pLr0uyErdUGlpbnK/HxLvapfSaB11DzNANAbBgSYDg=; b=NCKRIFPiJ76VtuonhrfZH0ldTMo+Y7bFBAa3pw0jvXUcCk5cXj6Kisoxcf89HQAg73 0zLnCNoSGKRJiZ1Zy0LCE5ta6PMgGwbnWpg7lvk+AhH5hv5MMMxR6t1RjjSrz0QJFSOP 0ZBmIJfxi6LglSuXYTR7czr+td0C5oapkiXa3/E6h7ficUzzR3uF709l3u9WMXK+nZOa UvzootZCTA5yqr+s8EokIvppjGR/74Xk815vCDkEZg/d+c8VZXW4TiYbgjRttg4kiLAq IOj984Twlr1o2HHBHddIJUs0Q9FCFxeMMt2Ts0hAuD7nXWVsu/oJVC0cNSpWHXSeqeXX RTMg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1720003380; x=1720608180; 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=+pLr0uyErdUGlpbnK/HxLvapfSaB11DzNANAbBgSYDg=; b=rmLgeUhhP/4wQwWac5HxueJTFMnt7BQmUkKNbMnCoy9ET/zsUZgzfphv0pjAqA1JRP 15tfyK/H3bLvZ7hXq1ZAAK1lHpvCfqLp1gthGv11MKGJf2oaht9mRBZAyjVGqTvdJ+/I g53I2PlCREMfbkkmoCWzeTZfNgUVjJugqPbDLY8quszCs3yaV3wpKTheYd38vSyg0o0c Cir7cBpDDZaU2Clhzc5906k4syvcJOTKG6EsNgt/7Jkzvk8EPbuX5gDbfBKc0Hg17Z8x oTJK/c0EMVDCJg+OXa1tLY4KmJOT911EH9J/HPDl7ejrw8nRpqXxR9VoscGk0EFjw0qg SbkQ== X-Gm-Message-State: AOJu0YxQb8NaxdLmwDuZMRuHSUdgJ5ZaGXaJOfZawLdaKgR02I0WZXee KwLkOXA3snOnErrB8omUiiKFYTCktp5ETtBUlpSri3FKtNE/Une9KUYnihm5 X-Google-Smtp-Source: AGHT+IH3O6KWGvDg2t91/NyMVCFCqzBu4loX4h2mF+Jp6kwL5bKL+02NZHeN4ouuhErBQnF9C49v+g== X-Received: by 2002:a17:907:7295:b0:a72:7bf4:694c with SMTP id a640c23a62f3a-a751443c582mr1021317066b.16.1720003379590; Wed, 03 Jul 2024 03:42:59 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Oleksii Kurochko , Alistair Francis , Bob Eshleman , Connor Davis , Andrew Cooper , Jan Beulich , Julien Grall , Stefano Stabellini Subject: [PATCH v1 5/5] xen/riscv: map FDT Date: Wed, 3 Jul 2024 12:42:51 +0200 Message-ID: <7e492df051c949744755a221c0448c740d2c681b.1720002425.git.oleksii.kurochko@gmail.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: References: MIME-Version: 1.0 Except mapping of FDT, it is also printing command line passed by a DTB and initialize bootinfo from a DTB. Signed-off-by: Oleksii Kurochko --- xen/arch/riscv/riscv64/head.S | 3 +++ xen/arch/riscv/setup.c | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/xen/arch/riscv/riscv64/head.S b/xen/arch/riscv/riscv64/head.S index 3261e9fce8..22fb36a861 100644 --- a/xen/arch/riscv/riscv64/head.S +++ b/xen/arch/riscv/riscv64/head.S @@ -41,6 +41,9 @@ FUNC(start) jal setup_initial_pagetables + mv a0, s1 + jal fdt_map + /* Calculate proper VA after jump from 1:1 mapping */ la a0, .L_primary_switched sub a0, a0, s2 diff --git a/xen/arch/riscv/setup.c b/xen/arch/riscv/setup.c index 4f06203b46..b346956e06 100644 --- a/xen/arch/riscv/setup.c +++ b/xen/arch/riscv/setup.c @@ -1,7 +1,9 @@ /* SPDX-License-Identifier: GPL-2.0-only */ +#include #include #include +#include #include #include @@ -33,15 +35,34 @@ static void test_macros_from_bug_h(void) printk("WARN is most likely working\n"); } +void __init fdt_map(paddr_t dtb_addr) +{ + device_tree_flattened = early_fdt_map(dtb_addr); + if ( !device_tree_flattened ) + { + printk("wrong FDT\n"); + die(); + } +} + void __init noreturn start_xen(unsigned long bootcpu_id, paddr_t dtb_addr) { + size_t fdt_size; + const char *cmdline; + remove_identity_mapping(); trap_init(); test_macros_from_bug_h(); + fdt_size = boot_fdt_info(device_tree_flattened, dtb_addr); + + cmdline = boot_fdt_cmdline(device_tree_flattened); + printk("Command line: %s\n", cmdline); + cmdline_parse(cmdline); + printk("All set up\n"); for ( ;; )