Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.15 237 lines 5.7 kB view raw
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#include <linux/export.h> 24#include <linux/module.h> 25#include <linux/miscdevice.h> 26 27#include <asm/reg.h> 28#include <asm/cputable.h> 29#include <asm/tlbflush.h> 30#include <asm/kvm_44x.h> 31#include <asm/kvm_ppc.h> 32 33#include "44x_tlb.h" 34#include "booke.h" 35 36static void kvmppc_core_vcpu_load_44x(struct kvm_vcpu *vcpu, int cpu) 37{ 38 kvmppc_booke_vcpu_load(vcpu, cpu); 39 kvmppc_44x_tlb_load(vcpu); 40} 41 42static void kvmppc_core_vcpu_put_44x(struct kvm_vcpu *vcpu) 43{ 44 kvmppc_44x_tlb_put(vcpu); 45 kvmppc_booke_vcpu_put(vcpu); 46} 47 48int kvmppc_core_check_processor_compat(void) 49{ 50 int r; 51 52 if (strncmp(cur_cpu_spec->platform, "ppc440", 6) == 0) 53 r = 0; 54 else 55 r = -ENOTSUPP; 56 57 return r; 58} 59 60int kvmppc_core_vcpu_setup(struct kvm_vcpu *vcpu) 61{ 62 struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); 63 struct kvmppc_44x_tlbe *tlbe = &vcpu_44x->guest_tlb[0]; 64 int i; 65 66 tlbe->tid = 0; 67 tlbe->word0 = PPC44x_TLB_16M | PPC44x_TLB_VALID; 68 tlbe->word1 = 0; 69 tlbe->word2 = PPC44x_TLB_SX | PPC44x_TLB_SW | PPC44x_TLB_SR; 70 71 tlbe++; 72 tlbe->tid = 0; 73 tlbe->word0 = 0xef600000 | PPC44x_TLB_4K | PPC44x_TLB_VALID; 74 tlbe->word1 = 0xef600000; 75 tlbe->word2 = PPC44x_TLB_SX | PPC44x_TLB_SW | PPC44x_TLB_SR 76 | PPC44x_TLB_I | PPC44x_TLB_G; 77 78 /* Since the guest can directly access the timebase, it must know the 79 * real timebase frequency. Accordingly, it must see the state of 80 * CCR1[TCS]. */ 81 /* XXX CCR1 doesn't exist on all 440 SoCs. */ 82 vcpu->arch.ccr1 = mfspr(SPRN_CCR1); 83 84 for (i = 0; i < ARRAY_SIZE(vcpu_44x->shadow_refs); i++) 85 vcpu_44x->shadow_refs[i].gtlb_index = -1; 86 87 vcpu->arch.cpu_type = KVM_CPU_440; 88 vcpu->arch.pvr = mfspr(SPRN_PVR); 89 90 return 0; 91} 92 93/* 'linear_address' is actually an encoding of AS|PID|EADDR . */ 94int kvmppc_core_vcpu_translate(struct kvm_vcpu *vcpu, 95 struct kvm_translation *tr) 96{ 97 int index; 98 gva_t eaddr; 99 u8 pid; 100 u8 as; 101 102 eaddr = tr->linear_address; 103 pid = (tr->linear_address >> 32) & 0xff; 104 as = (tr->linear_address >> 40) & 0x1; 105 106 index = kvmppc_44x_tlb_index(vcpu, eaddr, pid, as); 107 if (index == -1) { 108 tr->valid = 0; 109 return 0; 110 } 111 112 tr->physical_address = kvmppc_mmu_xlate(vcpu, index, eaddr); 113 /* XXX what does "writeable" and "usermode" even mean? */ 114 tr->valid = 1; 115 116 return 0; 117} 118 119static int kvmppc_core_get_sregs_44x(struct kvm_vcpu *vcpu, 120 struct kvm_sregs *sregs) 121{ 122 return kvmppc_get_sregs_ivor(vcpu, sregs); 123} 124 125static int kvmppc_core_set_sregs_44x(struct kvm_vcpu *vcpu, 126 struct kvm_sregs *sregs) 127{ 128 return kvmppc_set_sregs_ivor(vcpu, sregs); 129} 130 131static int kvmppc_get_one_reg_44x(struct kvm_vcpu *vcpu, u64 id, 132 union kvmppc_one_reg *val) 133{ 134 return -EINVAL; 135} 136 137static int kvmppc_set_one_reg_44x(struct kvm_vcpu *vcpu, u64 id, 138 union kvmppc_one_reg *val) 139{ 140 return -EINVAL; 141} 142 143static struct kvm_vcpu *kvmppc_core_vcpu_create_44x(struct kvm *kvm, 144 unsigned int id) 145{ 146 struct kvmppc_vcpu_44x *vcpu_44x; 147 struct kvm_vcpu *vcpu; 148 int err; 149 150 vcpu_44x = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL); 151 if (!vcpu_44x) { 152 err = -ENOMEM; 153 goto out; 154 } 155 156 vcpu = &vcpu_44x->vcpu; 157 err = kvm_vcpu_init(vcpu, kvm, id); 158 if (err) 159 goto free_vcpu; 160 161 vcpu->arch.shared = (void*)__get_free_page(GFP_KERNEL|__GFP_ZERO); 162 if (!vcpu->arch.shared) 163 goto uninit_vcpu; 164 165 return vcpu; 166 167uninit_vcpu: 168 kvm_vcpu_uninit(vcpu); 169free_vcpu: 170 kmem_cache_free(kvm_vcpu_cache, vcpu_44x); 171out: 172 return ERR_PTR(err); 173} 174 175static void kvmppc_core_vcpu_free_44x(struct kvm_vcpu *vcpu) 176{ 177 struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); 178 179 free_page((unsigned long)vcpu->arch.shared); 180 kvm_vcpu_uninit(vcpu); 181 kmem_cache_free(kvm_vcpu_cache, vcpu_44x); 182} 183 184static int kvmppc_core_init_vm_44x(struct kvm *kvm) 185{ 186 return 0; 187} 188 189static void kvmppc_core_destroy_vm_44x(struct kvm *kvm) 190{ 191} 192 193static struct kvmppc_ops kvm_ops_44x = { 194 .get_sregs = kvmppc_core_get_sregs_44x, 195 .set_sregs = kvmppc_core_set_sregs_44x, 196 .get_one_reg = kvmppc_get_one_reg_44x, 197 .set_one_reg = kvmppc_set_one_reg_44x, 198 .vcpu_load = kvmppc_core_vcpu_load_44x, 199 .vcpu_put = kvmppc_core_vcpu_put_44x, 200 .vcpu_create = kvmppc_core_vcpu_create_44x, 201 .vcpu_free = kvmppc_core_vcpu_free_44x, 202 .mmu_destroy = kvmppc_mmu_destroy_44x, 203 .init_vm = kvmppc_core_init_vm_44x, 204 .destroy_vm = kvmppc_core_destroy_vm_44x, 205 .emulate_op = kvmppc_core_emulate_op_44x, 206 .emulate_mtspr = kvmppc_core_emulate_mtspr_44x, 207 .emulate_mfspr = kvmppc_core_emulate_mfspr_44x, 208}; 209 210static int __init kvmppc_44x_init(void) 211{ 212 int r; 213 214 r = kvmppc_booke_init(); 215 if (r) 216 goto err_out; 217 218 r = kvm_init(NULL, sizeof(struct kvmppc_vcpu_44x), 0, THIS_MODULE); 219 if (r) 220 goto err_out; 221 kvm_ops_44x.owner = THIS_MODULE; 222 kvmppc_pr_ops = &kvm_ops_44x; 223 224err_out: 225 return r; 226} 227 228static void __exit kvmppc_44x_exit(void) 229{ 230 kvmppc_pr_ops = NULL; 231 kvmppc_booke_exit(); 232} 233 234module_init(kvmppc_44x_init); 235module_exit(kvmppc_44x_exit); 236MODULE_ALIAS_MISCDEV(KVM_MINOR); 237MODULE_ALIAS("devname:kvm");