2012-12-10 20:23:59 +04:00
/*
* Copyright ( C ) 2012 , 2013 - ARM Ltd
* Author : Marc Zyngier < marc . zyngier @ arm . com >
*
* Derived from arch / arm / kvm / reset . c
* 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 , see < http : //www.gnu.org/licenses/>.
*/
# include <linux/errno.h>
# include <linux/kvm_host.h>
# include <linux/kvm.h>
2015-07-07 19:30:02 +03:00
# include <linux/hw_breakpoint.h>
2012-12-10 20:23:59 +04:00
2012-12-07 21:52:03 +04:00
# include <kvm/arm_arch_timer.h>
2012-12-10 20:23:59 +04:00
# include <asm/cputype.h>
# include <asm/ptrace.h>
# include <asm/kvm_arm.h>
arm64: kvm: allows kvm cpu hotplug
The current kvm implementation on arm64 does cpu-specific initialization
at system boot, and has no way to gracefully shutdown a core in terms of
kvm. This prevents kexec from rebooting the system at EL2.
This patch adds a cpu tear-down function and also puts an existing cpu-init
code into a separate function, kvm_arch_hardware_disable() and
kvm_arch_hardware_enable() respectively.
We don't need the arm64 specific cpu hotplug hook any more.
Since this patch modifies common code between arm and arm64, one stub
definition, __cpu_reset_hyp_mode(), is added on arm side to avoid
compilation errors.
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
[Rebase, added separate VHE init/exit path, changed resets use of
kvm_call_hyp() to the __version, en/disabled hardware in init_subsystems(),
added icache maintenance to __kvm_hyp_reset() and removed lr restore, removed
guest-enter after teardown handling]
Signed-off-by: James Morse <james.morse@arm.com>
Acked-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
2016-04-27 19:47:05 +03:00
# include <asm/kvm_asm.h>
2012-12-10 20:23:59 +04:00
# include <asm/kvm_coproc.h>
arm64: kvm: allows kvm cpu hotplug
The current kvm implementation on arm64 does cpu-specific initialization
at system boot, and has no way to gracefully shutdown a core in terms of
kvm. This prevents kexec from rebooting the system at EL2.
This patch adds a cpu tear-down function and also puts an existing cpu-init
code into a separate function, kvm_arch_hardware_disable() and
kvm_arch_hardware_enable() respectively.
We don't need the arm64 specific cpu hotplug hook any more.
Since this patch modifies common code between arm and arm64, one stub
definition, __cpu_reset_hyp_mode(), is added on arm side to avoid
compilation errors.
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
[Rebase, added separate VHE init/exit path, changed resets use of
kvm_call_hyp() to the __version, en/disabled hardware in init_subsystems(),
added icache maintenance to __kvm_hyp_reset() and removed lr restore, removed
guest-enter after teardown handling]
Signed-off-by: James Morse <james.morse@arm.com>
Acked-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
2016-04-27 19:47:05 +03:00
# include <asm/kvm_mmu.h>
2012-12-10 20:23:59 +04:00
/*
* ARMv8 Reset Values
*/
static const struct kvm_regs default_regs_reset = {
. regs . pstate = ( PSR_MODE_EL1h | PSR_A_BIT | PSR_I_BIT |
PSR_F_BIT | PSR_D_BIT ) ,
} ;
2013-02-07 14:46:46 +04:00
static const struct kvm_regs default_regs_reset32 = {
. regs . pstate = ( COMPAT_PSR_MODE_SVC | COMPAT_PSR_A_BIT |
COMPAT_PSR_I_BIT | COMPAT_PSR_F_BIT ) ,
} ;
2017-02-03 18:20:03 +03:00
static const struct kvm_irq_level default_ptimer_irq = {
. irq = 30 ,
. level = 1 ,
} ;
2012-12-07 21:52:03 +04:00
static const struct kvm_irq_level default_vtimer_irq = {
. irq = 27 ,
. level = 1 ,
} ;
2013-02-07 14:46:46 +04:00
static bool cpu_has_32bit_el1 ( void )
{
u64 pfr0 ;
2015-10-19 16:24:55 +03:00
pfr0 = read_system_reg ( SYS_ID_AA64PFR0_EL1 ) ;
2013-02-07 14:46:46 +04:00
return ! ! ( pfr0 & 0x20 ) ;
}
2015-07-07 19:30:02 +03:00
/**
* kvm_arch_dev_ioctl_check_extension
*
* We currently assume that the number of HW registers is uniform
* across all CPUs ( see cpuinfo_sanity_check ) .
*/
2016-07-15 14:43:25 +03:00
int kvm_arch_dev_ioctl_check_extension ( struct kvm * kvm , long ext )
2012-12-10 20:23:59 +04:00
{
int r ;
switch ( ext ) {
2013-02-07 14:46:46 +04:00
case KVM_CAP_ARM_EL1_32BIT :
r = cpu_has_32bit_el1 ( ) ;
break ;
2015-07-07 19:30:02 +03:00
case KVM_CAP_GUEST_DEBUG_HW_BPS :
r = get_num_brps ( ) ;
break ;
case KVM_CAP_GUEST_DEBUG_HW_WPS :
r = get_num_wrps ( ) ;
break ;
2016-01-11 17:46:15 +03:00
case KVM_CAP_ARM_PMU_V3 :
r = kvm_arm_support_pmu_v3 ( ) ;
break ;
2015-07-07 19:30:02 +03:00
case KVM_CAP_SET_GUEST_DEBUG :
2016-01-11 15:56:17 +03:00
case KVM_CAP_VCPU_ATTRIBUTES :
2015-07-07 19:30:02 +03:00
r = 1 ;
break ;
2012-12-10 20:23:59 +04:00
default :
r = 0 ;
}
return r ;
}
/**
* kvm_reset_vcpu - sets core registers and sys_regs to reset value
* @ vcpu : The VCPU pointer
*
* This function finds the right table above and sets the registers on
2016-05-21 14:53:14 +03:00
* the virtual CPU struct to their architecturally defined reset
2012-12-10 20:23:59 +04:00
* values .
*/
int kvm_reset_vcpu ( struct kvm_vcpu * vcpu )
{
2012-12-07 21:52:03 +04:00
const struct kvm_irq_level * cpu_vtimer_irq ;
2017-02-03 18:20:03 +03:00
const struct kvm_irq_level * cpu_ptimer_irq ;
2012-12-10 20:23:59 +04:00
const struct kvm_regs * cpu_reset ;
switch ( vcpu - > arch . target ) {
default :
2013-02-07 14:46:46 +04:00
if ( test_bit ( KVM_ARM_VCPU_EL1_32BIT , vcpu - > arch . features ) ) {
if ( ! cpu_has_32bit_el1 ( ) )
return - EINVAL ;
cpu_reset = & default_regs_reset32 ;
} else {
cpu_reset = & default_regs_reset ;
}
2012-12-07 21:52:03 +04:00
cpu_vtimer_irq = & default_vtimer_irq ;
2017-02-03 18:20:03 +03:00
cpu_ptimer_irq = & default_ptimer_irq ;
2012-12-10 20:23:59 +04:00
break ;
}
/* Reset core registers */
memcpy ( vcpu_gp_regs ( vcpu ) , cpu_reset , sizeof ( * cpu_reset ) ) ;
/* Reset system registers */
kvm_reset_sys_regs ( vcpu ) ;
2015-09-11 06:30:22 +03:00
/* Reset PMU */
kvm_pmu_vcpu_reset ( vcpu ) ;
2012-12-07 21:52:03 +04:00
/* Reset timer */
2017-02-03 18:20:03 +03:00
return kvm_timer_vcpu_reset ( vcpu , cpu_vtimer_irq , cpu_ptimer_irq ) ;
2012-12-10 20:23:59 +04:00
}