1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * 64-bit pSeries and RS/6000 setup code. |
4 | * |
5 | * Copyright (C) 1995 Linus Torvalds |
6 | * Adapted from 'alpha' version by Gary Thomas |
7 | * Modified by Cort Dougan (cort@cs.nmt.edu) |
8 | * Modified by PPC64 Team, IBM Corp |
9 | */ |
10 | |
11 | /* |
12 | * bootup setup stuff.. |
13 | */ |
14 | |
15 | #include <linux/cpu.h> |
16 | #include <linux/errno.h> |
17 | #include <linux/platform_device.h> |
18 | #include <linux/sched.h> |
19 | #include <linux/kernel.h> |
20 | #include <linux/mm.h> |
21 | #include <linux/stddef.h> |
22 | #include <linux/unistd.h> |
23 | #include <linux/user.h> |
24 | #include <linux/tty.h> |
25 | #include <linux/major.h> |
26 | #include <linux/interrupt.h> |
27 | #include <linux/reboot.h> |
28 | #include <linux/init.h> |
29 | #include <linux/ioport.h> |
30 | #include <linux/console.h> |
31 | #include <linux/pci.h> |
32 | #include <linux/utsname.h> |
33 | #include <linux/adb.h> |
34 | #include <linux/export.h> |
35 | #include <linux/delay.h> |
36 | #include <linux/irq.h> |
37 | #include <linux/seq_file.h> |
38 | #include <linux/root_dev.h> |
39 | #include <linux/of.h> |
40 | #include <linux/of_irq.h> |
41 | #include <linux/of_pci.h> |
42 | #include <linux/memblock.h> |
43 | #include <linux/swiotlb.h> |
44 | #include <linux/seq_buf.h> |
45 | |
46 | #include <asm/mmu.h> |
47 | #include <asm/processor.h> |
48 | #include <asm/io.h> |
49 | #include <asm/rtas.h> |
50 | #include <asm/pci-bridge.h> |
51 | #include <asm/iommu.h> |
52 | #include <asm/dma.h> |
53 | #include <asm/machdep.h> |
54 | #include <asm/irq.h> |
55 | #include <asm/time.h> |
56 | #include <asm/nvram.h> |
57 | #include <asm/pmc.h> |
58 | #include <asm/xics.h> |
59 | #include <asm/xive.h> |
60 | #include <asm/papr-sysparm.h> |
61 | #include <asm/ppc-pci.h> |
62 | #include <asm/i8259.h> |
63 | #include <asm/udbg.h> |
64 | #include <asm/smp.h> |
65 | #include <asm/firmware.h> |
66 | #include <asm/eeh.h> |
67 | #include <asm/reg.h> |
68 | #include <asm/plpar_wrappers.h> |
69 | #include <asm/kexec.h> |
70 | #include <asm/isa-bridge.h> |
71 | #include <asm/security_features.h> |
72 | #include <asm/asm-const.h> |
73 | #include <asm/idle.h> |
74 | #include <asm/swiotlb.h> |
75 | #include <asm/svm.h> |
76 | #include <asm/dtl.h> |
77 | #include <asm/hvconsole.h> |
78 | #include <asm/setup.h> |
79 | |
80 | #include "pseries.h" |
81 | |
82 | DEFINE_STATIC_KEY_FALSE(shared_processor); |
83 | EXPORT_SYMBOL(shared_processor); |
84 | |
85 | #ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING |
86 | struct static_key paravirt_steal_enabled; |
87 | struct static_key paravirt_steal_rq_enabled; |
88 | |
89 | static bool steal_acc = true; |
90 | static int __init parse_no_stealacc(char *arg) |
91 | { |
92 | steal_acc = false; |
93 | return 0; |
94 | } |
95 | |
96 | early_param("no-steal-acc" , parse_no_stealacc); |
97 | #endif |
98 | |
99 | int CMO_PrPSP = -1; |
100 | int CMO_SecPSP = -1; |
101 | unsigned long CMO_PageSize = (ASM_CONST(1) << IOMMU_PAGE_SHIFT_4K); |
102 | EXPORT_SYMBOL(CMO_PageSize); |
103 | |
104 | int fwnmi_active; /* TRUE if an FWNMI handler is present */ |
105 | int ibm_nmi_interlock_token; |
106 | u32 pseries_security_flavor; |
107 | |
108 | static void pSeries_show_cpuinfo(struct seq_file *m) |
109 | { |
110 | struct device_node *root; |
111 | const char *model = "" ; |
112 | |
113 | root = of_find_node_by_path(path: "/" ); |
114 | if (root) |
115 | model = of_get_property(node: root, name: "model" , NULL); |
116 | seq_printf(m, fmt: "machine\t\t: CHRP %s\n" , model); |
117 | of_node_put(node: root); |
118 | if (radix_enabled()) |
119 | seq_printf(m, fmt: "MMU\t\t: Radix\n" ); |
120 | else |
121 | seq_printf(m, fmt: "MMU\t\t: Hash\n" ); |
122 | } |
123 | |
124 | /* Initialize firmware assisted non-maskable interrupts if |
125 | * the firmware supports this feature. |
126 | */ |
127 | static void __init fwnmi_init(void) |
128 | { |
129 | unsigned long system_reset_addr, machine_check_addr; |
130 | u8 *mce_data_buf; |
131 | unsigned int i; |
132 | int nr_cpus = num_possible_cpus(); |
133 | #ifdef CONFIG_PPC_64S_HASH_MMU |
134 | struct slb_entry *slb_ptr; |
135 | size_t size; |
136 | #endif |
137 | int ibm_nmi_register_token; |
138 | |
139 | ibm_nmi_register_token = rtas_function_token(RTAS_FN_IBM_NMI_REGISTER); |
140 | if (ibm_nmi_register_token == RTAS_UNKNOWN_SERVICE) |
141 | return; |
142 | |
143 | ibm_nmi_interlock_token = rtas_function_token(RTAS_FN_IBM_NMI_INTERLOCK); |
144 | if (WARN_ON(ibm_nmi_interlock_token == RTAS_UNKNOWN_SERVICE)) |
145 | return; |
146 | |
147 | /* If the kernel's not linked at zero we point the firmware at low |
148 | * addresses anyway, and use a trampoline to get to the real code. */ |
149 | system_reset_addr = __pa(system_reset_fwnmi) - PHYSICAL_START; |
150 | machine_check_addr = __pa(machine_check_fwnmi) - PHYSICAL_START; |
151 | |
152 | if (0 == rtas_call(ibm_nmi_register_token, 2, 1, NULL, |
153 | system_reset_addr, machine_check_addr)) |
154 | fwnmi_active = 1; |
155 | |
156 | /* |
157 | * Allocate a chunk for per cpu buffer to hold rtas errorlog. |
158 | * It will be used in real mode mce handler, hence it needs to be |
159 | * below RMA. |
160 | */ |
161 | mce_data_buf = memblock_alloc_try_nid_raw(size: RTAS_ERROR_LOG_MAX * nr_cpus, |
162 | align: RTAS_ERROR_LOG_MAX, MEMBLOCK_LOW_LIMIT, |
163 | max_addr: ppc64_rma_size, NUMA_NO_NODE); |
164 | if (!mce_data_buf) |
165 | panic(fmt: "Failed to allocate %d bytes below %pa for MCE buffer\n" , |
166 | RTAS_ERROR_LOG_MAX * nr_cpus, &ppc64_rma_size); |
167 | |
168 | for_each_possible_cpu(i) { |
169 | paca_ptrs[i]->mce_data_buf = mce_data_buf + |
170 | (RTAS_ERROR_LOG_MAX * i); |
171 | } |
172 | |
173 | #ifdef CONFIG_PPC_64S_HASH_MMU |
174 | if (!radix_enabled()) { |
175 | /* Allocate per cpu area to save old slb contents during MCE */ |
176 | size = sizeof(struct slb_entry) * mmu_slb_size * nr_cpus; |
177 | slb_ptr = memblock_alloc_try_nid_raw(size, |
178 | sizeof(struct slb_entry), MEMBLOCK_LOW_LIMIT, |
179 | ppc64_rma_size, NUMA_NO_NODE); |
180 | if (!slb_ptr) |
181 | panic("Failed to allocate %zu bytes below %pa for slb area\n" , |
182 | size, &ppc64_rma_size); |
183 | |
184 | for_each_possible_cpu(i) |
185 | paca_ptrs[i]->mce_faulty_slbs = slb_ptr + (mmu_slb_size * i); |
186 | } |
187 | #endif |
188 | } |
189 | |
190 | /* |
191 | * Affix a device for the first timer to the platform bus if |
192 | * we have firmware support for the H_WATCHDOG hypercall. |
193 | */ |
194 | static __init int pseries_wdt_init(void) |
195 | { |
196 | if (firmware_has_feature(FW_FEATURE_WATCHDOG)) |
197 | platform_device_register_simple(name: "pseries-wdt" , id: 0, NULL, num: 0); |
198 | return 0; |
199 | } |
200 | machine_subsys_initcall(pseries, pseries_wdt_init); |
201 | |
202 | static void pseries_8259_cascade(struct irq_desc *desc) |
203 | { |
204 | struct irq_chip *chip = irq_desc_get_chip(desc); |
205 | unsigned int cascade_irq = i8259_irq(); |
206 | |
207 | if (cascade_irq) |
208 | generic_handle_irq(irq: cascade_irq); |
209 | |
210 | chip->irq_eoi(&desc->irq_data); |
211 | } |
212 | |
213 | static void __init pseries_setup_i8259_cascade(void) |
214 | { |
215 | struct device_node *np, *old, *found = NULL; |
216 | unsigned int cascade; |
217 | const u32 *addrp; |
218 | unsigned long intack = 0; |
219 | int naddr; |
220 | |
221 | for_each_node_by_type(np, "interrupt-controller" ) { |
222 | if (of_device_is_compatible(device: np, "chrp,iic" )) { |
223 | found = np; |
224 | break; |
225 | } |
226 | } |
227 | |
228 | if (found == NULL) { |
229 | printk(KERN_DEBUG "pic: no ISA interrupt controller\n" ); |
230 | return; |
231 | } |
232 | |
233 | cascade = irq_of_parse_and_map(node: found, index: 0); |
234 | if (!cascade) { |
235 | printk(KERN_ERR "pic: failed to map cascade interrupt" ); |
236 | return; |
237 | } |
238 | pr_debug("pic: cascade mapped to irq %d\n" , cascade); |
239 | |
240 | for (old = of_node_get(node: found); old != NULL ; old = np) { |
241 | np = of_get_parent(node: old); |
242 | of_node_put(node: old); |
243 | if (np == NULL) |
244 | break; |
245 | if (!of_node_name_eq(np, name: "pci" )) |
246 | continue; |
247 | addrp = of_get_property(node: np, name: "8259-interrupt-acknowledge" , NULL); |
248 | if (addrp == NULL) |
249 | continue; |
250 | naddr = of_n_addr_cells(np); |
251 | intack = addrp[naddr-1]; |
252 | if (naddr > 1) |
253 | intack |= ((unsigned long)addrp[naddr-2]) << 32; |
254 | } |
255 | if (intack) |
256 | printk(KERN_DEBUG "pic: PCI 8259 intack at 0x%016lx\n" , intack); |
257 | i8259_init(found, intack); |
258 | of_node_put(node: found); |
259 | irq_set_chained_handler(irq: cascade, handle: pseries_8259_cascade); |
260 | } |
261 | |
262 | static void __init pseries_init_irq(void) |
263 | { |
264 | /* Try using a XIVE if available, otherwise use a XICS */ |
265 | if (!xive_spapr_init()) { |
266 | xics_init(); |
267 | pseries_setup_i8259_cascade(); |
268 | } |
269 | } |
270 | |
271 | static void pseries_lpar_enable_pmcs(void) |
272 | { |
273 | unsigned long set, reset; |
274 | |
275 | set = 1UL << 63; |
276 | reset = 0; |
277 | plpar_hcall_norets(H_PERFMON, set, reset); |
278 | } |
279 | |
280 | static int pci_dn_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *data) |
281 | { |
282 | struct of_reconfig_data *rd = data; |
283 | struct device_node *parent, *np = rd->dn; |
284 | struct pci_dn *pdn; |
285 | int err = NOTIFY_OK; |
286 | |
287 | switch (action) { |
288 | case OF_RECONFIG_ATTACH_NODE: |
289 | parent = of_get_parent(node: np); |
290 | pdn = parent ? PCI_DN(parent) : NULL; |
291 | if (pdn) |
292 | pci_add_device_node_info(pdn->phb, np); |
293 | |
294 | of_node_put(node: parent); |
295 | break; |
296 | case OF_RECONFIG_DETACH_NODE: |
297 | pdn = PCI_DN(np); |
298 | if (pdn) |
299 | list_del(entry: &pdn->list); |
300 | break; |
301 | default: |
302 | err = NOTIFY_DONE; |
303 | break; |
304 | } |
305 | return err; |
306 | } |
307 | |
308 | static struct notifier_block pci_dn_reconfig_nb = { |
309 | .notifier_call = pci_dn_reconfig_notifier, |
310 | }; |
311 | |
312 | struct kmem_cache *dtl_cache; |
313 | |
314 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE |
315 | /* |
316 | * Allocate space for the dispatch trace log for all possible cpus |
317 | * and register the buffers with the hypervisor. This is used for |
318 | * computing time stolen by the hypervisor. |
319 | */ |
320 | static int alloc_dispatch_logs(void) |
321 | { |
322 | if (!firmware_has_feature(FW_FEATURE_SPLPAR)) |
323 | return 0; |
324 | |
325 | if (!dtl_cache) |
326 | return 0; |
327 | |
328 | alloc_dtl_buffers(0); |
329 | |
330 | /* Register the DTL for the current (boot) cpu */ |
331 | register_dtl_buffer(smp_processor_id()); |
332 | |
333 | return 0; |
334 | } |
335 | #else /* !CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */ |
336 | static inline int alloc_dispatch_logs(void) |
337 | { |
338 | return 0; |
339 | } |
340 | #endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */ |
341 | |
342 | static int alloc_dispatch_log_kmem_cache(void) |
343 | { |
344 | void (*ctor)(void *) = get_dtl_cache_ctor(); |
345 | |
346 | dtl_cache = kmem_cache_create(name: "dtl" , size: DISPATCH_LOG_BYTES, |
347 | align: DISPATCH_LOG_BYTES, flags: 0, ctor); |
348 | if (!dtl_cache) { |
349 | pr_warn("Failed to create dispatch trace log buffer cache\n" ); |
350 | pr_warn("Stolen time statistics will be unreliable\n" ); |
351 | return 0; |
352 | } |
353 | |
354 | return alloc_dispatch_logs(); |
355 | } |
356 | machine_early_initcall(pseries, alloc_dispatch_log_kmem_cache); |
357 | |
358 | DEFINE_PER_CPU(u64, idle_spurr_cycles); |
359 | DEFINE_PER_CPU(u64, idle_entry_purr_snap); |
360 | DEFINE_PER_CPU(u64, idle_entry_spurr_snap); |
361 | static void pseries_lpar_idle(void) |
362 | { |
363 | /* |
364 | * Default handler to go into low thread priority and possibly |
365 | * low power mode by ceding processor to hypervisor |
366 | */ |
367 | |
368 | if (!prep_irq_for_idle()) |
369 | return; |
370 | |
371 | /* Indicate to hypervisor that we are idle. */ |
372 | pseries_idle_prolog(); |
373 | |
374 | /* |
375 | * Yield the processor to the hypervisor. We return if |
376 | * an external interrupt occurs (which are driven prior |
377 | * to returning here) or if a prod occurs from another |
378 | * processor. When returning here, external interrupts |
379 | * are enabled. |
380 | */ |
381 | cede_processor(); |
382 | |
383 | pseries_idle_epilog(); |
384 | } |
385 | |
386 | static bool pseries_reloc_on_exception_enabled; |
387 | |
388 | bool pseries_reloc_on_exception(void) |
389 | { |
390 | return pseries_reloc_on_exception_enabled; |
391 | } |
392 | EXPORT_SYMBOL_GPL(pseries_reloc_on_exception); |
393 | |
394 | /* |
395 | * Enable relocation on during exceptions. This has partition wide scope and |
396 | * may take a while to complete, if it takes longer than one second we will |
397 | * just give up rather than wasting any more time on this - if that turns out |
398 | * to ever be a problem in practice we can move this into a kernel thread to |
399 | * finish off the process later in boot. |
400 | */ |
401 | bool pseries_enable_reloc_on_exc(void) |
402 | { |
403 | long rc; |
404 | unsigned int delay, total_delay = 0; |
405 | |
406 | while (1) { |
407 | rc = enable_reloc_on_exceptions(); |
408 | if (!H_IS_LONG_BUSY(rc)) { |
409 | if (rc == H_P2) { |
410 | pr_info("Relocation on exceptions not" |
411 | " supported\n" ); |
412 | return false; |
413 | } else if (rc != H_SUCCESS) { |
414 | pr_warn("Unable to enable relocation" |
415 | " on exceptions: %ld\n" , rc); |
416 | return false; |
417 | } |
418 | pseries_reloc_on_exception_enabled = true; |
419 | return true; |
420 | } |
421 | |
422 | delay = get_longbusy_msecs(rc); |
423 | total_delay += delay; |
424 | if (total_delay > 1000) { |
425 | pr_warn("Warning: Giving up waiting to enable " |
426 | "relocation on exceptions (%u msec)!\n" , |
427 | total_delay); |
428 | return false; |
429 | } |
430 | |
431 | mdelay(delay); |
432 | } |
433 | } |
434 | EXPORT_SYMBOL(pseries_enable_reloc_on_exc); |
435 | |
436 | void pseries_disable_reloc_on_exc(void) |
437 | { |
438 | long rc; |
439 | |
440 | while (1) { |
441 | rc = disable_reloc_on_exceptions(); |
442 | if (!H_IS_LONG_BUSY(rc)) |
443 | break; |
444 | mdelay(get_longbusy_msecs(rc)); |
445 | } |
446 | if (rc == H_SUCCESS) |
447 | pseries_reloc_on_exception_enabled = false; |
448 | else |
449 | pr_warn("Warning: Failed to disable relocation on exceptions: %ld\n" , |
450 | rc); |
451 | } |
452 | EXPORT_SYMBOL(pseries_disable_reloc_on_exc); |
453 | |
454 | #ifdef __LITTLE_ENDIAN__ |
455 | void pseries_big_endian_exceptions(void) |
456 | { |
457 | long rc; |
458 | |
459 | while (1) { |
460 | rc = enable_big_endian_exceptions(); |
461 | if (!H_IS_LONG_BUSY(rc)) |
462 | break; |
463 | mdelay(get_longbusy_msecs(rc)); |
464 | } |
465 | |
466 | /* |
467 | * At this point it is unlikely panic() will get anything |
468 | * out to the user, since this is called very late in kexec |
469 | * but at least this will stop us from continuing on further |
470 | * and creating an even more difficult to debug situation. |
471 | * |
472 | * There is a known problem when kdump'ing, if cpus are offline |
473 | * the above call will fail. Rather than panicking again, keep |
474 | * going and hope the kdump kernel is also little endian, which |
475 | * it usually is. |
476 | */ |
477 | if (rc && !kdump_in_progress()) |
478 | panic(fmt: "Could not enable big endian exceptions" ); |
479 | } |
480 | |
481 | void __init pseries_little_endian_exceptions(void) |
482 | { |
483 | long rc; |
484 | |
485 | while (1) { |
486 | rc = enable_little_endian_exceptions(); |
487 | if (!H_IS_LONG_BUSY(rc)) |
488 | break; |
489 | mdelay(get_longbusy_msecs(rc)); |
490 | } |
491 | if (rc) { |
492 | ppc_md.progress("H_SET_MODE LE exception fail" , 0); |
493 | panic(fmt: "Could not enable little endian exceptions" ); |
494 | } |
495 | } |
496 | #endif |
497 | |
498 | static void __init pSeries_discover_phbs(void) |
499 | { |
500 | struct device_node *node; |
501 | struct pci_controller *phb; |
502 | struct device_node *root = of_find_node_by_path(path: "/" ); |
503 | |
504 | for_each_child_of_node(root, node) { |
505 | if (!of_node_is_type(np: node, type: "pci" ) && |
506 | !of_node_is_type(np: node, type: "pciex" )) |
507 | continue; |
508 | |
509 | phb = pcibios_alloc_controller(node); |
510 | if (!phb) |
511 | continue; |
512 | rtas_setup_phb(phb); |
513 | pci_process_bridge_OF_ranges(phb, node, 0); |
514 | isa_bridge_find_early(phb); |
515 | phb->controller_ops = pseries_pci_controller_ops; |
516 | |
517 | /* create pci_dn's for DT nodes under this PHB */ |
518 | pci_devs_phb_init_dynamic(phb); |
519 | |
520 | pseries_msi_allocate_domains(phb); |
521 | } |
522 | |
523 | of_node_put(node: root); |
524 | |
525 | /* |
526 | * PCI_PROBE_ONLY and PCI_REASSIGN_ALL_BUS can be set via properties |
527 | * in chosen. |
528 | */ |
529 | of_pci_check_probe_only(); |
530 | } |
531 | |
532 | static void init_cpu_char_feature_flags(struct h_cpu_char_result *result) |
533 | { |
534 | /* |
535 | * The features below are disabled by default, so we instead look to see |
536 | * if firmware has *enabled* them, and set them if so. |
537 | */ |
538 | if (result->character & H_CPU_CHAR_SPEC_BAR_ORI31) |
539 | security_ftr_set(SEC_FTR_SPEC_BAR_ORI31); |
540 | |
541 | if (result->character & H_CPU_CHAR_BCCTRL_SERIALISED) |
542 | security_ftr_set(SEC_FTR_BCCTRL_SERIALISED); |
543 | |
544 | if (result->character & H_CPU_CHAR_L1D_FLUSH_ORI30) |
545 | security_ftr_set(SEC_FTR_L1D_FLUSH_ORI30); |
546 | |
547 | if (result->character & H_CPU_CHAR_L1D_FLUSH_TRIG2) |
548 | security_ftr_set(SEC_FTR_L1D_FLUSH_TRIG2); |
549 | |
550 | if (result->character & H_CPU_CHAR_L1D_THREAD_PRIV) |
551 | security_ftr_set(SEC_FTR_L1D_THREAD_PRIV); |
552 | |
553 | if (result->character & H_CPU_CHAR_COUNT_CACHE_DISABLED) |
554 | security_ftr_set(SEC_FTR_COUNT_CACHE_DISABLED); |
555 | |
556 | if (result->character & H_CPU_CHAR_BCCTR_FLUSH_ASSIST) |
557 | security_ftr_set(SEC_FTR_BCCTR_FLUSH_ASSIST); |
558 | |
559 | if (result->character & H_CPU_CHAR_BCCTR_LINK_FLUSH_ASSIST) |
560 | security_ftr_set(SEC_FTR_BCCTR_LINK_FLUSH_ASSIST); |
561 | |
562 | if (result->behaviour & H_CPU_BEHAV_FLUSH_COUNT_CACHE) |
563 | security_ftr_set(SEC_FTR_FLUSH_COUNT_CACHE); |
564 | |
565 | if (result->behaviour & H_CPU_BEHAV_FLUSH_LINK_STACK) |
566 | security_ftr_set(SEC_FTR_FLUSH_LINK_STACK); |
567 | |
568 | /* |
569 | * The features below are enabled by default, so we instead look to see |
570 | * if firmware has *disabled* them, and clear them if so. |
571 | * H_CPU_BEHAV_FAVOUR_SECURITY_H could be set only if |
572 | * H_CPU_BEHAV_FAVOUR_SECURITY is. |
573 | */ |
574 | if (!(result->behaviour & H_CPU_BEHAV_FAVOUR_SECURITY)) { |
575 | security_ftr_clear(SEC_FTR_FAVOUR_SECURITY); |
576 | pseries_security_flavor = 0; |
577 | } else if (result->behaviour & H_CPU_BEHAV_FAVOUR_SECURITY_H) |
578 | pseries_security_flavor = 1; |
579 | else |
580 | pseries_security_flavor = 2; |
581 | |
582 | if (!(result->behaviour & H_CPU_BEHAV_L1D_FLUSH_PR)) |
583 | security_ftr_clear(SEC_FTR_L1D_FLUSH_PR); |
584 | |
585 | if (result->behaviour & H_CPU_BEHAV_NO_L1D_FLUSH_ENTRY) |
586 | security_ftr_clear(SEC_FTR_L1D_FLUSH_ENTRY); |
587 | |
588 | if (result->behaviour & H_CPU_BEHAV_NO_L1D_FLUSH_UACCESS) |
589 | security_ftr_clear(SEC_FTR_L1D_FLUSH_UACCESS); |
590 | |
591 | if (result->behaviour & H_CPU_BEHAV_NO_STF_BARRIER) |
592 | security_ftr_clear(SEC_FTR_STF_BARRIER); |
593 | |
594 | if (!(result->behaviour & H_CPU_BEHAV_BNDS_CHK_SPEC_BAR)) |
595 | security_ftr_clear(SEC_FTR_BNDS_CHK_SPEC_BAR); |
596 | } |
597 | |
598 | void pseries_setup_security_mitigations(void) |
599 | { |
600 | struct h_cpu_char_result result; |
601 | enum l1d_flush_type types; |
602 | bool enable; |
603 | long rc; |
604 | |
605 | /* |
606 | * Set features to the defaults assumed by init_cpu_char_feature_flags() |
607 | * so it can set/clear again any features that might have changed after |
608 | * migration, and in case the hypercall fails and it is not even called. |
609 | */ |
610 | powerpc_security_features = SEC_FTR_DEFAULT; |
611 | |
612 | rc = plpar_get_cpu_characteristics(&result); |
613 | if (rc == H_SUCCESS) |
614 | init_cpu_char_feature_flags(result: &result); |
615 | |
616 | /* |
617 | * We're the guest so this doesn't apply to us, clear it to simplify |
618 | * handling of it elsewhere. |
619 | */ |
620 | security_ftr_clear(SEC_FTR_L1D_FLUSH_HV); |
621 | |
622 | types = L1D_FLUSH_FALLBACK; |
623 | |
624 | if (security_ftr_enabled(SEC_FTR_L1D_FLUSH_TRIG2)) |
625 | types |= L1D_FLUSH_MTTRIG; |
626 | |
627 | if (security_ftr_enabled(SEC_FTR_L1D_FLUSH_ORI30)) |
628 | types |= L1D_FLUSH_ORI; |
629 | |
630 | enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) && \ |
631 | security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR); |
632 | |
633 | setup_rfi_flush(types, enable); |
634 | setup_count_cache_flush(); |
635 | |
636 | enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) && |
637 | security_ftr_enabled(SEC_FTR_L1D_FLUSH_ENTRY); |
638 | setup_entry_flush(enable); |
639 | |
640 | enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) && |
641 | security_ftr_enabled(SEC_FTR_L1D_FLUSH_UACCESS); |
642 | setup_uaccess_flush(enable); |
643 | |
644 | setup_stf_barrier(); |
645 | } |
646 | |
647 | #ifdef CONFIG_PCI_IOV |
648 | enum rtas_iov_fw_value_map { |
649 | NUM_RES_PROPERTY = 0, /* Number of Resources */ |
650 | LOW_INT = 1, /* Lowest 32 bits of Address */ |
651 | START_OF_ENTRIES = 2, /* Always start of entry */ |
652 | APERTURE_PROPERTY = 2, /* Start of entry+ to Aperture Size */ |
653 | WDW_SIZE_PROPERTY = 4, /* Start of entry+ to Window Size */ |
654 | NEXT_ENTRY = 7 /* Go to next entry on array */ |
655 | }; |
656 | |
657 | enum get_iov_fw_value_index { |
658 | BAR_ADDRS = 1, /* Get Bar Address */ |
659 | APERTURE_SIZE = 2, /* Get Aperture Size */ |
660 | WDW_SIZE = 3 /* Get Window Size */ |
661 | }; |
662 | |
663 | static resource_size_t pseries_get_iov_fw_value(struct pci_dev *dev, int resno, |
664 | enum get_iov_fw_value_index value) |
665 | { |
666 | const int *indexes; |
667 | struct device_node *dn = pci_device_to_OF_node(pdev: dev); |
668 | int i, num_res, ret = 0; |
669 | |
670 | indexes = of_get_property(node: dn, name: "ibm,open-sriov-vf-bar-info" , NULL); |
671 | if (!indexes) |
672 | return 0; |
673 | |
674 | /* |
675 | * First element in the array is the number of Bars |
676 | * returned. Search through the list to find the matching |
677 | * bar |
678 | */ |
679 | num_res = of_read_number(cell: &indexes[NUM_RES_PROPERTY], size: 1); |
680 | if (resno >= num_res) |
681 | return 0; /* or an error */ |
682 | |
683 | i = START_OF_ENTRIES + NEXT_ENTRY * resno; |
684 | switch (value) { |
685 | case BAR_ADDRS: |
686 | ret = of_read_number(cell: &indexes[i], size: 2); |
687 | break; |
688 | case APERTURE_SIZE: |
689 | ret = of_read_number(cell: &indexes[i + APERTURE_PROPERTY], size: 2); |
690 | break; |
691 | case WDW_SIZE: |
692 | ret = of_read_number(cell: &indexes[i + WDW_SIZE_PROPERTY], size: 2); |
693 | break; |
694 | } |
695 | |
696 | return ret; |
697 | } |
698 | |
699 | static void of_pci_set_vf_bar_size(struct pci_dev *dev, const int *indexes) |
700 | { |
701 | struct resource *res; |
702 | resource_size_t base, size; |
703 | int i, r, num_res; |
704 | |
705 | num_res = of_read_number(cell: &indexes[NUM_RES_PROPERTY], size: 1); |
706 | num_res = min_t(int, num_res, PCI_SRIOV_NUM_BARS); |
707 | for (i = START_OF_ENTRIES, r = 0; r < num_res && r < PCI_SRIOV_NUM_BARS; |
708 | i += NEXT_ENTRY, r++) { |
709 | res = &dev->resource[r + PCI_IOV_RESOURCES]; |
710 | base = of_read_number(cell: &indexes[i], size: 2); |
711 | size = of_read_number(cell: &indexes[i + APERTURE_PROPERTY], size: 2); |
712 | res->flags = pci_parse_of_flags(of_read_number |
713 | (cell: &indexes[i + LOW_INT], size: 1), 0); |
714 | res->flags |= (IORESOURCE_MEM_64 | IORESOURCE_PCI_FIXED); |
715 | res->name = pci_name(pdev: dev); |
716 | res->start = base; |
717 | res->end = base + size - 1; |
718 | } |
719 | } |
720 | |
721 | static void of_pci_parse_iov_addrs(struct pci_dev *dev, const int *indexes) |
722 | { |
723 | struct resource *res, *root, *conflict; |
724 | resource_size_t base, size; |
725 | int i, r, num_res; |
726 | |
727 | /* |
728 | * First element in the array is the number of Bars |
729 | * returned. Search through the list to find the matching |
730 | * bars assign them from firmware into resources structure. |
731 | */ |
732 | num_res = of_read_number(cell: &indexes[NUM_RES_PROPERTY], size: 1); |
733 | for (i = START_OF_ENTRIES, r = 0; r < num_res && r < PCI_SRIOV_NUM_BARS; |
734 | i += NEXT_ENTRY, r++) { |
735 | res = &dev->resource[r + PCI_IOV_RESOURCES]; |
736 | base = of_read_number(cell: &indexes[i], size: 2); |
737 | size = of_read_number(cell: &indexes[i + WDW_SIZE_PROPERTY], size: 2); |
738 | res->name = pci_name(pdev: dev); |
739 | res->start = base; |
740 | res->end = base + size - 1; |
741 | root = &iomem_resource; |
742 | dev_dbg(&dev->dev, |
743 | "pSeries IOV BAR %d: trying firmware assignment %pR\n" , |
744 | r + PCI_IOV_RESOURCES, res); |
745 | conflict = request_resource_conflict(root, new: res); |
746 | if (conflict) { |
747 | dev_info(&dev->dev, |
748 | "BAR %d: %pR conflicts with %s %pR\n" , |
749 | r + PCI_IOV_RESOURCES, res, |
750 | conflict->name, conflict); |
751 | res->flags |= IORESOURCE_UNSET; |
752 | } |
753 | } |
754 | } |
755 | |
756 | static void pseries_disable_sriov_resources(struct pci_dev *pdev) |
757 | { |
758 | int i; |
759 | |
760 | pci_warn(pdev, "No hypervisor support for SR-IOV on this device, IOV BARs disabled.\n" ); |
761 | for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) |
762 | pdev->resource[i + PCI_IOV_RESOURCES].flags = 0; |
763 | } |
764 | |
765 | static void pseries_pci_fixup_resources(struct pci_dev *pdev) |
766 | { |
767 | const int *indexes; |
768 | struct device_node *dn = pci_device_to_OF_node(pdev); |
769 | |
770 | /*Firmware must support open sriov otherwise dont configure*/ |
771 | indexes = of_get_property(node: dn, name: "ibm,open-sriov-vf-bar-info" , NULL); |
772 | if (indexes) |
773 | of_pci_set_vf_bar_size(dev: pdev, indexes); |
774 | else |
775 | pseries_disable_sriov_resources(pdev); |
776 | } |
777 | |
778 | static void pseries_pci_fixup_iov_resources(struct pci_dev *pdev) |
779 | { |
780 | const int *indexes; |
781 | struct device_node *dn = pci_device_to_OF_node(pdev); |
782 | |
783 | if (!pdev->is_physfn) |
784 | return; |
785 | /*Firmware must support open sriov otherwise don't configure*/ |
786 | indexes = of_get_property(node: dn, name: "ibm,open-sriov-vf-bar-info" , NULL); |
787 | if (indexes) |
788 | of_pci_parse_iov_addrs(dev: pdev, indexes); |
789 | else |
790 | pseries_disable_sriov_resources(pdev); |
791 | } |
792 | |
793 | static resource_size_t pseries_pci_iov_resource_alignment(struct pci_dev *pdev, |
794 | int resno) |
795 | { |
796 | const __be32 *reg; |
797 | struct device_node *dn = pci_device_to_OF_node(pdev); |
798 | |
799 | /*Firmware must support open sriov otherwise report regular alignment*/ |
800 | reg = of_get_property(node: dn, name: "ibm,is-open-sriov-pf" , NULL); |
801 | if (!reg) |
802 | return pci_iov_resource_size(dev: pdev, resno); |
803 | |
804 | if (!pdev->is_physfn) |
805 | return 0; |
806 | return pseries_get_iov_fw_value(dev: pdev, |
807 | resno: resno - PCI_IOV_RESOURCES, |
808 | value: APERTURE_SIZE); |
809 | } |
810 | #endif |
811 | |
812 | static void __init pSeries_setup_arch(void) |
813 | { |
814 | set_arch_panic_timeout(10, ARCH_PANIC_TIMEOUT); |
815 | |
816 | /* Discover PIC type and setup ppc_md accordingly */ |
817 | smp_init_pseries(); |
818 | |
819 | // Setup CPU hotplug callbacks |
820 | pseries_cpu_hotplug_init(); |
821 | |
822 | if (radix_enabled() && !mmu_has_feature(MMU_FTR_GTSE)) |
823 | if (!firmware_has_feature(FW_FEATURE_RPT_INVALIDATE)) |
824 | panic(fmt: "BUG: Radix support requires either GTSE or RPT_INVALIDATE\n" ); |
825 | |
826 | |
827 | /* openpic global configuration register (64-bit format). */ |
828 | /* openpic Interrupt Source Unit pointer (64-bit format). */ |
829 | /* python0 facility area (mmio) (64-bit format) REAL address. */ |
830 | |
831 | /* init to some ~sane value until calibrate_delay() runs */ |
832 | loops_per_jiffy = 50000000; |
833 | |
834 | fwnmi_init(); |
835 | |
836 | pseries_setup_security_mitigations(); |
837 | if (!radix_enabled()) |
838 | pseries_lpar_read_hblkrm_characteristics(); |
839 | |
840 | /* By default, only probe PCI (can be overridden by rtas_pci) */ |
841 | pci_add_flags(flags: PCI_PROBE_ONLY); |
842 | |
843 | /* Find and initialize PCI host bridges */ |
844 | init_pci_config_tokens(); |
845 | of_reconfig_notifier_register(&pci_dn_reconfig_nb); |
846 | |
847 | pSeries_nvram_init(); |
848 | |
849 | if (firmware_has_feature(FW_FEATURE_LPAR)) { |
850 | vpa_init(boot_cpuid); |
851 | |
852 | if (lppaca_shared_proc()) { |
853 | static_branch_enable(&shared_processor); |
854 | pv_spinlocks_init(); |
855 | #ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING |
856 | static_key_slow_inc(key: ¶virt_steal_enabled); |
857 | if (steal_acc) |
858 | static_key_slow_inc(key: ¶virt_steal_rq_enabled); |
859 | #endif |
860 | } |
861 | |
862 | ppc_md.power_save = pseries_lpar_idle; |
863 | ppc_md.enable_pmcs = pseries_lpar_enable_pmcs; |
864 | #ifdef CONFIG_PCI_IOV |
865 | ppc_md.pcibios_fixup_resources = |
866 | pseries_pci_fixup_resources; |
867 | ppc_md.pcibios_fixup_sriov = |
868 | pseries_pci_fixup_iov_resources; |
869 | ppc_md.pcibios_iov_resource_alignment = |
870 | pseries_pci_iov_resource_alignment; |
871 | #endif |
872 | } else { |
873 | /* No special idle routine */ |
874 | ppc_md.enable_pmcs = power4_enable_pmcs; |
875 | } |
876 | |
877 | ppc_md.pcibios_root_bridge_prepare = pseries_root_bridge_prepare; |
878 | pseries_rng_init(); |
879 | } |
880 | |
881 | static void pseries_panic(char *str) |
882 | { |
883 | panic_flush_kmsg_end(); |
884 | rtas_os_term(str); |
885 | } |
886 | |
887 | static int __init pSeries_init_panel(void) |
888 | { |
889 | /* Manually leave the kernel version on the panel. */ |
890 | #ifdef __BIG_ENDIAN__ |
891 | ppc_md.progress("Linux ppc64\n" , 0); |
892 | #else |
893 | ppc_md.progress("Linux ppc64le\n" , 0); |
894 | #endif |
895 | ppc_md.progress(init_utsname()->version, 0); |
896 | |
897 | return 0; |
898 | } |
899 | machine_arch_initcall(pseries, pSeries_init_panel); |
900 | |
901 | static int pseries_set_dabr(unsigned long dabr, unsigned long dabrx) |
902 | { |
903 | return plpar_hcall_norets(H_SET_DABR, dabr); |
904 | } |
905 | |
906 | static int pseries_set_xdabr(unsigned long dabr, unsigned long dabrx) |
907 | { |
908 | /* Have to set at least one bit in the DABRX according to PAPR */ |
909 | if (dabrx == 0 && dabr == 0) |
910 | dabrx = DABRX_USER; |
911 | /* PAPR says we can only set kernel and user bits */ |
912 | dabrx &= DABRX_KERNEL | DABRX_USER; |
913 | |
914 | return plpar_hcall_norets(H_SET_XDABR, dabr, dabrx); |
915 | } |
916 | |
917 | static int pseries_set_dawr(int nr, unsigned long dawr, unsigned long dawrx) |
918 | { |
919 | /* PAPR says we can't set HYP */ |
920 | dawrx &= ~DAWRX_HYP; |
921 | |
922 | if (nr == 0) |
923 | return plpar_set_watchpoint0(dawr, dawrx); |
924 | else |
925 | return plpar_set_watchpoint1(dawr, dawrx); |
926 | } |
927 | |
928 | #define CMO_CHARACTERISTICS_TOKEN 44 |
929 | #define CMO_MAXLENGTH 1026 |
930 | |
931 | void pSeries_coalesce_init(void) |
932 | { |
933 | struct hvcall_mpp_x_data mpp_x_data; |
934 | |
935 | if (firmware_has_feature(FW_FEATURE_CMO) && !h_get_mpp_x(&mpp_x_data)) |
936 | powerpc_firmware_features |= FW_FEATURE_XCMO; |
937 | else |
938 | powerpc_firmware_features &= ~FW_FEATURE_XCMO; |
939 | } |
940 | |
941 | /** |
942 | * fw_cmo_feature_init - FW_FEATURE_CMO is not stored in ibm,hypertas-functions, |
943 | * handle that here. (Stolen from parse_system_parameter_string) |
944 | */ |
945 | static void __init pSeries_cmo_feature_init(void) |
946 | { |
947 | static struct papr_sysparm_buf buf __initdata; |
948 | static_assert(sizeof(buf.val) >= CMO_MAXLENGTH); |
949 | char *ptr, *key, *value, *end; |
950 | int page_order = IOMMU_PAGE_SHIFT_4K; |
951 | |
952 | pr_debug(" -> fw_cmo_feature_init()\n" ); |
953 | |
954 | if (papr_sysparm_get(PAPR_SYSPARM_COOP_MEM_OVERCOMMIT_ATTRS, &buf)) { |
955 | pr_debug("CMO not available\n" ); |
956 | pr_debug(" <- fw_cmo_feature_init()\n" ); |
957 | return; |
958 | } |
959 | |
960 | end = &buf.val[CMO_MAXLENGTH]; |
961 | ptr = &buf.val[0]; |
962 | key = value = ptr; |
963 | |
964 | while (*ptr && (ptr <= end)) { |
965 | /* Separate the key and value by replacing '=' with '\0' and |
966 | * point the value at the string after the '=' |
967 | */ |
968 | if (ptr[0] == '=') { |
969 | ptr[0] = '\0'; |
970 | value = ptr + 1; |
971 | } else if (ptr[0] == '\0' || ptr[0] == ',') { |
972 | /* Terminate the string containing the key/value pair */ |
973 | ptr[0] = '\0'; |
974 | |
975 | if (key == value) { |
976 | pr_debug("Malformed key/value pair\n" ); |
977 | /* Never found a '=', end processing */ |
978 | break; |
979 | } |
980 | |
981 | if (0 == strcmp(key, "CMOPageSize" )) |
982 | page_order = simple_strtol(value, NULL, 10); |
983 | else if (0 == strcmp(key, "PrPSP" )) |
984 | CMO_PrPSP = simple_strtol(value, NULL, 10); |
985 | else if (0 == strcmp(key, "SecPSP" )) |
986 | CMO_SecPSP = simple_strtol(value, NULL, 10); |
987 | value = key = ptr + 1; |
988 | } |
989 | ptr++; |
990 | } |
991 | |
992 | /* Page size is returned as the power of 2 of the page size, |
993 | * convert to the page size in bytes before returning |
994 | */ |
995 | CMO_PageSize = 1 << page_order; |
996 | pr_debug("CMO_PageSize = %lu\n" , CMO_PageSize); |
997 | |
998 | if (CMO_PrPSP != -1 || CMO_SecPSP != -1) { |
999 | pr_info("CMO enabled\n" ); |
1000 | pr_debug("CMO enabled, PrPSP=%d, SecPSP=%d\n" , CMO_PrPSP, |
1001 | CMO_SecPSP); |
1002 | powerpc_firmware_features |= FW_FEATURE_CMO; |
1003 | pSeries_coalesce_init(); |
1004 | } else |
1005 | pr_debug("CMO not enabled, PrPSP=%d, SecPSP=%d\n" , CMO_PrPSP, |
1006 | CMO_SecPSP); |
1007 | pr_debug(" <- fw_cmo_feature_init()\n" ); |
1008 | } |
1009 | |
1010 | static void __init pseries_add_hw_description(void) |
1011 | { |
1012 | struct device_node *dn; |
1013 | const char *s; |
1014 | |
1015 | dn = of_find_node_by_path(path: "/openprom" ); |
1016 | if (dn) { |
1017 | if (of_property_read_string(dn, "model" , &s) == 0) |
1018 | seq_buf_printf(&ppc_hw_desc, "of:%s " , s); |
1019 | |
1020 | of_node_put(node: dn); |
1021 | } |
1022 | |
1023 | dn = of_find_node_by_path(path: "/hypervisor" ); |
1024 | if (dn) { |
1025 | if (of_property_read_string(dn, "compatible" , &s) == 0) |
1026 | seq_buf_printf(&ppc_hw_desc, "hv:%s " , s); |
1027 | |
1028 | of_node_put(node: dn); |
1029 | return; |
1030 | } |
1031 | |
1032 | dn = of_find_node_by_path(path: "/" ); |
1033 | if (of_property_read_bool(dn, "ibm,powervm-partition" ) || |
1034 | of_property_read_bool(dn, "ibm,fw-net-version" )) |
1035 | seq_buf_printf(&ppc_hw_desc, "hv:phyp " ); |
1036 | of_node_put(node: dn); |
1037 | } |
1038 | |
1039 | /* |
1040 | * Early initialization. Relocation is on but do not reference unbolted pages |
1041 | */ |
1042 | static void __init pseries_init(void) |
1043 | { |
1044 | pr_debug(" -> pseries_init()\n" ); |
1045 | |
1046 | pseries_add_hw_description(); |
1047 | |
1048 | #ifdef CONFIG_HVC_CONSOLE |
1049 | if (firmware_has_feature(FW_FEATURE_LPAR)) |
1050 | hvc_vio_init_early(); |
1051 | #endif |
1052 | if (firmware_has_feature(FW_FEATURE_XDABR)) |
1053 | ppc_md.set_dabr = pseries_set_xdabr; |
1054 | else if (firmware_has_feature(FW_FEATURE_DABR)) |
1055 | ppc_md.set_dabr = pseries_set_dabr; |
1056 | |
1057 | if (firmware_has_feature(FW_FEATURE_SET_MODE)) |
1058 | ppc_md.set_dawr = pseries_set_dawr; |
1059 | |
1060 | pSeries_cmo_feature_init(); |
1061 | iommu_init_early_pSeries(); |
1062 | |
1063 | pr_debug(" <- pseries_init()\n" ); |
1064 | } |
1065 | |
1066 | /** |
1067 | * pseries_power_off - tell firmware about how to power off the system. |
1068 | * |
1069 | * This function calls either the power-off rtas token in normal cases |
1070 | * or the ibm,power-off-ups token (if present & requested) in case of |
1071 | * a power failure. If power-off token is used, power on will only be |
1072 | * possible with power button press. If ibm,power-off-ups token is used |
1073 | * it will allow auto poweron after power is restored. |
1074 | */ |
1075 | static void pseries_power_off(void) |
1076 | { |
1077 | int rc; |
1078 | int rtas_poweroff_ups_token = rtas_function_token(RTAS_FN_IBM_POWER_OFF_UPS); |
1079 | |
1080 | if (rtas_flash_term_hook) |
1081 | rtas_flash_term_hook(SYS_POWER_OFF); |
1082 | |
1083 | if (rtas_poweron_auto == 0 || |
1084 | rtas_poweroff_ups_token == RTAS_UNKNOWN_SERVICE) { |
1085 | rc = rtas_call(rtas_function_token(RTAS_FN_POWER_OFF), 2, 1, NULL, -1, -1); |
1086 | printk(KERN_INFO "RTAS power-off returned %d\n" , rc); |
1087 | } else { |
1088 | rc = rtas_call(rtas_poweroff_ups_token, 0, 1, NULL); |
1089 | printk(KERN_INFO "RTAS ibm,power-off-ups returned %d\n" , rc); |
1090 | } |
1091 | for (;;); |
1092 | } |
1093 | |
1094 | static int __init pSeries_probe(void) |
1095 | { |
1096 | struct device_node *root = of_find_node_by_path(path: "/" ); |
1097 | bool ret = of_node_is_type(np: root, type: "chrp" ); |
1098 | |
1099 | of_node_put(node: root); |
1100 | if (!ret) |
1101 | return 0; |
1102 | |
1103 | /* Cell blades firmware claims to be chrp while it's not. Until this |
1104 | * is fixed, we need to avoid those here. |
1105 | */ |
1106 | if (of_machine_is_compatible(compat: "IBM,CPBW-1.0" ) || |
1107 | of_machine_is_compatible(compat: "IBM,CBEA" )) |
1108 | return 0; |
1109 | |
1110 | pm_power_off = pseries_power_off; |
1111 | |
1112 | pr_debug("Machine is%s LPAR !\n" , |
1113 | (powerpc_firmware_features & FW_FEATURE_LPAR) ? "" : " not" ); |
1114 | |
1115 | pseries_init(); |
1116 | |
1117 | return 1; |
1118 | } |
1119 | |
1120 | static int pSeries_pci_probe_mode(struct pci_bus *bus) |
1121 | { |
1122 | if (firmware_has_feature(FW_FEATURE_LPAR)) |
1123 | return PCI_PROBE_DEVTREE; |
1124 | return PCI_PROBE_NORMAL; |
1125 | } |
1126 | |
1127 | #ifdef CONFIG_MEMORY_HOTPLUG |
1128 | static unsigned long pseries_memory_block_size(void) |
1129 | { |
1130 | return memory_block_size; |
1131 | } |
1132 | #endif |
1133 | |
1134 | struct pci_controller_ops pseries_pci_controller_ops = { |
1135 | .probe_mode = pSeries_pci_probe_mode, |
1136 | #ifdef CONFIG_SPAPR_TCE_IOMMU |
1137 | .device_group = pSeries_pci_device_group, |
1138 | #endif |
1139 | }; |
1140 | |
1141 | define_machine(pseries) { |
1142 | .name = "pSeries" , |
1143 | .probe = pSeries_probe, |
1144 | .setup_arch = pSeries_setup_arch, |
1145 | .init_IRQ = pseries_init_irq, |
1146 | .show_cpuinfo = pSeries_show_cpuinfo, |
1147 | .log_error = pSeries_log_error, |
1148 | .discover_phbs = pSeries_discover_phbs, |
1149 | .pcibios_fixup = pSeries_final_fixup, |
1150 | .restart = rtas_restart, |
1151 | .halt = rtas_halt, |
1152 | .panic = pseries_panic, |
1153 | .get_boot_time = rtas_get_boot_time, |
1154 | .get_rtc_time = rtas_get_rtc_time, |
1155 | .set_rtc_time = rtas_set_rtc_time, |
1156 | .progress = rtas_progress, |
1157 | .system_reset_exception = pSeries_system_reset_exception, |
1158 | .machine_check_early = pseries_machine_check_realmode, |
1159 | .machine_check_exception = pSeries_machine_check_exception, |
1160 | .machine_check_log_err = pSeries_machine_check_log_err, |
1161 | #ifdef CONFIG_KEXEC_CORE |
1162 | .machine_kexec = pseries_machine_kexec, |
1163 | .kexec_cpu_down = pseries_kexec_cpu_down, |
1164 | #endif |
1165 | #ifdef CONFIG_MEMORY_HOTPLUG |
1166 | .memory_block_size = pseries_memory_block_size, |
1167 | #endif |
1168 | }; |
1169 | |