arm64 fixes:
- Fix potential memory leak in perf PMU probing - BPF sign extension fix for 64-bit immediates - Fix build failure with unusual configuration - Revert unused and broken branch patching from alternative code -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABCgAGBQJVVGxeAAoJELescNyEwWM05DYH/Ajusp2WZjh3FVC7tJbNF1ky ODplN/p2bWDFhq62/pFKIR7Ms5+l6BgcS3rLxIzN6CeMIyKiU/jHnCKvNNyBcL/K aXLPJ84zNQ+iMCbjwDOEqwE2h2dPb1dXYAWsIywJ1ZzRSEwe9uIdlbLoicQT3HM6 pTbmjvNxDY/nRygFgCa/o2MCnnyld1heGibeVdSivFSRxg59E+d9i2PVlLjl05ND V5cPFdRS/TEJnjOQ0g3c+sBSqrYwD5ad0RiFJMAS0mUG7ww0wwhCUE4hkmZy7sqT Iwux96/h5VzCwlHszFmfq0/kQoa/uYusydAhQ/chlTYyWG4CXq05O6mpfql72KU= =MDVF -----END PGP SIGNATURE----- Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux Pull arm64 fixes from Will Deacon: - fix potential memory leak in perf PMU probing - BPF sign extension fix for 64-bit immediates - fix build failure with unusual configuration - revert unused and broken branch patching from alternative code * tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux: arm64: perf: fix memory leak when probing PMU PPIs arm64: bpf: fix signedness bug in loading 64-bit immediate arm64: mm: Fix build error with CONFIG_SPARSEMEM_VMEMMAP disabled Revert "arm64: alternative: Allow immediate branch as alternative instruction"
This commit is contained in:
Коммит
fc8c540b1d
|
@ -24,7 +24,6 @@
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
#include <asm/alternative.h>
|
#include <asm/alternative.h>
|
||||||
#include <asm/cpufeature.h>
|
#include <asm/cpufeature.h>
|
||||||
#include <asm/insn.h>
|
|
||||||
#include <linux/stop_machine.h>
|
#include <linux/stop_machine.h>
|
||||||
|
|
||||||
extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
|
extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
|
||||||
|
@ -34,48 +33,6 @@ struct alt_region {
|
||||||
struct alt_instr *end;
|
struct alt_instr *end;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
* Decode the imm field of a b/bl instruction, and return the byte
|
|
||||||
* offset as a signed value (so it can be used when computing a new
|
|
||||||
* branch target).
|
|
||||||
*/
|
|
||||||
static s32 get_branch_offset(u32 insn)
|
|
||||||
{
|
|
||||||
s32 imm = aarch64_insn_decode_immediate(AARCH64_INSN_IMM_26, insn);
|
|
||||||
|
|
||||||
/* sign-extend the immediate before turning it into a byte offset */
|
|
||||||
return (imm << 6) >> 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
static u32 get_alt_insn(u8 *insnptr, u8 *altinsnptr)
|
|
||||||
{
|
|
||||||
u32 insn;
|
|
||||||
|
|
||||||
aarch64_insn_read(altinsnptr, &insn);
|
|
||||||
|
|
||||||
/* Stop the world on instructions we don't support... */
|
|
||||||
BUG_ON(aarch64_insn_is_cbz(insn));
|
|
||||||
BUG_ON(aarch64_insn_is_cbnz(insn));
|
|
||||||
BUG_ON(aarch64_insn_is_bcond(insn));
|
|
||||||
/* ... and there is probably more. */
|
|
||||||
|
|
||||||
if (aarch64_insn_is_b(insn) || aarch64_insn_is_bl(insn)) {
|
|
||||||
enum aarch64_insn_branch_type type;
|
|
||||||
unsigned long target;
|
|
||||||
|
|
||||||
if (aarch64_insn_is_b(insn))
|
|
||||||
type = AARCH64_INSN_BRANCH_NOLINK;
|
|
||||||
else
|
|
||||||
type = AARCH64_INSN_BRANCH_LINK;
|
|
||||||
|
|
||||||
target = (unsigned long)altinsnptr + get_branch_offset(insn);
|
|
||||||
insn = aarch64_insn_gen_branch_imm((unsigned long)insnptr,
|
|
||||||
target, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
return insn;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int __apply_alternatives(void *alt_region)
|
static int __apply_alternatives(void *alt_region)
|
||||||
{
|
{
|
||||||
struct alt_instr *alt;
|
struct alt_instr *alt;
|
||||||
|
@ -83,9 +40,6 @@ static int __apply_alternatives(void *alt_region)
|
||||||
u8 *origptr, *replptr;
|
u8 *origptr, *replptr;
|
||||||
|
|
||||||
for (alt = region->begin; alt < region->end; alt++) {
|
for (alt = region->begin; alt < region->end; alt++) {
|
||||||
u32 insn;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (!cpus_have_cap(alt->cpufeature))
|
if (!cpus_have_cap(alt->cpufeature))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -95,12 +49,7 @@ static int __apply_alternatives(void *alt_region)
|
||||||
|
|
||||||
origptr = (u8 *)&alt->orig_offset + alt->orig_offset;
|
origptr = (u8 *)&alt->orig_offset + alt->orig_offset;
|
||||||
replptr = (u8 *)&alt->alt_offset + alt->alt_offset;
|
replptr = (u8 *)&alt->alt_offset + alt->alt_offset;
|
||||||
|
memcpy(origptr, replptr, alt->alt_len);
|
||||||
for (i = 0; i < alt->alt_len; i += sizeof(insn)) {
|
|
||||||
insn = get_alt_insn(origptr + i, replptr + i);
|
|
||||||
aarch64_insn_write(origptr + i, insn);
|
|
||||||
}
|
|
||||||
|
|
||||||
flush_icache_range((uintptr_t)origptr,
|
flush_icache_range((uintptr_t)origptr,
|
||||||
(uintptr_t)(origptr + alt->alt_len));
|
(uintptr_t)(origptr + alt->alt_len));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1315,15 +1315,15 @@ static int armpmu_device_probe(struct platform_device *pdev)
|
||||||
if (!cpu_pmu)
|
if (!cpu_pmu)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
irqs = kcalloc(pdev->num_resources, sizeof(*irqs), GFP_KERNEL);
|
|
||||||
if (!irqs)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
/* Don't bother with PPIs; they're already affine */
|
/* Don't bother with PPIs; they're already affine */
|
||||||
irq = platform_get_irq(pdev, 0);
|
irq = platform_get_irq(pdev, 0);
|
||||||
if (irq >= 0 && irq_is_percpu(irq))
|
if (irq >= 0 && irq_is_percpu(irq))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
irqs = kcalloc(pdev->num_resources, sizeof(*irqs), GFP_KERNEL);
|
||||||
|
if (!irqs)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
for (i = 0; i < pdev->num_resources; ++i) {
|
for (i = 0; i < pdev->num_resources; ++i) {
|
||||||
struct device_node *dn;
|
struct device_node *dn;
|
||||||
int cpu;
|
int cpu;
|
||||||
|
|
|
@ -328,10 +328,12 @@ static int ptdump_init(void)
|
||||||
for (j = 0; j < pg_level[i].num; j++)
|
for (j = 0; j < pg_level[i].num; j++)
|
||||||
pg_level[i].mask |= pg_level[i].bits[j].mask;
|
pg_level[i].mask |= pg_level[i].bits[j].mask;
|
||||||
|
|
||||||
|
#ifdef CONFIG_SPARSEMEM_VMEMMAP
|
||||||
address_markers[VMEMMAP_START_NR].start_address =
|
address_markers[VMEMMAP_START_NR].start_address =
|
||||||
(unsigned long)virt_to_page(PAGE_OFFSET);
|
(unsigned long)virt_to_page(PAGE_OFFSET);
|
||||||
address_markers[VMEMMAP_END_NR].start_address =
|
address_markers[VMEMMAP_END_NR].start_address =
|
||||||
(unsigned long)virt_to_page(high_memory);
|
(unsigned long)virt_to_page(high_memory);
|
||||||
|
#endif
|
||||||
|
|
||||||
pe = debugfs_create_file("kernel_page_tables", 0400, NULL, NULL,
|
pe = debugfs_create_file("kernel_page_tables", 0400, NULL, NULL,
|
||||||
&ptdump_fops);
|
&ptdump_fops);
|
||||||
|
|
|
@ -487,7 +487,7 @@ emit_cond_jmp:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
imm64 = (u64)insn1.imm << 32 | imm;
|
imm64 = (u64)insn1.imm << 32 | (u32)imm;
|
||||||
emit_a64_mov_i64(dst, imm64, ctx);
|
emit_a64_mov_i64(dst, imm64, ctx);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче