0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/kvm_host.h>
0013 #include <linux/slab.h>
0014 #include <linux/err.h>
0015 #include <linux/export.h>
0016 #include <linux/module.h>
0017 #include <linux/miscdevice.h>
0018
0019 #include <asm/reg.h>
0020 #include <asm/cputable.h>
0021 #include <asm/kvm_ppc.h>
0022
0023 #include "../mm/mmu_decl.h"
0024 #include "booke.h"
0025 #include "e500.h"
0026
0027 struct id {
0028 unsigned long val;
0029 struct id **pentry;
0030 };
0031
0032 #define NUM_TIDS 256
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043 struct vcpu_id_table {
0044 struct id id[2][NUM_TIDS][2];
0045 };
0046
0047
0048
0049
0050
0051
0052 struct pcpu_id_table {
0053 struct id *entry[NUM_TIDS];
0054 };
0055
0056 static DEFINE_PER_CPU(struct pcpu_id_table, pcpu_sids);
0057
0058
0059
0060 static DEFINE_PER_CPU(unsigned long, pcpu_last_used_sid);
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070 static inline int local_sid_setup_one(struct id *entry)
0071 {
0072 unsigned long sid;
0073 int ret = -1;
0074
0075 sid = __this_cpu_inc_return(pcpu_last_used_sid);
0076 if (sid < NUM_TIDS) {
0077 __this_cpu_write(pcpu_sids.entry[sid], entry);
0078 entry->val = sid;
0079 entry->pentry = this_cpu_ptr(&pcpu_sids.entry[sid]);
0080 ret = sid;
0081 }
0082
0083
0084
0085
0086
0087
0088
0089
0090 WARN_ON(sid > NUM_TIDS);
0091
0092 return ret;
0093 }
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104 static inline int local_sid_lookup(struct id *entry)
0105 {
0106 if (entry && entry->val != 0 &&
0107 __this_cpu_read(pcpu_sids.entry[entry->val]) == entry &&
0108 entry->pentry == this_cpu_ptr(&pcpu_sids.entry[entry->val]))
0109 return entry->val;
0110 return -1;
0111 }
0112
0113
0114 static inline void local_sid_destroy_all(void)
0115 {
0116 __this_cpu_write(pcpu_last_used_sid, 0);
0117 memset(this_cpu_ptr(&pcpu_sids), 0, sizeof(pcpu_sids));
0118 }
0119
0120 static void *kvmppc_e500_id_table_alloc(struct kvmppc_vcpu_e500 *vcpu_e500)
0121 {
0122 vcpu_e500->idt = kzalloc(sizeof(struct vcpu_id_table), GFP_KERNEL);
0123 return vcpu_e500->idt;
0124 }
0125
0126 static void kvmppc_e500_id_table_free(struct kvmppc_vcpu_e500 *vcpu_e500)
0127 {
0128 kfree(vcpu_e500->idt);
0129 vcpu_e500->idt = NULL;
0130 }
0131
0132
0133
0134
0135
0136 static void kvmppc_e500_recalc_shadow_pid(struct kvmppc_vcpu_e500 *vcpu_e500)
0137 {
0138 preempt_disable();
0139 vcpu_e500->vcpu.arch.shadow_pid = kvmppc_e500_get_sid(vcpu_e500,
0140 get_cur_as(&vcpu_e500->vcpu),
0141 get_cur_pid(&vcpu_e500->vcpu),
0142 get_cur_pr(&vcpu_e500->vcpu), 1);
0143 vcpu_e500->vcpu.arch.shadow_pid1 = kvmppc_e500_get_sid(vcpu_e500,
0144 get_cur_as(&vcpu_e500->vcpu), 0,
0145 get_cur_pr(&vcpu_e500->vcpu), 1);
0146 preempt_enable();
0147 }
0148
0149
0150 static void kvmppc_e500_id_table_reset_all(struct kvmppc_vcpu_e500 *vcpu_e500)
0151 {
0152 memset(vcpu_e500->idt, 0, sizeof(struct vcpu_id_table));
0153
0154
0155 kvmppc_e500_recalc_shadow_pid(vcpu_e500);
0156 }
0157
0158
0159 static inline void kvmppc_e500_id_table_reset_one(
0160 struct kvmppc_vcpu_e500 *vcpu_e500,
0161 int as, int pid, int pr)
0162 {
0163 struct vcpu_id_table *idt = vcpu_e500->idt;
0164
0165 BUG_ON(as >= 2);
0166 BUG_ON(pid >= NUM_TIDS);
0167 BUG_ON(pr >= 2);
0168
0169 idt->id[as][pid][pr].val = 0;
0170 idt->id[as][pid][pr].pentry = NULL;
0171
0172
0173 kvmppc_e500_recalc_shadow_pid(vcpu_e500);
0174 }
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185 unsigned int kvmppc_e500_get_sid(struct kvmppc_vcpu_e500 *vcpu_e500,
0186 unsigned int as, unsigned int gid,
0187 unsigned int pr, int avoid_recursion)
0188 {
0189 struct vcpu_id_table *idt = vcpu_e500->idt;
0190 int sid;
0191
0192 BUG_ON(as >= 2);
0193 BUG_ON(gid >= NUM_TIDS);
0194 BUG_ON(pr >= 2);
0195
0196 sid = local_sid_lookup(&idt->id[as][gid][pr]);
0197
0198 while (sid <= 0) {
0199
0200 sid = local_sid_setup_one(&idt->id[as][gid][pr]);
0201 if (sid <= 0) {
0202 _tlbil_all();
0203 local_sid_destroy_all();
0204 }
0205
0206
0207 if (!avoid_recursion)
0208 kvmppc_e500_recalc_shadow_pid(vcpu_e500);
0209 }
0210
0211 return sid;
0212 }
0213
0214 unsigned int kvmppc_e500_get_tlb_stid(struct kvm_vcpu *vcpu,
0215 struct kvm_book3e_206_tlb_entry *gtlbe)
0216 {
0217 return kvmppc_e500_get_sid(to_e500(vcpu), get_tlb_ts(gtlbe),
0218 get_tlb_tid(gtlbe), get_cur_pr(vcpu), 0);
0219 }
0220
0221 void kvmppc_set_pid(struct kvm_vcpu *vcpu, u32 pid)
0222 {
0223 struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
0224
0225 if (vcpu->arch.pid != pid) {
0226 vcpu_e500->pid[0] = vcpu->arch.pid = pid;
0227 kvmppc_e500_recalc_shadow_pid(vcpu_e500);
0228 }
0229 }
0230
0231
0232 void kvmppc_e500_tlbil_one(struct kvmppc_vcpu_e500 *vcpu_e500,
0233 struct kvm_book3e_206_tlb_entry *gtlbe)
0234 {
0235 struct vcpu_id_table *idt = vcpu_e500->idt;
0236 unsigned int pr, tid, ts;
0237 int pid;
0238 u32 val, eaddr;
0239 unsigned long flags;
0240
0241 ts = get_tlb_ts(gtlbe);
0242 tid = get_tlb_tid(gtlbe);
0243
0244 preempt_disable();
0245
0246
0247 for (pr = 0; pr < 2; pr++) {
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257 pid = local_sid_lookup(&idt->id[ts][tid][pr]);
0258 if (pid <= 0) {
0259 kvmppc_e500_id_table_reset_one(vcpu_e500, ts, tid, pr);
0260 continue;
0261 }
0262
0263
0264
0265
0266
0267
0268
0269 val = (pid << MAS6_SPID_SHIFT) | MAS6_SAS;
0270 eaddr = get_tlb_eaddr(gtlbe);
0271
0272 local_irq_save(flags);
0273
0274 mtspr(SPRN_MAS6, val);
0275 asm volatile("tlbsx 0, %[eaddr]" : : [eaddr] "r" (eaddr));
0276 val = mfspr(SPRN_MAS1);
0277 if (val & MAS1_VALID) {
0278 mtspr(SPRN_MAS1, val & ~MAS1_VALID);
0279 asm volatile("tlbwe");
0280 }
0281
0282 local_irq_restore(flags);
0283 }
0284
0285 preempt_enable();
0286 }
0287
0288 void kvmppc_e500_tlbil_all(struct kvmppc_vcpu_e500 *vcpu_e500)
0289 {
0290 kvmppc_e500_id_table_reset_all(vcpu_e500);
0291 }
0292
0293 void kvmppc_mmu_msr_notify(struct kvm_vcpu *vcpu, u32 old_msr)
0294 {
0295
0296 kvmppc_e500_recalc_shadow_pid(to_e500(vcpu));
0297 }
0298
0299 static void kvmppc_core_vcpu_load_e500(struct kvm_vcpu *vcpu, int cpu)
0300 {
0301 kvmppc_booke_vcpu_load(vcpu, cpu);
0302
0303
0304 kvmppc_e500_recalc_shadow_pid(to_e500(vcpu));
0305 }
0306
0307 static void kvmppc_core_vcpu_put_e500(struct kvm_vcpu *vcpu)
0308 {
0309 #ifdef CONFIG_SPE
0310 if (vcpu->arch.shadow_msr & MSR_SPE)
0311 kvmppc_vcpu_disable_spe(vcpu);
0312 #endif
0313
0314 kvmppc_booke_vcpu_put(vcpu);
0315 }
0316
0317 int kvmppc_core_check_processor_compat(void)
0318 {
0319 int r;
0320
0321 if (strcmp(cur_cpu_spec->cpu_name, "e500v2") == 0)
0322 r = 0;
0323 else
0324 r = -ENOTSUPP;
0325
0326 return r;
0327 }
0328
0329 static void kvmppc_e500_tlb_setup(struct kvmppc_vcpu_e500 *vcpu_e500)
0330 {
0331 struct kvm_book3e_206_tlb_entry *tlbe;
0332
0333
0334 tlbe = get_entry(vcpu_e500, 1, 0);
0335 tlbe->mas1 = MAS1_VALID | MAS1_TSIZE(BOOK3E_PAGESZ_256M);
0336 tlbe->mas2 = 0;
0337 tlbe->mas7_3 = E500_TLB_SUPER_PERM_MASK;
0338
0339
0340 tlbe = get_entry(vcpu_e500, 1, 1);
0341 tlbe->mas1 = MAS1_VALID | MAS1_TSIZE(BOOK3E_PAGESZ_4K);
0342 tlbe->mas2 = (0xe0004500 & 0xFFFFF000) | MAS2_I | MAS2_G;
0343 tlbe->mas7_3 = (0xe0004500 & 0xFFFFF000) | E500_TLB_SUPER_PERM_MASK;
0344 }
0345
0346 int kvmppc_core_vcpu_setup(struct kvm_vcpu *vcpu)
0347 {
0348 struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
0349
0350 kvmppc_e500_tlb_setup(vcpu_e500);
0351
0352
0353 vcpu->arch.pvr = mfspr(SPRN_PVR);
0354 vcpu_e500->svr = mfspr(SPRN_SVR);
0355
0356 vcpu->arch.cpu_type = KVM_CPU_E500V2;
0357
0358 return 0;
0359 }
0360
0361 static int kvmppc_core_get_sregs_e500(struct kvm_vcpu *vcpu,
0362 struct kvm_sregs *sregs)
0363 {
0364 struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
0365
0366 sregs->u.e.features |= KVM_SREGS_E_ARCH206_MMU | KVM_SREGS_E_SPE |
0367 KVM_SREGS_E_PM;
0368 sregs->u.e.impl_id = KVM_SREGS_E_IMPL_FSL;
0369
0370 sregs->u.e.impl.fsl.features = 0;
0371 sregs->u.e.impl.fsl.svr = vcpu_e500->svr;
0372 sregs->u.e.impl.fsl.hid0 = vcpu_e500->hid0;
0373 sregs->u.e.impl.fsl.mcar = vcpu_e500->mcar;
0374
0375 sregs->u.e.ivor_high[0] = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL];
0376 sregs->u.e.ivor_high[1] = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_DATA];
0377 sregs->u.e.ivor_high[2] = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND];
0378 sregs->u.e.ivor_high[3] =
0379 vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR];
0380
0381 kvmppc_get_sregs_ivor(vcpu, sregs);
0382 kvmppc_get_sregs_e500_tlb(vcpu, sregs);
0383 return 0;
0384 }
0385
0386 static int kvmppc_core_set_sregs_e500(struct kvm_vcpu *vcpu,
0387 struct kvm_sregs *sregs)
0388 {
0389 struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
0390 int ret;
0391
0392 if (sregs->u.e.impl_id == KVM_SREGS_E_IMPL_FSL) {
0393 vcpu_e500->svr = sregs->u.e.impl.fsl.svr;
0394 vcpu_e500->hid0 = sregs->u.e.impl.fsl.hid0;
0395 vcpu_e500->mcar = sregs->u.e.impl.fsl.mcar;
0396 }
0397
0398 ret = kvmppc_set_sregs_e500_tlb(vcpu, sregs);
0399 if (ret < 0)
0400 return ret;
0401
0402 if (!(sregs->u.e.features & KVM_SREGS_E_IVOR))
0403 return 0;
0404
0405 if (sregs->u.e.features & KVM_SREGS_E_SPE) {
0406 vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL] =
0407 sregs->u.e.ivor_high[0];
0408 vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_DATA] =
0409 sregs->u.e.ivor_high[1];
0410 vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND] =
0411 sregs->u.e.ivor_high[2];
0412 }
0413
0414 if (sregs->u.e.features & KVM_SREGS_E_PM) {
0415 vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR] =
0416 sregs->u.e.ivor_high[3];
0417 }
0418
0419 return kvmppc_set_sregs_ivor(vcpu, sregs);
0420 }
0421
0422 static int kvmppc_get_one_reg_e500(struct kvm_vcpu *vcpu, u64 id,
0423 union kvmppc_one_reg *val)
0424 {
0425 int r = kvmppc_get_one_reg_e500_tlb(vcpu, id, val);
0426 return r;
0427 }
0428
0429 static int kvmppc_set_one_reg_e500(struct kvm_vcpu *vcpu, u64 id,
0430 union kvmppc_one_reg *val)
0431 {
0432 int r = kvmppc_get_one_reg_e500_tlb(vcpu, id, val);
0433 return r;
0434 }
0435
0436 static int kvmppc_core_vcpu_create_e500(struct kvm_vcpu *vcpu)
0437 {
0438 struct kvmppc_vcpu_e500 *vcpu_e500;
0439 int err;
0440
0441 BUILD_BUG_ON(offsetof(struct kvmppc_vcpu_e500, vcpu) != 0);
0442 vcpu_e500 = to_e500(vcpu);
0443
0444 if (kvmppc_e500_id_table_alloc(vcpu_e500) == NULL)
0445 return -ENOMEM;
0446
0447 err = kvmppc_e500_tlb_init(vcpu_e500);
0448 if (err)
0449 goto uninit_id;
0450
0451 vcpu->arch.shared = (void*)__get_free_page(GFP_KERNEL|__GFP_ZERO);
0452 if (!vcpu->arch.shared) {
0453 err = -ENOMEM;
0454 goto uninit_tlb;
0455 }
0456
0457 return 0;
0458
0459 uninit_tlb:
0460 kvmppc_e500_tlb_uninit(vcpu_e500);
0461 uninit_id:
0462 kvmppc_e500_id_table_free(vcpu_e500);
0463 return err;
0464 }
0465
0466 static void kvmppc_core_vcpu_free_e500(struct kvm_vcpu *vcpu)
0467 {
0468 struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
0469
0470 free_page((unsigned long)vcpu->arch.shared);
0471 kvmppc_e500_tlb_uninit(vcpu_e500);
0472 kvmppc_e500_id_table_free(vcpu_e500);
0473 }
0474
0475 static int kvmppc_core_init_vm_e500(struct kvm *kvm)
0476 {
0477 return 0;
0478 }
0479
0480 static void kvmppc_core_destroy_vm_e500(struct kvm *kvm)
0481 {
0482 }
0483
0484 static struct kvmppc_ops kvm_ops_e500 = {
0485 .get_sregs = kvmppc_core_get_sregs_e500,
0486 .set_sregs = kvmppc_core_set_sregs_e500,
0487 .get_one_reg = kvmppc_get_one_reg_e500,
0488 .set_one_reg = kvmppc_set_one_reg_e500,
0489 .vcpu_load = kvmppc_core_vcpu_load_e500,
0490 .vcpu_put = kvmppc_core_vcpu_put_e500,
0491 .vcpu_create = kvmppc_core_vcpu_create_e500,
0492 .vcpu_free = kvmppc_core_vcpu_free_e500,
0493 .init_vm = kvmppc_core_init_vm_e500,
0494 .destroy_vm = kvmppc_core_destroy_vm_e500,
0495 .emulate_op = kvmppc_core_emulate_op_e500,
0496 .emulate_mtspr = kvmppc_core_emulate_mtspr_e500,
0497 .emulate_mfspr = kvmppc_core_emulate_mfspr_e500,
0498 .create_vcpu_debugfs = kvmppc_create_vcpu_debugfs_e500,
0499 };
0500
0501 static int __init kvmppc_e500_init(void)
0502 {
0503 int r, i;
0504 unsigned long ivor[3];
0505
0506 unsigned long *handler = &kvmppc_booke_handler_addr[16];
0507 unsigned long handler_len;
0508 unsigned long max_ivor = 0;
0509
0510 r = kvmppc_core_check_processor_compat();
0511 if (r)
0512 goto err_out;
0513
0514 r = kvmppc_booke_init();
0515 if (r)
0516 goto err_out;
0517
0518
0519 ivor[0] = mfspr(SPRN_IVOR32);
0520 ivor[1] = mfspr(SPRN_IVOR33);
0521 ivor[2] = mfspr(SPRN_IVOR34);
0522 for (i = 0; i < 3; i++) {
0523 if (ivor[i] > ivor[max_ivor])
0524 max_ivor = i;
0525
0526 handler_len = handler[i + 1] - handler[i];
0527 memcpy((void *)kvmppc_booke_handlers + ivor[i],
0528 (void *)handler[i], handler_len);
0529 }
0530 handler_len = handler[max_ivor + 1] - handler[max_ivor];
0531 flush_icache_range(kvmppc_booke_handlers, kvmppc_booke_handlers +
0532 ivor[max_ivor] + handler_len);
0533
0534 r = kvm_init(NULL, sizeof(struct kvmppc_vcpu_e500), 0, THIS_MODULE);
0535 if (r)
0536 goto err_out;
0537 kvm_ops_e500.owner = THIS_MODULE;
0538 kvmppc_pr_ops = &kvm_ops_e500;
0539
0540 err_out:
0541 return r;
0542 }
0543
0544 static void __exit kvmppc_e500_exit(void)
0545 {
0546 kvmppc_pr_ops = NULL;
0547 kvmppc_booke_exit();
0548 }
0549
0550 module_init(kvmppc_e500_init);
0551 module_exit(kvmppc_e500_exit);
0552 MODULE_ALIAS_MISCDEV(KVM_MINOR);
0553 MODULE_ALIAS("devname:kvm");