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

Pull powerpc updates from Michael Ellerman:
 "Highlights include:

   - Support for the kexec_file_load() syscall, which is a prereq for
     secure and trusted boot.

   - Prevent kernel execution of userspace on P9 Radix (similar to
     SMEP/PXN).

   - Sort the exception tables at build time, to save time at boot, and
     store them as relative offsets to save space in the kernel image &
     memory.

   - Allow building the kernel with thin archives, which should allow us
     to build an allyesconfig once some other fixes land.

   - Build fixes to allow us to correctly rebuild when changing the
     kernel endian from big to little or vice versa.

   - Plumbing so that we can avoid doing a full mm TLB flush on P9
     Radix.

   - Initial stack protector support (-fstack-protector).

   - Support for dumping the radix (aka. Linux) and hash page tables via
     debugfs.

   - Fix an oops in cxl coredump generation when cxl_get_fd() is used.

   - Freescale updates from Scott: "Highlights include 8xx hugepage
     support, qbman fixes/cleanup, device tree updates, and some misc
     cleanup."

   - Many and varied fixes and minor enhancements as always.

  Thanks to:
    Alexey Kardashevskiy, Andrew Donnellan, Aneesh Kumar K.V, Anshuman
    Khandual, Anton Blanchard, Balbir Singh, Bartlomiej Zolnierkiewicz,
    Christophe Jaillet, Christophe Leroy, Denis Kirjanov, Elimar
    Riesebieter, Frederic Barrat, Gautham R. Shenoy, Geliang Tang, Geoff
    Levand, Jack Miller, Johan Hovold, Lars-Peter Clausen, Libin,
    Madhavan Srinivasan, Michael Neuling, Nathan Fontenot, Naveen N.
    Rao, Nicholas Piggin, Pan Xinhui, Peter Senna Tschudin, Rashmica
    Gupta, Rui Teng, Russell Currey, Scott Wood, Simon Guo, Suraj
    Jitindar Singh, Thiago Jung Bauermann, Tobias Klauser, Vaibhav Jain"

[ And thanks to Michael, who took time off from a new baby to get this
  pull request done.   - Linus ]

* tag 'powerpc-4.10-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: (174 commits)
  powerpc/fsl/dts: add FMan node for t1042d4rdb
  powerpc/fsl/dts: add sg_2500_aqr105_phy4 alias on t1024rdb
  powerpc/fsl/dts: add QMan and BMan nodes on t1024
  powerpc/fsl/dts: add QMan and BMan nodes on t1023
  soc/fsl/qman: test: use DEFINE_SPINLOCK()
  powerpc/fsl-lbc: use DEFINE_SPINLOCK()
  powerpc/8xx: Implement support of hugepages
  powerpc: get hugetlbpage handling more generic
  powerpc: port 64 bits pgtable_cache to 32 bits
  powerpc/boot: Request no dynamic linker for boot wrapper
  soc/fsl/bman: Use resource_size instead of computation
  soc/fsl/qe: use builtin_platform_driver
  powerpc/fsl_pmc: use builtin_platform_driver
  powerpc/83xx/suspend: use builtin_platform_driver
  powerpc/ftrace: Fix the comments for ftrace_modify_code
  powerpc/perf: macros for power9 format encoding
  powerpc/perf: power9 raw event format encoding
  powerpc/perf: update attribute_group data structure
  powerpc/perf: factor out the event format field
  powerpc/mm/iommu, vfio/spapr: Put pages on VFIO container shutdown
  ...
This commit is contained in:
Linus Torvalds
2016-12-16 09:26:42 -08:00
259 changed files with 8706 additions and 2642 deletions

View File

@@ -428,25 +428,65 @@ static int locate_mem_hole_callback(u64 start, u64 end, void *arg)
return locate_mem_hole_bottom_up(start, end, kbuf);
}
/*
* Helper function for placing a buffer in a kexec segment. This assumes
* that kexec_mutex is held.
/**
* arch_kexec_walk_mem - call func(data) on free memory regions
* @kbuf: Context info for the search. Also passed to @func.
* @func: Function to call for each memory region.
*
* Return: The memory walk will stop when func returns a non-zero value
* and that value will be returned. If all free regions are visited without
* func returning non-zero, then zero will be returned.
*/
int kexec_add_buffer(struct kimage *image, char *buffer, unsigned long bufsz,
unsigned long memsz, unsigned long buf_align,
unsigned long buf_min, unsigned long buf_max,
bool top_down, unsigned long *load_addr)
int __weak arch_kexec_walk_mem(struct kexec_buf *kbuf,
int (*func)(u64, u64, void *))
{
if (kbuf->image->type == KEXEC_TYPE_CRASH)
return walk_iomem_res_desc(crashk_res.desc,
IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY,
crashk_res.start, crashk_res.end,
kbuf, func);
else
return walk_system_ram_res(0, ULONG_MAX, kbuf, func);
}
/**
* kexec_locate_mem_hole - find free memory for the purgatory or the next kernel
* @kbuf: Parameters for the memory search.
*
* On success, kbuf->mem will have the start address of the memory region found.
*
* Return: 0 on success, negative errno on error.
*/
int kexec_locate_mem_hole(struct kexec_buf *kbuf)
{
int ret;
ret = arch_kexec_walk_mem(kbuf, locate_mem_hole_callback);
return ret == 1 ? 0 : -EADDRNOTAVAIL;
}
/**
* kexec_add_buffer - place a buffer in a kexec segment
* @kbuf: Buffer contents and memory parameters.
*
* This function assumes that kexec_mutex is held.
* On successful return, @kbuf->mem will have the physical address of
* the buffer in memory.
*
* Return: 0 on success, negative errno on error.
*/
int kexec_add_buffer(struct kexec_buf *kbuf)
{
struct kexec_segment *ksegment;
struct kexec_buf buf, *kbuf;
int ret;
/* Currently adding segment this way is allowed only in file mode */
if (!image->file_mode)
if (!kbuf->image->file_mode)
return -EINVAL;
if (image->nr_segments >= KEXEC_SEGMENT_MAX)
if (kbuf->image->nr_segments >= KEXEC_SEGMENT_MAX)
return -EINVAL;
/*
@@ -456,45 +496,27 @@ int kexec_add_buffer(struct kimage *image, char *buffer, unsigned long bufsz,
* logic goes through list of segments to make sure there are
* no destination overlaps.
*/
if (!list_empty(&image->control_pages)) {
if (!list_empty(&kbuf->image->control_pages)) {
WARN_ON(1);
return -EINVAL;
}
memset(&buf, 0, sizeof(struct kexec_buf));
kbuf = &buf;
kbuf->image = image;
kbuf->buffer = buffer;
kbuf->bufsz = bufsz;
kbuf->memsz = ALIGN(memsz, PAGE_SIZE);
kbuf->buf_align = max(buf_align, PAGE_SIZE);
kbuf->buf_min = buf_min;
kbuf->buf_max = buf_max;
kbuf->top_down = top_down;
/* Ensure minimum alignment needed for segments. */
kbuf->memsz = ALIGN(kbuf->memsz, PAGE_SIZE);
kbuf->buf_align = max(kbuf->buf_align, PAGE_SIZE);
/* Walk the RAM ranges and allocate a suitable range for the buffer */
if (image->type == KEXEC_TYPE_CRASH)
ret = walk_iomem_res_desc(crashk_res.desc,
IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY,
crashk_res.start, crashk_res.end, kbuf,
locate_mem_hole_callback);
else
ret = walk_system_ram_res(0, -1, kbuf,
locate_mem_hole_callback);
if (ret != 1) {
/* A suitable memory range could not be found for buffer */
return -EADDRNOTAVAIL;
}
ret = kexec_locate_mem_hole(kbuf);
if (ret)
return ret;
/* Found a suitable memory range */
ksegment = &image->segment[image->nr_segments];
ksegment = &kbuf->image->segment[kbuf->image->nr_segments];
ksegment->kbuf = kbuf->buffer;
ksegment->bufsz = kbuf->bufsz;
ksegment->mem = kbuf->mem;
ksegment->memsz = kbuf->memsz;
image->nr_segments++;
*load_addr = ksegment->mem;
kbuf->image->nr_segments++;
return 0;
}
@@ -616,13 +638,15 @@ static int __kexec_load_purgatory(struct kimage *image, unsigned long min,
unsigned long max, int top_down)
{
struct purgatory_info *pi = &image->purgatory_info;
unsigned long align, buf_align, bss_align, buf_sz, bss_sz, bss_pad;
unsigned long memsz, entry, load_addr, curr_load_addr, bss_addr, offset;
unsigned long align, bss_align, bss_sz, bss_pad;
unsigned long entry, load_addr, curr_load_addr, bss_addr, offset;
unsigned char *buf_addr, *src;
int i, ret = 0, entry_sidx = -1;
const Elf_Shdr *sechdrs_c;
Elf_Shdr *sechdrs = NULL;
void *purgatory_buf = NULL;
struct kexec_buf kbuf = { .image = image, .bufsz = 0, .buf_align = 1,
.buf_min = min, .buf_max = max,
.top_down = top_down };
/*
* sechdrs_c points to section headers in purgatory and are read
@@ -688,9 +712,7 @@ static int __kexec_load_purgatory(struct kimage *image, unsigned long min,
}
/* Determine how much memory is needed to load relocatable object. */
buf_align = 1;
bss_align = 1;
buf_sz = 0;
bss_sz = 0;
for (i = 0; i < pi->ehdr->e_shnum; i++) {
@@ -699,10 +721,10 @@ static int __kexec_load_purgatory(struct kimage *image, unsigned long min,
align = sechdrs[i].sh_addralign;
if (sechdrs[i].sh_type != SHT_NOBITS) {
if (buf_align < align)
buf_align = align;
buf_sz = ALIGN(buf_sz, align);
buf_sz += sechdrs[i].sh_size;
if (kbuf.buf_align < align)
kbuf.buf_align = align;
kbuf.bufsz = ALIGN(kbuf.bufsz, align);
kbuf.bufsz += sechdrs[i].sh_size;
} else {
/* bss section */
if (bss_align < align)
@@ -714,32 +736,31 @@ static int __kexec_load_purgatory(struct kimage *image, unsigned long min,
/* Determine the bss padding required to align bss properly */
bss_pad = 0;
if (buf_sz & (bss_align - 1))
bss_pad = bss_align - (buf_sz & (bss_align - 1));
if (kbuf.bufsz & (bss_align - 1))
bss_pad = bss_align - (kbuf.bufsz & (bss_align - 1));
memsz = buf_sz + bss_pad + bss_sz;
kbuf.memsz = kbuf.bufsz + bss_pad + bss_sz;
/* Allocate buffer for purgatory */
purgatory_buf = vzalloc(buf_sz);
if (!purgatory_buf) {
kbuf.buffer = vzalloc(kbuf.bufsz);
if (!kbuf.buffer) {
ret = -ENOMEM;
goto out;
}
if (buf_align < bss_align)
buf_align = bss_align;
if (kbuf.buf_align < bss_align)
kbuf.buf_align = bss_align;
/* Add buffer to segment list */
ret = kexec_add_buffer(image, purgatory_buf, buf_sz, memsz,
buf_align, min, max, top_down,
&pi->purgatory_load_addr);
ret = kexec_add_buffer(&kbuf);
if (ret)
goto out;
pi->purgatory_load_addr = kbuf.mem;
/* Load SHF_ALLOC sections */
buf_addr = purgatory_buf;
buf_addr = kbuf.buffer;
load_addr = curr_load_addr = pi->purgatory_load_addr;
bss_addr = load_addr + buf_sz + bss_pad;
bss_addr = load_addr + kbuf.bufsz + bss_pad;
for (i = 0; i < pi->ehdr->e_shnum; i++) {
if (!(sechdrs[i].sh_flags & SHF_ALLOC))
@@ -785,11 +806,11 @@ static int __kexec_load_purgatory(struct kimage *image, unsigned long min,
* Used later to identify which section is purgatory and skip it
* from checksumming.
*/
pi->purgatory_buf = purgatory_buf;
pi->purgatory_buf = kbuf.buffer;
return ret;
out:
vfree(sechdrs);
vfree(purgatory_buf);
vfree(kbuf.buffer);
return ret;
}

View File

@@ -20,22 +20,6 @@ struct kexec_sha_region {
unsigned long len;
};
/*
* Keeps track of buffer parameters as provided by caller for requesting
* memory placement of buffer.
*/
struct kexec_buf {
struct kimage *image;
char *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; /* allocate from top of memory hole */
};
void kimage_file_post_load_cleanup(struct kimage *image);
#else /* CONFIG_KEXEC_FILE */
static inline void kimage_file_post_load_cleanup(struct kimage *image) { }