Merge "arm: mm: program ptes for access restriction"
This commit is contained in:
commit
8f0a76b8f6
4 changed files with 125 additions and 4 deletions
|
@ -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
|
||||
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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>
|
||||
|
@ -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
|
||||
|
|
|
@ -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[] = {
|
||||
|
@ -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). */
|
||||
{
|
||||
|
@ -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). */
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
section_update(addr, perms[i].mask,
|
||||
set ? perms[i].prot : perms[i].clear, mm);
|
||||
}
|
||||
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);
|
||||
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…
Add table
Reference in a new issue