aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/kvm/emulate.c6
-rw-r--r--arch/arm/kvm/hyp/Makefile2
-rw-r--r--arch/arm64/kvm/hyp/Makefile2
-rw-r--r--arch/arm64/kvm/inject_fault.c16
-rw-r--r--virt/kvm/arm/arm.c31
-rw-r--r--virt/kvm/arm/vgic/vgic-its.c73
6 files changed, 81 insertions, 49 deletions
diff --git a/arch/arm/kvm/emulate.c b/arch/arm/kvm/emulate.c
index 0064b86a2c87..30a13647c54c 100644
--- a/arch/arm/kvm/emulate.c
+++ b/arch/arm/kvm/emulate.c
@@ -227,7 +227,7 @@ void kvm_inject_undefined(struct kvm_vcpu *vcpu)
227 u32 return_offset = (is_thumb) ? 2 : 4; 227 u32 return_offset = (is_thumb) ? 2 : 4;
228 228
229 kvm_update_psr(vcpu, UND_MODE); 229 kvm_update_psr(vcpu, UND_MODE);
230 *vcpu_reg(vcpu, 14) = *vcpu_pc(vcpu) - return_offset; 230 *vcpu_reg(vcpu, 14) = *vcpu_pc(vcpu) + return_offset;
231 231
232 /* Branch to exception vector */ 232 /* Branch to exception vector */
233 *vcpu_pc(vcpu) = exc_vector_base(vcpu) + vect_offset; 233 *vcpu_pc(vcpu) = exc_vector_base(vcpu) + vect_offset;
@@ -239,10 +239,8 @@ void kvm_inject_undefined(struct kvm_vcpu *vcpu)
239 */ 239 */
240static void inject_abt(struct kvm_vcpu *vcpu, bool is_pabt, unsigned long addr) 240static void inject_abt(struct kvm_vcpu *vcpu, bool is_pabt, unsigned long addr)
241{ 241{
242 unsigned long cpsr = *vcpu_cpsr(vcpu);
243 bool is_thumb = (cpsr & PSR_T_BIT);
244 u32 vect_offset; 242 u32 vect_offset;
245 u32 return_offset = (is_thumb) ? 4 : 0; 243 u32 return_offset = (is_pabt) ? 4 : 8;
246 bool is_lpae; 244 bool is_lpae;
247 245
248 kvm_update_psr(vcpu, ABT_MODE); 246 kvm_update_psr(vcpu, ABT_MODE);
diff --git a/arch/arm/kvm/hyp/Makefile b/arch/arm/kvm/hyp/Makefile
index 8679405b0b2b..92eab1d51785 100644
--- a/arch/arm/kvm/hyp/Makefile
+++ b/arch/arm/kvm/hyp/Makefile
@@ -2,7 +2,7 @@
2# Makefile for Kernel-based Virtual Machine module, HYP part 2# Makefile for Kernel-based Virtual Machine module, HYP part
3# 3#
4 4
5ccflags-y += -fno-stack-protector 5ccflags-y += -fno-stack-protector -DDISABLE_BRANCH_PROFILING
6 6
7KVM=../../../../virt/kvm 7KVM=../../../../virt/kvm
8 8
diff --git a/arch/arm64/kvm/hyp/Makefile b/arch/arm64/kvm/hyp/Makefile
index 14c4e3b14bcb..48b03547a969 100644
--- a/arch/arm64/kvm/hyp/Makefile
+++ b/arch/arm64/kvm/hyp/Makefile
@@ -2,7 +2,7 @@
2# Makefile for Kernel-based Virtual Machine module, HYP part 2# Makefile for Kernel-based Virtual Machine module, HYP part
3# 3#
4 4
5ccflags-y += -fno-stack-protector 5ccflags-y += -fno-stack-protector -DDISABLE_BRANCH_PROFILING
6 6
7KVM=../../../../virt/kvm 7KVM=../../../../virt/kvm
8 8
diff --git a/arch/arm64/kvm/inject_fault.c b/arch/arm64/kvm/inject_fault.c
index da6a8cfa54a0..3556715a774e 100644
--- a/arch/arm64/kvm/inject_fault.c
+++ b/arch/arm64/kvm/inject_fault.c
@@ -33,12 +33,26 @@
33#define LOWER_EL_AArch64_VECTOR 0x400 33#define LOWER_EL_AArch64_VECTOR 0x400
34#define LOWER_EL_AArch32_VECTOR 0x600 34#define LOWER_EL_AArch32_VECTOR 0x600
35 35
36/*
37 * Table taken from ARMv8 ARM DDI0487B-B, table G1-10.
38 */
39static const u8 return_offsets[8][2] = {
40 [0] = { 0, 0 }, /* Reset, unused */
41 [1] = { 4, 2 }, /* Undefined */
42 [2] = { 0, 0 }, /* SVC, unused */
43 [3] = { 4, 4 }, /* Prefetch abort */
44 [4] = { 8, 8 }, /* Data abort */
45 [5] = { 0, 0 }, /* HVC, unused */
46 [6] = { 4, 4 }, /* IRQ, unused */
47 [7] = { 4, 4 }, /* FIQ, unused */
48};
49
36static void prepare_fault32(struct kvm_vcpu *vcpu, u32 mode, u32 vect_offset) 50static void prepare_fault32(struct kvm_vcpu *vcpu, u32 mode, u32 vect_offset)
37{ 51{
38 unsigned long cpsr; 52 unsigned long cpsr;
39 unsigned long new_spsr_value = *vcpu_cpsr(vcpu); 53 unsigned long new_spsr_value = *vcpu_cpsr(vcpu);
40 bool is_thumb = (new_spsr_value & COMPAT_PSR_T_BIT); 54 bool is_thumb = (new_spsr_value & COMPAT_PSR_T_BIT);
41 u32 return_offset = (is_thumb) ? 4 : 0; 55 u32 return_offset = return_offsets[vect_offset >> 2][is_thumb];
42 u32 sctlr = vcpu_cp15(vcpu, c1_SCTLR); 56 u32 sctlr = vcpu_cp15(vcpu, c1_SCTLR);
43 57
44 cpsr = mode | COMPAT_PSR_I_BIT; 58 cpsr = mode | COMPAT_PSR_I_BIT;
diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c
index b9f68e4add71..95cba0799828 100644
--- a/virt/kvm/arm/arm.c
+++ b/virt/kvm/arm/arm.c
@@ -1326,21 +1326,12 @@ static void teardown_hyp_mode(void)
1326{ 1326{
1327 int cpu; 1327 int cpu;
1328 1328
1329 if (is_kernel_in_hyp_mode())
1330 return;
1331
1332 free_hyp_pgds(); 1329 free_hyp_pgds();
1333 for_each_possible_cpu(cpu) 1330 for_each_possible_cpu(cpu)
1334 free_page(per_cpu(kvm_arm_hyp_stack_page, cpu)); 1331 free_page(per_cpu(kvm_arm_hyp_stack_page, cpu));
1335 hyp_cpu_pm_exit(); 1332 hyp_cpu_pm_exit();
1336} 1333}
1337 1334
1338static int init_vhe_mode(void)
1339{
1340 kvm_info("VHE mode initialized successfully\n");
1341 return 0;
1342}
1343
1344/** 1335/**
1345 * Inits Hyp-mode on all online CPUs 1336 * Inits Hyp-mode on all online CPUs
1346 */ 1337 */
@@ -1421,8 +1412,6 @@ static int init_hyp_mode(void)
1421 } 1412 }
1422 } 1413 }
1423 1414
1424 kvm_info("Hyp mode initialized successfully\n");
1425
1426 return 0; 1415 return 0;
1427 1416
1428out_err: 1417out_err:
@@ -1456,6 +1445,7 @@ int kvm_arch_init(void *opaque)
1456{ 1445{
1457 int err; 1446 int err;
1458 int ret, cpu; 1447 int ret, cpu;
1448 bool in_hyp_mode;
1459 1449
1460 if (!is_hyp_mode_available()) { 1450 if (!is_hyp_mode_available()) {
1461 kvm_err("HYP mode not available\n"); 1451 kvm_err("HYP mode not available\n");
@@ -1474,21 +1464,28 @@ int kvm_arch_init(void *opaque)
1474 if (err) 1464 if (err)
1475 return err; 1465 return err;
1476 1466
1477 if (is_kernel_in_hyp_mode()) 1467 in_hyp_mode = is_kernel_in_hyp_mode();
1478 err = init_vhe_mode(); 1468
1479 else 1469 if (!in_hyp_mode) {
1480 err = init_hyp_mode(); 1470 err = init_hyp_mode();
1481 if (err) 1471 if (err)
1482 goto out_err; 1472 goto out_err;
1473 }
1483 1474
1484 err = init_subsystems(); 1475 err = init_subsystems();
1485 if (err) 1476 if (err)
1486 goto out_hyp; 1477 goto out_hyp;
1487 1478
1479 if (in_hyp_mode)
1480 kvm_info("VHE mode initialized successfully\n");
1481 else
1482 kvm_info("Hyp mode initialized successfully\n");
1483
1488 return 0; 1484 return 0;
1489 1485
1490out_hyp: 1486out_hyp:
1491 teardown_hyp_mode(); 1487 if (!in_hyp_mode)
1488 teardown_hyp_mode();
1492out_err: 1489out_err:
1493 teardown_common_resources(); 1490 teardown_common_resources();
1494 return err; 1491 return err;
diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index f51c1e1b3f70..547f12dc4d54 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -1466,6 +1466,16 @@ static void vgic_mmio_write_its_ctlr(struct kvm *kvm, struct vgic_its *its,
1466{ 1466{
1467 mutex_lock(&its->cmd_lock); 1467 mutex_lock(&its->cmd_lock);
1468 1468
1469 /*
1470 * It is UNPREDICTABLE to enable the ITS if any of the CBASER or
1471 * device/collection BASER are invalid
1472 */
1473 if (!its->enabled && (val & GITS_CTLR_ENABLE) &&
1474 (!(its->baser_device_table & GITS_BASER_VALID) ||
1475 !(its->baser_coll_table & GITS_BASER_VALID) ||
1476 !(its->cbaser & GITS_CBASER_VALID)))
1477 goto out;
1478
1469 its->enabled = !!(val & GITS_CTLR_ENABLE); 1479 its->enabled = !!(val & GITS_CTLR_ENABLE);
1470 1480
1471 /* 1481 /*
@@ -1474,6 +1484,7 @@ static void vgic_mmio_write_its_ctlr(struct kvm *kvm, struct vgic_its *its,
1474 */ 1484 */
1475 vgic_its_process_commands(kvm, its); 1485 vgic_its_process_commands(kvm, its);
1476 1486
1487out:
1477 mutex_unlock(&its->cmd_lock); 1488 mutex_unlock(&its->cmd_lock);
1478} 1489}
1479 1490
@@ -1801,37 +1812,33 @@ typedef int (*entry_fn_t)(struct vgic_its *its, u32 id, void *entry,
1801static int scan_its_table(struct vgic_its *its, gpa_t base, int size, int esz, 1812static int scan_its_table(struct vgic_its *its, gpa_t base, int size, int esz,
1802 int start_id, entry_fn_t fn, void *opaque) 1813 int start_id, entry_fn_t fn, void *opaque)
1803{ 1814{
1804 void *entry = kzalloc(esz, GFP_KERNEL);
1805 struct kvm *kvm = its->dev->kvm; 1815 struct kvm *kvm = its->dev->kvm;
1806 unsigned long len = size; 1816 unsigned long len = size;
1807 int id = start_id; 1817 int id = start_id;
1808 gpa_t gpa = base; 1818 gpa_t gpa = base;
1819 char entry[esz];
1809 int ret; 1820 int ret;
1810 1821
1822 memset(entry, 0, esz);
1823
1811 while (len > 0) { 1824 while (len > 0) {
1812 int next_offset; 1825 int next_offset;
1813 size_t byte_offset; 1826 size_t byte_offset;
1814 1827
1815 ret = kvm_read_guest(kvm, gpa, entry, esz); 1828 ret = kvm_read_guest(kvm, gpa, entry, esz);
1816 if (ret) 1829 if (ret)
1817 goto out; 1830 return ret;
1818 1831
1819 next_offset = fn(its, id, entry, opaque); 1832 next_offset = fn(its, id, entry, opaque);
1820 if (next_offset <= 0) { 1833 if (next_offset <= 0)
1821 ret = next_offset; 1834 return next_offset;
1822 goto out;
1823 }
1824 1835
1825 byte_offset = next_offset * esz; 1836 byte_offset = next_offset * esz;
1826 id += next_offset; 1837 id += next_offset;
1827 gpa += byte_offset; 1838 gpa += byte_offset;
1828 len -= byte_offset; 1839 len -= byte_offset;
1829 } 1840 }
1830 ret = 1; 1841 return 1;
1831
1832out:
1833 kfree(entry);
1834 return ret;
1835} 1842}
1836 1843
1837/** 1844/**
@@ -1940,6 +1947,14 @@ static int vgic_its_save_itt(struct vgic_its *its, struct its_device *device)
1940 return 0; 1947 return 0;
1941} 1948}
1942 1949
1950/**
1951 * vgic_its_restore_itt - restore the ITT of a device
1952 *
1953 * @its: its handle
1954 * @dev: device handle
1955 *
1956 * Return 0 on success, < 0 on error
1957 */
1943static int vgic_its_restore_itt(struct vgic_its *its, struct its_device *dev) 1958static int vgic_its_restore_itt(struct vgic_its *its, struct its_device *dev)
1944{ 1959{
1945 const struct vgic_its_abi *abi = vgic_its_get_abi(its); 1960 const struct vgic_its_abi *abi = vgic_its_get_abi(its);
@@ -1951,6 +1966,10 @@ static int vgic_its_restore_itt(struct vgic_its *its, struct its_device *dev)
1951 ret = scan_its_table(its, base, max_size, ite_esz, 0, 1966 ret = scan_its_table(its, base, max_size, ite_esz, 0,
1952 vgic_its_restore_ite, dev); 1967 vgic_its_restore_ite, dev);
1953 1968
1969 /* scan_its_table returns +1 if all ITEs are invalid */
1970 if (ret > 0)
1971 ret = 0;
1972
1954 return ret; 1973 return ret;
1955} 1974}
1956 1975
@@ -2048,11 +2067,12 @@ static int vgic_its_device_cmp(void *priv, struct list_head *a,
2048static int vgic_its_save_device_tables(struct vgic_its *its) 2067static int vgic_its_save_device_tables(struct vgic_its *its)
2049{ 2068{
2050 const struct vgic_its_abi *abi = vgic_its_get_abi(its); 2069 const struct vgic_its_abi *abi = vgic_its_get_abi(its);
2070 u64 baser = its->baser_device_table;
2051 struct its_device *dev; 2071 struct its_device *dev;
2052 int dte_esz = abi->dte_esz; 2072 int dte_esz = abi->dte_esz;
2053 u64 baser;
2054 2073
2055 baser = its->baser_device_table; 2074 if (!(baser & GITS_BASER_VALID))
2075 return 0;
2056 2076
2057 list_sort(NULL, &its->device_list, vgic_its_device_cmp); 2077 list_sort(NULL, &its->device_list, vgic_its_device_cmp);
2058 2078
@@ -2107,10 +2127,7 @@ static int handle_l1_dte(struct vgic_its *its, u32 id, void *addr,
2107 ret = scan_its_table(its, gpa, SZ_64K, dte_esz, 2127 ret = scan_its_table(its, gpa, SZ_64K, dte_esz,
2108 l2_start_id, vgic_its_restore_dte, NULL); 2128 l2_start_id, vgic_its_restore_dte, NULL);
2109 2129
2110 if (ret <= 0) 2130 return ret;
2111 return ret;
2112
2113 return 1;
2114} 2131}
2115 2132
2116/** 2133/**
@@ -2140,8 +2157,9 @@ static int vgic_its_restore_device_tables(struct vgic_its *its)
2140 vgic_its_restore_dte, NULL); 2157 vgic_its_restore_dte, NULL);
2141 } 2158 }
2142 2159
2160 /* scan_its_table returns +1 if all entries are invalid */
2143 if (ret > 0) 2161 if (ret > 0)
2144 ret = -EINVAL; 2162 ret = 0;
2145 2163
2146 return ret; 2164 return ret;
2147} 2165}
@@ -2198,17 +2216,17 @@ static int vgic_its_restore_cte(struct vgic_its *its, gpa_t gpa, int esz)
2198static int vgic_its_save_collection_table(struct vgic_its *its) 2216static int vgic_its_save_collection_table(struct vgic_its *its)
2199{ 2217{
2200 const struct vgic_its_abi *abi = vgic_its_get_abi(its); 2218 const struct vgic_its_abi *abi = vgic_its_get_abi(its);
2219 u64 baser = its->baser_coll_table;
2220 gpa_t gpa = BASER_ADDRESS(baser);
2201 struct its_collection *collection; 2221 struct its_collection *collection;
2202 u64 val; 2222 u64 val;
2203 gpa_t gpa;
2204 size_t max_size, filled = 0; 2223 size_t max_size, filled = 0;
2205 int ret, cte_esz = abi->cte_esz; 2224 int ret, cte_esz = abi->cte_esz;
2206 2225
2207 gpa = BASER_ADDRESS(its->baser_coll_table); 2226 if (!(baser & GITS_BASER_VALID))
2208 if (!gpa)
2209 return 0; 2227 return 0;
2210 2228
2211 max_size = GITS_BASER_NR_PAGES(its->baser_coll_table) * SZ_64K; 2229 max_size = GITS_BASER_NR_PAGES(baser) * SZ_64K;
2212 2230
2213 list_for_each_entry(collection, &its->collection_list, coll_list) { 2231 list_for_each_entry(collection, &its->collection_list, coll_list) {
2214 ret = vgic_its_save_cte(its, collection, gpa, cte_esz); 2232 ret = vgic_its_save_cte(its, collection, gpa, cte_esz);
@@ -2239,17 +2257,18 @@ static int vgic_its_save_collection_table(struct vgic_its *its)
2239static int vgic_its_restore_collection_table(struct vgic_its *its) 2257static int vgic_its_restore_collection_table(struct vgic_its *its)
2240{ 2258{
2241 const struct vgic_its_abi *abi = vgic_its_get_abi(its); 2259 const struct vgic_its_abi *abi = vgic_its_get_abi(its);
2260 u64 baser = its->baser_coll_table;
2242 int cte_esz = abi->cte_esz; 2261 int cte_esz = abi->cte_esz;
2243 size_t max_size, read = 0; 2262 size_t max_size, read = 0;
2244 gpa_t gpa; 2263 gpa_t gpa;
2245 int ret; 2264 int ret;
2246 2265
2247 if (!(its->baser_coll_table & GITS_BASER_VALID)) 2266 if (!(baser & GITS_BASER_VALID))
2248 return 0; 2267 return 0;
2249 2268
2250 gpa = BASER_ADDRESS(its->baser_coll_table); 2269 gpa = BASER_ADDRESS(baser);
2251 2270
2252 max_size = GITS_BASER_NR_PAGES(its->baser_coll_table) * SZ_64K; 2271 max_size = GITS_BASER_NR_PAGES(baser) * SZ_64K;
2253 2272
2254 while (read < max_size) { 2273 while (read < max_size) {
2255 ret = vgic_its_restore_cte(its, gpa, cte_esz); 2274 ret = vgic_its_restore_cte(its, gpa, cte_esz);
@@ -2258,6 +2277,10 @@ static int vgic_its_restore_collection_table(struct vgic_its *its)
2258 gpa += cte_esz; 2277 gpa += cte_esz;
2259 read += cte_esz; 2278 read += cte_esz;
2260 } 2279 }
2280
2281 if (ret > 0)
2282 return 0;
2283
2261 return ret; 2284 return ret;
2262} 2285}
2263 2286