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 v5.0-rc4 178 lines 5.4 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/mm.h> 20#include <linux/kvm_host.h> 21#include <asm/kvm_arm.h> 22#include <asm/kvm_emulate.h> 23#include <asm/opcodes.h> 24#include <trace/events/kvm.h> 25 26#include "trace.h" 27 28#define VCPU_NR_MODES 6 29#define VCPU_REG_OFFSET_USR 0 30#define VCPU_REG_OFFSET_FIQ 1 31#define VCPU_REG_OFFSET_IRQ 2 32#define VCPU_REG_OFFSET_SVC 3 33#define VCPU_REG_OFFSET_ABT 4 34#define VCPU_REG_OFFSET_UND 5 35#define REG_OFFSET(_reg) \ 36 (offsetof(struct kvm_regs, _reg) / sizeof(u32)) 37 38#define USR_REG_OFFSET(_num) REG_OFFSET(usr_regs.uregs[_num]) 39 40static const unsigned long vcpu_reg_offsets[VCPU_NR_MODES][15] = { 41 /* USR/SYS Registers */ 42 [VCPU_REG_OFFSET_USR] = { 43 USR_REG_OFFSET(0), USR_REG_OFFSET(1), USR_REG_OFFSET(2), 44 USR_REG_OFFSET(3), USR_REG_OFFSET(4), USR_REG_OFFSET(5), 45 USR_REG_OFFSET(6), USR_REG_OFFSET(7), USR_REG_OFFSET(8), 46 USR_REG_OFFSET(9), USR_REG_OFFSET(10), USR_REG_OFFSET(11), 47 USR_REG_OFFSET(12), USR_REG_OFFSET(13), USR_REG_OFFSET(14), 48 }, 49 50 /* FIQ Registers */ 51 [VCPU_REG_OFFSET_FIQ] = { 52 USR_REG_OFFSET(0), USR_REG_OFFSET(1), USR_REG_OFFSET(2), 53 USR_REG_OFFSET(3), USR_REG_OFFSET(4), USR_REG_OFFSET(5), 54 USR_REG_OFFSET(6), USR_REG_OFFSET(7), 55 REG_OFFSET(fiq_regs[0]), /* r8 */ 56 REG_OFFSET(fiq_regs[1]), /* r9 */ 57 REG_OFFSET(fiq_regs[2]), /* r10 */ 58 REG_OFFSET(fiq_regs[3]), /* r11 */ 59 REG_OFFSET(fiq_regs[4]), /* r12 */ 60 REG_OFFSET(fiq_regs[5]), /* r13 */ 61 REG_OFFSET(fiq_regs[6]), /* r14 */ 62 }, 63 64 /* IRQ Registers */ 65 [VCPU_REG_OFFSET_IRQ] = { 66 USR_REG_OFFSET(0), USR_REG_OFFSET(1), USR_REG_OFFSET(2), 67 USR_REG_OFFSET(3), USR_REG_OFFSET(4), USR_REG_OFFSET(5), 68 USR_REG_OFFSET(6), USR_REG_OFFSET(7), USR_REG_OFFSET(8), 69 USR_REG_OFFSET(9), USR_REG_OFFSET(10), USR_REG_OFFSET(11), 70 USR_REG_OFFSET(12), 71 REG_OFFSET(irq_regs[0]), /* r13 */ 72 REG_OFFSET(irq_regs[1]), /* r14 */ 73 }, 74 75 /* SVC Registers */ 76 [VCPU_REG_OFFSET_SVC] = { 77 USR_REG_OFFSET(0), USR_REG_OFFSET(1), USR_REG_OFFSET(2), 78 USR_REG_OFFSET(3), USR_REG_OFFSET(4), USR_REG_OFFSET(5), 79 USR_REG_OFFSET(6), USR_REG_OFFSET(7), USR_REG_OFFSET(8), 80 USR_REG_OFFSET(9), USR_REG_OFFSET(10), USR_REG_OFFSET(11), 81 USR_REG_OFFSET(12), 82 REG_OFFSET(svc_regs[0]), /* r13 */ 83 REG_OFFSET(svc_regs[1]), /* r14 */ 84 }, 85 86 /* ABT Registers */ 87 [VCPU_REG_OFFSET_ABT] = { 88 USR_REG_OFFSET(0), USR_REG_OFFSET(1), USR_REG_OFFSET(2), 89 USR_REG_OFFSET(3), USR_REG_OFFSET(4), USR_REG_OFFSET(5), 90 USR_REG_OFFSET(6), USR_REG_OFFSET(7), USR_REG_OFFSET(8), 91 USR_REG_OFFSET(9), USR_REG_OFFSET(10), USR_REG_OFFSET(11), 92 USR_REG_OFFSET(12), 93 REG_OFFSET(abt_regs[0]), /* r13 */ 94 REG_OFFSET(abt_regs[1]), /* r14 */ 95 }, 96 97 /* UND Registers */ 98 [VCPU_REG_OFFSET_UND] = { 99 USR_REG_OFFSET(0), USR_REG_OFFSET(1), USR_REG_OFFSET(2), 100 USR_REG_OFFSET(3), USR_REG_OFFSET(4), USR_REG_OFFSET(5), 101 USR_REG_OFFSET(6), USR_REG_OFFSET(7), USR_REG_OFFSET(8), 102 USR_REG_OFFSET(9), USR_REG_OFFSET(10), USR_REG_OFFSET(11), 103 USR_REG_OFFSET(12), 104 REG_OFFSET(und_regs[0]), /* r13 */ 105 REG_OFFSET(und_regs[1]), /* r14 */ 106 }, 107}; 108 109/* 110 * Return a pointer to the register number valid in the current mode of 111 * the virtual CPU. 112 */ 113unsigned long *vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num) 114{ 115 unsigned long *reg_array = (unsigned long *)&vcpu->arch.ctxt.gp_regs; 116 unsigned long mode = *vcpu_cpsr(vcpu) & MODE_MASK; 117 118 switch (mode) { 119 case USR_MODE...SVC_MODE: 120 mode &= ~MODE32_BIT; /* 0 ... 3 */ 121 break; 122 123 case ABT_MODE: 124 mode = VCPU_REG_OFFSET_ABT; 125 break; 126 127 case UND_MODE: 128 mode = VCPU_REG_OFFSET_UND; 129 break; 130 131 case SYSTEM_MODE: 132 mode = VCPU_REG_OFFSET_USR; 133 break; 134 135 default: 136 BUG(); 137 } 138 139 return reg_array + vcpu_reg_offsets[mode][reg_num]; 140} 141 142/* 143 * Return the SPSR for the current mode of the virtual CPU. 144 */ 145unsigned long *__vcpu_spsr(struct kvm_vcpu *vcpu) 146{ 147 unsigned long mode = *vcpu_cpsr(vcpu) & MODE_MASK; 148 switch (mode) { 149 case SVC_MODE: 150 return &vcpu->arch.ctxt.gp_regs.KVM_ARM_SVC_spsr; 151 case ABT_MODE: 152 return &vcpu->arch.ctxt.gp_regs.KVM_ARM_ABT_spsr; 153 case UND_MODE: 154 return &vcpu->arch.ctxt.gp_regs.KVM_ARM_UND_spsr; 155 case IRQ_MODE: 156 return &vcpu->arch.ctxt.gp_regs.KVM_ARM_IRQ_spsr; 157 case FIQ_MODE: 158 return &vcpu->arch.ctxt.gp_regs.KVM_ARM_FIQ_spsr; 159 default: 160 BUG(); 161 } 162} 163 164/****************************************************************************** 165 * Inject exceptions into the guest 166 */ 167 168/** 169 * kvm_inject_vabt - inject an async abort / SError into the guest 170 * @vcpu: The VCPU to receive the exception 171 * 172 * It is assumed that this code is called from the VCPU thread and that the 173 * VCPU therefore is not currently executing guest code. 174 */ 175void kvm_inject_vabt(struct kvm_vcpu *vcpu) 176{ 177 *vcpu_hcr(vcpu) |= HCR_VA; 178}