.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * 64-bit pSeries and RS/6000 setup code. |
---|
3 | 4 | * |
---|
.. | .. |
---|
5 | 6 | * Adapted from 'alpha' version by Gary Thomas |
---|
6 | 7 | * Modified by Cort Dougan (cort@cs.nmt.edu) |
---|
7 | 8 | * Modified by PPC64 Team, IBM Corp |
---|
8 | | - * |
---|
9 | | - * This program is free software; you can redistribute it and/or |
---|
10 | | - * modify it under the terms of the GNU General Public License |
---|
11 | | - * as published by the Free Software Foundation; either version |
---|
12 | | - * 2 of the License, or (at your option) any later version. |
---|
13 | 9 | */ |
---|
14 | 10 | |
---|
15 | 11 | /* |
---|
.. | .. |
---|
42 | 38 | #include <linux/of.h> |
---|
43 | 39 | #include <linux/of_pci.h> |
---|
44 | 40 | #include <linux/memblock.h> |
---|
| 41 | +#include <linux/swiotlb.h> |
---|
45 | 42 | |
---|
46 | 43 | #include <asm/mmu.h> |
---|
47 | 44 | #include <asm/processor.h> |
---|
48 | 45 | #include <asm/io.h> |
---|
49 | | -#include <asm/pgtable.h> |
---|
50 | 46 | #include <asm/prom.h> |
---|
51 | 47 | #include <asm/rtas.h> |
---|
52 | 48 | #include <asm/pci-bridge.h> |
---|
.. | .. |
---|
71 | 67 | #include <asm/isa-bridge.h> |
---|
72 | 68 | #include <asm/security_features.h> |
---|
73 | 69 | #include <asm/asm-const.h> |
---|
| 70 | +#include <asm/idle.h> |
---|
| 71 | +#include <asm/swiotlb.h> |
---|
| 72 | +#include <asm/svm.h> |
---|
| 73 | +#include <asm/dtl.h> |
---|
74 | 74 | |
---|
75 | 75 | #include "pseries.h" |
---|
76 | 76 | #include "../../../../drivers/pci/pci.h" |
---|
.. | .. |
---|
84 | 84 | EXPORT_SYMBOL(CMO_PageSize); |
---|
85 | 85 | |
---|
86 | 86 | int fwnmi_active; /* TRUE if an FWNMI handler is present */ |
---|
| 87 | +int ibm_nmi_interlock_token; |
---|
87 | 88 | |
---|
88 | 89 | static void pSeries_show_cpuinfo(struct seq_file *m) |
---|
89 | 90 | { |
---|
.. | .. |
---|
110 | 111 | u8 *mce_data_buf; |
---|
111 | 112 | unsigned int i; |
---|
112 | 113 | int nr_cpus = num_possible_cpus(); |
---|
| 114 | +#ifdef CONFIG_PPC_BOOK3S_64 |
---|
| 115 | + struct slb_entry *slb_ptr; |
---|
| 116 | + size_t size; |
---|
| 117 | +#endif |
---|
| 118 | + int ibm_nmi_register_token; |
---|
113 | 119 | |
---|
114 | | - int ibm_nmi_register = rtas_token("ibm,nmi-register"); |
---|
115 | | - if (ibm_nmi_register == RTAS_UNKNOWN_SERVICE) |
---|
| 120 | + ibm_nmi_register_token = rtas_token("ibm,nmi-register"); |
---|
| 121 | + if (ibm_nmi_register_token == RTAS_UNKNOWN_SERVICE) |
---|
| 122 | + return; |
---|
| 123 | + |
---|
| 124 | + ibm_nmi_interlock_token = rtas_token("ibm,nmi-interlock"); |
---|
| 125 | + if (WARN_ON(ibm_nmi_interlock_token == RTAS_UNKNOWN_SERVICE)) |
---|
116 | 126 | return; |
---|
117 | 127 | |
---|
118 | 128 | /* If the kernel's not linked at zero we point the firmware at low |
---|
.. | .. |
---|
120 | 130 | system_reset_addr = __pa(system_reset_fwnmi) - PHYSICAL_START; |
---|
121 | 131 | machine_check_addr = __pa(machine_check_fwnmi) - PHYSICAL_START; |
---|
122 | 132 | |
---|
123 | | - if (0 == rtas_call(ibm_nmi_register, 2, 1, NULL, system_reset_addr, |
---|
124 | | - machine_check_addr)) |
---|
| 133 | + if (0 == rtas_call(ibm_nmi_register_token, 2, 1, NULL, |
---|
| 134 | + system_reset_addr, machine_check_addr)) |
---|
125 | 135 | fwnmi_active = 1; |
---|
126 | 136 | |
---|
127 | 137 | /* |
---|
.. | .. |
---|
129 | 139 | * It will be used in real mode mce handler, hence it needs to be |
---|
130 | 140 | * below RMA. |
---|
131 | 141 | */ |
---|
132 | | - mce_data_buf = __va(memblock_alloc_base(RTAS_ERROR_LOG_MAX * nr_cpus, |
---|
133 | | - RTAS_ERROR_LOG_MAX, ppc64_rma_size)); |
---|
| 142 | + mce_data_buf = memblock_alloc_try_nid_raw(RTAS_ERROR_LOG_MAX * nr_cpus, |
---|
| 143 | + RTAS_ERROR_LOG_MAX, MEMBLOCK_LOW_LIMIT, |
---|
| 144 | + ppc64_rma_size, NUMA_NO_NODE); |
---|
| 145 | + if (!mce_data_buf) |
---|
| 146 | + panic("Failed to allocate %d bytes below %pa for MCE buffer\n", |
---|
| 147 | + RTAS_ERROR_LOG_MAX * nr_cpus, &ppc64_rma_size); |
---|
| 148 | + |
---|
134 | 149 | for_each_possible_cpu(i) { |
---|
135 | 150 | paca_ptrs[i]->mce_data_buf = mce_data_buf + |
---|
136 | 151 | (RTAS_ERROR_LOG_MAX * i); |
---|
137 | 152 | } |
---|
| 153 | + |
---|
| 154 | +#ifdef CONFIG_PPC_BOOK3S_64 |
---|
| 155 | + if (!radix_enabled()) { |
---|
| 156 | + /* Allocate per cpu area to save old slb contents during MCE */ |
---|
| 157 | + size = sizeof(struct slb_entry) * mmu_slb_size * nr_cpus; |
---|
| 158 | + slb_ptr = memblock_alloc_try_nid_raw(size, |
---|
| 159 | + sizeof(struct slb_entry), MEMBLOCK_LOW_LIMIT, |
---|
| 160 | + ppc64_rma_size, NUMA_NO_NODE); |
---|
| 161 | + if (!slb_ptr) |
---|
| 162 | + panic("Failed to allocate %zu bytes below %pa for slb area\n", |
---|
| 163 | + size, &ppc64_rma_size); |
---|
| 164 | + |
---|
| 165 | + for_each_possible_cpu(i) |
---|
| 166 | + paca_ptrs[i]->mce_faulty_slbs = slb_ptr + (mmu_slb_size * i); |
---|
| 167 | + } |
---|
| 168 | +#endif |
---|
138 | 169 | } |
---|
139 | 170 | |
---|
140 | 171 | static void pseries_8259_cascade(struct irq_desc *desc) |
---|
.. | .. |
---|
180 | 211 | of_node_put(old); |
---|
181 | 212 | if (np == NULL) |
---|
182 | 213 | break; |
---|
183 | | - if (strcmp(np->name, "pci") != 0) |
---|
| 214 | + if (!of_node_name_eq(np, "pci")) |
---|
184 | 215 | continue; |
---|
185 | 216 | addrp = of_get_property(np, "8259-interrupt-acknowledge", NULL); |
---|
186 | 217 | if (addrp == NULL) |
---|
.. | .. |
---|
257 | 288 | */ |
---|
258 | 289 | static int alloc_dispatch_logs(void) |
---|
259 | 290 | { |
---|
260 | | - int cpu, ret; |
---|
261 | | - struct paca_struct *pp; |
---|
262 | | - struct dtl_entry *dtl; |
---|
263 | | - |
---|
264 | 291 | if (!firmware_has_feature(FW_FEATURE_SPLPAR)) |
---|
265 | 292 | return 0; |
---|
266 | 293 | |
---|
267 | 294 | if (!dtl_cache) |
---|
268 | 295 | return 0; |
---|
269 | 296 | |
---|
270 | | - for_each_possible_cpu(cpu) { |
---|
271 | | - pp = paca_ptrs[cpu]; |
---|
272 | | - dtl = kmem_cache_alloc(dtl_cache, GFP_KERNEL); |
---|
273 | | - if (!dtl) { |
---|
274 | | - pr_warn("Failed to allocate dispatch trace log for cpu %d\n", |
---|
275 | | - cpu); |
---|
276 | | - pr_warn("Stolen time statistics will be unreliable\n"); |
---|
277 | | - break; |
---|
278 | | - } |
---|
279 | | - |
---|
280 | | - pp->dtl_ridx = 0; |
---|
281 | | - pp->dispatch_log = dtl; |
---|
282 | | - pp->dispatch_log_end = dtl + N_DISPATCH_LOG; |
---|
283 | | - pp->dtl_curr = dtl; |
---|
284 | | - } |
---|
| 297 | + alloc_dtl_buffers(0); |
---|
285 | 298 | |
---|
286 | 299 | /* Register the DTL for the current (boot) cpu */ |
---|
287 | | - dtl = get_paca()->dispatch_log; |
---|
288 | | - get_paca()->dtl_ridx = 0; |
---|
289 | | - get_paca()->dtl_curr = dtl; |
---|
290 | | - get_paca()->lppaca_ptr->dtl_idx = 0; |
---|
291 | | - |
---|
292 | | - /* hypervisor reads buffer length from this field */ |
---|
293 | | - dtl->enqueue_to_dispatch_time = cpu_to_be32(DISPATCH_LOG_BYTES); |
---|
294 | | - ret = register_dtl(hard_smp_processor_id(), __pa(dtl)); |
---|
295 | | - if (ret) |
---|
296 | | - pr_err("WARNING: DTL registration of cpu %d (hw %d) failed " |
---|
297 | | - "with %d\n", smp_processor_id(), |
---|
298 | | - hard_smp_processor_id(), ret); |
---|
299 | | - get_paca()->lppaca_ptr->dtl_enable_mask = 2; |
---|
| 300 | + register_dtl_buffer(smp_processor_id()); |
---|
300 | 301 | |
---|
301 | 302 | return 0; |
---|
302 | 303 | } |
---|
.. | .. |
---|
309 | 310 | |
---|
310 | 311 | static int alloc_dispatch_log_kmem_cache(void) |
---|
311 | 312 | { |
---|
| 313 | + void (*ctor)(void *) = get_dtl_cache_ctor(); |
---|
| 314 | + |
---|
312 | 315 | dtl_cache = kmem_cache_create("dtl", DISPATCH_LOG_BYTES, |
---|
313 | | - DISPATCH_LOG_BYTES, 0, NULL); |
---|
| 316 | + DISPATCH_LOG_BYTES, 0, ctor); |
---|
314 | 317 | if (!dtl_cache) { |
---|
315 | 318 | pr_warn("Failed to create dispatch trace log buffer cache\n"); |
---|
316 | 319 | pr_warn("Stolen time statistics will be unreliable\n"); |
---|
.. | .. |
---|
321 | 324 | } |
---|
322 | 325 | machine_early_initcall(pseries, alloc_dispatch_log_kmem_cache); |
---|
323 | 326 | |
---|
| 327 | +DEFINE_PER_CPU(u64, idle_spurr_cycles); |
---|
| 328 | +DEFINE_PER_CPU(u64, idle_entry_purr_snap); |
---|
| 329 | +DEFINE_PER_CPU(u64, idle_entry_spurr_snap); |
---|
324 | 330 | static void pseries_lpar_idle(void) |
---|
325 | 331 | { |
---|
326 | 332 | /* |
---|
.. | .. |
---|
332 | 338 | return; |
---|
333 | 339 | |
---|
334 | 340 | /* Indicate to hypervisor that we are idle. */ |
---|
335 | | - get_lppaca()->idle = 1; |
---|
| 341 | + pseries_idle_prolog(); |
---|
336 | 342 | |
---|
337 | 343 | /* |
---|
338 | 344 | * Yield the processor to the hypervisor. We return if |
---|
.. | .. |
---|
343 | 349 | */ |
---|
344 | 350 | cede_processor(); |
---|
345 | 351 | |
---|
346 | | - get_lppaca()->idle = 0; |
---|
| 352 | + pseries_idle_epilog(); |
---|
347 | 353 | } |
---|
348 | 354 | |
---|
349 | 355 | /* |
---|
.. | .. |
---|
353 | 359 | * to ever be a problem in practice we can move this into a kernel thread to |
---|
354 | 360 | * finish off the process later in boot. |
---|
355 | 361 | */ |
---|
356 | | -void pseries_enable_reloc_on_exc(void) |
---|
| 362 | +bool pseries_enable_reloc_on_exc(void) |
---|
357 | 363 | { |
---|
358 | 364 | long rc; |
---|
359 | 365 | unsigned int delay, total_delay = 0; |
---|
.. | .. |
---|
364 | 370 | if (rc == H_P2) { |
---|
365 | 371 | pr_info("Relocation on exceptions not" |
---|
366 | 372 | " supported\n"); |
---|
| 373 | + return false; |
---|
367 | 374 | } else if (rc != H_SUCCESS) { |
---|
368 | 375 | pr_warn("Unable to enable relocation" |
---|
369 | 376 | " on exceptions: %ld\n", rc); |
---|
| 377 | + return false; |
---|
370 | 378 | } |
---|
371 | | - break; |
---|
| 379 | + return true; |
---|
372 | 380 | } |
---|
373 | 381 | |
---|
374 | 382 | delay = get_longbusy_msecs(rc); |
---|
.. | .. |
---|
377 | 385 | pr_warn("Warning: Giving up waiting to enable " |
---|
378 | 386 | "relocation on exceptions (%u msec)!\n", |
---|
379 | 387 | total_delay); |
---|
380 | | - return; |
---|
| 388 | + return false; |
---|
381 | 389 | } |
---|
382 | 390 | |
---|
383 | 391 | mdelay(delay); |
---|
.. | .. |
---|
462 | 470 | struct device_node *root = of_find_node_by_path("/"); |
---|
463 | 471 | |
---|
464 | 472 | for_each_child_of_node(root, node) { |
---|
465 | | - if (node->type == NULL || (strcmp(node->type, "pci") != 0 && |
---|
466 | | - strcmp(node->type, "pciex") != 0)) |
---|
| 473 | + if (!of_node_is_type(node, "pci") && |
---|
| 474 | + !of_node_is_type(node, "pciex")) |
---|
467 | 475 | continue; |
---|
468 | 476 | |
---|
469 | 477 | phb = pcibios_alloc_controller(node); |
---|
.. | .. |
---|
511 | 519 | if (result->character & H_CPU_CHAR_BCCTR_FLUSH_ASSIST) |
---|
512 | 520 | security_ftr_set(SEC_FTR_BCCTR_FLUSH_ASSIST); |
---|
513 | 521 | |
---|
| 522 | + if (result->character & H_CPU_CHAR_BCCTR_LINK_FLUSH_ASSIST) |
---|
| 523 | + security_ftr_set(SEC_FTR_BCCTR_LINK_FLUSH_ASSIST); |
---|
| 524 | + |
---|
514 | 525 | if (result->behaviour & H_CPU_BEHAV_FLUSH_COUNT_CACHE) |
---|
515 | 526 | security_ftr_set(SEC_FTR_FLUSH_COUNT_CACHE); |
---|
| 527 | + |
---|
| 528 | + if (result->behaviour & H_CPU_BEHAV_FLUSH_LINK_STACK) |
---|
| 529 | + security_ftr_set(SEC_FTR_FLUSH_LINK_STACK); |
---|
516 | 530 | |
---|
517 | 531 | /* |
---|
518 | 532 | * The features below are enabled by default, so we instead look to see |
---|
.. | .. |
---|
524 | 538 | if (!(result->behaviour & H_CPU_BEHAV_L1D_FLUSH_PR)) |
---|
525 | 539 | security_ftr_clear(SEC_FTR_L1D_FLUSH_PR); |
---|
526 | 540 | |
---|
| 541 | + if (result->behaviour & H_CPU_BEHAV_NO_L1D_FLUSH_ENTRY) |
---|
| 542 | + security_ftr_clear(SEC_FTR_L1D_FLUSH_ENTRY); |
---|
| 543 | + |
---|
| 544 | + if (result->behaviour & H_CPU_BEHAV_NO_L1D_FLUSH_UACCESS) |
---|
| 545 | + security_ftr_clear(SEC_FTR_L1D_FLUSH_UACCESS); |
---|
| 546 | + |
---|
527 | 547 | if (!(result->behaviour & H_CPU_BEHAV_BNDS_CHK_SPEC_BAR)) |
---|
528 | 548 | security_ftr_clear(SEC_FTR_BNDS_CHK_SPEC_BAR); |
---|
529 | 549 | } |
---|
530 | 550 | |
---|
531 | | -void pseries_setup_rfi_flush(void) |
---|
| 551 | +void pseries_setup_security_mitigations(void) |
---|
532 | 552 | { |
---|
533 | 553 | struct h_cpu_char_result result; |
---|
534 | 554 | enum l1d_flush_type types; |
---|
.. | .. |
---|
573 | 593 | enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) && |
---|
574 | 594 | security_ftr_enabled(SEC_FTR_L1D_FLUSH_UACCESS); |
---|
575 | 595 | setup_uaccess_flush(enable); |
---|
| 596 | + |
---|
| 597 | + setup_stf_barrier(); |
---|
576 | 598 | } |
---|
577 | 599 | |
---|
578 | 600 | #ifdef CONFIG_PCI_IOV |
---|
.. | .. |
---|
748 | 770 | smp_init_pseries(); |
---|
749 | 771 | |
---|
750 | 772 | |
---|
| 773 | + if (radix_enabled() && !mmu_has_feature(MMU_FTR_GTSE)) |
---|
| 774 | + if (!firmware_has_feature(FW_FEATURE_RPT_INVALIDATE)) |
---|
| 775 | + panic("BUG: Radix support requires either GTSE or RPT_INVALIDATE\n"); |
---|
| 776 | + |
---|
| 777 | + |
---|
751 | 778 | /* openpic global configuration register (64-bit format). */ |
---|
752 | 779 | /* openpic Interrupt Source Unit pointer (64-bit format). */ |
---|
753 | 780 | /* python0 facility area (mmio) (64-bit format) REAL address. */ |
---|
.. | .. |
---|
757 | 784 | |
---|
758 | 785 | fwnmi_init(); |
---|
759 | 786 | |
---|
760 | | - pseries_setup_rfi_flush(); |
---|
761 | | - setup_stf_barrier(); |
---|
| 787 | + pseries_setup_security_mitigations(); |
---|
| 788 | + pseries_lpar_read_hblkrm_characteristics(); |
---|
762 | 789 | |
---|
763 | 790 | /* By default, only probe PCI (can be overridden by rtas_pci) */ |
---|
764 | 791 | pci_add_flags(PCI_PROBE_ONLY); |
---|
.. | .. |
---|
773 | 800 | if (firmware_has_feature(FW_FEATURE_LPAR)) { |
---|
774 | 801 | vpa_init(boot_cpuid); |
---|
775 | 802 | |
---|
776 | | - if (lppaca_shared_proc(get_lppaca())) |
---|
| 803 | + if (lppaca_shared_proc()) { |
---|
777 | 804 | static_branch_enable(&shared_processor); |
---|
| 805 | + pv_spinlocks_init(); |
---|
| 806 | + } |
---|
778 | 807 | |
---|
779 | 808 | ppc_md.power_save = pseries_lpar_idle; |
---|
780 | 809 | ppc_md.enable_pmcs = pseries_lpar_enable_pmcs; |
---|
.. | .. |
---|
792 | 821 | } |
---|
793 | 822 | |
---|
794 | 823 | ppc_md.pcibios_root_bridge_prepare = pseries_root_bridge_prepare; |
---|
| 824 | + |
---|
| 825 | + if (swiotlb_force == SWIOTLB_FORCE) |
---|
| 826 | + ppc_swiotlb_enable = 1; |
---|
| 827 | + |
---|
| 828 | + pseries_rng_init(); |
---|
795 | 829 | } |
---|
796 | 830 | |
---|
797 | 831 | static void pseries_panic(char *str) |
---|
.. | .. |
---|
830 | 864 | return plpar_hcall_norets(H_SET_XDABR, dabr, dabrx); |
---|
831 | 865 | } |
---|
832 | 866 | |
---|
833 | | -static int pseries_set_dawr(unsigned long dawr, unsigned long dawrx) |
---|
| 867 | +static int pseries_set_dawr(int nr, unsigned long dawr, unsigned long dawrx) |
---|
834 | 868 | { |
---|
835 | 869 | /* PAPR says we can't set HYP */ |
---|
836 | 870 | dawrx &= ~DAWRX_HYP; |
---|
837 | 871 | |
---|
838 | | - return plpar_set_watchpoint0(dawr, dawrx); |
---|
| 872 | + if (nr == 0) |
---|
| 873 | + return plpar_set_watchpoint0(dawr, dawrx); |
---|
| 874 | + else |
---|
| 875 | + return plpar_set_watchpoint1(dawr, dawrx); |
---|
839 | 876 | } |
---|
840 | 877 | |
---|
841 | 878 | #define CMO_CHARACTERISTICS_TOKEN 44 |
---|
.. | .. |
---|
983 | 1020 | |
---|
984 | 1021 | static int __init pSeries_probe(void) |
---|
985 | 1022 | { |
---|
986 | | - const char *dtype = of_get_property(of_root, "device_type", NULL); |
---|
987 | | - |
---|
988 | | - if (dtype == NULL) |
---|
989 | | - return 0; |
---|
990 | | - if (strcmp(dtype, "chrp")) |
---|
| 1023 | + if (!of_node_is_type(of_root, "chrp")) |
---|
991 | 1024 | return 0; |
---|
992 | 1025 | |
---|
993 | 1026 | /* Cell blades firmware claims to be chrp while it's not. Until this |
---|
.. | .. |
---|
1035 | 1068 | .calibrate_decr = generic_calibrate_decr, |
---|
1036 | 1069 | .progress = rtas_progress, |
---|
1037 | 1070 | .system_reset_exception = pSeries_system_reset_exception, |
---|
| 1071 | + .machine_check_early = pseries_machine_check_realmode, |
---|
1038 | 1072 | .machine_check_exception = pSeries_machine_check_exception, |
---|
1039 | 1073 | #ifdef CONFIG_KEXEC_CORE |
---|
1040 | 1074 | .machine_kexec = pSeries_machine_kexec, |
---|