Commit 74c16b2e authored by Bibo Mao's avatar Bibo Mao Committed by Huacai Chen
Browse files

LoongArch: KVM: Add PV IPI support on guest side



PARAVIRT config option and PV IPI is added for the guest side, function
pv_ipi_init() is used to add IPI sending and IPI receiving hooks. This
function firstly checks whether system runs in VM mode, and if kernel
runs in VM mode, it will call function kvm_para_available() to detect
the current hypervirsor type (now only KVM type detection is supported).
The paravirt functions can work only if current hypervisor type is KVM,
since there is only KVM supported on LoongArch now.

PV IPI uses virtual IPI sender and virtual IPI receiver functions. With
virtual IPI sender, IPI message is stored in memory rather than emulated
HW. IPI multicast is also supported, and 128 vcpus can received IPIs
at the same time like X86 KVM method. Hypercall method is used for IPI
sending.

With virtual IPI receiver, HW SWI0 is used rather than real IPI HW.
Since VCPU has separate HW SWI0 like HW timer, there is no trap in IPI
interrupt acknowledge. Since IPI message is stored in memory, there is
no trap in getting IPI message.

Signed-off-by: default avatarBibo Mao <maobibo@loongson.cn>
Signed-off-by: default avatarHuacai Chen <chenhuacai@loongson.cn>
parent e33bda7e
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -632,6 +632,15 @@ config RANDOMIZE_BASE_MAX_OFFSET

source "kernel/livepatch/Kconfig"

config PARAVIRT
	bool "Enable paravirtualization code"
	depends on AS_HAS_LVZ_EXTENSION
	help
	  This changes the kernel so it can modify itself when it is run
	  under a hypervisor, potentially improving performance significantly
	  over full virtualization.  However, when run without a hypervisor
	  the kernel is theoretically slower and slightly larger.

endmenu

config ARCH_SELECT_MEMORY_MODEL
+1 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ enum ipi_msg_type {
typedef struct {
	unsigned int ipi_irqs[NR_IPI];
	unsigned int __softirq_pending;
	atomic_t message ____cacheline_aligned_in_smp;
} ____cacheline_aligned irq_cpustat_t;

DECLARE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat);
+30 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_LOONGARCH_PARAVIRT_H
#define _ASM_LOONGARCH_PARAVIRT_H

#ifdef CONFIG_PARAVIRT

#include <linux/static_call_types.h>
struct static_key;
extern struct static_key paravirt_steal_enabled;
extern struct static_key paravirt_steal_rq_enabled;

u64 dummy_steal_clock(int cpu);
DECLARE_STATIC_CALL(pv_steal_clock, dummy_steal_clock);

static inline u64 paravirt_steal_clock(int cpu)
{
	return static_call(pv_steal_clock)(cpu);
}

int __init pv_ipi_init(void);

#else

static inline int pv_ipi_init(void)
{
	return 0;
}

#endif // CONFIG_PARAVIRT
#endif
+1 −0
Original line number Diff line number Diff line
#include <asm/paravirt.h>
+1 −0
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ obj-$(CONFIG_MODULES) += module.o module-sections.o
obj-$(CONFIG_STACKTRACE)	+= stacktrace.o

obj-$(CONFIG_PROC_FS)		+= proc.o
obj-$(CONFIG_PARAVIRT)		+= paravirt.o

obj-$(CONFIG_SMP)		+= smp.o

Loading