|
23 | 23 | * This list should get updated as new features get added to the NV
|
24 | 24 | * support, and new extension to the architecture.
|
25 | 25 | */
|
26 |
| -static u64 limit_nv_id_reg(u32 id, u64 val) |
| 26 | +static void limit_nv_id_regs(struct kvm *kvm) |
27 | 27 | {
|
28 |
| - u64 tmp; |
29 |
| - |
30 |
| - switch (id) { |
31 |
| - case SYS_ID_AA64ISAR0_EL1: |
32 |
| - /* Support everything but TME, O.S. and Range TLBIs */ |
33 |
| - val &= ~(NV_FTR(ISAR0, TLB) | |
34 |
| - NV_FTR(ISAR0, TME)); |
35 |
| - break; |
36 |
| - |
37 |
| - case SYS_ID_AA64ISAR1_EL1: |
38 |
| - /* Support everything but Spec Invalidation */ |
39 |
| - val &= ~(GENMASK_ULL(63, 56) | |
40 |
| - NV_FTR(ISAR1, SPECRES)); |
41 |
| - break; |
42 |
| - |
43 |
| - case SYS_ID_AA64PFR0_EL1: |
44 |
| - /* No AMU, MPAM, S-EL2, RAS or SVE */ |
45 |
| - val &= ~(GENMASK_ULL(55, 52) | |
46 |
| - NV_FTR(PFR0, AMU) | |
47 |
| - NV_FTR(PFR0, MPAM) | |
48 |
| - NV_FTR(PFR0, SEL2) | |
49 |
| - NV_FTR(PFR0, RAS) | |
50 |
| - NV_FTR(PFR0, SVE) | |
51 |
| - NV_FTR(PFR0, EL3) | |
52 |
| - NV_FTR(PFR0, EL2) | |
53 |
| - NV_FTR(PFR0, EL1)); |
54 |
| - /* 64bit EL1/EL2/EL3 only */ |
55 |
| - val |= FIELD_PREP(NV_FTR(PFR0, EL1), 0b0001); |
56 |
| - val |= FIELD_PREP(NV_FTR(PFR0, EL2), 0b0001); |
57 |
| - val |= FIELD_PREP(NV_FTR(PFR0, EL3), 0b0001); |
58 |
| - break; |
59 |
| - |
60 |
| - case SYS_ID_AA64PFR1_EL1: |
61 |
| - /* Only support SSBS */ |
62 |
| - val &= NV_FTR(PFR1, SSBS); |
63 |
| - break; |
64 |
| - |
65 |
| - case SYS_ID_AA64MMFR0_EL1: |
66 |
| - /* Hide ECV, ExS, Secure Memory */ |
67 |
| - val &= ~(NV_FTR(MMFR0, ECV) | |
68 |
| - NV_FTR(MMFR0, EXS) | |
69 |
| - NV_FTR(MMFR0, TGRAN4_2) | |
70 |
| - NV_FTR(MMFR0, TGRAN16_2) | |
71 |
| - NV_FTR(MMFR0, TGRAN64_2) | |
72 |
| - NV_FTR(MMFR0, SNSMEM)); |
73 |
| - |
74 |
| - /* Disallow unsupported S2 page sizes */ |
75 |
| - switch (PAGE_SIZE) { |
76 |
| - case SZ_64K: |
77 |
| - val |= FIELD_PREP(NV_FTR(MMFR0, TGRAN16_2), 0b0001); |
78 |
| - fallthrough; |
79 |
| - case SZ_16K: |
80 |
| - val |= FIELD_PREP(NV_FTR(MMFR0, TGRAN4_2), 0b0001); |
81 |
| - fallthrough; |
82 |
| - case SZ_4K: |
83 |
| - /* Support everything */ |
84 |
| - break; |
85 |
| - } |
86 |
| - /* |
87 |
| - * Since we can't support a guest S2 page size smaller than |
88 |
| - * the host's own page size (due to KVM only populating its |
89 |
| - * own S2 using the kernel's page size), advertise the |
90 |
| - * limitation using FEAT_GTG. |
91 |
| - */ |
92 |
| - switch (PAGE_SIZE) { |
93 |
| - case SZ_4K: |
94 |
| - val |= FIELD_PREP(NV_FTR(MMFR0, TGRAN4_2), 0b0010); |
95 |
| - fallthrough; |
96 |
| - case SZ_16K: |
97 |
| - val |= FIELD_PREP(NV_FTR(MMFR0, TGRAN16_2), 0b0010); |
98 |
| - fallthrough; |
99 |
| - case SZ_64K: |
100 |
| - val |= FIELD_PREP(NV_FTR(MMFR0, TGRAN64_2), 0b0010); |
101 |
| - break; |
102 |
| - } |
103 |
| - /* Cap PARange to 48bits */ |
104 |
| - tmp = FIELD_GET(NV_FTR(MMFR0, PARANGE), val); |
105 |
| - if (tmp > 0b0101) { |
106 |
| - val &= ~NV_FTR(MMFR0, PARANGE); |
107 |
| - val |= FIELD_PREP(NV_FTR(MMFR0, PARANGE), 0b0101); |
108 |
| - } |
| 28 | + u64 val, tmp; |
| 29 | + |
| 30 | + /* Support everything but TME, O.S. and Range TLBIs */ |
| 31 | + val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64ISAR0_EL1); |
| 32 | + val &= ~(NV_FTR(ISAR0, TLB) | |
| 33 | + NV_FTR(ISAR0, TME)); |
| 34 | + kvm_set_vm_id_reg(kvm, SYS_ID_AA64ISAR0_EL1, val); |
| 35 | + |
| 36 | + /* Support everything but Spec Invalidation */ |
| 37 | + val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64ISAR1_EL1); |
| 38 | + val &= ~(GENMASK_ULL(63, 56) | |
| 39 | + NV_FTR(ISAR1, SPECRES)); |
| 40 | + kvm_set_vm_id_reg(kvm, SYS_ID_AA64ISAR1_EL1, val); |
| 41 | + |
| 42 | + /* No AMU, MPAM, S-EL2, RAS or SVE */ |
| 43 | + kvm_read_vm_id_reg(kvm, SYS_ID_AA64PFR0_EL1); |
| 44 | + val &= ~(GENMASK_ULL(55, 52) | |
| 45 | + NV_FTR(PFR0, AMU) | |
| 46 | + NV_FTR(PFR0, MPAM) | |
| 47 | + NV_FTR(PFR0, SEL2) | |
| 48 | + NV_FTR(PFR0, RAS) | |
| 49 | + NV_FTR(PFR0, SVE) | |
| 50 | + NV_FTR(PFR0, EL3) | |
| 51 | + NV_FTR(PFR0, EL2) | |
| 52 | + NV_FTR(PFR0, EL1)); |
| 53 | + /* 64bit EL1/EL2/EL3 only */ |
| 54 | + val |= FIELD_PREP(NV_FTR(PFR0, EL1), 0b0001); |
| 55 | + val |= FIELD_PREP(NV_FTR(PFR0, EL2), 0b0001); |
| 56 | + val |= FIELD_PREP(NV_FTR(PFR0, EL3), 0b0001); |
| 57 | + kvm_set_vm_id_reg(kvm, SYS_ID_AA64PFR0_EL1, val); |
| 58 | + |
| 59 | + /* Only support SSBS */ |
| 60 | + val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64PFR1_EL1); |
| 61 | + val &= NV_FTR(PFR1, SSBS); |
| 62 | + kvm_set_vm_id_reg(kvm, SYS_ID_AA64PFR1_EL1, val); |
| 63 | + |
| 64 | + /* Hide ECV, ExS, Secure Memory */ |
| 65 | + val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64MMFR0_EL1); |
| 66 | + val &= ~(NV_FTR(MMFR0, ECV) | |
| 67 | + NV_FTR(MMFR0, EXS) | |
| 68 | + NV_FTR(MMFR0, TGRAN4_2) | |
| 69 | + NV_FTR(MMFR0, TGRAN16_2) | |
| 70 | + NV_FTR(MMFR0, TGRAN64_2) | |
| 71 | + NV_FTR(MMFR0, SNSMEM)); |
| 72 | + |
| 73 | + /* Disallow unsupported S2 page sizes */ |
| 74 | + switch (PAGE_SIZE) { |
| 75 | + case SZ_64K: |
| 76 | + val |= FIELD_PREP(NV_FTR(MMFR0, TGRAN16_2), 0b0001); |
| 77 | + fallthrough; |
| 78 | + case SZ_16K: |
| 79 | + val |= FIELD_PREP(NV_FTR(MMFR0, TGRAN4_2), 0b0001); |
| 80 | + fallthrough; |
| 81 | + case SZ_4K: |
| 82 | + /* Support everything */ |
109 | 83 | break;
|
110 |
| - |
111 |
| - case SYS_ID_AA64MMFR1_EL1: |
112 |
| - val &= (NV_FTR(MMFR1, HCX) | |
113 |
| - NV_FTR(MMFR1, PAN) | |
114 |
| - NV_FTR(MMFR1, LO) | |
115 |
| - NV_FTR(MMFR1, HPDS) | |
116 |
| - NV_FTR(MMFR1, VH) | |
117 |
| - NV_FTR(MMFR1, VMIDBits)); |
118 |
| - break; |
119 |
| - |
120 |
| - case SYS_ID_AA64MMFR2_EL1: |
121 |
| - val &= ~(NV_FTR(MMFR2, BBM) | |
122 |
| - NV_FTR(MMFR2, TTL) | |
123 |
| - GENMASK_ULL(47, 44) | |
124 |
| - NV_FTR(MMFR2, ST) | |
125 |
| - NV_FTR(MMFR2, CCIDX) | |
126 |
| - NV_FTR(MMFR2, VARange)); |
127 |
| - |
128 |
| - /* Force TTL support */ |
129 |
| - val |= FIELD_PREP(NV_FTR(MMFR2, TTL), 0b0001); |
130 |
| - break; |
131 |
| - |
132 |
| - case SYS_ID_AA64MMFR4_EL1: |
133 |
| - val = 0; |
134 |
| - if (!cpus_have_final_cap(ARM64_HAS_HCR_NV1)) |
135 |
| - val |= FIELD_PREP(NV_FTR(MMFR4, E2H0), |
136 |
| - ID_AA64MMFR4_EL1_E2H0_NI_NV1); |
137 |
| - break; |
138 |
| - |
139 |
| - case SYS_ID_AA64DFR0_EL1: |
140 |
| - /* Only limited support for PMU, Debug, BPs and WPs */ |
141 |
| - val &= (NV_FTR(DFR0, PMUVer) | |
142 |
| - NV_FTR(DFR0, WRPs) | |
143 |
| - NV_FTR(DFR0, BRPs) | |
144 |
| - NV_FTR(DFR0, DebugVer)); |
145 |
| - |
146 |
| - /* Cap Debug to ARMv8.1 */ |
147 |
| - tmp = FIELD_GET(NV_FTR(DFR0, DebugVer), val); |
148 |
| - if (tmp > 0b0111) { |
149 |
| - val &= ~NV_FTR(DFR0, DebugVer); |
150 |
| - val |= FIELD_PREP(NV_FTR(DFR0, DebugVer), 0b0111); |
151 |
| - } |
152 |
| - break; |
153 |
| - |
154 |
| - default: |
155 |
| - /* Unknown register, just wipe it clean */ |
156 |
| - val = 0; |
| 84 | + } |
| 85 | + /* |
| 86 | + * Since we can't support a guest S2 page size smaller than |
| 87 | + * the host's own page size (due to KVM only populating its |
| 88 | + * own S2 using the kernel's page size), advertise the |
| 89 | + * limitation using FEAT_GTG. |
| 90 | + */ |
| 91 | + switch (PAGE_SIZE) { |
| 92 | + case SZ_4K: |
| 93 | + val |= FIELD_PREP(NV_FTR(MMFR0, TGRAN4_2), 0b0010); |
| 94 | + fallthrough; |
| 95 | + case SZ_16K: |
| 96 | + val |= FIELD_PREP(NV_FTR(MMFR0, TGRAN16_2), 0b0010); |
| 97 | + fallthrough; |
| 98 | + case SZ_64K: |
| 99 | + val |= FIELD_PREP(NV_FTR(MMFR0, TGRAN64_2), 0b0010); |
157 | 100 | break;
|
158 | 101 | }
|
159 |
| - |
160 |
| - return val; |
| 102 | + /* Cap PARange to 48bits */ |
| 103 | + tmp = FIELD_GET(NV_FTR(MMFR0, PARANGE), val); |
| 104 | + if (tmp > 0b0101) { |
| 105 | + val &= ~NV_FTR(MMFR0, PARANGE); |
| 106 | + val |= FIELD_PREP(NV_FTR(MMFR0, PARANGE), 0b0101); |
| 107 | + } |
| 108 | + kvm_set_vm_id_reg(kvm, SYS_ID_AA64MMFR0_EL1, val); |
| 109 | + |
| 110 | + val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64MMFR1_EL1); |
| 111 | + val &= (NV_FTR(MMFR1, HCX) | |
| 112 | + NV_FTR(MMFR1, PAN) | |
| 113 | + NV_FTR(MMFR1, LO) | |
| 114 | + NV_FTR(MMFR1, HPDS) | |
| 115 | + NV_FTR(MMFR1, VH) | |
| 116 | + NV_FTR(MMFR1, VMIDBits)); |
| 117 | + kvm_set_vm_id_reg(kvm, SYS_ID_AA64MMFR1_EL1, val); |
| 118 | + |
| 119 | + val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64MMFR2_EL1); |
| 120 | + val &= ~(NV_FTR(MMFR2, BBM) | |
| 121 | + NV_FTR(MMFR2, TTL) | |
| 122 | + GENMASK_ULL(47, 44) | |
| 123 | + NV_FTR(MMFR2, ST) | |
| 124 | + NV_FTR(MMFR2, CCIDX) | |
| 125 | + NV_FTR(MMFR2, VARange)); |
| 126 | + |
| 127 | + /* Force TTL support */ |
| 128 | + val |= FIELD_PREP(NV_FTR(MMFR2, TTL), 0b0001); |
| 129 | + kvm_set_vm_id_reg(kvm, SYS_ID_AA64MMFR2_EL1, val); |
| 130 | + |
| 131 | + val = 0; |
| 132 | + if (!cpus_have_final_cap(ARM64_HAS_HCR_NV1)) |
| 133 | + val |= FIELD_PREP(NV_FTR(MMFR4, E2H0), |
| 134 | + ID_AA64MMFR4_EL1_E2H0_NI_NV1); |
| 135 | + kvm_set_vm_id_reg(kvm, SYS_ID_AA64MMFR4_EL1, val); |
| 136 | + |
| 137 | + /* Only limited support for PMU, Debug, BPs and WPs */ |
| 138 | + val = kvm_read_vm_id_reg(kvm, SYS_ID_AA64DFR0_EL1); |
| 139 | + val &= (NV_FTR(DFR0, PMUVer) | |
| 140 | + NV_FTR(DFR0, WRPs) | |
| 141 | + NV_FTR(DFR0, BRPs) | |
| 142 | + NV_FTR(DFR0, DebugVer)); |
| 143 | + |
| 144 | + /* Cap Debug to ARMv8.1 */ |
| 145 | + tmp = FIELD_GET(NV_FTR(DFR0, DebugVer), val); |
| 146 | + if (tmp > 0b0111) { |
| 147 | + val &= ~NV_FTR(DFR0, DebugVer); |
| 148 | + val |= FIELD_PREP(NV_FTR(DFR0, DebugVer), 0b0111); |
| 149 | + } |
| 150 | + kvm_set_vm_id_reg(kvm, SYS_ID_AA64DFR0_EL1, val); |
161 | 151 | }
|
162 | 152 |
|
163 | 153 | u64 kvm_vcpu_sanitise_vncr_reg(const struct kvm_vcpu *vcpu, enum vcpu_sysreg sr)
|
@@ -202,9 +192,7 @@ int kvm_init_nv_sysregs(struct kvm *kvm)
|
202 | 192 | goto out;
|
203 | 193 | }
|
204 | 194 |
|
205 |
| - for (int i = 0; i < KVM_ARM_ID_REG_NUM; i++) |
206 |
| - kvm_set_vm_id_reg(kvm, IDX_IDREG(i), limit_nv_id_reg(IDX_IDREG(i), |
207 |
| - kvm->arch.id_regs[i])); |
| 195 | + limit_nv_id_regs(kvm); |
208 | 196 |
|
209 | 197 | /* VTTBR_EL2 */
|
210 | 198 | res0 = res1 = 0;
|
|
0 commit comments