2013-01-21 03:28:06 +04:00
/*
* Copyright ( C ) 2012 - Virtual Open Systems and Columbia University
* Author : Christoffer Dall < c . dall @ virtualopensystems . com >
*
* 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 <linux/compiler.h>
# include <linux/errno.h>
# include <linux/sched.h>
# include <linux/kvm_host.h>
# include <linux/kvm.h>
# include <asm/unified.h>
# include <asm/ptrace.h>
# include <asm/cputype.h>
# include <asm/kvm_arm.h>
# include <asm/kvm_coproc.h>
2018-12-20 14:36:07 +03:00
# include <asm/kvm_emulate.h>
2013-01-21 03:28:06 +04:00
2013-04-30 10:32:15 +04:00
# include <kvm/arm_arch_timer.h>
2013-01-21 03:28:06 +04:00
/******************************************************************************
2013-09-26 19:49:28 +04:00
* Cortex - A15 and Cortex - A7 Reset Values
2013-01-21 03:28:06 +04:00
*/
2013-09-26 19:49:28 +04:00
static struct kvm_regs cortexa_regs_reset = {
2013-01-21 03:28:06 +04:00
. usr_regs . ARM_cpsr = SVC_MODE | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT ,
} ;
/*******************************************************************************
* Exported reset function
*/
/**
* kvm_reset_vcpu - sets core registers and cp15 registers to reset value
* @ vcpu : The VCPU pointer
*
* This function finds the right table above and sets the registers on the
2016-05-21 14:48:35 +03:00
* virtual CPU struct to their architecturally defined reset values .
2013-01-21 03:28:06 +04:00
*/
int kvm_reset_vcpu ( struct kvm_vcpu * vcpu )
{
2013-09-12 02:27:41 +04:00
struct kvm_regs * reset_regs ;
2013-01-21 03:28:06 +04:00
switch ( vcpu - > arch . target ) {
2013-09-26 19:49:28 +04:00
case KVM_ARM_TARGET_CORTEX_A7 :
2013-01-21 03:28:06 +04:00
case KVM_ARM_TARGET_CORTEX_A15 :
2013-10-17 18:04:47 +04:00
reset_regs = & cortexa_regs_reset ;
2013-01-21 03:28:06 +04:00
vcpu - > arch . midr = read_cpuid_id ( ) ;
break ;
default :
return - ENODEV ;
}
/* Reset core registers */
2016-01-03 14:26:01 +03:00
memcpy ( & vcpu - > arch . ctxt . gp_regs , reset_regs , sizeof ( vcpu - > arch . ctxt . gp_regs ) ) ;
2013-01-21 03:28:06 +04:00
/* Reset CP15 registers */
kvm_reset_coprocs ( vcpu ) ;
2018-12-20 14:36:07 +03:00
/*
* Additional reset state handling that PSCI may have imposed on us .
* Must be done after all the sys_reg reset .
*/
if ( READ_ONCE ( vcpu - > arch . reset_state . reset ) ) {
unsigned long target_pc = vcpu - > arch . reset_state . pc ;
/* Gracefully handle Thumb2 entry point */
if ( target_pc & 1 ) {
target_pc & = ~ 1UL ;
vcpu_set_thumb ( vcpu ) ;
}
/* Propagate caller endianness */
if ( vcpu - > arch . reset_state . be )
kvm_vcpu_set_be ( vcpu ) ;
* vcpu_pc ( vcpu ) = target_pc ;
vcpu_set_reg ( vcpu , 0 , vcpu - > arch . reset_state . r0 ) ;
vcpu - > arch . reset_state . reset = false ;
}
2013-04-30 10:32:15 +04:00
/* Reset arch_timer context */
2017-05-02 21:14:06 +03:00
return kvm_timer_vcpu_reset ( vcpu ) ;
2013-01-21 03:28:06 +04:00
}