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) 2015 Josh Poimboeuf <jpoimboe@redhat.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * This file reads all the special sections which have alternate instructions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  * which can be patched in or redirected to at runtime.
^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 <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include "builtin.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include "special.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include "warn.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include "arch_special.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) struct special_entry {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 	const char *sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 	bool group, jump_or_nop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 	unsigned char size, orig, new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 	unsigned char orig_len, new_len; /* group only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 	unsigned char feature; /* ALTERNATIVE macro CPU feature */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) struct special_entry entries[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 		.sec = ".altinstructions",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 		.group = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 		.size = ALT_ENTRY_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 		.orig = ALT_ORIG_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 		.orig_len = ALT_ORIG_LEN_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 		.new = ALT_NEW_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 		.new_len = ALT_NEW_LEN_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 		.feature = ALT_FEATURE_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) 		.sec = "__jump_table",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 		.jump_or_nop = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 		.size = JUMP_ENTRY_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 		.orig = JUMP_ORIG_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 		.new = JUMP_NEW_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) 		.sec = "__ex_table",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 		.size = EX_ENTRY_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 		.orig = EX_ORIG_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 		.new = EX_NEW_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	{},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) void __weak arch_handle_alternative(unsigned short feature, struct special_alt *alt)
^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) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) static int get_alt_entry(struct elf *elf, struct special_entry *entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 			 struct section *sec, int idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 			 struct special_alt *alt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	struct reloc *orig_reloc, *new_reloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	unsigned long offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	offset = idx * entry->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	alt->group = entry->group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	alt->jump_or_nop = entry->jump_or_nop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	if (alt->group) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 		alt->orig_len = *(unsigned char *)(sec->data->d_buf + offset +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 						   entry->orig_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 		alt->new_len = *(unsigned char *)(sec->data->d_buf + offset +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 						  entry->new_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	if (entry->feature) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 		unsigned short feature;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 		feature = *(unsigned short *)(sec->data->d_buf + offset +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 					      entry->feature);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 		arch_handle_alternative(feature, alt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	orig_reloc = find_reloc_by_dest(elf, sec, offset + entry->orig);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	if (!orig_reloc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 		WARN_FUNC("can't find orig reloc", sec, offset + entry->orig);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	if (orig_reloc->sym->type != STT_SECTION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 		WARN_FUNC("don't know how to handle non-section reloc symbol %s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 			   sec, offset + entry->orig, orig_reloc->sym->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	alt->orig_sec = orig_reloc->sym->sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	alt->orig_off = orig_reloc->addend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	if (!entry->group || alt->new_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 		new_reloc = find_reloc_by_dest(elf, sec, offset + entry->new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 		if (!new_reloc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 			WARN_FUNC("can't find new reloc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 				  sec, offset + entry->new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 		alt->new_sec = new_reloc->sym->sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 		alt->new_off = (unsigned int)new_reloc->addend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		/* _ASM_EXTABLE_EX hack */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 		if (alt->new_off >= 0x7ffffff0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 			alt->new_off -= 0x7ffffff0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^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)  * Read all the special sections and create a list of special_alt structs which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)  * describe all the alternate instructions which can be patched in or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)  * redirected to at runtime.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) int special_get_alts(struct elf *elf, struct list_head *alts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	struct special_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	struct section *sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	unsigned int nr_entries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	struct special_alt *alt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	int idx, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	INIT_LIST_HEAD(alts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	for (entry = entries; entry->sec; entry++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 		sec = find_section_by_name(elf, entry->sec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 		if (!sec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 		if (sec->len % entry->size != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 			WARN("%s size not a multiple of %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 			     sec->name, entry->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 		nr_entries = sec->len / entry->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 		for (idx = 0; idx < nr_entries; idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 			alt = malloc(sizeof(*alt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 			if (!alt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 				WARN("malloc failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 				return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 			memset(alt, 0, sizeof(*alt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 			ret = get_alt_entry(elf, entry, sec, idx, alt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 			if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 				return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 			list_add_tail(&alt->list, alts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }