[PATCH v5 0/3] LoongArch: KVM: Add Binary Translation extension support

0 views
Skip to first unread message

Bibo Mao

unread,
Jul 24, 2024, 11:34:34 PM (5 days ago) Jul 24
to Tianrui Zhao, Huacai Chen, WANG Xuerui, k...@vger.kernel.org, loon...@lists.linux.dev, linux-...@vger.kernel.org, Jiaxun Yang
Loongson Binary Translation (LBT) is used to accelerate binary
translation, which contains 4 scratch registers (scr0 to scr3), x86/ARM
eflags (eflags) and x87 fpu stack pointer (ftop).

Like FPU extension, here lately enabling method is used for LBT. LBT
context is saved/restored during vcpu context switch path.

Also this patch set LBT capability detection, and LBT register get/set
interface for userspace vmm, so that vm supports migration with BT
extension.

---
v4 ... v5:
1. Add feature detection for LSX/LASX from vm side, previously
LSX/LASX feature is detected from vcpu ioctl command, now both methods
are supported.

v3 ... v4:
1. Merge LBT feature detection for VM and VCPU into one patch.
2. Move function declaration such as kvm_lose_lbt()/kvm_check_fcsr()/
kvm_enable_lbt_fpu() from header file to c file, since it is only
used in one c file.

v2 ... v3:
1. Split KVM_LOONGARCH_VM_FEAT_LBT capability checking into three
sub-features, KVM_LOONGARCH_VM_FEAT_X86BT/KVM_LOONGARCH_VM_FEAT_ARMBT
and KVM_LOONGARCH_VM_FEAT_MIPSBT. Return success only if host supports
the sub-feature.

v1 ... v2:
1. With LBT register read or write interface to userpace, replace
device attr method with KVM_GET_ONE_REG method, since lbt register is
vcpu register and can be added in kvm_reg_list in future.
2. Add vm device attr ctrl marcro KVM_LOONGARCH_VM_FEAT_CTRL, it is
used to get supported LBT feature before vm or vcpu is created.
---

Bibo Mao (3):
LoongArch: KVM: Add HW Binary Translation extension support
LoongArch: KVM: Add LBT feature detection function
LoongArch: KVM: Add vm migration support for LBT registers

arch/loongarch/include/asm/kvm_host.h | 8 ++
arch/loongarch/include/asm/kvm_vcpu.h | 6 ++
arch/loongarch/include/uapi/asm/kvm.h | 17 ++++
arch/loongarch/kvm/exit.c | 9 ++
arch/loongarch/kvm/vcpu.c | 126 +++++++++++++++++++++++++-
arch/loongarch/kvm/vm.c | 52 ++++++++++-
6 files changed, 216 insertions(+), 2 deletions(-)


base-commit: c33ffdb70cc6df4105160f991288e7d2567d7ffa
--
2.39.3


Bibo Mao

unread,
Jul 24, 2024, 11:34:50 PM (5 days ago) Jul 24
to Tianrui Zhao, Huacai Chen, WANG Xuerui, k...@vger.kernel.org, loon...@lists.linux.dev, linux-...@vger.kernel.org, Jiaxun Yang
Every vcpu has separate LBT registers. And there are four scr registers,
one flags and ftop register for LBT extension. When VM migrates, VMM
needs to get LBT registers for every vcpu.

Here macro KVM_REG_LOONGARCH_LBT is added for new vcpu lbt register type,
the following macro is added to get/put LBT registers.
KVM_REG_LOONGARCH_LBT_SCR0
KVM_REG_LOONGARCH_LBT_SCR1
KVM_REG_LOONGARCH_LBT_SCR2
KVM_REG_LOONGARCH_LBT_SCR3
KVM_REG_LOONGARCH_LBT_EFLAGS
KVM_REG_LOONGARCH_LBT_FTOP

Signed-off-by: Bibo Mao <mao...@loongson.cn>
---
arch/loongarch/include/uapi/asm/kvm.h | 9 +++++
arch/loongarch/kvm/vcpu.c | 56 +++++++++++++++++++++++++++
2 files changed, 65 insertions(+)

diff --git a/arch/loongarch/include/uapi/asm/kvm.h b/arch/loongarch/include/uapi/asm/kvm.h
index 49bafac8b22d..003fb766c93f 100644
--- a/arch/loongarch/include/uapi/asm/kvm.h
+++ b/arch/loongarch/include/uapi/asm/kvm.h
@@ -64,6 +64,7 @@ struct kvm_fpu {
#define KVM_REG_LOONGARCH_KVM (KVM_REG_LOONGARCH | 0x20000ULL)
#define KVM_REG_LOONGARCH_FPSIMD (KVM_REG_LOONGARCH | 0x30000ULL)
#define KVM_REG_LOONGARCH_CPUCFG (KVM_REG_LOONGARCH | 0x40000ULL)
+#define KVM_REG_LOONGARCH_LBT (KVM_REG_LOONGARCH | 0x50000ULL)
#define KVM_REG_LOONGARCH_MASK (KVM_REG_LOONGARCH | 0x70000ULL)
#define KVM_CSR_IDX_MASK 0x7fff
#define KVM_CPUCFG_IDX_MASK 0x7fff
@@ -77,6 +78,14 @@ struct kvm_fpu {
/* Debugging: Special instruction for software breakpoint */
#define KVM_REG_LOONGARCH_DEBUG_INST (KVM_REG_LOONGARCH_KVM | KVM_REG_SIZE_U64 | 3)

+/* LBT registers */
+#define KVM_REG_LOONGARCH_LBT_SCR0 (KVM_REG_LOONGARCH_LBT | KVM_REG_SIZE_U64 | 1)
+#define KVM_REG_LOONGARCH_LBT_SCR1 (KVM_REG_LOONGARCH_LBT | KVM_REG_SIZE_U64 | 2)
+#define KVM_REG_LOONGARCH_LBT_SCR2 (KVM_REG_LOONGARCH_LBT | KVM_REG_SIZE_U64 | 3)
+#define KVM_REG_LOONGARCH_LBT_SCR3 (KVM_REG_LOONGARCH_LBT | KVM_REG_SIZE_U64 | 4)
+#define KVM_REG_LOONGARCH_LBT_EFLAGS (KVM_REG_LOONGARCH_LBT | KVM_REG_SIZE_U64 | 5)
+#define KVM_REG_LOONGARCH_LBT_FTOP (KVM_REG_LOONGARCH_LBT | KVM_REG_SIZE_U64 | 6)
+
#define LOONGARCH_REG_SHIFT 3
#define LOONGARCH_REG_64(TYPE, REG) (TYPE | KVM_REG_SIZE_U64 | (REG << LOONGARCH_REG_SHIFT))
#define KVM_IOC_CSRID(REG) LOONGARCH_REG_64(KVM_REG_LOONGARCH_CSR, REG)
diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c
index aeb5f76a86c1..76719bf522b7 100644
--- a/arch/loongarch/kvm/vcpu.c
+++ b/arch/loongarch/kvm/vcpu.c
@@ -597,6 +597,34 @@ static int kvm_get_one_reg(struct kvm_vcpu *vcpu,
break;
}
break;
+ case KVM_REG_LOONGARCH_LBT:
+ if (!kvm_guest_has_lbt(&vcpu->arch))
+ return -ENXIO;
+
+ switch (reg->id) {
+ case KVM_REG_LOONGARCH_LBT_SCR0:
+ vcpu->arch.lbt.scr0 = v;
+ break;
+ case KVM_REG_LOONGARCH_LBT_SCR1:
+ vcpu->arch.lbt.scr1 = v;
+ break;
+ case KVM_REG_LOONGARCH_LBT_SCR2:
+ vcpu->arch.lbt.scr2 = v;
+ break;
+ case KVM_REG_LOONGARCH_LBT_SCR3:
+ vcpu->arch.lbt.scr3 = v;
+ break;
+ case KVM_REG_LOONGARCH_LBT_EFLAGS:
+ vcpu->arch.lbt.eflags = v;
+ break;
+ case KVM_REG_LOONGARCH_LBT_FTOP:
+ vcpu->arch.fpu.ftop = v;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ break;
default:
ret = -EINVAL;
break;
@@ -663,6 +691,34 @@ static int kvm_set_one_reg(struct kvm_vcpu *vcpu,
break;
}
break;
+ case KVM_REG_LOONGARCH_LBT:
+ if (!kvm_guest_has_lbt(&vcpu->arch))
+ return -ENXIO;
+
+ switch (reg->id) {
+ case KVM_REG_LOONGARCH_LBT_SCR0:
+ *v = vcpu->arch.lbt.scr0;
+ break;
+ case KVM_REG_LOONGARCH_LBT_SCR1:
+ *v = vcpu->arch.lbt.scr1;
+ break;
+ case KVM_REG_LOONGARCH_LBT_SCR2:
+ *v = vcpu->arch.lbt.scr2;
+ break;
+ case KVM_REG_LOONGARCH_LBT_SCR3:
+ *v = vcpu->arch.lbt.scr3;
+ break;
+ case KVM_REG_LOONGARCH_LBT_EFLAGS:
+ *v = vcpu->arch.lbt.eflags;
+ break;
+ case KVM_REG_LOONGARCH_LBT_FTOP:
+ *v = vcpu->arch.fpu.ftop;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ break;
default:
ret = -EINVAL;
break;
--
2.39.3


Bibo Mao

unread,
Jul 24, 2024, 11:35:10 PM (5 days ago) Jul 24
to Tianrui Zhao, Huacai Chen, WANG Xuerui, k...@vger.kernel.org, loon...@lists.linux.dev, linux-...@vger.kernel.org, Jiaxun Yang
Loongson Binary Translation (LBT) is used to accelerate binary translation,
which contains 4 scratch registers (scr0 to scr3), x86/ARM eflags (eflags)
and x87 fpu stack pointer (ftop).

Like FPU extension, here late enabling method is used for LBT. LBT context
is saved/restored on vcpu context switch path.

Signed-off-by: Bibo Mao <mao...@loongson.cn>
---
arch/loongarch/include/asm/kvm_host.h | 8 ++++
arch/loongarch/include/asm/kvm_vcpu.h | 6 +++
arch/loongarch/kvm/exit.c | 9 ++++
arch/loongarch/kvm/vcpu.c | 64 ++++++++++++++++++++++++++-
4 files changed, 86 insertions(+), 1 deletion(-)

diff --git a/arch/loongarch/include/asm/kvm_host.h b/arch/loongarch/include/asm/kvm_host.h
index 44b54965f5b4..c409ab15bae1 100644
--- a/arch/loongarch/include/asm/kvm_host.h
+++ b/arch/loongarch/include/asm/kvm_host.h
@@ -137,6 +137,7 @@ enum emulation_result {
#define KVM_LARCH_LASX (0x1 << 2)
#define KVM_LARCH_SWCSR_LATEST (0x1 << 3)
#define KVM_LARCH_HWCSR_USABLE (0x1 << 4)
+#define KVM_LARCH_LBT (0x1 << 5)

struct kvm_vcpu_arch {
/*
@@ -170,6 +171,7 @@ struct kvm_vcpu_arch {

/* FPU state */
struct loongarch_fpu fpu FPU_ALIGN;
+ struct loongarch_lbt lbt;

/* CSR state */
struct loongarch_csrs *csr;
@@ -241,6 +243,12 @@ static inline bool kvm_guest_has_lasx(struct kvm_vcpu_arch *arch)
return arch->cpucfg[2] & CPUCFG2_LASX;
}

+static inline bool kvm_guest_has_lbt(struct kvm_vcpu_arch *arch)
+{
+ return arch->cpucfg[2] & (CPUCFG2_X86BT | CPUCFG2_ARMBT
+ | CPUCFG2_MIPSBT);
+}
+
/* Debug: dump vcpu state */
int kvm_arch_vcpu_dump_regs(struct kvm_vcpu *vcpu);

diff --git a/arch/loongarch/include/asm/kvm_vcpu.h b/arch/loongarch/include/asm/kvm_vcpu.h
index c416cb7125c0..3cc906a0ff54 100644
--- a/arch/loongarch/include/asm/kvm_vcpu.h
+++ b/arch/loongarch/include/asm/kvm_vcpu.h
@@ -75,6 +75,12 @@ static inline void kvm_save_lasx(struct loongarch_fpu *fpu) { }
static inline void kvm_restore_lasx(struct loongarch_fpu *fpu) { }
#endif

+#ifdef CONFIG_CPU_HAS_LBT
+int kvm_own_lbt(struct kvm_vcpu *vcpu);
+#else
+static inline int kvm_own_lbt(struct kvm_vcpu *vcpu) { return -EINVAL; }
+#endif
+
void kvm_init_timer(struct kvm_vcpu *vcpu, unsigned long hz);
void kvm_reset_timer(struct kvm_vcpu *vcpu);
void kvm_save_timer(struct kvm_vcpu *vcpu);
diff --git a/arch/loongarch/kvm/exit.c b/arch/loongarch/kvm/exit.c
index ea73f9dc2cc6..be2c326253a3 100644
--- a/arch/loongarch/kvm/exit.c
+++ b/arch/loongarch/kvm/exit.c
@@ -835,6 +835,14 @@ static int kvm_handle_hypercall(struct kvm_vcpu *vcpu)
return ret;
}

+static int kvm_handle_lbt_disabled(struct kvm_vcpu *vcpu)
+{
+ if (kvm_own_lbt(vcpu))
+ kvm_queue_exception(vcpu, EXCCODE_INE, 0);
+
+ return RESUME_GUEST;
+}
+
/*
* LoongArch KVM callback handling for unimplemented guest exiting
*/
@@ -867,6 +875,7 @@ static exit_handle_fn kvm_fault_tables[EXCCODE_INT_START] = {
[EXCCODE_LASXDIS] = kvm_handle_lasx_disabled,
[EXCCODE_GSPR] = kvm_handle_gspr,
[EXCCODE_HVC] = kvm_handle_hypercall,
+ [EXCCODE_BTDIS] = kvm_handle_lbt_disabled,
};

int kvm_handle_fault(struct kvm_vcpu *vcpu, int fault)
diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c
index 16756ffb55e8..9c5d2d286607 100644
--- a/arch/loongarch/kvm/vcpu.c
+++ b/arch/loongarch/kvm/vcpu.c
@@ -6,6 +6,7 @@
#include <linux/kvm_host.h>
#include <linux/entry-kvm.h>
#include <asm/fpu.h>
+#include <asm/lbt.h>
#include <asm/loongarch.h>
#include <asm/setup.h>
#include <asm/time.h>
@@ -977,12 +978,69 @@ int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
return 0;
}

+#ifdef CONFIG_CPU_HAS_LBT
+int kvm_own_lbt(struct kvm_vcpu *vcpu)
+{
+ if (!kvm_guest_has_lbt(&vcpu->arch))
+ return -EINVAL;
+
+ preempt_disable();
+ set_csr_euen(CSR_EUEN_LBTEN);
+
+ _restore_lbt(&vcpu->arch.lbt);
+ vcpu->arch.aux_inuse |= KVM_LARCH_LBT;
+ preempt_enable();
+ return 0;
+}
+
+static void kvm_lose_lbt(struct kvm_vcpu *vcpu)
+{
+ preempt_disable();
+ if (vcpu->arch.aux_inuse & KVM_LARCH_LBT) {
+ _save_lbt(&vcpu->arch.lbt);
+ clear_csr_euen(CSR_EUEN_LBTEN);
+ vcpu->arch.aux_inuse &= ~KVM_LARCH_LBT;
+ }
+ preempt_enable();
+}
+
+static void kvm_enable_lbt_fpu(struct kvm_vcpu *vcpu, unsigned long fcsr)
+{
+ /*
+ * if TM is enabled, top register save/restore will
+ * cause lbt exception, here enable lbt in advance
+ */
+ if (fcsr & FPU_CSR_TM)
+ kvm_own_lbt(vcpu);
+}
+
+static void kvm_check_fcsr(struct kvm_vcpu *vcpu)
+{
+ unsigned long fcsr;
+
+ if (vcpu->arch.aux_inuse & KVM_LARCH_FPU)
+ if (!(vcpu->arch.aux_inuse & KVM_LARCH_LBT)) {
+ fcsr = read_fcsr(LOONGARCH_FCSR0);
+ kvm_enable_lbt_fpu(vcpu, fcsr);
+ }
+}
+#else
+static inline void kvm_lose_lbt(struct kvm_vcpu *vcpu) { }
+static inline void kvm_enable_lbt_fpu(struct kvm_vcpu *vcpu,
+ unsigned long fcsr) { }
+static inline void kvm_check_fcsr(struct kvm_vcpu *vcpu) { }
+#endif
+
/* Enable FPU and restore context */
void kvm_own_fpu(struct kvm_vcpu *vcpu)
{
preempt_disable();

- /* Enable FPU */
+ /*
+ * Enable FPU for guest
+ * We set FR and FRE according to guest context
+ */
+ kvm_enable_lbt_fpu(vcpu, vcpu->arch.fpu.fcsr);
set_csr_euen(CSR_EUEN_FPEN);

kvm_restore_fpu(&vcpu->arch.fpu);
@@ -1002,6 +1060,7 @@ int kvm_own_lsx(struct kvm_vcpu *vcpu)
preempt_disable();

/* Enable LSX for guest */
+ kvm_enable_lbt_fpu(vcpu, vcpu->arch.fpu.fcsr);
set_csr_euen(CSR_EUEN_LSXEN | CSR_EUEN_FPEN);
switch (vcpu->arch.aux_inuse & KVM_LARCH_FPU) {
case KVM_LARCH_FPU:
@@ -1036,6 +1095,7 @@ int kvm_own_lasx(struct kvm_vcpu *vcpu)

preempt_disable();

+ kvm_enable_lbt_fpu(vcpu, vcpu->arch.fpu.fcsr);
set_csr_euen(CSR_EUEN_FPEN | CSR_EUEN_LSXEN | CSR_EUEN_LASXEN);
switch (vcpu->arch.aux_inuse & (KVM_LARCH_FPU | KVM_LARCH_LSX)) {
case KVM_LARCH_LSX:
@@ -1067,6 +1127,7 @@ void kvm_lose_fpu(struct kvm_vcpu *vcpu)
{
preempt_disable();

+ kvm_check_fcsr(vcpu);
if (vcpu->arch.aux_inuse & KVM_LARCH_LASX) {
kvm_save_lasx(&vcpu->arch.fpu);
vcpu->arch.aux_inuse &= ~(KVM_LARCH_LSX | KVM_LARCH_FPU | KVM_LARCH_LASX);
@@ -1089,6 +1150,7 @@ void kvm_lose_fpu(struct kvm_vcpu *vcpu)
/* Disable FPU */
clear_csr_euen(CSR_EUEN_FPEN);
}
+ kvm_lose_lbt(vcpu);

preempt_enable();
}
--
2.39.3


Bibo Mao

unread,
Jul 24, 2024, 11:35:18 PM (5 days ago) Jul 24
to Tianrui Zhao, Huacai Chen, WANG Xuerui, k...@vger.kernel.org, loon...@lists.linux.dev, linux-...@vger.kernel.org, Jiaxun Yang
Two kinds of LBT feature detection are added here, one is VCPU
feature, the other is VM feature. VCPU feature dection can only
work with VCPU thread itself, and requires VCPU thread is created
already. So LBT feature detection for VM is added also, it can
be done even if VM is not created, and also can be done by any
thread besides VCPU threads.

Loongson Binary Translation (LBT) feature is defined in register
cpucfg2. Here LBT capability detection for VCPU is added.

Here ioctl command KVM_HAS_DEVICE_ATTR is added for VM, and macro
KVM_LOONGARCH_VM_FEAT_CTRL is added to check supported feature. And
three sub-features relative with LBT are added as following:
KVM_LOONGARCH_VM_FEAT_X86BT
KVM_LOONGARCH_VM_FEAT_ARMBT
KVM_LOONGARCH_VM_FEAT_MIPSBT

Signed-off-by: Bibo Mao <mao...@loongson.cn>
---
arch/loongarch/include/uapi/asm/kvm.h | 8 +++++
arch/loongarch/kvm/vcpu.c | 6 ++++
arch/loongarch/kvm/vm.c | 52 ++++++++++++++++++++++++++-
3 files changed, 65 insertions(+), 1 deletion(-)

diff --git a/arch/loongarch/include/uapi/asm/kvm.h b/arch/loongarch/include/uapi/asm/kvm.h
index ddc5cab0ffd0..49bafac8b22d 100644
--- a/arch/loongarch/include/uapi/asm/kvm.h
+++ b/arch/loongarch/include/uapi/asm/kvm.h
@@ -82,6 +82,14 @@ struct kvm_fpu {
#define KVM_IOC_CSRID(REG) LOONGARCH_REG_64(KVM_REG_LOONGARCH_CSR, REG)
#define KVM_IOC_CPUCFG(REG) LOONGARCH_REG_64(KVM_REG_LOONGARCH_CPUCFG, REG)

+/* Device Control API on vm fd */
+#define KVM_LOONGARCH_VM_FEAT_CTRL 0
+#define KVM_LOONGARCH_VM_FEAT_LSX 0
+#define KVM_LOONGARCH_VM_FEAT_LASX 1
+#define KVM_LOONGARCH_VM_FEAT_X86BT 2
+#define KVM_LOONGARCH_VM_FEAT_ARMBT 3
+#define KVM_LOONGARCH_VM_FEAT_MIPSBT 4
+
/* Device Control API on vcpu fd */
#define KVM_LOONGARCH_VCPU_CPUCFG 0
#define KVM_LOONGARCH_VCPU_PVTIME_CTRL 1
diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c
index 9c5d2d286607..aeb5f76a86c1 100644
--- a/arch/loongarch/kvm/vcpu.c
+++ b/arch/loongarch/kvm/vcpu.c
@@ -498,6 +498,12 @@ static int _kvm_get_cpucfg_mask(int id, u64 *v)
*v |= CPUCFG2_LSX;
if (cpu_has_lasx)
*v |= CPUCFG2_LASX;
+ if (cpu_has_lbt_x86)
+ *v |= CPUCFG2_X86BT;
+ if (cpu_has_lbt_arm)
+ *v |= CPUCFG2_ARMBT;
+ if (cpu_has_lbt_mips)
+ *v |= CPUCFG2_MIPSBT;

return 0;
case LOONGARCH_CPUCFG3:
diff --git a/arch/loongarch/kvm/vm.c b/arch/loongarch/kvm/vm.c
index 6b2e4f66ad26..f9604bc2b3ea 100644
--- a/arch/loongarch/kvm/vm.c
+++ b/arch/loongarch/kvm/vm.c
@@ -99,7 +99,57 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
return r;
}

+static int kvm_vm_feature_has_attr(struct kvm *kvm, struct kvm_device_attr *attr)
+{
+ switch (attr->attr) {
+ case KVM_LOONGARCH_VM_FEAT_LSX:
+ if (cpu_has_lsx)
+ return 0;
+ return -ENXIO;
+ case KVM_LOONGARCH_VM_FEAT_LASX:
+ if (cpu_has_lasx)
+ return 0;
+ return -ENXIO;
+ case KVM_LOONGARCH_VM_FEAT_X86BT:
+ if (cpu_has_lbt_x86)
+ return 0;
+ return -ENXIO;
+ case KVM_LOONGARCH_VM_FEAT_ARMBT:
+ if (cpu_has_lbt_arm)
+ return 0;
+ return -ENXIO;
+ case KVM_LOONGARCH_VM_FEAT_MIPSBT:
+ if (cpu_has_lbt_mips)
+ return 0;
+ return -ENXIO;
+ default:
+ return -ENXIO;
+ }
+}
+
+static int kvm_vm_has_attr(struct kvm *kvm, struct kvm_device_attr *attr)
+{
+ switch (attr->group) {
+ case KVM_LOONGARCH_VM_FEAT_CTRL:
+ return kvm_vm_feature_has_attr(kvm, attr);
+ default:
+ return -ENXIO;
+ }
+}
+
int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
{
- return -ENOIOCTLCMD;
+ struct kvm *kvm = filp->private_data;
+ void __user *argp = (void __user *)arg;
+ struct kvm_device_attr attr;
+
+ switch (ioctl) {
+ case KVM_HAS_DEVICE_ATTR:
+ if (copy_from_user(&attr, argp, sizeof(attr)))
+ return -EFAULT;
+
+ return kvm_vm_has_attr(kvm, &attr);
+ default:
+ return -EINVAL;
+ }
}
--
2.39.3


kernel test robot

unread,
Jul 25, 2024, 9:59:15 AM (5 days ago) Jul 25
to Bibo Mao, Tianrui Zhao, Huacai Chen, oe-kbu...@lists.linux.dev, WANG Xuerui, k...@vger.kernel.org, loon...@lists.linux.dev, linux-...@vger.kernel.org, Jiaxun Yang
Hi Bibo,

kernel test robot noticed the following build errors:

[auto build test ERROR on c33ffdb70cc6df4105160f991288e7d2567d7ffa]

url: https://github.com/intel-lab-lkp/linux/commits/Bibo-Mao/LoongArch-KVM-Add-HW-Binary-Translation-extension-support/20240725-113707
base: c33ffdb70cc6df4105160f991288e7d2567d7ffa
patch link: https://lore.kernel.org/r/20240725033404.2675204-4-maobibo%40loongson.cn
patch subject: [PATCH v5 3/3] LoongArch: KVM: Add vm migration support for LBT registers
config: loongarch-defconfig (https://download.01.org/0day-ci/archive/20240725/202407252157...@intel.com/config)
compiler: loongarch64-linux-gcc (GCC) 14.1.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240725/202407252157...@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <l...@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202407252157...@intel.com/

All errors (new ones prefixed by >>):

arch/loongarch/kvm/vcpu.c: In function 'kvm_get_one_reg':
>> arch/loongarch/kvm/vcpu.c:606:45: error: assignment to 'long unsigned int' from 'u64 *' {aka 'long long unsigned int *'} makes integer from pointer without a cast [-Wint-conversion]
606 | vcpu->arch.lbt.scr0 = v;
| ^
arch/loongarch/kvm/vcpu.c:609:45: error: assignment to 'long unsigned int' from 'u64 *' {aka 'long long unsigned int *'} makes integer from pointer without a cast [-Wint-conversion]
609 | vcpu->arch.lbt.scr1 = v;
| ^
arch/loongarch/kvm/vcpu.c:612:45: error: assignment to 'long unsigned int' from 'u64 *' {aka 'long long unsigned int *'} makes integer from pointer without a cast [-Wint-conversion]
612 | vcpu->arch.lbt.scr2 = v;
| ^
arch/loongarch/kvm/vcpu.c:615:45: error: assignment to 'long unsigned int' from 'u64 *' {aka 'long long unsigned int *'} makes integer from pointer without a cast [-Wint-conversion]
615 | vcpu->arch.lbt.scr3 = v;
| ^
arch/loongarch/kvm/vcpu.c:618:47: error: assignment to 'long unsigned int' from 'u64 *' {aka 'long long unsigned int *'} makes integer from pointer without a cast [-Wint-conversion]
618 | vcpu->arch.lbt.eflags = v;
| ^
>> arch/loongarch/kvm/vcpu.c:621:45: error: assignment to 'uint32_t' {aka 'unsigned int'} from 'u64 *' {aka 'long long unsigned int *'} makes integer from pointer without a cast [-Wint-conversion]
621 | vcpu->arch.fpu.ftop = v;
| ^
arch/loongarch/kvm/vcpu.c: In function 'kvm_set_one_reg':
>> arch/loongarch/kvm/vcpu.c:700:25: error: invalid type argument of unary '*' (have 'u64' {aka 'long long unsigned int'})
700 | *v = vcpu->arch.lbt.scr0;
| ^~
arch/loongarch/kvm/vcpu.c:703:25: error: invalid type argument of unary '*' (have 'u64' {aka 'long long unsigned int'})
703 | *v = vcpu->arch.lbt.scr1;
| ^~
arch/loongarch/kvm/vcpu.c:706:25: error: invalid type argument of unary '*' (have 'u64' {aka 'long long unsigned int'})
706 | *v = vcpu->arch.lbt.scr2;
| ^~
arch/loongarch/kvm/vcpu.c:709:25: error: invalid type argument of unary '*' (have 'u64' {aka 'long long unsigned int'})
709 | *v = vcpu->arch.lbt.scr3;
| ^~
arch/loongarch/kvm/vcpu.c:712:25: error: invalid type argument of unary '*' (have 'u64' {aka 'long long unsigned int'})
712 | *v = vcpu->arch.lbt.eflags;
| ^~
arch/loongarch/kvm/vcpu.c:715:25: error: invalid type argument of unary '*' (have 'u64' {aka 'long long unsigned int'})
715 | *v = vcpu->arch.fpu.ftop;
| ^~


vim +606 arch/loongarch/kvm/vcpu.c

568
569 static int kvm_get_one_reg(struct kvm_vcpu *vcpu,
570 const struct kvm_one_reg *reg, u64 *v)
571 {
572 int id, ret = 0;
573 u64 type = reg->id & KVM_REG_LOONGARCH_MASK;
574
575 switch (type) {
576 case KVM_REG_LOONGARCH_CSR:
577 id = KVM_GET_IOC_CSR_IDX(reg->id);
578 ret = _kvm_getcsr(vcpu, id, v);
579 break;
580 case KVM_REG_LOONGARCH_CPUCFG:
581 id = KVM_GET_IOC_CPUCFG_IDX(reg->id);
582 if (id >= 0 && id < KVM_MAX_CPUCFG_REGS)
583 *v = vcpu->arch.cpucfg[id];
584 else
585 ret = -EINVAL;
586 break;
587 case KVM_REG_LOONGARCH_KVM:
588 switch (reg->id) {
589 case KVM_REG_LOONGARCH_COUNTER:
590 *v = drdtime() + vcpu->kvm->arch.time_offset;
591 break;
592 case KVM_REG_LOONGARCH_DEBUG_INST:
593 *v = INSN_HVCL | KVM_HCALL_SWDBG;
594 break;
595 default:
596 ret = -EINVAL;
597 break;
598 }
599 break;
600 case KVM_REG_LOONGARCH_LBT:
601 if (!kvm_guest_has_lbt(&vcpu->arch))
602 return -ENXIO;
603
604 switch (reg->id) {
605 case KVM_REG_LOONGARCH_LBT_SCR0:
> 606 vcpu->arch.lbt.scr0 = v;
607 break;
608 case KVM_REG_LOONGARCH_LBT_SCR1:
609 vcpu->arch.lbt.scr1 = v;
610 break;
611 case KVM_REG_LOONGARCH_LBT_SCR2:
612 vcpu->arch.lbt.scr2 = v;
613 break;
614 case KVM_REG_LOONGARCH_LBT_SCR3:
615 vcpu->arch.lbt.scr3 = v;
616 break;
617 case KVM_REG_LOONGARCH_LBT_EFLAGS:
618 vcpu->arch.lbt.eflags = v;
619 break;
620 case KVM_REG_LOONGARCH_LBT_FTOP:
> 621 vcpu->arch.fpu.ftop = v;
622 break;
623 default:
624 ret = -EINVAL;
625 break;
626 }
627 break;
628 default:
629 ret = -EINVAL;
630 break;
631 }
632
633 return ret;
634 }
635
636 static int kvm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
637 {
638 int ret = 0;
639 u64 v, size = reg->id & KVM_REG_SIZE_MASK;
640
641 switch (size) {
642 case KVM_REG_SIZE_U64:
643 ret = kvm_get_one_reg(vcpu, reg, &v);
644 if (ret)
645 return ret;
646 ret = put_user(v, (u64 __user *)(long)reg->addr);
647 break;
648 default:
649 ret = -EINVAL;
650 break;
651 }
652
653 return ret;
654 }
655
656 static int kvm_set_one_reg(struct kvm_vcpu *vcpu,
657 const struct kvm_one_reg *reg, u64 v)
658 {
659 int id, ret = 0;
660 u64 type = reg->id & KVM_REG_LOONGARCH_MASK;
661
662 switch (type) {
663 case KVM_REG_LOONGARCH_CSR:
664 id = KVM_GET_IOC_CSR_IDX(reg->id);
665 ret = _kvm_setcsr(vcpu, id, v);
666 break;
667 case KVM_REG_LOONGARCH_CPUCFG:
668 id = KVM_GET_IOC_CPUCFG_IDX(reg->id);
669 ret = kvm_check_cpucfg(id, v);
670 if (ret)
671 break;
672 vcpu->arch.cpucfg[id] = (u32)v;
673 break;
674 case KVM_REG_LOONGARCH_KVM:
675 switch (reg->id) {
676 case KVM_REG_LOONGARCH_COUNTER:
677 /*
678 * gftoffset is relative with board, not vcpu
679 * only set for the first time for smp system
680 */
681 if (vcpu->vcpu_id == 0)
682 vcpu->kvm->arch.time_offset = (signed long)(v - drdtime());
683 break;
684 case KVM_REG_LOONGARCH_VCPU_RESET:
685 kvm_reset_timer(vcpu);
686 memset(&vcpu->arch.irq_pending, 0, sizeof(vcpu->arch.irq_pending));
687 memset(&vcpu->arch.irq_clear, 0, sizeof(vcpu->arch.irq_clear));
688 break;
689 default:
690 ret = -EINVAL;
691 break;
692 }
693 break;
694 case KVM_REG_LOONGARCH_LBT:
695 if (!kvm_guest_has_lbt(&vcpu->arch))
696 return -ENXIO;
697
698 switch (reg->id) {
699 case KVM_REG_LOONGARCH_LBT_SCR0:
> 700 *v = vcpu->arch.lbt.scr0;
701 break;
702 case KVM_REG_LOONGARCH_LBT_SCR1:
703 *v = vcpu->arch.lbt.scr1;
704 break;
705 case KVM_REG_LOONGARCH_LBT_SCR2:
706 *v = vcpu->arch.lbt.scr2;
707 break;
708 case KVM_REG_LOONGARCH_LBT_SCR3:
709 *v = vcpu->arch.lbt.scr3;
710 break;
711 case KVM_REG_LOONGARCH_LBT_EFLAGS:
712 *v = vcpu->arch.lbt.eflags;
713 break;
714 case KVM_REG_LOONGARCH_LBT_FTOP:
715 *v = vcpu->arch.fpu.ftop;
716 break;
717 default:
718 ret = -EINVAL;
719 break;
720 }
721 break;
722 default:
723 ret = -EINVAL;
724 break;
725 }
726
727 return ret;
728 }
729

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

Bibo Mao

unread,
3:58 AM (4 hours ago) 3:58 AM
to Tianrui Zhao, Huacai Chen, WANG Xuerui, k...@vger.kernel.org, loon...@lists.linux.dev, linux-...@vger.kernel.org, Jiaxun Yang
Loongson Binary Translation (LBT) is used to accelerate binary
translation, which contains 4 scratch registers (scr0 to scr3), x86/ARM
eflags (eflags) and x87 fpu stack pointer (ftop).

Like FPU extension, here lately enabling method is used for LBT. LBT
context is saved/restored during vcpu context switch path.

Also this patch set LBT capability detection, and LBT register get and set
interface for userspace vmm, so that vm supports migration with BT
extension.

---
v5 ... v6:
1. Solve compiling issue with function kvm_get_one_reg() and
kvm_set_one_reg().

v4 ... v5:
1. Add feature detection for LSX/LASX from vm side, previously
LSX/LASX feature is detected from vcpu ioctl command, now both
methods are supported.

v3 ... v4:
1. Merge LBT feature detection for VM and VCPU into one patch.
2. Move function declaration such as kvm_lose_lbt()/kvm_check_fcsr()/
kvm_enable_lbt_fpu() from header file to c file, since it is only
used in one c file.

v2 ... v3:
1. Split KVM_LOONGARCH_VM_FEAT_LBT capability checking into three
sub-features, KVM_LOONGARCH_VM_FEAT_X86BT/KVM_LOONGARCH_VM_FEAT_ARMBT
and KVM_LOONGARCH_VM_FEAT_MIPSBT. Return success only if host
supports the sub-feature.

v1 ... v2:
1. With LBT register read or write interface to userpace, replace
device attr method with KVM_GET_ONE_REG method, since lbt register is
vcpu register and can be added in kvm_reg_list in future.
2. Add vm device attr ctrl marcro KVM_LOONGARCH_VM_FEAT_CTRL, it is
used to get supported LBT feature before vm or vcpu is created.
---
Bibo Mao (3):
LoongArch: KVM: Add HW Binary Translation extension support
LoongArch: KVM: Add LBT feature detection function
LoongArch: KVM: Add vm migration support for LBT registers

arch/loongarch/include/asm/kvm_host.h | 8 ++
arch/loongarch/include/asm/kvm_vcpu.h | 6 ++
arch/loongarch/include/uapi/asm/kvm.h | 17 ++++
arch/loongarch/kvm/exit.c | 9 ++
arch/loongarch/kvm/vcpu.c | 128 +++++++++++++++++++++++++-
arch/loongarch/kvm/vm.c | 52 ++++++++++-
6 files changed, 218 insertions(+), 2 deletions(-)


base-commit: 8400291e289ee6b2bf9779ff1c83a291501f017b
--
2.39.3


Bibo Mao

unread,
3:58 AM (4 hours ago) 3:58 AM
to Tianrui Zhao, Huacai Chen, WANG Xuerui, k...@vger.kernel.org, loon...@lists.linux.dev, linux-...@vger.kernel.org, Jiaxun Yang
Loongson Binary Translation (LBT) is used to accelerate binary translation,
which contains 4 scratch registers (scr0 to scr3), x86/ARM eflags (eflags)
and x87 fpu stack pointer (ftop).

Like FPU extension, here late enabling method is used for LBT. LBT context
is saved/restored on vcpu context switch path.

Signed-off-by: Bibo Mao <mao...@loongson.cn>
---
arch/loongarch/include/asm/kvm_host.h | 8 ++++
arch/loongarch/include/asm/kvm_vcpu.h | 6 +++
arch/loongarch/kvm/exit.c | 9 ++++
arch/loongarch/kvm/vcpu.c | 66 ++++++++++++++++++++++++++-
4 files changed, 88 insertions(+), 1 deletion(-)
diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c
index 16756ffb55e8..36db2b257a95 100644
--- a/arch/loongarch/kvm/vcpu.c
+++ b/arch/loongarch/kvm/vcpu.c
@@ -6,6 +6,7 @@
#include <linux/kvm_host.h>
#include <linux/entry-kvm.h>
#include <asm/fpu.h>
+#include <asm/lbt.h>
#include <asm/loongarch.h>
#include <asm/setup.h>
#include <asm/time.h>
@@ -977,12 +978,71 @@ int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
+static void kvm_check_fscr(struct kvm_vcpu *vcpu, unsigned long fcsr)
+{
+ /*
+ * If TM is enabled, top register save/restore will
+ * cause lbt exception, here enable lbt in advance
+ */
+ if (fcsr & FPU_CSR_TM)
+ kvm_own_lbt(vcpu);
+}
+
+static void kvm_check_fcsr_alive(struct kvm_vcpu *vcpu)
+{
+ unsigned long fcsr;
+
+ if (vcpu->arch.aux_inuse & KVM_LARCH_FPU) {
+ if (vcpu->arch.aux_inuse & KVM_LARCH_LBT)
+ return;
+
+ fcsr = read_fcsr(LOONGARCH_FCSR0);
+ kvm_check_fscr(vcpu, fcsr);
+ }
+}
+#else
+static inline void kvm_lose_lbt(struct kvm_vcpu *vcpu) { }
+static inline void kvm_check_fscr(struct kvm_vcpu *vcpu,
+ unsigned long fcsr) { }
+static inline void kvm_check_fcsr_alive(struct kvm_vcpu *vcpu) { }
+#endif
+
/* Enable FPU and restore context */
void kvm_own_fpu(struct kvm_vcpu *vcpu)
{
preempt_disable();

- /* Enable FPU */
+ /*
+ * Enable FPU for guest
+ * Set FR and FRE according to guest context
+ */
+ kvm_check_fscr(vcpu, vcpu->arch.fpu.fcsr);
set_csr_euen(CSR_EUEN_FPEN);

kvm_restore_fpu(&vcpu->arch.fpu);
@@ -1002,6 +1062,7 @@ int kvm_own_lsx(struct kvm_vcpu *vcpu)
preempt_disable();

/* Enable LSX for guest */
+ kvm_check_fscr(vcpu, vcpu->arch.fpu.fcsr);
set_csr_euen(CSR_EUEN_LSXEN | CSR_EUEN_FPEN);
switch (vcpu->arch.aux_inuse & KVM_LARCH_FPU) {
case KVM_LARCH_FPU:
@@ -1036,6 +1097,7 @@ int kvm_own_lasx(struct kvm_vcpu *vcpu)

preempt_disable();

+ kvm_check_fscr(vcpu, vcpu->arch.fpu.fcsr);
set_csr_euen(CSR_EUEN_FPEN | CSR_EUEN_LSXEN | CSR_EUEN_LASXEN);
switch (vcpu->arch.aux_inuse & (KVM_LARCH_FPU | KVM_LARCH_LSX)) {
case KVM_LARCH_LSX:
@@ -1067,6 +1129,7 @@ void kvm_lose_fpu(struct kvm_vcpu *vcpu)
{
preempt_disable();

+ kvm_check_fcsr_alive(vcpu);
if (vcpu->arch.aux_inuse & KVM_LARCH_LASX) {
kvm_save_lasx(&vcpu->arch.fpu);
vcpu->arch.aux_inuse &= ~(KVM_LARCH_LSX | KVM_LARCH_FPU | KVM_LARCH_LASX);
@@ -1089,6 +1152,7 @@ void kvm_lose_fpu(struct kvm_vcpu *vcpu)

Bibo Mao

unread,
3:58 AM (4 hours ago) 3:58 AM
to Tianrui Zhao, Huacai Chen, WANG Xuerui, k...@vger.kernel.org, loon...@lists.linux.dev, linux-...@vger.kernel.org, Jiaxun Yang
Every vcpu has separate LBT registers. And there are four scr registers,
one flags and ftop register for LBT extension. When VM migrates, VMM
needs to get LBT registers for every vcpu.

Here macro KVM_REG_LOONGARCH_LBT is added for new vcpu lbt register type,
the following macro is added to get/put LBT registers.
KVM_REG_LOONGARCH_LBT_SCR0
KVM_REG_LOONGARCH_LBT_SCR1
KVM_REG_LOONGARCH_LBT_SCR2
KVM_REG_LOONGARCH_LBT_SCR3
KVM_REG_LOONGARCH_LBT_EFLAGS
KVM_REG_LOONGARCH_LBT_FTOP

Signed-off-by: Bibo Mao <mao...@loongson.cn>
---
arch/loongarch/include/uapi/asm/kvm.h | 9 +++++
arch/loongarch/kvm/vcpu.c | 56 +++++++++++++++++++++++++++
2 files changed, 65 insertions(+)

diff --git a/arch/loongarch/include/uapi/asm/kvm.h b/arch/loongarch/include/uapi/asm/kvm.h
index 49bafac8b22d..003fb766c93f 100644
--- a/arch/loongarch/include/uapi/asm/kvm.h
+++ b/arch/loongarch/include/uapi/asm/kvm.h
@@ -64,6 +64,7 @@ struct kvm_fpu {
#define KVM_REG_LOONGARCH_KVM (KVM_REG_LOONGARCH | 0x20000ULL)
#define KVM_REG_LOONGARCH_FPSIMD (KVM_REG_LOONGARCH | 0x30000ULL)
#define KVM_REG_LOONGARCH_CPUCFG (KVM_REG_LOONGARCH | 0x40000ULL)
+#define KVM_REG_LOONGARCH_LBT (KVM_REG_LOONGARCH | 0x50000ULL)
#define KVM_REG_LOONGARCH_MASK (KVM_REG_LOONGARCH | 0x70000ULL)
#define KVM_CSR_IDX_MASK 0x7fff
#define KVM_CPUCFG_IDX_MASK 0x7fff
@@ -77,6 +78,14 @@ struct kvm_fpu {
/* Debugging: Special instruction for software breakpoint */
#define KVM_REG_LOONGARCH_DEBUG_INST (KVM_REG_LOONGARCH_KVM | KVM_REG_SIZE_U64 | 3)

+/* LBT registers */
+#define KVM_REG_LOONGARCH_LBT_SCR0 (KVM_REG_LOONGARCH_LBT | KVM_REG_SIZE_U64 | 1)
+#define KVM_REG_LOONGARCH_LBT_SCR1 (KVM_REG_LOONGARCH_LBT | KVM_REG_SIZE_U64 | 2)
+#define KVM_REG_LOONGARCH_LBT_SCR2 (KVM_REG_LOONGARCH_LBT | KVM_REG_SIZE_U64 | 3)
+#define KVM_REG_LOONGARCH_LBT_SCR3 (KVM_REG_LOONGARCH_LBT | KVM_REG_SIZE_U64 | 4)
+#define KVM_REG_LOONGARCH_LBT_EFLAGS (KVM_REG_LOONGARCH_LBT | KVM_REG_SIZE_U64 | 5)
+#define KVM_REG_LOONGARCH_LBT_FTOP (KVM_REG_LOONGARCH_LBT | KVM_REG_SIZE_U64 | 6)
+
#define LOONGARCH_REG_SHIFT 3
#define LOONGARCH_REG_64(TYPE, REG) (TYPE | KVM_REG_SIZE_U64 | (REG << LOONGARCH_REG_SHIFT))
#define KVM_IOC_CSRID(REG) LOONGARCH_REG_64(KVM_REG_LOONGARCH_CSR, REG)
diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c
index b5324885a81a..b2500d4fa729 100644
--- a/arch/loongarch/kvm/vcpu.c
+++ b/arch/loongarch/kvm/vcpu.c
@@ -597,6 +597,34 @@ static int kvm_get_one_reg(struct kvm_vcpu *vcpu,
break;
}
break;
+ case KVM_REG_LOONGARCH_LBT:
+ if (!kvm_guest_has_lbt(&vcpu->arch))
@@ -663,6 +691,34 @@ static int kvm_set_one_reg(struct kvm_vcpu *vcpu,
break;
}
break;
+ case KVM_REG_LOONGARCH_LBT:
+ if (!kvm_guest_has_lbt(&vcpu->arch))
--
2.39.3


Bibo Mao

unread,
4:03 AM (4 hours ago) 4:03 AM
to Tianrui Zhao, Huacai Chen, WANG Xuerui, k...@vger.kernel.org, loon...@lists.linux.dev, linux-...@vger.kernel.org, Jiaxun Yang
Two kinds of LBT feature detection are added here, one is VCPU
feature, the other is VM feature. VCPU feature dection can only
work with VCPU thread itself, and requires VCPU thread is created
already. So LBT feature detection for VM is added also, it can
be done even if VM is not created, and also can be done by any
thread besides VCPU threads.

Loongson Binary Translation (LBT) feature is defined in register
cpucfg2. Here LBT capability detection for VCPU is added.

Here ioctl command KVM_HAS_DEVICE_ATTR is added for VM, and macro
KVM_LOONGARCH_VM_FEAT_CTRL is added to check supported feature. And
three sub-features relative with LBT are added as following:
KVM_LOONGARCH_VM_FEAT_X86BT
KVM_LOONGARCH_VM_FEAT_ARMBT
KVM_LOONGARCH_VM_FEAT_MIPSBT

Also two extra sub-features is added for VM feature dectection,
previously features LSX/LASX are detected from vcpu context, now
it can be detected from VM context.
KVM_LOONGARCH_VM_FEAT_LSX
KVM_LOONGARCH_VM_FEAT_LASX

Signed-off-by: Bibo Mao <mao...@loongson.cn>
---
arch/loongarch/include/uapi/asm/kvm.h | 8 +++++
arch/loongarch/kvm/vcpu.c | 6 ++++
arch/loongarch/kvm/vm.c | 52 ++++++++++++++++++++++++++-
3 files changed, 65 insertions(+), 1 deletion(-)

diff --git a/arch/loongarch/include/uapi/asm/kvm.h b/arch/loongarch/include/uapi/asm/kvm.h
index ddc5cab0ffd0..49bafac8b22d 100644
--- a/arch/loongarch/include/uapi/asm/kvm.h
+++ b/arch/loongarch/include/uapi/asm/kvm.h
@@ -82,6 +82,14 @@ struct kvm_fpu {
#define KVM_IOC_CSRID(REG) LOONGARCH_REG_64(KVM_REG_LOONGARCH_CSR, REG)
#define KVM_IOC_CPUCFG(REG) LOONGARCH_REG_64(KVM_REG_LOONGARCH_CPUCFG, REG)

+/* Device Control API on vm fd */
+#define KVM_LOONGARCH_VM_FEAT_CTRL 0
+#define KVM_LOONGARCH_VM_FEAT_LSX 0
+#define KVM_LOONGARCH_VM_FEAT_LASX 1
+#define KVM_LOONGARCH_VM_FEAT_X86BT 2
+#define KVM_LOONGARCH_VM_FEAT_ARMBT 3
+#define KVM_LOONGARCH_VM_FEAT_MIPSBT 4
+
/* Device Control API on vcpu fd */
#define KVM_LOONGARCH_VCPU_CPUCFG 0
#define KVM_LOONGARCH_VCPU_PVTIME_CTRL 1
diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c
index 36db2b257a95..b5324885a81a 100644
--- a/arch/loongarch/kvm/vcpu.c
+++ b/arch/loongarch/kvm/vcpu.c
+ return -ENXIO;
+ }
+}
+
+static int kvm_vm_has_attr(struct kvm *kvm, struct kvm_device_attr *attr)
+{
+ switch (attr->group) {
+ case KVM_LOONGARCH_VM_FEAT_CTRL:
+ return kvm_vm_feature_has_attr(kvm, attr);
+ default:
+ return -ENXIO;
+ }
+}
Reply all
Reply to author
Forward
0 new messages