Merge tag 'powerpc-7.1-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux

Pull powerpc updates from Madhavan Srinivasan:

 - powerpc support for huge pfnmaps

 - Cleanups to use masked user access

 - Rework pnv_ioda_pick_m64_pe() to use better bitmap API

 - Convert powerpc to AUDIT_ARCH_COMPAT_GENERIC

 - Backup region offset update to eflcorehdr

 - Fixes for wii/ps3 platform

 - Implement JIT support for private stack in powerpc

 - Implement JIT support for fsession in powerpc64 trampoline

 - Add support for instruction array and indirect jump in powerpc

 - Misc selftest fixes and cleanups

Thanks to Abhishek Dubey, Aditya Gupta, Alex Williamson, Amit Machhiwal,
Andrew Donnellan, Bartosz Golaszewski, Cédric Le Goater, Chen Ni,
Christophe Leroy (CS GROUP), Hari Bathini, J. Neuschäfer, Mukesh Kumar
Chaurasiya (IBM), Nam Cao, Nilay Shroff, Pavithra Prakash, Randy Dunlap,
Ritesh Harjani (IBM), Shrikanth Hegde, Sourabh Jain, Vaibhav Jain,
Venkat Rao Bagalkote, and Yury Norov (NVIDIA)

* tag 'powerpc-7.1-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: (47 commits)
  mailmap: Add entry for Andrew Donnellan
  powerpc32/bpf: fix loading fsession func metadata using PPC_LI32
  selftest/bpf: Enable gotox tests for powerpc64
  powerpc64/bpf: Add support for indirect jump
  selftest/bpf: Enable instruction array test for powerpc
  powerpc/bpf: Add support for instruction array
  powerpc32/bpf: Add fsession support
  powerpc64/bpf: Implement fsession support
  selftests/bpf: Enable private stack tests for powerpc64
  powerpc64/bpf: Implement JIT support for private stack
  powerpc: pci-ioda: Optimize pnv_ioda_pick_m64_pe()
  powerpc: pci-ioda: use bitmap_alloc() in pnv_ioda_pick_m64_pe()
  powerpc/net: Inline checksum wrappers and convert to scoped user access
  powerpc/sstep: Convert to scoped user access
  powerpc/align: Convert emulate_spe() to scoped user access
  powerpc/ptrace: Convert gpr32_set_common_user() to scoped user access
  powerpc/futex: Use masked user access
  powerpc/audit: Convert powerpc to AUDIT_ARCH_COMPAT_GENERIC
  cpuidle: powerpc: avoid double clear when breaking snooze
  powerpc/ps3: spu.c: fix enum and Return kernel-doc warnings
  ...
This commit is contained in:
Linus Torvalds
2026-04-14 17:10:15 -07:00
49 changed files with 688 additions and 567 deletions
+3
View File
@@ -75,6 +75,9 @@ Andreas Herrmann <aherrman@de.ibm.com>
Andreas Hindborg <a.hindborg@kernel.org> <a.hindborg@samsung.com>
Andrej Shadura <andrew.shadura@collabora.co.uk>
Andrej Shadura <andrew@shadura.me> <andrew@beldisplaytech.com>
Andrew Donnellan <andrew+kernel@donnellan.id.au> <andrew@donnellan.id.au>
Andrew Donnellan <andrew+kernel@donnellan.id.au> <ajd@linux.ibm.com>
Andrew Donnellan <andrew+kernel@donnellan.id.au> <andrew.donnellan@au1.ibm.com>
Andrew Morton <akpm@linux-foundation.org>
Andrew Murray <amurray@thegoodpenguin.co.uk> <amurray@embedded-bits.co.uk>
Andrew Murray <amurray@thegoodpenguin.co.uk> <andrew.murray@arm.com>
+2 -4
View File
@@ -172,6 +172,7 @@ config PPC
select ARCH_STACKWALK
select ARCH_SUPPORTS_ATOMIC_RMW
select ARCH_SUPPORTS_DEBUG_PAGEALLOC if PPC_BOOK3S || PPC_8xx
select ARCH_SUPPORTS_HUGE_PFNMAP if PPC_BOOK3S_64 && TRANSPARENT_HUGEPAGE
select ARCH_SUPPORTS_PAGE_TABLE_CHECK if !HUGETLB_PAGE
select ARCH_SUPPORTS_SCHED_MC if SMP
select ARCH_SUPPORTS_SCHED_SMT if PPC64 && SMP
@@ -188,6 +189,7 @@ config PPC
select ARCH_WANT_OPTIMIZE_DAX_VMEMMAP if PPC_RADIX_MMU
select ARCH_WANTS_MODULES_DATA_IN_VMALLOC if PPC_BOOK3S_32 || PPC_8xx
select ARCH_WEAK_RELEASE_ACQUIRE
select AUDIT_ARCH_COMPAT_GENERIC
select BINFMT_ELF
select BUILDTIME_TABLE_SORT
select CLONE_BACKWARDS
@@ -370,10 +372,6 @@ config GENERIC_TBSYNC
bool
default y if PPC32 && SMP
config AUDIT_ARCH
bool
default y
config GENERIC_BUG
bool
default y
+4 -4
View File
@@ -29,7 +29,7 @@
bootargs = "root=/dev/mmcblk0p2 rootwait udbg-immortal";
};
memory {
memory@0 {
device_type = "memory";
reg = <0x00000000 0x01800000 /* MEM1 24MB 1T-SRAM */
0x10000000 0x04000000>; /* MEM2 64MB GDDR3 */
@@ -246,7 +246,7 @@
compatible = "gpio-leds";
/* This is the blue LED in the disk drive slot */
drive-slot {
led-0 {
label = "wii:blue:drive_slot";
gpios = <&GPIO 5 GPIO_ACTIVE_HIGH>;
panic-indicator;
@@ -256,13 +256,13 @@
gpio-keys {
compatible = "gpio-keys";
power {
button-power {
label = "Power Button";
gpios = <&GPIO 0 GPIO_ACTIVE_HIGH>;
linux,code = <KEY_POWER>;
};
eject {
button-eject {
label = "Eject Button";
gpios = <&GPIO 6 GPIO_ACTIVE_HIGH>;
linux,code = <KEY_EJECTCD>;
+40 -3
View File
@@ -107,8 +107,8 @@
* in here, on radix we expect them to be zero.
*/
#define _HPAGE_CHG_MASK (PTE_RPN_MASK | _PAGE_HPTEFLAGS | _PAGE_DIRTY | \
_PAGE_ACCESSED | H_PAGE_THP_HUGE | _PAGE_PTE | \
_PAGE_SOFT_DIRTY)
_PAGE_ACCESSED | H_PAGE_THP_HUGE | _PAGE_SPECIAL | \
_PAGE_PTE | _PAGE_SOFT_DIRTY)
/*
* user access blocked by key
*/
@@ -1289,6 +1289,29 @@ static inline pud_t pud_mkhuge(pud_t pud)
return pud;
}
#ifdef CONFIG_ARCH_SUPPORTS_PMD_PFNMAP
static inline bool pmd_special(pmd_t pmd)
{
return pte_special(pmd_pte(pmd));
}
static inline pmd_t pmd_mkspecial(pmd_t pmd)
{
return pte_pmd(pte_mkspecial(pmd_pte(pmd)));
}
#endif
#ifdef CONFIG_ARCH_SUPPORTS_PUD_PFNMAP
static inline bool pud_special(pud_t pud)
{
return pte_special(pud_pte(pud));
}
static inline pud_t pud_mkspecial(pud_t pud)
{
return pte_pud(pte_mkspecial(pud_pte(pud)));
}
#endif
#define __HAVE_ARCH_PMDP_SET_ACCESS_FLAGS
extern int pmdp_set_access_flags(struct vm_area_struct *vma,
@@ -1313,12 +1336,27 @@ static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
{
pmd_t old_pmd;
/*
* Non-present PMDs can be migration entries or device-private THP
* entries. This can happen at 2 places:
* - When the address space is being unmapped zap_huge_pmd(), and we
* encounter non-present pmds.
* - migrate_vma_collect_huge_pmd() could calls this during migration
* of device-private pmd entries.
*/
if (!pmd_present(*pmdp)) {
old_pmd = READ_ONCE(*pmdp);
pmd_clear(pmdp);
goto out;
}
if (radix_enabled()) {
old_pmd = radix__pmdp_huge_get_and_clear(mm, addr, pmdp);
} else {
old_pmd = hash__pmdp_huge_get_and_clear(mm, addr, pmdp);
}
out:
page_table_check_pmd_clear(mm, addr, old_pmd);
return old_pmd;
@@ -1400,7 +1438,6 @@ static inline bool arch_needs_pgtable_deposit(void)
return false;
return true;
}
extern void serialize_against_pte_lookup(struct mm_struct *mm);
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
@@ -92,7 +92,6 @@ extern void radix__flush_tlb_page_psize(struct mm_struct *mm, unsigned long vmad
#define radix__flush_tlb_page(vma,addr) radix__local_flush_tlb_page(vma,addr)
#define radix__flush_tlb_page_psize(mm,addr,p) radix__local_flush_tlb_page_psize(mm,addr,p)
#endif
extern void radix__flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr);
extern void radix__flush_tlb_collapsed_pmd(struct mm_struct *mm, unsigned long addr);
extern void radix__flush_tlb_all(void);
+18 -4
View File
@@ -8,6 +8,7 @@
#include <linux/bitops.h>
#include <linux/in6.h>
#include <linux/uaccess.h>
/*
* Computes the checksum of a memory block at src, length len,
* and adds in "sum" (32-bit), while copying the block to dst.
@@ -21,11 +22,24 @@
extern __wsum csum_partial_copy_generic(const void *src, void *dst, int len);
#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
extern __wsum csum_and_copy_from_user(const void __user *src, void *dst,
int len);
static inline __wsum csum_and_copy_from_user(const void __user *src, void *dst, int len)
{
scoped_user_read_access_size(src, len, efault)
return csum_partial_copy_generic((void __force *)src, dst, len);
efault:
return 0;
}
#define HAVE_CSUM_COPY_USER
extern __wsum csum_and_copy_to_user(const void *src, void __user *dst,
int len);
static inline __wsum csum_and_copy_to_user(const void *src, void __user *dst, int len)
{
scoped_user_write_access_size(dst, len, efault)
return csum_partial_copy_generic(src, (void __force *)dst, len);
efault:
return 0;
}
#define _HAVE_ARCH_CSUM_AND_COPY
#define csum_partial_copy_nocheck(src, dst, len) \
+2 -4
View File
@@ -33,8 +33,7 @@ static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
{
int oldval = 0, ret;
if (!user_access_begin(uaddr, sizeof(u32)))
return -EFAULT;
uaddr = masked_user_access_begin(uaddr);
switch (op) {
case FUTEX_OP_SET:
@@ -69,8 +68,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
int ret = 0;
u32 prev;
if (!user_access_begin(uaddr, sizeof(u32)))
return -EFAULT;
uaddr = masked_user_access_begin(uaddr);
__asm__ __volatile__ (
PPC_ATOMIC_ENTRY_BARRIER
+11 -3
View File
@@ -66,11 +66,9 @@ void relocate_new_kernel(unsigned long indirection_page, unsigned long reboot_co
unsigned long start_address) __noreturn;
void kexec_copy_flush(struct kimage *image);
#ifdef CONFIG_KEXEC_FILE
extern const struct kexec_file_ops kexec_elf64_ops;
#if defined(CONFIG_KEXEC_FILE) || defined(CONFIG_CRASH_DUMP)
#define ARCH_HAS_KIMAGE_ARCH
struct kimage_arch {
struct crash_mem *exclude_ranges;
@@ -78,6 +76,10 @@ struct kimage_arch {
void *backup_buf;
void *fdt;
};
#endif
#ifdef CONFIG_KEXEC_FILE
extern const struct kexec_file_ops kexec_elf64_ops;
char *setup_kdump_cmdline(struct kimage *image, char *cmdline,
unsigned long cmdline_len);
@@ -145,6 +147,10 @@ int arch_crash_hotplug_support(struct kimage *image, unsigned long kexec_flags);
unsigned int arch_crash_get_elfcorehdr_size(void);
#define crash_get_elfcorehdr_size arch_crash_get_elfcorehdr_size
int machine_kexec_post_load(struct kimage *image);
#define machine_kexec_post_load machine_kexec_post_load
#endif /* CONFIG_CRASH_HOTPLUG */
extern int crashing_cpu;
@@ -159,6 +165,8 @@ extern void default_machine_crash_shutdown(struct pt_regs *regs);
extern void crash_kexec_prepare(void);
extern void crash_kexec_secondary(struct pt_regs *regs);
extern void sync_backup_region_phdr(struct kimage *image, Elf64_Ehdr *ehdr,
bool phdr_to_kimage);
static inline bool kdump_in_progress(void)
{
return crashing_cpu >= 0;
+14
View File
@@ -63,6 +63,20 @@ static inline pgprot_t pte_pgprot(pte_t pte)
return __pgprot(pte_flags);
}
#ifdef CONFIG_PPC64
#define pmd_pgprot pmd_pgprot
static inline pgprot_t pmd_pgprot(pmd_t pmd)
{
return pte_pgprot(pmd_pte(pmd));
}
#define pud_pgprot pud_pgprot
static inline pgprot_t pud_pgprot(pud_t pud)
{
return pte_pgprot(pud_pte(pud));
}
#endif /* CONFIG_PPC64 */
static inline pgprot_t pgprot_nx(pgprot_t prot)
{
return pte_pgprot(pte_exprotect(__pte(pgprot_val(prot))));
+9 -6
View File
@@ -65,6 +65,7 @@ struct ps3_dma_region_ops;
/**
* struct ps3_dma_region - A per device dma state variables structure
* @dev: device structure
* @did: The HV device id.
* @page_size: The ioc pagesize.
* @region_type: The HV region type.
@@ -108,15 +109,15 @@ struct ps3_dma_region_ops {
dma_addr_t bus_addr,
unsigned long len);
};
struct ps3_system_bus_device;
/**
* struct ps3_dma_region_init - Helper to initialize structure variables
*
* Helper to properly initialize variables prior to calling
* ps3_system_bus_device_register.
*/
struct ps3_system_bus_device;
int ps3_dma_region_init(struct ps3_system_bus_device *dev,
struct ps3_dma_region *r, enum ps3_dma_page_size page_size,
enum ps3_dma_region_type region_type, void *addr, unsigned long len);
@@ -156,10 +157,12 @@ struct ps3_mmio_region_ops {
int (*free)(struct ps3_mmio_region *);
};
/**
* struct ps3_mmio_region_init - Helper to initialize structure variables
* ps3_mmio_region_init - Helper to initialize structure variables
*
* Helper to properly initialize variables prior to calling
* ps3_system_bus_device_register.
*
* Returns: %0 on success, %-errno on error (or BUG())
*/
int ps3_mmio_region_init(struct ps3_system_bus_device *dev,
@@ -405,7 +408,7 @@ static inline struct ps3_system_bus_driver *
}
/**
* ps3_system_bus_set_drvdata -
* ps3_system_bus_set_drvdata - set driver's private data for this device
* @dev: device structure
* @data: Data to set
*/
@@ -464,7 +467,7 @@ enum ps3_lpm_rights {
* enum ps3_lpm_tb_type - Type of trace buffer lv1 should use.
*
* @PS3_LPM_TB_TYPE_NONE: Do not use a trace buffer.
* @PS3_LPM_RIGHTS_USE_TB: Use the lv1 internal trace buffer. Must have
* @PS3_LPM_TB_TYPE_INTERNAL: Use the lv1 internal trace buffer. Must have
* rights @PS3_LPM_RIGHTS_USE_TB.
*/
+7
View File
@@ -0,0 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#ifndef _ASM_POWERPC_UNISTD32_H_
#define _ASM_POWERPC_UNISTD32_H_
#include <asm/unistd_32.h>
#endif /* _ASM_POWERPC_UNISTD32_H_ */
-3
View File
@@ -149,9 +149,6 @@ obj-$(CONFIG_PCI) += pci_$(BITS).o $(pci64-y) \
pci-common.o pci_of_scan.o
obj-$(CONFIG_PCI_MSI) += msi.o
obj-$(CONFIG_AUDIT) += audit.o
obj64-$(CONFIG_AUDIT) += compat_audit.o
obj-y += trace/
ifneq ($(CONFIG_PPC_INDIRECT_PIO),y)
+33 -42
View File
@@ -165,25 +165,23 @@ static int emulate_spe(struct pt_regs *regs, unsigned int reg,
temp.ll = data.ll = 0;
p = addr;
if (!user_read_access_begin(addr, nb))
return -EFAULT;
switch (nb) {
case 8:
unsafe_get_user(temp.v[0], p++, Efault_read);
unsafe_get_user(temp.v[1], p++, Efault_read);
unsafe_get_user(temp.v[2], p++, Efault_read);
unsafe_get_user(temp.v[3], p++, Efault_read);
fallthrough;
case 4:
unsafe_get_user(temp.v[4], p++, Efault_read);
unsafe_get_user(temp.v[5], p++, Efault_read);
fallthrough;
case 2:
unsafe_get_user(temp.v[6], p++, Efault_read);
unsafe_get_user(temp.v[7], p++, Efault_read);
scoped_user_read_access_size(addr, nb, efault) {
switch (nb) {
case 8:
unsafe_get_user(temp.v[0], p++, efault);
unsafe_get_user(temp.v[1], p++, efault);
unsafe_get_user(temp.v[2], p++, efault);
unsafe_get_user(temp.v[3], p++, efault);
fallthrough;
case 4:
unsafe_get_user(temp.v[4], p++, efault);
unsafe_get_user(temp.v[5], p++, efault);
fallthrough;
case 2:
unsafe_get_user(temp.v[6], p++, efault);
unsafe_get_user(temp.v[7], p++, efault);
}
}
user_read_access_end();
switch (instr) {
case EVLDD:
@@ -252,25 +250,23 @@ static int emulate_spe(struct pt_regs *regs, unsigned int reg,
if (flags & ST) {
p = addr;
if (!user_write_access_begin(addr, nb))
return -EFAULT;
switch (nb) {
case 8:
unsafe_put_user(data.v[0], p++, Efault_write);
unsafe_put_user(data.v[1], p++, Efault_write);
unsafe_put_user(data.v[2], p++, Efault_write);
unsafe_put_user(data.v[3], p++, Efault_write);
fallthrough;
case 4:
unsafe_put_user(data.v[4], p++, Efault_write);
unsafe_put_user(data.v[5], p++, Efault_write);
fallthrough;
case 2:
unsafe_put_user(data.v[6], p++, Efault_write);
unsafe_put_user(data.v[7], p++, Efault_write);
scoped_user_write_access_size(addr, nb, efault) {
switch (nb) {
case 8:
unsafe_put_user(data.v[0], p++, efault);
unsafe_put_user(data.v[1], p++, efault);
unsafe_put_user(data.v[2], p++, efault);
unsafe_put_user(data.v[3], p++, efault);
fallthrough;
case 4:
unsafe_put_user(data.v[4], p++, efault);
unsafe_put_user(data.v[5], p++, efault);
fallthrough;
case 2:
unsafe_put_user(data.v[6], p++, efault);
unsafe_put_user(data.v[7], p++, efault);
}
}
user_write_access_end();
} else {
*evr = data.w[0];
regs->gpr[reg] = data.w[1];
@@ -278,12 +274,7 @@ static int emulate_spe(struct pt_regs *regs, unsigned int reg,
return 1;
Efault_read:
user_read_access_end();
return -EFAULT;
Efault_write:
user_write_access_end();
efault:
return -EFAULT;
}
#endif /* CONFIG_SPE */
-87
View File
@@ -1,87 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/init.h>
#include <linux/types.h>
#include <linux/audit.h>
#include <asm/unistd.h>
#include "audit_32.h"
static unsigned dir_class[] = {
#include <asm-generic/audit_dir_write.h>
~0U
};
static unsigned read_class[] = {
#include <asm-generic/audit_read.h>
~0U
};
static unsigned write_class[] = {
#include <asm-generic/audit_write.h>
~0U
};
static unsigned chattr_class[] = {
#include <asm-generic/audit_change_attr.h>
~0U
};
static unsigned signal_class[] = {
#include <asm-generic/audit_signal.h>
~0U
};
int audit_classify_arch(int arch)
{
#ifdef CONFIG_PPC64
if (arch == AUDIT_ARCH_PPC)
return 1;
#endif
return 0;
}
int audit_classify_syscall(int abi, unsigned syscall)
{
#ifdef CONFIG_PPC64
if (abi == AUDIT_ARCH_PPC)
return ppc32_classify_syscall(syscall);
#endif
switch(syscall) {
case __NR_open:
return AUDITSC_OPEN;
case __NR_openat:
return AUDITSC_OPENAT;
case __NR_socketcall:
return AUDITSC_SOCKETCALL;
case __NR_execve:
return AUDITSC_EXECVE;
case __NR_openat2:
return AUDITSC_OPENAT2;
default:
return AUDITSC_NATIVE;
}
}
static int __init audit_classes_init(void)
{
#ifdef CONFIG_PPC64
extern __u32 ppc32_dir_class[];
extern __u32 ppc32_write_class[];
extern __u32 ppc32_read_class[];
extern __u32 ppc32_chattr_class[];
extern __u32 ppc32_signal_class[];
audit_register_class(AUDIT_CLASS_WRITE_32, ppc32_write_class);
audit_register_class(AUDIT_CLASS_READ_32, ppc32_read_class);
audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ppc32_dir_class);
audit_register_class(AUDIT_CLASS_CHATTR_32, ppc32_chattr_class);
audit_register_class(AUDIT_CLASS_SIGNAL_32, ppc32_signal_class);
#endif
audit_register_class(AUDIT_CLASS_WRITE, write_class);
audit_register_class(AUDIT_CLASS_READ, read_class);
audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
audit_register_class(AUDIT_CLASS_SIGNAL, signal_class);
return 0;
}
__initcall(audit_classes_init);
-48
View File
@@ -1,48 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/audit_arch.h>
#include <asm/unistd_32.h>
#include "audit_32.h"
unsigned ppc32_dir_class[] = {
#include <asm-generic/audit_dir_write.h>
~0U
};
unsigned ppc32_chattr_class[] = {
#include <asm-generic/audit_change_attr.h>
~0U
};
unsigned ppc32_write_class[] = {
#include <asm-generic/audit_write.h>
~0U
};
unsigned ppc32_read_class[] = {
#include <asm-generic/audit_read.h>
~0U
};
unsigned ppc32_signal_class[] = {
#include <asm-generic/audit_signal.h>
~0U
};
int ppc32_classify_syscall(unsigned syscall)
{
switch(syscall) {
case __NR_open:
return AUDITSC_OPEN;
case __NR_openat:
return AUDITSC_OPENAT;
case __NR_socketcall:
return AUDITSC_SOCKETCALL;
case __NR_execve:
return AUDITSC_EXECVE;
case __NR_openat2:
return AUDITSC_OPENAT2;
default:
return AUDITSC_COMPAT;
}
}
+2 -1
View File
@@ -101,7 +101,6 @@ static int computeSignal(unsigned int tt)
}
/**
*
* kgdb_skipexception - Bail out of KGDB when we've been triggered.
* @exception: Exception vector number
* @regs: Current &struct pt_regs.
@@ -109,6 +108,8 @@ static int computeSignal(unsigned int tt)
* On some architectures we need to skip a breakpoint exception when
* it occurs after a breakpoint has been removed.
*
* Return: return %1 if the breakpoint for this address has been removed,
* otherwise return %0
*/
int kgdb_skipexception(int exception, struct pt_regs *regs)
{
+29 -31
View File
@@ -758,39 +758,38 @@ static int gpr32_set_common_user(struct task_struct *target,
const void *kbuf = NULL;
compat_ulong_t reg;
if (!user_read_access_begin(u, count))
return -EFAULT;
scoped_user_read_access_size(ubuf, count, efault) {
u = ubuf;
pos /= sizeof(reg);
count /= sizeof(reg);
pos /= sizeof(reg);
count /= sizeof(reg);
for (; count > 0 && pos < PT_MSR; --count) {
unsafe_get_user(reg, u++, efault);
regs[pos++] = reg;
}
for (; count > 0 && pos < PT_MSR; --count) {
unsafe_get_user(reg, u++, Efault);
regs[pos++] = reg;
if (count > 0 && pos == PT_MSR) {
unsafe_get_user(reg, u++, efault);
set_user_msr(target, reg);
++pos;
--count;
}
for (; count > 0 && pos <= PT_MAX_PUT_REG; --count) {
unsafe_get_user(reg, u++, efault);
regs[pos++] = reg;
}
for (; count > 0 && pos < PT_TRAP; --count, ++pos)
unsafe_get_user(reg, u++, efault);
if (count > 0 && pos == PT_TRAP) {
unsafe_get_user(reg, u++, efault);
set_user_trap(target, reg);
++pos;
--count;
}
}
if (count > 0 && pos == PT_MSR) {
unsafe_get_user(reg, u++, Efault);
set_user_msr(target, reg);
++pos;
--count;
}
for (; count > 0 && pos <= PT_MAX_PUT_REG; --count) {
unsafe_get_user(reg, u++, Efault);
regs[pos++] = reg;
}
for (; count > 0 && pos < PT_TRAP; --count, ++pos)
unsafe_get_user(reg, u++, Efault);
if (count > 0 && pos == PT_TRAP) {
unsafe_get_user(reg, u++, Efault);
set_user_trap(target, reg);
++pos;
--count;
}
user_read_access_end();
ubuf = u;
pos *= sizeof(reg);
count *= sizeof(reg);
@@ -798,8 +797,7 @@ static int gpr32_set_common_user(struct task_struct *target,
(PT_TRAP + 1) * sizeof(reg), -1);
return 0;
Efault:
user_read_access_end();
efault:
return -EFAULT;
}
+4
View File
@@ -865,6 +865,10 @@ static __init void print_system_info(void)
cur_cpu_spec->cpu_user_features,
cur_cpu_spec->cpu_user_features2);
pr_info("mmu_features = 0x%08x\n", cur_cpu_spec->mmu_features);
pr_info(" possible = 0x%016lx\n",
(unsigned long)MMU_FTRS_POSSIBLE);
pr_info(" always = 0x%016lx\n",
(unsigned long)MMU_FTRS_ALWAYS);
#ifdef CONFIG_PPC64
pr_info("firmware_features = 0x%016lx\n", powerpc_firmware_features);
#ifdef CONFIG_PPC_BOOK3S
+64
View File
@@ -27,6 +27,7 @@
#include <asm/debug.h>
#include <asm/interrupt.h>
#include <asm/kexec_ranges.h>
#include <asm/crashdump-ppc64.h>
/*
* The primary CPU waits a while for all secondary CPUs to enter. This is to
@@ -399,7 +400,68 @@ void default_machine_crash_shutdown(struct pt_regs *regs)
ppc_md.kexec_cpu_down(1, 0);
}
#ifdef CONFIG_CRASH_DUMP
/**
* sync_backup_region_phdr - synchronize backup region offset between
* kexec image and ELF core header.
* @image: Kexec image.
* @ehdr: ELF core header.
* @phdr_to_kimage: If true, read the offset from the ELF program header
* and update the kimage backup region. If false, update
* the ELF program header offset from the kimage backup
* region.
*
* Note: During kexec_load, this is called with phdr_to_kimage = true. For
* kexec_file_load and ELF core header recreation during memory hotplug
* events, it is called with phdr_to_kimage = false.
*
* Returns nothing.
*/
void sync_backup_region_phdr(struct kimage *image, Elf64_Ehdr *ehdr, bool phdr_to_kimage)
{
Elf64_Phdr *phdr;
unsigned int i;
phdr = (Elf64_Phdr *)(ehdr + 1);
for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
if (phdr->p_paddr == BACKUP_SRC_START) {
if (phdr_to_kimage)
image->arch.backup_start = phdr->p_offset;
else
phdr->p_offset = image->arch.backup_start;
kexec_dprintk("Backup region offset updated to 0x%lx\n",
image->arch.backup_start);
return;
}
}
}
#endif /* CONFIG_CRASH_DUMP */
#ifdef CONFIG_CRASH_HOTPLUG
int machine_kexec_post_load(struct kimage *image)
{
int i;
unsigned long mem;
unsigned char *ptr;
if (image->type != KEXEC_TYPE_CRASH)
return 0;
if (image->file_mode)
return 0;
for (i = 0; i < image->nr_segments; i++) {
mem = image->segment[i].mem;
ptr = (char *)__va(mem);
if (ptr && memcmp(ptr, ELFMAG, SELFMAG) == 0)
sync_backup_region_phdr(image, (Elf64_Ehdr *) ptr, true);
}
return 0;
}
#undef pr_fmt
#define pr_fmt(fmt) "crash hp: " fmt
@@ -474,6 +536,8 @@ static void update_crash_elfcorehdr(struct kimage *image, struct memory_notify *
goto out;
}
sync_backup_region_phdr(image, (Elf64_Ehdr *) elfbuf, false);
ptr = __va(mem);
if (ptr) {
/* Temporarily invalidate the crash image while it is replaced */
+1 -28
View File
@@ -374,33 +374,6 @@ static int load_backup_segment(struct kimage *image, struct kexec_buf *kbuf)
return 0;
}
/**
* update_backup_region_phdr - Update backup region's offset for the core to
* export the region appropriately.
* @image: Kexec image.
* @ehdr: ELF core header.
*
* Assumes an exclusive program header is setup for the backup region
* in the ELF headers
*
* Returns nothing.
*/
static void update_backup_region_phdr(struct kimage *image, Elf64_Ehdr *ehdr)
{
Elf64_Phdr *phdr;
unsigned int i;
phdr = (Elf64_Phdr *)(ehdr + 1);
for (i = 0; i < ehdr->e_phnum; i++) {
if (phdr->p_paddr == BACKUP_SRC_START) {
phdr->p_offset = image->arch.backup_start;
kexec_dprintk("Backup region offset updated to 0x%lx\n",
image->arch.backup_start);
return;
}
}
}
static unsigned int kdump_extra_elfcorehdr_size(struct crash_mem *cmem)
{
#if defined(CONFIG_CRASH_HOTPLUG) && defined(CONFIG_MEMORY_HOTPLUG)
@@ -445,7 +418,7 @@ static int load_elfcorehdr_segment(struct kimage *image, struct kexec_buf *kbuf)
}
/* Fix the offset for backup region in the ELF header */
update_backup_region_phdr(image, headers);
sync_backup_region_phdr(image, headers, false);
kbuf->buffer = headers;
kbuf->mem = KEXEC_BUF_MEM_UNKNOWN;

Some files were not shown because too many files have changed in this diff Show More