]> www.infradead.org Git - nvme.git/commitdiff
KVM: arm64: nv: Add handling of outer-shareable TLBI operations
authorMarc Zyngier <maz@kernel.org>
Fri, 14 Jun 2024 14:45:50 +0000 (15:45 +0100)
committerOliver Upton <oliver.upton@linux.dev>
Wed, 19 Jun 2024 08:14:38 +0000 (08:14 +0000)
Our handling of outer-shareable TLBIs is pretty basic: we just
map them to the existing inner-shareable ones, because we really
don't have anything else.

The only significant change is that we can now advertise FEAT_TLBIOS
support if the host supports it.

Signed-off-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20240614144552.2773592-15-maz@kernel.org
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
arch/arm64/kvm/hyp/vhe/tlb.c
arch/arm64/kvm/nested.c
arch/arm64/kvm/sys_regs.c

index 75aa3646580584d4f74ea7086004459c83bf90d1..85db6ffd9d9d80c41d22844d6f298ee2e128f1b2 100644 (file)
@@ -226,6 +226,7 @@ void __kvm_flush_vm_context(void)
  *
  * - a TLBI targeting EL2 S1 is remapped to EL1 S1
  * - a non-shareable TLBI is upgraded to being inner-shareable
+ * - an outer-shareable TLBI is also mapped to inner-shareable
  */
 int __kvm_tlbi_s1e2(struct kvm_s2_mmu *mmu, u64 va, u64 sys_encoding)
 {
@@ -245,32 +246,41 @@ int __kvm_tlbi_s1e2(struct kvm_s2_mmu *mmu, u64 va, u64 sys_encoding)
        switch (sys_encoding) {
        case OP_TLBI_ALLE2:
        case OP_TLBI_ALLE2IS:
+       case OP_TLBI_ALLE2OS:
        case OP_TLBI_VMALLE1:
        case OP_TLBI_VMALLE1IS:
+       case OP_TLBI_VMALLE1OS:
                __tlbi(vmalle1is);
                break;
        case OP_TLBI_VAE2:
        case OP_TLBI_VAE2IS:
+       case OP_TLBI_VAE2OS:
        case OP_TLBI_VAE1:
        case OP_TLBI_VAE1IS:
+       case OP_TLBI_VAE1OS:
                __tlbi(vae1is, va);
                break;
        case OP_TLBI_VALE2:
        case OP_TLBI_VALE2IS:
+       case OP_TLBI_VALE2OS:
        case OP_TLBI_VALE1:
        case OP_TLBI_VALE1IS:
+       case OP_TLBI_VALE1OS:
                __tlbi(vale1is, va);
                break;
        case OP_TLBI_ASIDE1:
        case OP_TLBI_ASIDE1IS:
+       case OP_TLBI_ASIDE1OS:
                __tlbi(aside1is, va);
                break;
        case OP_TLBI_VAAE1:
        case OP_TLBI_VAAE1IS:
+       case OP_TLBI_VAAE1OS:
                __tlbi(vaae1is, va);
                break;
        case OP_TLBI_VAALE1:
        case OP_TLBI_VAALE1IS:
+       case OP_TLBI_VAALE1OS:
                __tlbi(vaale1is, va);
                break;
        default:
index 1860ed4a4c003f84bd39de3bf039157ef21c2a0e..63bc8d5022fea48bd945fde2bbcf3a6dff7eb934 100644 (file)
@@ -805,9 +805,12 @@ static u64 limit_nv_id_reg(u32 id, u64 val)
 
        switch (id) {
        case SYS_ID_AA64ISAR0_EL1:
-               /* Support everything but TME, O.S. and Range TLBIs */
+               /* Support everything but TME and Range TLBIs */
+               tmp = FIELD_GET(NV_FTR(ISAR0, TLB), val);
+               tmp = min(tmp, ID_AA64ISAR0_EL1_TLB_OS);
                val &= ~(NV_FTR(ISAR0, TLB)             |
                         NV_FTR(ISAR0, TME));
+               val |= FIELD_PREP(NV_FTR(ISAR0, TLB), tmp);
                break;
 
        case SYS_ID_AA64ISAR1_EL1:
index 5bed362f80d361bc09681fd0719d1d436938cb36..7dec7da167f6cfe0637e2e94afc8cceb43d9b009 100644 (file)
@@ -2959,6 +2959,13 @@ static struct sys_reg_desc sys_insn_descs[] = {
        { SYS_DESC(SYS_DC_CIGSW), access_dcgsw },
        { SYS_DESC(SYS_DC_CIGDSW), access_dcgsw },
 
+       SYS_INSN(TLBI_VMALLE1OS, handle_tlbi_el1),
+       SYS_INSN(TLBI_VAE1OS, handle_tlbi_el1),
+       SYS_INSN(TLBI_ASIDE1OS, handle_tlbi_el1),
+       SYS_INSN(TLBI_VAAE1OS, handle_tlbi_el1),
+       SYS_INSN(TLBI_VALE1OS, handle_tlbi_el1),
+       SYS_INSN(TLBI_VAALE1OS, handle_tlbi_el1),
+
        SYS_INSN(TLBI_VMALLE1IS, handle_tlbi_el1),
        SYS_INSN(TLBI_VAE1IS, handle_tlbi_el1),
        SYS_INSN(TLBI_ASIDE1IS, handle_tlbi_el1),
@@ -2975,9 +2982,17 @@ static struct sys_reg_desc sys_insn_descs[] = {
        SYS_INSN(TLBI_IPAS2E1IS, handle_ipas2e1is),
        SYS_INSN(TLBI_IPAS2LE1IS, handle_ipas2e1is),
 
+       SYS_INSN(TLBI_ALLE2OS, trap_undef),
+       SYS_INSN(TLBI_VAE2OS, trap_undef),
+       SYS_INSN(TLBI_ALLE1OS, handle_alle1is),
+       SYS_INSN(TLBI_VALE2OS, trap_undef),
+       SYS_INSN(TLBI_VMALLS12E1OS, handle_vmalls12e1is),
+
        SYS_INSN(TLBI_ALLE1IS, handle_alle1is),
        SYS_INSN(TLBI_VMALLS12E1IS, handle_vmalls12e1is),
+       SYS_INSN(TLBI_IPAS2E1OS, handle_ipas2e1is),
        SYS_INSN(TLBI_IPAS2E1, handle_ipas2e1is),
+       SYS_INSN(TLBI_IPAS2LE1OS, handle_ipas2e1is),
        SYS_INSN(TLBI_IPAS2LE1, handle_ipas2e1is),
        SYS_INSN(TLBI_ALLE1, handle_alle1is),
        SYS_INSN(TLBI_VMALLS12E1, handle_vmalls12e1is),