ia64/xen-unstable

view xen/arch/x86/x86_32/mm.c @ 19835:edfdeb150f27

Fix buildsystem to detect udev > version 124

udev removed the udevinfo symlink from versions higher than 123 and
xen's build-system could not detect if udev is in place and has the
required version.

Signed-off-by: Marc-A. Dahlhaus <mad@wol.de>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Jun 25 13:02:37 2009 +0100 (2009-06-25)
parents 67a0ffade665
children
line source
1 /******************************************************************************
2 * arch/x86/x86_32/mm.c
3 *
4 * Modifications to Linux original are copyright (c) 2004, K A Fraser
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
21 #include <xen/config.h>
22 #include <xen/lib.h>
23 #include <xen/init.h>
24 #include <xen/mm.h>
25 #include <xen/sched.h>
26 #include <xen/guest_access.h>
27 #include <asm/current.h>
28 #include <asm/page.h>
29 #include <asm/flushtlb.h>
30 #include <asm/fixmap.h>
31 #include <public/memory.h>
33 l2_pgentry_t __attribute__ ((__section__ (".bss.page_aligned")))
34 idle_pg_table_l2[4 * L2_PAGETABLE_ENTRIES];
36 extern l1_pgentry_t l1_identmap[L1_PAGETABLE_ENTRIES];
38 unsigned int PAGE_HYPERVISOR = __PAGE_HYPERVISOR;
39 unsigned int PAGE_HYPERVISOR_NOCACHE = __PAGE_HYPERVISOR_NOCACHE;
41 static unsigned long mpt_size;
43 void *alloc_xen_pagetable(void)
44 {
45 extern int early_boot;
46 extern unsigned long xenheap_initial_phys_start;
47 unsigned long mfn;
49 if ( !early_boot )
50 {
51 void *v = alloc_xenheap_page();
52 BUG_ON(v == NULL);
53 return v;
54 }
56 mfn = xenheap_initial_phys_start >> PAGE_SHIFT;
57 xenheap_initial_phys_start += PAGE_SIZE;
58 return mfn_to_virt(mfn);
59 }
61 l2_pgentry_t *virt_to_xen_l2e(unsigned long v)
62 {
63 return &idle_pg_table_l2[l2_linear_offset(v)];
64 }
66 void *do_page_walk(struct vcpu *v, unsigned long addr)
67 {
68 return NULL;
69 }
71 void __init paging_init(void)
72 {
73 unsigned long v;
74 struct page_info *pg;
75 int i;
77 if ( cpu_has_pge )
78 {
79 /* Suitable Xen mapping can be GLOBAL. */
80 set_in_cr4(X86_CR4_PGE);
81 PAGE_HYPERVISOR |= _PAGE_GLOBAL;
82 PAGE_HYPERVISOR_NOCACHE |= _PAGE_GLOBAL;
83 /* Transform early mappings (e.g., the frametable). */
84 for ( v = HYPERVISOR_VIRT_START; v; v += (1 << L2_PAGETABLE_SHIFT) )
85 if ( (l2e_get_flags(idle_pg_table_l2[l2_linear_offset(v)]) &
86 (_PAGE_PSE|_PAGE_PRESENT)) == (_PAGE_PSE|_PAGE_PRESENT) )
87 l2e_add_flags(idle_pg_table_l2[l2_linear_offset(v)],
88 _PAGE_GLOBAL);
89 for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++ )
90 l1e_add_flags(l1_identmap[i], _PAGE_GLOBAL);
91 }
93 /*
94 * Allocate and map the machine-to-phys table and create read-only mapping
95 * of MPT for guest-OS use.
96 */
97 mpt_size = (max_page * BYTES_PER_LONG) + (1UL << L2_PAGETABLE_SHIFT) - 1;
98 mpt_size &= ~((1UL << L2_PAGETABLE_SHIFT) - 1UL);
99 for ( i = 0; i < (mpt_size >> L2_PAGETABLE_SHIFT); i++ )
100 {
101 if ( (pg = alloc_domheap_pages(NULL, PAGETABLE_ORDER, 0)) == NULL )
102 panic("Not enough memory to bootstrap Xen.\n");
103 l2e_write(&idle_pg_table_l2[l2_linear_offset(RDWR_MPT_VIRT_START) + i],
104 l2e_from_page(pg, PAGE_HYPERVISOR | _PAGE_PSE));
105 /* NB. Cannot be GLOBAL as shadow_mode_translate reuses this area. */
106 l2e_write(&idle_pg_table_l2[l2_linear_offset(RO_MPT_VIRT_START) + i],
107 l2e_from_page(
108 pg, (__PAGE_HYPERVISOR | _PAGE_PSE) & ~_PAGE_RW));
109 }
111 /* Fill with an obvious debug pattern. */
112 for ( i = 0; i < (mpt_size / BYTES_PER_LONG); i++)
113 set_gpfn_from_mfn(i, 0x55555555);
115 /* Create page tables for ioremap()/map_domain_page_global(). */
116 for ( i = 0; i < (IOREMAP_MBYTES >> (L2_PAGETABLE_SHIFT - 20)); i++ )
117 {
118 void *p;
119 l2_pgentry_t *pl2e;
120 pl2e = &idle_pg_table_l2[l2_linear_offset(IOREMAP_VIRT_START) + i];
121 if ( l2e_get_flags(*pl2e) & _PAGE_PRESENT )
122 continue;
123 p = alloc_xenheap_page();
124 clear_page(p);
125 l2e_write(pl2e, l2e_from_page(virt_to_page(p), __PAGE_HYPERVISOR));
126 }
127 }
129 void __init setup_idle_pagetable(void)
130 {
131 int i;
133 for ( i = 0; i < PDPT_L2_ENTRIES; i++ )
134 l2e_write(&idle_pg_table_l2[l2_linear_offset(PERDOMAIN_VIRT_START)+i],
135 l2e_from_page(virt_to_page(idle_vcpu[0]->domain->
136 arch.mm_perdomain_pt) + i,
137 __PAGE_HYPERVISOR));
138 }
140 void __init zap_low_mappings(l2_pgentry_t *dom0_l2)
141 {
142 int i;
144 /* Clear temporary idle mappings from the dom0 initial l2. */
145 for ( i = 0; i < (HYPERVISOR_VIRT_START >> L2_PAGETABLE_SHIFT); i++ )
146 if ( l2e_get_intpte(dom0_l2[i]) ==
147 l2e_get_intpte(idle_pg_table_l2[i]) )
148 l2e_write(&dom0_l2[i], l2e_empty());
150 /* Now zap mappings in the idle pagetables. */
151 BUG_ON(l2e_get_pfn(idle_pg_table_l2[0]) != virt_to_mfn(l1_identmap));
152 l2e_write_atomic(&idle_pg_table_l2[0], l2e_empty());
153 destroy_xen_mappings(0, HYPERVISOR_VIRT_START);
155 flush_all(FLUSH_TLB_GLOBAL);
157 /* Replace with mapping of the boot trampoline only. */
158 map_pages_to_xen(BOOT_TRAMPOLINE, BOOT_TRAMPOLINE >> PAGE_SHIFT,
159 0x10, __PAGE_HYPERVISOR);
160 }
162 void __init subarch_init_memory(void)
163 {
164 unsigned long m2p_start_mfn;
165 unsigned int i, j;
167 BUILD_BUG_ON(sizeof(struct page_info) != 24);
169 /* M2P table is mappable read-only by privileged domains. */
170 for ( i = 0; i < (mpt_size >> L2_PAGETABLE_SHIFT); i++ )
171 {
172 m2p_start_mfn = l2e_get_pfn(
173 idle_pg_table_l2[l2_linear_offset(RDWR_MPT_VIRT_START) + i]);
174 for ( j = 0; j < L2_PAGETABLE_ENTRIES; j++ )
175 {
176 struct page_info *page = mfn_to_page(m2p_start_mfn + j);
177 share_xen_page_with_privileged_guests(page, XENSHARE_readonly);
178 }
179 }
181 if ( supervisor_mode_kernel )
182 {
183 /* Guest kernel runs in ring 0, not ring 1. */
184 struct desc_struct *d;
185 d = &boot_cpu_gdt_table[(FLAT_RING1_CS >> 3) - FIRST_RESERVED_GDT_ENTRY];
186 d[0].b &= ~_SEGMENT_DPL;
187 d[1].b &= ~_SEGMENT_DPL;
188 }
189 }
191 long subarch_memory_op(int op, XEN_GUEST_HANDLE(void) arg)
192 {
193 struct xen_machphys_mfn_list xmml;
194 unsigned long mfn;
195 unsigned int i, max;
196 long rc = 0;
198 switch ( op )
199 {
200 case XENMEM_machphys_mfn_list:
201 if ( copy_from_guest(&xmml, arg, 1) )
202 return -EFAULT;
204 max = min_t(unsigned int, xmml.max_extents, mpt_size >> 21);
206 for ( i = 0; i < max; i++ )
207 {
208 mfn = l2e_get_pfn(idle_pg_table_l2[l2_linear_offset(
209 RDWR_MPT_VIRT_START + (i << 21))]) + l1_table_offset(i << 21);
210 if ( copy_to_guest_offset(xmml.extent_start, i, &mfn, 1) )
211 return -EFAULT;
212 }
214 xmml.nr_extents = i;
215 if ( copy_to_guest(arg, &xmml, 1) )
216 return -EFAULT;
218 break;
220 default:
221 rc = -ENOSYS;
222 break;
223 }
225 return rc;
226 }
228 long do_stack_switch(unsigned long ss, unsigned long esp)
229 {
230 int nr = smp_processor_id();
231 struct tss_struct *t = &init_tss[nr];
233 fixup_guest_stack_selector(current->domain, ss);
235 current->arch.guest_context.kernel_ss = ss;
236 current->arch.guest_context.kernel_sp = esp;
237 t->ss1 = ss;
238 t->esp1 = esp;
240 return 0;
241 }
243 /* Returns TRUE if given descriptor is valid for GDT or LDT. */
244 int check_descriptor(const struct domain *dom, struct desc_struct *d)
245 {
246 unsigned long base, limit;
247 u32 a = d->a, b = d->b;
248 u16 cs;
250 /* Let a ring0 guest kernel set any descriptor it wants to. */
251 if ( supervisor_mode_kernel )
252 return 1;
254 /* A not-present descriptor will always fault, so is safe. */
255 if ( !(b & _SEGMENT_P) )
256 goto good;
258 /*
259 * We don't allow a DPL of zero. There is no legitimate reason for
260 * specifying DPL==0, and it gets rather dangerous if we also accept call
261 * gates (consider a call gate pointing at another kernel descriptor with
262 * DPL 0 -- this would get the OS ring-0 privileges).
263 */
264 if ( (b & _SEGMENT_DPL) < (GUEST_KERNEL_RPL(dom) << 13) )
265 d->b = b = (b & ~_SEGMENT_DPL) | (GUEST_KERNEL_RPL(dom) << 13);
267 if ( !(b & _SEGMENT_S) )
268 {
269 /*
270 * System segment:
271 * 1. Don't allow interrupt or trap gates as they belong in the IDT.
272 * 2. Don't allow TSS descriptors or task gates as we don't
273 * virtualise x86 tasks.
274 * 3. Don't allow LDT descriptors because they're unnecessary and
275 * I'm uneasy about allowing an LDT page to contain LDT
276 * descriptors. In any case, Xen automatically creates the
277 * required descriptor when reloading the LDT register.
278 * 4. We allow call gates but they must not jump to a private segment.
279 */
281 /* Disallow everything but call gates. */
282 if ( (b & _SEGMENT_TYPE) != 0xc00 )
283 goto bad;
285 /* Validate and fix up the target code selector. */
286 cs = a >> 16;
287 fixup_guest_code_selector(dom, cs);
288 if ( !guest_gate_selector_okay(dom, cs) )
289 goto bad;
290 a = d->a = (d->a & 0xffffU) | (cs << 16);
292 /* Reserved bits must be zero. */
293 if ( (b & 0xe0) != 0 )
294 goto bad;
296 /* No base/limit check is needed for a call gate. */
297 goto good;
298 }
300 /* Check that base is at least a page away from Xen-private area. */
301 base = (b&(0xff<<24)) | ((b&0xff)<<16) | (a>>16);
302 if ( base >= (GUEST_SEGMENT_MAX_ADDR - PAGE_SIZE) )
303 goto bad;
305 /* Check and truncate the limit if necessary. */
306 limit = (b&0xf0000) | (a&0xffff);
307 limit++; /* We add one because limit is inclusive. */
308 if ( (b & _SEGMENT_G) )
309 limit <<= 12;
311 if ( (b & (_SEGMENT_CODE | _SEGMENT_EC)) == _SEGMENT_EC )
312 {
313 /*
314 * DATA, GROWS-DOWN.
315 * Grows-down limit check.
316 * NB. limit == 0xFFFFF provides no access (if G=1).
317 * limit == 0x00000 provides 4GB-4kB access (if G=1).
318 */
319 if ( (base + limit) > base )
320 {
321 limit = -(base & PAGE_MASK);
322 goto truncate;
323 }
324 }
325 else
326 {
327 /*
328 * DATA, GROWS-UP.
329 * CODE (CONFORMING AND NON-CONFORMING).
330 * Grows-up limit check.
331 * NB. limit == 0xFFFFF provides 4GB access (if G=1).
332 * limit == 0x00000 provides 4kB access (if G=1).
333 */
334 if ( ((base + limit) <= base) ||
335 ((base + limit) > GUEST_SEGMENT_MAX_ADDR) )
336 {
337 limit = GUEST_SEGMENT_MAX_ADDR - base;
338 truncate:
339 if ( !(b & _SEGMENT_G) )
340 goto bad; /* too dangerous; too hard to work out... */
341 limit = (limit >> 12) - 1;
342 d->a &= ~0x0ffff; d->a |= limit & 0x0ffff;
343 d->b &= ~0xf0000; d->b |= limit & 0xf0000;
344 }
345 }
347 good:
348 return 1;
349 bad:
350 return 0;
351 }
353 /*
354 * Local variables:
355 * mode: C
356 * c-set-style: "BSD"
357 * c-basic-offset: 4
358 * tab-width: 4
359 * indent-tabs-mode: nil
360 * End:
361 */