^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * ePAPR para-virtualization support.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2012 Freescale Semiconductor, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/of_fdt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <asm/epapr_hcalls.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <asm/cacheflush.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <asm/code-patching.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <asm/machdep.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <asm/inst.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #if !defined(CONFIG_64BIT) || defined(CONFIG_PPC_BOOK3E_64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) extern void epapr_ev_idle(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) extern u32 epapr_ev_idle_start[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) bool epapr_paravirt_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) static bool __maybe_unused epapr_has_idle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) static int __init early_init_dt_scan_epapr(unsigned long node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) const char *uname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) int depth, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) const u32 *insts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) insts = of_get_flat_dt_prop(node, "hcall-instructions", &len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) if (!insts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) if (len % 4 || len > (4 * 4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) for (i = 0; i < (len / 4); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) struct ppc_inst inst = ppc_inst(be32_to_cpu(insts[i]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) patch_instruction((struct ppc_inst *)(epapr_hypercall_start + i), inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #if !defined(CONFIG_64BIT) || defined(CONFIG_PPC_BOOK3E_64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) patch_instruction((struct ppc_inst *)(epapr_ev_idle_start + i), inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #if !defined(CONFIG_64BIT) || defined(CONFIG_PPC_BOOK3E_64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) if (of_get_flat_dt_prop(node, "has-idle", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) epapr_has_idle = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) epapr_paravirt_enabled = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) int __init epapr_paravirt_early_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) of_scan_flat_dt(early_init_dt_scan_epapr, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static int __init epapr_idle_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #if !defined(CONFIG_64BIT) || defined(CONFIG_PPC_BOOK3E_64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (epapr_has_idle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) ppc_md.power_save = epapr_ev_idle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) postcore_initcall(epapr_idle_init);