arm64 fixes:
- Enable 48-bit VA space now that KVM has been fixed, together with a couple of fixes for pgd allocation alignment and initial memblock current_limit. There is still a dependency on !ARM_SMMU which needs to be updated as it uses the page table manipulation macros of the host kernel - eBPF fixes following changes/conflicts during the merging window - Compat types affecting compat_elf_prpsinfo - Compilation error on UP builds - ASLR fix when /proc/sys/kernel/randomize_va_space == 0 - DT definitions for CLCD support on ARMv8 model platform -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJUSowhAAoJEGvWsS0AyF7x4A8QAK/KJj3aEhRoJCFKtkrKcQer WydkHEVpJtk8Y+o9zIBU/J9HXDDakQlIZi3bNcWA+TQda1yr7zqEgVRZwhfaQMIu oXLzSLnZtiqe2HU7TaccJfFG293K+gysjTPRPixdAwWO/9hvoPOqJHnBRWKTDNzh 8D04PTM9dcpKXvVjPcRHIxbk2oH04a/tjOBeTpi5uWaUdZLWjHt2dTjWwP/q0af4 XsDrF5pYQaYEzCI9MczSbcQLwFPkxhS36JH+V+OhmVoCFv0PT7mm5o29DiU1N/Rt UsAwtBQ4oQV8seZMQaT5sVDNBqqqyfrYDAACdY0ewIr81PF7z8tdm5+G1P4JfQ0t iVguz3s1rJ6V0yXy0t18XHgpPFLLqpoEDEO6obYXYrhe2nTquQulgJoLaIu2qXmO jlL8R1rHWKRAQ7xIyLATjhUmW5dc2aK6xO+/3Xuz1+JOunNeOZW67xexpPzRU4Vh sw9S8sKwJmL5wH+ojqxsbg73WvTUs5dd4WoK7Tci8FZ0qfG14pyaX4s9iRhUZArQ 4vx8lfF7FQma8nZ0ytXSY/666dAedL/bXZrmPhjVl/XYoEA4IFaW7uDIIqGbUMWr oNOe4QahxZu5jHI8CYncXHw51RXst+03oE5Uon30x7F3ZD71perLZe2dMTTaezKv 2MX9/BULRrjpgkA4gW5L =QssH -----END PGP SIGNATURE----- Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux Pull arm64 fixes from Catalin Marinas: - enable 48-bit VA space now that KVM has been fixed, together with a couple of fixes for pgd allocation alignment and initial memblock current_limit. There is still a dependency on !ARM_SMMU which needs to be updated as it uses the page table manipulation macros of the host kernel - eBPF fixes following changes/conflicts during the merging window - Compat types affecting compat_elf_prpsinfo - Compilation error on UP builds - ASLR fix when /proc/sys/kernel/randomize_va_space == 0 - DT definitions for CLCD support on ARMv8 model platform * tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux: arm64: Fix memblock current_limit with 64K pages and 48-bit VA arm64: ASLR: Don't randomise text when randomise_va_space == 0 arm64: vexpress: Add CLCD support to the ARMv8 model platform arm64: Fix compilation error on UP builds Documentation/arm64/memory.txt: fix typo net: bpf: arm64: minor fix of type in jited arm64: bpf: add 'load 64-bit immediate' instruction arm64: bpf: add 'shift by register' instructions net: bpf: arm64: address randomize and write protect JIT code arm64: mm: Correct fixmap pagetable types arm64: compat: fix compat types affecting struct compat_elf_prpsinfo arm64: Align less than PAGE_SIZE pgds naturally arm64: Allow 48-bits VA space without ARM_SMMU
This commit is contained in:
Коммит
cdc63a0595
|
@ -17,7 +17,7 @@ User addresses have bits 63:48 set to 0 while the kernel addresses have
|
|||
the same bits set to 1. TTBRx selection is given by bit 63 of the
|
||||
virtual address. The swapper_pg_dir contains only kernel (global)
|
||||
mappings while the user pgd contains only user (non-global) mappings.
|
||||
The swapper_pgd_dir address is written to TTBR1 and never written to
|
||||
The swapper_pg_dir address is written to TTBR1 and never written to
|
||||
TTBR0.
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
config ARM64
|
||||
def_bool y
|
||||
select ARCH_BINFMT_ELF_RANDOMIZE_PIE
|
||||
select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
|
||||
select ARCH_HAS_SG_CHAIN
|
||||
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
|
||||
|
@ -232,7 +233,7 @@ config ARM64_VA_BITS_42
|
|||
|
||||
config ARM64_VA_BITS_48
|
||||
bool "48-bit"
|
||||
depends on BROKEN
|
||||
depends on !ARM_SMMU
|
||||
|
||||
endchoice
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
bank-width = <4>;
|
||||
};
|
||||
|
||||
vram@2,00000000 {
|
||||
v2m_video_ram: vram@2,00000000 {
|
||||
compatible = "arm,vexpress-vram";
|
||||
reg = <2 0x00000000 0x00800000>;
|
||||
};
|
||||
|
@ -179,9 +179,42 @@
|
|||
clcd@1f0000 {
|
||||
compatible = "arm,pl111", "arm,primecell";
|
||||
reg = <0x1f0000 0x1000>;
|
||||
interrupt-names = "combined";
|
||||
interrupts = <14>;
|
||||
clocks = <&v2m_oscclk1>, <&v2m_clk24mhz>;
|
||||
clock-names = "clcdclk", "apb_pclk";
|
||||
arm,pl11x,framebuffer = <0x18000000 0x00180000>;
|
||||
memory-region = <&v2m_video_ram>;
|
||||
max-memory-bandwidth = <130000000>; /* 16bpp @ 63.5MHz */
|
||||
|
||||
port {
|
||||
v2m_clcd_pads: endpoint {
|
||||
remote-endpoint = <&v2m_clcd_panel>;
|
||||
arm,pl11x,tft-r0g0b0-pads = <0 8 16>;
|
||||
};
|
||||
};
|
||||
|
||||
panel {
|
||||
compatible = "panel-dpi";
|
||||
|
||||
port {
|
||||
v2m_clcd_panel: endpoint {
|
||||
remote-endpoint = <&v2m_clcd_pads>;
|
||||
};
|
||||
};
|
||||
|
||||
panel-timing {
|
||||
clock-frequency = <63500127>;
|
||||
hactive = <1024>;
|
||||
hback-porch = <152>;
|
||||
hfront-porch = <48>;
|
||||
hsync-len = <104>;
|
||||
vactive = <768>;
|
||||
vback-porch = <23>;
|
||||
vfront-porch = <3>;
|
||||
vsync-len = <4>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
virtio_block@0130000 {
|
||||
|
|
|
@ -78,6 +78,7 @@ CONFIG_NET_XGENE=y
|
|||
# CONFIG_WLAN is not set
|
||||
CONFIG_INPUT_EVDEV=y
|
||||
# CONFIG_SERIO_SERPORT is not set
|
||||
CONFIG_SERIO_AMBAKMI=y
|
||||
CONFIG_LEGACY_PTY_COUNT=16
|
||||
CONFIG_SERIAL_8250=y
|
||||
CONFIG_SERIAL_8250_CONSOLE=y
|
||||
|
@ -90,6 +91,7 @@ CONFIG_VIRTIO_CONSOLE=y
|
|||
CONFIG_REGULATOR=y
|
||||
CONFIG_REGULATOR_FIXED_VOLTAGE=y
|
||||
CONFIG_FB=y
|
||||
CONFIG_FB_ARMCLCD=y
|
||||
CONFIG_FRAMEBUFFER_CONSOLE=y
|
||||
CONFIG_LOGO=y
|
||||
# CONFIG_LOGO_LINUX_MONO is not set
|
||||
|
|
|
@ -37,8 +37,8 @@ typedef s32 compat_ssize_t;
|
|||
typedef s32 compat_time_t;
|
||||
typedef s32 compat_clock_t;
|
||||
typedef s32 compat_pid_t;
|
||||
typedef u32 __compat_uid_t;
|
||||
typedef u32 __compat_gid_t;
|
||||
typedef u16 __compat_uid_t;
|
||||
typedef u16 __compat_gid_t;
|
||||
typedef u16 __compat_uid16_t;
|
||||
typedef u16 __compat_gid16_t;
|
||||
typedef u32 __compat_uid32_t;
|
||||
|
|
|
@ -126,7 +126,7 @@ typedef struct user_fpsimd_state elf_fpregset_t;
|
|||
* that it will "exec", and that there is sufficient room for the brk.
|
||||
*/
|
||||
extern unsigned long randomize_et_dyn(unsigned long base);
|
||||
#define ELF_ET_DYN_BASE (randomize_et_dyn(2 * TASK_SIZE_64 / 3))
|
||||
#define ELF_ET_DYN_BASE (2 * TASK_SIZE_64 / 3)
|
||||
|
||||
/*
|
||||
* When the program starts, a1 contains a pointer to a function to be
|
||||
|
@ -169,7 +169,7 @@ extern unsigned long arch_randomize_brk(struct mm_struct *mm);
|
|||
#define COMPAT_ELF_PLATFORM ("v8l")
|
||||
#endif
|
||||
|
||||
#define COMPAT_ELF_ET_DYN_BASE (randomize_et_dyn(2 * TASK_SIZE_32 / 3))
|
||||
#define COMPAT_ELF_ET_DYN_BASE (2 * TASK_SIZE_32 / 3)
|
||||
|
||||
/* AArch32 registers. */
|
||||
#define COMPAT_ELF_NGREG 18
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef __ASM_IRQ_WORK_H
|
||||
#define __ASM_IRQ_WORK_H
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
#include <asm/smp.h>
|
||||
|
||||
static inline bool arch_irq_work_has_interrupt(void)
|
||||
|
@ -8,4 +10,13 @@ static inline bool arch_irq_work_has_interrupt(void)
|
|||
return !!__smp_cross_call;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline bool arch_irq_work_has_interrupt(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __ASM_IRQ_WORK_H */
|
||||
|
|
|
@ -378,8 +378,3 @@ unsigned long arch_randomize_brk(struct mm_struct *mm)
|
|||
{
|
||||
return randomize_base(mm->brk);
|
||||
}
|
||||
|
||||
unsigned long randomize_et_dyn(unsigned long base)
|
||||
{
|
||||
return randomize_base(base);
|
||||
}
|
||||
|
|
|
@ -105,10 +105,10 @@ EXPORT_SYMBOL(ioremap_cache);
|
|||
|
||||
static pte_t bm_pte[PTRS_PER_PTE] __page_aligned_bss;
|
||||
#if CONFIG_ARM64_PGTABLE_LEVELS > 2
|
||||
static pte_t bm_pmd[PTRS_PER_PMD] __page_aligned_bss;
|
||||
static pmd_t bm_pmd[PTRS_PER_PMD] __page_aligned_bss;
|
||||
#endif
|
||||
#if CONFIG_ARM64_PGTABLE_LEVELS > 3
|
||||
static pte_t bm_pud[PTRS_PER_PUD] __page_aligned_bss;
|
||||
static pud_t bm_pud[PTRS_PER_PUD] __page_aligned_bss;
|
||||
#endif
|
||||
|
||||
static inline pud_t * __init early_ioremap_pud(unsigned long addr)
|
||||
|
|
|
@ -297,11 +297,15 @@ static void __init map_mem(void)
|
|||
* create_mapping requires puds, pmds and ptes to be allocated from
|
||||
* memory addressable from the initial direct kernel mapping.
|
||||
*
|
||||
* The initial direct kernel mapping, located at swapper_pg_dir,
|
||||
* gives us PUD_SIZE memory starting from PHYS_OFFSET (which must be
|
||||
* aligned to 2MB as per Documentation/arm64/booting.txt).
|
||||
* The initial direct kernel mapping, located at swapper_pg_dir, gives
|
||||
* us PUD_SIZE (4K pages) or PMD_SIZE (64K pages) memory starting from
|
||||
* PHYS_OFFSET (which must be aligned to 2MB as per
|
||||
* Documentation/arm64/booting.txt).
|
||||
*/
|
||||
limit = PHYS_OFFSET + PUD_SIZE;
|
||||
if (IS_ENABLED(CONFIG_ARM64_64K_PAGES))
|
||||
limit = PHYS_OFFSET + PMD_SIZE;
|
||||
else
|
||||
limit = PHYS_OFFSET + PUD_SIZE;
|
||||
memblock_set_current_limit(limit);
|
||||
|
||||
/* map all the memory banks */
|
||||
|
|
|
@ -30,12 +30,14 @@
|
|||
|
||||
#define PGD_SIZE (PTRS_PER_PGD * sizeof(pgd_t))
|
||||
|
||||
static struct kmem_cache *pgd_cache;
|
||||
|
||||
pgd_t *pgd_alloc(struct mm_struct *mm)
|
||||
{
|
||||
if (PGD_SIZE == PAGE_SIZE)
|
||||
return (pgd_t *)get_zeroed_page(GFP_KERNEL);
|
||||
else
|
||||
return kzalloc(PGD_SIZE, GFP_KERNEL);
|
||||
return kmem_cache_zalloc(pgd_cache, GFP_KERNEL);
|
||||
}
|
||||
|
||||
void pgd_free(struct mm_struct *mm, pgd_t *pgd)
|
||||
|
@ -43,5 +45,17 @@ void pgd_free(struct mm_struct *mm, pgd_t *pgd)
|
|||
if (PGD_SIZE == PAGE_SIZE)
|
||||
free_page((unsigned long)pgd);
|
||||
else
|
||||
kfree(pgd);
|
||||
kmem_cache_free(pgd_cache, pgd);
|
||||
}
|
||||
|
||||
static int __init pgd_cache_init(void)
|
||||
{
|
||||
/*
|
||||
* Naturally aligned pgds required by the architecture.
|
||||
*/
|
||||
if (PGD_SIZE != PAGE_SIZE)
|
||||
pgd_cache = kmem_cache_create("pgd_cache", PGD_SIZE, PGD_SIZE,
|
||||
SLAB_PANIC, NULL);
|
||||
return 0;
|
||||
}
|
||||
core_initcall(pgd_cache_init);
|
||||
|
|
|
@ -144,8 +144,12 @@
|
|||
|
||||
/* Data-processing (2 source) */
|
||||
/* Rd = Rn OP Rm */
|
||||
#define A64_UDIV(sf, Rd, Rn, Rm) aarch64_insn_gen_data2(Rd, Rn, Rm, \
|
||||
A64_VARIANT(sf), AARCH64_INSN_DATA2_UDIV)
|
||||
#define A64_DATA2(sf, Rd, Rn, Rm, type) aarch64_insn_gen_data2(Rd, Rn, Rm, \
|
||||
A64_VARIANT(sf), AARCH64_INSN_DATA2_##type)
|
||||
#define A64_UDIV(sf, Rd, Rn, Rm) A64_DATA2(sf, Rd, Rn, Rm, UDIV)
|
||||
#define A64_LSLV(sf, Rd, Rn, Rm) A64_DATA2(sf, Rd, Rn, Rm, LSLV)
|
||||
#define A64_LSRV(sf, Rd, Rn, Rm) A64_DATA2(sf, Rd, Rn, Rm, LSRV)
|
||||
#define A64_ASRV(sf, Rd, Rn, Rm) A64_DATA2(sf, Rd, Rn, Rm, ASRV)
|
||||
|
||||
/* Data-processing (3 source) */
|
||||
/* Rd = Ra + Rn * Rm */
|
||||
|
|
|
@ -19,12 +19,13 @@
|
|||
#define pr_fmt(fmt) "bpf_jit: " fmt
|
||||
|
||||
#include <linux/filter.h>
|
||||
#include <linux/moduleloader.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/debug-monitors.h>
|
||||
|
||||
#include "bpf_jit.h"
|
||||
|
||||
|
@ -119,6 +120,14 @@ static inline int bpf2a64_offset(int bpf_to, int bpf_from,
|
|||
return to - from;
|
||||
}
|
||||
|
||||
static void jit_fill_hole(void *area, unsigned int size)
|
||||
{
|
||||
u32 *ptr;
|
||||
/* We are guaranteed to have aligned memory. */
|
||||
for (ptr = area; size >= sizeof(u32); size -= sizeof(u32))
|
||||
*ptr++ = cpu_to_le32(AARCH64_BREAK_FAULT);
|
||||
}
|
||||
|
||||
static inline int epilogue_offset(const struct jit_ctx *ctx)
|
||||
{
|
||||
int to = ctx->offset[ctx->prog->len - 1];
|
||||
|
@ -196,6 +205,12 @@ static void build_epilogue(struct jit_ctx *ctx)
|
|||
emit(A64_RET(A64_LR), ctx);
|
||||
}
|
||||
|
||||
/* JITs an eBPF instruction.
|
||||
* Returns:
|
||||
* 0 - successfully JITed an 8-byte eBPF instruction.
|
||||
* >0 - successfully JITed a 16-byte eBPF instruction.
|
||||
* <0 - failed to JIT.
|
||||
*/
|
||||
static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
|
||||
{
|
||||
const u8 code = insn->code;
|
||||
|
@ -252,6 +267,18 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
|
|||
emit(A64_MUL(is64, tmp, tmp, src), ctx);
|
||||
emit(A64_SUB(is64, dst, dst, tmp), ctx);
|
||||
break;
|
||||
case BPF_ALU | BPF_LSH | BPF_X:
|
||||
case BPF_ALU64 | BPF_LSH | BPF_X:
|
||||
emit(A64_LSLV(is64, dst, dst, src), ctx);
|
||||
break;
|
||||
case BPF_ALU | BPF_RSH | BPF_X:
|
||||
case BPF_ALU64 | BPF_RSH | BPF_X:
|
||||
emit(A64_LSRV(is64, dst, dst, src), ctx);
|
||||
break;
|
||||
case BPF_ALU | BPF_ARSH | BPF_X:
|
||||
case BPF_ALU64 | BPF_ARSH | BPF_X:
|
||||
emit(A64_ASRV(is64, dst, dst, src), ctx);
|
||||
break;
|
||||
/* dst = -dst */
|
||||
case BPF_ALU | BPF_NEG:
|
||||
case BPF_ALU64 | BPF_NEG:
|
||||
|
@ -443,6 +470,27 @@ emit_cond_jmp:
|
|||
emit(A64_B(jmp_offset), ctx);
|
||||
break;
|
||||
|
||||
/* dst = imm64 */
|
||||
case BPF_LD | BPF_IMM | BPF_DW:
|
||||
{
|
||||
const struct bpf_insn insn1 = insn[1];
|
||||
u64 imm64;
|
||||
|
||||
if (insn1.code != 0 || insn1.src_reg != 0 ||
|
||||
insn1.dst_reg != 0 || insn1.off != 0) {
|
||||
/* Note: verifier in BPF core must catch invalid
|
||||
* instructions.
|
||||
*/
|
||||
pr_err_once("Invalid BPF_LD_IMM64 instruction\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
imm64 = (u64)insn1.imm << 32 | imm;
|
||||
emit_a64_mov_i64(dst, imm64, ctx);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* LDX: dst = *(size *)(src + off) */
|
||||
case BPF_LDX | BPF_MEM | BPF_W:
|
||||
case BPF_LDX | BPF_MEM | BPF_H:
|
||||
|
@ -594,6 +642,10 @@ static int build_body(struct jit_ctx *ctx)
|
|||
ctx->offset[i] = ctx->idx;
|
||||
|
||||
ret = build_insn(insn, ctx);
|
||||
if (ret > 0) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
@ -613,8 +665,10 @@ void bpf_jit_compile(struct bpf_prog *prog)
|
|||
|
||||
void bpf_int_jit_compile(struct bpf_prog *prog)
|
||||
{
|
||||
struct bpf_binary_header *header;
|
||||
struct jit_ctx ctx;
|
||||
int image_size;
|
||||
u8 *image_ptr;
|
||||
|
||||
if (!bpf_jit_enable)
|
||||
return;
|
||||
|
@ -636,23 +690,25 @@ void bpf_int_jit_compile(struct bpf_prog *prog)
|
|||
goto out;
|
||||
|
||||
build_prologue(&ctx);
|
||||
|
||||
build_epilogue(&ctx);
|
||||
|
||||
/* Now we know the actual image size. */
|
||||
image_size = sizeof(u32) * ctx.idx;
|
||||
ctx.image = module_alloc(image_size);
|
||||
if (unlikely(ctx.image == NULL))
|
||||
header = bpf_jit_binary_alloc(image_size, &image_ptr,
|
||||
sizeof(u32), jit_fill_hole);
|
||||
if (header == NULL)
|
||||
goto out;
|
||||
|
||||
/* 2. Now, the actual pass. */
|
||||
|
||||
ctx.image = (u32 *)image_ptr;
|
||||
ctx.idx = 0;
|
||||
|
||||
build_prologue(&ctx);
|
||||
|
||||
ctx.body_offset = ctx.idx;
|
||||
if (build_body(&ctx)) {
|
||||
module_free(NULL, ctx.image);
|
||||
bpf_jit_binary_free(header);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -663,17 +719,25 @@ void bpf_int_jit_compile(struct bpf_prog *prog)
|
|||
bpf_jit_dump(prog->len, image_size, 2, ctx.image);
|
||||
|
||||
bpf_flush_icache(ctx.image, ctx.image + ctx.idx);
|
||||
prog->bpf_func = (void *)ctx.image;
|
||||
prog->jited = 1;
|
||||
|
||||
set_memory_ro((unsigned long)header, header->pages);
|
||||
prog->bpf_func = (void *)ctx.image;
|
||||
prog->jited = true;
|
||||
out:
|
||||
kfree(ctx.offset);
|
||||
}
|
||||
|
||||
void bpf_jit_free(struct bpf_prog *prog)
|
||||
{
|
||||
if (prog->jited)
|
||||
module_free(NULL, prog->bpf_func);
|
||||
unsigned long addr = (unsigned long)prog->bpf_func & PAGE_MASK;
|
||||
struct bpf_binary_header *header = (void *)addr;
|
||||
|
||||
kfree(prog);
|
||||
if (!prog->jited)
|
||||
goto free_filter;
|
||||
|
||||
set_memory_rw(addr, header->pages);
|
||||
bpf_jit_binary_free(header);
|
||||
|
||||
free_filter:
|
||||
bpf_prog_unlock_free(prog);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче