1 /* 2 * Copyright (C) 2008 Freescale Semiconductor, Inc. All rights reserved. 3 * 4 * Author: Yu Liu, <yu.liu@freescale.com> 5 * 6 * Description: 7 * This file is derived from arch/powerpc/kvm/44x.c, 8 * by Hollis Blanchard <hollisb@us.ibm.com>. 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License, version 2, as 12 * published by the Free Software Foundation. 13 */ 14 15 #include <linux/kvm_host.h> 16 #include <linux/err.h> 17 18 #include <asm/reg.h> 19 #include <asm/cputable.h> 20 #include <asm/tlbflush.h> 21 #include <asm/kvm_e500.h> 22 #include <asm/kvm_ppc.h> 23 24 #include "booke.h" 25 #include "e500_tlb.h" 26 27 void kvmppc_core_load_host_debugstate(struct kvm_vcpu *vcpu) 28 { 29 } 30 31 void kvmppc_core_load_guest_debugstate(struct kvm_vcpu *vcpu) 32 { 33 } 34 35 void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu) 36 { 37 kvmppc_e500_tlb_load(vcpu, cpu); 38 } 39 40 void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu) 41 { 42 kvmppc_e500_tlb_put(vcpu); 43 } 44 45 int kvmppc_core_check_processor_compat(void) 46 { 47 int r; 48 49 if (strcmp(cur_cpu_spec->cpu_name, "e500v2") == 0) 50 r = 0; 51 else 52 r = -ENOTSUPP; 53 54 return r; 55 } 56 57 int kvmppc_core_vcpu_setup(struct kvm_vcpu *vcpu) 58 { 59 struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); 60 61 kvmppc_e500_tlb_setup(vcpu_e500); 62 63 /* Use the same core vertion as host's */ 64 vcpu->arch.pvr = mfspr(SPRN_PVR); 65 66 return 0; 67 } 68 69 /* 'linear_address' is actually an encoding of AS|PID|EADDR . */ 70 int kvmppc_core_vcpu_translate(struct kvm_vcpu *vcpu, 71 struct kvm_translation *tr) 72 { 73 int index; 74 gva_t eaddr; 75 u8 pid; 76 u8 as; 77 78 eaddr = tr->linear_address; 79 pid = (tr->linear_address >> 32) & 0xff; 80 as = (tr->linear_address >> 40) & 0x1; 81 82 index = kvmppc_e500_tlb_search(vcpu, eaddr, pid, as); 83 if (index < 0) { 84 tr->valid = 0; 85 return 0; 86 } 87 88 tr->physical_address = kvmppc_mmu_xlate(vcpu, index, eaddr); 89 /* XXX what does "writeable" and "usermode" even mean? */ 90 tr->valid = 1; 91 92 return 0; 93 } 94 95 struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id) 96 { 97 struct kvmppc_vcpu_e500 *vcpu_e500; 98 struct kvm_vcpu *vcpu; 99 int err; 100 101 vcpu_e500 = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL); 102 if (!vcpu_e500) { 103 err = -ENOMEM; 104 goto out; 105 } 106 107 vcpu = &vcpu_e500->vcpu; 108 err = kvm_vcpu_init(vcpu, kvm, id); 109 if (err) 110 goto free_vcpu; 111 112 err = kvmppc_e500_tlb_init(vcpu_e500); 113 if (err) 114 goto uninit_vcpu; 115 116 return vcpu; 117 118 uninit_vcpu: 119 kvm_vcpu_uninit(vcpu); 120 free_vcpu: 121 kmem_cache_free(kvm_vcpu_cache, vcpu_e500); 122 out: 123 return ERR_PTR(err); 124 } 125 126 void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu) 127 { 128 struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); 129 130 kvmppc_e500_tlb_uninit(vcpu_e500); 131 kvm_vcpu_uninit(vcpu); 132 kmem_cache_free(kvm_vcpu_cache, vcpu_e500); 133 } 134 135 static int kvmppc_e500_init(void) 136 { 137 int r, i; 138 unsigned long ivor[3]; 139 unsigned long max_ivor = 0; 140 141 r = kvmppc_booke_init(); 142 if (r) 143 return r; 144 145 /* copy extra E500 exception handlers */ 146 ivor[0] = mfspr(SPRN_IVOR32); 147 ivor[1] = mfspr(SPRN_IVOR33); 148 ivor[2] = mfspr(SPRN_IVOR34); 149 for (i = 0; i < 3; i++) { 150 if (ivor[i] > max_ivor) 151 max_ivor = ivor[i]; 152 153 memcpy((void *)kvmppc_booke_handlers + ivor[i], 154 kvmppc_handlers_start + (i + 16) * kvmppc_handler_len, 155 kvmppc_handler_len); 156 } 157 flush_icache_range(kvmppc_booke_handlers, 158 kvmppc_booke_handlers + max_ivor + kvmppc_handler_len); 159 160 return kvm_init(NULL, sizeof(struct kvmppc_vcpu_e500), THIS_MODULE); 161 } 162 163 static void kvmppc_e500_exit(void) 164 { 165 kvmppc_booke_exit(); 166 } 167 168 module_init(kvmppc_e500_init); 169 module_exit(kvmppc_e500_exit); 170