linux kvm c代码,代码阅读 - Linux\kernel\linux-5.0\arch\arm\kvm\emulate.c

/*

* Copyright (C) 2012 - Virtual Open Systems and Columbia University

* Author: Christoffer Dall *

* This program is free software; you can redistribute it and/or modify

* it under the terms of the GNU General Public License, version 2, as

* published by the Free Software Foundation.

*

* This program is distributed in the hope that it will be useful,

* but WITHOUT ANY WARRANTY; without even the implied warranty of

* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

* GNU General Public License for more details.

*

* You should have received a copy of the GNU General Public License

* along with this program; if not, write to the Free Software

* Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

*/

#include

#include

#include

#include

#include

#include

#include "trace.h"

#define VCPU_NR_MODES6

#define VCPU_REG_OFFSET_USR0

#define VCPU_REG_OFFSET_FIQ1

#define VCPU_REG_OFFSET_IRQ2

#define VCPU_REG_OFFSET_SVC3

#define VCPU_REG_OFFSET_ABT4

#define VCPU_REG_OFFSET_UND5

#define REG_OFFSET(_reg) \

(offsetof(struct kvm_regs, _reg) / sizeof(u32))

#define USR_REG_OFFSET(_num) REG_OFFSET(usr_regs.uregs[_num])

static const unsigned long vcpu_reg_offsets[VCPU_NR_MODES][15] = {

/* USR/SYS Registers */

[VCPU_REG_OFFSET_USR] = {

USR_REG_OFFSET(0), USR_REG_OFFSET(1), USR_REG_OFFSET(2),

USR_REG_OFFSET(3), USR_REG_OFFSET(4), USR_REG_OFFSET(5),

USR_REG_OFFSET(6), USR_REG_OFFSET(7), USR_REG_OFFSET(8),

USR_REG_OFFSET(9), USR_REG_OFFSET(10), USR_REG_OFFSET(11),

USR_REG_OFFSET(12), USR_REG_OFFSET(13),USR_REG_OFFSET(14),

},

/* FIQ Registers */

[VCPU_REG_OFFSET_FIQ] = {

USR_REG_OFFSET(0), USR_REG_OFFSET(1), USR_REG_OFFSET(2),

USR_REG_OFFSET(3), USR_REG_OFFSET(4), USR_REG_OFFSET(5),

USR_REG_OFFSET(6), USR_REG_OFFSET(7),

REG_OFFSET(fiq_regs[0]), /* r8 */

REG_OFFSET(fiq_regs[1]), /* r9 */

REG_OFFSET(fiq_regs[2]), /* r10 */

REG_OFFSET(fiq_regs[3]), /* r11 */

REG_OFFSET(fiq_regs[4]), /* r12 */

REG_OFFSET(fiq_regs[5]), /* r13 */

REG_OFFSET(fiq_regs[6]), /* r14 */

},

/* IRQ Registers */

[VCPU_REG_OFFSET_IRQ] = {

USR_REG_OFFSET(0), USR_REG_OFFSET(1), USR_REG_OFFSET(2),

USR_REG_OFFSET(3), USR_REG_OFFSET(4), USR_REG_OFFSET(5),

USR_REG_OFFSET(6), USR_REG_OFFSET(7), USR_REG_OFFSET(8),

USR_REG_OFFSET(9), USR_REG_OFFSET(10), USR_REG_OFFSET(11),

USR_REG_OFFSET(12),

REG_OFFSET(irq_regs[0]), /* r13 */

REG_OFFSET(irq_regs[1]), /* r14 */

},

/* SVC Registers */

[VCPU_REG_OFFSET_SVC] = {

USR_REG_OFFSET(0), USR_REG_OFFSET(1), USR_REG_OFFSET(2),

USR_REG_OFFSET(3), USR_REG_OFFSET(4), USR_REG_OFFSET(5),

USR_REG_OFFSET(6), USR_REG_OFFSET(7), USR_REG_OFFSET(8),

USR_REG_OFFSET(9), USR_REG_OFFSET(10), USR_REG_OFFSET(11),

USR_REG_OFFSET(12),

REG_OFFSET(svc_regs[0]), /* r13 */

REG_OFFSET(svc_regs[1]), /* r14 */

},

/* ABT Registers */

[VCPU_REG_OFFSET_ABT] = {

USR_REG_OFFSET(0), USR_REG_OFFSET(1), USR_REG_OFFSET(2),

USR_REG_OFFSET(3), USR_REG_OFFSET(4), USR_REG_OFFSET(5),

USR_REG_OFFSET(6), USR_REG_OFFSET(7), USR_REG_OFFSET(8),

USR_REG_OFFSET(9), USR_REG_OFFSET(10), USR_REG_OFFSET(11),

USR_REG_OFFSET(12),

REG_OFFSET(abt_regs[0]), /* r13 */

REG_OFFSET(abt_regs[1]), /* r14 */

},

/* UND Registers */

[VCPU_REG_OFFSET_UND] = {

USR_REG_OFFSET(0), USR_REG_OFFSET(1), USR_REG_OFFSET(2),

USR_REG_OFFSET(3), USR_REG_OFFSET(4), USR_REG_OFFSET(5),

USR_REG_OFFSET(6), USR_REG_OFFSET(7), USR_REG_OFFSET(8),

USR_REG_OFFSET(9), USR_REG_OFFSET(10), USR_REG_OFFSET(11),

USR_REG_OFFSET(12),

REG_OFFSET(und_regs[0]), /* r13 */

REG_OFFSET(und_regs[1]), /* r14 */

},

};

/*

* Return a pointer to the register number valid in the current mode of

* the virtual CPU.

*/

unsigned long *vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num)

{

unsigned long *reg_array = (unsigned long *)&vcpu->arch.ctxt.gp_regs;

unsigned long mode = *vcpu_cpsr(vcpu) & MODE_MASK;

switch (mode) {

case USR_MODE...SVC_MODE:

mode &= ~MODE32_BIT; /* 0 ... 3 */

break;

case ABT_MODE:

mode = VCPU_REG_OFFSET_ABT;

break;

case UND_MODE:

mode = VCPU_REG_OFFSET_UND;

break;

case SYSTEM_MODE:

mode = VCPU_REG_OFFSET_USR;

break;

default:

BUG();

}

return reg_array + vcpu_reg_offsets[mode][reg_num];

}

/*

* Return the SPSR for the current mode of the virtual CPU.

*/

unsigned long *__vcpu_spsr(struct kvm_vcpu *vcpu)

{

unsigned long mode = *vcpu_cpsr(vcpu) & MODE_MASK;

switch (mode) {

case SVC_MODE:

return &vcpu->arch.ctxt.gp_regs.KVM_ARM_SVC_spsr;

case ABT_MODE:

return &vcpu->arch.ctxt.gp_regs.KVM_ARM_ABT_spsr;

case UND_MODE:

return &vcpu->arch.ctxt.gp_regs.KVM_ARM_UND_spsr;

case IRQ_MODE:

return &vcpu->arch.ctxt.gp_regs.KVM_ARM_IRQ_spsr;

case FIQ_MODE:

return &vcpu->arch.ctxt.gp_regs.KVM_ARM_FIQ_spsr;

default:

BUG();

}

}

/******************************************************************************

* Inject exceptions into the guest

*/

/**

* kvm_inject_vabt - inject an async abort / SError into the guest

* @vcpu: The VCPU to receive the exception

*

* It is assumed that this code is called from the VCPU thread and that the

* VCPU therefore is not currently executing guest code.

*/

void kvm_inject_vabt(struct kvm_vcpu *vcpu)

{

*vcpu_hcr(vcpu) |= HCR_VA;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值