diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-16 20:17:24 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-16 20:17:24 -0400 |
commit | be092017b6ffbd013f481f915632db6aa9fc3ca3 (patch) | |
tree | 56f37b2b232ef41c0202c4f57d8e83e93d9168f4 /arch/arm/kvm | |
parent | fb6363e9f4eeb37323feb8253b93854195942b8b (diff) | |
parent | e6d9a52543338603e25e71e0e4942f05dae0dd8a (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.c | 118 | ||||
-rw-r--r-- | arch/arm/kvm/mmu.c | 5 |
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 | ||
67 | static bool vgic_present; | 66 | static bool vgic_present; |
68 | 67 | ||
68 | static DEFINE_PER_CPU(unsigned char, kvm_arm_hardware_enabled); | ||
69 | |||
69 | static void kvm_arm_set_running_vcpu(struct kvm_vcpu *vcpu) | 70 | static 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 | ||
93 | int kvm_arch_hardware_enable(void) | ||
94 | { | ||
95 | return 0; | ||
96 | } | ||
97 | |||
98 | int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu) | 94 | int 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 | ||
1036 | static void cpu_init_stage2(void *dummy) | ||
1037 | { | ||
1038 | __cpu_init_stage2(); | ||
1039 | } | ||
1040 | |||
1041 | static void cpu_init_hyp_mode(void *dummy) | 1032 | static 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 | ||
1078 | static int hyp_init_cpu_notify(struct notifier_block *self, | 1069 | static 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 | |||
1082 | static 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 | |||
1090 | int kvm_arch_hardware_enable(void) | ||
1091 | { | ||
1092 | _kvm_arch_hardware_enable(NULL); | ||
1093 | return 0; | ||
1094 | } | ||
1086 | 1095 | ||
1087 | return NOTIFY_OK; | 1096 | static 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 | ||
1090 | static struct notifier_block hyp_init_cpu_nb = { | 1104 | void 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 |
1095 | static int hyp_init_cpu_pm_notifier(struct notifier_block *self, | 1110 | static 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 | ||
1107 | static struct notifier_block hyp_init_cpu_pm_nb = { | 1142 | static struct notifier_block hyp_init_cpu_pm_nb = { |
@@ -1143,16 +1178,12 @@ static int init_common_resources(void) | |||
1143 | 1178 | ||
1144 | static int init_subsystems(void) | 1179 | static 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; | 1220 | out: |
1221 | on_each_cpu(_kvm_arch_hardware_disable, NULL, 1); | ||
1222 | |||
1223 | return err; | ||
1189 | } | 1224 | } |
1190 | 1225 | ||
1191 | static void teardown_hyp_mode(void) | 1226 | static 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 | ||
1205 | static int init_vhe_mode(void) | 1239 | static 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 | ||
1669 | phys_addr_t kvm_get_idmap_start(void) | ||
1670 | { | ||
1671 | return hyp_idmap_start; | ||
1672 | } | ||
1673 | |||
1669 | int kvm_mmu_init(void) | 1674 | int kvm_mmu_init(void) |
1670 | { | 1675 | { |
1671 | int err; | 1676 | int err; |