ia64/xen-unstable

view xenolinux-2.4.21-pre4-sparse/arch/xeno/mm/hypervisor.c @ 235:d7d0a23b2e07

bitkeeper revision 1.93 (3e5a4e6bkPheUp3x1uufN2MS3LAB7A)

Latest and Greatest version of XenoLinux based on the Linux-2.4.21-pre4
kernel.
author iap10@labyrinth.cl.cam.ac.uk
date Mon Feb 24 16:55:07 2003 +0000 (2003-02-24)
parents
children 666728c2dad4
line source
1 /******************************************************************************
2 * xeno/mm/hypervisor.c
3 *
4 * Update page tables via the hypervisor.
5 *
6 * Copyright (c) 2002, K A Fraser
7 */
9 #include <linux/config.h>
10 #include <linux/sched.h>
11 #include <asm/hypervisor.h>
12 #include <asm/page.h>
13 #include <asm/pgtable.h>
15 #define QUEUE_SIZE 2048
16 static page_update_request_t update_queue[QUEUE_SIZE];
17 unsigned int pt_update_queue_idx = 0;
18 #define idx pt_update_queue_idx
20 #if PT_UPDATE_DEBUG > 0
21 page_update_debug_t update_debug_queue[QUEUE_SIZE] = {{0}};
22 #undef queue_l1_entry_update
23 #undef queue_l2_entry_update
24 static void DEBUG_allow_pt_reads(void)
25 {
26 pte_t *pte;
27 page_update_request_t update;
28 int i;
29 for ( i = idx-1; i >= 0; i-- )
30 {
31 pte = update_debug_queue[i].ptep;
32 if ( pte == NULL ) continue;
33 update_debug_queue[i].ptep = NULL;
34 update.ptr = phys_to_machine(__pa(pte));
35 update.val = update_debug_queue[i].pteval;
36 HYPERVISOR_pt_update(&update, 1);
37 }
38 }
39 static void DEBUG_disallow_pt_read(unsigned long pa)
40 {
41 pte_t *pte;
42 pmd_t *pmd;
43 pgd_t *pgd;
44 unsigned long pteval;
45 /*
46 * We may fault because of an already outstanding update.
47 * That's okay -- it'll get fixed up in the fault handler.
48 */
49 page_update_request_t update;
50 unsigned long va = (unsigned long)__va(pa);
51 pgd = pgd_offset_k(va);
52 pmd = pmd_offset(pgd, va);
53 pte = pte_offset(pmd, va);
54 update.ptr = phys_to_machine(__pa(pte));
55 pteval = *(unsigned long *)pte;
56 update.val = pteval & ~_PAGE_PRESENT;
57 HYPERVISOR_pt_update(&update, 1);
58 update_debug_queue[idx].ptep = pte;
59 update_debug_queue[idx].pteval = pteval;
60 }
61 #endif
63 #if PT_UPDATE_DEBUG > 1
64 #undef queue_pt_switch
65 #undef queue_tlb_flush
66 #undef queue_invlpg
67 #undef queue_pgd_pin
68 #undef queue_pgd_unpin
69 #undef queue_pte_pin
70 #undef queue_pte_unpin
71 #endif
74 /*
75 * This is the current pagetable base pointer, which is updated
76 * on context switch.
77 */
78 unsigned long pt_baseptr;
80 void _flush_page_update_queue(void)
81 {
82 if ( idx == 0 ) return;
83 #if PT_UPDATE_DEBUG > 1
84 printk("Flushing %d entries from pt update queue\n", idx);
85 #endif
86 #if PT_UPDATE_DEBUG > 0
87 DEBUG_allow_pt_reads();
88 #endif
89 HYPERVISOR_pt_update(update_queue, idx);
90 idx = 0;
91 }
93 static void increment_index(void)
94 {
95 if ( ++idx == QUEUE_SIZE ) _flush_page_update_queue();
96 }
98 void queue_l1_entry_update(unsigned long ptr, unsigned long val)
99 {
100 #if PT_UPDATE_DEBUG > 0
101 DEBUG_disallow_pt_read(ptr);
102 #endif
103 update_queue[idx].ptr = phys_to_machine(ptr);
104 update_queue[idx].val = val;
105 increment_index();
106 }
108 void queue_l2_entry_update(unsigned long ptr, unsigned long val)
109 {
110 update_queue[idx].ptr = phys_to_machine(ptr);
111 update_queue[idx].val = val;
112 increment_index();
113 }
115 void queue_pt_switch(unsigned long ptr)
116 {
117 update_queue[idx].ptr = phys_to_machine(ptr);
118 update_queue[idx].ptr |= PGREQ_EXTENDED_COMMAND;
119 update_queue[idx].val = PGEXT_NEW_BASEPTR;
120 increment_index();
121 }
123 void queue_tlb_flush(void)
124 {
125 update_queue[idx].ptr = PGREQ_EXTENDED_COMMAND;
126 update_queue[idx].val = PGEXT_TLB_FLUSH;
127 increment_index();
128 }
130 void queue_invlpg(unsigned long ptr)
131 {
132 update_queue[idx].ptr = PGREQ_EXTENDED_COMMAND;
133 update_queue[idx].val = ptr & PAGE_MASK;
134 update_queue[idx].val |= PGEXT_INVLPG;
135 increment_index();
136 }
138 void queue_pgd_pin(unsigned long ptr)
139 {
140 update_queue[idx].ptr = phys_to_machine(ptr);
141 update_queue[idx].ptr |= PGREQ_EXTENDED_COMMAND;
142 update_queue[idx].val = PGEXT_PIN_L2_TABLE;
143 increment_index();
144 }
146 void queue_pgd_unpin(unsigned long ptr)
147 {
148 update_queue[idx].ptr = phys_to_machine(ptr);
149 update_queue[idx].ptr |= PGREQ_EXTENDED_COMMAND;
150 update_queue[idx].val = PGEXT_UNPIN_TABLE;
151 increment_index();
152 }
154 void queue_pte_pin(unsigned long ptr)
155 {
156 update_queue[idx].ptr = phys_to_machine(ptr);
157 update_queue[idx].ptr |= PGREQ_EXTENDED_COMMAND;
158 update_queue[idx].val = PGEXT_PIN_L1_TABLE;
159 increment_index();
160 }
162 void queue_pte_unpin(unsigned long ptr)
163 {
164 update_queue[idx].ptr = phys_to_machine(ptr);
165 update_queue[idx].ptr |= PGREQ_EXTENDED_COMMAND;
166 update_queue[idx].val = PGEXT_UNPIN_TABLE;
167 increment_index();
168 }