mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-27 06:04:23 +08:00
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
|
||||
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
|
||||
#endif
|
||||
.ltorg
|
||||
|
||||
/* Load previously selected UART address */
|
||||
@ -189,30 +216,3 @@
|
||||
|
||||
.macro waituarttxrdy,rd,rx
|
||||
.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/dma-mapping.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/kexec-internal.h>
|
||||
#include <asm/glue-df.h>
|
||||
#include <asm/glue-pf.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_PRLAR, offsetof(struct mpu_rgn, prlar));
|
||||
#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;
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <linux/of_fdt.h>
|
||||
#include <asm/mmu_context.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/kexec-internal.h>
|
||||
#include <asm/fncpy.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/smp_plat.h>
|
||||
@ -22,11 +23,6 @@
|
||||
extern void relocate_new_kernel(void);
|
||||
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;
|
||||
|
||||
/*
|
||||
@ -159,6 +155,7 @@ void (*kexec_reinit)(void);
|
||||
void machine_kexec(struct kimage *image)
|
||||
{
|
||||
unsigned long page_list, reboot_entry_phys;
|
||||
struct kexec_relocate_data *data;
|
||||
void (*reboot_entry)(void);
|
||||
void *reboot_code_buffer;
|
||||
|
||||
@ -174,18 +171,17 @@ void machine_kexec(struct kimage *image)
|
||||
|
||||
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 */
|
||||
reboot_entry = fncpy(reboot_code_buffer,
|
||||
&relocate_new_kernel,
|
||||
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 */
|
||||
reboot_entry_phys = virt_to_idmap(reboot_entry);
|
||||
|
||||
|
@ -5,14 +5,16 @@
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <asm/kexec.h>
|
||||
|
||||
.align 3 /* not needed for this code, but keeps fncpy() happy */
|
||||
|
||||
ENTRY(relocate_new_kernel)
|
||||
|
||||
ldr r0,kexec_indirection_page
|
||||
ldr r1,kexec_start_address
|
||||
adr r7, relocate_new_kernel_end
|
||||
ldr r0, [r7, #KEXEC_INDIR_PAGE]
|
||||
ldr r1, [r7, #KEXEC_START_ADDR]
|
||||
|
||||
/*
|
||||
* If there is no indirection page (we are doing crashdumps)
|
||||
@ -57,34 +59,16 @@ ENTRY(relocate_new_kernel)
|
||||
|
||||
2:
|
||||
/* Jump to relocated kernel */
|
||||
mov lr,r1
|
||||
mov r0,#0
|
||||
ldr r1,kexec_mach_type
|
||||
ldr r2,kexec_boot_atags
|
||||
ARM( ret 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
|
||||
mov lr, r1
|
||||
mov r0, #0
|
||||
ldr r1, [r7, #KEXEC_MACH_TYPE]
|
||||
ldr r2, [r7, #KEXEC_R2]
|
||||
ARM( ret lr )
|
||||
THUMB( bx lr )
|
||||
|
||||
ENDPROC(relocate_new_kernel)
|
||||
|
||||
.align 3
|
||||
relocate_new_kernel_end:
|
||||
|
||||
.globl relocate_new_kernel_size
|
||||
|
@ -693,18 +693,20 @@ struct page *get_signal_page(void)
|
||||
|
||||
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 */
|
||||
offset = 0x200 + (get_random_int() & 0x7fc);
|
||||
signal_return_offset = offset;
|
||||
|
||||
/*
|
||||
* Copy signal return handlers into the vector page, and
|
||||
* set sigreturn to be a pointer to these.
|
||||
*/
|
||||
/* Copy signal return handlers into the page */
|
||||
memcpy(addr + offset, sigreturn_codes, sizeof(sigreturn_codes));
|
||||
|
||||
ptr = (unsigned long)addr + offset;
|
||||
flush_icache_range(ptr, ptr + sizeof(sigreturn_codes));
|
||||
/* Flush out all instructions in this page */
|
||||
ptr = (unsigned long)addr;
|
||||
flush_icache_range(ptr, ptr + PAGE_SIZE);
|
||||
|
||||
return page;
|
||||
}
|
||||
|
@ -65,15 +65,15 @@ dc21285_read_config(struct pci_bus *bus, unsigned int devfn, int where,
|
||||
if (addr)
|
||||
switch (size) {
|
||||
case 1:
|
||||
asm("ldrb %0, [%1, %2]"
|
||||
asm volatile("ldrb %0, [%1, %2]"
|
||||
: "=r" (v) : "r" (addr), "r" (where) : "cc");
|
||||
break;
|
||||
case 2:
|
||||
asm("ldrh %0, [%1, %2]"
|
||||
asm volatile("ldrh %0, [%1, %2]"
|
||||
: "=r" (v) : "r" (addr), "r" (where) : "cc");
|
||||
break;
|
||||
case 4:
|
||||
asm("ldr %0, [%1, %2]"
|
||||
asm volatile("ldr %0, [%1, %2]"
|
||||
: "=r" (v) : "r" (addr), "r" (where) : "cc");
|
||||
break;
|
||||
}
|
||||
@ -99,17 +99,17 @@ dc21285_write_config(struct pci_bus *bus, unsigned int devfn, int where,
|
||||
if (addr)
|
||||
switch (size) {
|
||||
case 1:
|
||||
asm("strb %0, [%1, %2]"
|
||||
asm volatile("strb %0, [%1, %2]"
|
||||
: : "r" (value), "r" (addr), "r" (where)
|
||||
: "cc");
|
||||
break;
|
||||
case 2:
|
||||
asm("strh %0, [%1, %2]"
|
||||
asm volatile("strh %0, [%1, %2]"
|
||||
: : "r" (value), "r" (addr), "r" (where)
|
||||
: "cc");
|
||||
break;
|
||||
case 4:
|
||||
asm("str %0, [%1, %2]"
|
||||
asm volatile("str %0, [%1, %2]"
|
||||
: : "r" (value), "r" (addr), "r" (where)
|
||||
: "cc");
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user