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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1633 jcastillo
/*
2
 * linux/include/asm-arm/proc-armv/pgtable.h
3
 *
4
 * Copyright (C) 1995, 1996, 1997 Russell King
5
 *
6
 * 12-01-1997   RMK     Altered flushing routines to use function pointers
7
 *                      now possible to combine ARM6, ARM7 and StrongARM versions.
8
 */
9
#ifndef __ASM_PROC_PGTABLE_H
10
#define __ASM_PROC_PGTABLE_H
11
 
12
#include <asm/arch/mmu.h>
13
 
14
#define LIBRARY_TEXT_START 0x0c000000
15
 
16
/*
17
 * Cache flushing...
18
 */
19
#define flush_cache_all()                                               \
20
        processor.u.armv3v4._flush_cache_all()
21
 
22
#define flush_cache_mm(_mm)                                             \
23
        do {                                                            \
24
                if ((_mm) == current->mm)                               \
25
                        processor.u.armv3v4._flush_cache_all();         \
26
        } while (0)
27
 
28
#define flush_cache_range(_mm,_start,_end)                              \
29
        do {                                                            \
30
                if ((_mm) == current->mm)                               \
31
                        processor.u.armv3v4._flush_cache_area           \
32
                                ((_start), (_end), 1);                  \
33
        } while (0)
34
 
35
#define flush_cache_page(_vma,_vmaddr)                                  \
36
        do {                                                            \
37
                if ((_vma)->vm_mm == current->mm)                       \
38
                        processor.u.armv3v4._flush_cache_area           \
39
                                ((_vmaddr), (_vmaddr) + PAGE_SIZE,      \
40
                                 ((_vma)->vm_flags & VM_EXEC) ? 1 : 0);  \
41
        } while (0)
42
 
43
/*
44
 * We don't have a mem map cache...
45
 */
46
#define update_mm_cache_all()                   do { } while (0)
47
#define update_mm_cache_task(tsk)               do { } while (0)
48
#define update_mm_cache_mm(mm)                  do { } while (0)
49
#define update_mm_cache_mm_addr(mm,addr,pte)    do { } while (0)
50
 
51
/*
52
 * This flushes back any buffered write data.  We have to clean and flush the entries
53
 * in the cache for this page.  Is it necessary to invalidate the I-cache?
54
 */
55
#define flush_page_to_ram(_page)                                        \
56
        processor.u.armv3v4._flush_ram_page ((_page) & PAGE_MASK);
57
 
58
/*
59
 * Make the page uncacheable (must flush page beforehand).
60
 */
61
#define uncache_page(_page)                                             \
62
        processor.u.armv3v4._flush_ram_page ((_page) & PAGE_MASK);
63
 
64
/*
65
 * TLB flushing:
66
 *
67
 *  - flush_tlb() flushes the current mm struct TLBs
68
 *  - flush_tlb_all() flushes all processes TLBs
69
 *  - flush_tlb_mm(mm) flushes the specified mm context TLB's
70
 *  - flush_tlb_page(vma, vmaddr) flushes one page
71
 *  - flush_tlb_range(mm, start, end) flushes a range of pages
72
 *
73
 * GCC uses conditional instructions, and expects the assembler code to do so as well.
74
 *
75
 * We drain the write buffer in here to ensure that the page tables in ram
76
 * are really up to date.  It is more efficient to do this here...
77
 */
78
#define flush_tlb() flush_tlb_all()
79
 
80
#define flush_tlb_all()                                                         \
81
        processor.u.armv3v4._flush_tlb_all()
82
 
83
#define flush_tlb_mm(_mm)                                                       \
84
        do {                                                                    \
85
                if ((_mm) == current->mm)                                       \
86
                        processor.u.armv3v4._flush_tlb_all();                   \
87
        } while (0)
88
 
89
#define flush_tlb_range(_mm,_start,_end)                                        \
90
        do {                                                                    \
91
                if ((_mm) == current->mm)                                       \
92
                        processor.u.armv3v4._flush_tlb_area                     \
93
                                ((_start), (_end), 1);                          \
94
        } while (0)
95
 
96
#define flush_tlb_page(_vma,_vmaddr)                                            \
97
        do {                                                                    \
98
                if ((_vma)->vm_mm == current->mm)                               \
99
                        processor.u.armv3v4._flush_tlb_area                     \
100
                                ((_vmaddr), (_vmaddr) + PAGE_SIZE,              \
101
                                 ((_vma)->vm_flags & VM_EXEC) ? 1 : 0);          \
102
        } while (0)
103
 
104
/*
105
 * Since the page tables are in cached memory, we need to flush the dirty
106
 * data cached entries back before we flush the tlb...  This is also useful
107
 * to flush out the SWI instruction for signal handlers...
108
 */
109
#define __flush_entry_to_ram(entry)                                             \
110
        processor.u.armv3v4._flush_cache_entry((unsigned long)(entry))
111
 
112
#define __flush_pte_to_ram(entry)                                               \
113
        processor.u.armv3v4._flush_cache_pte((unsigned long)(entry))
114
 
115
/* PMD_SHIFT determines the size of the area a second-level page table can map */
116
#define PMD_SHIFT       20
117
#define PMD_SIZE        (1UL << PMD_SHIFT)
118
#define PMD_MASK        (~(PMD_SIZE-1))
119
 
120
/* PGDIR_SHIFT determines what a third-level page table entry can map */
121
#define PGDIR_SHIFT     20
122
#define PGDIR_SIZE      (1UL << PGDIR_SHIFT)
123
#define PGDIR_MASK      (~(PGDIR_SIZE-1))
124
 
125
/*
126
 * entries per page directory level: the sa110 is two-level, so
127
 * we don't really have any PMD directory physically.
128
 */
129
#define PTRS_PER_PTE    256
130
#define PTRS_PER_PMD    1
131
#define PTRS_PER_PGD    4096
132
 
133
/* Just any arbitrary offset to the start of the vmalloc VM area: the
134
 * current 8MB value just means that there will be a 8MB "hole" after the
135
 * physical memory until the kernel virtual memory starts.  That means that
136
 * any out-of-bounds memory accesses will hopefully be caught.
137
 * The vmalloc() routines leaves a hole of 4kB between each vmalloced
138
 * area for the same reason. ;)
139
 */
140
#define VMALLOC_OFFSET    (8*1024*1024)
141
#define VMALLOC_START     ((high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
142
#define VMALLOC_VMADDR(x) ((unsigned long)(x))
143
 
144
/* PMD types (actually level 1 descriptor) */
145
#define PMD_TYPE_MASK           0x0003
146
#define PMD_TYPE_FAULT          0x0000
147
#define PMD_TYPE_TABLE          0x0001
148
#define PMD_TYPE_SECT           0x0002
149
#define PMD_UPDATABLE           0x0010
150
#define PMD_SECT_CACHEABLE      0x0008
151
#define PMD_SECT_BUFFERABLE     0x0004
152
#define PMD_SECT_AP_WRITE       0x0400
153
#define PMD_SECT_AP_READ        0x0800
154
#define PMD_DOMAIN(x)           ((x) << 5)
155
 
156
/* PTE types (actually level 2 descriptor) */
157
#define PTE_TYPE_MASK   0x0003
158
#define PTE_TYPE_FAULT  0x0000
159
#define PTE_TYPE_LARGE  0x0001
160
#define PTE_TYPE_SMALL  0x0002
161
#define PTE_AP_READ     0x0aa0
162
#define PTE_AP_WRITE    0x0550
163
#define PTE_CACHEABLE   0x0008
164
#define PTE_BUFFERABLE  0x0004
165
 
166
/* Domains */
167
#define DOMAIN_KERNEL   0
168
 
169
#define _PAGE_CHG_MASK  (0xfffff00c | PTE_TYPE_MASK)
170
 
171
/*
172
 * We define the bits in the page tables as follows:
173
 *  PTE_BUFFERABLE      page is dirty
174
 *  PTE_AP_WRITE        page is writable
175
 *  PTE_AP_READ         page is a young (unsetting this causes faults for any access)
176
 *
177
 * Any page that is mapped in is assumed to be readable...
178
 */
179
#define PAGE_NONE       __pgprot(PTE_TYPE_SMALL)
180
#define PAGE_SHARED     __pgprot(PTE_TYPE_SMALL | PTE_CACHEABLE | PTE_AP_READ | PTE_AP_WRITE)
181
#define PAGE_COPY       __pgprot(PTE_TYPE_SMALL | PTE_CACHEABLE | PTE_AP_READ)
182
#define PAGE_READONLY   __pgprot(PTE_TYPE_SMALL | PTE_CACHEABLE | PTE_AP_READ)
183
#define PAGE_KERNEL     __pgprot(PTE_TYPE_SMALL | PTE_CACHEABLE | PTE_BUFFERABLE | PTE_AP_WRITE)
184
 
185
#define _PAGE_TABLE     (PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_KERNEL))
186
 
187
/*
188
 * The arm can't do page protection for execute, and considers that the same are read.
189
 * Also, write permissions imply read permissions. This is the closest we can get..
190
 */
191
#define __P000  PAGE_NONE
192
#define __P001  PAGE_READONLY
193
#define __P010  PAGE_COPY
194
#define __P011  PAGE_COPY
195
#define __P100  PAGE_READONLY
196
#define __P101  PAGE_READONLY
197
#define __P110  PAGE_COPY
198
#define __P111  PAGE_COPY
199
 
200
#define __S000  PAGE_NONE
201
#define __S001  PAGE_READONLY
202
#define __S010  PAGE_SHARED
203
#define __S011  PAGE_SHARED
204
#define __S100  PAGE_READONLY
205
#define __S101  PAGE_READONLY
206
#define __S110  PAGE_SHARED
207
#define __S111  PAGE_SHARED
208
 
209
#undef TEST_VERIFY_AREA
210
 
211
/*
212
 * BAD_PAGETABLE is used when we need a bogus page-table, while
213
 * BAD_PAGE is used for a bogus page.
214
 *
215
 * ZERO_PAGE is a global shared page that is always zero: used
216
 * for zero-mapped memory areas etc..
217
 */
218
extern pte_t __bad_page(void);
219
extern pte_t * __bad_pagetable(void);
220
extern unsigned long *empty_zero_page;
221
 
222
#define BAD_PAGETABLE __bad_pagetable()
223
#define BAD_PAGE __bad_page()
224
#define ZERO_PAGE ((unsigned long) empty_zero_page)
225
 
226
/* number of bits that fit into a memory pointer */
227
#define BYTES_PER_PTR                   (sizeof(unsigned long))
228
#define BITS_PER_PTR                    (8*BYTES_PER_PTR)
229
 
230
/* to align the pointer to a pointer address */
231
#define PTR_MASK                        (~(sizeof(void*)-1))
232
 
233
/* sizeof(void*)==1<<SIZEOF_PTR_LOG2 */
234
#define SIZEOF_PTR_LOG2                 2
235
 
236
/* to find an entry in a page-table */
237
#define PAGE_PTR(address) \
238
((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
239
 
240
/* to set the page-dir */
241
#define SET_PAGE_DIR(tsk,pgdir)                                 \
242
do {                                                            \
243
        tsk->tss.memmap = __virt_to_phys((unsigned long)pgdir); \
244
        if ((tsk) == current)                                   \
245
                __asm__ __volatile__(                           \
246
                "mcr%?  p15, 0, %0, c2, c0, 0\n"                \
247
                : : "r" (tsk->tss.memmap));                     \
248
} while (0)
249
 
250
extern __inline__ int pte_none(pte_t pte)
251
{
252
        return !pte_val(pte);
253
}
254
 
255
#define pte_clear(ptep) set_pte(ptep, __pte(0))
256
 
257
extern __inline__ int pte_present(pte_t pte)
258
{
259
        switch (pte_val(pte) & PTE_TYPE_MASK) {
260
        case PTE_TYPE_LARGE:
261
        case PTE_TYPE_SMALL:
262
                return 1;
263
        default:
264
                return 0;
265
        }
266
}
267
 
268
extern __inline__ int pmd_none(pmd_t pmd)
269
{
270
        return !pmd_val(pmd);
271
}
272
 
273
#define pmd_clear(pmdp) set_pmd(pmdp, __pmd(0))
274
 
275
extern __inline__ int pmd_bad(pmd_t pmd)
276
{
277
        switch (pmd_val(pmd) & PMD_TYPE_MASK) {
278
        case PMD_TYPE_FAULT:
279
        case PMD_TYPE_TABLE:
280
                return 0;
281
        default:
282
                return 1;
283
        }
284
}
285
 
286
extern __inline__ int pmd_present(pmd_t pmd)
287
{
288
        switch (pmd_val(pmd) & PMD_TYPE_MASK) {
289
        case PMD_TYPE_TABLE:
290
                return 1;
291
        default:
292
                return 0;
293
        }
294
}
295
 
296
/*
297
 * The "pgd_xxx()" functions here are trivial for a folded two-level
298
 * setup: the pgd is never bad, and a pmd always exists (as it's folded
299
 * into the pgd entry)
300
 */
301
#define pgd_none(pgd)           (0)
302
#define pgd_bad(pgd)            (0)
303
#define pgd_present(pgd)        (1)
304
#define pgd_clear(pgdp)
305
 
306
/*
307
 * The following only work if pte_present() is true.
308
 * Undefined behaviour if not..
309
 */
310
#define pte_read(pte)           (1)
311
#define pte_exec(pte)           (1)
312
 
313
extern __inline__ int pte_write(pte_t pte)
314
{
315
        return pte_val(pte) & PTE_AP_WRITE;
316
}
317
 
318
extern __inline__ int pte_cacheable(pte_t pte)
319
{
320
        return pte_val(pte) & PTE_CACHEABLE;
321
}
322
 
323
extern __inline__ int pte_dirty(pte_t pte)
324
{
325
        return pte_val(pte) & PTE_BUFFERABLE;
326
}
327
 
328
extern __inline__ int pte_young(pte_t pte)
329
{
330
        return pte_val(pte) & PTE_AP_READ;
331
}
332
 
333
extern __inline__ pte_t pte_wrprotect(pte_t pte)
334
{
335
        pte_val(pte) &= ~PTE_AP_WRITE;
336
        return pte;
337
}
338
 
339
extern __inline__ pte_t pte_nocache(pte_t pte)
340
{
341
        pte_val(pte) &= ~PTE_CACHEABLE;
342
        return pte;
343
}
344
 
345
extern __inline__ pte_t pte_mkclean(pte_t pte)
346
{
347
        pte_val(pte) &= ~PTE_BUFFERABLE;
348
        return pte;
349
}
350
 
351
extern __inline__ pte_t pte_mkold(pte_t pte)
352
{
353
        pte_val(pte) &= ~PTE_AP_READ;
354
        return pte;
355
}
356
 
357
extern __inline__ pte_t pte_mkwrite(pte_t pte)
358
{
359
        pte_val(pte) |= PTE_AP_WRITE;
360
        return pte;
361
}
362
 
363
extern __inline__ pte_t pte_mkdirty(pte_t pte)
364
{
365
        pte_val(pte) |= PTE_BUFFERABLE;
366
        return pte;
367
}
368
 
369
extern __inline__ pte_t pte_mkyoung(pte_t pte)
370
{
371
        pte_val(pte) |= PTE_AP_READ;
372
        return pte;
373
}
374
 
375
/*
376
 * The following are unable to be implemented on this MMU
377
 */
378
#if 0
379
extern __inline__ pte_t pte_rdprotect(pte_t pte)
380
{
381
        pte_val(pte) &= ~(PTE_CACHEABLE|PTE_AP_READ);
382
        return pte;
383
}
384
 
385
extern __inline__ pte_t pte_exprotect(pte_t pte)
386
{
387
        pte_val(pte) &= ~(PTE_CACHEABLE|PTE_AP_READ);
388
        return pte;
389
}
390
 
391
extern __inline__ pte_t pte_mkread(pte_t pte)
392
{
393
        pte_val(pte) |= PTE_CACHEABLE;
394
        return pte;
395
}
396
 
397
extern __inline__ pte_t pte_mkexec(pte_t pte)
398
{
399
        pte_val(pte) |= PTE_CACHEABLE;
400
        return pte;
401
}
402
#endif
403
 
404
/*
405
 * Conversion functions: convert a page and protection to a page entry,
406
 * and a page entry and page directory to the page they refer to.
407
 */
408
extern __inline__ pte_t mk_pte(unsigned long page, pgprot_t pgprot)
409
{
410
        pte_t pte;
411
        pte_val(pte) = __virt_to_phys(page) | pgprot_val(pgprot);
412
        return pte;
413
}
414
 
415
extern __inline__ pte_t pte_modify(pte_t pte, pgprot_t newprot)
416
{
417
        pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot);
418
        return pte;
419
}
420
 
421
extern __inline__ void set_pte(pte_t *pteptr, pte_t pteval)
422
{
423
        *pteptr = pteval;
424
        __flush_pte_to_ram(pteptr);
425
}
426
 
427
extern __inline__ unsigned long pte_page(pte_t pte)
428
{
429
        return __phys_to_virt(pte_val(pte) & PAGE_MASK);
430
}
431
 
432
extern __inline__ pmd_t mk_pmd(pte_t *ptep)
433
{
434
        pmd_t pmd;
435
        pmd_val(pmd) = __virt_to_phys((unsigned long)ptep) | _PAGE_TABLE;
436
        return pmd;
437
}
438
 
439
#if 1
440
#define set_pmd(pmdp,pmd) processor.u.armv3v4._set_pmd(pmdp,pmd)
441
#else
442
extern __inline__ void set_pmd(pmd_t *pmdp, pmd_t pmd)
443
{
444
        *pmdp = pmd;
445
        __flush_pte_to_ram(pmdp);
446
}
447
#endif
448
 
449
extern __inline__ unsigned long pmd_page(pmd_t pmd)
450
{
451
        return __phys_to_virt(pmd_val(pmd) & 0xfffffc00);
452
}
453
 
454
/* to find an entry in a page-table-directory */
455
extern __inline__ pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address)
456
{
457
        return mm->pgd + (address >> PGDIR_SHIFT);
458
}
459
 
460
/* Find an entry in the second-level page table.. */
461
#define pmd_offset(dir, address) ((pmd_t *)(dir))
462
 
463
/* Find an entry in the third-level page table.. */
464
extern __inline__ pte_t * pte_offset(pmd_t * dir, unsigned long address)
465
{
466
        return (pte_t *) pmd_page(*dir) + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
467
}
468
 
469
extern unsigned long get_small_page(int priority);
470
extern void free_small_page(unsigned long page);
471
 
472
/*
473
 * Allocate and free page tables. The xxx_kernel() versions are
474
 * used to allocate a kernel page table - this turns on ASN bits
475
 * if any.
476
 */
477
extern __inline__ void pte_free_kernel(pte_t * pte)
478
{
479
        free_small_page((unsigned long) pte);
480
}
481
 
482
extern const char bad_pmd_string[];
483
 
484
extern __inline__ pte_t * pte_alloc_kernel(pmd_t *pmd, unsigned long address)
485
{
486
        address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
487
        if (pmd_none(*pmd)) {
488
                pte_t *page = (pte_t *) get_small_page(GFP_KERNEL);
489
                if (pmd_none(*pmd)) {
490
                        if (page) {
491
                                memzero (page, PTRS_PER_PTE * BYTES_PER_PTR);
492
                                set_pmd(pmd, mk_pmd(page));
493
                                return page + address;
494
                        }
495
                        set_pmd(pmd, mk_pmd(BAD_PAGETABLE));
496
                        return NULL;
497
                }
498
                free_small_page((unsigned long) page);
499
        }
500
        if (pmd_bad(*pmd)) {
501
                printk(bad_pmd_string, pmd_val(*pmd));
502
                set_pmd(pmd, mk_pmd(BAD_PAGETABLE));
503
                return NULL;
504
        }
505
        return (pte_t *) pmd_page(*pmd) + address;
506
}
507
 
508
/*
509
 * allocating and freeing a pmd is trivial: the 1-entry pmd is
510
 * inside the pgd, so has no extra memory associated with it.
511
 */
512
#define pmd_free_kernel(pmdp) pmd_val(*(pmdp)) = 0;
513
#define pmd_alloc_kernel(pgdp, address) ((pmd_t *)(pgdp))
514
 
515
extern __inline__ void pte_free(pte_t * pte)
516
{
517
        free_small_page((unsigned long) pte);
518
}
519
 
520
extern __inline__ pte_t * pte_alloc(pmd_t * pmd, unsigned long address)
521
{
522
        address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
523
 
524
        if (pmd_none(*pmd)) {
525
                pte_t *page = (pte_t *) get_small_page(GFP_KERNEL);
526
                if (pmd_none(*pmd)) {
527
                        if (page) {
528
                                memzero (page, PTRS_PER_PTE * BYTES_PER_PTR);
529
                                set_pmd(pmd, mk_pmd(page));
530
                                return page + address;
531
                        }
532
                        set_pmd(pmd, mk_pmd(BAD_PAGETABLE));
533
                        return NULL;
534
                }
535
                free_small_page ((unsigned long) page);
536
        }
537
        if (pmd_bad(*pmd)) {
538
                printk(bad_pmd_string, pmd_val(*pmd));
539
                set_pmd(pmd, mk_pmd(BAD_PAGETABLE));
540
                return NULL;
541
        }
542
        return (pte_t *) pmd_page(*pmd) + address;
543
}
544
 
545
/*
546
 * allocating and freeing a pmd is trivial: the 1-entry pmd is
547
 * inside the pgd, so has no extra memory associated with it.
548
 */
549
#define pmd_free(pmdp) pmd_val(*(pmdp)) = 0;
550
#define pmd_alloc(pgdp, address) ((pmd_t *)(pgdp))
551
 
552
/*
553
 * Free a page directory.  Takes the virtual address.
554
 */
555
extern __inline__ void pgd_free(pgd_t * pgd)
556
{
557
        free_pages((unsigned long) pgd, 2);
558
}
559
 
560
/*
561
 * Allocate a new page directory.  Return the virtual address of it.
562
 */
563
extern __inline__ pgd_t * pgd_alloc(void)
564
{
565
        unsigned long pgd;
566
 
567
        /*
568
         * need to get a 16k page for level 1
569
         */
570
        pgd = __get_free_pages(GFP_KERNEL,2,0);
571
        if (pgd)
572
                memzero ((void *)pgd, PTRS_PER_PGD * BYTES_PER_PTR);
573
        return (pgd_t *)pgd;
574
}
575
 
576
extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
577
 
578
/*
579
 * The sa110 doesn't have any external MMU info: the kernel page
580
 * tables contain all the necessary information.
581
 */
582
extern __inline__ void update_mmu_cache(struct vm_area_struct * vma,
583
        unsigned long address, pte_t pte)
584
{
585
}
586
 
587
#define SWP_TYPE(entry) (((entry) >> 2) & 0x7f)
588
#define SWP_OFFSET(entry) ((entry) >> 9)
589
#define SWP_ENTRY(type,offset) (((type) << 2) | ((offset) << 9))
590
 
591
#endif /* __ASM_PROC_PAGE_H */
592
 

powered by: WebSVN 2.1.0

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