mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-12 13:55:32 +00:00
![Linus Torvalds](/assets/img/avatar_default.png)
* Support for the Svpbmt extension, which allows memory attributes to be encoded in pages. * Support for the Allwinner D1's implementation of page-based memory attributes. * Support for running rv32 binaries on rv64 systems, via the compat subsystem. * Support for kexec_file(). * Support for the new generic ticket-based spinlocks, which allows us to also move to qrwlock. These should have already gone in through the asm-geneic tree as well. * A handful of cleanups and fixes, include some larger ones around atomics and XIP. -----BEGIN PGP SIGNATURE----- iQJHBAABCAAxFiEEKzw3R0RoQ7JKlDp6LhMZ81+7GIkFAmKWOx8THHBhbG1lckBk YWJiZWx0LmNvbQAKCRAuExnzX7sYieAiEADAUdP7ctoaSQwk5skd/fdA3b4KJuKn 1Zjl+Br32WP0DlbirYBYWRUQZnCCsvABbTiwSJMcG7NBpU5pyQ5XDtB3OA5kJswO Fdp8Nd53//+GK1M5zdEM9OdgvT9fbfTZ3qTu8bKsROOQhGwnYL+Csc9KjFRqEmzN oQii0jlb3n5PM4FL3GsbV4uMn9zzkP9mnVAPQktcock2EKFEK/Fy3uNYMQiO2KPi n8O6bIDaeRdQ6SurzWOuOkt0cro0tEF85ilzT04mynQsOU0el5oGqCxnOhNH3VWg ndqPT6Yafw12hZOtbKJeP+nF8IIR6aJLP3jOtRwEVgcfbXYAw4QwbAV8kQZISefN ipn8JGY7GX9Y9TYU692OUGkcmAb3/dxb6c0WihBdvJ0M6YyLD5X+YKHNuG2onLgK ss43C5Mxsu629rsjdu/PV91B1+pve3rG9siVmF+g4eo0x9rjMq6/JB0Kal/8SLI1 Je5T55d5ujV1a2XxhZLQOSD5owrK7J1M9owb0bloTnr9nVwFTWDrfEQEU82o3kP+ Xm+FfXktnz9ai55NjkMbbEur5D++dKJhBavwCTnBcTrJmMtEH0R45GTK9ZehP+WC rNVrRXjIsS18wsTfJxnkZeFQA38as6VBKTzvwHvOgzTrrZU1/xk3lpkouYtAO6BG gKacHshVilmUuA== =Loi6 -----END PGP SIGNATURE----- Merge tag 'riscv-for-linus-5.19-mw0' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux Pull RISC-V updates from Palmer Dabbelt: - Support for the Svpbmt extension, which allows memory attributes to be encoded in pages - Support for the Allwinner D1's implementation of page-based memory attributes - Support for running rv32 binaries on rv64 systems, via the compat subsystem - Support for kexec_file() - Support for the new generic ticket-based spinlocks, which allows us to also move to qrwlock. These should have already gone in through the asm-geneic tree as well - A handful of cleanups and fixes, include some larger ones around atomics and XIP * tag 'riscv-for-linus-5.19-mw0' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux: (51 commits) RISC-V: Prepare dropping week attribute from arch_kexec_apply_relocations[_add] riscv: compat: Using seperated vdso_maps for compat_vdso_info RISC-V: Fix the XIP build RISC-V: Split out the XIP fixups into their own file RISC-V: ignore xipImage RISC-V: Avoid empty create_*_mapping definitions riscv: Don't output a bogus mmu-type on a no MMU kernel riscv: atomic: Add custom conditional atomic operation implementation riscv: atomic: Optimize dec_if_positive functions riscv: atomic: Cleanup unnecessary definition RISC-V: Load purgatory in kexec_file RISC-V: Add purgatory RISC-V: Support for kexec_file on panic RISC-V: Add kexec_file support RISC-V: use memcpy for kexec_file mode kexec_file: Fix kexec_file.c build error for riscv platform riscv: compat: Add COMPAT Kbuild skeletal support riscv: compat: ptrace: Add compat_arch_ptrace implement riscv: compat: signal: Add rt_frame implementation riscv: add memory-type errata for T-Head ...
457 lines
12 KiB
C
457 lines
12 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef LINUX_KEXEC_H
|
|
#define LINUX_KEXEC_H
|
|
|
|
#define IND_DESTINATION_BIT 0
|
|
#define IND_INDIRECTION_BIT 1
|
|
#define IND_DONE_BIT 2
|
|
#define IND_SOURCE_BIT 3
|
|
|
|
#define IND_DESTINATION (1 << IND_DESTINATION_BIT)
|
|
#define IND_INDIRECTION (1 << IND_INDIRECTION_BIT)
|
|
#define IND_DONE (1 << IND_DONE_BIT)
|
|
#define IND_SOURCE (1 << IND_SOURCE_BIT)
|
|
#define IND_FLAGS (IND_DESTINATION | IND_INDIRECTION | IND_DONE | IND_SOURCE)
|
|
|
|
#if !defined(__ASSEMBLY__)
|
|
|
|
#include <linux/crash_core.h>
|
|
#include <asm/io.h>
|
|
|
|
#include <uapi/linux/kexec.h>
|
|
|
|
/* Location of a reserved region to hold the crash kernel.
|
|
*/
|
|
extern struct resource crashk_res;
|
|
extern struct resource crashk_low_res;
|
|
extern note_buf_t __percpu *crash_notes;
|
|
|
|
#ifdef CONFIG_KEXEC_CORE
|
|
#include <linux/list.h>
|
|
#include <linux/compat.h>
|
|
#include <linux/ioport.h>
|
|
#include <linux/module.h>
|
|
#include <asm/kexec.h>
|
|
|
|
/* Verify architecture specific macros are defined */
|
|
|
|
#ifndef KEXEC_SOURCE_MEMORY_LIMIT
|
|
#error KEXEC_SOURCE_MEMORY_LIMIT not defined
|
|
#endif
|
|
|
|
#ifndef KEXEC_DESTINATION_MEMORY_LIMIT
|
|
#error KEXEC_DESTINATION_MEMORY_LIMIT not defined
|
|
#endif
|
|
|
|
#ifndef KEXEC_CONTROL_MEMORY_LIMIT
|
|
#error KEXEC_CONTROL_MEMORY_LIMIT not defined
|
|
#endif
|
|
|
|
#ifndef KEXEC_CONTROL_MEMORY_GFP
|
|
#define KEXEC_CONTROL_MEMORY_GFP (GFP_KERNEL | __GFP_NORETRY)
|
|
#endif
|
|
|
|
#ifndef KEXEC_CONTROL_PAGE_SIZE
|
|
#error KEXEC_CONTROL_PAGE_SIZE not defined
|
|
#endif
|
|
|
|
#ifndef KEXEC_ARCH
|
|
#error KEXEC_ARCH not defined
|
|
#endif
|
|
|
|
#ifndef KEXEC_CRASH_CONTROL_MEMORY_LIMIT
|
|
#define KEXEC_CRASH_CONTROL_MEMORY_LIMIT KEXEC_CONTROL_MEMORY_LIMIT
|
|
#endif
|
|
|
|
#ifndef KEXEC_CRASH_MEM_ALIGN
|
|
#define KEXEC_CRASH_MEM_ALIGN PAGE_SIZE
|
|
#endif
|
|
|
|
#define KEXEC_CORE_NOTE_NAME CRASH_CORE_NOTE_NAME
|
|
|
|
/*
|
|
* This structure is used to hold the arguments that are used when loading
|
|
* kernel binaries.
|
|
*/
|
|
|
|
typedef unsigned long kimage_entry_t;
|
|
|
|
struct kexec_segment {
|
|
/*
|
|
* This pointer can point to user memory if kexec_load() system
|
|
* call is used or will point to kernel memory if
|
|
* kexec_file_load() system call is used.
|
|
*
|
|
* Use ->buf when expecting to deal with user memory and use ->kbuf
|
|
* when expecting to deal with kernel memory.
|
|
*/
|
|
union {
|
|
void __user *buf;
|
|
void *kbuf;
|
|
};
|
|
size_t bufsz;
|
|
unsigned long mem;
|
|
size_t memsz;
|
|
};
|
|
|
|
#ifdef CONFIG_COMPAT
|
|
struct compat_kexec_segment {
|
|
compat_uptr_t buf;
|
|
compat_size_t bufsz;
|
|
compat_ulong_t mem; /* User space sees this as a (void *) ... */
|
|
compat_size_t memsz;
|
|
};
|
|
#endif
|
|
|
|
#ifdef CONFIG_KEXEC_FILE
|
|
struct purgatory_info {
|
|
/*
|
|
* Pointer to elf header at the beginning of kexec_purgatory.
|
|
* Note: kexec_purgatory is read only
|
|
*/
|
|
const Elf_Ehdr *ehdr;
|
|
/*
|
|
* Temporary, modifiable buffer for sechdrs used for relocation.
|
|
* This memory can be freed post image load.
|
|
*/
|
|
Elf_Shdr *sechdrs;
|
|
/*
|
|
* Temporary, modifiable buffer for stripped purgatory used for
|
|
* relocation. This memory can be freed post image load.
|
|
*/
|
|
void *purgatory_buf;
|
|
};
|
|
|
|
struct kimage;
|
|
|
|
typedef int (kexec_probe_t)(const char *kernel_buf, unsigned long kernel_size);
|
|
typedef void *(kexec_load_t)(struct kimage *image, char *kernel_buf,
|
|
unsigned long kernel_len, char *initrd,
|
|
unsigned long initrd_len, char *cmdline,
|
|
unsigned long cmdline_len);
|
|
typedef int (kexec_cleanup_t)(void *loader_data);
|
|
|
|
#ifdef CONFIG_KEXEC_SIG
|
|
typedef int (kexec_verify_sig_t)(const char *kernel_buf,
|
|
unsigned long kernel_len);
|
|
#endif
|
|
|
|
struct kexec_file_ops {
|
|
kexec_probe_t *probe;
|
|
kexec_load_t *load;
|
|
kexec_cleanup_t *cleanup;
|
|
#ifdef CONFIG_KEXEC_SIG
|
|
kexec_verify_sig_t *verify_sig;
|
|
#endif
|
|
};
|
|
|
|
extern const struct kexec_file_ops * const kexec_file_loaders[];
|
|
|
|
int kexec_image_probe_default(struct kimage *image, void *buf,
|
|
unsigned long buf_len);
|
|
int kexec_image_post_load_cleanup_default(struct kimage *image);
|
|
|
|
/*
|
|
* If kexec_buf.mem is set to this value, kexec_locate_mem_hole()
|
|
* will try to allocate free memory. Arch may overwrite it.
|
|
*/
|
|
#ifndef KEXEC_BUF_MEM_UNKNOWN
|
|
#define KEXEC_BUF_MEM_UNKNOWN 0
|
|
#endif
|
|
|
|
/**
|
|
* struct kexec_buf - parameters for finding a place for a buffer in memory
|
|
* @image: kexec image in which memory to search.
|
|
* @buffer: Contents which will be copied to the allocated memory.
|
|
* @bufsz: Size of @buffer.
|
|
* @mem: On return will have address of the buffer in memory.
|
|
* @memsz: Size for the buffer in memory.
|
|
* @buf_align: Minimum alignment needed.
|
|
* @buf_min: The buffer can't be placed below this address.
|
|
* @buf_max: The buffer can't be placed above this address.
|
|
* @top_down: Allocate from top of memory.
|
|
*/
|
|
struct kexec_buf {
|
|
struct kimage *image;
|
|
void *buffer;
|
|
unsigned long bufsz;
|
|
unsigned long mem;
|
|
unsigned long memsz;
|
|
unsigned long buf_align;
|
|
unsigned long buf_min;
|
|
unsigned long buf_max;
|
|
bool top_down;
|
|
};
|
|
|
|
int kexec_load_purgatory(struct kimage *image, struct kexec_buf *kbuf);
|
|
int kexec_purgatory_get_set_symbol(struct kimage *image, const char *name,
|
|
void *buf, unsigned int size,
|
|
bool get_value);
|
|
void *kexec_purgatory_get_symbol_addr(struct kimage *image, const char *name);
|
|
|
|
/* Architectures may override the below functions */
|
|
int arch_kexec_kernel_image_probe(struct kimage *image, void *buf,
|
|
unsigned long buf_len);
|
|
void *arch_kexec_kernel_image_load(struct kimage *image);
|
|
int arch_kimage_file_post_load_cleanup(struct kimage *image);
|
|
#ifdef CONFIG_KEXEC_SIG
|
|
int arch_kexec_kernel_verify_sig(struct kimage *image, void *buf,
|
|
unsigned long buf_len);
|
|
#endif
|
|
int arch_kexec_locate_mem_hole(struct kexec_buf *kbuf);
|
|
|
|
extern int kexec_add_buffer(struct kexec_buf *kbuf);
|
|
int kexec_locate_mem_hole(struct kexec_buf *kbuf);
|
|
|
|
/* Alignment required for elf header segment */
|
|
#define ELF_CORE_HEADER_ALIGN 4096
|
|
|
|
struct crash_mem_range {
|
|
u64 start, end;
|
|
};
|
|
|
|
struct crash_mem {
|
|
unsigned int max_nr_ranges;
|
|
unsigned int nr_ranges;
|
|
struct crash_mem_range ranges[];
|
|
};
|
|
|
|
extern int crash_exclude_mem_range(struct crash_mem *mem,
|
|
unsigned long long mstart,
|
|
unsigned long long mend);
|
|
extern int crash_prepare_elf64_headers(struct crash_mem *mem, int need_kernel_map,
|
|
void **addr, unsigned long *sz);
|
|
|
|
#ifndef arch_kexec_apply_relocations_add
|
|
/*
|
|
* arch_kexec_apply_relocations_add - apply relocations of type RELA
|
|
* @pi: Purgatory to be relocated.
|
|
* @section: Section relocations applying to.
|
|
* @relsec: Section containing RELAs.
|
|
* @symtab: Corresponding symtab.
|
|
*
|
|
* Return: 0 on success, negative errno on error.
|
|
*/
|
|
static inline int
|
|
arch_kexec_apply_relocations_add(struct purgatory_info *pi, Elf_Shdr *section,
|
|
const Elf_Shdr *relsec, const Elf_Shdr *symtab)
|
|
{
|
|
pr_err("RELA relocation unsupported.\n");
|
|
return -ENOEXEC;
|
|
}
|
|
#endif
|
|
|
|
#ifndef arch_kexec_apply_relocations
|
|
/*
|
|
* arch_kexec_apply_relocations - apply relocations of type REL
|
|
* @pi: Purgatory to be relocated.
|
|
* @section: Section relocations applying to.
|
|
* @relsec: Section containing RELs.
|
|
* @symtab: Corresponding symtab.
|
|
*
|
|
* Return: 0 on success, negative errno on error.
|
|
*/
|
|
static inline int
|
|
arch_kexec_apply_relocations(struct purgatory_info *pi, Elf_Shdr *section,
|
|
const Elf_Shdr *relsec, const Elf_Shdr *symtab)
|
|
{
|
|
pr_err("REL relocation unsupported.\n");
|
|
return -ENOEXEC;
|
|
}
|
|
#endif
|
|
#endif /* CONFIG_KEXEC_FILE */
|
|
|
|
#ifdef CONFIG_KEXEC_ELF
|
|
struct kexec_elf_info {
|
|
/*
|
|
* Where the ELF binary contents are kept.
|
|
* Memory managed by the user of the struct.
|
|
*/
|
|
const char *buffer;
|
|
|
|
const struct elfhdr *ehdr;
|
|
const struct elf_phdr *proghdrs;
|
|
};
|
|
|
|
int kexec_build_elf_info(const char *buf, size_t len, struct elfhdr *ehdr,
|
|
struct kexec_elf_info *elf_info);
|
|
|
|
int kexec_elf_load(struct kimage *image, struct elfhdr *ehdr,
|
|
struct kexec_elf_info *elf_info,
|
|
struct kexec_buf *kbuf,
|
|
unsigned long *lowest_load_addr);
|
|
|
|
void kexec_free_elf_info(struct kexec_elf_info *elf_info);
|
|
int kexec_elf_probe(const char *buf, unsigned long len);
|
|
#endif
|
|
struct kimage {
|
|
kimage_entry_t head;
|
|
kimage_entry_t *entry;
|
|
kimage_entry_t *last_entry;
|
|
|
|
unsigned long start;
|
|
struct page *control_code_page;
|
|
struct page *swap_page;
|
|
void *vmcoreinfo_data_copy; /* locates in the crash memory */
|
|
|
|
unsigned long nr_segments;
|
|
struct kexec_segment segment[KEXEC_SEGMENT_MAX];
|
|
|
|
struct list_head control_pages;
|
|
struct list_head dest_pages;
|
|
struct list_head unusable_pages;
|
|
|
|
/* Address of next control page to allocate for crash kernels. */
|
|
unsigned long control_page;
|
|
|
|
/* Flags to indicate special processing */
|
|
unsigned int type : 1;
|
|
#define KEXEC_TYPE_DEFAULT 0
|
|
#define KEXEC_TYPE_CRASH 1
|
|
unsigned int preserve_context : 1;
|
|
/* If set, we are using file mode kexec syscall */
|
|
unsigned int file_mode:1;
|
|
|
|
#ifdef ARCH_HAS_KIMAGE_ARCH
|
|
struct kimage_arch arch;
|
|
#endif
|
|
|
|
#ifdef CONFIG_KEXEC_FILE
|
|
/* Additional fields for file based kexec syscall */
|
|
void *kernel_buf;
|
|
unsigned long kernel_buf_len;
|
|
|
|
void *initrd_buf;
|
|
unsigned long initrd_buf_len;
|
|
|
|
char *cmdline_buf;
|
|
unsigned long cmdline_buf_len;
|
|
|
|
/* File operations provided by image loader */
|
|
const struct kexec_file_ops *fops;
|
|
|
|
/* Image loader handling the kernel can store a pointer here */
|
|
void *image_loader_data;
|
|
|
|
/* Information for loading purgatory */
|
|
struct purgatory_info purgatory_info;
|
|
#endif
|
|
|
|
#ifdef CONFIG_IMA_KEXEC
|
|
/* Virtual address of IMA measurement buffer for kexec syscall */
|
|
void *ima_buffer;
|
|
|
|
phys_addr_t ima_buffer_addr;
|
|
size_t ima_buffer_size;
|
|
#endif
|
|
|
|
/* Core ELF header buffer */
|
|
void *elf_headers;
|
|
unsigned long elf_headers_sz;
|
|
unsigned long elf_load_addr;
|
|
};
|
|
|
|
/* kexec interface functions */
|
|
extern void machine_kexec(struct kimage *image);
|
|
extern int machine_kexec_prepare(struct kimage *image);
|
|
extern void machine_kexec_cleanup(struct kimage *image);
|
|
extern int kernel_kexec(void);
|
|
extern struct page *kimage_alloc_control_pages(struct kimage *image,
|
|
unsigned int order);
|
|
int machine_kexec_post_load(struct kimage *image);
|
|
|
|
extern void __crash_kexec(struct pt_regs *);
|
|
extern void crash_kexec(struct pt_regs *);
|
|
int kexec_should_crash(struct task_struct *);
|
|
int kexec_crash_loaded(void);
|
|
void crash_save_cpu(struct pt_regs *regs, int cpu);
|
|
extern int kimage_crash_copy_vmcoreinfo(struct kimage *image);
|
|
|
|
extern struct kimage *kexec_image;
|
|
extern struct kimage *kexec_crash_image;
|
|
extern int kexec_load_disabled;
|
|
|
|
#ifndef kexec_flush_icache_page
|
|
#define kexec_flush_icache_page(page)
|
|
#endif
|
|
|
|
/* List of defined/legal kexec flags */
|
|
#ifndef CONFIG_KEXEC_JUMP
|
|
#define KEXEC_FLAGS KEXEC_ON_CRASH
|
|
#else
|
|
#define KEXEC_FLAGS (KEXEC_ON_CRASH | KEXEC_PRESERVE_CONTEXT)
|
|
#endif
|
|
|
|
/* List of defined/legal kexec file flags */
|
|
#define KEXEC_FILE_FLAGS (KEXEC_FILE_UNLOAD | KEXEC_FILE_ON_CRASH | \
|
|
KEXEC_FILE_NO_INITRAMFS)
|
|
|
|
/* flag to track if kexec reboot is in progress */
|
|
extern bool kexec_in_progress;
|
|
|
|
int crash_shrink_memory(unsigned long new_size);
|
|
size_t crash_get_memory_size(void);
|
|
void crash_free_reserved_phys_range(unsigned long begin, unsigned long end);
|
|
|
|
void arch_kexec_protect_crashkres(void);
|
|
void arch_kexec_unprotect_crashkres(void);
|
|
|
|
#ifndef page_to_boot_pfn
|
|
static inline unsigned long page_to_boot_pfn(struct page *page)
|
|
{
|
|
return page_to_pfn(page);
|
|
}
|
|
#endif
|
|
|
|
#ifndef boot_pfn_to_page
|
|
static inline struct page *boot_pfn_to_page(unsigned long boot_pfn)
|
|
{
|
|
return pfn_to_page(boot_pfn);
|
|
}
|
|
#endif
|
|
|
|
#ifndef phys_to_boot_phys
|
|
static inline unsigned long phys_to_boot_phys(phys_addr_t phys)
|
|
{
|
|
return phys;
|
|
}
|
|
#endif
|
|
|
|
#ifndef boot_phys_to_phys
|
|
static inline phys_addr_t boot_phys_to_phys(unsigned long boot_phys)
|
|
{
|
|
return boot_phys;
|
|
}
|
|
#endif
|
|
|
|
static inline unsigned long virt_to_boot_phys(void *addr)
|
|
{
|
|
return phys_to_boot_phys(__pa((unsigned long)addr));
|
|
}
|
|
|
|
static inline void *boot_phys_to_virt(unsigned long entry)
|
|
{
|
|
return phys_to_virt(boot_phys_to_phys(entry));
|
|
}
|
|
|
|
#ifndef arch_kexec_post_alloc_pages
|
|
static inline int arch_kexec_post_alloc_pages(void *vaddr, unsigned int pages, gfp_t gfp) { return 0; }
|
|
#endif
|
|
|
|
#ifndef arch_kexec_pre_free_pages
|
|
static inline void arch_kexec_pre_free_pages(void *vaddr, unsigned int pages) { }
|
|
#endif
|
|
|
|
#else /* !CONFIG_KEXEC_CORE */
|
|
struct pt_regs;
|
|
struct task_struct;
|
|
static inline void __crash_kexec(struct pt_regs *regs) { }
|
|
static inline void crash_kexec(struct pt_regs *regs) { }
|
|
static inline int kexec_should_crash(struct task_struct *p) { return 0; }
|
|
static inline int kexec_crash_loaded(void) { return 0; }
|
|
#define kexec_in_progress false
|
|
#endif /* CONFIG_KEXEC_CORE */
|
|
|
|
#endif /* !defined(__ASSEBMLY__) */
|
|
|
|
#endif /* LINUX_KEXEC_H */
|