Commit b4ba1f0f authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux

Pull arm64 fixes from Catalin Marinas:

 - Fix size alignment in __iommu_{alloc,free}_attrs

 - Kernel memory mapping fix with CONFIG_DEBUG_RODATA for page sizes
   other than 4KB and a fix of the mark_rodata_ro permissions

 - dma_get_ops() simplification and behaviour alignment between DT and
   ACPI

 - function_graph trace fix for cpu_suspend() (CPUs returning from deep
   sleep via a different path and confusing the tracer)

 - Use of non-global mappings for UEFI run-time services to avoid a
   (potentially theoretical) TLB conflict

 - Crypto priority reduction of core AES cipher (the accelerated
   asynchronous implementation is preferred when available)

 - Reverting an old commit that removed BogoMIPS from /proc/cpuinfo on
   arm64.  Apparently, we had it for a relatively short time and libvirt
   started checking for its presence

 - Compiler warnings fixed (ptrace.h inclusion from compat.h,
   smp_load_acquire with const argument)

* tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux:
  arm64: restore bogomips information in /proc/cpuinfo
  arm64: barriers: fix smp_load_acquire to work with const arguments
  arm64: Fix R/O permissions in mark_rodata_ro
  arm64: crypto: reduce priority of core AES cipher
  arm64: use non-global mappings for UEFI runtime regions
  arm64: kernel: pause/unpause function graph tracer in cpu_suspend()
  arm64: do not include ptrace.h from compat.h
  arm64: simplify dma_get_ops
  arm64: mm: use correct mapping granularity under DEBUG_RODATA
  arm64/dma-mapping: Fix sizes in __iommu_{alloc,free}_attrs
parents a3d66b5a 92e788b7
...@@ -237,7 +237,7 @@ EXPORT_SYMBOL(ce_aes_setkey); ...@@ -237,7 +237,7 @@ EXPORT_SYMBOL(ce_aes_setkey);
static struct crypto_alg aes_alg = { static struct crypto_alg aes_alg = {
.cra_name = "aes", .cra_name = "aes",
.cra_driver_name = "aes-ce", .cra_driver_name = "aes-ce",
.cra_priority = 300, .cra_priority = 250,
.cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
.cra_blocksize = AES_BLOCK_SIZE, .cra_blocksize = AES_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct crypto_aes_ctx), .cra_ctxsize = sizeof(struct crypto_aes_ctx),
......
...@@ -64,27 +64,31 @@ do { \ ...@@ -64,27 +64,31 @@ do { \
#define smp_load_acquire(p) \ #define smp_load_acquire(p) \
({ \ ({ \
typeof(*p) ___p1; \ union { typeof(*p) __val; char __c[1]; } __u; \
compiletime_assert_atomic_type(*p); \ compiletime_assert_atomic_type(*p); \
switch (sizeof(*p)) { \ switch (sizeof(*p)) { \
case 1: \ case 1: \
asm volatile ("ldarb %w0, %1" \ asm volatile ("ldarb %w0, %1" \
: "=r" (___p1) : "Q" (*p) : "memory"); \ : "=r" (*(__u8 *)__u.__c) \
: "Q" (*p) : "memory"); \
break; \ break; \
case 2: \ case 2: \
asm volatile ("ldarh %w0, %1" \ asm volatile ("ldarh %w0, %1" \
: "=r" (___p1) : "Q" (*p) : "memory"); \ : "=r" (*(__u16 *)__u.__c) \
: "Q" (*p) : "memory"); \
break; \ break; \
case 4: \ case 4: \
asm volatile ("ldar %w0, %1" \ asm volatile ("ldar %w0, %1" \
: "=r" (___p1) : "Q" (*p) : "memory"); \ : "=r" (*(__u32 *)__u.__c) \
: "Q" (*p) : "memory"); \
break; \ break; \
case 8: \ case 8: \
asm volatile ("ldar %0, %1" \ asm volatile ("ldar %0, %1" \
: "=r" (___p1) : "Q" (*p) : "memory"); \ : "=r" (*(__u64 *)__u.__c) \
: "Q" (*p) : "memory"); \
break; \ break; \
} \ } \
___p1; \ __u.__val; \
}) })
#define read_barrier_depends() do { } while(0) #define read_barrier_depends() do { } while(0)
......
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
*/ */
#include <linux/types.h> #include <linux/types.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/ptrace.h>
#define COMPAT_USER_HZ 100 #define COMPAT_USER_HZ 100
#ifdef __AARCH64EB__ #ifdef __AARCH64EB__
...@@ -234,7 +233,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) ...@@ -234,7 +233,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr)
return (u32)(unsigned long)uptr; return (u32)(unsigned long)uptr;
} }
#define compat_user_stack_pointer() (user_stack_pointer(current_pt_regs())) #define compat_user_stack_pointer() (user_stack_pointer(task_pt_regs(current)))
static inline void __user *arch_compat_alloc_user_space(long len) static inline void __user *arch_compat_alloc_user_space(long len)
{ {
......
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <linux/acpi.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
...@@ -26,22 +25,16 @@ ...@@ -26,22 +25,16 @@
#include <asm/xen/hypervisor.h> #include <asm/xen/hypervisor.h>
#define DMA_ERROR_CODE (~(dma_addr_t)0) #define DMA_ERROR_CODE (~(dma_addr_t)0)
extern struct dma_map_ops *dma_ops;
extern struct dma_map_ops dummy_dma_ops; extern struct dma_map_ops dummy_dma_ops;
static inline struct dma_map_ops *__generic_dma_ops(struct device *dev) static inline struct dma_map_ops *__generic_dma_ops(struct device *dev)
{ {
if (unlikely(!dev)) if (dev && dev->archdata.dma_ops)
return dma_ops;
else if (dev->archdata.dma_ops)
return dev->archdata.dma_ops; return dev->archdata.dma_ops;
else if (acpi_disabled)
return dma_ops;
/* /*
* When ACPI is enabled, if arch_set_dma_ops is not called, * We expect no ISA devices, and all other DMA masters are expected to
* we will disable device DMA capability by setting it * have someone call arch_setup_dma_ops at device creation time.
* to dummy_dma_ops.
*/ */
return &dummy_dma_ops; return &dummy_dma_ops;
} }
......
...@@ -101,7 +101,7 @@ static inline void cpu_set_default_tcr_t0sz(void) ...@@ -101,7 +101,7 @@ static inline void cpu_set_default_tcr_t0sz(void)
#define destroy_context(mm) do { } while(0) #define destroy_context(mm) do { } while(0)
void check_and_switch_context(struct mm_struct *mm, unsigned int cpu); void check_and_switch_context(struct mm_struct *mm, unsigned int cpu);
#define init_new_context(tsk,mm) ({ atomic64_set(&mm->context.id, 0); 0; }) #define init_new_context(tsk,mm) ({ atomic64_set(&(mm)->context.id, 0); 0; })
/* /*
* This is called when "tsk" is about to enter lazy TLB mode. * This is called when "tsk" is about to enter lazy TLB mode.
......
...@@ -81,6 +81,7 @@ extern void __pgd_error(const char *file, int line, unsigned long val); ...@@ -81,6 +81,7 @@ extern void __pgd_error(const char *file, int line, unsigned long val);
#define PAGE_KERNEL __pgprot(_PAGE_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE) #define PAGE_KERNEL __pgprot(_PAGE_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE)
#define PAGE_KERNEL_RO __pgprot(_PAGE_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_RDONLY) #define PAGE_KERNEL_RO __pgprot(_PAGE_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_RDONLY)
#define PAGE_KERNEL_ROX __pgprot(_PAGE_DEFAULT | PTE_UXN | PTE_DIRTY | PTE_RDONLY)
#define PAGE_KERNEL_EXEC __pgprot(_PAGE_DEFAULT | PTE_UXN | PTE_DIRTY | PTE_WRITE) #define PAGE_KERNEL_EXEC __pgprot(_PAGE_DEFAULT | PTE_UXN | PTE_DIRTY | PTE_WRITE)
#define PAGE_KERNEL_EXEC_CONT __pgprot(_PAGE_DEFAULT | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_CONT) #define PAGE_KERNEL_EXEC_CONT __pgprot(_PAGE_DEFAULT | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_CONT)
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/delay.h>
/* /*
* In case the boot CPU is hotpluggable, we record its initial state and * In case the boot CPU is hotpluggable, we record its initial state and
...@@ -112,6 +113,10 @@ static int c_show(struct seq_file *m, void *v) ...@@ -112,6 +113,10 @@ static int c_show(struct seq_file *m, void *v)
*/ */
seq_printf(m, "processor\t: %d\n", i); seq_printf(m, "processor\t: %d\n", i);
seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
loops_per_jiffy / (500000UL/HZ),
loops_per_jiffy / (5000UL/HZ) % 100);
/* /*
* Dump out the common processor features in a single line. * Dump out the common processor features in a single line.
* Userspace should read the hwcaps with getauxval(AT_HWCAP) * Userspace should read the hwcaps with getauxval(AT_HWCAP)
......
...@@ -224,6 +224,8 @@ static bool __init efi_virtmap_init(void) ...@@ -224,6 +224,8 @@ static bool __init efi_virtmap_init(void)
{ {
efi_memory_desc_t *md; efi_memory_desc_t *md;
init_new_context(NULL, &efi_mm);
for_each_efi_memory_desc(&memmap, md) { for_each_efi_memory_desc(&memmap, md) {
u64 paddr, npages, size; u64 paddr, npages, size;
pgprot_t prot; pgprot_t prot;
...@@ -254,7 +256,8 @@ static bool __init efi_virtmap_init(void) ...@@ -254,7 +256,8 @@ static bool __init efi_virtmap_init(void)
else else
prot = PAGE_KERNEL; prot = PAGE_KERNEL;
create_pgd_mapping(&efi_mm, paddr, md->virt_addr, size, prot); create_pgd_mapping(&efi_mm, paddr, md->virt_addr, size,
__pgprot(pgprot_val(prot) | PTE_NG));
} }
return true; return true;
} }
...@@ -329,14 +332,7 @@ core_initcall(arm64_dmi_init); ...@@ -329,14 +332,7 @@ core_initcall(arm64_dmi_init);
static void efi_set_pgd(struct mm_struct *mm) static void efi_set_pgd(struct mm_struct *mm)
{ {
if (mm == &init_mm) switch_mm(NULL, mm, NULL);
cpu_set_reserved_ttbr0();
else
cpu_switch_mm(mm->pgd, mm);
local_flush_tlb_all();
if (icache_is_aivivt())
__local_flush_icache_all();
} }
void efi_virtmap_load(void) void efi_virtmap_load(void)
......
#include <linux/ftrace.h>
#include <linux/percpu.h> #include <linux/percpu.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
...@@ -70,6 +71,13 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) ...@@ -70,6 +71,13 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
*/ */
local_dbg_save(flags); local_dbg_save(flags);
/*
* Function graph tracer state gets incosistent when the kernel
* calls functions that never return (aka suspend finishers) hence
* disable graph tracing during their execution.
*/
pause_graph_tracing();
/* /*
* mm context saved on the stack, it will be restored when * mm context saved on the stack, it will be restored when
* the cpu comes out of reset through the identity mapped * the cpu comes out of reset through the identity mapped
...@@ -111,6 +119,8 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) ...@@ -111,6 +119,8 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
hw_breakpoint_restore(NULL); hw_breakpoint_restore(NULL);
} }
unpause_graph_tracing();
/* /*
* Restore pstate flags. OS lock and mdscr have been already * Restore pstate flags. OS lock and mdscr have been already
* restored, so from this point onwards, debugging is fully * restored, so from this point onwards, debugging is fully
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
*/ */
#include <linux/gfp.h> #include <linux/gfp.h>
#include <linux/acpi.h>
#include <linux/export.h> #include <linux/export.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/genalloc.h> #include <linux/genalloc.h>
...@@ -28,9 +29,6 @@ ...@@ -28,9 +29,6 @@
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
struct dma_map_ops *dma_ops;
EXPORT_SYMBOL(dma_ops);
static pgprot_t __get_dma_pgprot(struct dma_attrs *attrs, pgprot_t prot, static pgprot_t __get_dma_pgprot(struct dma_attrs *attrs, pgprot_t prot,
bool coherent) bool coherent)
{ {
...@@ -515,13 +513,7 @@ EXPORT_SYMBOL(dummy_dma_ops); ...@@ -515,13 +513,7 @@ EXPORT_SYMBOL(dummy_dma_ops);
static int __init arm64_dma_init(void) static int __init arm64_dma_init(void)
{ {
int ret; return atomic_pool_init();
dma_ops = &swiotlb_dma_ops;
ret = atomic_pool_init();
return ret;
} }
arch_initcall(arm64_dma_init); arch_initcall(arm64_dma_init);
...@@ -552,10 +544,14 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size, ...@@ -552,10 +544,14 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size,
{ {
bool coherent = is_device_dma_coherent(dev); bool coherent = is_device_dma_coherent(dev);
int ioprot = dma_direction_to_prot(DMA_BIDIRECTIONAL, coherent); int ioprot = dma_direction_to_prot(DMA_BIDIRECTIONAL, coherent);
size_t iosize = size;
void *addr; void *addr;
if (WARN(!dev, "cannot create IOMMU mapping for unknown device\n")) if (WARN(!dev, "cannot create IOMMU mapping for unknown device\n"))
return NULL; return NULL;
size = PAGE_ALIGN(size);
/* /*
* Some drivers rely on this, and we probably don't want the * Some drivers rely on this, and we probably don't want the
* possibility of stale kernel data being read by devices anyway. * possibility of stale kernel data being read by devices anyway.
...@@ -566,7 +562,7 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size, ...@@ -566,7 +562,7 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size,
struct page **pages; struct page **pages;
pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL, coherent); pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL, coherent);
pages = iommu_dma_alloc(dev, size, gfp, ioprot, handle, pages = iommu_dma_alloc(dev, iosize, gfp, ioprot, handle,
flush_page); flush_page);
if (!pages) if (!pages)
return NULL; return NULL;
...@@ -574,7 +570,7 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size, ...@@ -574,7 +570,7 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size,
addr = dma_common_pages_remap(pages, size, VM_USERMAP, prot, addr = dma_common_pages_remap(pages, size, VM_USERMAP, prot,
__builtin_return_address(0)); __builtin_return_address(0));
if (!addr) if (!addr)
iommu_dma_free(dev, pages, size, handle); iommu_dma_free(dev, pages, iosize, handle);
} else { } else {
struct page *page; struct page *page;
/* /*
...@@ -591,7 +587,7 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size, ...@@ -591,7 +587,7 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size,
if (!addr) if (!addr)
return NULL; return NULL;
*handle = iommu_dma_map_page(dev, page, 0, size, ioprot); *handle = iommu_dma_map_page(dev, page, 0, iosize, ioprot);
if (iommu_dma_mapping_error(dev, *handle)) { if (iommu_dma_mapping_error(dev, *handle)) {
if (coherent) if (coherent)
__free_pages(page, get_order(size)); __free_pages(page, get_order(size));
...@@ -606,6 +602,9 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size, ...@@ -606,6 +602,9 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size,
static void __iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr, static void __iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
dma_addr_t handle, struct dma_attrs *attrs) dma_addr_t handle, struct dma_attrs *attrs)
{ {
size_t iosize = size;
size = PAGE_ALIGN(size);
/* /*
* @cpu_addr will be one of 3 things depending on how it was allocated: * @cpu_addr will be one of 3 things depending on how it was allocated:
* - A remapped array of pages from iommu_dma_alloc(), for all * - A remapped array of pages from iommu_dma_alloc(), for all
...@@ -617,17 +616,17 @@ static void __iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr, ...@@ -617,17 +616,17 @@ static void __iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
* Hence how dodgy the below logic looks... * Hence how dodgy the below logic looks...
*/ */
if (__in_atomic_pool(cpu_addr, size)) { if (__in_atomic_pool(cpu_addr, size)) {
iommu_dma_unmap_page(dev, handle, size, 0, NULL); iommu_dma_unmap_page(dev, handle, iosize, 0, NULL);
__free_from_pool(cpu_addr, size); __free_from_pool(cpu_addr, size);
} else if (is_vmalloc_addr(cpu_addr)){ } else if (is_vmalloc_addr(cpu_addr)){
struct vm_struct *area = find_vm_area(cpu_addr); struct vm_struct *area = find_vm_area(cpu_addr);
if (WARN_ON(!area || !area->pages)) if (WARN_ON(!area || !area->pages))
return; return;
iommu_dma_free(dev, area->pages, size, &handle); iommu_dma_free(dev, area->pages, iosize, &handle);
dma_common_free_remap(cpu_addr, size, VM_USERMAP); dma_common_free_remap(cpu_addr, size, VM_USERMAP);
} else { } else {
iommu_dma_unmap_page(dev, handle, size, 0, NULL); iommu_dma_unmap_page(dev, handle, iosize, 0, NULL);
__free_pages(virt_to_page(cpu_addr), get_order(size)); __free_pages(virt_to_page(cpu_addr), get_order(size));
} }
} }
...@@ -984,8 +983,8 @@ static void __iommu_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, ...@@ -984,8 +983,8 @@ static void __iommu_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
struct iommu_ops *iommu, bool coherent) struct iommu_ops *iommu, bool coherent)
{ {
if (!acpi_disabled && !dev->archdata.dma_ops) if (!dev->archdata.dma_ops)
dev->archdata.dma_ops = dma_ops; dev->archdata.dma_ops = &swiotlb_dma_ops;
dev->archdata.dma_coherent = coherent; dev->archdata.dma_coherent = coherent;
__iommu_setup_dma_ops(dev, dma_base, size, iommu); __iommu_setup_dma_ops(dev, dma_base, size, iommu);
......
...@@ -362,8 +362,8 @@ static void __init __map_memblock(phys_addr_t start, phys_addr_t end) ...@@ -362,8 +362,8 @@ static void __init __map_memblock(phys_addr_t start, phys_addr_t end)
* for now. This will get more fine grained later once all memory * for now. This will get more fine grained later once all memory
* is mapped * is mapped
*/ */
unsigned long kernel_x_start = round_down(__pa(_stext), SECTION_SIZE); unsigned long kernel_x_start = round_down(__pa(_stext), SWAPPER_BLOCK_SIZE);
unsigned long kernel_x_end = round_up(__pa(__init_end), SECTION_SIZE); unsigned long kernel_x_end = round_up(__pa(__init_end), SWAPPER_BLOCK_SIZE);
if (end < kernel_x_start) { if (end < kernel_x_start) {
create_mapping(start, __phys_to_virt(start), create_mapping(start, __phys_to_virt(start),
...@@ -451,18 +451,18 @@ static void __init fixup_executable(void) ...@@ -451,18 +451,18 @@ static void __init fixup_executable(void)
{ {
#ifdef CONFIG_DEBUG_RODATA #ifdef CONFIG_DEBUG_RODATA
/* now that we are actually fully mapped, make the start/end more fine grained */ /* now that we are actually fully mapped, make the start/end more fine grained */
if (!IS_ALIGNED((unsigned long)_stext, SECTION_SIZE)) { if (!IS_ALIGNED((unsigned long)_stext, SWAPPER_BLOCK_SIZE)) {
unsigned long aligned_start = round_down(__pa(_stext), unsigned long aligned_start = round_down(__pa(_stext),
SECTION_SIZE); SWAPPER_BLOCK_SIZE);
create_mapping(aligned_start, __phys_to_virt(aligned_start), create_mapping(aligned_start, __phys_to_virt(aligned_start),
__pa(_stext) - aligned_start, __pa(_stext) - aligned_start,
PAGE_KERNEL); PAGE_KERNEL);
} }
if (!IS_ALIGNED((unsigned long)__init_end, SECTION_SIZE)) { if (!IS_ALIGNED((unsigned long)__init_end, SWAPPER_BLOCK_SIZE)) {
unsigned long aligned_end = round_up(__pa(__init_end), unsigned long aligned_end = round_up(__pa(__init_end),
SECTION_SIZE); SWAPPER_BLOCK_SIZE);
create_mapping(__pa(__init_end), (unsigned long)__init_end, create_mapping(__pa(__init_end), (unsigned long)__init_end,
aligned_end - __pa(__init_end), aligned_end - __pa(__init_end),
PAGE_KERNEL); PAGE_KERNEL);
...@@ -475,7 +475,7 @@ void mark_rodata_ro(void) ...@@ -475,7 +475,7 @@ void mark_rodata_ro(void)
{ {
create_mapping_late(__pa(_stext), (unsigned long)_stext, create_mapping_late(__pa(_stext), (unsigned long)_stext,
(unsigned long)_etext - (unsigned long)_stext, (unsigned long)_etext - (unsigned long)_stext,
PAGE_KERNEL_EXEC | PTE_RDONLY); PAGE_KERNEL_ROX);
} }
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment