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.19-rc4 310 lines 7.3 kB view raw
1/* 2 * Copyright (C) 2012 - Virtual Open Systems and Columbia University 3 * Author: Christoffer Dall <c.dall@virtualopensystems.com> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License, version 2, as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 */ 18 19#include <linux/errno.h> 20#include <linux/err.h> 21#include <linux/kvm_host.h> 22#include <linux/module.h> 23#include <linux/vmalloc.h> 24#include <linux/fs.h> 25#include <asm/cputype.h> 26#include <asm/uaccess.h> 27#include <asm/kvm.h> 28#include <asm/kvm_asm.h> 29#include <asm/kvm_emulate.h> 30#include <asm/kvm_coproc.h> 31 32#define VM_STAT(x) { #x, offsetof(struct kvm, stat.x), KVM_STAT_VM } 33#define VCPU_STAT(x) { #x, offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU } 34 35struct kvm_stats_debugfs_item debugfs_entries[] = { 36 { NULL } 37}; 38 39int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) 40{ 41 return 0; 42} 43 44static u64 core_reg_offset_from_id(u64 id) 45{ 46 return id & ~(KVM_REG_ARCH_MASK | KVM_REG_SIZE_MASK | KVM_REG_ARM_CORE); 47} 48 49static int get_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) 50{ 51 u32 __user *uaddr = (u32 __user *)(long)reg->addr; 52 struct kvm_regs *regs = &vcpu->arch.regs; 53 u64 off; 54 55 if (KVM_REG_SIZE(reg->id) != 4) 56 return -ENOENT; 57 58 /* Our ID is an index into the kvm_regs struct. */ 59 off = core_reg_offset_from_id(reg->id); 60 if (off >= sizeof(*regs) / KVM_REG_SIZE(reg->id)) 61 return -ENOENT; 62 63 return put_user(((u32 *)regs)[off], uaddr); 64} 65 66static int set_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) 67{ 68 u32 __user *uaddr = (u32 __user *)(long)reg->addr; 69 struct kvm_regs *regs = &vcpu->arch.regs; 70 u64 off, val; 71 72 if (KVM_REG_SIZE(reg->id) != 4) 73 return -ENOENT; 74 75 /* Our ID is an index into the kvm_regs struct. */ 76 off = core_reg_offset_from_id(reg->id); 77 if (off >= sizeof(*regs) / KVM_REG_SIZE(reg->id)) 78 return -ENOENT; 79 80 if (get_user(val, uaddr) != 0) 81 return -EFAULT; 82 83 if (off == KVM_REG_ARM_CORE_REG(usr_regs.ARM_cpsr)) { 84 unsigned long mode = val & MODE_MASK; 85 switch (mode) { 86 case USR_MODE: 87 case FIQ_MODE: 88 case IRQ_MODE: 89 case SVC_MODE: 90 case ABT_MODE: 91 case UND_MODE: 92 break; 93 default: 94 return -EINVAL; 95 } 96 } 97 98 ((u32 *)regs)[off] = val; 99 return 0; 100} 101 102int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) 103{ 104 return -EINVAL; 105} 106 107int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) 108{ 109 return -EINVAL; 110} 111 112#ifndef CONFIG_KVM_ARM_TIMER 113 114#define NUM_TIMER_REGS 0 115 116static int copy_timer_indices(struct kvm_vcpu *vcpu, u64 __user *uindices) 117{ 118 return 0; 119} 120 121static bool is_timer_reg(u64 index) 122{ 123 return false; 124} 125 126#else 127 128#define NUM_TIMER_REGS 3 129 130static bool is_timer_reg(u64 index) 131{ 132 switch (index) { 133 case KVM_REG_ARM_TIMER_CTL: 134 case KVM_REG_ARM_TIMER_CNT: 135 case KVM_REG_ARM_TIMER_CVAL: 136 return true; 137 } 138 return false; 139} 140 141static int copy_timer_indices(struct kvm_vcpu *vcpu, u64 __user *uindices) 142{ 143 if (put_user(KVM_REG_ARM_TIMER_CTL, uindices)) 144 return -EFAULT; 145 uindices++; 146 if (put_user(KVM_REG_ARM_TIMER_CNT, uindices)) 147 return -EFAULT; 148 uindices++; 149 if (put_user(KVM_REG_ARM_TIMER_CVAL, uindices)) 150 return -EFAULT; 151 152 return 0; 153} 154 155#endif 156 157static int set_timer_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) 158{ 159 void __user *uaddr = (void __user *)(long)reg->addr; 160 u64 val; 161 int ret; 162 163 ret = copy_from_user(&val, uaddr, KVM_REG_SIZE(reg->id)); 164 if (ret != 0) 165 return -EFAULT; 166 167 return kvm_arm_timer_set_reg(vcpu, reg->id, val); 168} 169 170static int get_timer_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) 171{ 172 void __user *uaddr = (void __user *)(long)reg->addr; 173 u64 val; 174 175 val = kvm_arm_timer_get_reg(vcpu, reg->id); 176 return copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id)); 177} 178 179static unsigned long num_core_regs(void) 180{ 181 return sizeof(struct kvm_regs) / sizeof(u32); 182} 183 184/** 185 * kvm_arm_num_regs - how many registers do we present via KVM_GET_ONE_REG 186 * 187 * This is for all registers. 188 */ 189unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu) 190{ 191 return num_core_regs() + kvm_arm_num_coproc_regs(vcpu) 192 + NUM_TIMER_REGS; 193} 194 195/** 196 * kvm_arm_copy_reg_indices - get indices of all registers. 197 * 198 * We do core registers right here, then we apppend coproc regs. 199 */ 200int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices) 201{ 202 unsigned int i; 203 const u64 core_reg = KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_CORE; 204 int ret; 205 206 for (i = 0; i < sizeof(struct kvm_regs)/sizeof(u32); i++) { 207 if (put_user(core_reg | i, uindices)) 208 return -EFAULT; 209 uindices++; 210 } 211 212 ret = copy_timer_indices(vcpu, uindices); 213 if (ret) 214 return ret; 215 uindices += NUM_TIMER_REGS; 216 217 return kvm_arm_copy_coproc_indices(vcpu, uindices); 218} 219 220int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) 221{ 222 /* We currently use nothing arch-specific in upper 32 bits */ 223 if ((reg->id & ~KVM_REG_SIZE_MASK) >> 32 != KVM_REG_ARM >> 32) 224 return -EINVAL; 225 226 /* Register group 16 means we want a core register. */ 227 if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE) 228 return get_core_reg(vcpu, reg); 229 230 if (is_timer_reg(reg->id)) 231 return get_timer_reg(vcpu, reg); 232 233 return kvm_arm_coproc_get_reg(vcpu, reg); 234} 235 236int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) 237{ 238 /* We currently use nothing arch-specific in upper 32 bits */ 239 if ((reg->id & ~KVM_REG_SIZE_MASK) >> 32 != KVM_REG_ARM >> 32) 240 return -EINVAL; 241 242 /* Register group 16 means we set a core register. */ 243 if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE) 244 return set_core_reg(vcpu, reg); 245 246 if (is_timer_reg(reg->id)) 247 return set_timer_reg(vcpu, reg); 248 249 return kvm_arm_coproc_set_reg(vcpu, reg); 250} 251 252int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu, 253 struct kvm_sregs *sregs) 254{ 255 return -EINVAL; 256} 257 258int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, 259 struct kvm_sregs *sregs) 260{ 261 return -EINVAL; 262} 263 264int __attribute_const__ kvm_target_cpu(void) 265{ 266 switch (read_cpuid_part()) { 267 case ARM_CPU_PART_CORTEX_A7: 268 return KVM_ARM_TARGET_CORTEX_A7; 269 case ARM_CPU_PART_CORTEX_A15: 270 return KVM_ARM_TARGET_CORTEX_A15; 271 default: 272 return -EINVAL; 273 } 274} 275 276int kvm_vcpu_preferred_target(struct kvm_vcpu_init *init) 277{ 278 int target = kvm_target_cpu(); 279 280 if (target < 0) 281 return -ENODEV; 282 283 memset(init, 0, sizeof(*init)); 284 285 /* 286 * For now, we don't return any features. 287 * In future, we might use features to return target 288 * specific features available for the preferred 289 * target type. 290 */ 291 init->target = (__u32)target; 292 293 return 0; 294} 295 296int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) 297{ 298 return -EINVAL; 299} 300 301int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) 302{ 303 return -EINVAL; 304} 305 306int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu, 307 struct kvm_translation *tr) 308{ 309 return -EINVAL; 310}