From patchwork Tue Jan 14 16:09:36 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Djokic X-Patchwork-Id: 13938951 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 B57B0E77188 for ; Tue, 14 Jan 2025 16:11:22 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.871516.1282500 (Exim 4.92) (envelope-from ) id 1tXjVT-0007ik-GX; Tue, 14 Jan 2025 16:11:07 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 871516.1282500; Tue, 14 Jan 2025 16:11:07 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1tXjVT-0007id-DZ; Tue, 14 Jan 2025 16:11:07 +0000 Received: by outflank-mailman (input) for mailman id 871516; Tue, 14 Jan 2025 16:11:07 +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 1tXjVS-0007iX-Nt for xen-devel@lists.xenproject.org; Tue, 14 Jan 2025 16:11:06 +0000 Received: from mail-wm1-x336.google.com (mail-wm1-x336.google.com [2a00:1450:4864:20::336]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id 27a418d1-d292-11ef-a0e1-8be0dac302b0; Tue, 14 Jan 2025 17:11:04 +0100 (CET) Received: by mail-wm1-x336.google.com with SMTP id 5b1f17b1804b1-4361b0ec57aso54560925e9.0 for ; Tue, 14 Jan 2025 08:11:04 -0800 (PST) Received: from RTRKN418-LIN.domain.local ([89.216.37.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-38bddbf50a2sm4812812f8f.43.2025.01.14.08.11.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 14 Jan 2025 08:11:02 -0800 (PST) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 27a418d1-d292-11ef-a0e1-8be0dac302b0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1736871064; x=1737475864; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=NTHO6ORbJHu4Fft/9aF8Dega/+gwwgtxpWn3kQGQUvA=; b=URTbAiczX+lhNujMTN8lB0kYEDWp1iMPave02r0cxlR9lUx/722S+McR6lZKRTi4xo AEy4hftTD+RGABo6vc2s37GCEPefmwf2Q4BcsX1NVqGMRquDDvHB4I91F6jTEndMsisH xT2SUdN9u0TmexzzbYYGoP+LnCoiG7lLnKp5pHk5Tw90GwZOwhQ1onj3YSawlU8vScWx R3AVUIwEgfyp2K7wbJVvg33/KKM8pI619vqUILL4YiS5QXIB0UnIRYM/VrjTvsviARoY 0pKSwxDmIZWX6XVjWBvvjsUmacZocLoc/BoyY5TjjaPyX/qmheRgT3mi4v2U06eKYHgj Ns/A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1736871064; x=1737475864; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=NTHO6ORbJHu4Fft/9aF8Dega/+gwwgtxpWn3kQGQUvA=; b=iPILosnLomc5KL7anTMd6iNQ86jeEkQ3Yd2fYEGoHZIzIbWrHAvjTaoJwixgyDzB2g pvogyLEIPRITnkZzzYV7gPSShnqzY67+a8ufpuWMpbEi6r1JQHKUWkRzYxVAclpVaI1Q Riy9iFZiGwCGAKH5wwjx3gmBVtGbppQBLONVjBCevt6UlMT3gvab3Ys4iRIh3i2CxrVc wdVRqHjBdENPCwVgsctcdy0FEk0EQAcyP4J4okNpAZEUDchU+vAgoatYUwqoROEwCIB1 ec3YxEqIqmmxhWTVMb88jdhWZI78MzqsLK1tFwB7hzI1/j+6TPCTUib5Ve5dqJJh4koN Emog== X-Forwarded-Encrypted: i=1; AJvYcCV2EigAOcSM1dEmU8KSbxa1rOKVKSC3ZYKIY3XXC9kiVzeOi5x7c1fThRP4Gd20EUEIYTAaraMSJJc=@lists.xenproject.org X-Gm-Message-State: AOJu0Yzukuy5ZDZ+p2s03d7mO4CgwG0lR5WOgyaVlX1h7KY/FLCxSwzW z6J3fBax9nL9E7cIk/FNc4SCdTCWKCCoqUIwY5XRjQSeXeWADYE+ X-Gm-Gg: ASbGncvIcMNP+3/U6hruGwnuVpJZCjVgEt94dreFpWddmh306x+o0frs/990cixwM1j /xjSI0j6ftf+kjoOaHlAwnijPN4zTb60LlMjfL8NquuxT99ayZKnKgnujvhjhPogXLl4+qWyPOz lZFOF/vbdMonrmUgRQocZWlBDwNKzDbYN9kecMIrDfXGLqv0JQ05EPh8tusIsD0vnvCsiyeQLgK rKr7eUyyGQOC7DGjrbAhkwCfa61JHzNQLDw4Pyom/Pee3HndGHvpjRRVWLWPIH/xIY4M9x+ETwF hZnWzg== X-Google-Smtp-Source: AGHT+IEkkv0RUPmhyicxqkBxmhOobZ5p48nMpzZapAIFwHFVu/2/9jKyyv0rb4O/+ZjNNPQ4Ul9LXw== X-Received: by 2002:a05:600c:4e8c:b0:434:f5c0:3288 with SMTP id 5b1f17b1804b1-436e271d355mr233324995e9.29.1736871063354; Tue, 14 Jan 2025 08:11:03 -0800 (PST) From: Milan Djokic To: linux-riscv@lists.infradead.org Cc: paul.walmsley@sifive.com, palmer@dabbelt.com, aou@eecs.berkeley.edu, jgross@suse.com, sstabellini@kernel.org, oleksandr_tyshchenko@epam.com, Slavisa.Petrovic@rt-rk.com, Milan.Djokic@rt-rk.com, rafael.j.wysocki@intel.com, sunilvl@ventanamicro.com, takakura@valinux.co.jp, linux-kernel@vger.kernel.org, xen-devel@lists.xenproject.org, iommu@lists.linux.dev Subject: [PATCH] riscv: Add initial Xen guest support for RISC-V Date: Tue, 14 Jan 2025 17:09:36 +0100 Message-ID: X-Mailer: git-send-email 2.43.0 MIME-Version: 1.0 From: Slavisa Petrovic This patch introduces initial support for running RISC-V as a Xen guest. It provides the necessary infrastructure and stubs for Xen-specific operations. Key changes include: - Modifications to the RISC-V kernel to integrate Xen-specific hypercalls and interfaces, with function implementations stubbed for future work. - Introduction of Xen-specific headers for RISC-V, including event handling, hypervisor interaction, and page management. Functions are defined but not yet implemented. - Stub implementations for memory management, grant tables, and context switching in the Xen environment, allowing further development and integration. Signed-off-by: Milan Djokic Signed-off-by: Slavisa Petrovic --- arch/riscv/Kbuild | 1 + arch/riscv/Kconfig | 19 +++ arch/riscv/include/asm/cpu.h | 1 + arch/riscv/include/asm/hypervisor.h | 9 ++ arch/riscv/include/asm/irq.h | 5 + arch/riscv/include/asm/sync_bitops.h | 27 ++++ arch/riscv/include/asm/xen/events.h | 28 ++++ arch/riscv/include/asm/xen/hypercall.h | 2 + arch/riscv/include/asm/xen/hypervisor.h | 2 + arch/riscv/include/asm/xen/interface.h | 2 + arch/riscv/include/asm/xen/page.h | 3 + arch/riscv/include/asm/xen/swiotlb-xen.h | 2 + arch/riscv/xen/Makefile | 2 + arch/riscv/xen/enlighten.c | 164 +++++++++++++++++++++++ arch/riscv/xen/grant-table.c | 57 ++++++++ arch/riscv/xen/hypercall.S | 71 ++++++++++ arch/riscv/xen/p2m.c | 76 +++++++++++ include/xen/interface/io/protocols.h | 3 + include/xen/riscv/hypercall.h | 71 ++++++++++ include/xen/riscv/hypervisor.h | 26 ++++ include/xen/riscv/interface.h | 85 ++++++++++++ include/xen/riscv/page.h | 106 +++++++++++++++ include/xen/riscv/swiotlb-xen.h | 13 ++ test.txt | 21 +++ 24 files changed, 796 insertions(+) create mode 100644 arch/riscv/include/asm/hypervisor.h create mode 100644 arch/riscv/include/asm/sync_bitops.h create mode 100644 arch/riscv/include/asm/xen/events.h create mode 100644 arch/riscv/include/asm/xen/hypercall.h create mode 100644 arch/riscv/include/asm/xen/hypervisor.h create mode 100644 arch/riscv/include/asm/xen/interface.h create mode 100644 arch/riscv/include/asm/xen/page.h create mode 100644 arch/riscv/include/asm/xen/swiotlb-xen.h create mode 100644 arch/riscv/xen/Makefile create mode 100644 arch/riscv/xen/enlighten.c create mode 100644 arch/riscv/xen/grant-table.c create mode 100644 arch/riscv/xen/hypercall.S create mode 100644 arch/riscv/xen/p2m.c create mode 100644 include/xen/riscv/hypercall.h create mode 100644 include/xen/riscv/hypervisor.h create mode 100644 include/xen/riscv/interface.h create mode 100644 include/xen/riscv/page.h create mode 100644 include/xen/riscv/swiotlb-xen.h create mode 100644 test.txt -- 2.43.0 diff --git a/arch/riscv/Kbuild b/arch/riscv/Kbuild index 2c585f7a0b6e..d9b71deed2cd 100644 --- a/arch/riscv/Kbuild +++ b/arch/riscv/Kbuild @@ -5,6 +5,7 @@ obj-$(CONFIG_BUILTIN_DTB) += boot/dts/ obj-$(CONFIG_CRYPTO) += crypto/ obj-y += errata/ obj-$(CONFIG_KVM) += kvm/ +obj-$(CONFIG_XEN) += xen/ obj-$(CONFIG_ARCH_SUPPORTS_KEXEC_PURGATORY) += purgatory/ diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index d4a7ca0388c0..13ea75221524 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -1071,6 +1071,25 @@ config PARAVIRT_TIME_ACCOUNTING If in doubt, say N here. +config XEN_DOM0 + def_bool y + depends on XEN + +config XEN + bool "Xen guest support on RISCV" + depends on RISCV && OF + select PARAVIRT + help + Enables support for running Linux as a Xen guest on RISC-V. + + Xen is a type-1 hypervisor that allows multiple operating systems + to run on the same hardware. Enabling this option allows the kernel + to function as a guest under the Xen hypervisor on RISC-V platforms. + + Say Y if you want to run this kernel as a guest under Xen on RISC-V. + + If unsure, say N. + config RELOCATABLE bool "Build a relocatable kernel" depends on MMU && 64BIT && !XIP_KERNEL diff --git a/arch/riscv/include/asm/cpu.h b/arch/riscv/include/asm/cpu.h index 28d45a6678ce..fb2aac6a068e 100644 --- a/arch/riscv/include/asm/cpu.h +++ b/arch/riscv/include/asm/cpu.h @@ -4,5 +4,6 @@ #define _ASM_CPU_H /* This header is required unconditionally by the ACPI core */ +#include #endif /* _ASM_CPU_H */ diff --git a/arch/riscv/include/asm/hypervisor.h b/arch/riscv/include/asm/hypervisor.h new file mode 100644 index 000000000000..3a117afe57f0 --- /dev/null +++ b/arch/riscv/include/asm/hypervisor.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_RISCV_HYPERVISOR_H +#define _ASM_RISCV_HYPERVISOR_H + +#include + +void kvm_init_hyp_services(void); + +#endif diff --git a/arch/riscv/include/asm/irq.h b/arch/riscv/include/asm/irq.h index 7b038f3b7cb0..b14621848eae 100644 --- a/arch/riscv/include/asm/irq.h +++ b/arch/riscv/include/asm/irq.h @@ -23,6 +23,11 @@ void riscv_set_intc_hwnode_fn(struct fwnode_handle *(*fn)(void)); struct fwnode_handle *riscv_get_intc_hwnode(void); +static inline int nr_legacy_irqs(void) +{ + return 0; +} + #ifdef CONFIG_ACPI enum riscv_irqchip_type { diff --git a/arch/riscv/include/asm/sync_bitops.h b/arch/riscv/include/asm/sync_bitops.h new file mode 100644 index 000000000000..28e3c64ba852 --- /dev/null +++ b/arch/riscv/include/asm/sync_bitops.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __ASM_SYNC_BITOPS_H__ +#define __ASM_SYNC_BITOPS_H__ + +#include +#include + +/* sync_bitops functions are equivalent to the SMP implementation of the + * original functions, independently from CONFIG_SMP being defined. + * + * We need them because _set_bit etc are not SMP safe if !CONFIG_SMP. But + * under Xen you might be communicating with a completely external entity + * who might be on another CPU (e.g. two uniprocessor guests communicating + * via event channels and grant tables). So we need a variant of the bit + * ops which are SMP safe even on a UP kernel. + */ + +#define sync_set_bit(nr, p) set_bit(nr, p) +#define sync_clear_bit(nr, p) clear_bit(nr, p) +#define sync_change_bit(nr, p) change_bit(nr, p) +#define sync_test_and_set_bit(nr, p) test_and_set_bit(nr, p) +#define sync_test_and_clear_bit(nr, p) test_and_clear_bit(nr, p) +#define sync_test_and_change_bit(nr, p) test_and_change_bit(nr, p) +#define sync_test_bit(nr, addr) test_bit(nr, addr) +#define arch_sync_cmpxchg arch_cmpxchg + +#endif diff --git a/arch/riscv/include/asm/xen/events.h b/arch/riscv/include/asm/xen/events.h new file mode 100644 index 000000000000..a3d0332ca46c --- /dev/null +++ b/arch/riscv/include/asm/xen/events.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_RISCV_XEN_EVENTS_H +#define _ASM_RISCV_XEN_EVENTS_H + +#include +#include + +enum ipi_vector { + XEN_PLACEHOLDER_VECTOR, + + /* Xen IPIs go here */ + XEN_NR_IPIS, +}; + +static inline int xen_irqs_disabled(struct pt_regs *regs) +{ + return 0; +} + +#define xchg_xen_ulong(ptr, val) xchg((ptr), (val)) + +/* Rebind event channel is supported by default */ +static inline bool xen_support_evtchn_rebind(void) +{ + return true; +} + +#endif /* _ASM_RISCV_XEN_EVENTS_H */ diff --git a/arch/riscv/include/asm/xen/hypercall.h b/arch/riscv/include/asm/xen/hypercall.h new file mode 100644 index 000000000000..0841ba1f0835 --- /dev/null +++ b/arch/riscv/include/asm/xen/hypercall.h @@ -0,0 +1,2 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#include diff --git a/arch/riscv/include/asm/xen/hypervisor.h b/arch/riscv/include/asm/xen/hypervisor.h new file mode 100644 index 000000000000..05b7c834d0a9 --- /dev/null +++ b/arch/riscv/include/asm/xen/hypervisor.h @@ -0,0 +1,2 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#include diff --git a/arch/riscv/include/asm/xen/interface.h b/arch/riscv/include/asm/xen/interface.h new file mode 100644 index 000000000000..9f30b1d7e77c --- /dev/null +++ b/arch/riscv/include/asm/xen/interface.h @@ -0,0 +1,2 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#include diff --git a/arch/riscv/include/asm/xen/page.h b/arch/riscv/include/asm/xen/page.h new file mode 100644 index 000000000000..c8f5b873445b --- /dev/null +++ b/arch/riscv/include/asm/xen/page.h @@ -0,0 +1,3 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#include +#include diff --git a/arch/riscv/include/asm/xen/swiotlb-xen.h b/arch/riscv/include/asm/xen/swiotlb-xen.h new file mode 100644 index 000000000000..aa3bc339df03 --- /dev/null +++ b/arch/riscv/include/asm/xen/swiotlb-xen.h @@ -0,0 +1,2 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#include diff --git a/arch/riscv/xen/Makefile b/arch/riscv/xen/Makefile new file mode 100644 index 000000000000..f6d3a357e4c7 --- /dev/null +++ b/arch/riscv/xen/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0-only +obj-y := enlighten.o p2m.o grant-table.o hypercall.o diff --git a/arch/riscv/xen/enlighten.c b/arch/riscv/xen/enlighten.c new file mode 100644 index 000000000000..28bd66c288f9 --- /dev/null +++ b/arch/riscv/xen/enlighten.c @@ -0,0 +1,164 @@ +// SPDX-License-Identifier: GPL-2.0-only +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static struct start_info _xen_start_info; +struct start_info *xen_start_info = &_xen_start_info; +EXPORT_SYMBOL(xen_start_info); + +enum xen_domain_type xen_domain_type = XEN_NATIVE; +EXPORT_SYMBOL(xen_domain_type); + +struct shared_info xen_dummy_shared_info; +struct shared_info *HYPERVISOR_shared_info = (void *)&xen_dummy_shared_info; + +DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu); +static struct vcpu_info __percpu *xen_vcpu_info; + +/* Linux <-> Xen vCPU id mapping */ +DEFINE_PER_CPU(uint32_t, xen_vcpu_id); +EXPORT_PER_CPU_SYMBOL(xen_vcpu_id); + +/* These are unused until we support booting "pre-ballooned" */ +unsigned long xen_released_pages; +struct xen_memory_region xen_extra_mem[XEN_EXTRA_MEM_MAX_REGIONS] __initdata; + +static __read_mostly unsigned int xen_events_irq; +static __read_mostly phys_addr_t xen_grant_frames; + +#define GRANT_TABLE_INDEX 0 +#define EXT_REGION_INDEX 1 + +uint32_t xen_start_flags; +EXPORT_SYMBOL(xen_start_flags); + +int xen_unmap_domain_gfn_range(struct vm_area_struct *vma, + int nr, struct page **pages) +{ + return 0; +} +EXPORT_SYMBOL_GPL(xen_unmap_domain_gfn_range); + +static void xen_read_wallclock(struct timespec64 *ts) +{ +} + +static int xen_pvclock_gtod_notify(struct notifier_block *nb, + unsigned long was_set, void *priv) +{ + return 0; +} + +static struct notifier_block xen_pvclock_gtod_notifier = { + .notifier_call = xen_pvclock_gtod_notify, +}; + +static int xen_starting_cpu(unsigned int cpu) +{ + return 0; +} + +static int xen_dying_cpu(unsigned int cpu) +{ + return 0; +} + +void xen_reboot(int reason) +{ +} + +static int xen_restart(struct notifier_block *nb, unsigned long action, + void *data) +{ + return 0; +} + +static struct notifier_block xen_restart_nb = { + .notifier_call = xen_restart, + .priority = 192, +}; + +static void xen_power_off(void) +{ +} + +static __initdata struct { + const char *compat; + const char *prefix; + const char *version; + bool found; +} hyper_node = {"xen,xen", "xen,xen-", NULL, false}; + +static int __init fdt_find_hyper_node(unsigned long node, const char *uname, + int depth, void *data) +{ + return 0; +} + +void __init xen_early_init(void) +{ +} + +static void __init xen_dt_guest_init(void) +{ +} + +static int __init xen_guest_init(void) +{ + return 0; +} +early_initcall(xen_guest_init); + +static int xen_starting_runstate_cpu(unsigned int cpu) +{ + return 0; +} + +static int __init xen_late_init(void) +{ + return 0; +} +late_initcall(xen_late_init); + + +/* empty stubs */ +void xen_arch_pre_suspend(void) { } +void xen_arch_post_suspend(int suspend_cancelled) { } +void xen_timer_resume(void) { } +void xen_arch_resume(void) { } +void xen_arch_suspend(void) { } diff --git a/arch/riscv/xen/grant-table.c b/arch/riscv/xen/grant-table.c new file mode 100644 index 000000000000..9dd0cea74360 --- /dev/null +++ b/arch/riscv/xen/grant-table.c @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: GPL-2.0 +/****************************************************************************** + * grant_table.c + * + * Granting foreign access to our memory reservation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation; or, when distributed + * separately from the Linux kernel or incorporated into other + * software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include +#include +#include + +int arch_gnttab_map_shared(xen_pfn_t *frames, unsigned long nr_gframes, + unsigned long max_nr_gframes, + void **__shared) +{ + return 0; +} + +void arch_gnttab_unmap(void *shared, unsigned long nr_gframes) +{ +} + +int arch_gnttab_map_status(uint64_t *frames, unsigned long nr_gframes, + unsigned long max_nr_gframes, + grant_status_t **__shared) +{ + return 0; +} + +int arch_gnttab_init(unsigned long nr_shared, unsigned long nr_status) +{ + return 0; +} diff --git a/arch/riscv/xen/hypercall.S b/arch/riscv/xen/hypercall.S new file mode 100644 index 000000000000..a81afd2a11c4 --- /dev/null +++ b/arch/riscv/xen/hypercall.S @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#include +#include +#include +EXPORT_SYMBOL_GPL(HYPERVISOR_event_channel_op); +EXPORT_SYMBOL_GPL(HYPERVISOR_grant_table_op); +EXPORT_SYMBOL_GPL(HYPERVISOR_xen_version); +EXPORT_SYMBOL_GPL(HYPERVISOR_console_io); +EXPORT_SYMBOL_GPL(HYPERVISOR_sched_op); +EXPORT_SYMBOL_GPL(HYPERVISOR_hvm_op); +EXPORT_SYMBOL_GPL(HYPERVISOR_memory_op); +EXPORT_SYMBOL_GPL(HYPERVISOR_physdev_op); +EXPORT_SYMBOL_GPL(HYPERVISOR_vcpu_op); +EXPORT_SYMBOL_GPL(HYPERVISOR_platform_op_raw); +EXPORT_SYMBOL_GPL(HYPERVISOR_multicall); +EXPORT_SYMBOL_GPL(HYPERVISOR_vm_assist); +EXPORT_SYMBOL_GPL(HYPERVISOR_dm_op); +EXPORT_SYMBOL_GPL(privcmd_call); +#define SBI_ECALL 0xE + + .data + +#define HYPERCALL_SIMPLE(hypercall) \ +SYM_FUNC_START(HYPERVISOR_##hypercall) \ + li a6, __HYPERVISOR_##hypercall; \ + li a7, SBI_ECALL; \ + mv a5, a4; \ + mv a4, a3; \ + mv a3, a2; \ + mv a2, a1; \ + mv a1, a0; \ + li a0, 0; \ + ecall; \ + ret; \ +SYM_FUNC_END(HYPERVISOR_##hypercall) + +#define HYPERCALL0 HYPERCALL_SIMPLE +#define HYPERCALL1 HYPERCALL_SIMPLE +#define HYPERCALL2 HYPERCALL_SIMPLE +#define HYPERCALL3 HYPERCALL_SIMPLE +#define HYPERCALL4 HYPERCALL_SIMPLE +#define HYPERCALL5 HYPERCALL_SIMPLE + + .text + +HYPERCALL2(xen_version); +HYPERCALL3(console_io); +HYPERCALL3(grant_table_op); +HYPERCALL2(sched_op); +HYPERCALL2(event_channel_op); +HYPERCALL2(hvm_op); +HYPERCALL2(memory_op); +HYPERCALL2(physdev_op); +HYPERCALL3(vcpu_op); +HYPERCALL1(platform_op_raw); +HYPERCALL2(multicall); +HYPERCALL2(vm_assist); +HYPERCALL3(dm_op); + +SYM_FUNC_START(privcmd_call) + mv a6, a0 + li a7, SBI_ECALL + mv a5, a4; + mv a4, a3; + mv a3, a2; + mv a2, a1; + mv a1, a0; + li a0, 0; + ecall + ret +SYM_FUNC_END(privcmd_call); diff --git a/arch/riscv/xen/p2m.c b/arch/riscv/xen/p2m.c new file mode 100644 index 000000000000..7ce75e52d7c4 --- /dev/null +++ b/arch/riscv/xen/p2m.c @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: GPL-2.0-only +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +struct xen_p2m_entry { + unsigned long pfn; + unsigned long mfn; + unsigned long nr_pages; + struct rb_node rbnode_phys; +}; + +static rwlock_t p2m_lock; +struct rb_root phys_to_mach = RB_ROOT; +EXPORT_SYMBOL_GPL(phys_to_mach); + +static int xen_add_phys_to_mach_entry(struct xen_p2m_entry *new) +{ + + return 0; +} + +unsigned long __pfn_to_mfn(unsigned long pfn) +{ + return 0; +} +EXPORT_SYMBOL_GPL(__pfn_to_mfn); + +int set_foreign_p2m_mapping(struct gnttab_map_grant_ref *map_ops, + struct gnttab_map_grant_ref *kmap_ops, + struct page **pages, unsigned int count) +{ + return 0; +} + +int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops, + struct gnttab_unmap_grant_ref *kunmap_ops, + struct page **pages, unsigned int count) +{ + return 0; +} + +bool __set_phys_to_machine_multi(unsigned long pfn, + unsigned long mfn, unsigned long nr_pages) +{ + return true; +} +EXPORT_SYMBOL_GPL(__set_phys_to_machine_multi); + +bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn) +{ + return true; +} +EXPORT_SYMBOL_GPL(__set_phys_to_machine); + +static int p2m_init(void) +{ + return 0; +} +arch_initcall(p2m_init); diff --git a/include/xen/interface/io/protocols.h b/include/xen/interface/io/protocols.h index 22099bb4079f..6c6317462be0 100644 --- a/include/xen/interface/io/protocols.h +++ b/include/xen/interface/io/protocols.h @@ -6,6 +6,7 @@ #define XEN_IO_PROTO_ABI_X86_64 "x86_64-abi" #define XEN_IO_PROTO_ABI_POWERPC64 "powerpc64-abi" #define XEN_IO_PROTO_ABI_ARM "arm-abi" +#define XEN_IO_PROTO_ABI_RISCV "riscv-abi" #if defined(__i386__) # define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_X86_32 @@ -15,6 +16,8 @@ # define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_POWERPC64 #elif defined(__arm__) || defined(__aarch64__) # define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_ARM +#elif defined(__riscv) +# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_RISCV #else # error arch fixup needed here #endif diff --git a/include/xen/riscv/hypercall.h b/include/xen/riscv/hypercall.h new file mode 100644 index 000000000000..f76d8a018f26 --- /dev/null +++ b/include/xen/riscv/hypercall.h @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/****************************************************************************** + * hypercall.h + * + * Linux-specific hypervisor handling. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation; or, when distributed + * separately from the Linux kernel or incorporated into other + * software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef _ASM_RISCV_XEN_HYPERCALL_H +#define _ASM_RISCV_XEN_HYPERCALL_H + +#include + +#include +#include +#include + +struct xen_dm_op_buf; + +long privcmd_call(unsigned int call, unsigned long a1, + unsigned long a2, unsigned long a3, + unsigned long a4, unsigned long a5); +int HYPERVISOR_xen_version(int cmd, void *arg); +int HYPERVISOR_console_io(int cmd, int count, char *str); +int HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count); +int HYPERVISOR_sched_op(int cmd, void *arg); +int HYPERVISOR_event_channel_op(int cmd, void *arg); +unsigned long HYPERVISOR_hvm_op(int op, void *arg); +int HYPERVISOR_memory_op(unsigned int cmd, void *arg); +int HYPERVISOR_physdev_op(int cmd, void *arg); +int HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args); +int HYPERVISOR_vm_assist(unsigned int cmd, unsigned int type); +int HYPERVISOR_dm_op(domid_t domid, unsigned int nr_bufs, + struct xen_dm_op_buf *bufs); +int HYPERVISOR_platform_op_raw(void *arg); +static inline int HYPERVISOR_platform_op(struct xen_platform_op *op) +{ + return 0; +} +int HYPERVISOR_multicall(struct multicall_entry *calls, uint32_t nr); + +static inline int +HYPERVISOR_suspend(unsigned long start_info_mfn) +{ + return 0; +} + +#endif /* _ASM_RISCV_XEN_HYPERCALL_H */ diff --git a/include/xen/riscv/hypervisor.h b/include/xen/riscv/hypervisor.h new file mode 100644 index 000000000000..2c1f9625be80 --- /dev/null +++ b/include/xen/riscv/hypervisor.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_RISCV_XEN_HYPERVISOR_H +#define _ASM_RISCV_XEN_HYPERVISOR_H + +#include + +extern struct shared_info *HYPERVISOR_shared_info; +extern struct start_info *xen_start_info; + +#ifdef CONFIG_XEN +void __init xen_early_init(void); +#else +static inline void xen_early_init(void) { return; } +#endif + +#ifdef CONFIG_HOTPLUG_CPU +static inline void xen_arch_register_cpu(int num) +{ +} + +static inline void xen_arch_unregister_cpu(int num) +{ +} +#endif + +#endif /* _ASM_RISCV_XEN_HYPERVISOR_H */ diff --git a/include/xen/riscv/interface.h b/include/xen/riscv/interface.h new file mode 100644 index 000000000000..6769b5b39cba --- /dev/null +++ b/include/xen/riscv/interface.h @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/****************************************************************************** + * Guest OS interface to RISCV Xen. + * + */ + +#ifndef _ASM_RISCV_XEN_INTERFACE_H +#define _ASM_RISCV_XEN_INTERFACE_H + +#include + +#define uint64_aligned_t uint64_t __aligned(8) + +#define __DEFINE_GUEST_HANDLE(name, type) \ + typedef struct { union { type * p; uint64_aligned_t q; }; } \ + __guest_handle_ ## name + +#define DEFINE_GUEST_HANDLE_STRUCT(name) \ + __DEFINE_GUEST_HANDLE(name, struct name) +#define DEFINE_GUEST_HANDLE(name) __DEFINE_GUEST_HANDLE(name, name) +#define GUEST_HANDLE(name) __guest_handle_ ## name + +#define set_xen_guest_handle(hnd, val) \ + do { \ + if (sizeof(hnd) == 8) \ + *(uint64_t *)&(hnd) = 0; \ + (hnd).p = val; \ + } while (0) + +#define __HYPERVISOR_platform_op_raw __HYPERVISOR_platform_op + +#ifndef __ASSEMBLY__ +/* Explicitly size integers that represent pfns in the interface with + * Xen so that we can have one ABI that works for 32 and 64 bit guests. + * Note that this means that the xen_pfn_t type may be capable of + * representing pfn's which the guest cannot represent in its own pfn + * type. However since pfn space is controlled by the guest this is + * fine since it simply wouldn't be able to create any sure pfns in + * the first place. + */ +typedef uint64_t xen_pfn_t; +#define PRI_xen_pfn "llx" +typedef uint64_t xen_ulong_t; +#define PRI_xen_ulong "llx" +typedef int64_t xen_long_t; +#define PRI_xen_long "llx" +/* Guest handles for primitive C types. */ +__DEFINE_GUEST_HANDLE(uchar, unsigned char); +__DEFINE_GUEST_HANDLE(uint, unsigned int); +DEFINE_GUEST_HANDLE(char); +DEFINE_GUEST_HANDLE(int); +DEFINE_GUEST_HANDLE(void); +DEFINE_GUEST_HANDLE(uint64_t); +DEFINE_GUEST_HANDLE(uint32_t); +DEFINE_GUEST_HANDLE(xen_pfn_t); +DEFINE_GUEST_HANDLE(xen_ulong_t); + +/* Maximum number of virtual CPUs in multi-processor guests. */ +#define MAX_VIRT_CPUS 1 + +struct arch_vcpu_info { }; +struct arch_shared_info { }; + +/* TODO: Move pvclock definitions some place arch independent */ +struct pvclock_vcpu_time_info { + u32 version; + u32 pad0; + u64 tsc_timestamp; + u64 system_time; + u32 tsc_to_system_mul; + s8 tsc_shift; + u8 flags; + u8 pad[2]; +} __packed; /* 32 bytes */ + +/* It is OK to have a 12 bytes struct with no padding because it is packed */ +struct pvclock_wall_clock { + u32 version; + u32 sec; + u32 nsec; + u32 sec_hi; +} __packed; +#endif + +#endif /* _ASM_RISCV_XEN_INTERFACE_H */ diff --git a/include/xen/riscv/page.h b/include/xen/riscv/page.h new file mode 100644 index 000000000000..fe07a9bffa7e --- /dev/null +++ b/include/xen/riscv/page.h @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_RISCV_XEN_PAGE_H +#define _ASM_RISCV_XEN_PAGE_H + +#include + +#include +#include +#include +#include + +#include +#include + +/* Xen machine address */ +struct xmaddr { + phys_addr_t maddr; +}; + +/* Xen pseudo-physical address */ +struct xpaddr { + phys_addr_t paddr; +}; + +#define XMADDR(x) ((struct xmaddr) { .maddr = (x) }) +#define XPADDR(x) ((struct xpaddr) { .paddr = (x) }) + +#define INVALID_P2M_ENTRY (~0UL) + +/* + * The pseudo-physical frame (pfn) used in all the helpers is always based + * on Xen page granularity (i.e 4KB). + * + * A Linux page may be split across multiple non-contiguous Xen page so we + * have to keep track with frame based on 4KB page granularity. + * + * PV drivers should never make a direct usage of those helpers (particularly + * pfn_to_gfn and gfn_to_pfn). + */ + +unsigned long __pfn_to_mfn(unsigned long pfn); +extern struct rb_root phys_to_mach; + +/* Pseudo-physical <-> Guest conversion */ +static inline unsigned long pfn_to_gfn(unsigned long pfn) +{ + return 0; +} + +static inline unsigned long gfn_to_pfn(unsigned long gfn) +{ + return 0; +} + +/* Pseudo-physical <-> BUS conversion */ +static inline unsigned long pfn_to_bfn(unsigned long pfn) +{ + return 0; +} + +static inline unsigned long bfn_to_pfn(unsigned long bfn) +{ + return 0; +} + +#define bfn_to_local_pfn(bfn) bfn_to_pfn(bfn) + +/* VIRT <-> GUEST conversion */ +#define virt_to_gfn(v) \ + ({ \ + WARN_ON_ONCE(!virt_addr_valid(v)); \ + pfn_to_gfn(virt_to_phys(v) >> XEN_PAGE_SHIFT); \ + }) +#define gfn_to_virt(m) (__va(gfn_to_pfn(m) << XEN_PAGE_SHIFT)) + +#define percpu_to_gfn(v) \ + (pfn_to_gfn(per_cpu_ptr_to_phys(v) >> XEN_PAGE_SHIFT)) + +static inline struct xmaddr arbitrary_virt_to_machine(void *vaddr) +{ + WARN_ON_ONCE(1); + return (struct xmaddr){0}; +} + +extern int set_foreign_p2m_mapping(struct gnttab_map_grant_ref *map_ops, + struct gnttab_map_grant_ref *kmap_ops, + struct page **pages, unsigned int count); + +extern int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops, + struct gnttab_unmap_grant_ref *kunmap_ops, + struct page **pages, unsigned int count); + +bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn); +bool __set_phys_to_machine_multi(unsigned long pfn, unsigned long mfn, + unsigned long nr_pages); + +static inline bool set_phys_to_machine(unsigned long pfn, unsigned long mfn) +{ + return 0; +} + +bool xen_arch_need_swiotlb(struct device *dev, + phys_addr_t phys, + dma_addr_t dev_addr); + +#endif /* _ASM_RISCV_XEN_PAGE_H */ diff --git a/include/xen/riscv/swiotlb-xen.h b/include/xen/riscv/swiotlb-xen.h new file mode 100644 index 000000000000..97ecd8cbbc2d --- /dev/null +++ b/include/xen/riscv/swiotlb-xen.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_RISCV_SWIOTLB_XEN_H +#define _ASM_RISCV_SWIOTLB_XEN_H + +#include +#include + +static inline int xen_swiotlb_detect(void) +{ + return 0; +} + +#endif /* _ASM_RISCV_SWIOTLB_XEN_H */ diff --git a/test.txt b/test.txt new file mode 100644 index 000000000000..e54267998982 --- /dev/null +++ b/test.txt @@ -0,0 +1,21 @@ +WARNING: added, moved or deleted file(s), does MAINTAINERS need updating? +#120: +new file mode 100644 + +WARNING: do not add new typedefs +#808: FILE: include/xen/riscv/interface.h:15: ++ typedef struct { union { type * p; uint64_aligned_t q; }; } \ + +WARNING: please, no spaces at the start of a line +#1006: FILE: include/xen/riscv/swiotlb-xen.h:10: ++ return 0;$ + +total: 0 errors, 3 warnings, 810 lines checked + +NOTE: For some of the reported defects, checkpatch may be able to + mechanically convert to the typical style using --fix or --fix-inplace. + +0001-riscv-Add-initial-Xen-guest-support-for-RISC-V.patch has style problems, please review. + +NOTE: If any of the errors are false positives, please report + them to the maintainer, see CHECKPATCH in MAINTAINERS.