OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [include/] [asm-armnommu/] [proc-armo/] [pgtable.h] - Blame information for rev 1777

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1633 jcastillo
/*
2
 * linux/include/asm-arm/proc-armo/pgtable.h
3
 *
4
 * Copyright (C) 1995, 1996 Russell King
5
 * Modified 18/19-Oct-1997 for two-level page table
6
 */
7
#ifndef __ASM_PROC_PGTABLE_H
8
#define __ASM_PROC_PGTABLE_H
9
 
10
#include <asm/arch/mmu.h>
11
 
12
#define LIBRARY_TEXT_START 0x0c000000
13
 
14
/*
15
 * Cache flushing...
16
 */
17
#define flush_cache_all()                       do { } while (0)
18
#define flush_cache_mm(mm)                      do { } while (0)
19
#define flush_cache_range(mm,start,end)         do { } while (0)
20
#define flush_cache_page(vma,vmaddr)            do { } while (0)
21
#define flush_page_to_ram(page)                 do { } while (0)
22
 
23
/*
24
 * TLB flushing:
25
 *
26
 *  - flush_tlb() flushes the current mm struct TLBs
27
 *  - flush_tlb_all() flushes all processes TLBs
28
 *  - flush_tlb_mm(mm) flushes the specified mm context TLB's
29
 *  - flush_tlb_page(vma, vmaddr) flushes one page
30
 *  - flush_tlb_range(mm, start, end) flushes a range of pages
31
 */
32
#define flush_tlb()                     do { } while (0)
33
#define flush_tlb_all()                 do { } while (0)
34
#define flush_tlb_mm(mm)                do { } while (0)
35
#define flush_tlb_range(mm, start, end) do { } while (0)
36
#define flush_tlb_page(vma, vmaddr)     do { } while (0)
37
 
38
/*
39
 * We have a mem map cache...
40
 */
41
extern __inline__ void update_mm_cache_all(void)
42
{
43
        struct task_struct *p;
44
 
45
        p = &init_task;
46
        do {
47
                processor.u.armv2._update_map(p);
48
                p = p->next_task;
49
        } while (p != &init_task);
50
 
51
        processor.u.armv2._remap_memc (current);
52
}
53
 
54
extern __inline__ void update_mm_cache_task(struct task_struct *tsk)
55
{
56
        processor.u.armv2._update_map(tsk);
57
 
58
        if (tsk == current)
59
                processor.u.armv2._remap_memc (tsk);
60
}
61
 
62
extern __inline__ void update_mm_cache_mm(struct mm_struct *mm)
63
{
64
        struct task_struct *p;
65
 
66
        p = &init_task;
67
        do {
68
                if (p->mm == mm)
69
                        processor.u.armv2._update_map(p);
70
                p = p->next_task;
71
        } while (p != &init_task);
72
 
73
        if (current->mm == mm)
74
                processor.u.armv2._remap_memc (current);
75
}
76
 
77
extern __inline__ void update_mm_cache_mm_addr(struct mm_struct *mm, unsigned long addr, pte_t pte)
78
{
79
        struct task_struct *p;
80
 
81
        p = &init_task;
82
        do {
83
                if (p->mm == mm)
84
                        processor.u.armv2._update_mmu_cache(p, addr, pte);
85
                p = p->next_task;
86
        } while (p != &init_task);
87
 
88
        if (current->mm == mm)
89
                processor.u.armv2._remap_memc (current);
90
}
91
 
92
#define __flush_entry_to_ram(entry)
93
 
94
/* Certain architectures need to do special things when pte's
95
 * within a page table are directly modified.  Thus, the following
96
 * hook is made available.
97
 */
98
/* PMD_SHIFT determines the size of the area a second-level page table can map */
99
#define PMD_SHIFT       20
100
#define PMD_SIZE        (1UL << PMD_SHIFT)
101
#define PMD_MASK        (~(PMD_SIZE-1))
102
 
103
/* PGDIR_SHIFT determines what a third-level page table entry can map */
104
#define PGDIR_SHIFT     20
105
#define PGDIR_SIZE      (1UL << PGDIR_SHIFT)
106
#define PGDIR_MASK      (~(PGDIR_SIZE-1))
107
 
108
/*
109
 * entries per page directory level: the arm3 is one-level, so
110
 * we don't really have any PMD or PTE directory physically.
111
 *
112
 * 18-Oct-1997 RMK Now two-level (32x32)
113
 */
114
#define PTRS_PER_PTE    32
115
#define PTRS_PER_PMD    1
116
#define PTRS_PER_PGD    32
117
 
118
/* Just any arbitrary offset to the start of the vmalloc VM area: the
119
 * current 8MB value just means that there will be a 8MB "hole" after the
120
 * physical memory until the kernel virtual memory starts.  That means that
121
 * any out-of-bounds memory accesses will hopefully be caught.
122
 * The vmalloc() routines leaves a hole of 4kB between each vmalloced
123
 * area for the same reason. ;)
124
 */
125
#define VMALLOC_START   0x01a00000
126
#define VMALLOC_VMADDR(x) ((unsigned long)(x))
127
 
128
#define _PAGE_PRESENT           0x01
129
#define _PAGE_READONLY          0x02
130
#define _PAGE_NOT_USER          0x04
131
#define _PAGE_OLD               0x08
132
#define _PAGE_CLEAN             0x10
133
 
134
#define _PAGE_TABLE     (_PAGE_PRESENT)
135
#define _PAGE_CHG_MASK  (PAGE_MASK | _PAGE_OLD | _PAGE_CLEAN)
136
 
137
/*                               -- present --   -- !dirty --  --- !write ---   ---- !user --- */
138
#define PAGE_NONE       __pgprot(_PAGE_PRESENT | _PAGE_CLEAN | _PAGE_READONLY | _PAGE_NOT_USER)
139
#define PAGE_SHARED     __pgprot(_PAGE_PRESENT | _PAGE_CLEAN                                  )
140
#define PAGE_COPY       __pgprot(_PAGE_PRESENT | _PAGE_CLEAN | _PAGE_READONLY                 )
141
#define PAGE_READONLY   __pgprot(_PAGE_PRESENT | _PAGE_CLEAN | _PAGE_READONLY                 )
142
#define PAGE_KERNEL     __pgprot(_PAGE_PRESENT                                | _PAGE_NOT_USER)
143
 
144
/*
145
 * The arm can't do page protection for execute, and considers that the same are read.
146
 * Also, write permissions imply read permissions. This is the closest we can get..
147
 */
148
#define __P000  PAGE_NONE
149
#define __P001  PAGE_READONLY
150
#define __P010  PAGE_COPY
151
#define __P011  PAGE_COPY
152
#define __P100  PAGE_READONLY
153
#define __P101  PAGE_READONLY
154
#define __P110  PAGE_COPY
155
#define __P111  PAGE_COPY
156
 
157
#define __S000  PAGE_NONE
158
#define __S001  PAGE_READONLY
159
#define __S010  PAGE_SHARED
160
#define __S011  PAGE_SHARED
161
#define __S100  PAGE_READONLY
162
#define __S101  PAGE_READONLY
163
#define __S110  PAGE_SHARED
164
#define __S111  PAGE_SHARED
165
 
166
#undef TEST_VERIFY_AREA
167
 
168
extern unsigned long *empty_zero_page;
169
 
170
/*
171
 * BAD_PAGETABLE is used when we need a bogus page-table, while
172
 * BAD_PAGE is used for a bogus page.
173
 *
174
 * ZERO_PAGE is a global shared page that is always zero: used
175
 * for zero-mapped memory areas etc..
176
 */
177
extern pte_t __bad_page(void);
178
extern pte_t *__bad_pagetable(void);
179
 
180
#define BAD_PAGETABLE __bad_pagetable()
181
#define BAD_PAGE __bad_page()
182
#define ZERO_PAGE ((unsigned long) empty_zero_page)
183
 
184
/* number of bits that fit into a memory pointer */
185
#define BYTES_PER_PTR                   (sizeof(unsigned long))
186
#define BITS_PER_PTR                    (8*BYTES_PER_PTR)
187
 
188
/* to align the pointer to a pointer address */
189
#define PTR_MASK                        (~(sizeof(void*)-1))
190
 
191
/* sizeof(void*)==1<<SIZEOF_PTR_LOG2 */
192
#define SIZEOF_PTR_LOG2                 2
193
 
194
/* to find an entry in a page-table */
195
#define PAGE_PTR(address) \
196
((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
197
 
198
/* to set the page-dir */
199
#define SET_PAGE_DIR(tsk,pgdir)                                         \
200
do {                                                                    \
201
        tsk->tss.memmap = (unsigned long)pgdir;                         \
202
        processor.u.armv2._update_map(tsk);                             \
203
        if ((tsk) == current)                                           \
204
                processor.u.armv2._remap_memc (current);                \
205
} while (0)
206
 
207
extern unsigned long physical_start;
208
extern unsigned long physical_end;
209
 
210
#define pte_none(pte)           (!pte_val(pte))
211
#define pte_present(pte)        (pte_val(pte) & _PAGE_PRESENT)
212
#define pte_clear(ptep)         set_pte((ptep), __pte(0))
213
 
214
#define pmd_none(pmd)           (!pmd_val(pmd))
215
#define pmd_bad(pmd)            ((pmd_val(pmd) & 0xfc000002))
216
#define pmd_present(pmd)        (pmd_val(pmd) & _PAGE_PRESENT)
217
#define pmd_clear(pmdp)         set_pmd(pmdp, __pmd(0))
218
 
219
/*
220
 * The "pgd_xxx()" functions here are trivial for a folded two-level
221
 * setup: the pgd is never bad, and a pmd always exists (as it's folded
222
 * into the pgd entry)
223
 */
224
#define pgd_none(pgd)           (0)
225
#define pgd_bad(pgd)            (0)
226
#define pgd_present(pgd)        (1)
227
#define pgd_clear(pgdp)
228
 
229
/*
230
 * The following only work if pte_present() is true.
231
 * Undefined behaviour if not..
232
 */
233
extern inline int pte_read(pte_t pte)           { return !(pte_val(pte) & _PAGE_NOT_USER);     }
234
extern inline int pte_write(pte_t pte)          { return !(pte_val(pte) & _PAGE_READONLY);     }
235
extern inline int pte_exec(pte_t pte)           { return !(pte_val(pte) & _PAGE_NOT_USER);     }
236
extern inline int pte_dirty(pte_t pte)          { return !(pte_val(pte) & _PAGE_CLEAN);        }
237
extern inline int pte_young(pte_t pte)          { return !(pte_val(pte) & _PAGE_OLD);          }
238
#define pte_cacheable(pte) 1
239
 
240
extern inline pte_t pte_nocache(pte_t pte)      { return pte; }
241
extern inline pte_t pte_wrprotect(pte_t pte)    { pte_val(pte) |= _PAGE_READONLY;  return pte; }
242
extern inline pte_t pte_rdprotect(pte_t pte)    { pte_val(pte) |= _PAGE_NOT_USER;  return pte; }
243
extern inline pte_t pte_exprotect(pte_t pte)    { pte_val(pte) |= _PAGE_NOT_USER;  return pte; }
244
extern inline pte_t pte_mkclean(pte_t pte)      { pte_val(pte) |= _PAGE_CLEAN;     return pte; }
245
extern inline pte_t pte_mkold(pte_t pte)        { pte_val(pte) |= _PAGE_OLD;       return pte; }
246
 
247
extern inline pte_t pte_mkwrite(pte_t pte)      { pte_val(pte) &= ~_PAGE_READONLY; return pte; }
248
extern inline pte_t pte_mkread(pte_t pte)       { pte_val(pte) &= ~_PAGE_NOT_USER; return pte; }
249
extern inline pte_t pte_mkexec(pte_t pte)       { pte_val(pte) &= ~_PAGE_NOT_USER; return pte; }
250
extern inline pte_t pte_mkdirty(pte_t pte)      { pte_val(pte) &= ~_PAGE_CLEAN;    return pte; }
251
extern inline pte_t pte_mkyoung(pte_t pte)      { pte_val(pte) &= ~_PAGE_OLD;      return pte; }
252
 
253
/*
254
 * Conversion functions: convert a page and protection to a page entry,
255
 * and a page entry and page directory to the page they refer to.
256
 */
257
extern __inline__ pte_t mk_pte(unsigned long page, pgprot_t pgprot)
258
{
259
        pte_t pte;
260
        pte_val(pte) = __virt_to_phys(page) | pgprot_val(pgprot);
261
        return pte;
262
}
263
 
264
extern __inline__ pte_t pte_modify(pte_t pte, pgprot_t newprot)
265
{
266
        pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot);
267
        return pte;
268
}
269
 
270
#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval))
271
 
272
extern __inline__ unsigned long pte_page(pte_t pte)
273
{
274
        return __phys_to_virt(pte_val(pte) & PAGE_MASK);
275
}
276
 
277
extern __inline__ pmd_t mk_pmd (pte_t *ptep)
278
{
279
        pmd_t pmd;
280
        pmd_val(pmd) = __virt_to_phys((unsigned long)ptep) | _PAGE_TABLE;
281
        return pmd;
282
}
283
 
284
#define set_pmd(pmdp,pmd) ((*(pmdp)) = (pmd))
285
 
286
extern __inline__ unsigned long pmd_page(pmd_t pmd)
287
{
288
        return __phys_to_virt(pmd_val(pmd) & ~_PAGE_TABLE);
289
}
290
 
291
/* to find an entry in a page-table-directory */
292
extern __inline__ pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address)
293
{
294
        return mm->pgd + (address >> PGDIR_SHIFT);
295
}
296
 
297
/* Find an entry in the second-level page table.. */
298
#define pmd_offset(dir, address) ((pmd_t *)(dir))
299
 
300
/* Find an entry in the third-level page table.. */
301
extern __inline__ pte_t * pte_offset(pmd_t *dir, unsigned long address)
302
{
303
        return (pte_t *)pmd_page(*dir) + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
304
}
305
 
306
/*
307
 * Allocate and free page tables. The xxx_kernel() versions are
308
 * used to allocate a kernel page table - this turns on ASN bits
309
 * if any.
310
 */
311
#define pte_free_kernel(pte) pte_free((pte))
312
#define pte_alloc_kernel(pmd,address) pte_alloc((pmd),(address))
313
 
314
/*
315
 * allocating and freeing a pmd is trivial: the 1-entry pmd is
316
 * inside the pgd, so has no extra memory associated with it.
317
 */
318
#define pmd_free_kernel(pmdp)
319
#define pmd_alloc_kernel(pgd,address) ((pmd_t *)(pgd))
320
 
321
extern __inline__ void pte_free(pte_t * pte)
322
{
323
        extern void kfree(void *);
324
        kfree (pte);
325
}
326
 
327
extern const char bad_pmd_string[];
328
 
329
extern __inline__ pte_t *pte_alloc(pmd_t * pmd, unsigned long address)
330
{
331
        address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
332
 
333
        if (pmd_none (*pmd)) {
334
                pte_t *page = (pte_t *) kmalloc (PTRS_PER_PTE * BYTES_PER_PTR, GFP_KERNEL);
335
                if (pmd_none (*pmd)) {
336
                        if (page) {
337
                                memzero (page, PTRS_PER_PTE * BYTES_PER_PTR);
338
                                set_pmd(pmd, mk_pmd(page));
339
                                return page + address;
340
                        }
341
                        set_pmd (pmd, mk_pmd (BAD_PAGETABLE));
342
                        return NULL;
343
                }
344
                kfree (page);
345
        }
346
        if (pmd_bad (*pmd)) {
347
                printk(bad_pmd_string, pmd_val(*pmd));
348
                set_pmd (pmd, mk_pmd (BAD_PAGETABLE));
349
                return NULL;
350
        }
351
        return (pte_t *) pmd_page(*pmd) + address;
352
}
353
 
354
/*
355
 * allocating and freeing a pmd is trivial: the 1-entry pmd is
356
 * inside the pgd, so has no extra memory associated with it.
357
 */
358
#define pmd_free(pmd)
359
#define pmd_alloc(pgd,address) ((pmd_t *)(pgd))
360
 
361
/*
362
 * Free a page directory.  Takes the virtual address.
363
 */
364
extern __inline__ void pgd_free(pgd_t * pgd)
365
{
366
        extern void kfree(void *);
367
        kfree ((void *)pgd);
368
}
369
 
370
/*
371
 * Allocate a new page directory.  Return the virtual address of it.
372
 */
373
extern __inline__ pgd_t * pgd_alloc(void)
374
{
375
        pgd_t *pgd;
376
        extern void *kmalloc(unsigned int, int);
377
 
378
        pgd = (pgd_t *) kmalloc(PTRS_PER_PGD * BYTES_PER_PTR, GFP_KERNEL);
379
        if (pgd)
380
                memzero (pgd, PTRS_PER_PGD * BYTES_PER_PTR);
381
        return pgd;
382
}
383
 
384
extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
385
 
386
#define update_mmu_cache(vma,address,pte)
387
 
388
#define SWP_TYPE(entry) (((entry) >> 1) & 0x7f)
389
#define SWP_OFFSET(entry) ((entry) >> 8)
390
#define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) <<  8))
391
 
392
#endif /* __ASM_PROC_PAGE_H */
393
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.