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 v4.10-rc2 303 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 <linux/uaccess.h> 27#include <asm/kvm.h> 28#include <asm/kvm_emulate.h> 29#include <asm/kvm_coproc.h> 30 31#define VM_STAT(x) { #x, offsetof(struct kvm, stat.x), KVM_STAT_VM } 32#define VCPU_STAT(x) { #x, offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU } 33 34struct kvm_stats_debugfs_item debugfs_entries[] = { 35 VCPU_STAT(hvc_exit_stat), 36 VCPU_STAT(wfe_exit_stat), 37 VCPU_STAT(wfi_exit_stat), 38 VCPU_STAT(mmio_exit_user), 39 VCPU_STAT(mmio_exit_kernel), 40 VCPU_STAT(exits), 41 { NULL } 42}; 43 44int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) 45{ 46 return 0; 47} 48 49static u64 core_reg_offset_from_id(u64 id) 50{ 51 return id & ~(KVM_REG_ARCH_MASK | KVM_REG_SIZE_MASK | KVM_REG_ARM_CORE); 52} 53 54static int get_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) 55{ 56 u32 __user *uaddr = (u32 __user *)(long)reg->addr; 57 struct kvm_regs *regs = &vcpu->arch.ctxt.gp_regs; 58 u64 off; 59 60 if (KVM_REG_SIZE(reg->id) != 4) 61 return -ENOENT; 62 63 /* Our ID is an index into the kvm_regs struct. */ 64 off = core_reg_offset_from_id(reg->id); 65 if (off >= sizeof(*regs) / KVM_REG_SIZE(reg->id)) 66 return -ENOENT; 67 68 return put_user(((u32 *)regs)[off], uaddr); 69} 70 71static int set_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) 72{ 73 u32 __user *uaddr = (u32 __user *)(long)reg->addr; 74 struct kvm_regs *regs = &vcpu->arch.ctxt.gp_regs; 75 u64 off, val; 76 77 if (KVM_REG_SIZE(reg->id) != 4) 78 return -ENOENT; 79 80 /* Our ID is an index into the kvm_regs struct. */ 81 off = core_reg_offset_from_id(reg->id); 82 if (off >= sizeof(*regs) / KVM_REG_SIZE(reg->id)) 83 return -ENOENT; 84 85 if (get_user(val, uaddr) != 0) 86 return -EFAULT; 87 88 if (off == KVM_REG_ARM_CORE_REG(usr_regs.ARM_cpsr)) { 89 unsigned long mode = val & MODE_MASK; 90 switch (mode) { 91 case USR_MODE: 92 case FIQ_MODE: 93 case IRQ_MODE: 94 case SVC_MODE: 95 case ABT_MODE: 96 case UND_MODE: 97 break; 98 default: 99 return -EINVAL; 100 } 101 } 102 103 ((u32 *)regs)[off] = val; 104 return 0; 105} 106 107int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) 108{ 109 return -EINVAL; 110} 111 112int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) 113{ 114 return -EINVAL; 115} 116 117#define NUM_TIMER_REGS 3 118 119static bool is_timer_reg(u64 index) 120{ 121 switch (index) { 122 case KVM_REG_ARM_TIMER_CTL: 123 case KVM_REG_ARM_TIMER_CNT: 124 case KVM_REG_ARM_TIMER_CVAL: 125 return true; 126 } 127 return false; 128} 129 130static int copy_timer_indices(struct kvm_vcpu *vcpu, u64 __user *uindices) 131{ 132 if (put_user(KVM_REG_ARM_TIMER_CTL, uindices)) 133 return -EFAULT; 134 uindices++; 135 if (put_user(KVM_REG_ARM_TIMER_CNT, uindices)) 136 return -EFAULT; 137 uindices++; 138 if (put_user(KVM_REG_ARM_TIMER_CVAL, uindices)) 139 return -EFAULT; 140 141 return 0; 142} 143 144static int set_timer_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) 145{ 146 void __user *uaddr = (void __user *)(long)reg->addr; 147 u64 val; 148 int ret; 149 150 ret = copy_from_user(&val, uaddr, KVM_REG_SIZE(reg->id)); 151 if (ret != 0) 152 return -EFAULT; 153 154 return kvm_arm_timer_set_reg(vcpu, reg->id, val); 155} 156 157static int get_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 162 val = kvm_arm_timer_get_reg(vcpu, reg->id); 163 return copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id)) ? -EFAULT : 0; 164} 165 166static unsigned long num_core_regs(void) 167{ 168 return sizeof(struct kvm_regs) / sizeof(u32); 169} 170 171/** 172 * kvm_arm_num_regs - how many registers do we present via KVM_GET_ONE_REG 173 * 174 * This is for all registers. 175 */ 176unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu) 177{ 178 return num_core_regs() + kvm_arm_num_coproc_regs(vcpu) 179 + NUM_TIMER_REGS; 180} 181 182/** 183 * kvm_arm_copy_reg_indices - get indices of all registers. 184 * 185 * We do core registers right here, then we append coproc regs. 186 */ 187int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices) 188{ 189 unsigned int i; 190 const u64 core_reg = KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_CORE; 191 int ret; 192 193 for (i = 0; i < sizeof(struct kvm_regs)/sizeof(u32); i++) { 194 if (put_user(core_reg | i, uindices)) 195 return -EFAULT; 196 uindices++; 197 } 198 199 ret = copy_timer_indices(vcpu, uindices); 200 if (ret) 201 return ret; 202 uindices += NUM_TIMER_REGS; 203 204 return kvm_arm_copy_coproc_indices(vcpu, uindices); 205} 206 207int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) 208{ 209 /* We currently use nothing arch-specific in upper 32 bits */ 210 if ((reg->id & ~KVM_REG_SIZE_MASK) >> 32 != KVM_REG_ARM >> 32) 211 return -EINVAL; 212 213 /* Register group 16 means we want a core register. */ 214 if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE) 215 return get_core_reg(vcpu, reg); 216 217 if (is_timer_reg(reg->id)) 218 return get_timer_reg(vcpu, reg); 219 220 return kvm_arm_coproc_get_reg(vcpu, reg); 221} 222 223int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) 224{ 225 /* We currently use nothing arch-specific in upper 32 bits */ 226 if ((reg->id & ~KVM_REG_SIZE_MASK) >> 32 != KVM_REG_ARM >> 32) 227 return -EINVAL; 228 229 /* Register group 16 means we set a core register. */ 230 if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE) 231 return set_core_reg(vcpu, reg); 232 233 if (is_timer_reg(reg->id)) 234 return set_timer_reg(vcpu, reg); 235 236 return kvm_arm_coproc_set_reg(vcpu, reg); 237} 238 239int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu, 240 struct kvm_sregs *sregs) 241{ 242 return -EINVAL; 243} 244 245int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, 246 struct kvm_sregs *sregs) 247{ 248 return -EINVAL; 249} 250 251int __attribute_const__ kvm_target_cpu(void) 252{ 253 switch (read_cpuid_part()) { 254 case ARM_CPU_PART_CORTEX_A7: 255 return KVM_ARM_TARGET_CORTEX_A7; 256 case ARM_CPU_PART_CORTEX_A15: 257 return KVM_ARM_TARGET_CORTEX_A15; 258 default: 259 return -EINVAL; 260 } 261} 262 263int kvm_vcpu_preferred_target(struct kvm_vcpu_init *init) 264{ 265 int target = kvm_target_cpu(); 266 267 if (target < 0) 268 return -ENODEV; 269 270 memset(init, 0, sizeof(*init)); 271 272 /* 273 * For now, we don't return any features. 274 * In future, we might use features to return target 275 * specific features available for the preferred 276 * target type. 277 */ 278 init->target = (__u32)target; 279 280 return 0; 281} 282 283int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) 284{ 285 return -EINVAL; 286} 287 288int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) 289{ 290 return -EINVAL; 291} 292 293int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu, 294 struct kvm_translation *tr) 295{ 296 return -EINVAL; 297} 298 299int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu, 300 struct kvm_guest_debug *dbg) 301{ 302 return -EINVAL; 303}