Merge branches 'x86/early-printk', 'x86/microcode' and 'core/objtool' into x86/urgent, to pick up simple topic branches
Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
commit
4b783dd6a4
|
@ -1068,7 +1068,7 @@
|
||||||
earlyprintk=serial[,0x...[,baudrate]]
|
earlyprintk=serial[,0x...[,baudrate]]
|
||||||
earlyprintk=ttySn[,baudrate]
|
earlyprintk=ttySn[,baudrate]
|
||||||
earlyprintk=dbgp[debugController#]
|
earlyprintk=dbgp[debugController#]
|
||||||
earlyprintk=pciserial,bus:device.function[,baudrate]
|
earlyprintk=pciserial[,force],bus:device.function[,baudrate]
|
||||||
earlyprintk=xdbc[xhciController#]
|
earlyprintk=xdbc[xhciController#]
|
||||||
|
|
||||||
earlyprintk is useful when the kernel crashes before
|
earlyprintk is useful when the kernel crashes before
|
||||||
|
@ -1100,6 +1100,10 @@
|
||||||
|
|
||||||
The sclp output can only be used on s390.
|
The sclp output can only be used on s390.
|
||||||
|
|
||||||
|
The optional "force" to "pciserial" enables use of a
|
||||||
|
PCI device even when its classcode is not of the
|
||||||
|
UART class.
|
||||||
|
|
||||||
edac_report= [HW,EDAC] Control how to report EDAC event
|
edac_report= [HW,EDAC] Control how to report EDAC event
|
||||||
Format: {"on" | "off" | "force"}
|
Format: {"on" | "off" | "force"}
|
||||||
on: enable EDAC to report H/W event. May be overridden
|
on: enable EDAC to report H/W event. May be overridden
|
||||||
|
|
|
@ -666,8 +666,8 @@ static ssize_t pf_show(struct device *dev,
|
||||||
}
|
}
|
||||||
|
|
||||||
static DEVICE_ATTR_WO(reload);
|
static DEVICE_ATTR_WO(reload);
|
||||||
static DEVICE_ATTR(version, 0400, version_show, NULL);
|
static DEVICE_ATTR(version, 0444, version_show, NULL);
|
||||||
static DEVICE_ATTR(processor_flags, 0400, pf_show, NULL);
|
static DEVICE_ATTR(processor_flags, 0444, pf_show, NULL);
|
||||||
|
|
||||||
static struct attribute *mc_default_attrs[] = {
|
static struct attribute *mc_default_attrs[] = {
|
||||||
&dev_attr_version.attr,
|
&dev_attr_version.attr,
|
||||||
|
|
|
@ -213,8 +213,9 @@ static unsigned int mem32_serial_in(unsigned long addr, int offset)
|
||||||
* early_pci_serial_init()
|
* early_pci_serial_init()
|
||||||
*
|
*
|
||||||
* This function is invoked when the early_printk param starts with "pciserial"
|
* This function is invoked when the early_printk param starts with "pciserial"
|
||||||
* The rest of the param should be ",B:D.F,baud" where B, D & F describe the
|
* The rest of the param should be "[force],B:D.F,baud", where B, D & F describe
|
||||||
* location of a PCI device that must be a UART device.
|
* the location of a PCI device that must be a UART device. "force" is optional
|
||||||
|
* and overrides the use of an UART device with a wrong PCI class code.
|
||||||
*/
|
*/
|
||||||
static __init void early_pci_serial_init(char *s)
|
static __init void early_pci_serial_init(char *s)
|
||||||
{
|
{
|
||||||
|
@ -224,17 +225,23 @@ static __init void early_pci_serial_init(char *s)
|
||||||
u32 classcode, bar0;
|
u32 classcode, bar0;
|
||||||
u16 cmdreg;
|
u16 cmdreg;
|
||||||
char *e;
|
char *e;
|
||||||
|
int force = 0;
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* First, part the param to get the BDF values
|
|
||||||
*/
|
|
||||||
if (*s == ',')
|
if (*s == ',')
|
||||||
++s;
|
++s;
|
||||||
|
|
||||||
if (*s == 0)
|
if (*s == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* Force the use of an UART device with wrong class code */
|
||||||
|
if (!strncmp(s, "force,", 6)) {
|
||||||
|
force = 1;
|
||||||
|
s += 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Part the param to get the BDF values
|
||||||
|
*/
|
||||||
bus = (u8)simple_strtoul(s, &e, 16);
|
bus = (u8)simple_strtoul(s, &e, 16);
|
||||||
s = e;
|
s = e;
|
||||||
if (*s != ':')
|
if (*s != ':')
|
||||||
|
@ -253,7 +260,7 @@ static __init void early_pci_serial_init(char *s)
|
||||||
s++;
|
s++;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Second, find the device from the BDF
|
* Find the device from the BDF
|
||||||
*/
|
*/
|
||||||
cmdreg = read_pci_config(bus, slot, func, PCI_COMMAND);
|
cmdreg = read_pci_config(bus, slot, func, PCI_COMMAND);
|
||||||
classcode = read_pci_config(bus, slot, func, PCI_CLASS_REVISION);
|
classcode = read_pci_config(bus, slot, func, PCI_CLASS_REVISION);
|
||||||
|
@ -264,8 +271,10 @@ static __init void early_pci_serial_init(char *s)
|
||||||
*/
|
*/
|
||||||
if (((classcode >> 16 != PCI_CLASS_COMMUNICATION_MODEM) &&
|
if (((classcode >> 16 != PCI_CLASS_COMMUNICATION_MODEM) &&
|
||||||
(classcode >> 16 != PCI_CLASS_COMMUNICATION_SERIAL)) ||
|
(classcode >> 16 != PCI_CLASS_COMMUNICATION_SERIAL)) ||
|
||||||
(((classcode >> 8) & 0xff) != 0x02)) /* 16550 I/F at BAR0 */
|
(((classcode >> 8) & 0xff) != 0x02)) /* 16550 I/F at BAR0 */ {
|
||||||
|
if (!force)
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Determine if it is IO or memory mapped
|
* Determine if it is IO or memory mapped
|
||||||
|
@ -289,7 +298,7 @@ static __init void early_pci_serial_init(char *s)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Lastly, initialize the hardware
|
* Initialize the hardware
|
||||||
*/
|
*/
|
||||||
if (*s) {
|
if (*s) {
|
||||||
if (strcmp(s, "nocfg") == 0)
|
if (strcmp(s, "nocfg") == 0)
|
||||||
|
|
|
@ -836,7 +836,7 @@ static int add_switch_table(struct objtool_file *file, struct instruction *insn,
|
||||||
struct symbol *pfunc = insn->func->pfunc;
|
struct symbol *pfunc = insn->func->pfunc;
|
||||||
unsigned int prev_offset = 0;
|
unsigned int prev_offset = 0;
|
||||||
|
|
||||||
list_for_each_entry_from(rela, &file->rodata->rela->rela_list, list) {
|
list_for_each_entry_from(rela, &table->rela_sec->rela_list, list) {
|
||||||
if (rela == next_table)
|
if (rela == next_table)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -926,6 +926,7 @@ static struct rela *find_switch_table(struct objtool_file *file,
|
||||||
{
|
{
|
||||||
struct rela *text_rela, *rodata_rela;
|
struct rela *text_rela, *rodata_rela;
|
||||||
struct instruction *orig_insn = insn;
|
struct instruction *orig_insn = insn;
|
||||||
|
struct section *rodata_sec;
|
||||||
unsigned long table_offset;
|
unsigned long table_offset;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -953,10 +954,13 @@ static struct rela *find_switch_table(struct objtool_file *file,
|
||||||
/* look for a relocation which references .rodata */
|
/* look for a relocation which references .rodata */
|
||||||
text_rela = find_rela_by_dest_range(insn->sec, insn->offset,
|
text_rela = find_rela_by_dest_range(insn->sec, insn->offset,
|
||||||
insn->len);
|
insn->len);
|
||||||
if (!text_rela || text_rela->sym != file->rodata->sym)
|
if (!text_rela || text_rela->sym->type != STT_SECTION ||
|
||||||
|
!text_rela->sym->sec->rodata)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
table_offset = text_rela->addend;
|
table_offset = text_rela->addend;
|
||||||
|
rodata_sec = text_rela->sym->sec;
|
||||||
|
|
||||||
if (text_rela->type == R_X86_64_PC32)
|
if (text_rela->type == R_X86_64_PC32)
|
||||||
table_offset += 4;
|
table_offset += 4;
|
||||||
|
|
||||||
|
@ -964,10 +968,10 @@ static struct rela *find_switch_table(struct objtool_file *file,
|
||||||
* Make sure the .rodata address isn't associated with a
|
* Make sure the .rodata address isn't associated with a
|
||||||
* symbol. gcc jump tables are anonymous data.
|
* symbol. gcc jump tables are anonymous data.
|
||||||
*/
|
*/
|
||||||
if (find_symbol_containing(file->rodata, table_offset))
|
if (find_symbol_containing(rodata_sec, table_offset))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
rodata_rela = find_rela_by_dest(file->rodata, table_offset);
|
rodata_rela = find_rela_by_dest(rodata_sec, table_offset);
|
||||||
if (rodata_rela) {
|
if (rodata_rela) {
|
||||||
/*
|
/*
|
||||||
* Use of RIP-relative switch jumps is quite rare, and
|
* Use of RIP-relative switch jumps is quite rare, and
|
||||||
|
@ -1052,7 +1056,7 @@ static int add_switch_table_alts(struct objtool_file *file)
|
||||||
struct symbol *func;
|
struct symbol *func;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!file->rodata || !file->rodata->rela)
|
if (!file->rodata)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for_each_sec(file, sec) {
|
for_each_sec(file, sec) {
|
||||||
|
@ -1198,10 +1202,33 @@ static int read_retpoline_hints(struct objtool_file *file)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void mark_rodata(struct objtool_file *file)
|
||||||
|
{
|
||||||
|
struct section *sec;
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This searches for the .rodata section or multiple .rodata.func_name
|
||||||
|
* sections if -fdata-sections is being used. The .str.1.1 and .str.1.8
|
||||||
|
* rodata sections are ignored as they don't contain jump tables.
|
||||||
|
*/
|
||||||
|
for_each_sec(file, sec) {
|
||||||
|
if (!strncmp(sec->name, ".rodata", 7) &&
|
||||||
|
!strstr(sec->name, ".str1.")) {
|
||||||
|
sec->rodata = true;
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
file->rodata = found;
|
||||||
|
}
|
||||||
|
|
||||||
static int decode_sections(struct objtool_file *file)
|
static int decode_sections(struct objtool_file *file)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
mark_rodata(file);
|
||||||
|
|
||||||
ret = decode_instructions(file);
|
ret = decode_instructions(file);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -2171,7 +2198,6 @@ int check(const char *_objname, bool orc)
|
||||||
INIT_LIST_HEAD(&file.insn_list);
|
INIT_LIST_HEAD(&file.insn_list);
|
||||||
hash_init(file.insn_hash);
|
hash_init(file.insn_hash);
|
||||||
file.whitelist = find_section_by_name(file.elf, ".discard.func_stack_frame_non_standard");
|
file.whitelist = find_section_by_name(file.elf, ".discard.func_stack_frame_non_standard");
|
||||||
file.rodata = find_section_by_name(file.elf, ".rodata");
|
|
||||||
file.c_file = find_section_by_name(file.elf, ".comment");
|
file.c_file = find_section_by_name(file.elf, ".comment");
|
||||||
file.ignore_unreachables = no_unreachable;
|
file.ignore_unreachables = no_unreachable;
|
||||||
file.hints = false;
|
file.hints = false;
|
||||||
|
|
|
@ -60,8 +60,8 @@ struct objtool_file {
|
||||||
struct elf *elf;
|
struct elf *elf;
|
||||||
struct list_head insn_list;
|
struct list_head insn_list;
|
||||||
DECLARE_HASHTABLE(insn_hash, 16);
|
DECLARE_HASHTABLE(insn_hash, 16);
|
||||||
struct section *rodata, *whitelist;
|
struct section *whitelist;
|
||||||
bool ignore_unreachables, c_file, hints;
|
bool ignore_unreachables, c_file, hints, rodata;
|
||||||
};
|
};
|
||||||
|
|
||||||
int check(const char *objname, bool orc);
|
int check(const char *objname, bool orc);
|
||||||
|
|
|
@ -379,6 +379,7 @@ static int read_relas(struct elf *elf)
|
||||||
rela->offset = rela->rela.r_offset;
|
rela->offset = rela->rela.r_offset;
|
||||||
symndx = GELF_R_SYM(rela->rela.r_info);
|
symndx = GELF_R_SYM(rela->rela.r_info);
|
||||||
rela->sym = find_symbol_by_index(elf, symndx);
|
rela->sym = find_symbol_by_index(elf, symndx);
|
||||||
|
rela->rela_sec = sec;
|
||||||
if (!rela->sym) {
|
if (!rela->sym) {
|
||||||
WARN("can't find rela entry symbol %d for %s",
|
WARN("can't find rela entry symbol %d for %s",
|
||||||
symndx, sec->name);
|
symndx, sec->name);
|
||||||
|
|
|
@ -48,7 +48,7 @@ struct section {
|
||||||
char *name;
|
char *name;
|
||||||
int idx;
|
int idx;
|
||||||
unsigned int len;
|
unsigned int len;
|
||||||
bool changed, text;
|
bool changed, text, rodata;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct symbol {
|
struct symbol {
|
||||||
|
@ -68,6 +68,7 @@ struct rela {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
struct hlist_node hash;
|
struct hlist_node hash;
|
||||||
GElf_Rela rela;
|
GElf_Rela rela;
|
||||||
|
struct section *rela_sec;
|
||||||
struct symbol *sym;
|
struct symbol *sym;
|
||||||
unsigned int type;
|
unsigned int type;
|
||||||
unsigned long offset;
|
unsigned long offset;
|
||||||
|
|
Loading…
Reference in New Issue