~ubuntu-branches/ubuntu/utopic/xen/utopic

« back to all changes in this revision

Viewing changes to xenolinux-2.4.25-sparse/include/asm-xeno/pgalloc.h

  • Committer: Bazaar Package Importer
  • Author(s): Bastian Blank
  • Date: 2010-05-06 15:47:38 UTC
  • mto: (1.3.1) (15.1.1 sid) (4.1.1 experimental)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20100506154738-agoz0rlafrh1fnq7
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#ifndef _I386_PGALLOC_H
2
 
#define _I386_PGALLOC_H
3
 
 
4
 
#include <linux/config.h>
5
 
#include <asm/processor.h>
6
 
#include <asm/fixmap.h>
7
 
#include <asm/hypervisor.h>
8
 
#include <linux/threads.h>
9
 
 
10
 
/*
11
 
 * Quick lists are aligned so that least significant bits of array pointer
12
 
 * are all zero when list is empty, and all one when list is full.
13
 
 */
14
 
#define QUICKLIST_ENTRIES 256
15
 
#define QUICKLIST_EMPTY(_l) !((unsigned long)(_l) & ((QUICKLIST_ENTRIES*4)-1))
16
 
#define QUICKLIST_FULL(_l)  QUICKLIST_EMPTY((_l)+1)
17
 
#define pgd_quicklist (current_cpu_data.pgd_quick)
18
 
#define pmd_quicklist (current_cpu_data.pmd_quick)
19
 
#define pte_quicklist (current_cpu_data.pte_quick)
20
 
#define pgtable_cache_size (current_cpu_data.pgtable_cache_sz)
21
 
 
22
 
#define pmd_populate(mm, pmd, pte)                \
23
 
 do {                                             \
24
 
  set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte)));   \
25
 
  XENO_flush_page_update_queue();                 \
26
 
 } while ( 0 )
27
 
 
28
 
/*
29
 
 * Allocate and free page tables.
30
 
 */
31
 
 
32
 
#if defined (CONFIG_X86_PAE)
33
 
 
34
 
#error "no PAE support as yet"
35
 
 
36
 
/*
37
 
 * We can't include <linux/slab.h> here, thus these uglinesses.
38
 
 */
39
 
struct kmem_cache_s;
40
 
 
41
 
extern struct kmem_cache_s *pae_pgd_cachep;
42
 
extern void *kmem_cache_alloc(struct kmem_cache_s *, int);
43
 
extern void kmem_cache_free(struct kmem_cache_s *, void *);
44
 
 
45
 
 
46
 
static inline pgd_t *get_pgd_slow(void)
47
 
{
48
 
        int i;
49
 
        pgd_t *pgd = kmem_cache_alloc(pae_pgd_cachep, GFP_KERNEL);
50
 
 
51
 
        if (pgd) {
52
 
                for (i = 0; i < USER_PTRS_PER_PGD; i++) {
53
 
                        unsigned long pmd = __get_free_page(GFP_KERNEL);
54
 
                        if (!pmd)
55
 
                                goto out_oom;
56
 
                        clear_page(pmd);
57
 
                        set_pgd(pgd + i, __pgd(1 + __pa(pmd)));
58
 
                }
59
 
                memcpy(pgd + USER_PTRS_PER_PGD,
60
 
                        swapper_pg_dir + USER_PTRS_PER_PGD,
61
 
                        (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
62
 
        }
63
 
        return pgd;
64
 
out_oom:
65
 
        for (i--; i >= 0; i--)
66
 
                free_page((unsigned long)__va(pgd_val(pgd[i])-1));
67
 
        kmem_cache_free(pae_pgd_cachep, pgd);
68
 
        return NULL;
69
 
}
70
 
 
71
 
#else
72
 
 
73
 
static inline pgd_t *get_pgd_slow(void)
74
 
{
75
 
        pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL);
76
 
 
77
 
        if (pgd) {
78
 
                memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
79
 
                memcpy(pgd + USER_PTRS_PER_PGD,
80
 
                        init_mm.pgd + USER_PTRS_PER_PGD,
81
 
                        (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
82
 
                __make_page_readonly(pgd);
83
 
                queue_pgd_pin(__pa(pgd));
84
 
 
85
 
        }
86
 
        return pgd;
87
 
}
88
 
 
89
 
#endif /* CONFIG_X86_PAE */
90
 
 
91
 
static inline pgd_t *get_pgd_fast(void)
92
 
{
93
 
        unsigned long ret;
94
 
 
95
 
        if ( !QUICKLIST_EMPTY(pgd_quicklist) ) {
96
 
                ret = *(--pgd_quicklist);
97
 
                pgtable_cache_size--;
98
 
 
99
 
        } else
100
 
                ret = (unsigned long)get_pgd_slow();
101
 
        return (pgd_t *)ret;
102
 
}
103
 
 
104
 
static inline void free_pgd_slow(pgd_t *pgd)
105
 
{
106
 
#if defined(CONFIG_X86_PAE)
107
 
#error
108
 
        int i;
109
 
 
110
 
        for (i = 0; i < USER_PTRS_PER_PGD; i++)
111
 
                free_page((unsigned long)__va(pgd_val(pgd[i])-1));
112
 
        kmem_cache_free(pae_pgd_cachep, pgd);
113
 
#else
114
 
        queue_pgd_unpin(__pa(pgd));
115
 
        __make_page_writeable(pgd);
116
 
        free_page((unsigned long)pgd);
117
 
#endif
118
 
}
119
 
 
120
 
static inline void free_pgd_fast(pgd_t *pgd)
121
 
{
122
 
        if ( !QUICKLIST_FULL(pgd_quicklist) ) {
123
 
                *(pgd_quicklist++) = (unsigned long)pgd;
124
 
                pgtable_cache_size++;
125
 
        } else
126
 
                free_pgd_slow(pgd);
127
 
}
128
 
 
129
 
static inline pte_t *pte_alloc_one(struct mm_struct *mm, unsigned long address)
130
 
{
131
 
    pte_t *pte;
132
 
 
133
 
    pte = (pte_t *) __get_free_page(GFP_KERNEL);
134
 
    if (pte)
135
 
    {
136
 
        clear_page(pte);
137
 
        __make_page_readonly(pte);
138
 
        queue_pte_pin(__pa(pte));
139
 
    }
140
 
    return pte;
141
 
 
142
 
}
143
 
 
144
 
static inline pte_t *pte_alloc_one_fast(struct mm_struct *mm,
145
 
                                        unsigned long address)
146
 
{
147
 
    unsigned long ret = 0;
148
 
    if ( !QUICKLIST_EMPTY(pte_quicklist) ) {
149
 
        ret = *(--pte_quicklist);
150
 
        pgtable_cache_size--;
151
 
    }
152
 
    return (pte_t *)ret;
153
 
}
154
 
 
155
 
static __inline__ void pte_free_slow(pte_t *pte)
156
 
{
157
 
    queue_pte_unpin(__pa(pte));
158
 
    __make_page_writeable(pte);
159
 
    free_page((unsigned long)pte);
160
 
}
161
 
 
162
 
static inline void pte_free_fast(pte_t *pte)
163
 
{
164
 
    if ( !QUICKLIST_FULL(pte_quicklist) ) {
165
 
        *(pte_quicklist++) = (unsigned long)pte;
166
 
        pgtable_cache_size++;
167
 
    } else
168
 
        pte_free_slow(pte);
169
 
}
170
 
 
171
 
#define pte_free(pte)           pte_free_fast(pte)
172
 
#define pgd_free(pgd)           free_pgd_fast(pgd)
173
 
#define pgd_alloc(mm)           get_pgd_fast()
174
 
 
175
 
/*
176
 
 * allocating and freeing a pmd is trivial: the 1-entry pmd is
177
 
 * inside the pgd, so has no extra memory associated with it.
178
 
 * (In the PAE case we free the pmds as part of the pgd.)
179
 
 */
180
 
 
181
 
#define pmd_alloc_one_fast(mm, addr)    ({ BUG(); ((pmd_t *)1); })
182
 
#define pmd_alloc_one(mm, addr)         ({ BUG(); ((pmd_t *)2); })
183
 
#define pmd_free_slow(x)                do { } while (0)
184
 
#define pmd_free_fast(x)                do { } while (0)
185
 
#define pmd_free(x)                     do { } while (0)
186
 
#define pgd_populate(mm, pmd, pte)      BUG()
187
 
 
188
 
extern int do_check_pgt_cache(int, int);
189
 
 
190
 
/*
191
 
 * TLB flushing:
192
 
 *
193
 
 *  - flush_tlb() flushes the current mm struct TLBs
194
 
 *  - flush_tlb_all() flushes all processes TLBs
195
 
 *  - flush_tlb_mm(mm) flushes the specified mm context TLB's
196
 
 *  - flush_tlb_page(vma, vmaddr) flushes one page
197
 
 *  - flush_tlb_range(mm, start, end) flushes a range of pages
198
 
 *  - flush_tlb_pgtables(mm, start, end) flushes a range of page tables
199
 
 *
200
 
 * ..but the i386 has somewhat limited tlb flushing capabilities,
201
 
 * and page-granular flushes are available only on i486 and up.
202
 
 */
203
 
 
204
 
#ifndef CONFIG_SMP
205
 
 
206
 
#define flush_tlb() __flush_tlb()
207
 
#define flush_tlb_all() __flush_tlb_all()
208
 
#define local_flush_tlb() __flush_tlb()
209
 
 
210
 
static inline void flush_tlb_mm(struct mm_struct *mm)
211
 
{
212
 
        if (mm == current->active_mm) queue_tlb_flush();
213
 
        XENO_flush_page_update_queue();
214
 
}
215
 
 
216
 
static inline void flush_tlb_page(struct vm_area_struct *vma,
217
 
        unsigned long addr)
218
 
{
219
 
        if (vma->vm_mm == current->active_mm) queue_invlpg(addr);
220
 
        XENO_flush_page_update_queue();
221
 
}
222
 
 
223
 
static inline void flush_tlb_range(struct mm_struct *mm,
224
 
        unsigned long start, unsigned long end)
225
 
{
226
 
        if (mm == current->active_mm) queue_tlb_flush();
227
 
        XENO_flush_page_update_queue();
228
 
}
229
 
 
230
 
#else
231
 
#error no guestos SMP support yet...
232
 
#include <asm/smp.h>
233
 
 
234
 
#define local_flush_tlb() \
235
 
        __flush_tlb()
236
 
 
237
 
extern void flush_tlb_all(void);
238
 
extern void flush_tlb_current_task(void);
239
 
extern void flush_tlb_mm(struct mm_struct *);
240
 
extern void flush_tlb_page(struct vm_area_struct *, unsigned long);
241
 
 
242
 
#define flush_tlb()     flush_tlb_current_task()
243
 
 
244
 
static inline void flush_tlb_range(struct mm_struct * mm, unsigned long start, unsigned long end)
245
 
{
246
 
        flush_tlb_mm(mm);
247
 
}
248
 
 
249
 
#define TLBSTATE_OK     1
250
 
#define TLBSTATE_LAZY   2
251
 
 
252
 
struct tlb_state
253
 
{
254
 
        struct mm_struct *active_mm;
255
 
        int state;
256
 
} ____cacheline_aligned;
257
 
extern struct tlb_state cpu_tlbstate[NR_CPUS];
258
 
 
259
 
#endif /* CONFIG_SMP */
260
 
 
261
 
static inline void flush_tlb_pgtables(struct mm_struct *mm,
262
 
                                      unsigned long start, unsigned long end)
263
 
{
264
 
    /* i386 does not keep any page table caches in TLB */
265
 
    XENO_flush_page_update_queue();
266
 
}
267
 
 
268
 
extern int direct_remap_area_pages(struct mm_struct *mm,
269
 
                                   unsigned long address, 
270
 
                                   unsigned long machine_addr,
271
 
                                   unsigned long size, 
272
 
                                   pgprot_t prot);
273
 
 
274
 
#endif /* _I386_PGALLOC_H */