aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kvm
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-05-16 20:17:24 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-05-16 20:17:24 -0400
commitbe092017b6ffbd013f481f915632db6aa9fc3ca3 (patch)
tree56f37b2b232ef41c0202c4f57d8e83e93d9168f4 /arch/arm/kvm
parentfb6363e9f4eeb37323feb8253b93854195942b8b (diff)
parente6d9a52543338603e25e71e0e4942f05dae0dd8a (diff)
Merge tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
Pull arm64 updates from Will Deacon: - virt_to_page/page_address optimisations - support for NUMA systems described using device-tree - support for hibernate/suspend-to-disk - proper support for maxcpus= command line parameter - detection and graceful handling of AArch64-only CPUs - miscellaneous cleanups and non-critical fixes * tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux: (92 commits) arm64: do not enforce strict 16 byte alignment to stack pointer arm64: kernel: Fix incorrect brk randomization arm64: cpuinfo: Missing NULL terminator in compat_hwcap_str arm64: secondary_start_kernel: Remove unnecessary barrier arm64: Ensure pmd_present() returns false after pmd_mknotpresent() arm64: Replace hard-coded values in the pmd/pud_bad() macros arm64: Implement pmdp_set_access_flags() for hardware AF/DBM arm64: Fix typo in the pmdp_huge_get_and_clear() definition arm64: mm: remove unnecessary EXPORT_SYMBOL_GPL arm64: always use STRICT_MM_TYPECHECKS arm64: kvm: Fix kvm teardown for systems using the extended idmap arm64: kaslr: increase randomization granularity arm64: kconfig: drop CONFIG_RTC_LIB dependency arm64: make ARCH_SUPPORTS_DEBUG_PAGEALLOC depend on !HIBERNATION arm64: hibernate: Refuse to hibernate if the boot cpu is offline arm64: kernel: Add support for hibernate/suspend-to-disk PM / Hibernate: Call flush_icache_range() on pages restored in-place arm64: Add new asm macro copy_page arm64: Promote KERNEL_START/KERNEL_END definitions to a header file arm64: kernel: Include _AC definition in page.h ...
Diffstat (limited to 'arch/arm/kvm')
-rw-r--r--arch/arm/kvm/arm.c118
-rw-r--r--arch/arm/kvm/mmu.c5
2 files changed, 76 insertions, 47 deletions
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index dded1b763c16..9ef013d86cc5 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -16,7 +16,6 @@
16 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 16 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */ 17 */
18 18
19#include <linux/cpu.h>
20#include <linux/cpu_pm.h> 19#include <linux/cpu_pm.h>
21#include <linux/errno.h> 20#include <linux/errno.h>
22#include <linux/err.h> 21#include <linux/err.h>
@@ -66,6 +65,8 @@ static DEFINE_SPINLOCK(kvm_vmid_lock);
66 65
67static bool vgic_present; 66static bool vgic_present;
68 67
68static DEFINE_PER_CPU(unsigned char, kvm_arm_hardware_enabled);
69
69static void kvm_arm_set_running_vcpu(struct kvm_vcpu *vcpu) 70static void kvm_arm_set_running_vcpu(struct kvm_vcpu *vcpu)
70{ 71{
71 BUG_ON(preemptible()); 72 BUG_ON(preemptible());
@@ -90,11 +91,6 @@ struct kvm_vcpu * __percpu *kvm_get_running_vcpus(void)
90 return &kvm_arm_running_vcpu; 91 return &kvm_arm_running_vcpu;
91} 92}
92 93
93int kvm_arch_hardware_enable(void)
94{
95 return 0;
96}
97
98int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu) 94int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu)
99{ 95{
100 return kvm_vcpu_exiting_guest_mode(vcpu) == IN_GUEST_MODE; 96 return kvm_vcpu_exiting_guest_mode(vcpu) == IN_GUEST_MODE;
@@ -1033,11 +1029,6 @@ long kvm_arch_vm_ioctl(struct file *filp,
1033 } 1029 }
1034} 1030}
1035 1031
1036static void cpu_init_stage2(void *dummy)
1037{
1038 __cpu_init_stage2();
1039}
1040
1041static void cpu_init_hyp_mode(void *dummy) 1032static void cpu_init_hyp_mode(void *dummy)
1042{ 1033{
1043 phys_addr_t boot_pgd_ptr; 1034 phys_addr_t boot_pgd_ptr;
@@ -1065,43 +1056,87 @@ static void cpu_hyp_reinit(void)
1065{ 1056{
1066 if (is_kernel_in_hyp_mode()) { 1057 if (is_kernel_in_hyp_mode()) {
1067 /* 1058 /*
1068 * cpu_init_stage2() is safe to call even if the PM 1059 * __cpu_init_stage2() is safe to call even if the PM
1069 * event was cancelled before the CPU was reset. 1060 * event was cancelled before the CPU was reset.
1070 */ 1061 */
1071 cpu_init_stage2(NULL); 1062 __cpu_init_stage2();
1072 } else { 1063 } else {
1073 if (__hyp_get_vectors() == hyp_default_vectors) 1064 if (__hyp_get_vectors() == hyp_default_vectors)
1074 cpu_init_hyp_mode(NULL); 1065 cpu_init_hyp_mode(NULL);
1075 } 1066 }
1076} 1067}
1077 1068
1078static int hyp_init_cpu_notify(struct notifier_block *self, 1069static void cpu_hyp_reset(void)
1079 unsigned long action, void *cpu) 1070{
1071 phys_addr_t boot_pgd_ptr;
1072 phys_addr_t phys_idmap_start;
1073
1074 if (!is_kernel_in_hyp_mode()) {
1075 boot_pgd_ptr = kvm_mmu_get_boot_httbr();
1076 phys_idmap_start = kvm_get_idmap_start();
1077
1078 __cpu_reset_hyp_mode(boot_pgd_ptr, phys_idmap_start);
1079 }
1080}
1081
1082static void _kvm_arch_hardware_enable(void *discard)
1080{ 1083{
1081 switch (action) { 1084 if (!__this_cpu_read(kvm_arm_hardware_enabled)) {
1082 case CPU_STARTING:
1083 case CPU_STARTING_FROZEN:
1084 cpu_hyp_reinit(); 1085 cpu_hyp_reinit();
1086 __this_cpu_write(kvm_arm_hardware_enabled, 1);
1085 } 1087 }
1088}
1089
1090int kvm_arch_hardware_enable(void)
1091{
1092 _kvm_arch_hardware_enable(NULL);
1093 return 0;
1094}
1086 1095
1087 return NOTIFY_OK; 1096static void _kvm_arch_hardware_disable(void *discard)
1097{
1098 if (__this_cpu_read(kvm_arm_hardware_enabled)) {
1099 cpu_hyp_reset();
1100 __this_cpu_write(kvm_arm_hardware_enabled, 0);
1101 }
1088} 1102}
1089 1103
1090static struct notifier_block hyp_init_cpu_nb = { 1104void kvm_arch_hardware_disable(void)
1091 .notifier_call = hyp_init_cpu_notify, 1105{
1092}; 1106 _kvm_arch_hardware_disable(NULL);
1107}
1093 1108
1094#ifdef CONFIG_CPU_PM 1109#ifdef CONFIG_CPU_PM
1095static int hyp_init_cpu_pm_notifier(struct notifier_block *self, 1110static int hyp_init_cpu_pm_notifier(struct notifier_block *self,
1096 unsigned long cmd, 1111 unsigned long cmd,
1097 void *v) 1112 void *v)
1098{ 1113{
1099 if (cmd == CPU_PM_EXIT) { 1114 /*
1100 cpu_hyp_reinit(); 1115 * kvm_arm_hardware_enabled is left with its old value over
1116 * PM_ENTER->PM_EXIT. It is used to indicate PM_EXIT should
1117 * re-enable hyp.
1118 */
1119 switch (cmd) {
1120 case CPU_PM_ENTER:
1121 if (__this_cpu_read(kvm_arm_hardware_enabled))
1122 /*
1123 * don't update kvm_arm_hardware_enabled here
1124 * so that the hardware will be re-enabled
1125 * when we resume. See below.
1126 */
1127 cpu_hyp_reset();
1128
1129 return NOTIFY_OK;
1130 case CPU_PM_EXIT:
1131 if (__this_cpu_read(kvm_arm_hardware_enabled))
1132 /* The hardware was enabled before suspend. */
1133 cpu_hyp_reinit();
1134
1101 return NOTIFY_OK; 1135 return NOTIFY_OK;
1102 }
1103 1136
1104 return NOTIFY_DONE; 1137 default:
1138 return NOTIFY_DONE;
1139 }
1105} 1140}
1106 1141
1107static struct notifier_block hyp_init_cpu_pm_nb = { 1142static struct notifier_block hyp_init_cpu_pm_nb = {
@@ -1143,16 +1178,12 @@ static int init_common_resources(void)
1143 1178
1144static int init_subsystems(void) 1179static int init_subsystems(void)
1145{ 1180{
1146 int err; 1181 int err = 0;
1147 1182
1148 /* 1183 /*
1149 * Register CPU Hotplug notifier 1184 * Enable hardware so that subsystem initialisation can access EL2.
1150 */ 1185 */
1151 err = register_cpu_notifier(&hyp_init_cpu_nb); 1186 on_each_cpu(_kvm_arch_hardware_enable, NULL, 1);
1152 if (err) {
1153 kvm_err("Cannot register KVM init CPU notifier (%d)\n", err);
1154 return err;
1155 }
1156 1187
1157 /* 1188 /*
1158 * Register CPU lower-power notifier 1189 * Register CPU lower-power notifier
@@ -1170,9 +1201,10 @@ static int init_subsystems(void)
1170 case -ENODEV: 1201 case -ENODEV:
1171 case -ENXIO: 1202 case -ENXIO:
1172 vgic_present = false; 1203 vgic_present = false;
1204 err = 0;
1173 break; 1205 break;
1174 default: 1206 default:
1175 return err; 1207 goto out;
1176 } 1208 }
1177 1209
1178 /* 1210 /*
@@ -1180,12 +1212,15 @@ static int init_subsystems(void)
1180 */ 1212 */
1181 err = kvm_timer_hyp_init(); 1213 err = kvm_timer_hyp_init();
1182 if (err) 1214 if (err)
1183 return err; 1215 goto out;
1184 1216
1185 kvm_perf_init(); 1217 kvm_perf_init();
1186 kvm_coproc_table_init(); 1218 kvm_coproc_table_init();
1187 1219
1188 return 0; 1220out:
1221 on_each_cpu(_kvm_arch_hardware_disable, NULL, 1);
1222
1223 return err;
1189} 1224}
1190 1225
1191static void teardown_hyp_mode(void) 1226static void teardown_hyp_mode(void)
@@ -1198,17 +1233,11 @@ static void teardown_hyp_mode(void)
1198 free_hyp_pgds(); 1233 free_hyp_pgds();
1199 for_each_possible_cpu(cpu) 1234 for_each_possible_cpu(cpu)
1200 free_page(per_cpu(kvm_arm_hyp_stack_page, cpu)); 1235 free_page(per_cpu(kvm_arm_hyp_stack_page, cpu));
1201 unregister_cpu_notifier(&hyp_init_cpu_nb);
1202 hyp_cpu_pm_exit(); 1236 hyp_cpu_pm_exit();
1203} 1237}
1204 1238
1205static int init_vhe_mode(void) 1239static int init_vhe_mode(void)
1206{ 1240{
1207 /*
1208 * Execute the init code on each CPU.
1209 */
1210 on_each_cpu(cpu_init_stage2, NULL, 1);
1211
1212 /* set size of VMID supported by CPU */ 1241 /* set size of VMID supported by CPU */
1213 kvm_vmid_bits = kvm_get_vmid_bits(); 1242 kvm_vmid_bits = kvm_get_vmid_bits();
1214 kvm_info("%d-bit VMID\n", kvm_vmid_bits); 1243 kvm_info("%d-bit VMID\n", kvm_vmid_bits);
@@ -1295,11 +1324,6 @@ static int init_hyp_mode(void)
1295 } 1324 }
1296 } 1325 }
1297 1326
1298 /*
1299 * Execute the init code on each CPU.
1300 */
1301 on_each_cpu(cpu_init_hyp_mode, NULL, 1);
1302
1303#ifndef CONFIG_HOTPLUG_CPU 1327#ifndef CONFIG_HOTPLUG_CPU
1304 free_boot_hyp_pgd(); 1328 free_boot_hyp_pgd();
1305#endif 1329#endif
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index d6d4191e68f2..be302128c5d7 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -1666,6 +1666,11 @@ phys_addr_t kvm_get_idmap_vector(void)
1666 return hyp_idmap_vector; 1666 return hyp_idmap_vector;
1667} 1667}
1668 1668
1669phys_addr_t kvm_get_idmap_start(void)
1670{
1671 return hyp_idmap_start;
1672}
1673
1669int kvm_mmu_init(void) 1674int kvm_mmu_init(void)
1670{ 1675{
1671 int err; 1676 int err;