ARM fixes for 5.11:
- Fix latent bug with DC21285 (Footbridge PCI bridge) configuration accessors that affects GCC >= 4.9.2 - Fix misplaced tegra_uart_config in decompressor - Ensure signal page contents are initialised - Fix kexec oops -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEuNNh8scc2k/wOAE+9OeQG+StrGQFAmAdHmUACgkQ9OeQG+St rGTctQ/8Dlwc3G40ziB7WgaSTKsx809e5rLmoT5EvzyCuuHy6wDIbtmmY+hb7HUU h1bys4epWYwbiYHsDDfGWKJy+qHA1sBfZunJdRVE0O/v1x5vMkLruyC8oh0NtplS LRj2HReK6oIuNFA/ywa30xcWvw/BnpM+saoptXQhdsuy26QNirUqQYsq/E2mMkBG Sq9KMtncxw3R1o4ahgJcDAQ7PtvKZIzkEym7gtF/PhaTuiDhmDCOMzVQwikGmgnw ci8Mtzvses6segdCrYGr+4f7G+D7LhEprXLCbpwT5tCoEXXTQ1SIQPIvTjX0qMip UpZ7gP+x7eQZTWv+OnKfgRf4pOC3sqKDth3glrYVJWBzoC7faW1KrY5ugpf4OmQ8 /IKd33PUMmm+a0eHBX/Z/ZZplzIJn81O1gBswG3zfjSCw1xa53QlfZlWEhgttZmN aqTnaP5dcp0mlyOkvju4AcdQ9xBxdBlCQimSRDkCy3FPjgpwlw4zNVPhnYaoK7En sguTGXI8MXAB6MpxGom5oPQw+GtUngyZIrQlk6PbXpmfBUmqAOhRVg6TbyvbgMIy 5i+CVyp3tIzFpY19pSnpNhbzTgnmybBRY0BqFBg8KH0s1r2SyxhhmqSm00bIw4Cf rNuLQtEy4YEVOdcmKlwX9sxUBUo/M27ZXkx7u96+QLapKAFyTb8= =V/Oi -----END PGP SIGNATURE----- Merge tag 'for-linus' of git://git.armlinux.org.uk/~rmk/linux-arm Pull ARM fixes from Russell King: - Fix latent bug with DC21285 (Footbridge PCI bridge) configuration accessors that affects GCC >= 4.9.2 - Fix misplaced tegra_uart_config in decompressor - Ensure signal page contents are initialised - Fix kexec oops * tag 'for-linus' of git://git.armlinux.org.uk/~rmk/linux-arm: ARM: kexec: fix oops after TLB are invalidated ARM: ensure the signal page contains defined contents ARM: 9043/1: tegra: Fix misplaced tegra_uart_config in decompressor ARM: footbridge: fix dc21285 PCI configuration accessors
This commit is contained in:
commit
4a7859ea09
12
arch/arm/include/asm/kexec-internal.h
Normal file
12
arch/arm/include/asm/kexec-internal.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
#ifndef _ARM_KEXEC_INTERNAL_H
|
||||||
|
#define _ARM_KEXEC_INTERNAL_H
|
||||||
|
|
||||||
|
struct kexec_relocate_data {
|
||||||
|
unsigned long kexec_start_address;
|
||||||
|
unsigned long kexec_indirection_page;
|
||||||
|
unsigned long kexec_mach_type;
|
||||||
|
unsigned long kexec_r2;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -149,7 +149,34 @@
|
|||||||
|
|
||||||
.align
|
.align
|
||||||
99: .word .
|
99: .word .
|
||||||
|
#if defined(ZIMAGE)
|
||||||
|
.word . + 4
|
||||||
|
/*
|
||||||
|
* Storage for the state maintained by the macro.
|
||||||
|
*
|
||||||
|
* In the kernel proper, this data is located in arch/arm/mach-tegra/tegra.c.
|
||||||
|
* That's because this header is included from multiple files, and we only
|
||||||
|
* want a single copy of the data. In particular, the UART probing code above
|
||||||
|
* assumes it's running using physical addresses. This is true when this file
|
||||||
|
* is included from head.o, but not when included from debug.o. So we need
|
||||||
|
* to share the probe results between the two copies, rather than having
|
||||||
|
* to re-run the probing again later.
|
||||||
|
*
|
||||||
|
* In the decompressor, we put the storage right here, since common.c
|
||||||
|
* isn't included in the decompressor build. This storage data gets put in
|
||||||
|
* .text even though it's really data, since .data is discarded from the
|
||||||
|
* decompressor. Luckily, .text is writeable in the decompressor, unless
|
||||||
|
* CONFIG_ZBOOT_ROM. That dependency is handled in arch/arm/Kconfig.debug.
|
||||||
|
*/
|
||||||
|
/* Debug UART initialization required */
|
||||||
|
.word 1
|
||||||
|
/* Debug UART physical address */
|
||||||
|
.word 0
|
||||||
|
/* Debug UART virtual address */
|
||||||
|
.word 0
|
||||||
|
#else
|
||||||
.word tegra_uart_config
|
.word tegra_uart_config
|
||||||
|
#endif
|
||||||
.ltorg
|
.ltorg
|
||||||
|
|
||||||
/* Load previously selected UART address */
|
/* Load previously selected UART address */
|
||||||
@ -189,30 +216,3 @@
|
|||||||
|
|
||||||
.macro waituarttxrdy,rd,rx
|
.macro waituarttxrdy,rd,rx
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/*
|
|
||||||
* Storage for the state maintained by the macros above.
|
|
||||||
*
|
|
||||||
* In the kernel proper, this data is located in arch/arm/mach-tegra/tegra.c.
|
|
||||||
* That's because this header is included from multiple files, and we only
|
|
||||||
* want a single copy of the data. In particular, the UART probing code above
|
|
||||||
* assumes it's running using physical addresses. This is true when this file
|
|
||||||
* is included from head.o, but not when included from debug.o. So we need
|
|
||||||
* to share the probe results between the two copies, rather than having
|
|
||||||
* to re-run the probing again later.
|
|
||||||
*
|
|
||||||
* In the decompressor, we put the symbol/storage right here, since common.c
|
|
||||||
* isn't included in the decompressor build. This symbol gets put in .text
|
|
||||||
* even though it's really data, since .data is discarded from the
|
|
||||||
* decompressor. Luckily, .text is writeable in the decompressor, unless
|
|
||||||
* CONFIG_ZBOOT_ROM. That dependency is handled in arch/arm/Kconfig.debug.
|
|
||||||
*/
|
|
||||||
#if defined(ZIMAGE)
|
|
||||||
tegra_uart_config:
|
|
||||||
/* Debug UART initialization required */
|
|
||||||
.word 1
|
|
||||||
/* Debug UART physical address */
|
|
||||||
.word 0
|
|
||||||
/* Debug UART virtual address */
|
|
||||||
.word 0
|
|
||||||
#endif
|
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
|
#include <asm/kexec-internal.h>
|
||||||
#include <asm/glue-df.h>
|
#include <asm/glue-df.h>
|
||||||
#include <asm/glue-pf.h>
|
#include <asm/glue-pf.h>
|
||||||
#include <asm/mach/arch.h>
|
#include <asm/mach/arch.h>
|
||||||
@ -170,5 +171,9 @@ int main(void)
|
|||||||
DEFINE(MPU_RGN_PRBAR, offsetof(struct mpu_rgn, prbar));
|
DEFINE(MPU_RGN_PRBAR, offsetof(struct mpu_rgn, prbar));
|
||||||
DEFINE(MPU_RGN_PRLAR, offsetof(struct mpu_rgn, prlar));
|
DEFINE(MPU_RGN_PRLAR, offsetof(struct mpu_rgn, prlar));
|
||||||
#endif
|
#endif
|
||||||
|
DEFINE(KEXEC_START_ADDR, offsetof(struct kexec_relocate_data, kexec_start_address));
|
||||||
|
DEFINE(KEXEC_INDIR_PAGE, offsetof(struct kexec_relocate_data, kexec_indirection_page));
|
||||||
|
DEFINE(KEXEC_MACH_TYPE, offsetof(struct kexec_relocate_data, kexec_mach_type));
|
||||||
|
DEFINE(KEXEC_R2, offsetof(struct kexec_relocate_data, kexec_r2));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include <linux/of_fdt.h>
|
#include <linux/of_fdt.h>
|
||||||
#include <asm/mmu_context.h>
|
#include <asm/mmu_context.h>
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
|
#include <asm/kexec-internal.h>
|
||||||
#include <asm/fncpy.h>
|
#include <asm/fncpy.h>
|
||||||
#include <asm/mach-types.h>
|
#include <asm/mach-types.h>
|
||||||
#include <asm/smp_plat.h>
|
#include <asm/smp_plat.h>
|
||||||
@ -22,11 +23,6 @@
|
|||||||
extern void relocate_new_kernel(void);
|
extern void relocate_new_kernel(void);
|
||||||
extern const unsigned int relocate_new_kernel_size;
|
extern const unsigned int relocate_new_kernel_size;
|
||||||
|
|
||||||
extern unsigned long kexec_start_address;
|
|
||||||
extern unsigned long kexec_indirection_page;
|
|
||||||
extern unsigned long kexec_mach_type;
|
|
||||||
extern unsigned long kexec_boot_atags;
|
|
||||||
|
|
||||||
static atomic_t waiting_for_crash_ipi;
|
static atomic_t waiting_for_crash_ipi;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -159,6 +155,7 @@ void (*kexec_reinit)(void);
|
|||||||
void machine_kexec(struct kimage *image)
|
void machine_kexec(struct kimage *image)
|
||||||
{
|
{
|
||||||
unsigned long page_list, reboot_entry_phys;
|
unsigned long page_list, reboot_entry_phys;
|
||||||
|
struct kexec_relocate_data *data;
|
||||||
void (*reboot_entry)(void);
|
void (*reboot_entry)(void);
|
||||||
void *reboot_code_buffer;
|
void *reboot_code_buffer;
|
||||||
|
|
||||||
@ -174,18 +171,17 @@ void machine_kexec(struct kimage *image)
|
|||||||
|
|
||||||
reboot_code_buffer = page_address(image->control_code_page);
|
reboot_code_buffer = page_address(image->control_code_page);
|
||||||
|
|
||||||
/* Prepare parameters for reboot_code_buffer*/
|
|
||||||
set_kernel_text_rw();
|
|
||||||
kexec_start_address = image->start;
|
|
||||||
kexec_indirection_page = page_list;
|
|
||||||
kexec_mach_type = machine_arch_type;
|
|
||||||
kexec_boot_atags = image->arch.kernel_r2;
|
|
||||||
|
|
||||||
/* copy our kernel relocation code to the control code page */
|
/* copy our kernel relocation code to the control code page */
|
||||||
reboot_entry = fncpy(reboot_code_buffer,
|
reboot_entry = fncpy(reboot_code_buffer,
|
||||||
&relocate_new_kernel,
|
&relocate_new_kernel,
|
||||||
relocate_new_kernel_size);
|
relocate_new_kernel_size);
|
||||||
|
|
||||||
|
data = reboot_code_buffer + relocate_new_kernel_size;
|
||||||
|
data->kexec_start_address = image->start;
|
||||||
|
data->kexec_indirection_page = page_list;
|
||||||
|
data->kexec_mach_type = machine_arch_type;
|
||||||
|
data->kexec_r2 = image->arch.kernel_r2;
|
||||||
|
|
||||||
/* get the identity mapping physical address for the reboot code */
|
/* get the identity mapping physical address for the reboot code */
|
||||||
reboot_entry_phys = virt_to_idmap(reboot_entry);
|
reboot_entry_phys = virt_to_idmap(reboot_entry);
|
||||||
|
|
||||||
|
@ -5,14 +5,16 @@
|
|||||||
|
|
||||||
#include <linux/linkage.h>
|
#include <linux/linkage.h>
|
||||||
#include <asm/assembler.h>
|
#include <asm/assembler.h>
|
||||||
|
#include <asm/asm-offsets.h>
|
||||||
#include <asm/kexec.h>
|
#include <asm/kexec.h>
|
||||||
|
|
||||||
.align 3 /* not needed for this code, but keeps fncpy() happy */
|
.align 3 /* not needed for this code, but keeps fncpy() happy */
|
||||||
|
|
||||||
ENTRY(relocate_new_kernel)
|
ENTRY(relocate_new_kernel)
|
||||||
|
|
||||||
ldr r0,kexec_indirection_page
|
adr r7, relocate_new_kernel_end
|
||||||
ldr r1,kexec_start_address
|
ldr r0, [r7, #KEXEC_INDIR_PAGE]
|
||||||
|
ldr r1, [r7, #KEXEC_START_ADDR]
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If there is no indirection page (we are doing crashdumps)
|
* If there is no indirection page (we are doing crashdumps)
|
||||||
@ -57,34 +59,16 @@ ENTRY(relocate_new_kernel)
|
|||||||
|
|
||||||
2:
|
2:
|
||||||
/* Jump to relocated kernel */
|
/* Jump to relocated kernel */
|
||||||
mov lr,r1
|
mov lr, r1
|
||||||
mov r0,#0
|
mov r0, #0
|
||||||
ldr r1,kexec_mach_type
|
ldr r1, [r7, #KEXEC_MACH_TYPE]
|
||||||
ldr r2,kexec_boot_atags
|
ldr r2, [r7, #KEXEC_R2]
|
||||||
ARM( ret lr )
|
ARM( ret lr )
|
||||||
THUMB( bx lr )
|
THUMB( bx lr )
|
||||||
|
|
||||||
.align
|
|
||||||
|
|
||||||
.globl kexec_start_address
|
|
||||||
kexec_start_address:
|
|
||||||
.long 0x0
|
|
||||||
|
|
||||||
.globl kexec_indirection_page
|
|
||||||
kexec_indirection_page:
|
|
||||||
.long 0x0
|
|
||||||
|
|
||||||
.globl kexec_mach_type
|
|
||||||
kexec_mach_type:
|
|
||||||
.long 0x0
|
|
||||||
|
|
||||||
/* phy addr of the atags for the new kernel */
|
|
||||||
.globl kexec_boot_atags
|
|
||||||
kexec_boot_atags:
|
|
||||||
.long 0x0
|
|
||||||
|
|
||||||
ENDPROC(relocate_new_kernel)
|
ENDPROC(relocate_new_kernel)
|
||||||
|
|
||||||
|
.align 3
|
||||||
relocate_new_kernel_end:
|
relocate_new_kernel_end:
|
||||||
|
|
||||||
.globl relocate_new_kernel_size
|
.globl relocate_new_kernel_size
|
||||||
|
@ -693,18 +693,20 @@ struct page *get_signal_page(void)
|
|||||||
|
|
||||||
addr = page_address(page);
|
addr = page_address(page);
|
||||||
|
|
||||||
|
/* Poison the entire page */
|
||||||
|
memset32(addr, __opcode_to_mem_arm(0xe7fddef1),
|
||||||
|
PAGE_SIZE / sizeof(u32));
|
||||||
|
|
||||||
/* Give the signal return code some randomness */
|
/* Give the signal return code some randomness */
|
||||||
offset = 0x200 + (get_random_int() & 0x7fc);
|
offset = 0x200 + (get_random_int() & 0x7fc);
|
||||||
signal_return_offset = offset;
|
signal_return_offset = offset;
|
||||||
|
|
||||||
/*
|
/* Copy signal return handlers into the page */
|
||||||
* Copy signal return handlers into the vector page, and
|
|
||||||
* set sigreturn to be a pointer to these.
|
|
||||||
*/
|
|
||||||
memcpy(addr + offset, sigreturn_codes, sizeof(sigreturn_codes));
|
memcpy(addr + offset, sigreturn_codes, sizeof(sigreturn_codes));
|
||||||
|
|
||||||
ptr = (unsigned long)addr + offset;
|
/* Flush out all instructions in this page */
|
||||||
flush_icache_range(ptr, ptr + sizeof(sigreturn_codes));
|
ptr = (unsigned long)addr;
|
||||||
|
flush_icache_range(ptr, ptr + PAGE_SIZE);
|
||||||
|
|
||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
@ -65,15 +65,15 @@ dc21285_read_config(struct pci_bus *bus, unsigned int devfn, int where,
|
|||||||
if (addr)
|
if (addr)
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case 1:
|
case 1:
|
||||||
asm("ldrb %0, [%1, %2]"
|
asm volatile("ldrb %0, [%1, %2]"
|
||||||
: "=r" (v) : "r" (addr), "r" (where) : "cc");
|
: "=r" (v) : "r" (addr), "r" (where) : "cc");
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
asm("ldrh %0, [%1, %2]"
|
asm volatile("ldrh %0, [%1, %2]"
|
||||||
: "=r" (v) : "r" (addr), "r" (where) : "cc");
|
: "=r" (v) : "r" (addr), "r" (where) : "cc");
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
asm("ldr %0, [%1, %2]"
|
asm volatile("ldr %0, [%1, %2]"
|
||||||
: "=r" (v) : "r" (addr), "r" (where) : "cc");
|
: "=r" (v) : "r" (addr), "r" (where) : "cc");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -99,17 +99,17 @@ dc21285_write_config(struct pci_bus *bus, unsigned int devfn, int where,
|
|||||||
if (addr)
|
if (addr)
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case 1:
|
case 1:
|
||||||
asm("strb %0, [%1, %2]"
|
asm volatile("strb %0, [%1, %2]"
|
||||||
: : "r" (value), "r" (addr), "r" (where)
|
: : "r" (value), "r" (addr), "r" (where)
|
||||||
: "cc");
|
: "cc");
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
asm("strh %0, [%1, %2]"
|
asm volatile("strh %0, [%1, %2]"
|
||||||
: : "r" (value), "r" (addr), "r" (where)
|
: : "r" (value), "r" (addr), "r" (where)
|
||||||
: "cc");
|
: "cc");
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
asm("str %0, [%1, %2]"
|
asm volatile("str %0, [%1, %2]"
|
||||||
: : "r" (value), "r" (addr), "r" (where)
|
: : "r" (value), "r" (addr), "r" (where)
|
||||||
: "cc");
|
: "cc");
|
||||||
break;
|
break;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user