Loading arch/arm/Kconfig +4 −0 Original line number Diff line number Diff line Loading @@ -230,6 +230,9 @@ config NEED_RET_TO_USER config ARCH_MTD_XIP bool config ARCH_WANT_KMAP_ATOMIC_FLUSH bool config VECTORS_BASE hex default 0xffff0000 if MMU || CPU_HIGH_VECTOR Loading Loading @@ -652,6 +655,7 @@ config ARCH_QCOM select SPARSE_IRQ select USE_OF select PINCTRL select ARCH_WANT_KMAP_ATOMIC_FLUSH help Support for Qualcomm MSM/QSD based systems. This runs on the apps processor of the MSM/QSD and depends on a shared memory Loading arch/arm/boot/dts/qcom/sdm630.dtsi +11 −0 Original line number Diff line number Diff line Loading @@ -320,6 +320,17 @@ alignment = <0x0 0x400000>; size = <0x0 0x5c00000>; }; /* global autoconfigured region for contiguous allocations */ linux,cma { compatible = "shared-dma-pool"; alloc-ranges = <0x0 0x00000000 0x0 0xffffffff>; reusable; alignment = <0x0 0x400000>; size = <0x0 0x2000000>; linux,cma-default; }; }; bluetooth: bt_wcn3990 { Loading arch/arm/mm/highmem.c +56 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ * published by the Free Software Foundation. */ #include <linux/cpu.h> #include <linux/module.h> #include <linux/highmem.h> #include <linux/interrupt.h> Loading Loading @@ -147,3 +148,58 @@ void *kmap_atomic_pfn(unsigned long pfn) return (void *)vaddr; } #ifdef CONFIG_ARCH_WANT_KMAP_ATOMIC_FLUSH static void kmap_remove_unused_cpu(int cpu) { int start_idx, idx, type; pagefault_disable(); type = kmap_atomic_idx(); start_idx = type + 1 + KM_TYPE_NR * cpu; for (idx = start_idx; idx < KM_TYPE_NR + KM_TYPE_NR * cpu; idx++) { unsigned long vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); pte_t ptep; ptep = get_top_pte(vaddr); if (ptep) set_top_pte(vaddr, __pte(0)); } pagefault_enable(); } static void kmap_remove_unused(void *unused) { kmap_remove_unused_cpu(smp_processor_id()); } void kmap_atomic_flush_unused(void) { on_each_cpu(kmap_remove_unused, NULL, 1); } static int hotplug_kmap_atomic_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { switch (action & (~CPU_TASKS_FROZEN)) { case CPU_DYING: kmap_remove_unused_cpu((int)hcpu); break; default: break; } return NOTIFY_OK; } static struct notifier_block hotplug_kmap_atomic_notifier = { .notifier_call = hotplug_kmap_atomic_callback, }; static int __init init_kmap_atomic(void) { return register_hotcpu_notifier(&hotplug_kmap_atomic_notifier); } early_initcall(init_kmap_atomic); #endif arch/arm/mm/init.c +54 −4 Original line number Diff line number Diff line Loading @@ -625,6 +625,9 @@ struct section_perm { pmdval_t mask; pmdval_t prot; pmdval_t clear; pteval_t ptemask; pteval_t pteprot; pteval_t pteclear; }; static struct section_perm nx_perms[] = { Loading @@ -634,6 +637,8 @@ static struct section_perm nx_perms[] = { .end = (unsigned long)_stext, .mask = ~PMD_SECT_XN, .prot = PMD_SECT_XN, .ptemask = ~L_PTE_XN, .pteprot = L_PTE_XN, }, /* Make init RW (set NX). */ { Loading @@ -641,6 +646,8 @@ static struct section_perm nx_perms[] = { .end = (unsigned long)_sdata, .mask = ~PMD_SECT_XN, .prot = PMD_SECT_XN, .ptemask = ~L_PTE_XN, .pteprot = L_PTE_XN, }, #ifdef CONFIG_DEBUG_RODATA /* Make rodata NX (set RO in ro_perms below). */ Loading @@ -649,6 +656,8 @@ static struct section_perm nx_perms[] = { .end = (unsigned long)__init_begin, .mask = ~PMD_SECT_XN, .prot = PMD_SECT_XN, .ptemask = ~L_PTE_XN, .pteprot = L_PTE_XN, }, #endif }; Loading @@ -667,6 +676,8 @@ static struct section_perm ro_perms[] = { .prot = PMD_SECT_APX | PMD_SECT_AP_WRITE, .clear = PMD_SECT_AP_WRITE, #endif .ptemask = ~L_PTE_RDONLY, .pteprot = L_PTE_RDONLY, }, }; #endif Loading @@ -676,6 +687,35 @@ static struct section_perm ro_perms[] = { * copied into each mm). During startup, this is the init_mm. Is only * safe to be called with preemption disabled, as under stop_machine(). */ struct pte_data { pteval_t mask; pteval_t val; }; static int __pte_update(pte_t *ptep, pgtable_t token, unsigned long addr, void *d) { struct pte_data *data = d; pte_t pte = *ptep; pte = __pte((pte_val(*ptep) & data->mask) | data->val); set_pte_ext(ptep, pte, 0); return 0; } static inline void pte_update(unsigned long addr, pteval_t mask, pteval_t prot, struct mm_struct *mm) { struct pte_data data; data.mask = mask; data.val = prot; apply_to_page_range(mm, addr, SECTION_SIZE, __pte_update, &data); flush_tlb_kernel_range(addr, addr + SECTION_SIZE); } static inline void section_update(unsigned long addr, pmdval_t mask, pmdval_t prot, struct mm_struct *mm) { Loading Loading @@ -724,11 +764,21 @@ void set_section_perms(struct section_perm *perms, int n, bool set, for (addr = perms[i].start; addr < perms[i].end; addr += SECTION_SIZE) addr += SECTION_SIZE) { pmd_t *pmd; pmd = pmd_offset(pud_offset(pgd_offset(mm, addr), addr), addr); if (pmd_bad(*pmd)) section_update(addr, perms[i].mask, set ? perms[i].prot : perms[i].clear, mm); set ? perms[i].prot : perms[i].clear, mm); else pte_update(addr, perms[i].ptemask, set ? perms[i].pteprot : perms[i].pteclear, mm); } } } static void update_sections_early(struct section_perm perms[], int n) Loading Loading
arch/arm/Kconfig +4 −0 Original line number Diff line number Diff line Loading @@ -230,6 +230,9 @@ config NEED_RET_TO_USER config ARCH_MTD_XIP bool config ARCH_WANT_KMAP_ATOMIC_FLUSH bool config VECTORS_BASE hex default 0xffff0000 if MMU || CPU_HIGH_VECTOR Loading Loading @@ -652,6 +655,7 @@ config ARCH_QCOM select SPARSE_IRQ select USE_OF select PINCTRL select ARCH_WANT_KMAP_ATOMIC_FLUSH help Support for Qualcomm MSM/QSD based systems. This runs on the apps processor of the MSM/QSD and depends on a shared memory Loading
arch/arm/boot/dts/qcom/sdm630.dtsi +11 −0 Original line number Diff line number Diff line Loading @@ -320,6 +320,17 @@ alignment = <0x0 0x400000>; size = <0x0 0x5c00000>; }; /* global autoconfigured region for contiguous allocations */ linux,cma { compatible = "shared-dma-pool"; alloc-ranges = <0x0 0x00000000 0x0 0xffffffff>; reusable; alignment = <0x0 0x400000>; size = <0x0 0x2000000>; linux,cma-default; }; }; bluetooth: bt_wcn3990 { Loading
arch/arm/mm/highmem.c +56 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ * published by the Free Software Foundation. */ #include <linux/cpu.h> #include <linux/module.h> #include <linux/highmem.h> #include <linux/interrupt.h> Loading Loading @@ -147,3 +148,58 @@ void *kmap_atomic_pfn(unsigned long pfn) return (void *)vaddr; } #ifdef CONFIG_ARCH_WANT_KMAP_ATOMIC_FLUSH static void kmap_remove_unused_cpu(int cpu) { int start_idx, idx, type; pagefault_disable(); type = kmap_atomic_idx(); start_idx = type + 1 + KM_TYPE_NR * cpu; for (idx = start_idx; idx < KM_TYPE_NR + KM_TYPE_NR * cpu; idx++) { unsigned long vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); pte_t ptep; ptep = get_top_pte(vaddr); if (ptep) set_top_pte(vaddr, __pte(0)); } pagefault_enable(); } static void kmap_remove_unused(void *unused) { kmap_remove_unused_cpu(smp_processor_id()); } void kmap_atomic_flush_unused(void) { on_each_cpu(kmap_remove_unused, NULL, 1); } static int hotplug_kmap_atomic_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { switch (action & (~CPU_TASKS_FROZEN)) { case CPU_DYING: kmap_remove_unused_cpu((int)hcpu); break; default: break; } return NOTIFY_OK; } static struct notifier_block hotplug_kmap_atomic_notifier = { .notifier_call = hotplug_kmap_atomic_callback, }; static int __init init_kmap_atomic(void) { return register_hotcpu_notifier(&hotplug_kmap_atomic_notifier); } early_initcall(init_kmap_atomic); #endif
arch/arm/mm/init.c +54 −4 Original line number Diff line number Diff line Loading @@ -625,6 +625,9 @@ struct section_perm { pmdval_t mask; pmdval_t prot; pmdval_t clear; pteval_t ptemask; pteval_t pteprot; pteval_t pteclear; }; static struct section_perm nx_perms[] = { Loading @@ -634,6 +637,8 @@ static struct section_perm nx_perms[] = { .end = (unsigned long)_stext, .mask = ~PMD_SECT_XN, .prot = PMD_SECT_XN, .ptemask = ~L_PTE_XN, .pteprot = L_PTE_XN, }, /* Make init RW (set NX). */ { Loading @@ -641,6 +646,8 @@ static struct section_perm nx_perms[] = { .end = (unsigned long)_sdata, .mask = ~PMD_SECT_XN, .prot = PMD_SECT_XN, .ptemask = ~L_PTE_XN, .pteprot = L_PTE_XN, }, #ifdef CONFIG_DEBUG_RODATA /* Make rodata NX (set RO in ro_perms below). */ Loading @@ -649,6 +656,8 @@ static struct section_perm nx_perms[] = { .end = (unsigned long)__init_begin, .mask = ~PMD_SECT_XN, .prot = PMD_SECT_XN, .ptemask = ~L_PTE_XN, .pteprot = L_PTE_XN, }, #endif }; Loading @@ -667,6 +676,8 @@ static struct section_perm ro_perms[] = { .prot = PMD_SECT_APX | PMD_SECT_AP_WRITE, .clear = PMD_SECT_AP_WRITE, #endif .ptemask = ~L_PTE_RDONLY, .pteprot = L_PTE_RDONLY, }, }; #endif Loading @@ -676,6 +687,35 @@ static struct section_perm ro_perms[] = { * copied into each mm). During startup, this is the init_mm. Is only * safe to be called with preemption disabled, as under stop_machine(). */ struct pte_data { pteval_t mask; pteval_t val; }; static int __pte_update(pte_t *ptep, pgtable_t token, unsigned long addr, void *d) { struct pte_data *data = d; pte_t pte = *ptep; pte = __pte((pte_val(*ptep) & data->mask) | data->val); set_pte_ext(ptep, pte, 0); return 0; } static inline void pte_update(unsigned long addr, pteval_t mask, pteval_t prot, struct mm_struct *mm) { struct pte_data data; data.mask = mask; data.val = prot; apply_to_page_range(mm, addr, SECTION_SIZE, __pte_update, &data); flush_tlb_kernel_range(addr, addr + SECTION_SIZE); } static inline void section_update(unsigned long addr, pmdval_t mask, pmdval_t prot, struct mm_struct *mm) { Loading Loading @@ -724,11 +764,21 @@ void set_section_perms(struct section_perm *perms, int n, bool set, for (addr = perms[i].start; addr < perms[i].end; addr += SECTION_SIZE) addr += SECTION_SIZE) { pmd_t *pmd; pmd = pmd_offset(pud_offset(pgd_offset(mm, addr), addr), addr); if (pmd_bad(*pmd)) section_update(addr, perms[i].mask, set ? perms[i].prot : perms[i].clear, mm); set ? perms[i].prot : perms[i].clear, mm); else pte_update(addr, perms[i].ptemask, set ? perms[i].pteprot : perms[i].pteclear, mm); } } } static void update_sections_early(struct section_perm perms[], int n) Loading