1/* 2 * This program is free software; you can redistribute it and/or modify 3 * it under the terms of the GNU General Public License, version 2, as 4 * published by the Free Software Foundation. 5 * 6 * This program is distributed in the hope that it will be useful, 7 * but WITHOUT ANY WARRANTY; without even the implied warranty of 8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 9 * GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License 12 * along with this program; if not, write to the Free Software 13 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 14 * 15 * Copyright IBM Corp. 2008 16 * 17 * Authors: Hollis Blanchard <hollisb@us.ibm.com> 18 */ 19 20#include <linux/kvm_host.h> 21#include <linux/slab.h> 22#include <linux/err.h> 23 24#include <asm/reg.h> 25#include <asm/cputable.h> 26#include <asm/tlbflush.h> 27#include <asm/kvm_44x.h> 28#include <asm/kvm_ppc.h> 29 30#include "44x_tlb.h" 31 32void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu) 33{ 34 kvmppc_44x_tlb_load(vcpu); 35} 36 37void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu) 38{ 39 kvmppc_44x_tlb_put(vcpu); 40} 41 42int kvmppc_core_check_processor_compat(void) 43{ 44 int r; 45 46 if (strcmp(cur_cpu_spec->platform, "ppc440") == 0) 47 r = 0; 48 else 49 r = -ENOTSUPP; 50 51 return r; 52} 53 54int kvmppc_core_vcpu_setup(struct kvm_vcpu *vcpu) 55{ 56 struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); 57 struct kvmppc_44x_tlbe *tlbe = &vcpu_44x->guest_tlb[0]; 58 int i; 59 60 tlbe->tid = 0; 61 tlbe->word0 = PPC44x_TLB_16M | PPC44x_TLB_VALID; 62 tlbe->word1 = 0; 63 tlbe->word2 = PPC44x_TLB_SX | PPC44x_TLB_SW | PPC44x_TLB_SR; 64 65 tlbe++; 66 tlbe->tid = 0; 67 tlbe->word0 = 0xef600000 | PPC44x_TLB_4K | PPC44x_TLB_VALID; 68 tlbe->word1 = 0xef600000; 69 tlbe->word2 = PPC44x_TLB_SX | PPC44x_TLB_SW | PPC44x_TLB_SR 70 | PPC44x_TLB_I | PPC44x_TLB_G; 71 72 /* Since the guest can directly access the timebase, it must know the 73 * real timebase frequency. Accordingly, it must see the state of 74 * CCR1[TCS]. */ 75 vcpu->arch.ccr1 = mfspr(SPRN_CCR1); 76 77 for (i = 0; i < ARRAY_SIZE(vcpu_44x->shadow_refs); i++) 78 vcpu_44x->shadow_refs[i].gtlb_index = -1; 79 80 return 0; 81} 82 83/* 'linear_address' is actually an encoding of AS|PID|EADDR . */ 84int kvmppc_core_vcpu_translate(struct kvm_vcpu *vcpu, 85 struct kvm_translation *tr) 86{ 87 int index; 88 gva_t eaddr; 89 u8 pid; 90 u8 as; 91 92 eaddr = tr->linear_address; 93 pid = (tr->linear_address >> 32) & 0xff; 94 as = (tr->linear_address >> 40) & 0x1; 95 96 index = kvmppc_44x_tlb_index(vcpu, eaddr, pid, as); 97 if (index == -1) { 98 tr->valid = 0; 99 return 0; 100 } 101 102 tr->physical_address = kvmppc_mmu_xlate(vcpu, index, eaddr); 103 tr->valid = 1; 104 105 return 0; 106} 107 108struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id) 109{ 110 struct kvmppc_vcpu_44x *vcpu_44x; 111 struct kvm_vcpu *vcpu; 112 int err; 113 114 vcpu_44x = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL); 115 if (!vcpu_44x) { 116 err = -ENOMEM; 117 goto out; 118 } 119 120 vcpu = &vcpu_44x->vcpu; 121 err = kvm_vcpu_init(vcpu, kvm, id); 122 if (err) 123 goto free_vcpu; 124 125 return vcpu; 126 127free_vcpu: 128 kmem_cache_free(kvm_vcpu_cache, vcpu_44x); 129out: 130 return ERR_PTR(err); 131} 132 133void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu) 134{ 135 struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); 136 137 kvm_vcpu_uninit(vcpu); 138 kmem_cache_free(kvm_vcpu_cache, vcpu_44x); 139} 140 141static int __init kvmppc_44x_init(void) 142{ 143 int r; 144 145 r = kvmppc_booke_init(); 146 if (r) 147 return r; 148 149 return kvm_init(NULL, sizeof(struct kvmppc_vcpu_44x), 0, THIS_MODULE); 150} 151 152static void __exit kvmppc_44x_exit(void) 153{ 154 kvmppc_booke_exit(); 155} 156 157module_init(kvmppc_44x_init); 158module_exit(kvmppc_44x_exit); 159