2012-12-11 00:23:59 +08: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-08 00:30:02 +08:00
|
|
|
#include <linux/hw_breakpoint.h>
|
2012-12-11 00:23:59 +08:00
|
|
|
|
2012-12-08 01:52:03 +08:00
|
|
|
#include <kvm/arm_arch_timer.h>
|
|
|
|
|
2012-12-11 00:23:59 +08: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-28 00:47:05 +08:00
|
|
|
#include <asm/kvm_asm.h>
|
2012-12-11 00:23:59 +08: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-28 00:47:05 +08:00
|
|
|
#include <asm/kvm_mmu.h>
|
2012-12-11 00:23:59 +08: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 18:46:46 +08: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),
|
|
|
|
};
|
|
|
|
|
2012-12-08 01:52:03 +08:00
|
|
|
static const struct kvm_irq_level default_vtimer_irq = {
|
|
|
|
.irq = 27,
|
|
|
|
.level = 1,
|
|
|
|
};
|
|
|
|
|
2013-02-07 18:46:46 +08:00
|
|
|
static bool cpu_has_32bit_el1(void)
|
|
|
|
{
|
|
|
|
u64 pfr0;
|
|
|
|
|
2015-10-19 21:24:55 +08:00
|
|
|
pfr0 = read_system_reg(SYS_ID_AA64PFR0_EL1);
|
2013-02-07 18:46:46 +08:00
|
|
|
return !!(pfr0 & 0x20);
|
|
|
|
}
|
|
|
|
|
2015-07-08 00:30:02 +08: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).
|
|
|
|
*/
|
2012-12-11 00:23:59 +08:00
|
|
|
int kvm_arch_dev_ioctl_check_extension(long ext)
|
|
|
|
{
|
|
|
|
int r;
|
|
|
|
|
|
|
|
switch (ext) {
|
2013-02-07 18:46:46 +08:00
|
|
|
case KVM_CAP_ARM_EL1_32BIT:
|
|
|
|
r = cpu_has_32bit_el1();
|
|
|
|
break;
|
2015-07-08 00:30:02 +08: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 22:46:15 +08:00
|
|
|
case KVM_CAP_ARM_PMU_V3:
|
|
|
|
r = kvm_arm_support_pmu_v3();
|
|
|
|
break;
|
2015-07-08 00:30:02 +08:00
|
|
|
case KVM_CAP_SET_GUEST_DEBUG:
|
2016-01-11 20:56:17 +08:00
|
|
|
case KVM_CAP_VCPU_ATTRIBUTES:
|
2015-07-08 00:30:02 +08:00
|
|
|
r = 1;
|
|
|
|
break;
|
2012-12-11 00:23:59 +08: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
|
|
|
|
* the virtual CPU struct to their architectually defined reset
|
|
|
|
* values.
|
|
|
|
*/
|
|
|
|
int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
|
|
|
|
{
|
2012-12-08 01:52:03 +08:00
|
|
|
const struct kvm_irq_level *cpu_vtimer_irq;
|
2012-12-11 00:23:59 +08:00
|
|
|
const struct kvm_regs *cpu_reset;
|
|
|
|
|
|
|
|
switch (vcpu->arch.target) {
|
|
|
|
default:
|
2013-02-07 18:46:46 +08: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-08 01:52:03 +08:00
|
|
|
cpu_vtimer_irq = &default_vtimer_irq;
|
2012-12-11 00:23:59 +08: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 11:30:22 +08:00
|
|
|
/* Reset PMU */
|
|
|
|
kvm_pmu_vcpu_reset(vcpu);
|
|
|
|
|
2012-12-08 01:52:03 +08:00
|
|
|
/* Reset timer */
|
2014-06-23 20:59:13 +08:00
|
|
|
return kvm_timer_vcpu_reset(vcpu, cpu_vtimer_irq);
|
2012-12-11 00:23:59 +08:00
|
|
|
}
|
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-28 00:47:05 +08:00
|
|
|
|
|
|
|
extern char __hyp_idmap_text_start[];
|
|
|
|
|
arm64: kvm: Fix kvm teardown for systems using the extended idmap
If memory is located above 1<<VA_BITS, kvm adds an extra level to its page
tables, merging the runtime tables and boot tables that contain the idmap.
This lets us avoid the trampoline dance during initialisation.
This also means there is no trampoline page mapped, so
__cpu_reset_hyp_mode() can't call __kvm_hyp_reset() in this page. The good
news is the idmap is still mapped, so we don't need the trampoline page.
The bad news is we can't call it directly as the idmap is above
HYP_PAGE_OFFSET, so its address is masked by kvm_call_hyp.
Add a function __extended_idmap_trampoline which will branch into
__kvm_hyp_reset in the idmap, change kvm_hyp_reset_entry() to return
this address if __kvm_cpu_uses_extended_idmap(). In this case
__kvm_hyp_reset() will still switch to the boot tables (which are the
merged tables that were already in use), and branch into the idmap (where
it already was).
This fixes boot failures on these systems, where we fail to execute the
missing trampoline page when tearing down kvm in init_subsystems():
[ 2.508922] kvm [1]: 8-bit VMID
[ 2.512057] kvm [1]: Hyp mode initialized successfully
[ 2.517242] kvm [1]: interrupt-controller@e1140000 IRQ13
[ 2.522622] kvm [1]: timer IRQ3
[ 2.525783] Kernel panic - not syncing: HYP panic:
[ 2.525783] PS:200003c9 PC:0000007ffffff820 ESR:86000005
[ 2.525783] FAR:0000007ffffff820 HPFAR:00000000003ffff0 PAR:0000000000000000
[ 2.525783] VCPU: (null)
[ 2.525783]
[ 2.547667] CPU: 0 PID: 0 Comm: swapper/0 Tainted: G W 4.6.0-rc5+ #1
[ 2.555137] Hardware name: Default string Default string/Default string, BIOS ROD0084E 09/03/2015
[ 2.563994] Call trace:
[ 2.566432] [<ffffff80080888d0>] dump_backtrace+0x0/0x240
[ 2.571818] [<ffffff8008088b24>] show_stack+0x14/0x20
[ 2.576858] [<ffffff80083423ac>] dump_stack+0x94/0xb8
[ 2.581899] [<ffffff8008152130>] panic+0x10c/0x250
[ 2.586677] [<ffffff8008152024>] panic+0x0/0x250
[ 2.591281] SMP: stopping secondary CPUs
[ 3.649692] SMP: failed to stop secondary CPUs 0-2,4-7
[ 3.654818] Kernel Offset: disabled
[ 3.658293] Memory Limit: none
[ 3.661337] ---[ end Kernel panic - not syncing: HYP panic:
[ 3.661337] PS:200003c9 PC:0000007ffffff820 ESR:86000005
[ 3.661337] FAR:0000007ffffff820 HPFAR:00000000003ffff0 PAR:0000000000000000
[ 3.661337] VCPU: (null)
[ 3.661337]
Reported-by: Will Deacon <will.deacon@arm.com>
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: James Morse <james.morse@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
2016-04-30 01:27:03 +08:00
|
|
|
unsigned long kvm_hyp_reset_entry(void)
|
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-28 00:47:05 +08:00
|
|
|
{
|
arm64: kvm: Fix kvm teardown for systems using the extended idmap
If memory is located above 1<<VA_BITS, kvm adds an extra level to its page
tables, merging the runtime tables and boot tables that contain the idmap.
This lets us avoid the trampoline dance during initialisation.
This also means there is no trampoline page mapped, so
__cpu_reset_hyp_mode() can't call __kvm_hyp_reset() in this page. The good
news is the idmap is still mapped, so we don't need the trampoline page.
The bad news is we can't call it directly as the idmap is above
HYP_PAGE_OFFSET, so its address is masked by kvm_call_hyp.
Add a function __extended_idmap_trampoline which will branch into
__kvm_hyp_reset in the idmap, change kvm_hyp_reset_entry() to return
this address if __kvm_cpu_uses_extended_idmap(). In this case
__kvm_hyp_reset() will still switch to the boot tables (which are the
merged tables that were already in use), and branch into the idmap (where
it already was).
This fixes boot failures on these systems, where we fail to execute the
missing trampoline page when tearing down kvm in init_subsystems():
[ 2.508922] kvm [1]: 8-bit VMID
[ 2.512057] kvm [1]: Hyp mode initialized successfully
[ 2.517242] kvm [1]: interrupt-controller@e1140000 IRQ13
[ 2.522622] kvm [1]: timer IRQ3
[ 2.525783] Kernel panic - not syncing: HYP panic:
[ 2.525783] PS:200003c9 PC:0000007ffffff820 ESR:86000005
[ 2.525783] FAR:0000007ffffff820 HPFAR:00000000003ffff0 PAR:0000000000000000
[ 2.525783] VCPU: (null)
[ 2.525783]
[ 2.547667] CPU: 0 PID: 0 Comm: swapper/0 Tainted: G W 4.6.0-rc5+ #1
[ 2.555137] Hardware name: Default string Default string/Default string, BIOS ROD0084E 09/03/2015
[ 2.563994] Call trace:
[ 2.566432] [<ffffff80080888d0>] dump_backtrace+0x0/0x240
[ 2.571818] [<ffffff8008088b24>] show_stack+0x14/0x20
[ 2.576858] [<ffffff80083423ac>] dump_stack+0x94/0xb8
[ 2.581899] [<ffffff8008152130>] panic+0x10c/0x250
[ 2.586677] [<ffffff8008152024>] panic+0x0/0x250
[ 2.591281] SMP: stopping secondary CPUs
[ 3.649692] SMP: failed to stop secondary CPUs 0-2,4-7
[ 3.654818] Kernel Offset: disabled
[ 3.658293] Memory Limit: none
[ 3.661337] ---[ end Kernel panic - not syncing: HYP panic:
[ 3.661337] PS:200003c9 PC:0000007ffffff820 ESR:86000005
[ 3.661337] FAR:0000007ffffff820 HPFAR:00000000003ffff0 PAR:0000000000000000
[ 3.661337] VCPU: (null)
[ 3.661337]
Reported-by: Will Deacon <will.deacon@arm.com>
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: James Morse <james.morse@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
2016-04-30 01:27:03 +08:00
|
|
|
if (!__kvm_cpu_uses_extended_idmap()) {
|
|
|
|
unsigned long offset;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Find the address of __kvm_hyp_reset() in the trampoline page.
|
|
|
|
* This is present in the running page tables, and the boot page
|
|
|
|
* tables, so we call the code here to start the trampoline
|
|
|
|
* dance in reverse.
|
|
|
|
*/
|
|
|
|
offset = (unsigned long)__kvm_hyp_reset
|
|
|
|
- ((unsigned long)__hyp_idmap_text_start & PAGE_MASK);
|
|
|
|
|
|
|
|
return TRAMPOLINE_VA + offset;
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* KVM is running with merged page tables, which don't have the
|
|
|
|
* trampoline page mapped. We know the idmap is still mapped,
|
|
|
|
* but can't be called into directly. Use
|
|
|
|
* __extended_idmap_trampoline to do the call.
|
|
|
|
*/
|
|
|
|
return (unsigned long)kvm_ksym_ref(__extended_idmap_trampoline);
|
|
|
|
}
|
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-28 00:47:05 +08:00
|
|
|
}
|