Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *  Copyright (C) 2001 Ben. Herrenschmidt (benh@kernel.crashing.org)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *  Modifications for ppc64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *      Copyright (C) 2003 Dave Engebretsen <engebret@us.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  *  Copyright 2008 Michael Ellerman, IBM Corporation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/jump_label.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/sched/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/stop_machine.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <asm/cputable.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <asm/code-patching.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <asm/page.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <asm/sections.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include <asm/setup.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include <asm/security_features.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #include <asm/firmware.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #include <asm/inst.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) struct fixup_entry {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	unsigned long	mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	unsigned long	value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	long		start_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	long		end_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	long		alt_start_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	long		alt_end_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) static struct ppc_inst *calc_addr(struct fixup_entry *fcur, long offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	 * We store the offset to the code as a negative offset from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	 * the start of the alt_entry, to support the VDSO. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	 * routine converts that back into an actual address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	return (struct ppc_inst *)((unsigned long)fcur + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) static int patch_alt_instruction(struct ppc_inst *src, struct ppc_inst *dest,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 				 struct ppc_inst *alt_start, struct ppc_inst *alt_end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	struct ppc_inst instr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	instr = ppc_inst_read(src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	if (instr_is_relative_branch(*src)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 		struct ppc_inst *target = (struct ppc_inst *)branch_target(src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 		/* Branch within the section doesn't need translating */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 		if (target < alt_start || target > alt_end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 			err = translate_branch(&instr, dest, src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 			if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 				return 1;
^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) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	raw_patch_instruction(dest, instr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) static int patch_feature_section(unsigned long value, struct fixup_entry *fcur)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	struct ppc_inst *start, *end, *alt_start, *alt_end, *src, *dest, nop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	start = calc_addr(fcur, fcur->start_off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	end = calc_addr(fcur, fcur->end_off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	alt_start = calc_addr(fcur, fcur->alt_start_off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	alt_end = calc_addr(fcur, fcur->alt_end_off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	if ((alt_end - alt_start) > (end - start))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	if ((value & fcur->mask) == fcur->value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	src = alt_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	dest = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	for (; src < alt_end; src = ppc_inst_next(src, src),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 			      dest = ppc_inst_next(dest, dest)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 		if (patch_alt_instruction(src, dest, alt_start, alt_end))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 			return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	nop = ppc_inst(PPC_INST_NOP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	for (; dest < end; dest = ppc_inst_next(dest, &nop))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 		raw_patch_instruction(dest, nop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) void do_feature_fixups(unsigned long value, void *fixup_start, void *fixup_end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	struct fixup_entry *fcur, *fend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	fcur = fixup_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	fend = fixup_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	for (; fcur < fend; fcur++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 		if (patch_feature_section(value, fcur)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 			WARN_ON(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 			printk("Unable to patch feature section at %p - %p" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 				" with %p - %p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 				calc_addr(fcur, fcur->start_off),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 				calc_addr(fcur, fcur->end_off),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 				calc_addr(fcur, fcur->alt_start_off),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 				calc_addr(fcur, fcur->alt_end_off));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #ifdef CONFIG_PPC_BOOK3S_64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) static void do_stf_entry_barrier_fixups(enum stf_barrier_type types)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	unsigned int instrs[3], *dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	long *start, *end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	start = PTRRELOC(&__start___stf_entry_barrier_fixup),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	end = PTRRELOC(&__stop___stf_entry_barrier_fixup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	instrs[0] = 0x60000000; /* nop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	instrs[1] = 0x60000000; /* nop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	instrs[2] = 0x60000000; /* nop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	if (types & STF_BARRIER_FALLBACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 		instrs[i++] = 0x7d4802a6; /* mflr r10		*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 		instrs[i++] = 0x60000000; /* branch patched below */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 		instrs[i++] = 0x7d4803a6; /* mtlr r10		*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	} else if (types & STF_BARRIER_EIEIO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 		instrs[i++] = 0x7e0006ac; /* eieio + bit 6 hint */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	} else if (types & STF_BARRIER_SYNC_ORI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 		instrs[i++] = 0x7c0004ac; /* hwsync		*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 		instrs[i++] = 0xe94d0000; /* ld r10,0(r13)	*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 		instrs[i++] = 0x63ff0000; /* ori 31,31,0 speculation barrier */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	for (i = 0; start < end; start++, i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 		dest = (void *)start + *start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 		pr_devel("patching dest %lx\n", (unsigned long)dest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 		patch_instruction((struct ppc_inst *)dest, ppc_inst(instrs[0]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		if (types & STF_BARRIER_FALLBACK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 			patch_branch((struct ppc_inst *)(dest + 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 				     (unsigned long)&stf_barrier_fallback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 				     BRANCH_SET_LINK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 			patch_instruction((struct ppc_inst *)(dest + 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 					  ppc_inst(instrs[1]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 		patch_instruction((struct ppc_inst *)(dest + 2), ppc_inst(instrs[2]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	printk(KERN_DEBUG "stf-barrier: patched %d entry locations (%s barrier)\n", i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 		(types == STF_BARRIER_NONE)                  ? "no" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 		(types == STF_BARRIER_FALLBACK)              ? "fallback" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 		(types == STF_BARRIER_EIEIO)                 ? "eieio" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 		(types == (STF_BARRIER_SYNC_ORI))            ? "hwsync"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 		                                           : "unknown");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) static void do_stf_exit_barrier_fixups(enum stf_barrier_type types)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	unsigned int instrs[6], *dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	long *start, *end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	start = PTRRELOC(&__start___stf_exit_barrier_fixup),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	end = PTRRELOC(&__stop___stf_exit_barrier_fixup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	instrs[0] = 0x60000000; /* nop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	instrs[1] = 0x60000000; /* nop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	instrs[2] = 0x60000000; /* nop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	instrs[3] = 0x60000000; /* nop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	instrs[4] = 0x60000000; /* nop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	instrs[5] = 0x60000000; /* nop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	if (types & STF_BARRIER_FALLBACK || types & STF_BARRIER_SYNC_ORI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 		if (cpu_has_feature(CPU_FTR_HVMODE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 			instrs[i++] = 0x7db14ba6; /* mtspr 0x131, r13 (HSPRG1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 			instrs[i++] = 0x7db04aa6; /* mfspr r13, 0x130 (HSPRG0) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 			instrs[i++] = 0x7db243a6; /* mtsprg 2,r13	*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 			instrs[i++] = 0x7db142a6; /* mfsprg r13,1    */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	        }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 		instrs[i++] = 0x7c0004ac; /* hwsync		*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 		instrs[i++] = 0xe9ad0000; /* ld r13,0(r13)	*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 		instrs[i++] = 0x63ff0000; /* ori 31,31,0 speculation barrier */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 		if (cpu_has_feature(CPU_FTR_HVMODE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 			instrs[i++] = 0x7db14aa6; /* mfspr r13, 0x131 (HSPRG1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 			instrs[i++] = 0x7db242a6; /* mfsprg r13,2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	} else if (types & STF_BARRIER_EIEIO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 		instrs[i++] = 0x7e0006ac; /* eieio + bit 6 hint */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	for (i = 0; start < end; start++, i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 		dest = (void *)start + *start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 		pr_devel("patching dest %lx\n", (unsigned long)dest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 		patch_instruction((struct ppc_inst *)dest, ppc_inst(instrs[0]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 		patch_instruction((struct ppc_inst *)(dest + 1), ppc_inst(instrs[1]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 		patch_instruction((struct ppc_inst *)(dest + 2), ppc_inst(instrs[2]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 		patch_instruction((struct ppc_inst *)(dest + 3), ppc_inst(instrs[3]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 		patch_instruction((struct ppc_inst *)(dest + 4), ppc_inst(instrs[4]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 		patch_instruction((struct ppc_inst *)(dest + 5), ppc_inst(instrs[5]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	printk(KERN_DEBUG "stf-barrier: patched %d exit locations (%s barrier)\n", i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 		(types == STF_BARRIER_NONE)                  ? "no" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 		(types == STF_BARRIER_FALLBACK)              ? "fallback" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 		(types == STF_BARRIER_EIEIO)                 ? "eieio" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 		(types == (STF_BARRIER_SYNC_ORI))            ? "hwsync"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 		                                           : "unknown");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) static int __do_stf_barrier_fixups(void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 	enum stf_barrier_type *types = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	do_stf_entry_barrier_fixups(*types);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	do_stf_exit_barrier_fixups(*types);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) void do_stf_barrier_fixups(enum stf_barrier_type types)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	 * The call to the fallback entry flush, and the fallback/sync-ori exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	 * flush can not be safely patched in/out while other CPUs are executing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	 * them. So call __do_stf_barrier_fixups() on one CPU while all other CPUs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	 * spin in the stop machine core with interrupts hard disabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	stop_machine(__do_stf_barrier_fixups, &types, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) void do_uaccess_flush_fixups(enum l1d_flush_type types)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	unsigned int instrs[4], *dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	long *start, *end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	start = PTRRELOC(&__start___uaccess_flush_fixup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	end = PTRRELOC(&__stop___uaccess_flush_fixup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	instrs[0] = 0x60000000; /* nop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	instrs[1] = 0x60000000; /* nop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	instrs[2] = 0x60000000; /* nop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	instrs[3] = 0x4e800020; /* blr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 	i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	if (types == L1D_FLUSH_FALLBACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 		instrs[3] = 0x60000000; /* nop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 		/* fallthrough to fallback flush */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	if (types & L1D_FLUSH_ORI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 		instrs[i++] = 0x63ff0000; /* ori 31,31,0 speculation barrier */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 		instrs[i++] = 0x63de0000; /* ori 30,30,0 L1d flush*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	if (types & L1D_FLUSH_MTTRIG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 		instrs[i++] = 0x7c12dba6; /* mtspr TRIG2,r0 (SPR #882) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	for (i = 0; start < end; start++, i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 		dest = (void *)start + *start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 		pr_devel("patching dest %lx\n", (unsigned long)dest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 		patch_instruction((struct ppc_inst *)dest, ppc_inst(instrs[0]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 		patch_instruction((struct ppc_inst *)(dest + 1), ppc_inst(instrs[1]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 		patch_instruction((struct ppc_inst *)(dest + 2), ppc_inst(instrs[2]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 		patch_instruction((struct ppc_inst *)(dest + 3), ppc_inst(instrs[3]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	printk(KERN_DEBUG "uaccess-flush: patched %d locations (%s flush)\n", i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 		(types == L1D_FLUSH_NONE)       ? "no" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 		(types == L1D_FLUSH_FALLBACK)   ? "fallback displacement" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 		(types &  L1D_FLUSH_ORI)        ? (types & L1D_FLUSH_MTTRIG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 							? "ori+mttrig type"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 							: "ori type" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 		(types &  L1D_FLUSH_MTTRIG)     ? "mttrig type"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 						: "unknown");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) static int __do_entry_flush_fixups(void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	enum l1d_flush_type types = *(enum l1d_flush_type *)data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	unsigned int instrs[3], *dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	long *start, *end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	instrs[0] = 0x60000000; /* nop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	instrs[1] = 0x60000000; /* nop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	instrs[2] = 0x60000000; /* nop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	if (types == L1D_FLUSH_FALLBACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 		instrs[i++] = 0x7d4802a6; /* mflr r10		*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 		instrs[i++] = 0x60000000; /* branch patched below */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 		instrs[i++] = 0x7d4803a6; /* mtlr r10		*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 	if (types & L1D_FLUSH_ORI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 		instrs[i++] = 0x63ff0000; /* ori 31,31,0 speculation barrier */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 		instrs[i++] = 0x63de0000; /* ori 30,30,0 L1d flush*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	if (types & L1D_FLUSH_MTTRIG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 		instrs[i++] = 0x7c12dba6; /* mtspr TRIG2,r0 (SPR #882) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 	start = PTRRELOC(&__start___entry_flush_fixup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	end = PTRRELOC(&__stop___entry_flush_fixup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 	for (i = 0; start < end; start++, i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 		dest = (void *)start + *start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 		pr_devel("patching dest %lx\n", (unsigned long)dest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 		patch_instruction((struct ppc_inst *)dest, ppc_inst(instrs[0]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 		if (types == L1D_FLUSH_FALLBACK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 			patch_branch((struct ppc_inst *)(dest + 1), (unsigned long)&entry_flush_fallback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 				     BRANCH_SET_LINK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 			patch_instruction((struct ppc_inst *)(dest + 1), ppc_inst(instrs[1]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 		patch_instruction((struct ppc_inst *)(dest + 2), ppc_inst(instrs[2]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 	start = PTRRELOC(&__start___scv_entry_flush_fixup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	end = PTRRELOC(&__stop___scv_entry_flush_fixup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 	for (; start < end; start++, i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 		dest = (void *)start + *start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 		pr_devel("patching dest %lx\n", (unsigned long)dest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 		patch_instruction((struct ppc_inst *)dest, ppc_inst(instrs[0]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 		if (types == L1D_FLUSH_FALLBACK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 			patch_branch((struct ppc_inst *)(dest + 1), (unsigned long)&scv_entry_flush_fallback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 				     BRANCH_SET_LINK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 			patch_instruction((struct ppc_inst *)(dest + 1), ppc_inst(instrs[1]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 		patch_instruction((struct ppc_inst *)(dest + 2), ppc_inst(instrs[2]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 	printk(KERN_DEBUG "entry-flush: patched %d locations (%s flush)\n", i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 		(types == L1D_FLUSH_NONE)       ? "no" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 		(types == L1D_FLUSH_FALLBACK)   ? "fallback displacement" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 		(types &  L1D_FLUSH_ORI)        ? (types & L1D_FLUSH_MTTRIG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 							? "ori+mttrig type"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 							: "ori type" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 		(types &  L1D_FLUSH_MTTRIG)     ? "mttrig type"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 						: "unknown");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) void do_entry_flush_fixups(enum l1d_flush_type types)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 	 * The call to the fallback flush can not be safely patched in/out while
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 	 * other CPUs are executing it. So call __do_entry_flush_fixups() on one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 	 * CPU while all other CPUs spin in the stop machine core with interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	 * hard disabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 	stop_machine(__do_entry_flush_fixups, &types, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) void do_rfi_flush_fixups(enum l1d_flush_type types)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 	unsigned int instrs[3], *dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 	long *start, *end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 	start = PTRRELOC(&__start___rfi_flush_fixup),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 	end = PTRRELOC(&__stop___rfi_flush_fixup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 	instrs[0] = 0x60000000; /* nop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 	instrs[1] = 0x60000000; /* nop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 	instrs[2] = 0x60000000; /* nop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 	if (types & L1D_FLUSH_FALLBACK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 		/* b .+16 to fallback flush */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 		instrs[0] = 0x48000010;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 	i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	if (types & L1D_FLUSH_ORI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 		instrs[i++] = 0x63ff0000; /* ori 31,31,0 speculation barrier */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 		instrs[i++] = 0x63de0000; /* ori 30,30,0 L1d flush*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 	if (types & L1D_FLUSH_MTTRIG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 		instrs[i++] = 0x7c12dba6; /* mtspr TRIG2,r0 (SPR #882) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 	for (i = 0; start < end; start++, i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 		dest = (void *)start + *start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 		pr_devel("patching dest %lx\n", (unsigned long)dest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 		patch_instruction((struct ppc_inst *)dest, ppc_inst(instrs[0]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 		patch_instruction((struct ppc_inst *)(dest + 1), ppc_inst(instrs[1]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 		patch_instruction((struct ppc_inst *)(dest + 2), ppc_inst(instrs[2]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 	printk(KERN_DEBUG "rfi-flush: patched %d locations (%s flush)\n", i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 		(types == L1D_FLUSH_NONE)       ? "no" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 		(types == L1D_FLUSH_FALLBACK)   ? "fallback displacement" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 		(types &  L1D_FLUSH_ORI)        ? (types & L1D_FLUSH_MTTRIG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 							? "ori+mttrig type"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 							: "ori type" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 		(types &  L1D_FLUSH_MTTRIG)     ? "mttrig type"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 						: "unknown");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) void do_barrier_nospec_fixups_range(bool enable, void *fixup_start, void *fixup_end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 	unsigned int instr, *dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 	long *start, *end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 	start = fixup_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 	end = fixup_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 	instr = 0x60000000; /* nop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 	if (enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 		pr_info("barrier-nospec: using ORI speculation barrier\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 		instr = 0x63ff0000; /* ori 31,31,0 speculation barrier */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 	for (i = 0; start < end; start++, i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 		dest = (void *)start + *start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 		pr_devel("patching dest %lx\n", (unsigned long)dest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 		patch_instruction((struct ppc_inst *)dest, ppc_inst(instr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 	printk(KERN_DEBUG "barrier-nospec: patched %d locations\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) #endif /* CONFIG_PPC_BOOK3S_64 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) #ifdef CONFIG_PPC_BARRIER_NOSPEC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) void do_barrier_nospec_fixups(bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 	void *start, *end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 	start = PTRRELOC(&__start___barrier_nospec_fixup),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 	end = PTRRELOC(&__stop___barrier_nospec_fixup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 	do_barrier_nospec_fixups_range(enable, start, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) #endif /* CONFIG_PPC_BARRIER_NOSPEC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) #ifdef CONFIG_PPC_FSL_BOOK3E
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) void do_barrier_nospec_fixups_range(bool enable, void *fixup_start, void *fixup_end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 	unsigned int instr[2], *dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 	long *start, *end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 	start = fixup_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 	end = fixup_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 	instr[0] = PPC_INST_NOP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 	instr[1] = PPC_INST_NOP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 	if (enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 		pr_info("barrier-nospec: using isync; sync as speculation barrier\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 		instr[0] = PPC_INST_ISYNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 		instr[1] = PPC_INST_SYNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 	for (i = 0; start < end; start++, i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 		dest = (void *)start + *start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 		pr_devel("patching dest %lx\n", (unsigned long)dest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 		patch_instruction((struct ppc_inst *)dest, ppc_inst(instr[0]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 		patch_instruction((struct ppc_inst *)(dest + 1), ppc_inst(instr[1]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 	printk(KERN_DEBUG "barrier-nospec: patched %d locations\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) static void patch_btb_flush_section(long *curr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 	unsigned int *start, *end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 	start = (void *)curr + *curr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 	end = (void *)curr + *(curr + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 	for (; start < end; start++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 		pr_devel("patching dest %lx\n", (unsigned long)start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 		patch_instruction((struct ppc_inst *)start, ppc_inst(PPC_INST_NOP));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) void do_btb_flush_fixups(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 	long *start, *end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 	start = PTRRELOC(&__start__btb_flush_fixup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 	end = PTRRELOC(&__stop__btb_flush_fixup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 	for (; start < end; start += 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 		patch_btb_flush_section(start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) #endif /* CONFIG_PPC_FSL_BOOK3E */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) void do_lwsync_fixups(unsigned long value, void *fixup_start, void *fixup_end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 	long *start, *end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 	struct ppc_inst *dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 	if (!(value & CPU_FTR_LWSYNC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 		return ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 	start = fixup_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 	end = fixup_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 	for (; start < end; start++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 		dest = (void *)start + *start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 		raw_patch_instruction(dest, ppc_inst(PPC_INST_LWSYNC));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) static void do_final_fixups(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) #if defined(CONFIG_PPC64) && defined(CONFIG_RELOCATABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 	struct ppc_inst inst, *src, *dest, *end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 	if (PHYSICAL_START == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 	src = (struct ppc_inst *)(KERNELBASE + PHYSICAL_START);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 	dest = (struct ppc_inst *)KERNELBASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 	end = (void *)src + (__end_interrupts - _stext);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 	while (src < end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 		inst = ppc_inst_read(src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 		raw_patch_instruction(dest, inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 		src = ppc_inst_next(src, src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 		dest = ppc_inst_next(dest, dest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) static unsigned long __initdata saved_cpu_features;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) static unsigned int __initdata saved_mmu_features;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) #ifdef CONFIG_PPC64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) static unsigned long __initdata saved_firmware_features;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) void __init apply_feature_fixups(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 	struct cpu_spec *spec = PTRRELOC(*PTRRELOC(&cur_cpu_spec));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 	*PTRRELOC(&saved_cpu_features) = spec->cpu_features;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 	*PTRRELOC(&saved_mmu_features) = spec->mmu_features;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 	 * Apply the CPU-specific and firmware specific fixups to kernel text
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 	 * (nop out sections not relevant to this CPU or this firmware).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 	do_feature_fixups(spec->cpu_features,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 			  PTRRELOC(&__start___ftr_fixup),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 			  PTRRELOC(&__stop___ftr_fixup));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 	do_feature_fixups(spec->mmu_features,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 			  PTRRELOC(&__start___mmu_ftr_fixup),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 			  PTRRELOC(&__stop___mmu_ftr_fixup));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 	do_lwsync_fixups(spec->cpu_features,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 			 PTRRELOC(&__start___lwsync_fixup),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 			 PTRRELOC(&__stop___lwsync_fixup));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) #ifdef CONFIG_PPC64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 	saved_firmware_features = powerpc_firmware_features;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 	do_feature_fixups(powerpc_firmware_features,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 			  &__start___fw_ftr_fixup, &__stop___fw_ftr_fixup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 	do_final_fixups();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) void __init setup_feature_keys(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 	 * Initialise jump label. This causes all the cpu/mmu_has_feature()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 	 * checks to take on their correct polarity based on the current set of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 	 * CPU/MMU features.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 	jump_label_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 	cpu_feature_keys_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 	mmu_feature_keys_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) static int __init check_features(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 	WARN(saved_cpu_features != cur_cpu_spec->cpu_features,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 	     "CPU features changed after feature patching!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 	WARN(saved_mmu_features != cur_cpu_spec->mmu_features,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 	     "MMU features changed after feature patching!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) #ifdef CONFIG_PPC64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 	WARN(saved_firmware_features != powerpc_firmware_features,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 	     "Firmware features changed after feature patching!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) late_initcall(check_features);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) #ifdef CONFIG_FTR_FIXUP_SELFTEST
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) #define check(x)	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 	if (!(x)) printk("feature-fixups: test failed at line %d\n", __LINE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) /* This must be after the text it fixes up, vmlinux.lds.S enforces that atm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) static struct fixup_entry fixup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) static long calc_offset(struct fixup_entry *entry, unsigned int *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) 	return (unsigned long)p - (unsigned long)entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) static void test_basic_patching(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) 	extern unsigned int ftr_fixup_test1[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) 	extern unsigned int end_ftr_fixup_test1[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) 	extern unsigned int ftr_fixup_test1_orig[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) 	extern unsigned int ftr_fixup_test1_expected[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) 	int size = 4 * (end_ftr_fixup_test1 - ftr_fixup_test1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) 	fixup.value = fixup.mask = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) 	fixup.start_off = calc_offset(&fixup, ftr_fixup_test1 + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) 	fixup.end_off = calc_offset(&fixup, ftr_fixup_test1 + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) 	fixup.alt_start_off = fixup.alt_end_off = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) 	/* Sanity check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) 	check(memcmp(ftr_fixup_test1, ftr_fixup_test1_orig, size) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) 	/* Check we don't patch if the value matches */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) 	patch_feature_section(8, &fixup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) 	check(memcmp(ftr_fixup_test1, ftr_fixup_test1_orig, size) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) 	/* Check we do patch if the value doesn't match */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) 	patch_feature_section(0, &fixup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) 	check(memcmp(ftr_fixup_test1, ftr_fixup_test1_expected, size) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) 	/* Check we do patch if the mask doesn't match */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) 	memcpy(ftr_fixup_test1, ftr_fixup_test1_orig, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) 	check(memcmp(ftr_fixup_test1, ftr_fixup_test1_orig, size) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) 	patch_feature_section(~8, &fixup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) 	check(memcmp(ftr_fixup_test1, ftr_fixup_test1_expected, size) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) static void test_alternative_patching(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) 	extern unsigned int ftr_fixup_test2[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) 	extern unsigned int end_ftr_fixup_test2[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) 	extern unsigned int ftr_fixup_test2_orig[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) 	extern unsigned int ftr_fixup_test2_alt[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) 	extern unsigned int ftr_fixup_test2_expected[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) 	int size = 4 * (end_ftr_fixup_test2 - ftr_fixup_test2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) 	fixup.value = fixup.mask = 0xF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) 	fixup.start_off = calc_offset(&fixup, ftr_fixup_test2 + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) 	fixup.end_off = calc_offset(&fixup, ftr_fixup_test2 + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) 	fixup.alt_start_off = calc_offset(&fixup, ftr_fixup_test2_alt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) 	fixup.alt_end_off = calc_offset(&fixup, ftr_fixup_test2_alt + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) 	/* Sanity check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) 	check(memcmp(ftr_fixup_test2, ftr_fixup_test2_orig, size) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) 	/* Check we don't patch if the value matches */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) 	patch_feature_section(0xF, &fixup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) 	check(memcmp(ftr_fixup_test2, ftr_fixup_test2_orig, size) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) 	/* Check we do patch if the value doesn't match */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) 	patch_feature_section(0, &fixup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) 	check(memcmp(ftr_fixup_test2, ftr_fixup_test2_expected, size) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) 	/* Check we do patch if the mask doesn't match */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) 	memcpy(ftr_fixup_test2, ftr_fixup_test2_orig, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) 	check(memcmp(ftr_fixup_test2, ftr_fixup_test2_orig, size) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) 	patch_feature_section(~0xF, &fixup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) 	check(memcmp(ftr_fixup_test2, ftr_fixup_test2_expected, size) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) static void test_alternative_case_too_big(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) 	extern unsigned int ftr_fixup_test3[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) 	extern unsigned int end_ftr_fixup_test3[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) 	extern unsigned int ftr_fixup_test3_orig[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) 	extern unsigned int ftr_fixup_test3_alt[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) 	int size = 4 * (end_ftr_fixup_test3 - ftr_fixup_test3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) 	fixup.value = fixup.mask = 0xC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) 	fixup.start_off = calc_offset(&fixup, ftr_fixup_test3 + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) 	fixup.end_off = calc_offset(&fixup, ftr_fixup_test3 + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) 	fixup.alt_start_off = calc_offset(&fixup, ftr_fixup_test3_alt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) 	fixup.alt_end_off = calc_offset(&fixup, ftr_fixup_test3_alt + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) 	/* Sanity check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) 	check(memcmp(ftr_fixup_test3, ftr_fixup_test3_orig, size) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) 	/* Expect nothing to be patched, and the error returned to us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) 	check(patch_feature_section(0xF, &fixup) == 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) 	check(memcmp(ftr_fixup_test3, ftr_fixup_test3_orig, size) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) 	check(patch_feature_section(0, &fixup) == 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) 	check(memcmp(ftr_fixup_test3, ftr_fixup_test3_orig, size) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) 	check(patch_feature_section(~0xF, &fixup) == 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) 	check(memcmp(ftr_fixup_test3, ftr_fixup_test3_orig, size) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) static void test_alternative_case_too_small(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) 	extern unsigned int ftr_fixup_test4[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) 	extern unsigned int end_ftr_fixup_test4[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) 	extern unsigned int ftr_fixup_test4_orig[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) 	extern unsigned int ftr_fixup_test4_alt[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) 	extern unsigned int ftr_fixup_test4_expected[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) 	int size = 4 * (end_ftr_fixup_test4 - ftr_fixup_test4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) 	unsigned long flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) 	/* Check a high-bit flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) 	flag = 1UL << ((sizeof(unsigned long) - 1) * 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) 	fixup.value = fixup.mask = flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) 	fixup.start_off = calc_offset(&fixup, ftr_fixup_test4 + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) 	fixup.end_off = calc_offset(&fixup, ftr_fixup_test4 + 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) 	fixup.alt_start_off = calc_offset(&fixup, ftr_fixup_test4_alt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) 	fixup.alt_end_off = calc_offset(&fixup, ftr_fixup_test4_alt + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) 	/* Sanity check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) 	check(memcmp(ftr_fixup_test4, ftr_fixup_test4_orig, size) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) 	/* Check we don't patch if the value matches */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) 	patch_feature_section(flag, &fixup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) 	check(memcmp(ftr_fixup_test4, ftr_fixup_test4_orig, size) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) 	/* Check we do patch if the value doesn't match */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) 	patch_feature_section(0, &fixup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) 	check(memcmp(ftr_fixup_test4, ftr_fixup_test4_expected, size) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) 	/* Check we do patch if the mask doesn't match */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) 	memcpy(ftr_fixup_test4, ftr_fixup_test4_orig, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) 	check(memcmp(ftr_fixup_test4, ftr_fixup_test4_orig, size) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) 	patch_feature_section(~flag, &fixup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) 	check(memcmp(ftr_fixup_test4, ftr_fixup_test4_expected, size) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) static void test_alternative_case_with_branch(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) 	extern unsigned int ftr_fixup_test5[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) 	extern unsigned int end_ftr_fixup_test5[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) 	extern unsigned int ftr_fixup_test5_expected[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) 	int size = 4 * (end_ftr_fixup_test5 - ftr_fixup_test5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) 	check(memcmp(ftr_fixup_test5, ftr_fixup_test5_expected, size) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) static void test_alternative_case_with_external_branch(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) 	extern unsigned int ftr_fixup_test6[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) 	extern unsigned int end_ftr_fixup_test6[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) 	extern unsigned int ftr_fixup_test6_expected[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) 	int size = 4 * (end_ftr_fixup_test6 - ftr_fixup_test6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) 	check(memcmp(ftr_fixup_test6, ftr_fixup_test6_expected, size) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) static void test_alternative_case_with_branch_to_end(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) 	extern unsigned int ftr_fixup_test7[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) 	extern unsigned int end_ftr_fixup_test7[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) 	extern unsigned int ftr_fixup_test7_expected[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) 	int size = 4 * (end_ftr_fixup_test7 - ftr_fixup_test7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) 	check(memcmp(ftr_fixup_test7, ftr_fixup_test7_expected, size) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) static void test_cpu_macros(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) 	extern u8 ftr_fixup_test_FTR_macros[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) 	extern u8 ftr_fixup_test_FTR_macros_expected[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) 	unsigned long size = ftr_fixup_test_FTR_macros_expected -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) 			     ftr_fixup_test_FTR_macros;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) 	/* The fixups have already been done for us during boot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) 	check(memcmp(ftr_fixup_test_FTR_macros,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) 		     ftr_fixup_test_FTR_macros_expected, size) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) static void test_fw_macros(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) #ifdef CONFIG_PPC64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) 	extern u8 ftr_fixup_test_FW_FTR_macros[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) 	extern u8 ftr_fixup_test_FW_FTR_macros_expected[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) 	unsigned long size = ftr_fixup_test_FW_FTR_macros_expected -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) 			     ftr_fixup_test_FW_FTR_macros;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) 	/* The fixups have already been done for us during boot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) 	check(memcmp(ftr_fixup_test_FW_FTR_macros,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) 		     ftr_fixup_test_FW_FTR_macros_expected, size) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) static void test_lwsync_macros(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) 	extern u8 lwsync_fixup_test[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) 	extern u8 end_lwsync_fixup_test[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) 	extern u8 lwsync_fixup_test_expected_LWSYNC[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) 	extern u8 lwsync_fixup_test_expected_SYNC[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) 	unsigned long size = end_lwsync_fixup_test -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) 			     lwsync_fixup_test;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) 	/* The fixups have already been done for us during boot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) 	if (cur_cpu_spec->cpu_features & CPU_FTR_LWSYNC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) 		check(memcmp(lwsync_fixup_test,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) 			     lwsync_fixup_test_expected_LWSYNC, size) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) 		check(memcmp(lwsync_fixup_test,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) 			     lwsync_fixup_test_expected_SYNC, size) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) #ifdef CONFIG_PPC64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) static void __init test_prefix_patching(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) 	extern unsigned int ftr_fixup_prefix1[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) 	extern unsigned int end_ftr_fixup_prefix1[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) 	extern unsigned int ftr_fixup_prefix1_orig[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) 	extern unsigned int ftr_fixup_prefix1_expected[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) 	int size = sizeof(unsigned int) * (end_ftr_fixup_prefix1 - ftr_fixup_prefix1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) 	fixup.value = fixup.mask = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) 	fixup.start_off = calc_offset(&fixup, ftr_fixup_prefix1 + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) 	fixup.end_off = calc_offset(&fixup, ftr_fixup_prefix1 + 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) 	fixup.alt_start_off = fixup.alt_end_off = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) 	/* Sanity check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) 	check(memcmp(ftr_fixup_prefix1, ftr_fixup_prefix1_orig, size) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) 	patch_feature_section(0, &fixup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) 	check(memcmp(ftr_fixup_prefix1, ftr_fixup_prefix1_expected, size) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) 	check(memcmp(ftr_fixup_prefix1, ftr_fixup_prefix1_orig, size) != 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) static void __init test_prefix_alt_patching(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) 	extern unsigned int ftr_fixup_prefix2[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) 	extern unsigned int end_ftr_fixup_prefix2[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) 	extern unsigned int ftr_fixup_prefix2_orig[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) 	extern unsigned int ftr_fixup_prefix2_expected[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) 	extern unsigned int ftr_fixup_prefix2_alt[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) 	int size = sizeof(unsigned int) * (end_ftr_fixup_prefix2 - ftr_fixup_prefix2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) 	fixup.value = fixup.mask = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) 	fixup.start_off = calc_offset(&fixup, ftr_fixup_prefix2 + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) 	fixup.end_off = calc_offset(&fixup, ftr_fixup_prefix2 + 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) 	fixup.alt_start_off = calc_offset(&fixup, ftr_fixup_prefix2_alt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) 	fixup.alt_end_off = calc_offset(&fixup, ftr_fixup_prefix2_alt + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) 	/* Sanity check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) 	check(memcmp(ftr_fixup_prefix2, ftr_fixup_prefix2_orig, size) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) 	patch_feature_section(0, &fixup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) 	check(memcmp(ftr_fixup_prefix2, ftr_fixup_prefix2_expected, size) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) 	check(memcmp(ftr_fixup_prefix2, ftr_fixup_prefix2_orig, size) != 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) static void __init test_prefix_word_alt_patching(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) 	extern unsigned int ftr_fixup_prefix3[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) 	extern unsigned int end_ftr_fixup_prefix3[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) 	extern unsigned int ftr_fixup_prefix3_orig[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) 	extern unsigned int ftr_fixup_prefix3_expected[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) 	extern unsigned int ftr_fixup_prefix3_alt[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) 	int size = sizeof(unsigned int) * (end_ftr_fixup_prefix3 - ftr_fixup_prefix3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) 	fixup.value = fixup.mask = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) 	fixup.start_off = calc_offset(&fixup, ftr_fixup_prefix3 + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) 	fixup.end_off = calc_offset(&fixup, ftr_fixup_prefix3 + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) 	fixup.alt_start_off = calc_offset(&fixup, ftr_fixup_prefix3_alt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) 	fixup.alt_end_off = calc_offset(&fixup, ftr_fixup_prefix3_alt + 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) 	/* Sanity check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) 	check(memcmp(ftr_fixup_prefix3, ftr_fixup_prefix3_orig, size) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) 	patch_feature_section(0, &fixup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) 	check(memcmp(ftr_fixup_prefix3, ftr_fixup_prefix3_expected, size) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) 	patch_feature_section(0, &fixup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) 	check(memcmp(ftr_fixup_prefix3, ftr_fixup_prefix3_orig, size) != 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) static inline void test_prefix_patching(void) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) static inline void test_prefix_alt_patching(void) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) static inline void test_prefix_word_alt_patching(void) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) #endif /* CONFIG_PPC64 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) static int __init test_feature_fixups(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) 	printk(KERN_DEBUG "Running feature fixup self-tests ...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) 	test_basic_patching();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) 	test_alternative_patching();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) 	test_alternative_case_too_big();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) 	test_alternative_case_too_small();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) 	test_alternative_case_with_branch();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) 	test_alternative_case_with_external_branch();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) 	test_alternative_case_with_branch_to_end();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) 	test_cpu_macros();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) 	test_fw_macros();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) 	test_lwsync_macros();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) 	test_prefix_patching();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) 	test_prefix_alt_patching();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) 	test_prefix_word_alt_patching();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) late_initcall(test_feature_fixups);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) #endif /* CONFIG_FTR_FIXUP_SELFTEST */