[PATCH] KVM: LoongArch: selftests: Enable HW PTW by auto detection method

Bibo Mao posted 1 patch 1 day, 12 hours ago
.../selftests/kvm/include/loongarch/processor.h  |  3 +++
.../selftests/kvm/lib/loongarch/processor.c      | 16 ++++++++++++++--
2 files changed, 17 insertions(+), 2 deletions(-)
[PATCH] KVM: LoongArch: selftests: Enable HW PTW by auto detection method
Posted by Bibo Mao 1 day, 12 hours ago
Add HW PTW feature when VM is created. This feature is detected firstly,
enable it if it is available on host machine. With HW PTW feature enabled,
refill exception will not happen and it is not necessary to set refill
exception entry.

Signed-off-by: Bibo Mao <maobibo@loongson.cn>
---
 .../selftests/kvm/include/loongarch/processor.h  |  3 +++
 .../selftests/kvm/lib/loongarch/processor.c      | 16 ++++++++++++++--
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/tools/testing/selftests/kvm/include/loongarch/processor.h b/tools/testing/selftests/kvm/include/loongarch/processor.h
index 0e59daa8024e..8d9fabdc89e3 100644
--- a/tools/testing/selftests/kvm/include/loongarch/processor.h
+++ b/tools/testing/selftests/kvm/include/loongarch/processor.h
@@ -79,6 +79,7 @@
 #define  CPUCFG2_LASX			BIT(7)
 #define  CPUCFG2_LLFTP			BIT(14)
 #define  CPUCFG2_LLFTPREV		GENMASK(17, 15)
+#define  CPUCFG2_PTW			BIT(24)
 
 /* LoongArch Basic CSR registers */
 #define LOONGARCH_CSR_CRMD		0x0 /* Current mode info */
@@ -128,6 +129,8 @@
 #define LOONGARCH_CSR_PGD		0x1b
 #define LOONGARCH_CSR_PWCTL0		0x1c
 #define LOONGARCH_CSR_PWCTL1		0x1d
+#define  CSR_PWCTL1_PTW_SHIFT		24
+#define  CSR_PWCTL1_PTW			BIT_ULL(CSR_PWCTL1_PTW_SHIFT)
 #define LOONGARCH_CSR_STLBPGSIZE	0x1e
 #define LOONGARCH_CSR_CPUID		0x20
 #define LOONGARCH_CSR_KS0		0x30
diff --git a/tools/testing/selftests/kvm/lib/loongarch/processor.c b/tools/testing/selftests/kvm/lib/loongarch/processor.c
index 47bbde3e205a..35e35c62759f 100644
--- a/tools/testing/selftests/kvm/lib/loongarch/processor.c
+++ b/tools/testing/selftests/kvm/lib/loongarch/processor.c
@@ -282,6 +282,7 @@ void loongarch_vcpu_setup(struct kvm_vcpu *vcpu)
 	unsigned int cfg;
 	unsigned long val;
 	struct kvm_vm *vm = vcpu->vm;
+	bool has_ptw = false;
 
 	switch (vm->mode) {
 	case VM_MODE_P36V47_16K:
@@ -300,6 +301,12 @@ void loongarch_vcpu_setup(struct kvm_vcpu *vcpu)
 	ret = __kvm_has_device_attr(vm->fd, KVM_LOONGARCH_VM_FEAT_CTRL, KVM_LOONGARCH_VM_FEAT_LASX);
 	if (!ret)
 		cfg |= CPUCFG2_LASX;
+	ret = __kvm_has_device_attr(vm->fd, KVM_LOONGARCH_VM_FEAT_CTRL, KVM_LOONGARCH_VM_FEAT_PTW);
+	if (!ret) {
+		cfg |= CPUCFG2_PTW;
+		has_ptw = true;
+	}
+
 	loongarch_set_cpucfg(vcpu, LOONGARCH_CPUCFG2, cfg);
 	cfg = read_cpucfg(LOONGARCH_CPUCFG6);
 	loongarch_set_cpucfg(vcpu, LOONGARCH_CPUCFG6, cfg);
@@ -338,6 +345,9 @@ void loongarch_vcpu_setup(struct kvm_vcpu *vcpu)
 
 	/* PGD page shift and width */
 	val = (vm->page_shift + width * (vm->mmu.pgtable_levels - 1)) | width << 6;
+	if (has_ptw)
+		val |= CSR_PWCTL1_PTW;
+
 	loongarch_set_csr(vcpu, LOONGARCH_CSR_PWCTL1, val);
 	loongarch_set_csr(vcpu, LOONGARCH_CSR_PGDL, vm->mmu.pgd);
 
@@ -345,8 +355,10 @@ void loongarch_vcpu_setup(struct kvm_vcpu *vcpu)
 	 * Refill exception runs on real mode
 	 * Entry address should be physical address
 	 */
-	val = addr_gva2gpa(vm, (unsigned long)handle_tlb_refill);
-	loongarch_set_csr(vcpu, LOONGARCH_CSR_TLBRENTRY, val);
+	if (!has_ptw) {
+		val = addr_gva2gpa(vm, (unsigned long)handle_tlb_refill);
+		loongarch_set_csr(vcpu, LOONGARCH_CSR_TLBRENTRY, val);
+	}
 
 	/*
 	 * General exception runs on page-enabled mode

base-commit: 93f51579e7df248780214094418f205253383cc5
-- 
2.39.3
Re: [PATCH] KVM: LoongArch: selftests: Enable HW PTW by auto detection method
Posted by Huacai Chen 1 day, 9 hours ago
Hi, Bibo,

On Wed, Sep 23, 2026 at 9:31 AM Bibo Mao <maobibo@loongson.cn> wrote:
>
> Add HW PTW feature when VM is created. This feature is detected firstly,
> enable it if it is available on host machine. With HW PTW feature enabled,
> refill exception will not happen and it is not necessary to set refill
> exception entry.
>
> Signed-off-by: Bibo Mao <maobibo@loongson.cn>
> ---
>  .../selftests/kvm/include/loongarch/processor.h  |  3 +++
>  .../selftests/kvm/lib/loongarch/processor.c      | 16 ++++++++++++++--
>  2 files changed, 17 insertions(+), 2 deletions(-)
>
> diff --git a/tools/testing/selftests/kvm/include/loongarch/processor.h b/tools/testing/selftests/kvm/include/loongarch/processor.h
> index 0e59daa8024e..8d9fabdc89e3 100644
> --- a/tools/testing/selftests/kvm/include/loongarch/processor.h
> +++ b/tools/testing/selftests/kvm/include/loongarch/processor.h
> @@ -79,6 +79,7 @@
>  #define  CPUCFG2_LASX                  BIT(7)
>  #define  CPUCFG2_LLFTP                 BIT(14)
>  #define  CPUCFG2_LLFTPREV              GENMASK(17, 15)
> +#define  CPUCFG2_PTW                   BIT(24)
>
>  /* LoongArch Basic CSR registers */
>  #define LOONGARCH_CSR_CRMD             0x0 /* Current mode info */
> @@ -128,6 +129,8 @@
>  #define LOONGARCH_CSR_PGD              0x1b
>  #define LOONGARCH_CSR_PWCTL0           0x1c
>  #define LOONGARCH_CSR_PWCTL1           0x1d
> +#define  CSR_PWCTL1_PTW_SHIFT          24
> +#define  CSR_PWCTL1_PTW                        BIT_ULL(CSR_PWCTL1_PTW_SHIFT)
>  #define LOONGARCH_CSR_STLBPGSIZE       0x1e
>  #define LOONGARCH_CSR_CPUID            0x20
>  #define LOONGARCH_CSR_KS0              0x30
> diff --git a/tools/testing/selftests/kvm/lib/loongarch/processor.c b/tools/testing/selftests/kvm/lib/loongarch/processor.c
> index 47bbde3e205a..35e35c62759f 100644
> --- a/tools/testing/selftests/kvm/lib/loongarch/processor.c
> +++ b/tools/testing/selftests/kvm/lib/loongarch/processor.c
> @@ -282,6 +282,7 @@ void loongarch_vcpu_setup(struct kvm_vcpu *vcpu)
>         unsigned int cfg;
>         unsigned long val;
>         struct kvm_vm *vm = vcpu->vm;
> +       bool has_ptw = false;
>
>         switch (vm->mode) {
>         case VM_MODE_P36V47_16K:
> @@ -300,6 +301,12 @@ void loongarch_vcpu_setup(struct kvm_vcpu *vcpu)
>         ret = __kvm_has_device_attr(vm->fd, KVM_LOONGARCH_VM_FEAT_CTRL, KVM_LOONGARCH_VM_FEAT_LASX);
>         if (!ret)
>                 cfg |= CPUCFG2_LASX;
> +       ret = __kvm_has_device_attr(vm->fd, KVM_LOONGARCH_VM_FEAT_CTRL, KVM_LOONGARCH_VM_FEAT_PTW);
> +       if (!ret) {
> +               cfg |= CPUCFG2_PTW;
> +               has_ptw = true;
> +       }
> +
>         loongarch_set_cpucfg(vcpu, LOONGARCH_CPUCFG2, cfg);
>         cfg = read_cpucfg(LOONGARCH_CPUCFG6);
>         loongarch_set_cpucfg(vcpu, LOONGARCH_CPUCFG6, cfg);
> @@ -338,6 +345,9 @@ void loongarch_vcpu_setup(struct kvm_vcpu *vcpu)
>
>         /* PGD page shift and width */
>         val = (vm->page_shift + width * (vm->mmu.pgtable_levels - 1)) | width << 6;
> +       if (has_ptw)
> +               val |= CSR_PWCTL1_PTW;
> +
>         loongarch_set_csr(vcpu, LOONGARCH_CSR_PWCTL1, val);
>         loongarch_set_csr(vcpu, LOONGARCH_CSR_PGDL, vm->mmu.pgd);
>
> @@ -345,8 +355,10 @@ void loongarch_vcpu_setup(struct kvm_vcpu *vcpu)
>          * Refill exception runs on real mode
>          * Entry address should be physical address
>          */
> -       val = addr_gva2gpa(vm, (unsigned long)handle_tlb_refill);
> -       loongarch_set_csr(vcpu, LOONGARCH_CSR_TLBRENTRY, val);
> +       if (!has_ptw) {
Why not just check CPUCFG2_PTW in cfg? In this way we can drop has_ptw.

Huacai

> +               val = addr_gva2gpa(vm, (unsigned long)handle_tlb_refill);
> +               loongarch_set_csr(vcpu, LOONGARCH_CSR_TLBRENTRY, val);
> +       }
>
>         /*
>          * General exception runs on page-enabled mode
>
> base-commit: 93f51579e7df248780214094418f205253383cc5
> --
> 2.39.3
>
Re: [PATCH] KVM: LoongArch: selftests: Enable HW PTW by auto detection method
Posted by Bibo Mao 1 day, 6 hours ago

On 2026/9/23 下午12:25, Huacai Chen wrote:
> Hi, Bibo,
> 
> On Wed, Sep 23, 2026 at 9:31 AM Bibo Mao <maobibo@loongson.cn> wrote:
>>
>> Add HW PTW feature when VM is created. This feature is detected firstly,
>> enable it if it is available on host machine. With HW PTW feature enabled,
>> refill exception will not happen and it is not necessary to set refill
>> exception entry.
>>
>> Signed-off-by: Bibo Mao <maobibo@loongson.cn>
>> ---
>>   .../selftests/kvm/include/loongarch/processor.h  |  3 +++
>>   .../selftests/kvm/lib/loongarch/processor.c      | 16 ++++++++++++++--
>>   2 files changed, 17 insertions(+), 2 deletions(-)
>>
>> diff --git a/tools/testing/selftests/kvm/include/loongarch/processor.h b/tools/testing/selftests/kvm/include/loongarch/processor.h
>> index 0e59daa8024e..8d9fabdc89e3 100644
>> --- a/tools/testing/selftests/kvm/include/loongarch/processor.h
>> +++ b/tools/testing/selftests/kvm/include/loongarch/processor.h
>> @@ -79,6 +79,7 @@
>>   #define  CPUCFG2_LASX                  BIT(7)
>>   #define  CPUCFG2_LLFTP                 BIT(14)
>>   #define  CPUCFG2_LLFTPREV              GENMASK(17, 15)
>> +#define  CPUCFG2_PTW                   BIT(24)
>>
>>   /* LoongArch Basic CSR registers */
>>   #define LOONGARCH_CSR_CRMD             0x0 /* Current mode info */
>> @@ -128,6 +129,8 @@
>>   #define LOONGARCH_CSR_PGD              0x1b
>>   #define LOONGARCH_CSR_PWCTL0           0x1c
>>   #define LOONGARCH_CSR_PWCTL1           0x1d
>> +#define  CSR_PWCTL1_PTW_SHIFT          24
>> +#define  CSR_PWCTL1_PTW                        BIT_ULL(CSR_PWCTL1_PTW_SHIFT)
>>   #define LOONGARCH_CSR_STLBPGSIZE       0x1e
>>   #define LOONGARCH_CSR_CPUID            0x20
>>   #define LOONGARCH_CSR_KS0              0x30
>> diff --git a/tools/testing/selftests/kvm/lib/loongarch/processor.c b/tools/testing/selftests/kvm/lib/loongarch/processor.c
>> index 47bbde3e205a..35e35c62759f 100644
>> --- a/tools/testing/selftests/kvm/lib/loongarch/processor.c
>> +++ b/tools/testing/selftests/kvm/lib/loongarch/processor.c
>> @@ -282,6 +282,7 @@ void loongarch_vcpu_setup(struct kvm_vcpu *vcpu)
>>          unsigned int cfg;
>>          unsigned long val;
>>          struct kvm_vm *vm = vcpu->vm;
>> +       bool has_ptw = false;
>>
>>          switch (vm->mode) {
>>          case VM_MODE_P36V47_16K:
>> @@ -300,6 +301,12 @@ void loongarch_vcpu_setup(struct kvm_vcpu *vcpu)
>>          ret = __kvm_has_device_attr(vm->fd, KVM_LOONGARCH_VM_FEAT_CTRL, KVM_LOONGARCH_VM_FEAT_LASX);
>>          if (!ret)
>>                  cfg |= CPUCFG2_LASX;
>> +       ret = __kvm_has_device_attr(vm->fd, KVM_LOONGARCH_VM_FEAT_CTRL, KVM_LOONGARCH_VM_FEAT_PTW);
>> +       if (!ret) {
>> +               cfg |= CPUCFG2_PTW;
>> +               has_ptw = true;
>> +       }
>> +
>>          loongarch_set_cpucfg(vcpu, LOONGARCH_CPUCFG2, cfg);
>>          cfg = read_cpucfg(LOONGARCH_CPUCFG6);
>>          loongarch_set_cpucfg(vcpu, LOONGARCH_CPUCFG6, cfg);
>> @@ -338,6 +345,9 @@ void loongarch_vcpu_setup(struct kvm_vcpu *vcpu)
>>
>>          /* PGD page shift and width */
>>          val = (vm->page_shift + width * (vm->mmu.pgtable_levels - 1)) | width << 6;
>> +       if (has_ptw)
>> +               val |= CSR_PWCTL1_PTW;
>> +
>>          loongarch_set_csr(vcpu, LOONGARCH_CSR_PWCTL1, val);
>>          loongarch_set_csr(vcpu, LOONGARCH_CSR_PGDL, vm->mmu.pgd);
>>
>> @@ -345,8 +355,10 @@ void loongarch_vcpu_setup(struct kvm_vcpu *vcpu)
>>           * Refill exception runs on real mode
>>           * Entry address should be physical address
>>           */
>> -       val = addr_gva2gpa(vm, (unsigned long)handle_tlb_refill);
>> -       loongarch_set_csr(vcpu, LOONGARCH_CSR_TLBRENTRY, val);
>> +       if (!has_ptw) {
> Why not just check CPUCFG2_PTW in cfg? In this way we can drop has_ptw.
Variable cfg is overwritten by the later sentence
  cfg = read_cpucfg(LOONGARCH_CPUCFG6);

> 
> Huacai
> 
>> +               val = addr_gva2gpa(vm, (unsigned long)handle_tlb_refill);
>> +               loongarch_set_csr(vcpu, LOONGARCH_CSR_TLBRENTRY, val);
>> +       }
>>
>>          /*
>>           * General exception runs on page-enabled mode
>>
>> base-commit: 93f51579e7df248780214094418f205253383cc5
>> --
>> 2.39.3
>>