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 v2.6.38-rc4 167 lines 3.9 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 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 (strncmp(cur_cpu_spec->platform, "ppc440", 6) == 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 /* XXX CCR1 doesn't exist on all 440 SoCs. */ 76 vcpu->arch.ccr1 = mfspr(SPRN_CCR1); 77 78 for (i = 0; i < ARRAY_SIZE(vcpu_44x->shadow_refs); i++) 79 vcpu_44x->shadow_refs[i].gtlb_index = -1; 80 81 return 0; 82} 83 84/* 'linear_address' is actually an encoding of AS|PID|EADDR . */ 85int kvmppc_core_vcpu_translate(struct kvm_vcpu *vcpu, 86 struct kvm_translation *tr) 87{ 88 int index; 89 gva_t eaddr; 90 u8 pid; 91 u8 as; 92 93 eaddr = tr->linear_address; 94 pid = (tr->linear_address >> 32) & 0xff; 95 as = (tr->linear_address >> 40) & 0x1; 96 97 index = kvmppc_44x_tlb_index(vcpu, eaddr, pid, as); 98 if (index == -1) { 99 tr->valid = 0; 100 return 0; 101 } 102 103 tr->physical_address = kvmppc_mmu_xlate(vcpu, index, eaddr); 104 /* XXX what does "writeable" and "usermode" even mean? */ 105 tr->valid = 1; 106 107 return 0; 108} 109 110struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id) 111{ 112 struct kvmppc_vcpu_44x *vcpu_44x; 113 struct kvm_vcpu *vcpu; 114 int err; 115 116 vcpu_44x = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL); 117 if (!vcpu_44x) { 118 err = -ENOMEM; 119 goto out; 120 } 121 122 vcpu = &vcpu_44x->vcpu; 123 err = kvm_vcpu_init(vcpu, kvm, id); 124 if (err) 125 goto free_vcpu; 126 127 vcpu->arch.shared = (void*)__get_free_page(GFP_KERNEL|__GFP_ZERO); 128 if (!vcpu->arch.shared) 129 goto uninit_vcpu; 130 131 return vcpu; 132 133uninit_vcpu: 134 kvm_vcpu_uninit(vcpu); 135free_vcpu: 136 kmem_cache_free(kvm_vcpu_cache, vcpu_44x); 137out: 138 return ERR_PTR(err); 139} 140 141void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu) 142{ 143 struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); 144 145 free_page((unsigned long)vcpu->arch.shared); 146 kvm_vcpu_uninit(vcpu); 147 kmem_cache_free(kvm_vcpu_cache, vcpu_44x); 148} 149 150static int __init kvmppc_44x_init(void) 151{ 152 int r; 153 154 r = kvmppc_booke_init(); 155 if (r) 156 return r; 157 158 return kvm_init(NULL, sizeof(struct kvmppc_vcpu_44x), 0, THIS_MODULE); 159} 160 161static void __exit kvmppc_44x_exit(void) 162{ 163 kvmppc_booke_exit(); 164} 165 166module_init(kvmppc_44x_init); 167module_exit(kvmppc_44x_exit);