aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorBernd Schmidt <bernd.schmidt@analog.com>2008-01-27 05:39:16 -0500
committerBryan Wu <bryan.wu@analog.com>2008-01-27 05:39:16 -0500
commitb97b8a998397e8c64699559099fa9febffae2b4d (patch)
tree689188b6336cf45b4391f5bc764878e342b9ac90 /include
parent2047e40d724d42928c0b5994a1568c1b738efdb7 (diff)
[Blackfin] arch: Initial checkin of the memory protection support.
Enable it with CONFIG_MPU. Signed-off-by: Bernd Schmidt <bernd.schmidt@analog.com> Signed-off-by: Bryan Wu <bryan.wu@analog.com>
Diffstat (limited to 'include')
-rw-r--r--include/asm-blackfin/cplb-mpu.h61
-rw-r--r--include/asm-blackfin/cplb.h4
-rw-r--r--include/asm-blackfin/cplbinit.h8
-rw-r--r--include/asm-blackfin/mmu.h4
-rw-r--r--include/asm-blackfin/mmu_context.h62
5 files changed, 133 insertions, 6 deletions
diff --git a/include/asm-blackfin/cplb-mpu.h b/include/asm-blackfin/cplb-mpu.h
new file mode 100644
index 000000000000..75c67b99d607
--- /dev/null
+++ b/include/asm-blackfin/cplb-mpu.h
@@ -0,0 +1,61 @@
1/*
2 * File: include/asm-blackfin/cplbinit.h
3 * Based on:
4 * Author:
5 *
6 * Created:
7 * Description:
8 *
9 * Modified:
10 * Copyright 2004-2006 Analog Devices Inc.
11 *
12 * Bugs: Enter bugs at http://blackfin.uclinux.org/
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, see the file COPYING, or write
26 * to the Free Software Foundation, Inc.,
27 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28 */
29#ifndef __ASM_BFIN_CPLB_MPU_H
30#define __ASM_BFIN_CPLB_MPU_H
31
32struct cplb_entry {
33 unsigned long data, addr;
34};
35
36struct mem_region {
37 unsigned long start, end;
38 unsigned long dcplb_data;
39 unsigned long icplb_data;
40};
41
42extern struct cplb_entry dcplb_tbl[MAX_CPLBS];
43extern struct cplb_entry icplb_tbl[MAX_CPLBS];
44extern int first_switched_icplb;
45extern int first_mask_dcplb;
46extern int first_switched_dcplb;
47
48extern int nr_dcplb_miss, nr_icplb_miss, nr_icplb_supv_miss, nr_dcplb_prot;
49extern int nr_cplb_flush;
50
51extern int page_mask_order;
52extern int page_mask_nelts;
53
54extern unsigned long *current_rwx_mask;
55
56extern void flush_switched_cplbs(void);
57extern void set_mask_dcplbs(unsigned long *);
58
59extern void __noreturn panic_cplb_error(int seqstat, struct pt_regs *);
60
61#endif /* __ASM_BFIN_CPLB_MPU_H */
diff --git a/include/asm-blackfin/cplb.h b/include/asm-blackfin/cplb.h
index 06828d77a58f..654375c2b746 100644
--- a/include/asm-blackfin/cplb.h
+++ b/include/asm-blackfin/cplb.h
@@ -65,7 +65,11 @@
65#define SIZE_1M 0x00100000 /* 1M */ 65#define SIZE_1M 0x00100000 /* 1M */
66#define SIZE_4M 0x00400000 /* 4M */ 66#define SIZE_4M 0x00400000 /* 4M */
67 67
68#ifdef CONFIG_MPU
69#define MAX_CPLBS 16
70#else
68#define MAX_CPLBS (16 * 2) 71#define MAX_CPLBS (16 * 2)
72#endif
69 73
70#define ASYNC_MEMORY_CPLB_COVERAGE ((ASYNC_BANK0_SIZE + ASYNC_BANK1_SIZE + \ 74#define ASYNC_MEMORY_CPLB_COVERAGE ((ASYNC_BANK0_SIZE + ASYNC_BANK1_SIZE + \
71 ASYNC_BANK2_SIZE + ASYNC_BANK3_SIZE) / SIZE_4M) 75 ASYNC_BANK2_SIZE + ASYNC_BANK3_SIZE) / SIZE_4M)
diff --git a/include/asm-blackfin/cplbinit.h b/include/asm-blackfin/cplbinit.h
index c4d0596e8e9f..0eb1c1b685a7 100644
--- a/include/asm-blackfin/cplbinit.h
+++ b/include/asm-blackfin/cplbinit.h
@@ -33,6 +33,12 @@
33#include <asm/blackfin.h> 33#include <asm/blackfin.h>
34#include <asm/cplb.h> 34#include <asm/cplb.h>
35 35
36#ifdef CONFIG_MPU
37
38#include <asm/cplb-mpu.h>
39
40#else
41
36#define INITIAL_T 0x1 42#define INITIAL_T 0x1
37#define SWITCH_T 0x2 43#define SWITCH_T 0x2
38#define I_CPLB 0x4 44#define I_CPLB 0x4
@@ -79,6 +85,8 @@ extern u_long ipdt_swapcount_table[];
79extern u_long dpdt_swapcount_table[]; 85extern u_long dpdt_swapcount_table[];
80#endif 86#endif
81 87
88#endif /* CONFIG_MPU */
89
82extern unsigned long reserved_mem_dcache_on; 90extern unsigned long reserved_mem_dcache_on;
83extern unsigned long reserved_mem_icache_on; 91extern unsigned long reserved_mem_icache_on;
84 92
diff --git a/include/asm-blackfin/mmu.h b/include/asm-blackfin/mmu.h
index 11d52f1167d0..757e43906ed4 100644
--- a/include/asm-blackfin/mmu.h
+++ b/include/asm-blackfin/mmu.h
@@ -24,7 +24,9 @@ typedef struct {
24 unsigned long exec_fdpic_loadmap; 24 unsigned long exec_fdpic_loadmap;
25 unsigned long interp_fdpic_loadmap; 25 unsigned long interp_fdpic_loadmap;
26#endif 26#endif
27 27#ifdef CONFIG_MPU
28 unsigned long *page_rwx_mask;
29#endif
28} mm_context_t; 30} mm_context_t;
29 31
30#endif 32#endif
diff --git a/include/asm-blackfin/mmu_context.h b/include/asm-blackfin/mmu_context.h
index c5c71a6aaf19..b5eb67596ad5 100644
--- a/include/asm-blackfin/mmu_context.h
+++ b/include/asm-blackfin/mmu_context.h
@@ -30,9 +30,12 @@
30#ifndef __BLACKFIN_MMU_CONTEXT_H__ 30#ifndef __BLACKFIN_MMU_CONTEXT_H__
31#define __BLACKFIN_MMU_CONTEXT_H__ 31#define __BLACKFIN_MMU_CONTEXT_H__
32 32
33#include <linux/gfp.h>
34#include <linux/sched.h>
33#include <asm/setup.h> 35#include <asm/setup.h>
34#include <asm/page.h> 36#include <asm/page.h>
35#include <asm/pgalloc.h> 37#include <asm/pgalloc.h>
38#include <asm/cplbinit.h>
36 39
37extern void *current_l1_stack_save; 40extern void *current_l1_stack_save;
38extern int nr_l1stack_tasks; 41extern int nr_l1stack_tasks;
@@ -50,6 +53,12 @@ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
50static inline int 53static inline int
51init_new_context(struct task_struct *tsk, struct mm_struct *mm) 54init_new_context(struct task_struct *tsk, struct mm_struct *mm)
52{ 55{
56#ifdef CONFIG_MPU
57 unsigned long p = __get_free_pages(GFP_KERNEL, page_mask_order);
58 mm->context.page_rwx_mask = (unsigned long *)p;
59 memset(mm->context.page_rwx_mask, 0,
60 page_mask_nelts * 3 * sizeof(long));
61#endif
53 return 0; 62 return 0;
54} 63}
55 64
@@ -73,6 +82,11 @@ static inline void destroy_context(struct mm_struct *mm)
73 sram_free(tmp->addr); 82 sram_free(tmp->addr);
74 kfree(tmp); 83 kfree(tmp);
75 } 84 }
85#ifdef CONFIG_MPU
86 if (current_rwx_mask == mm->context.page_rwx_mask)
87 current_rwx_mask = NULL;
88 free_pages((unsigned long)mm->context.page_rwx_mask, page_mask_order);
89#endif
76} 90}
77 91
78static inline unsigned long 92static inline unsigned long
@@ -106,9 +120,21 @@ activate_l1stack(struct mm_struct *mm, unsigned long sp_base)
106 120
107#define deactivate_mm(tsk,mm) do { } while (0) 121#define deactivate_mm(tsk,mm) do { } while (0)
108 122
109static inline void activate_mm(struct mm_struct *prev_mm, 123#define activate_mm(prev, next) switch_mm(prev, next, NULL)
110 struct mm_struct *next_mm) 124
125static inline void switch_mm(struct mm_struct *prev_mm, struct mm_struct *next_mm,
126 struct task_struct *tsk)
111{ 127{
128 if (prev_mm == next_mm)
129 return;
130#ifdef CONFIG_MPU
131 if (prev_mm->context.page_rwx_mask == current_rwx_mask) {
132 flush_switched_cplbs();
133 set_mask_dcplbs(next_mm->context.page_rwx_mask);
134 }
135#endif
136
137 /* L1 stack switching. */
112 if (!next_mm->context.l1_stack_save) 138 if (!next_mm->context.l1_stack_save)
113 return; 139 return;
114 if (next_mm->context.l1_stack_save == current_l1_stack_save) 140 if (next_mm->context.l1_stack_save == current_l1_stack_save)
@@ -120,10 +146,36 @@ static inline void activate_mm(struct mm_struct *prev_mm,
120 memcpy(l1_stack_base, current_l1_stack_save, l1_stack_len); 146 memcpy(l1_stack_base, current_l1_stack_save, l1_stack_len);
121} 147}
122 148
123static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, 149#ifdef CONFIG_MPU
124 struct task_struct *tsk) 150static inline void protect_page(struct mm_struct *mm, unsigned long addr,
151 unsigned long flags)
152{
153 unsigned long *mask = mm->context.page_rwx_mask;
154 unsigned long page = addr >> 12;
155 unsigned long idx = page >> 5;
156 unsigned long bit = 1 << (page & 31);
157
158 if (flags & VM_MAYREAD)
159 mask[idx] |= bit;
160 else
161 mask[idx] &= ~bit;
162 mask += page_mask_nelts;
163 if (flags & VM_MAYWRITE)
164 mask[idx] |= bit;
165 else
166 mask[idx] &= ~bit;
167 mask += page_mask_nelts;
168 if (flags & VM_MAYEXEC)
169 mask[idx] |= bit;
170 else
171 mask[idx] &= ~bit;
172}
173
174static inline void update_protections(struct mm_struct *mm)
125{ 175{
126 activate_mm(prev, next); 176 flush_switched_cplbs();
177 set_mask_dcplbs(mm->context.page_rwx_mask);
127} 178}
179#endif
128 180
129#endif 181#endif