|
16 | 16 |
|
17 | 17 | #include "sys_regs.h" |
18 | 18 |
|
19 | | -/* Protection against the sysreg repainting madness... */ |
20 | | -#define NV_FTR(r, f) ID_AA64##r##_EL1_##f |
21 | | - |
22 | 19 | /* |
23 | 20 | * Ratio of live shadow S2 MMU per vcpu. This is a trade-off between |
24 | 21 | * memory usage and potential number of different sets of S2 PTs in |
@@ -807,133 +804,169 @@ void kvm_arch_flush_shadow_all(struct kvm *kvm) |
807 | 804 | * This list should get updated as new features get added to the NV |
808 | 805 | * support, and new extension to the architecture. |
809 | 806 | */ |
| 807 | +static u64 limit_nv_id_reg(struct kvm *kvm, u32 reg, u64 val) |
| 808 | +{ |
| 809 | + switch (reg) { |
| 810 | + case SYS_ID_AA64ISAR0_EL1: |
| 811 | + /* Support everything but TME */ |
| 812 | + val &= ~ID_AA64ISAR0_EL1_TME; |
| 813 | + break; |
| 814 | + |
| 815 | + case SYS_ID_AA64ISAR1_EL1: |
| 816 | + /* Support everything but LS64 and Spec Invalidation */ |
| 817 | + val &= ~(ID_AA64ISAR1_EL1_LS64 | |
| 818 | + ID_AA64ISAR1_EL1_SPECRES); |
| 819 | + break; |
| 820 | + |
| 821 | + case SYS_ID_AA64PFR0_EL1: |
| 822 | + /* No RME, AMU, MPAM, S-EL2, or RAS */ |
| 823 | + val &= ~(ID_AA64PFR0_EL1_RME | |
| 824 | + ID_AA64PFR0_EL1_AMU | |
| 825 | + ID_AA64PFR0_EL1_MPAM | |
| 826 | + ID_AA64PFR0_EL1_SEL2 | |
| 827 | + ID_AA64PFR0_EL1_RAS | |
| 828 | + ID_AA64PFR0_EL1_EL3 | |
| 829 | + ID_AA64PFR0_EL1_EL2 | |
| 830 | + ID_AA64PFR0_EL1_EL1 | |
| 831 | + ID_AA64PFR0_EL1_EL0); |
| 832 | + /* 64bit only at any EL */ |
| 833 | + val |= SYS_FIELD_PREP_ENUM(ID_AA64PFR0_EL1, EL0, IMP); |
| 834 | + val |= SYS_FIELD_PREP_ENUM(ID_AA64PFR0_EL1, EL1, IMP); |
| 835 | + val |= SYS_FIELD_PREP_ENUM(ID_AA64PFR0_EL1, EL2, IMP); |
| 836 | + val |= SYS_FIELD_PREP_ENUM(ID_AA64PFR0_EL1, EL3, IMP); |
| 837 | + break; |
| 838 | + |
| 839 | + case SYS_ID_AA64PFR1_EL1: |
| 840 | + /* Only support BTI, SSBS, CSV2_frac */ |
| 841 | + val &= (ID_AA64PFR1_EL1_BT | |
| 842 | + ID_AA64PFR1_EL1_SSBS | |
| 843 | + ID_AA64PFR1_EL1_CSV2_frac); |
| 844 | + break; |
| 845 | + |
| 846 | + case SYS_ID_AA64MMFR0_EL1: |
| 847 | + /* Hide ECV, ExS, Secure Memory */ |
| 848 | + val &= ~(ID_AA64MMFR0_EL1_ECV | |
| 849 | + ID_AA64MMFR0_EL1_EXS | |
| 850 | + ID_AA64MMFR0_EL1_TGRAN4_2 | |
| 851 | + ID_AA64MMFR0_EL1_TGRAN16_2 | |
| 852 | + ID_AA64MMFR0_EL1_TGRAN64_2 | |
| 853 | + ID_AA64MMFR0_EL1_SNSMEM); |
| 854 | + |
| 855 | + /* Disallow unsupported S2 page sizes */ |
| 856 | + switch (PAGE_SIZE) { |
| 857 | + case SZ_64K: |
| 858 | + val |= SYS_FIELD_PREP_ENUM(ID_AA64MMFR0_EL1, TGRAN16_2, NI); |
| 859 | + fallthrough; |
| 860 | + case SZ_16K: |
| 861 | + val |= SYS_FIELD_PREP_ENUM(ID_AA64MMFR0_EL1, TGRAN4_2, NI); |
| 862 | + fallthrough; |
| 863 | + case SZ_4K: |
| 864 | + /* Support everything */ |
| 865 | + break; |
| 866 | + } |
| 867 | + |
| 868 | + /* |
| 869 | + * Since we can't support a guest S2 page size smaller |
| 870 | + * than the host's own page size (due to KVM only |
| 871 | + * populating its own S2 using the kernel's page |
| 872 | + * size), advertise the limitation using FEAT_GTG. |
| 873 | + */ |
| 874 | + switch (PAGE_SIZE) { |
| 875 | + case SZ_4K: |
| 876 | + val |= SYS_FIELD_PREP_ENUM(ID_AA64MMFR0_EL1, TGRAN4_2, IMP); |
| 877 | + fallthrough; |
| 878 | + case SZ_16K: |
| 879 | + val |= SYS_FIELD_PREP_ENUM(ID_AA64MMFR0_EL1, TGRAN16_2, IMP); |
| 880 | + fallthrough; |
| 881 | + case SZ_64K: |
| 882 | + val |= SYS_FIELD_PREP_ENUM(ID_AA64MMFR0_EL1, TGRAN64_2, IMP); |
| 883 | + break; |
| 884 | + } |
| 885 | + |
| 886 | + /* Cap PARange to 48bits */ |
| 887 | + val = ID_REG_LIMIT_FIELD_ENUM(val, ID_AA64MMFR0_EL1, PARANGE, 48); |
| 888 | + break; |
| 889 | + |
| 890 | + case SYS_ID_AA64MMFR1_EL1: |
| 891 | + val &= (ID_AA64MMFR1_EL1_HCX | |
| 892 | + ID_AA64MMFR1_EL1_PAN | |
| 893 | + ID_AA64MMFR1_EL1_LO | |
| 894 | + ID_AA64MMFR1_EL1_HPDS | |
| 895 | + ID_AA64MMFR1_EL1_VH | |
| 896 | + ID_AA64MMFR1_EL1_VMIDBits); |
| 897 | + break; |
| 898 | + |
| 899 | + case SYS_ID_AA64MMFR2_EL1: |
| 900 | + val &= ~(ID_AA64MMFR2_EL1_BBM | |
| 901 | + ID_AA64MMFR2_EL1_TTL | |
| 902 | + GENMASK_ULL(47, 44) | |
| 903 | + ID_AA64MMFR2_EL1_ST | |
| 904 | + ID_AA64MMFR2_EL1_CCIDX | |
| 905 | + ID_AA64MMFR2_EL1_VARange); |
| 906 | + |
| 907 | + /* Force TTL support */ |
| 908 | + val |= SYS_FIELD_PREP_ENUM(ID_AA64MMFR2_EL1, TTL, IMP); |
| 909 | + break; |
| 910 | + |
| 911 | + case SYS_ID_AA64MMFR4_EL1: |
| 912 | + val = SYS_FIELD_PREP_ENUM(ID_AA64MMFR4_EL1, NV_frac, NV2_ONLY); |
| 913 | + val |= SYS_FIELD_PREP_ENUM(ID_AA64MMFR4_EL1, E2H0, NI_NV1); |
| 914 | + break; |
| 915 | + |
| 916 | + case SYS_ID_AA64DFR0_EL1: |
| 917 | + /* Only limited support for PMU, Debug, BPs, WPs, and HPMN0 */ |
| 918 | + val &= (ID_AA64DFR0_EL1_PMUVer | |
| 919 | + ID_AA64DFR0_EL1_WRPs | |
| 920 | + ID_AA64DFR0_EL1_BRPs | |
| 921 | + ID_AA64DFR0_EL1_DebugVer| |
| 922 | + ID_AA64DFR0_EL1_HPMN0); |
| 923 | + |
| 924 | + /* Cap Debug to ARMv8.1 */ |
| 925 | + val = ID_REG_LIMIT_FIELD_ENUM(val, ID_AA64DFR0_EL1, DebugVer, VHE); |
| 926 | + break; |
| 927 | + } |
| 928 | + |
| 929 | + return val; |
| 930 | +} |
| 931 | + |
810 | 932 | static void limit_nv_id_regs(struct kvm *kvm) |
811 | 933 | { |
812 | | - u64 val, tmp; |
| 934 | + u64 val; |
813 | 935 |
|
814 | | - /* Support everything but TME */ |
815 | 936 | val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64ISAR0_EL1); |
816 | | - val &= ~NV_FTR(ISAR0, TME); |
| 937 | + val = limit_nv_id_reg(kvm, SYS_ID_AA64ISAR0_EL1, val); |
817 | 938 | kvm_set_vm_id_reg(kvm, SYS_ID_AA64ISAR0_EL1, val); |
818 | 939 |
|
819 | | - /* Support everything but Spec Invalidation and LS64 */ |
820 | 940 | val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64ISAR1_EL1); |
821 | | - val &= ~(NV_FTR(ISAR1, LS64) | |
822 | | - NV_FTR(ISAR1, SPECRES)); |
| 941 | + val = limit_nv_id_reg(kvm, SYS_ID_AA64ISAR1_EL1, val); |
823 | 942 | kvm_set_vm_id_reg(kvm, SYS_ID_AA64ISAR1_EL1, val); |
824 | 943 |
|
825 | | - /* No AMU, MPAM, S-EL2, or RAS */ |
826 | 944 | val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64PFR0_EL1); |
827 | | - val &= ~(GENMASK_ULL(55, 52) | |
828 | | - NV_FTR(PFR0, AMU) | |
829 | | - NV_FTR(PFR0, MPAM) | |
830 | | - NV_FTR(PFR0, SEL2) | |
831 | | - NV_FTR(PFR0, RAS) | |
832 | | - NV_FTR(PFR0, EL3) | |
833 | | - NV_FTR(PFR0, EL2) | |
834 | | - NV_FTR(PFR0, EL1) | |
835 | | - NV_FTR(PFR0, EL0)); |
836 | | - /* 64bit only at any EL */ |
837 | | - val |= FIELD_PREP(NV_FTR(PFR0, EL0), 0b0001); |
838 | | - val |= FIELD_PREP(NV_FTR(PFR0, EL1), 0b0001); |
839 | | - val |= FIELD_PREP(NV_FTR(PFR0, EL2), 0b0001); |
840 | | - val |= FIELD_PREP(NV_FTR(PFR0, EL3), 0b0001); |
| 945 | + val = limit_nv_id_reg(kvm, SYS_ID_AA64PFR0_EL1, val); |
841 | 946 | kvm_set_vm_id_reg(kvm, SYS_ID_AA64PFR0_EL1, val); |
842 | 947 |
|
843 | | - /* Only support BTI, SSBS, CSV2_frac */ |
844 | 948 | val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64PFR1_EL1); |
845 | | - val &= (NV_FTR(PFR1, BT) | |
846 | | - NV_FTR(PFR1, SSBS) | |
847 | | - NV_FTR(PFR1, CSV2_frac)); |
| 949 | + val = limit_nv_id_reg(kvm, SYS_ID_AA64PFR1_EL1, val); |
848 | 950 | kvm_set_vm_id_reg(kvm, SYS_ID_AA64PFR1_EL1, val); |
849 | 951 |
|
850 | | - /* Hide ECV, ExS, Secure Memory */ |
851 | 952 | val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64MMFR0_EL1); |
852 | | - val &= ~(NV_FTR(MMFR0, ECV) | |
853 | | - NV_FTR(MMFR0, EXS) | |
854 | | - NV_FTR(MMFR0, TGRAN4_2) | |
855 | | - NV_FTR(MMFR0, TGRAN16_2) | |
856 | | - NV_FTR(MMFR0, TGRAN64_2) | |
857 | | - NV_FTR(MMFR0, SNSMEM)); |
858 | | - |
859 | | - /* Disallow unsupported S2 page sizes */ |
860 | | - switch (PAGE_SIZE) { |
861 | | - case SZ_64K: |
862 | | - val |= FIELD_PREP(NV_FTR(MMFR0, TGRAN16_2), 0b0001); |
863 | | - fallthrough; |
864 | | - case SZ_16K: |
865 | | - val |= FIELD_PREP(NV_FTR(MMFR0, TGRAN4_2), 0b0001); |
866 | | - fallthrough; |
867 | | - case SZ_4K: |
868 | | - /* Support everything */ |
869 | | - break; |
870 | | - } |
871 | | - /* |
872 | | - * Since we can't support a guest S2 page size smaller than |
873 | | - * the host's own page size (due to KVM only populating its |
874 | | - * own S2 using the kernel's page size), advertise the |
875 | | - * limitation using FEAT_GTG. |
876 | | - */ |
877 | | - switch (PAGE_SIZE) { |
878 | | - case SZ_4K: |
879 | | - val |= FIELD_PREP(NV_FTR(MMFR0, TGRAN4_2), 0b0010); |
880 | | - fallthrough; |
881 | | - case SZ_16K: |
882 | | - val |= FIELD_PREP(NV_FTR(MMFR0, TGRAN16_2), 0b0010); |
883 | | - fallthrough; |
884 | | - case SZ_64K: |
885 | | - val |= FIELD_PREP(NV_FTR(MMFR0, TGRAN64_2), 0b0010); |
886 | | - break; |
887 | | - } |
888 | | - /* Cap PARange to 48bits */ |
889 | | - tmp = FIELD_GET(NV_FTR(MMFR0, PARANGE), val); |
890 | | - if (tmp > 0b0101) { |
891 | | - val &= ~NV_FTR(MMFR0, PARANGE); |
892 | | - val |= FIELD_PREP(NV_FTR(MMFR0, PARANGE), 0b0101); |
893 | | - } |
| 953 | + val = limit_nv_id_reg(kvm, SYS_ID_AA64MMFR0_EL1, val); |
894 | 954 | kvm_set_vm_id_reg(kvm, SYS_ID_AA64MMFR0_EL1, val); |
895 | 955 |
|
896 | 956 | val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64MMFR1_EL1); |
897 | | - val &= (NV_FTR(MMFR1, HCX) | |
898 | | - NV_FTR(MMFR1, PAN) | |
899 | | - NV_FTR(MMFR1, LO) | |
900 | | - NV_FTR(MMFR1, HPDS) | |
901 | | - NV_FTR(MMFR1, VH) | |
902 | | - NV_FTR(MMFR1, VMIDBits)); |
| 957 | + val = limit_nv_id_reg(kvm, SYS_ID_AA64MMFR1_EL1, val); |
903 | 958 | kvm_set_vm_id_reg(kvm, SYS_ID_AA64MMFR1_EL1, val); |
904 | 959 |
|
905 | 960 | val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64MMFR2_EL1); |
906 | | - val &= ~(NV_FTR(MMFR2, BBM) | |
907 | | - NV_FTR(MMFR2, TTL) | |
908 | | - GENMASK_ULL(47, 44) | |
909 | | - NV_FTR(MMFR2, ST) | |
910 | | - NV_FTR(MMFR2, CCIDX) | |
911 | | - NV_FTR(MMFR2, VARange)); |
912 | | - |
913 | | - /* Force TTL support */ |
914 | | - val |= FIELD_PREP(NV_FTR(MMFR2, TTL), 0b0001); |
| 961 | + val = limit_nv_id_reg(kvm, SYS_ID_AA64MMFR2_EL1, val); |
915 | 962 | kvm_set_vm_id_reg(kvm, SYS_ID_AA64MMFR2_EL1, val); |
916 | 963 |
|
917 | | - val = 0; |
918 | | - if (!cpus_have_final_cap(ARM64_HAS_HCR_NV1)) |
919 | | - val |= FIELD_PREP(NV_FTR(MMFR4, E2H0), |
920 | | - ID_AA64MMFR4_EL1_E2H0_NI_NV1); |
| 964 | + val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64MMFR4_EL1); |
| 965 | + val = limit_nv_id_reg(kvm, SYS_ID_AA64MMFR4_EL1, val); |
921 | 966 | kvm_set_vm_id_reg(kvm, SYS_ID_AA64MMFR4_EL1, val); |
922 | 967 |
|
923 | | - /* Only limited support for PMU, Debug, BPs, WPs, and HPMN0 */ |
924 | 968 | val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64DFR0_EL1); |
925 | | - val &= (NV_FTR(DFR0, PMUVer) | |
926 | | - NV_FTR(DFR0, WRPs) | |
927 | | - NV_FTR(DFR0, BRPs) | |
928 | | - NV_FTR(DFR0, DebugVer) | |
929 | | - NV_FTR(DFR0, HPMN0)); |
930 | | - |
931 | | - /* Cap Debug to ARMv8.1 */ |
932 | | - tmp = FIELD_GET(NV_FTR(DFR0, DebugVer), val); |
933 | | - if (tmp > 0b0111) { |
934 | | - val &= ~NV_FTR(DFR0, DebugVer); |
935 | | - val |= FIELD_PREP(NV_FTR(DFR0, DebugVer), 0b0111); |
936 | | - } |
| 969 | + val = limit_nv_id_reg(kvm, SYS_ID_AA64DFR0_EL1, val); |
937 | 970 | kvm_set_vm_id_reg(kvm, SYS_ID_AA64DFR0_EL1, val); |
938 | 971 | } |
939 | 972 |
|
|
0 commit comments