2024-05-06 22:00:46 +08:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0 */
|
|
|
|
#ifndef _ASM_LOONGARCH_KVM_PARA_H
|
|
|
|
#define _ASM_LOONGARCH_KVM_PARA_H
|
|
|
|
|
2024-09-12 20:53:40 +08:00
|
|
|
#include <uapi/asm/kvm_para.h>
|
|
|
|
|
LoongArch: KVM: Add PV IPI support on host side
On LoongArch system, IPI hw uses iocsr registers. There are one iocsr
register access on IPI sending, and two iocsr access on IPI receiving
for the IPI interrupt handler. In VM mode all iocsr accessing will cause
VM to trap into hypervisor. So with one IPI hw notification there will
be three times of trap.
In this patch PV IPI is added for VM, hypercall instruction is used for
IPI sender, and hypervisor will inject an SWI to the destination vcpu.
During the SWI interrupt handler, only CSR.ESTAT register is written to
clear irq. CSR.ESTAT register access will not trap into hypervisor, so
with PV IPI supported, there is one trap with IPI sender, and no trap
with IPI receiver, there is only one trap with IPI notification.
Also this patch adds IPI multicast support, the method is similar with
x86. With IPI multicast support, IPI notification can be sent to at
most 128 vcpus at one time. It greatly reduces the times of trapping
into hypervisor.
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
2024-05-06 22:00:47 +08:00
|
|
|
/*
|
|
|
|
* Hypercall code field
|
|
|
|
*/
|
|
|
|
#define HYPERVISOR_KVM 1
|
|
|
|
#define HYPERVISOR_VENDOR_SHIFT 8
|
|
|
|
#define HYPERCALL_ENCODE(vendor, code) ((vendor << HYPERVISOR_VENDOR_SHIFT) + code)
|
|
|
|
|
|
|
|
#define KVM_HCALL_CODE_SERVICE 0
|
2024-05-06 22:00:47 +08:00
|
|
|
#define KVM_HCALL_CODE_SWDBG 1
|
2025-01-13 21:37:17 +08:00
|
|
|
#define KVM_HCALL_CODE_USER_SERVICE 2
|
LoongArch: KVM: Add PV IPI support on host side
On LoongArch system, IPI hw uses iocsr registers. There are one iocsr
register access on IPI sending, and two iocsr access on IPI receiving
for the IPI interrupt handler. In VM mode all iocsr accessing will cause
VM to trap into hypervisor. So with one IPI hw notification there will
be three times of trap.
In this patch PV IPI is added for VM, hypercall instruction is used for
IPI sender, and hypervisor will inject an SWI to the destination vcpu.
During the SWI interrupt handler, only CSR.ESTAT register is written to
clear irq. CSR.ESTAT register access will not trap into hypervisor, so
with PV IPI supported, there is one trap with IPI sender, and no trap
with IPI receiver, there is only one trap with IPI notification.
Also this patch adds IPI multicast support, the method is similar with
x86. With IPI multicast support, IPI notification can be sent to at
most 128 vcpus at one time. It greatly reduces the times of trapping
into hypervisor.
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
2024-05-06 22:00:47 +08:00
|
|
|
|
|
|
|
#define KVM_HCALL_SERVICE HYPERCALL_ENCODE(HYPERVISOR_KVM, KVM_HCALL_CODE_SERVICE)
|
|
|
|
#define KVM_HCALL_FUNC_IPI 1
|
2024-07-09 16:25:51 +08:00
|
|
|
#define KVM_HCALL_FUNC_NOTIFY 2
|
LoongArch: KVM: Add PV IPI support on host side
On LoongArch system, IPI hw uses iocsr registers. There are one iocsr
register access on IPI sending, and two iocsr access on IPI receiving
for the IPI interrupt handler. In VM mode all iocsr accessing will cause
VM to trap into hypervisor. So with one IPI hw notification there will
be three times of trap.
In this patch PV IPI is added for VM, hypercall instruction is used for
IPI sender, and hypervisor will inject an SWI to the destination vcpu.
During the SWI interrupt handler, only CSR.ESTAT register is written to
clear irq. CSR.ESTAT register access will not trap into hypervisor, so
with PV IPI supported, there is one trap with IPI sender, and no trap
with IPI receiver, there is only one trap with IPI notification.
Also this patch adds IPI multicast support, the method is similar with
x86. With IPI multicast support, IPI notification can be sent to at
most 128 vcpus at one time. It greatly reduces the times of trapping
into hypervisor.
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
2024-05-06 22:00:47 +08:00
|
|
|
|
2024-05-06 22:00:47 +08:00
|
|
|
#define KVM_HCALL_SWDBG HYPERCALL_ENCODE(HYPERVISOR_KVM, KVM_HCALL_CODE_SWDBG)
|
|
|
|
|
2025-01-13 21:37:17 +08:00
|
|
|
#define KVM_HCALL_USER_SERVICE HYPERCALL_ENCODE(HYPERVISOR_KVM, KVM_HCALL_CODE_USER_SERVICE)
|
|
|
|
|
2024-05-06 22:00:46 +08:00
|
|
|
/*
|
|
|
|
* LoongArch hypercall return code
|
|
|
|
*/
|
|
|
|
#define KVM_HCALL_SUCCESS 0
|
|
|
|
#define KVM_HCALL_INVALID_CODE -1UL
|
|
|
|
#define KVM_HCALL_INVALID_PARAMETER -2UL
|
|
|
|
|
2024-07-09 16:25:51 +08:00
|
|
|
#define KVM_STEAL_PHYS_VALID BIT_ULL(0)
|
|
|
|
#define KVM_STEAL_PHYS_MASK GENMASK_ULL(63, 6)
|
|
|
|
|
|
|
|
struct kvm_steal_time {
|
|
|
|
__u64 steal;
|
|
|
|
__u32 version;
|
|
|
|
__u32 flags;
|
|
|
|
__u32 pad[12];
|
|
|
|
};
|
|
|
|
|
LoongArch: KVM: Add PV IPI support on host side
On LoongArch system, IPI hw uses iocsr registers. There are one iocsr
register access on IPI sending, and two iocsr access on IPI receiving
for the IPI interrupt handler. In VM mode all iocsr accessing will cause
VM to trap into hypervisor. So with one IPI hw notification there will
be three times of trap.
In this patch PV IPI is added for VM, hypercall instruction is used for
IPI sender, and hypervisor will inject an SWI to the destination vcpu.
During the SWI interrupt handler, only CSR.ESTAT register is written to
clear irq. CSR.ESTAT register access will not trap into hypervisor, so
with PV IPI supported, there is one trap with IPI sender, and no trap
with IPI receiver, there is only one trap with IPI notification.
Also this patch adds IPI multicast support, the method is similar with
x86. With IPI multicast support, IPI notification can be sent to at
most 128 vcpus at one time. It greatly reduces the times of trapping
into hypervisor.
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
2024-05-06 22:00:47 +08:00
|
|
|
/*
|
|
|
|
* Hypercall interface for KVM hypervisor
|
|
|
|
*
|
|
|
|
* a0: function identifier
|
2024-08-07 17:37:14 +08:00
|
|
|
* a1-a5: args
|
LoongArch: KVM: Add PV IPI support on host side
On LoongArch system, IPI hw uses iocsr registers. There are one iocsr
register access on IPI sending, and two iocsr access on IPI receiving
for the IPI interrupt handler. In VM mode all iocsr accessing will cause
VM to trap into hypervisor. So with one IPI hw notification there will
be three times of trap.
In this patch PV IPI is added for VM, hypercall instruction is used for
IPI sender, and hypervisor will inject an SWI to the destination vcpu.
During the SWI interrupt handler, only CSR.ESTAT register is written to
clear irq. CSR.ESTAT register access will not trap into hypervisor, so
with PV IPI supported, there is one trap with IPI sender, and no trap
with IPI receiver, there is only one trap with IPI notification.
Also this patch adds IPI multicast support, the method is similar with
x86. With IPI multicast support, IPI notification can be sent to at
most 128 vcpus at one time. It greatly reduces the times of trapping
into hypervisor.
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
2024-05-06 22:00:47 +08:00
|
|
|
* Return value will be placed in a0.
|
2024-08-07 17:37:14 +08:00
|
|
|
* Up to 5 arguments are passed in a1, a2, a3, a4, a5.
|
LoongArch: KVM: Add PV IPI support on host side
On LoongArch system, IPI hw uses iocsr registers. There are one iocsr
register access on IPI sending, and two iocsr access on IPI receiving
for the IPI interrupt handler. In VM mode all iocsr accessing will cause
VM to trap into hypervisor. So with one IPI hw notification there will
be three times of trap.
In this patch PV IPI is added for VM, hypercall instruction is used for
IPI sender, and hypervisor will inject an SWI to the destination vcpu.
During the SWI interrupt handler, only CSR.ESTAT register is written to
clear irq. CSR.ESTAT register access will not trap into hypervisor, so
with PV IPI supported, there is one trap with IPI sender, and no trap
with IPI receiver, there is only one trap with IPI notification.
Also this patch adds IPI multicast support, the method is similar with
x86. With IPI multicast support, IPI notification can be sent to at
most 128 vcpus at one time. It greatly reduces the times of trapping
into hypervisor.
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
2024-05-06 22:00:47 +08:00
|
|
|
*/
|
|
|
|
static __always_inline long kvm_hypercall0(u64 fid)
|
|
|
|
{
|
|
|
|
register long ret asm("a0");
|
|
|
|
register unsigned long fun asm("a0") = fid;
|
|
|
|
|
|
|
|
__asm__ __volatile__(
|
|
|
|
"hvcl "__stringify(KVM_HCALL_SERVICE)
|
|
|
|
: "=r" (ret)
|
|
|
|
: "r" (fun)
|
|
|
|
: "memory"
|
|
|
|
);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static __always_inline long kvm_hypercall1(u64 fid, unsigned long arg0)
|
|
|
|
{
|
|
|
|
register long ret asm("a0");
|
|
|
|
register unsigned long fun asm("a0") = fid;
|
|
|
|
register unsigned long a1 asm("a1") = arg0;
|
|
|
|
|
|
|
|
__asm__ __volatile__(
|
|
|
|
"hvcl "__stringify(KVM_HCALL_SERVICE)
|
|
|
|
: "=r" (ret)
|
|
|
|
: "r" (fun), "r" (a1)
|
|
|
|
: "memory"
|
|
|
|
);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static __always_inline long kvm_hypercall2(u64 fid,
|
|
|
|
unsigned long arg0, unsigned long arg1)
|
|
|
|
{
|
|
|
|
register long ret asm("a0");
|
|
|
|
register unsigned long fun asm("a0") = fid;
|
|
|
|
register unsigned long a1 asm("a1") = arg0;
|
|
|
|
register unsigned long a2 asm("a2") = arg1;
|
|
|
|
|
|
|
|
__asm__ __volatile__(
|
|
|
|
"hvcl "__stringify(KVM_HCALL_SERVICE)
|
|
|
|
: "=r" (ret)
|
|
|
|
: "r" (fun), "r" (a1), "r" (a2)
|
|
|
|
: "memory"
|
|
|
|
);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static __always_inline long kvm_hypercall3(u64 fid,
|
|
|
|
unsigned long arg0, unsigned long arg1, unsigned long arg2)
|
|
|
|
{
|
|
|
|
register long ret asm("a0");
|
|
|
|
register unsigned long fun asm("a0") = fid;
|
|
|
|
register unsigned long a1 asm("a1") = arg0;
|
|
|
|
register unsigned long a2 asm("a2") = arg1;
|
|
|
|
register unsigned long a3 asm("a3") = arg2;
|
|
|
|
|
|
|
|
__asm__ __volatile__(
|
|
|
|
"hvcl "__stringify(KVM_HCALL_SERVICE)
|
|
|
|
: "=r" (ret)
|
|
|
|
: "r" (fun), "r" (a1), "r" (a2), "r" (a3)
|
|
|
|
: "memory"
|
|
|
|
);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static __always_inline long kvm_hypercall4(u64 fid,
|
|
|
|
unsigned long arg0, unsigned long arg1,
|
|
|
|
unsigned long arg2, unsigned long arg3)
|
|
|
|
{
|
|
|
|
register long ret asm("a0");
|
|
|
|
register unsigned long fun asm("a0") = fid;
|
|
|
|
register unsigned long a1 asm("a1") = arg0;
|
|
|
|
register unsigned long a2 asm("a2") = arg1;
|
|
|
|
register unsigned long a3 asm("a3") = arg2;
|
|
|
|
register unsigned long a4 asm("a4") = arg3;
|
|
|
|
|
|
|
|
__asm__ __volatile__(
|
|
|
|
"hvcl "__stringify(KVM_HCALL_SERVICE)
|
|
|
|
: "=r" (ret)
|
|
|
|
: "r"(fun), "r" (a1), "r" (a2), "r" (a3), "r" (a4)
|
|
|
|
: "memory"
|
|
|
|
);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static __always_inline long kvm_hypercall5(u64 fid,
|
|
|
|
unsigned long arg0, unsigned long arg1,
|
|
|
|
unsigned long arg2, unsigned long arg3, unsigned long arg4)
|
|
|
|
{
|
|
|
|
register long ret asm("a0");
|
|
|
|
register unsigned long fun asm("a0") = fid;
|
|
|
|
register unsigned long a1 asm("a1") = arg0;
|
|
|
|
register unsigned long a2 asm("a2") = arg1;
|
|
|
|
register unsigned long a3 asm("a3") = arg2;
|
|
|
|
register unsigned long a4 asm("a4") = arg3;
|
|
|
|
register unsigned long a5 asm("a5") = arg4;
|
|
|
|
|
|
|
|
__asm__ __volatile__(
|
|
|
|
"hvcl "__stringify(KVM_HCALL_SERVICE)
|
|
|
|
: "=r" (ret)
|
|
|
|
: "r"(fun), "r" (a1), "r" (a2), "r" (a3), "r" (a4), "r" (a5)
|
|
|
|
: "memory"
|
|
|
|
);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2024-09-12 22:56:14 +08:00
|
|
|
#ifdef CONFIG_PARAVIRT
|
|
|
|
bool kvm_para_available(void);
|
|
|
|
unsigned int kvm_arch_para_features(void);
|
|
|
|
#else
|
|
|
|
static inline bool kvm_para_available(void)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-05-06 22:00:46 +08:00
|
|
|
static inline unsigned int kvm_arch_para_features(void)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2024-09-12 22:56:14 +08:00
|
|
|
#endif
|
2024-05-06 22:00:46 +08:00
|
|
|
|
|
|
|
static inline unsigned int kvm_arch_para_hints(void)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool kvm_check_and_clear_guest_paused(void)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* _ASM_LOONGARCH_KVM_PARA_H */
|