lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAAhSdy2rfbNT6tTK7i7rV6M1kNs2bFOQtN5QZpJ2xPrJx6WXjw@mail.gmail.com>
Date: Tue, 14 Jan 2025 22:10:52 +0530
From: Anup Patel <anup@...infault.org>
To: Milan Djokic <milandjokic1995@...il.com>
Cc: linux-riscv@...ts.infradead.org, paul.walmsley@...ive.com, 
	palmer@...belt.com, aou@...s.berkeley.edu, jgross@...e.com, 
	sstabellini@...nel.org, oleksandr_tyshchenko@...m.com, 
	Slavisa.Petrovic@...rk.com, Milan.Djokic@...rk.com, 
	rafael.j.wysocki@...el.com, sunilvl@...tanamicro.com, takakura@...inux.co.jp, 
	linux-kernel@...r.kernel.org, xen-devel@...ts.xenproject.org, 
	iommu@...ts.linux.dev
Subject: Re: [PATCH] riscv: Add initial Xen guest support for RISC-V

On Tue, Jan 14, 2025 at 9:41 PM Milan Djokic <milandjokic1995@...il.com> wrote:
>
> From: Slavisa Petrovic <Slavisa.Petrovic@...rk.com>
>
> 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 <Milan.Djokic@...rk.com>
> Signed-off-by: Slavisa Petrovic <Slavisa.Petrovic@...rk.com>

A single patch with many changes is hard to review.

Please convert this patch into a series with smaller patches.
Also, include a cover letter in the series explaining how to
test Xen on RISC-V.

Regards,
Anup

> ---
>  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
>
> 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 <linux/cpu.h>
>
>  #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 <asm/xen/hypervisor.h>
> +
> +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 <asm/bitops.h>
> +#include <asm/cmpxchg.h>
> +
> +/* 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 <asm/ptrace.h>
> +#include <asm/atomic.h>
> +
> +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 <xen/riscv/hypercall.h>
> 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 <xen/riscv/hypervisor.h>
> 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 <xen/riscv/interface.h>
> 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 <xen/riscv/page.h>
> +#include <asm/mmu.h>
> 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 <xen/riscv/swiotlb-xen.h>
> 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 <xen/xen.h>
> +#include <xen/events.h>
> +#include <xen/grant_table.h>
> +#include <xen/hvm.h>
> +#include <xen/interface/vcpu.h>
> +#include <xen/interface/xen.h>
> +#include <xen/interface/memory.h>
> +#include <xen/interface/hvm/params.h>
> +#include <xen/features.h>
> +#include <xen/platform_pci.h>
> +#include <xen/xenbus.h>
> +#include <xen/page.h>
> +#include <xen/interface/sched.h>
> +#include <xen/xen-ops.h>
> +#include <asm/xen/hypervisor.h>
> +#include <asm/xen/hypercall.h>
> +#include <asm/efi.h>
> +#include <linux/interrupt.h>
> +#include <linux/irqreturn.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_fdt.h>
> +#include <linux/of_irq.h>
> +#include <linux/of_address.h>
> +#include <linux/cpuidle.h>
> +#include <linux/cpufreq.h>
> +#include <linux/cpu.h>
> +#include <linux/console.h>
> +#include <linux/pvclock_gtod.h>
> +#include <linux/reboot.h>
> +#include <linux/time64.h>
> +#include <linux/timekeeping.h>
> +#include <linux/timekeeper_internal.h>
> +#include <linux/acpi.h>
> +#include <linux/virtio_anchor.h>
> +
> +#include <linux/mm.h>
> +
> +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 <xen/interface/xen.h>
> +#include <xen/page.h>
> +#include <xen/grant_table.h>
> +
> +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 <linux/linkage.h>
> +#include <asm/assembler.h>
> +#include <xen/interface/xen.h>
> +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 <linux/memblock.h>
> +#include <linux/gfp.h>
> +#include <linux/export.h>
> +#include <linux/spinlock.h>
> +#include <linux/slab.h>
> +#include <linux/types.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/vmalloc.h>
> +#include <linux/swiotlb.h>
> +
> +#include <xen/xen.h>
> +#include <xen/interface/memory.h>
> +#include <xen/grant_table.h>
> +#include <xen/page.h>
> +#include <xen/swiotlb-xen.h>
> +
> +#include <asm/cacheflush.h>
> +#include <asm/xen/hypercall.h>
> +#include <asm/xen/interface.h>
> +
> +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 <linux/bug.h>
> +
> +#include <xen/interface/xen.h>
> +#include <xen/interface/sched.h>
> +#include <xen/interface/platform.h>
> +
> +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 <linux/init.h>
> +
> +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 <linux/types.h>
> +
> +#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 <asm/page.h>
> +
> +#include <linux/pfn.h>
> +#include <linux/types.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/pgtable.h>
> +
> +#include <xen/xen.h>
> +#include <xen/interface/grant_table.h>
> +
> +/* 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 <xen/features.h>
> +#include <xen/xen.h>
> +
> +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.
> --
> 2.43.0
>
>

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ