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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [include/] [asm-parisc/] [pgalloc.h] - Blame information for rev 1774

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

Line No. Rev Author Line
1 1275 phoenix
#ifndef _ASM_PGALLOC_H
2
#define _ASM_PGALLOC_H
3
 
4
/* The usual comment is "Caches aren't brain-dead on the <architecture>".
5
 * Unfortunately, that doesn't apply to PA-RISC. */
6
 
7
#include <asm/processor.h>
8
#include <asm/fixmap.h>
9
#include <linux/threads.h>
10
 
11
#include <asm/pgtable.h>
12
#include <asm/cache.h>
13
 
14
#define flush_kernel_dcache_range(start,size) \
15
        flush_kernel_dcache_range_asm((start), (start)+(size));
16
 
17
static inline void
18
flush_page_to_ram(struct page *page)
19
{
20
}
21
 
22
extern void flush_cache_all_local(void);
23
 
24
#ifdef CONFIG_SMP
25
static inline void flush_cache_all(void)
26
{
27
        smp_call_function((void (*)(void *))flush_cache_all_local, NULL, 1, 1);
28
        flush_cache_all_local();
29
}
30
#else
31
#define flush_cache_all flush_cache_all_local
32
#endif
33
 
34
#ifdef CONFIG_SMP
35
#define flush_cache_mm(mm) flush_cache_all()
36
#else
37
#define flush_cache_mm(mm) flush_cache_all_local()
38
#endif
39
 
40
/* The following value needs to be tuned and probably scaled with the
41
 * cache size.
42
 */
43
 
44
#define FLUSH_THRESHOLD 0x80000
45
 
46
static inline void
47
flush_user_dcache_range(unsigned long start, unsigned long end)
48
{
49
#ifdef CONFIG_SMP
50
        flush_user_dcache_range_asm(start,end);
51
#else
52
        if ((end - start) < FLUSH_THRESHOLD)
53
                flush_user_dcache_range_asm(start,end);
54
        else
55
                flush_data_cache();
56
#endif
57
}
58
 
59
static inline void
60
flush_user_icache_range(unsigned long start, unsigned long end)
61
{
62
#ifdef CONFIG_SMP
63
        flush_user_icache_range_asm(start,end);
64
#else
65
        if ((end - start) < FLUSH_THRESHOLD)
66
                flush_user_icache_range_asm(start,end);
67
        else
68
                flush_instruction_cache();
69
#endif
70
}
71
 
72
static inline void
73
flush_cache_range(struct mm_struct *mm, unsigned long start, unsigned long end)
74
{
75
        int sr3;
76
 
77
        if (!mm->context) {
78
                BUG();
79
                return;
80
        }
81
 
82
        sr3 = mfsp(3);
83
        if (mm->context == sr3) {
84
                flush_user_dcache_range(start,end);
85
                flush_user_icache_range(start,end);
86
        } else {
87
                flush_cache_all();
88
        }
89
}
90
 
91
static inline void
92
flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr)
93
{
94
        int sr3;
95
 
96
        if (!vma->vm_mm->context) {
97
                BUG();
98
                return;
99
        }
100
 
101
        sr3 = mfsp(3);
102
        if (vma->vm_mm->context == sr3) {
103
                flush_user_dcache_range(vmaddr,vmaddr + PAGE_SIZE);
104
                if (vma->vm_flags & VM_EXEC)
105
                        flush_user_icache_range(vmaddr,vmaddr + PAGE_SIZE);
106
        } else {
107
                if (vma->vm_flags & VM_EXEC)
108
                        flush_cache_all();
109
                else
110
                        flush_data_cache();
111
        }
112
}
113
 
114
extern void __flush_dcache_page(struct page *page);
115
static inline void flush_dcache_page(struct page *page)
116
{
117
        if (page->mapping && !page->mapping->i_mmap &&
118
                        !page->mapping->i_mmap_shared) {
119
                set_bit(PG_dcache_dirty, &page->flags);
120
        } else {
121
                __flush_dcache_page(page);
122
        }
123
}
124
 
125
#define flush_icache_page(vma,page)     do { flush_kernel_dcache_page(page_address(page)); flush_kernel_icache_page(page_address(page)); } while (0)
126
 
127
#define flush_icache_user_range(vma, page, addr, len) \
128
        flush_user_icache_range(addr, addr + len);
129
 
130
#define flush_icache_range(s,e)         do { flush_kernel_dcache_range_asm(s,e); flush_kernel_icache_range_asm(s,e); } while (0)
131
 
132
/* TLB flushing routines.... */
133
 
134
extern void flush_tlb_all(void);
135
 
136
static inline void load_context(mm_context_t context)
137
{
138
        mtsp(context, 3);
139
#if SPACEID_SHIFT == 0
140
        mtctl(context << 1,8);
141
#else
142
        mtctl(context >> (SPACEID_SHIFT - 1),8);
143
#endif
144
}
145
 
146
/*
147
 * flush_tlb_mm()
148
 *
149
 * XXX This code is NOT valid for HP-UX compatibility processes,
150
 * (although it will probably work 99% of the time). HP-UX
151
 * processes are free to play with the space id's and save them
152
 * over long periods of time, etc. so we have to preserve the
153
 * space and just flush the entire tlb. We need to check the
154
 * personality in order to do that, but the personality is not
155
 * currently being set correctly.
156
 *
157
 * Of course, Linux processes could do the same thing, but
158
 * we don't support that (and the compilers, dynamic linker,
159
 * etc. do not do that).
160
 */
161
 
162
static inline void flush_tlb_mm(struct mm_struct *mm)
163
{
164
        if (mm == &init_mm) BUG(); /* Should never happen */
165
 
166
#ifdef CONFIG_SMP
167
        flush_tlb_all();
168
#else
169
        if (mm) {
170
                if (mm->context != 0)
171
                        free_sid(mm->context);
172
                mm->context = alloc_sid();
173
                if (mm == current->active_mm)
174
                        load_context(mm->context);
175
        }
176
#endif
177
}
178
 
179
extern __inline__ void flush_tlb_pgtables(struct mm_struct *mm, unsigned long start, unsigned long end)
180
{
181
}
182
 
183
static inline void flush_tlb_page(struct vm_area_struct *vma,
184
        unsigned long addr)
185
{
186
        /* For one page, it's not worth testing the split_tlb variable */
187
 
188
        mtsp(vma->vm_mm->context,1);
189
        pdtlb(addr);
190
        pitlb(addr);
191
}
192
 
193
static inline void flush_tlb_range(struct mm_struct *mm,
194
        unsigned long start, unsigned long end)
195
{
196
        unsigned long npages;
197
 
198
        npages = ((end - (start & PAGE_MASK)) + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
199
        if (npages >= 512)  /* XXX arbitrary, should be tuned */
200
                flush_tlb_all();
201
        else {
202
 
203
                mtsp(mm->context,1);
204
                if (split_tlb) {
205
                        while (npages--) {
206
                                pdtlb(start);
207
                                pitlb(start);
208
                                start += PAGE_SIZE;
209
                        }
210
                } else {
211
                        while (npages--) {
212
                                pdtlb(start);
213
                                start += PAGE_SIZE;
214
                        }
215
                }
216
        }
217
}
218
 
219
static inline pgd_t *pgd_alloc_one_fast (void)
220
{
221
        return NULL; /* not implemented */
222
}
223
 
224
static inline pgd_t *pgd_alloc (struct mm_struct *mm)
225
{
226
        /* the VM system never calls pgd_alloc_one_fast(), so we do it here. */
227
        pgd_t *pgd = pgd_alloc_one_fast();
228
        if (!pgd) {
229
                pgd = (pgd_t *)__get_free_page(GFP_KERNEL);
230
                if (pgd)
231
                        clear_page(pgd);
232
        }
233
        return pgd;
234
}
235
 
236
static inline void pgd_free(pgd_t *pgd)
237
{
238
        free_page((unsigned long)pgd);
239
}
240
 
241
#ifdef __LP64__
242
 
243
/* Three Level Page Table Support for pmd's */
244
 
245
static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmd)
246
{
247
        pgd_val(*pgd) = _PAGE_TABLE + __pa((unsigned long)pmd);
248
}
249
 
250
static inline pmd_t *pmd_alloc_one_fast(struct mm_struct *mm, unsigned long address)
251
{
252
        return NULL; /* la la */
253
}
254
 
255
static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
256
{
257
        pmd_t *pmd = (pmd_t *) __get_free_page(GFP_KERNEL);
258
        if (pmd)
259
                clear_page(pmd);
260
        return pmd;
261
}
262
 
263
static inline void pmd_free(pmd_t *pmd)
264
{
265
        free_page((unsigned long)pmd);
266
}
267
 
268
#else
269
 
270
/* Two Level Page Table Support for pmd's */
271
 
272
/*
273
 * allocating and freeing a pmd is trivial: the 1-entry pmd is
274
 * inside the pgd, so has no extra memory associated with it.
275
 */
276
 
277
#define pmd_alloc_one_fast(mm, addr)    ({ BUG(); ((pmd_t *)1); })
278
#define pmd_alloc_one(mm, addr)         ({ BUG(); ((pmd_t *)2); })
279
#define pmd_free(x)                     do { } while (0)
280
#define pgd_populate(mm, pmd, pte)      BUG()
281
 
282
#endif
283
 
284
static inline void pmd_populate (struct mm_struct *mm, pmd_t *pmd_entry, pte_t *pte)
285
{
286
        pmd_val(*pmd_entry) = _PAGE_TABLE + __pa((unsigned long)pte);
287
}
288
 
289
static inline pte_t *pte_alloc_one_fast(struct mm_struct *mm, unsigned long address)
290
{
291
        return NULL; /* la la */
292
}
293
 
294
static inline pte_t *pte_alloc_one(struct mm_struct *mm, unsigned long address)
295
{
296
        pte_t *pte = (pte_t *) __get_free_page(GFP_KERNEL);
297
        if (pte)
298
                clear_page(pte);
299
        return pte;
300
}
301
 
302
static inline void pte_free(pte_t *pte)
303
{
304
        free_page((unsigned long)pte);
305
}
306
 
307
extern int do_check_pgt_cache(int, int);
308
 
309
#endif

powered by: WebSVN 2.1.0

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