Merge tag 'x86_paravirt_for_v7.0_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 paravirt updates from Borislav Petkov:

 - A nice cleanup to the paravirt code containing a unification of the
   paravirt clock interface, taming the include hell by splitting the
   pv_ops structure and removing of a bunch of obsolete code (Juergen
   Gross)

* tag 'x86_paravirt_for_v7.0_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (23 commits)
  x86/paravirt: Use XOR r32,r32 to clear register in pv_vcpu_is_preempted()
  x86/paravirt: Remove trailing semicolons from alternative asm templates
  x86/pvlocks: Move paravirt spinlock functions into own header
  x86/paravirt: Specify pv_ops array in paravirt macros
  x86/paravirt: Allow pv-calls outside paravirt.h
  objtool: Allow multiple pv_ops arrays
  x86/xen: Drop xen_mmu_ops
  x86/xen: Drop xen_cpu_ops
  x86/xen: Drop xen_irq_ops
  x86/paravirt: Move pv_native_*() prototypes to paravirt.c
  x86/paravirt: Introduce new paravirt-base.h header
  x86/paravirt: Move paravirt_sched_clock() related code into tsc.c
  x86/paravirt: Use common code for paravirt_steal_clock()
  riscv/paravirt: Use common code for paravirt_steal_clock()
  loongarch/paravirt: Use common code for paravirt_steal_clock()
  arm64/paravirt: Use common code for paravirt_steal_clock()
  arm/paravirt: Use common code for paravirt_steal_clock()
  sched: Move clock related paravirt code to kernel/sched
  paravirt: Remove asm/paravirt_api_clock.h
  x86/paravirt: Move thunk macros to paravirt_types.h
  ...
This commit is contained in:
Linus Torvalds
2026-02-10 19:01:45 -08:00
66 changed files with 661 additions and 826 deletions

View File

@@ -711,10 +711,14 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
immr = find_reloc_by_dest(elf, (void *)sec, offset+3);
disp = find_reloc_by_dest(elf, (void *)sec, offset+7);
if (!immr || strcmp(immr->sym->name, "pv_ops"))
if (!immr || strncmp(immr->sym->name, "pv_ops", 6))
break;
idx = (reloc_addend(immr) + 8) / sizeof(void *);
idx = pv_ops_idx_off(immr->sym->name);
if (idx < 0)
break;
idx += (reloc_addend(immr) + 8) / sizeof(void *);
func = disp->sym;
if (disp->sym->type == STT_SECTION)

View File

@@ -521,21 +521,58 @@ static int decode_instructions(struct objtool_file *file)
}
/*
* Read the pv_ops[] .data table to find the static initialized values.
* Known pv_ops*[] arrays.
*/
static int add_pv_ops(struct objtool_file *file, const char *symname)
static struct {
const char *name;
int idx_off;
} pv_ops_tables[] = {
{ .name = "pv_ops", },
{ .name = "pv_ops_lock", },
{ .name = NULL, .idx_off = -1 }
};
/*
* Get index offset for a pv_ops* array.
*/
int pv_ops_idx_off(const char *symname)
{
int idx;
for (idx = 0; pv_ops_tables[idx].name; idx++) {
if (!strcmp(symname, pv_ops_tables[idx].name))
break;
}
return pv_ops_tables[idx].idx_off;
}
/*
* Read a pv_ops*[] .data table to find the static initialized values.
*/
static int add_pv_ops(struct objtool_file *file, int pv_ops_idx)
{
struct symbol *sym, *func;
unsigned long off, end;
struct reloc *reloc;
int idx;
int idx, idx_off;
const char *symname;
symname = pv_ops_tables[pv_ops_idx].name;
sym = find_symbol_by_name(file->elf, symname);
if (!sym)
return 0;
if (!sym) {
ERROR("Unknown pv_ops array %s", symname);
return -1;
}
off = sym->offset;
end = off + sym->len;
idx_off = pv_ops_tables[pv_ops_idx].idx_off;
if (idx_off < 0) {
ERROR("pv_ops array %s has unknown index offset", symname);
return -1;
}
for (;;) {
reloc = find_reloc_by_dest_range(file->elf, sym->sec, off, end - off);
if (!reloc)
@@ -553,7 +590,7 @@ static int add_pv_ops(struct objtool_file *file, const char *symname)
return -1;
}
if (objtool_pv_add(file, idx, func))
if (objtool_pv_add(file, idx + idx_off, func))
return -1;
off = reloc_offset(reloc) + 1;
@@ -569,14 +606,6 @@ static int add_pv_ops(struct objtool_file *file, const char *symname)
*/
static int init_pv_ops(struct objtool_file *file)
{
static const char *pv_ops_tables[] = {
"pv_ops",
"xen_cpu_ops",
"xen_irq_ops",
"xen_mmu_ops",
NULL,
};
const char *pv_ops;
struct symbol *sym;
int idx, nr;
@@ -585,11 +614,20 @@ static int init_pv_ops(struct objtool_file *file)
file->pv_ops = NULL;
sym = find_symbol_by_name(file->elf, "pv_ops");
if (!sym)
nr = 0;
for (idx = 0; pv_ops_tables[idx].name; idx++) {
sym = find_symbol_by_name(file->elf, pv_ops_tables[idx].name);
if (!sym) {
pv_ops_tables[idx].idx_off = -1;
continue;
}
pv_ops_tables[idx].idx_off = nr;
nr += sym->len / sizeof(unsigned long);
}
if (nr == 0)
return 0;
nr = sym->len / sizeof(unsigned long);
file->pv_ops = calloc(nr, sizeof(struct pv_state));
if (!file->pv_ops) {
ERROR_GLIBC("calloc");
@@ -599,8 +637,10 @@ static int init_pv_ops(struct objtool_file *file)
for (idx = 0; idx < nr; idx++)
INIT_LIST_HEAD(&file->pv_ops[idx].targets);
for (idx = 0; (pv_ops = pv_ops_tables[idx]); idx++) {
if (add_pv_ops(file, pv_ops))
for (idx = 0; pv_ops_tables[idx].name; idx++) {
if (pv_ops_tables[idx].idx_off < 0)
continue;
if (add_pv_ops(file, idx))
return -1;
}

View File

@@ -159,5 +159,6 @@ const char *objtool_disas_insn(struct instruction *insn);
extern size_t sym_name_max_len;
extern struct disas_context *objtool_disas_ctx;
int pv_ops_idx_off(const char *symname);
#endif /* _CHECK_H */