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