diff options
-rw-r--r-- | arch/arm/include/asm/kvm_vgic.h | 11 | ||||
-rw-r--r-- | arch/arm/kvm/arm.c | 15 | ||||
-rw-r--r-- | arch/arm/kvm/vgic.c | 224 |
3 files changed, 250 insertions, 0 deletions
diff --git a/arch/arm/include/asm/kvm_vgic.h b/arch/arm/include/asm/kvm_vgic.h index 11a6d90899f7..ab97207d9cd3 100644 --- a/arch/arm/include/asm/kvm_vgic.h +++ b/arch/arm/include/asm/kvm_vgic.h | |||
@@ -72,6 +72,7 @@ struct vgic_bytemap { | |||
72 | struct vgic_dist { | 72 | struct vgic_dist { |
73 | #ifdef CONFIG_KVM_ARM_VGIC | 73 | #ifdef CONFIG_KVM_ARM_VGIC |
74 | spinlock_t lock; | 74 | spinlock_t lock; |
75 | bool ready; | ||
75 | 76 | ||
76 | /* Virtual control interface mapping */ | 77 | /* Virtual control interface mapping */ |
77 | void __iomem *vctrl_base; | 78 | void __iomem *vctrl_base; |
@@ -145,6 +146,10 @@ struct kvm_exit_mmio; | |||
145 | 146 | ||
146 | #ifdef CONFIG_KVM_ARM_VGIC | 147 | #ifdef CONFIG_KVM_ARM_VGIC |
147 | int kvm_vgic_set_addr(struct kvm *kvm, unsigned long type, u64 addr); | 148 | int kvm_vgic_set_addr(struct kvm *kvm, unsigned long type, u64 addr); |
149 | int kvm_vgic_hyp_init(void); | ||
150 | int kvm_vgic_init(struct kvm *kvm); | ||
151 | int kvm_vgic_create(struct kvm *kvm); | ||
152 | int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu); | ||
148 | void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu); | 153 | void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu); |
149 | void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu); | 154 | void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu); |
150 | int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num, | 155 | int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num, |
@@ -154,6 +159,7 @@ bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run, | |||
154 | struct kvm_exit_mmio *mmio); | 159 | struct kvm_exit_mmio *mmio); |
155 | 160 | ||
156 | #define irqchip_in_kernel(k) (!!((k)->arch.vgic.vctrl_base)) | 161 | #define irqchip_in_kernel(k) (!!((k)->arch.vgic.vctrl_base)) |
162 | #define vgic_initialized(k) ((k)->arch.vgic.ready) | ||
157 | 163 | ||
158 | #else | 164 | #else |
159 | static inline int kvm_vgic_hyp_init(void) | 165 | static inline int kvm_vgic_hyp_init(void) |
@@ -205,6 +211,11 @@ static inline int irqchip_in_kernel(struct kvm *kvm) | |||
205 | { | 211 | { |
206 | return 0; | 212 | return 0; |
207 | } | 213 | } |
214 | |||
215 | static inline bool vgic_initialized(struct kvm *kvm) | ||
216 | { | ||
217 | return true; | ||
218 | } | ||
208 | #endif | 219 | #endif |
209 | 220 | ||
210 | #endif | 221 | #endif |
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c index 3c8d6a9be123..ea7383293ed0 100644 --- a/arch/arm/kvm/arm.c +++ b/arch/arm/kvm/arm.c | |||
@@ -642,6 +642,17 @@ static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu) | |||
642 | vcpu->arch.has_run_once = true; | 642 | vcpu->arch.has_run_once = true; |
643 | 643 | ||
644 | /* | 644 | /* |
645 | * Initialize the VGIC before running a vcpu the first time on | ||
646 | * this VM. | ||
647 | */ | ||
648 | if (irqchip_in_kernel(vcpu->kvm) && | ||
649 | unlikely(!vgic_initialized(vcpu->kvm))) { | ||
650 | int ret = kvm_vgic_init(vcpu->kvm); | ||
651 | if (ret) | ||
652 | return ret; | ||
653 | } | ||
654 | |||
655 | /* | ||
645 | * Handle the "start in power-off" case by calling into the | 656 | * Handle the "start in power-off" case by calling into the |
646 | * PSCI code. | 657 | * PSCI code. |
647 | */ | 658 | */ |
@@ -1085,6 +1096,10 @@ static int init_hyp_mode(void) | |||
1085 | if (err) | 1096 | if (err) |
1086 | goto out_free_vfp; | 1097 | goto out_free_vfp; |
1087 | 1098 | ||
1099 | #ifdef CONFIG_KVM_ARM_VGIC | ||
1100 | vgic_present = true; | ||
1101 | #endif | ||
1102 | |||
1088 | kvm_info("Hyp mode initialized successfully\n"); | 1103 | kvm_info("Hyp mode initialized successfully\n"); |
1089 | return 0; | 1104 | return 0; |
1090 | out_free_vfp: | 1105 | out_free_vfp: |
diff --git a/arch/arm/kvm/vgic.c b/arch/arm/kvm/vgic.c index 2e6a585c23e5..6d8407672dec 100644 --- a/arch/arm/kvm/vgic.c +++ b/arch/arm/kvm/vgic.c | |||
@@ -16,11 +16,20 @@ | |||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/cpu.h> | ||
19 | #include <linux/kvm.h> | 20 | #include <linux/kvm.h> |
20 | #include <linux/kvm_host.h> | 21 | #include <linux/kvm_host.h> |
21 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
22 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | #include <linux/of.h> | ||
25 | #include <linux/of_address.h> | ||
26 | #include <linux/of_irq.h> | ||
27 | |||
28 | #include <linux/irqchip/arm-gic.h> | ||
29 | |||
23 | #include <asm/kvm_emulate.h> | 30 | #include <asm/kvm_emulate.h> |
31 | #include <asm/kvm_arm.h> | ||
32 | #include <asm/kvm_mmu.h> | ||
24 | 33 | ||
25 | /* | 34 | /* |
26 | * How the whole thing works (courtesy of Christoffer Dall): | 35 | * How the whole thing works (courtesy of Christoffer Dall): |
@@ -62,6 +71,14 @@ | |||
62 | #define VGIC_ADDR_UNDEF (-1) | 71 | #define VGIC_ADDR_UNDEF (-1) |
63 | #define IS_VGIC_ADDR_UNDEF(_x) ((_x) == VGIC_ADDR_UNDEF) | 72 | #define IS_VGIC_ADDR_UNDEF(_x) ((_x) == VGIC_ADDR_UNDEF) |
64 | 73 | ||
74 | /* Physical address of vgic virtual cpu interface */ | ||
75 | static phys_addr_t vgic_vcpu_base; | ||
76 | |||
77 | /* Virtual control interface base address */ | ||
78 | static void __iomem *vgic_vctrl_base; | ||
79 | |||
80 | static struct device_node *vgic_node; | ||
81 | |||
65 | #define ACCESS_READ_VALUE (1 << 0) | 82 | #define ACCESS_READ_VALUE (1 << 0) |
66 | #define ACCESS_READ_RAZ (0 << 0) | 83 | #define ACCESS_READ_RAZ (0 << 0) |
67 | #define ACCESS_READ_MASK(x) ((x) & (1 << 0)) | 84 | #define ACCESS_READ_MASK(x) ((x) & (1 << 0)) |
@@ -75,6 +92,9 @@ static void vgic_retire_disabled_irqs(struct kvm_vcpu *vcpu); | |||
75 | static void vgic_update_state(struct kvm *kvm); | 92 | static void vgic_update_state(struct kvm *kvm); |
76 | static void vgic_kick_vcpus(struct kvm *kvm); | 93 | static void vgic_kick_vcpus(struct kvm *kvm); |
77 | static void vgic_dispatch_sgi(struct kvm_vcpu *vcpu, u32 reg); | 94 | static void vgic_dispatch_sgi(struct kvm_vcpu *vcpu, u32 reg); |
95 | static u32 vgic_nr_lr; | ||
96 | |||
97 | static unsigned int vgic_maint_irq; | ||
78 | 98 | ||
79 | static u32 *vgic_bitmap_get_reg(struct vgic_bitmap *x, | 99 | static u32 *vgic_bitmap_get_reg(struct vgic_bitmap *x, |
80 | int cpuid, u32 offset) | 100 | int cpuid, u32 offset) |
@@ -1221,6 +1241,210 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num, | |||
1221 | return 0; | 1241 | return 0; |
1222 | } | 1242 | } |
1223 | 1243 | ||
1244 | static irqreturn_t vgic_maintenance_handler(int irq, void *data) | ||
1245 | { | ||
1246 | /* | ||
1247 | * We cannot rely on the vgic maintenance interrupt to be | ||
1248 | * delivered synchronously. This means we can only use it to | ||
1249 | * exit the VM, and we perform the handling of EOIed | ||
1250 | * interrupts on the exit path (see vgic_process_maintenance). | ||
1251 | */ | ||
1252 | return IRQ_HANDLED; | ||
1253 | } | ||
1254 | |||
1255 | int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu) | ||
1256 | { | ||
1257 | struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; | ||
1258 | struct vgic_dist *dist = &vcpu->kvm->arch.vgic; | ||
1259 | int i; | ||
1260 | |||
1261 | if (!irqchip_in_kernel(vcpu->kvm)) | ||
1262 | return 0; | ||
1263 | |||
1264 | if (vcpu->vcpu_id >= VGIC_MAX_CPUS) | ||
1265 | return -EBUSY; | ||
1266 | |||
1267 | for (i = 0; i < VGIC_NR_IRQS; i++) { | ||
1268 | if (i < VGIC_NR_PPIS) | ||
1269 | vgic_bitmap_set_irq_val(&dist->irq_enabled, | ||
1270 | vcpu->vcpu_id, i, 1); | ||
1271 | if (i < VGIC_NR_PRIVATE_IRQS) | ||
1272 | vgic_bitmap_set_irq_val(&dist->irq_cfg, | ||
1273 | vcpu->vcpu_id, i, VGIC_CFG_EDGE); | ||
1274 | |||
1275 | vgic_cpu->vgic_irq_lr_map[i] = LR_EMPTY; | ||
1276 | } | ||
1277 | |||
1278 | /* | ||
1279 | * By forcing VMCR to zero, the GIC will restore the binary | ||
1280 | * points to their reset values. Anything else resets to zero | ||
1281 | * anyway. | ||
1282 | */ | ||
1283 | vgic_cpu->vgic_vmcr = 0; | ||
1284 | |||
1285 | vgic_cpu->nr_lr = vgic_nr_lr; | ||
1286 | vgic_cpu->vgic_hcr = GICH_HCR_EN; /* Get the show on the road... */ | ||
1287 | |||
1288 | return 0; | ||
1289 | } | ||
1290 | |||
1291 | static void vgic_init_maintenance_interrupt(void *info) | ||
1292 | { | ||
1293 | enable_percpu_irq(vgic_maint_irq, 0); | ||
1294 | } | ||
1295 | |||
1296 | static int vgic_cpu_notify(struct notifier_block *self, | ||
1297 | unsigned long action, void *cpu) | ||
1298 | { | ||
1299 | switch (action) { | ||
1300 | case CPU_STARTING: | ||
1301 | case CPU_STARTING_FROZEN: | ||
1302 | vgic_init_maintenance_interrupt(NULL); | ||
1303 | break; | ||
1304 | case CPU_DYING: | ||
1305 | case CPU_DYING_FROZEN: | ||
1306 | disable_percpu_irq(vgic_maint_irq); | ||
1307 | break; | ||
1308 | } | ||
1309 | |||
1310 | return NOTIFY_OK; | ||
1311 | } | ||
1312 | |||
1313 | static struct notifier_block vgic_cpu_nb = { | ||
1314 | .notifier_call = vgic_cpu_notify, | ||
1315 | }; | ||
1316 | |||
1317 | int kvm_vgic_hyp_init(void) | ||
1318 | { | ||
1319 | int ret; | ||
1320 | struct resource vctrl_res; | ||
1321 | struct resource vcpu_res; | ||
1322 | |||
1323 | vgic_node = of_find_compatible_node(NULL, NULL, "arm,cortex-a15-gic"); | ||
1324 | if (!vgic_node) { | ||
1325 | kvm_err("error: no compatible vgic node in DT\n"); | ||
1326 | return -ENODEV; | ||
1327 | } | ||
1328 | |||
1329 | vgic_maint_irq = irq_of_parse_and_map(vgic_node, 0); | ||
1330 | if (!vgic_maint_irq) { | ||
1331 | kvm_err("error getting vgic maintenance irq from DT\n"); | ||
1332 | ret = -ENXIO; | ||
1333 | goto out; | ||
1334 | } | ||
1335 | |||
1336 | ret = request_percpu_irq(vgic_maint_irq, vgic_maintenance_handler, | ||
1337 | "vgic", kvm_get_running_vcpus()); | ||
1338 | if (ret) { | ||
1339 | kvm_err("Cannot register interrupt %d\n", vgic_maint_irq); | ||
1340 | goto out; | ||
1341 | } | ||
1342 | |||
1343 | ret = register_cpu_notifier(&vgic_cpu_nb); | ||
1344 | if (ret) { | ||
1345 | kvm_err("Cannot register vgic CPU notifier\n"); | ||
1346 | goto out_free_irq; | ||
1347 | } | ||
1348 | |||
1349 | ret = of_address_to_resource(vgic_node, 2, &vctrl_res); | ||
1350 | if (ret) { | ||
1351 | kvm_err("Cannot obtain VCTRL resource\n"); | ||
1352 | goto out_free_irq; | ||
1353 | } | ||
1354 | |||
1355 | vgic_vctrl_base = of_iomap(vgic_node, 2); | ||
1356 | if (!vgic_vctrl_base) { | ||
1357 | kvm_err("Cannot ioremap VCTRL\n"); | ||
1358 | ret = -ENOMEM; | ||
1359 | goto out_free_irq; | ||
1360 | } | ||
1361 | |||
1362 | vgic_nr_lr = readl_relaxed(vgic_vctrl_base + GICH_VTR); | ||
1363 | vgic_nr_lr = (vgic_nr_lr & 0x3f) + 1; | ||
1364 | |||
1365 | ret = create_hyp_io_mappings(vgic_vctrl_base, | ||
1366 | vgic_vctrl_base + resource_size(&vctrl_res), | ||
1367 | vctrl_res.start); | ||
1368 | if (ret) { | ||
1369 | kvm_err("Cannot map VCTRL into hyp\n"); | ||
1370 | goto out_unmap; | ||
1371 | } | ||
1372 | |||
1373 | kvm_info("%s@%llx IRQ%d\n", vgic_node->name, | ||
1374 | vctrl_res.start, vgic_maint_irq); | ||
1375 | on_each_cpu(vgic_init_maintenance_interrupt, NULL, 1); | ||
1376 | |||
1377 | if (of_address_to_resource(vgic_node, 3, &vcpu_res)) { | ||
1378 | kvm_err("Cannot obtain VCPU resource\n"); | ||
1379 | ret = -ENXIO; | ||
1380 | goto out_unmap; | ||
1381 | } | ||
1382 | vgic_vcpu_base = vcpu_res.start; | ||
1383 | |||
1384 | goto out; | ||
1385 | |||
1386 | out_unmap: | ||
1387 | iounmap(vgic_vctrl_base); | ||
1388 | out_free_irq: | ||
1389 | free_percpu_irq(vgic_maint_irq, kvm_get_running_vcpus()); | ||
1390 | out: | ||
1391 | of_node_put(vgic_node); | ||
1392 | return ret; | ||
1393 | } | ||
1394 | |||
1395 | int kvm_vgic_init(struct kvm *kvm) | ||
1396 | { | ||
1397 | int ret = 0, i; | ||
1398 | |||
1399 | mutex_lock(&kvm->lock); | ||
1400 | |||
1401 | if (vgic_initialized(kvm)) | ||
1402 | goto out; | ||
1403 | |||
1404 | if (IS_VGIC_ADDR_UNDEF(kvm->arch.vgic.vgic_dist_base) || | ||
1405 | IS_VGIC_ADDR_UNDEF(kvm->arch.vgic.vgic_cpu_base)) { | ||
1406 | kvm_err("Need to set vgic cpu and dist addresses first\n"); | ||
1407 | ret = -ENXIO; | ||
1408 | goto out; | ||
1409 | } | ||
1410 | |||
1411 | ret = kvm_phys_addr_ioremap(kvm, kvm->arch.vgic.vgic_cpu_base, | ||
1412 | vgic_vcpu_base, KVM_VGIC_V2_CPU_SIZE); | ||
1413 | if (ret) { | ||
1414 | kvm_err("Unable to remap VGIC CPU to VCPU\n"); | ||
1415 | goto out; | ||
1416 | } | ||
1417 | |||
1418 | for (i = VGIC_NR_PRIVATE_IRQS; i < VGIC_NR_IRQS; i += 4) | ||
1419 | vgic_set_target_reg(kvm, 0, i); | ||
1420 | |||
1421 | kvm->arch.vgic.ready = true; | ||
1422 | out: | ||
1423 | mutex_unlock(&kvm->lock); | ||
1424 | return ret; | ||
1425 | } | ||
1426 | |||
1427 | int kvm_vgic_create(struct kvm *kvm) | ||
1428 | { | ||
1429 | int ret = 0; | ||
1430 | |||
1431 | mutex_lock(&kvm->lock); | ||
1432 | |||
1433 | if (atomic_read(&kvm->online_vcpus) || kvm->arch.vgic.vctrl_base) { | ||
1434 | ret = -EEXIST; | ||
1435 | goto out; | ||
1436 | } | ||
1437 | |||
1438 | spin_lock_init(&kvm->arch.vgic.lock); | ||
1439 | kvm->arch.vgic.vctrl_base = vgic_vctrl_base; | ||
1440 | kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF; | ||
1441 | kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF; | ||
1442 | |||
1443 | out: | ||
1444 | mutex_unlock(&kvm->lock); | ||
1445 | return ret; | ||
1446 | } | ||
1447 | |||
1224 | static bool vgic_ioaddr_overlap(struct kvm *kvm) | 1448 | static bool vgic_ioaddr_overlap(struct kvm *kvm) |
1225 | { | 1449 | { |
1226 | phys_addr_t dist = kvm->arch.vgic.vgic_dist_base; | 1450 | phys_addr_t dist = kvm->arch.vgic.vgic_dist_base; |