diff mbox series

[v2] LoongArch: KVM: Implement feature passing from user space

Message ID 20240611123655.4169939-1-maobibo@loongson.cn (mailing list archive)
State New, archived
Headers show
Series [v2] LoongArch: KVM: Implement feature passing from user space | expand

Commit Message

maobibo June 11, 2024, 12:36 p.m. UTC
Currently features defined in cpucfg CPUCFG_KVM_FEATURE come from
kvm kernel mode only. However KVM is not aware of user-space VMM
features which makes it hard to employ optimizations. Here interface
is added to update register CPUCFG_KVM_FEATURE from user space,
only bit 24 - 31 is valid, so that VM can detect features implemented
in user-space VMM.

A new feature bit KVM_LOONGARCH_VCPU_FEAT_VIRT_EXTIOI is added which
can be set from user space. This feature indicates that the virt EXTIOI
can route interrupts to 256 vCPUs, rather than 4 vCPUs like with real HW.

Signed-off-by: Bibo Mao <maobibo@loongson.cn>
---
v1 ... v2:
  1. Update changelog suggested by WangXuerui.
  2. Fix typo issue in function kvm_loongarch_cpucfg_set_attr(), usr_features
should be assigned directly, also suggested by WangXueRui.
---
 arch/loongarch/include/asm/kvm_host.h  |  4 +++
 arch/loongarch/include/asm/loongarch.h |  5 ++++
 arch/loongarch/include/uapi/asm/kvm.h  |  2 ++
 arch/loongarch/kvm/exit.c              |  1 +
 arch/loongarch/kvm/vcpu.c              | 36 +++++++++++++++++++++++---
 5 files changed, 44 insertions(+), 4 deletions(-)


base-commit: 2df0193e62cf887f373995fb8a91068562784adc

Comments

maobibo July 9, 2024, 9:22 a.m. UTC | #1
Gently ping.

On 2024/6/11 下午8:36, Bibo Mao wrote:
> Currently features defined in cpucfg CPUCFG_KVM_FEATURE come from
> kvm kernel mode only. However KVM is not aware of user-space VMM
> features which makes it hard to employ optimizations. Here interface
> is added to update register CPUCFG_KVM_FEATURE from user space,
> only bit 24 - 31 is valid, so that VM can detect features implemented
> in user-space VMM.
> 
> A new feature bit KVM_LOONGARCH_VCPU_FEAT_VIRT_EXTIOI is added which
> can be set from user space. This feature indicates that the virt EXTIOI
> can route interrupts to 256 vCPUs, rather than 4 vCPUs like with real HW.
> 
> Signed-off-by: Bibo Mao <maobibo@loongson.cn>
> ---
> v1 ... v2:
>    1. Update changelog suggested by WangXuerui.
>    2. Fix typo issue in function kvm_loongarch_cpucfg_set_attr(), usr_features
> should be assigned directly, also suggested by WangXueRui.
> ---
>   arch/loongarch/include/asm/kvm_host.h  |  4 +++
>   arch/loongarch/include/asm/loongarch.h |  5 ++++
>   arch/loongarch/include/uapi/asm/kvm.h  |  2 ++
>   arch/loongarch/kvm/exit.c              |  1 +
>   arch/loongarch/kvm/vcpu.c              | 36 +++++++++++++++++++++++---
>   5 files changed, 44 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/loongarch/include/asm/kvm_host.h b/arch/loongarch/include/asm/kvm_host.h
> index 88023ab59486..8fa50d757247 100644
> --- a/arch/loongarch/include/asm/kvm_host.h
> +++ b/arch/loongarch/include/asm/kvm_host.h
> @@ -135,6 +135,9 @@ enum emulation_result {
>   #define KVM_LARCH_HWCSR_USABLE	(0x1 << 4)
>   #define KVM_LARCH_LBT		(0x1 << 5)
>   
> +#define KVM_LOONGARCH_USR_FEAT_MASK			\
> +	BIT(KVM_LOONGARCH_VCPU_FEAT_VIRT_EXTIOI)
> +
>   struct kvm_vcpu_arch {
>   	/*
>   	 * Switch pointer-to-function type to unsigned long
> @@ -210,6 +213,7 @@ struct kvm_vcpu_arch {
>   		u64 last_steal;
>   		struct gfn_to_hva_cache cache;
>   	} st;
> +	unsigned int usr_features;
>   };
>   
>   static inline unsigned long readl_sw_gcsr(struct loongarch_csrs *csr, int reg)
> diff --git a/arch/loongarch/include/asm/loongarch.h b/arch/loongarch/include/asm/loongarch.h
> index 7a4633ef284b..4d9837512c19 100644
> --- a/arch/loongarch/include/asm/loongarch.h
> +++ b/arch/loongarch/include/asm/loongarch.h
> @@ -167,9 +167,14 @@
>   
>   #define CPUCFG_KVM_SIG			(CPUCFG_KVM_BASE + 0)
>   #define  KVM_SIGNATURE			"KVM\0"
> +/*
> + * BIT 24 - 31 is features configurable by user space vmm
> + */
>   #define CPUCFG_KVM_FEATURE		(CPUCFG_KVM_BASE + 4)
>   #define  KVM_FEATURE_IPI		BIT(1)
>   #define  KVM_FEATURE_STEAL_TIME		BIT(2)
> +/* With VIRT_EXTIOI feature, interrupt can route to 256 VCPUs */
> +#define  KVM_FEATURE_VIRT_EXTIOI	BIT(24)
>   
>   #ifndef __ASSEMBLY__
>   
> diff --git a/arch/loongarch/include/uapi/asm/kvm.h b/arch/loongarch/include/uapi/asm/kvm.h
> index ed12e509815c..dd141259de48 100644
> --- a/arch/loongarch/include/uapi/asm/kvm.h
> +++ b/arch/loongarch/include/uapi/asm/kvm.h
> @@ -99,6 +99,8 @@ struct kvm_fpu {
>   
>   /* Device Control API on vcpu fd */
>   #define KVM_LOONGARCH_VCPU_CPUCFG	0
> +/* For CPUCFG_KVM_FEATURE register */
> +#define  KVM_LOONGARCH_VCPU_FEAT_VIRT_EXTIOI	24
>   #define KVM_LOONGARCH_VCPU_PVTIME_CTRL	1
>   #define  KVM_LOONGARCH_VCPU_PVTIME_GPA	0
>   
> diff --git a/arch/loongarch/kvm/exit.c b/arch/loongarch/kvm/exit.c
> index e1bd81d27fd8..ab2dcc76784a 100644
> --- a/arch/loongarch/kvm/exit.c
> +++ b/arch/loongarch/kvm/exit.c
> @@ -53,6 +53,7 @@ static int kvm_emu_cpucfg(struct kvm_vcpu *vcpu, larch_inst inst)
>   		ret = KVM_FEATURE_IPI;
>   		if (sched_info_on())
>   			ret |= KVM_FEATURE_STEAL_TIME;
> +		ret |= vcpu->arch.usr_features;
>   		vcpu->arch.gprs[rd] = ret;
>   		break;
>   	default:
> diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c
> index 3783151fde32..4a06a9e96e4e 100644
> --- a/arch/loongarch/kvm/vcpu.c
> +++ b/arch/loongarch/kvm/vcpu.c
> @@ -832,6 +832,8 @@ static int kvm_loongarch_cpucfg_has_attr(struct kvm_vcpu *vcpu,
>   	switch (attr->attr) {
>   	case 2:
>   		return 0;
> +	case CPUCFG_KVM_FEATURE:
> +		return 0;
>   	default:
>   		return -ENXIO;
>   	}
> @@ -865,9 +867,18 @@ static int kvm_loongarch_get_cpucfg_attr(struct kvm_vcpu *vcpu,
>   	uint64_t val;
>   	uint64_t __user *uaddr = (uint64_t __user *)attr->addr;
>   
> -	ret = _kvm_get_cpucfg_mask(attr->attr, &val);
> -	if (ret)
> -		return ret;
> +	switch (attr->attr) {
> +	case 0 ... (KVM_MAX_CPUCFG_REGS - 1):
> +		ret = _kvm_get_cpucfg_mask(attr->attr, &val);
> +		if (ret)
> +			return ret;
> +		break;
> +	case CPUCFG_KVM_FEATURE:
> +		val = vcpu->arch.usr_features & KVM_LOONGARCH_USR_FEAT_MASK;
> +		break;
> +	default:
> +		return -ENXIO;
> +	}
>   
>   	put_user(val, uaddr);
>   
> @@ -896,7 +907,24 @@ static int kvm_loongarch_vcpu_get_attr(struct kvm_vcpu *vcpu,
>   static int kvm_loongarch_cpucfg_set_attr(struct kvm_vcpu *vcpu,
>   					 struct kvm_device_attr *attr)
>   {
> -	return -ENXIO;
> +	u64 __user *user = (u64 __user *)attr->addr;
> +	u64 val, valid_flags;
> +
> +	switch (attr->attr) {
> +	case CPUCFG_KVM_FEATURE:
> +		if (get_user(val, user))
> +			return -EFAULT;
> +
> +		valid_flags = KVM_LOONGARCH_USR_FEAT_MASK;
> +		if (val & ~valid_flags)
> +			return -EINVAL;
> +
> +		vcpu->arch.usr_features = val;
> +		return 0;
> +
> +	default:
> +		return -ENXIO;
> +	}
>   }
>   
>   static int kvm_loongarch_vcpu_set_attr(struct kvm_vcpu *vcpu,
> 
> base-commit: 2df0193e62cf887f373995fb8a91068562784adc
>
diff mbox series

Patch

diff --git a/arch/loongarch/include/asm/kvm_host.h b/arch/loongarch/include/asm/kvm_host.h
index 88023ab59486..8fa50d757247 100644
--- a/arch/loongarch/include/asm/kvm_host.h
+++ b/arch/loongarch/include/asm/kvm_host.h
@@ -135,6 +135,9 @@  enum emulation_result {
 #define KVM_LARCH_HWCSR_USABLE	(0x1 << 4)
 #define KVM_LARCH_LBT		(0x1 << 5)
 
+#define KVM_LOONGARCH_USR_FEAT_MASK			\
+	BIT(KVM_LOONGARCH_VCPU_FEAT_VIRT_EXTIOI)
+
 struct kvm_vcpu_arch {
 	/*
 	 * Switch pointer-to-function type to unsigned long
@@ -210,6 +213,7 @@  struct kvm_vcpu_arch {
 		u64 last_steal;
 		struct gfn_to_hva_cache cache;
 	} st;
+	unsigned int usr_features;
 };
 
 static inline unsigned long readl_sw_gcsr(struct loongarch_csrs *csr, int reg)
diff --git a/arch/loongarch/include/asm/loongarch.h b/arch/loongarch/include/asm/loongarch.h
index 7a4633ef284b..4d9837512c19 100644
--- a/arch/loongarch/include/asm/loongarch.h
+++ b/arch/loongarch/include/asm/loongarch.h
@@ -167,9 +167,14 @@ 
 
 #define CPUCFG_KVM_SIG			(CPUCFG_KVM_BASE + 0)
 #define  KVM_SIGNATURE			"KVM\0"
+/*
+ * BIT 24 - 31 is features configurable by user space vmm
+ */
 #define CPUCFG_KVM_FEATURE		(CPUCFG_KVM_BASE + 4)
 #define  KVM_FEATURE_IPI		BIT(1)
 #define  KVM_FEATURE_STEAL_TIME		BIT(2)
+/* With VIRT_EXTIOI feature, interrupt can route to 256 VCPUs */
+#define  KVM_FEATURE_VIRT_EXTIOI	BIT(24)
 
 #ifndef __ASSEMBLY__
 
diff --git a/arch/loongarch/include/uapi/asm/kvm.h b/arch/loongarch/include/uapi/asm/kvm.h
index ed12e509815c..dd141259de48 100644
--- a/arch/loongarch/include/uapi/asm/kvm.h
+++ b/arch/loongarch/include/uapi/asm/kvm.h
@@ -99,6 +99,8 @@  struct kvm_fpu {
 
 /* Device Control API on vcpu fd */
 #define KVM_LOONGARCH_VCPU_CPUCFG	0
+/* For CPUCFG_KVM_FEATURE register */
+#define  KVM_LOONGARCH_VCPU_FEAT_VIRT_EXTIOI	24
 #define KVM_LOONGARCH_VCPU_PVTIME_CTRL	1
 #define  KVM_LOONGARCH_VCPU_PVTIME_GPA	0
 
diff --git a/arch/loongarch/kvm/exit.c b/arch/loongarch/kvm/exit.c
index e1bd81d27fd8..ab2dcc76784a 100644
--- a/arch/loongarch/kvm/exit.c
+++ b/arch/loongarch/kvm/exit.c
@@ -53,6 +53,7 @@  static int kvm_emu_cpucfg(struct kvm_vcpu *vcpu, larch_inst inst)
 		ret = KVM_FEATURE_IPI;
 		if (sched_info_on())
 			ret |= KVM_FEATURE_STEAL_TIME;
+		ret |= vcpu->arch.usr_features;
 		vcpu->arch.gprs[rd] = ret;
 		break;
 	default:
diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c
index 3783151fde32..4a06a9e96e4e 100644
--- a/arch/loongarch/kvm/vcpu.c
+++ b/arch/loongarch/kvm/vcpu.c
@@ -832,6 +832,8 @@  static int kvm_loongarch_cpucfg_has_attr(struct kvm_vcpu *vcpu,
 	switch (attr->attr) {
 	case 2:
 		return 0;
+	case CPUCFG_KVM_FEATURE:
+		return 0;
 	default:
 		return -ENXIO;
 	}
@@ -865,9 +867,18 @@  static int kvm_loongarch_get_cpucfg_attr(struct kvm_vcpu *vcpu,
 	uint64_t val;
 	uint64_t __user *uaddr = (uint64_t __user *)attr->addr;
 
-	ret = _kvm_get_cpucfg_mask(attr->attr, &val);
-	if (ret)
-		return ret;
+	switch (attr->attr) {
+	case 0 ... (KVM_MAX_CPUCFG_REGS - 1):
+		ret = _kvm_get_cpucfg_mask(attr->attr, &val);
+		if (ret)
+			return ret;
+		break;
+	case CPUCFG_KVM_FEATURE:
+		val = vcpu->arch.usr_features & KVM_LOONGARCH_USR_FEAT_MASK;
+		break;
+	default:
+		return -ENXIO;
+	}
 
 	put_user(val, uaddr);
 
@@ -896,7 +907,24 @@  static int kvm_loongarch_vcpu_get_attr(struct kvm_vcpu *vcpu,
 static int kvm_loongarch_cpucfg_set_attr(struct kvm_vcpu *vcpu,
 					 struct kvm_device_attr *attr)
 {
-	return -ENXIO;
+	u64 __user *user = (u64 __user *)attr->addr;
+	u64 val, valid_flags;
+
+	switch (attr->attr) {
+	case CPUCFG_KVM_FEATURE:
+		if (get_user(val, user))
+			return -EFAULT;
+
+		valid_flags = KVM_LOONGARCH_USR_FEAT_MASK;
+		if (val & ~valid_flags)
+			return -EINVAL;
+
+		vcpu->arch.usr_features = val;
+		return 0;
+
+	default:
+		return -ENXIO;
+	}
 }
 
 static int kvm_loongarch_vcpu_set_attr(struct kvm_vcpu *vcpu,