From nobody Mon Apr 13 00:20:27 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1775836545; cv=none; d=zohomail.com; s=zohoarc; b=id88Ev8YWiMNSE1nzWmKMOCm/UOiy7b+nieLy6Y2dkaP7CPL4sB0ADojpU0YZ4xPDg9xKBUy9Gt9/e6aouTaNwuNiLBtGj85eQJhPycSjWhL71Su9hGjVHnhX58PQb5h0Aj7Mkhi+EekOKY+qZIgi1LzqK+oki79sraNlufYFEM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1775836545; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=B5ZH7rQJo78iVZbYMuHhA9Tl/XiBD/nIpAdpGmDqucg=; b=biDBngvTkgLuxtd20brm+V3EJnbrsQNSwfhC6m8UKE9Ea4Nm2MKEYJEtMwX0Xj19FBcTVuuFF5pBT+WX/+nrbD43K3yWTcPZqTOM7k45cyo+s4X6H0CR5UMKntcTiqPf0RHd2wo6Jqq2DcGIYQ/1m8NGbJNGpbA0AWXOuldPDVc= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1775836545460646.4572305703094; Fri, 10 Apr 2026 08:55:45 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1279419.1563878 (Exim 4.92) (envelope-from ) id 1wBECU-0007xK-V0; Fri, 10 Apr 2026 15:55:18 +0000 Received: by outflank-mailman (output) from mailman id 1279419.1563878; Fri, 10 Apr 2026 15:55:18 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wBECU-0007wr-R8; Fri, 10 Apr 2026 15:55:18 +0000 Received: by outflank-mailman (input) for mailman id 1279419; Fri, 10 Apr 2026 15:55:17 +0000 Received: from mx.expurgate.net ([195.190.135.10]) by lists.xenproject.org with esmtp (Exim 4.92) id 1wBECS-0007Yn-SI for xen-devel@lists.xenproject.org; Fri, 10 Apr 2026 15:55:16 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wBECS-00Cgsb-89 for xen-devel@lists.xenproject.org; Fri, 10 Apr 2026 17:55:16 +0200 Received: from [10.42.69.9] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 69d91d62-e002-0a2a0a5209dd-0a2a4509a384-2 for ; Fri, 10 Apr 2026 17:55:16 +0200 Received: from [209.85.128.45] (helo=mail-wm1-f45.google.com) by tlsNG-bad1c0.mxtls.expurgate.net with ESMTPS (eXpurgate 4.56.0) (envelope-from ) id 69d91d64-bf79-0a2a45090019-d155802daca4-3 for ; Fri, 10 Apr 2026 17:55:16 +0200 Received: by mail-wm1-f45.google.com with SMTP id 5b1f17b1804b1-488a14c31eeso17203645e9.0 for ; Fri, 10 Apr 2026 08:55:16 -0700 (PDT) Received: from fedora (user-109-243-69-121.play-internet.pl. [109.243.69.121]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-488d5b3c597sm78285605e9.12.2026.04.10.08.55.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Apr 2026 08:55:14 -0700 (PDT) X-Outflank-Mailman: Message body and most headers restored to incoming version 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" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1775836515; x=1776441315; 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=B5ZH7rQJo78iVZbYMuHhA9Tl/XiBD/nIpAdpGmDqucg=; b=nnd6pLLacLLQxFXoQZTBTas/aAPaGs+zWXRWBMHvtIZSL6uMkaKs5KbxepNfEUsyfC hRhvttFifqzWzm5r5j7jxvUSZcdP7peadLcWDo0IZQqDXgEKM/axwiP83RMgp/zIMwU+ ie0yGW/9EMqjRl7TZN/QRCnSkXWIoSp90Fz7vx74zYnHXoJeS+MttWM3DB6h6J6hozOR /WBC6E+LNSJ9W68bApkhejh7yJg+wh4XMCudZVcncs5f2whu2iI4yfv+MNaCfEy6tT7P bPcvbBbmtfAQjI/UcHoFSUQuwBo2Rupt7VW+J5DtGSOHWicv8Vb5uN5R3yXBb2X75OTr xF8A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775836515; x=1776441315; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=B5ZH7rQJo78iVZbYMuHhA9Tl/XiBD/nIpAdpGmDqucg=; b=i7kl1To89uhG5UBm4jwSBUiYut+pfozoNz3KD4ZgFj+4pKulVlpJ8ySworzf4dEQlt qze5pvPmLn7pqyFsFaReRFPWc8IzpLupKkkEjIBQIkAzhLdGwEyKM7RVvo+vExoxm6L2 N53I3x+gtA0HFtKXR3Hm94h75ZaExpJsj+cbWp9fUmhoWjTRsNYQoaNc4czDGSfA3C5O SIl0VHXp2R5qnuuXWhNz+wZDThHt5RpW7zMlgYACYtzC4VF1BYyWHi1som8p2+C9RUec 0WxFenxQ6bp6JyH34aI5ZHuaRfCZZy1zFH93RDTA0voyVgJ9DziZ9x4I5OBflvLRFMHd Ha/Q== X-Gm-Message-State: AOJu0YxCKrA6JE0CM88VHzANRTKaKiXWVXIvrjrnmf2yVAyiFCZ27kpp T5vucy1y8tmOQIvWOOTKlnRT0aA4ELeUweBo//omoZSzQCFxLAhP4cCip52jBA== X-Gm-Gg: AeBDievn0SMBEvyr7fOYEjCl8mdigIgU1DiHd3xcJ0PnunD+bZxKPOYZ1NgvVoxRfm0 iopLCDcsG6kskPA4nUxCml4fQU/rz8Q7Ur1zmv8nBt82t1U091QwMvurnizgJU6cjg8seOWqmGY mdk68wQrzbimANBYawyPxjZlxSpPpfQvkiNveQmJFc7D+gfakRxXhzAZIBy84tUCP9HD5z85RK4 gjzMQcD4XWQmoxa2UK8/9IqErE3L93NO25eQjL8rEDntlMAtzZ9ql7/FQq3f6Jo/l5Jh3H8m4G5 xbMl+eghclq0PJQcLJyZBGYagUWjaA79oJs2ZFW7ODQnztYDFjVUCFGKWHXraHQxSfYoyt3gkCj K39JXDX6tbzbx2Zp9J4EiqnBVdsdEiGDla9lgdK2j+JRp8QxaGbFBjoTls9lI3WFdV9GDruFKrT hce1+Tl2+wf28bSCMoJM/t+B9bX1GiZZfzs0sJ8ExcHVV0FXMRmABm4sqDQGcyln/TGQ== X-Received: by 2002:a05:600c:8284:b0:488:d228:a133 with SMTP id 5b1f17b1804b1-488d683d280mr45886265e9.14.1775836515301; Fri, 10 Apr 2026 08:55:15 -0700 (PDT) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Romain Caritey , Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini Subject: [PATCH v3 05/12] xen/riscv: add kernel loading support Date: Fri, 10 Apr 2026 17:54:51 +0200 Message-ID: <29ec8e444792caa925ba92cdc406ef8c0b3bd678.1775836193.git.oleksii.kurochko@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-purgate-ID: tlsNG-bad1c0/1775836516-57941152-7002F875/10/73395122804 X-purgate-type: spam X-purgate-size: 11722 X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1775836547068158500 Content-Type: text/plain; charset="utf-8" Introduce support for loading a Linux kernel Image which is got by uncompressing of Image.gz on RISC-V. kernel_image_load() and place_modules() currently call panic() on failure rather than returning an error. This is because the common kernel_load() in common/device-tree/kernel.c does not expect a return code. Handling errors gracefully would require a separate refactor. The implementation is based on the Xen Arm kernel loading code. text_offset is available for both 32-bit and 64-bit Image, so fix that. Signed-off-by: Oleksii Kurochko --- Changes in v3: - s/kernel.o/kernel.init.o. - s/struct kernel_info *info/const struct kernel_info *info for kernel_ima= ge_place - s/ioremap_wc/ioremap_cache() inside kernel_image_load(). - s/u/uint. - Drop hard tabs. - Add le{32,64}_to_cpu() when correpondent le endian fields are read. - Update the comment in kernel_image64_probe() about initialization of end= of image64. - Introduce image_size to pass to kernel load function total size of kernel it will have at runtime. - Update kernel_image_place() to not put Image always to bank 0. - Update place_modules() function to deal with different banks. - Propage error up the call chain in kernel_image_probe().=20 --- Changes in v2: - s/zimage/image as RISC-V doesn't support zImages, only Image and Image.{gz,...}. - Update the commit message. --- xen/arch/riscv/Makefile | 1 + xen/arch/riscv/include/asm/config.h | 13 ++ xen/arch/riscv/kernel.c | 230 ++++++++++++++++++++++++++++ xen/include/xen/fdt-kernel.h | 11 +- 4 files changed, 253 insertions(+), 2 deletions(-) create mode 100644 xen/arch/riscv/kernel.c diff --git a/xen/arch/riscv/Makefile b/xen/arch/riscv/Makefile index cfc3fdf7d208..eecdcbc76867 100644 --- a/xen/arch/riscv/Makefile +++ b/xen/arch/riscv/Makefile @@ -8,6 +8,7 @@ obj-y +=3D guestcopy.o obj-y +=3D imsic.o obj-y +=3D intc.o obj-y +=3D irq.o +obj-y +=3D kernel.init.o obj-y +=3D mm.o obj-y +=3D p2m.o obj-y +=3D paging.o diff --git a/xen/arch/riscv/include/asm/config.h b/xen/arch/riscv/include/a= sm/config.h index 0613de008b13..fd69057826e1 100644 --- a/xen/arch/riscv/include/asm/config.h +++ b/xen/arch/riscv/include/asm/config.h @@ -151,6 +151,19 @@ extern unsigned long phys_offset; /* =3D load_start - XEN_VIRT_START */ #endif =20 +/* + * KERNEL_LOAD_ADDR_ALIGNMENT is defined based on paragraph of + * "Kernel location" of boot.rst: + * https://docs.kernel.org/arch/riscv/boot.html#kernel-location + */ +#if defined(CONFIG_RISCV_32) +#define KERNEL_LOAD_ADDR_ALIGNMENT MB(4) +#elif defined(CONFIG_RISCV_64) +#define KERNEL_LOAD_ADDR_ALIGNMENT MB(2) +#else +#error "Define KERNEL_LOAD_ADDR_ALIGNMENT" +#endif + #endif /* ASM__RISCV__CONFIG_H */ /* * Local variables: diff --git a/xen/arch/riscv/kernel.c b/xen/arch/riscv/kernel.c new file mode 100644 index 000000000000..6d58f3372358 --- /dev/null +++ b/xen/arch/riscv/kernel.c @@ -0,0 +1,230 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define IMAGE64_MAGIC_V2 0x05435352 /* Magic number 2, le, "RSC\x05" */ + +static void __init place_modules(struct kernel_info *info, paddr_t kernbas= e, + paddr_t kernend) +{ + const struct boot_module *mod =3D info->bd.initrd; + const struct membanks *banks =3D kernel_info_get_mem_const(info); + const paddr_t initrd_len =3D ROUNDUP(mod ? mod->size : 0, + KERNEL_LOAD_ADDR_ALIGNMENT); + const paddr_t dtb_len =3D ROUNDUP(fdt_totalsize(info->fdt), + KERNEL_LOAD_ADDR_ALIGNMENT); + const paddr_t modsize =3D initrd_len + dtb_len; + int bi; + + BUG_ON(modsize < initrd_len); + + /* + * Place modules as high in RAM as possible, scanning banks from + * last to first so that the end of the last bank is preferred. + */ + for ( bi =3D banks->nr_banks - 1; bi >=3D 0; bi-- ) + { + const struct membank *bank =3D &banks->bank[bi]; + const paddr_t bank_end =3D bank->start + bank->size; + paddr_t modbase; + + if ( modsize > bank->size ) + continue; + + modbase =3D ROUNDDOWN(bank_end - modsize, KERNEL_LOAD_ADDR_ALIGNME= NT); + + if ( modbase < bank->start ) + continue; + + /* + * If the kernel resides in this bank, ensure modules do not + * overlap with it. + */ + if ( (kernbase >=3D bank->start) && (kernbase < bank_end) && + (modbase < ROUNDUP(kernend, KERNEL_LOAD_ADDR_ALIGNMENT)) && + (modbase + modsize > kernbase) ) + continue; + + info->dtb_paddr =3D modbase; + info->initrd_paddr =3D modbase + dtb_len; + + return; + } + + panic("Unable to find suitable location for dtb+initrd\n"); +} + +static paddr_t __init kernel_image_place(struct kernel_info *info) +{ + paddr_t load_addr =3D INVALID_PADDR; + uint64_t image_size =3D info->image.image_size ?: info->image.len; + const struct membanks *banks =3D kernel_info_get_mem_const(info); + unsigned int nr_banks =3D banks->nr_banks; + unsigned int bi; + + dprintk(XENLOG_DEBUG, "nr_banks(%u)\n", nr_banks); + + /* + * At the moment, RISC-V's Linux kernel should be always position + * independent based on "Per-MMU execution" of boot.rst: + * https://docs.kernel.org/arch/riscv/boot.html#pre-mmu-execution + * + * But just for the case when RISC-V's Linux kernel isn't position + * independent it is needed to take load address from + * info->image.start. + * + * If `start` is zero, the Image is position independent. + */ + if ( likely(!info->image.start) ) + { + for ( bi =3D 0; bi !=3D nr_banks; bi++ ) + { + const struct membank *bank =3D &banks->bank[bi]; + paddr_t bank_start =3D bank->start; + /* + * According to boot.rst kernel load address should be properly + * aligned: + * https://docs.kernel.org/arch/riscv/boot.html#kernel-locat= ion + * + * As Image in this case is PIC we can ignore + * info->image.text_offset. + */ + paddr_t aligned_start =3D ROUNDUP(bank_start, KERNEL_LOAD_ADDR= _ALIGNMENT); + paddr_t bank_end =3D bank_start + bank->size; + paddr_t bank_size; + + if ( aligned_start > bank_end ) + continue; + + bank_size =3D bank_end - aligned_start; + + dprintk(XENLOG_DEBUG, "bank[%u].start=3D%"PRIpaddr"\n", bi, ba= nk->start); + + if ( image_size <=3D bank_size ) + { + load_addr =3D aligned_start; + break; + } + } + } + else + { + load_addr =3D info->image.start + info->image.text_offset; + + WARN_ON(!IS_ALIGNED(load_addr, KERNEL_LOAD_ADDR_ALIGNMENT)); + + for ( bi =3D 0; bi !=3D nr_banks; bi++ ) + { + const struct membank *bank =3D &banks->bank[bi]; + paddr_t bank_start =3D bank->start; + paddr_t bank_end =3D bank_start + bank->size; + + if ( (load_addr >=3D bank_start) && (load_addr < bank_end) && + (bank_end - load_addr) >=3D image_size ) + break; + } + } + + if ( bi =3D=3D nr_banks ) + panic("Failed to place kernel image in any memory bank\n"); + + info->entry =3D load_addr; + + return load_addr; +} + +static void __init kernel_image_load(struct kernel_info *info) +{ + int rc; + paddr_t load_addr =3D kernel_image_place(info); + paddr_t paddr =3D info->image.kernel_addr; + paddr_t len =3D info->image.len; + paddr_t effective_size =3D info->image.image_size ?: len; + void *kernel; + + place_modules(info, load_addr, load_addr + effective_size); + + printk("Loading Image from %"PRIpaddr" to %"PRIpaddr"-%"PRIpaddr"\n", + paddr, load_addr, load_addr + effective_size); + + kernel =3D ioremap_cache(paddr, len); + + if ( !kernel ) + panic("Unable to map kernel\n"); + + /* Move kernel to proper location in guest phys map */ + rc =3D copy_to_guest_phys(info->bd.d, load_addr, kernel, len); + + if ( rc ) + panic("Unable to copy kernel to proper guest location\n"); + + iounmap(kernel); +} + +/* Check if the image is a 64-bit Image */ +static int __init kernel_image64_probe(struct kernel_info *info, + paddr_t addr, paddr_t size) +{ + /* riscv/boot-image-header.rst */ + struct { + uint32_t code0; /* Executable code */ + uint32_t code1; /* Executable code */ + uint64_t text_offset; /* Image load offset, little endian */ + uint64_t image_size; /* Effective Image size, little endian */ + uint64_t flags; /* kernel flags, little endian */ + uint32_t version; /* Version of this header */ + uint32_t res1; /* Reserved */ + uint64_t res2; /* Reserved */ + uint64_t magic; /* Deprecated: Magic number, little endian= , "RISCV" */ + uint32_t magic2; /* Magic number 2, little endian, "RSC\x05= " */ + uint32_t res3; /* Reserved for PE COFF offset */ + } image; + uint64_t effective_size; + + if ( size < sizeof(image) ) + return -EINVAL; + + copy_from_paddr(&image, addr, sizeof(image)); + + /* Magic v1 is deprecated and may be removed. Only use v2 */ + if ( le32_to_cpu(image.magic2) !=3D IMAGE64_MAGIC_V2 ) + return -EINVAL; + + effective_size =3D le64_to_cpu(image.image_size); + + if ( effective_size && size > effective_size ) + return -EINVAL; + + info->image.kernel_addr =3D addr; + /* Actual size in the binary file */ + info->image.len =3D size; + /* Total memory the kernel occupies at runtime */ + info->image.image_size =3D effective_size; + info->image.text_offset =3D le64_to_cpu(image.text_offset); + info->image.start =3D 0; + + info->load =3D kernel_image_load; + + return 0; +} + +int __init kernel_image_probe(struct kernel_info *info, paddr_t addr, + paddr_t size) +{ +#ifdef CONFIG_RISCV_64 + return kernel_image64_probe(info, addr, size); +#else + return -EOPNOTSUPP; +#endif +} diff --git a/xen/include/xen/fdt-kernel.h b/xen/include/xen/fdt-kernel.h index 2af3bd5f0722..aa977a50f4fc 100644 --- a/xen/include/xen/fdt-kernel.h +++ b/xen/include/xen/fdt-kernel.h @@ -52,8 +52,15 @@ struct kernel_info { struct { paddr_t kernel_addr; paddr_t len; -#if defined(CONFIG_ARM_64) || defined(CONFIG_RISCV_64) - paddr_t text_offset; /* 64-bit Image only */ +#if defined(CONFIG_ARM_64) || defined(CONFIG_RISCV) + /* + * ARM: 64-bit Image only. + * RISC-V: both 32-bit and 64-bit Images. + */ + paddr_t text_offset; +#endif +#if defined(CONFIG_RISCV) + uint64_t image_size; /* Effective size of Image */ #endif paddr_t start; /* Must be 0 for 64-bit Image */ } image; --=20 2.53.0