aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2007-10-21 21:24:24 -0400
committerRusty Russell <rusty@rustcorp.com.au>2007-10-23 01:49:56 -0400
commit2d37f94a28170ca656438758fca577acb49a7932 (patch)
tree21049219a98d314a2c442293e512b74d879e6270
parent56ae43dfe233323683248a5c553bad7160db2fa5 (diff)
generalize lgread_u32/lgwrite_u32.
Jes complains that page table code still uses lgread_u32 even though it now uses general kernel pte types. The best thing to do is to generalize lgread_u32 and lgwrite_u32. This means we lose the efficiency of getuser(). We could potentially regain it if we used __copy_from_user instead of copy_from_user, but I'm not certain that our range check is equivalent to access_ok() on all platforms. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Acked-by: Jes Sorensen <jes@sgi.com>
-rw-r--r--drivers/lguest/core.c39
-rw-r--r--drivers/lguest/hypercalls.c2
-rw-r--r--drivers/lguest/interrupts_and_traps.c2
-rw-r--r--drivers/lguest/lg.h23
-rw-r--r--drivers/lguest/page_tables.c10
-rw-r--r--drivers/lguest/segments.c4
-rw-r--r--drivers/lguest/x86/core.c4
7 files changed, 38 insertions, 46 deletions
diff --git a/drivers/lguest/core.c b/drivers/lguest/core.c
index 3aec29ec7715..35d19ae58de7 100644
--- a/drivers/lguest/core.c
+++ b/drivers/lguest/core.c
@@ -145,33 +145,10 @@ int lguest_address_ok(const struct lguest *lg,
145 return (addr+len) / PAGE_SIZE < lg->pfn_limit && (addr+len >= addr); 145 return (addr+len) / PAGE_SIZE < lg->pfn_limit && (addr+len >= addr);
146} 146}
147 147
148/* This is a convenient routine to get a 32-bit value from the Guest (a very 148/* This routine copies memory from the Guest. Here we can see how useful the
149 * common operation). Here we can see how useful the kill_lguest() routine we 149 * kill_lguest() routine we met in the Launcher can be: we return a random
150 * met in the Launcher can be: we return a random value (0) instead of needing 150 * value (all zeroes) instead of needing to return an error. */
151 * to return an error. */ 151void __lgread(struct lguest *lg, void *b, unsigned long addr, unsigned bytes)
152u32 lgread_u32(struct lguest *lg, unsigned long addr)
153{
154 u32 val = 0;
155
156 /* Don't let them access lguest binary. */
157 if (!lguest_address_ok(lg, addr, sizeof(val))
158 || get_user(val, (u32 *)(lg->mem_base + addr)) != 0)
159 kill_guest(lg, "bad read address %#lx: pfn_limit=%u membase=%p", addr, lg->pfn_limit, lg->mem_base);
160 return val;
161}
162
163/* Same thing for writing a value. */
164void lgwrite_u32(struct lguest *lg, unsigned long addr, u32 val)
165{
166 if (!lguest_address_ok(lg, addr, sizeof(val))
167 || put_user(val, (u32 *)(lg->mem_base + addr)) != 0)
168 kill_guest(lg, "bad write address %#lx", addr);
169}
170
171/* This routine is more generic, and copies a range of Guest bytes into a
172 * buffer. If the copy_from_user() fails, we fill the buffer with zeroes, so
173 * the caller doesn't end up using uninitialized kernel memory. */
174void lgread(struct lguest *lg, void *b, unsigned long addr, unsigned bytes)
175{ 152{
176 if (!lguest_address_ok(lg, addr, bytes) 153 if (!lguest_address_ok(lg, addr, bytes)
177 || copy_from_user(b, lg->mem_base + addr, bytes) != 0) { 154 || copy_from_user(b, lg->mem_base + addr, bytes) != 0) {
@@ -181,15 +158,15 @@ void lgread(struct lguest *lg, void *b, unsigned long addr, unsigned bytes)
181 } 158 }
182} 159}
183 160
184/* Similarly, our generic routine to copy into a range of Guest bytes. */ 161/* This is the write (copy into guest) version. */
185void lgwrite(struct lguest *lg, unsigned long addr, const void *b, 162void __lgwrite(struct lguest *lg, unsigned long addr, const void *b,
186 unsigned bytes) 163 unsigned bytes)
187{ 164{
188 if (!lguest_address_ok(lg, addr, bytes) 165 if (!lguest_address_ok(lg, addr, bytes)
189 || copy_to_user(lg->mem_base + addr, b, bytes) != 0) 166 || copy_to_user(lg->mem_base + addr, b, bytes) != 0)
190 kill_guest(lg, "bad write address %#lx len %u", addr, bytes); 167 kill_guest(lg, "bad write address %#lx len %u", addr, bytes);
191} 168}
192/* (end of memory access helper routines) :*/ 169/*:*/
193 170
194/*H:030 Let's jump straight to the the main loop which runs the Guest. 171/*H:030 Let's jump straight to the the main loop which runs the Guest.
195 * Remember, this is called by the Launcher reading /dev/lguest, and we keep 172 * Remember, this is called by the Launcher reading /dev/lguest, and we keep
diff --git a/drivers/lguest/hypercalls.c b/drivers/lguest/hypercalls.c
index 3a53788ba450..9d5184c7c14a 100644
--- a/drivers/lguest/hypercalls.c
+++ b/drivers/lguest/hypercalls.c
@@ -47,7 +47,7 @@ static void do_hcall(struct lguest *lg, struct hcall_args *args)
47 char msg[128]; 47 char msg[128];
48 /* If the lgread fails, it will call kill_guest() itself; the 48 /* If the lgread fails, it will call kill_guest() itself; the
49 * kill_guest() with the message will be ignored. */ 49 * kill_guest() with the message will be ignored. */
50 lgread(lg, msg, args->arg1, sizeof(msg)); 50 __lgread(lg, msg, args->arg1, sizeof(msg));
51 msg[sizeof(msg)-1] = '\0'; 51 msg[sizeof(msg)-1] = '\0';
52 kill_guest(lg, "CRASH: %s", msg); 52 kill_guest(lg, "CRASH: %s", msg);
53 break; 53 break;
diff --git a/drivers/lguest/interrupts_and_traps.c b/drivers/lguest/interrupts_and_traps.c
index 3271c0031a1b..82966982cb38 100644
--- a/drivers/lguest/interrupts_and_traps.c
+++ b/drivers/lguest/interrupts_and_traps.c
@@ -45,7 +45,7 @@ static void push_guest_stack(struct lguest *lg, unsigned long *gstack, u32 val)
45{ 45{
46 /* Stack grows upwards: move stack then write value. */ 46 /* Stack grows upwards: move stack then write value. */
47 *gstack -= 4; 47 *gstack -= 4;
48 lgwrite_u32(lg, *gstack, val); 48 lgwrite(lg, *gstack, u32, val);
49} 49}
50 50
51/*H:210 The set_guest_interrupt() routine actually delivers the interrupt or 51/*H:210 The set_guest_interrupt() routine actually delivers the interrupt or
diff --git a/drivers/lguest/lg.h b/drivers/lguest/lg.h
index 4d45b7036e82..d9144beca82c 100644
--- a/drivers/lguest/lg.h
+++ b/drivers/lguest/lg.h
@@ -98,12 +98,27 @@ struct lguest
98extern struct mutex lguest_lock; 98extern struct mutex lguest_lock;
99 99
100/* core.c: */ 100/* core.c: */
101u32 lgread_u32(struct lguest *lg, unsigned long addr);
102void lgwrite_u32(struct lguest *lg, unsigned long addr, u32 val);
103void lgread(struct lguest *lg, void *buf, unsigned long addr, unsigned len);
104void lgwrite(struct lguest *lg, unsigned long, const void *buf, unsigned len);
105int lguest_address_ok(const struct lguest *lg, 101int lguest_address_ok(const struct lguest *lg,
106 unsigned long addr, unsigned long len); 102 unsigned long addr, unsigned long len);
103void __lgread(struct lguest *, void *, unsigned long, unsigned);
104void __lgwrite(struct lguest *, unsigned long, const void *, unsigned);
105
106/*L:306 Using memory-copy operations like that is usually inconvient, so we
107 * have the following helper macros which read and write a specific type (often
108 * an unsigned long).
109 *
110 * This reads into a variable of the given type then returns that. */
111#define lgread(lg, addr, type) \
112 ({ type _v; __lgread((lg), &_v, (addr), sizeof(_v)); _v; })
113
114/* This checks that the variable is of the given type, then writes it out. */
115#define lgwrite(lg, addr, type, val) \
116 do { \
117 typecheck(type, val); \
118 __lgwrite((lg), (addr), &(val), sizeof(val)); \
119 } while(0)
120/* (end of memory access helper routines) :*/
121
107int run_guest(struct lguest *lg, unsigned long __user *user); 122int run_guest(struct lguest *lg, unsigned long __user *user);
108 123
109/* Helper macros to obtain the first 12 or the last 20 bits, this is only the 124/* Helper macros to obtain the first 12 or the last 20 bits, this is only the
diff --git a/drivers/lguest/page_tables.c b/drivers/lguest/page_tables.c
index fe3c7575647b..2a45f0691c9b 100644
--- a/drivers/lguest/page_tables.c
+++ b/drivers/lguest/page_tables.c
@@ -209,7 +209,7 @@ int demand_page(struct lguest *lg, unsigned long vaddr, int errcode)
209 pte_t *spte; 209 pte_t *spte;
210 210
211 /* First step: get the top-level Guest page table entry. */ 211 /* First step: get the top-level Guest page table entry. */
212 gpgd = __pgd(lgread_u32(lg, gpgd_addr(lg, vaddr))); 212 gpgd = lgread(lg, gpgd_addr(lg, vaddr), pgd_t);
213 /* Toplevel not present? We can't map it in. */ 213 /* Toplevel not present? We can't map it in. */
214 if (!(pgd_flags(gpgd) & _PAGE_PRESENT)) 214 if (!(pgd_flags(gpgd) & _PAGE_PRESENT))
215 return 0; 215 return 0;
@@ -235,7 +235,7 @@ int demand_page(struct lguest *lg, unsigned long vaddr, int errcode)
235 /* OK, now we look at the lower level in the Guest page table: keep its 235 /* OK, now we look at the lower level in the Guest page table: keep its
236 * address, because we might update it later. */ 236 * address, because we might update it later. */
237 gpte_ptr = gpte_addr(lg, gpgd, vaddr); 237 gpte_ptr = gpte_addr(lg, gpgd, vaddr);
238 gpte = __pte(lgread_u32(lg, gpte_ptr)); 238 gpte = lgread(lg, gpte_ptr, pte_t);
239 239
240 /* If this page isn't in the Guest page tables, we can't page it in. */ 240 /* If this page isn't in the Guest page tables, we can't page it in. */
241 if (!(pte_flags(gpte) & _PAGE_PRESENT)) 241 if (!(pte_flags(gpte) & _PAGE_PRESENT))
@@ -278,7 +278,7 @@ int demand_page(struct lguest *lg, unsigned long vaddr, int errcode)
278 278
279 /* Finally, we write the Guest PTE entry back: we've set the 279 /* Finally, we write the Guest PTE entry back: we've set the
280 * _PAGE_ACCESSED and maybe the _PAGE_DIRTY flags. */ 280 * _PAGE_ACCESSED and maybe the _PAGE_DIRTY flags. */
281 lgwrite_u32(lg, gpte_ptr, pte_val(gpte)); 281 lgwrite(lg, gpte_ptr, pte_t, gpte);
282 282
283 /* We succeeded in mapping the page! */ 283 /* We succeeded in mapping the page! */
284 return 1; 284 return 1;
@@ -366,12 +366,12 @@ unsigned long guest_pa(struct lguest *lg, unsigned long vaddr)
366 pte_t gpte; 366 pte_t gpte;
367 367
368 /* First step: get the top-level Guest page table entry. */ 368 /* First step: get the top-level Guest page table entry. */
369 gpgd = __pgd(lgread_u32(lg, gpgd_addr(lg, vaddr))); 369 gpgd = lgread(lg, gpgd_addr(lg, vaddr), pgd_t);
370 /* Toplevel not present? We can't map it in. */ 370 /* Toplevel not present? We can't map it in. */
371 if (!(pgd_flags(gpgd) & _PAGE_PRESENT)) 371 if (!(pgd_flags(gpgd) & _PAGE_PRESENT))
372 kill_guest(lg, "Bad address %#lx", vaddr); 372 kill_guest(lg, "Bad address %#lx", vaddr);
373 373
374 gpte = __pte(lgread_u32(lg, gpte_addr(lg, gpgd, vaddr))); 374 gpte = lgread(lg, gpte_addr(lg, gpgd, vaddr), pte_t);
375 if (!(pte_flags(gpte) & _PAGE_PRESENT)) 375 if (!(pte_flags(gpte) & _PAGE_PRESENT))
376 kill_guest(lg, "Bad address %#lx", vaddr); 376 kill_guest(lg, "Bad address %#lx", vaddr);
377 377
diff --git a/drivers/lguest/segments.c b/drivers/lguest/segments.c
index 95eb9cf297bf..c2434ec99f7b 100644
--- a/drivers/lguest/segments.c
+++ b/drivers/lguest/segments.c
@@ -150,7 +150,7 @@ void load_guest_gdt(struct lguest *lg, unsigned long table, u32 num)
150 kill_guest(lg, "too many gdt entries %i", num); 150 kill_guest(lg, "too many gdt entries %i", num);
151 151
152 /* We read the whole thing in, then fix it up. */ 152 /* We read the whole thing in, then fix it up. */
153 lgread(lg, lg->arch.gdt, table, num * sizeof(lg->arch.gdt[0])); 153 __lgread(lg, lg->arch.gdt, table, num * sizeof(lg->arch.gdt[0]));
154 fixup_gdt_table(lg, 0, ARRAY_SIZE(lg->arch.gdt)); 154 fixup_gdt_table(lg, 0, ARRAY_SIZE(lg->arch.gdt));
155 /* Mark that the GDT changed so the core knows it has to copy it again, 155 /* Mark that the GDT changed so the core knows it has to copy it again,
156 * even if the Guest is run on the same CPU. */ 156 * even if the Guest is run on the same CPU. */
@@ -161,7 +161,7 @@ void guest_load_tls(struct lguest *lg, unsigned long gtls)
161{ 161{
162 struct desc_struct *tls = &lg->arch.gdt[GDT_ENTRY_TLS_MIN]; 162 struct desc_struct *tls = &lg->arch.gdt[GDT_ENTRY_TLS_MIN];
163 163
164 lgread(lg, tls, gtls, sizeof(*tls)*GDT_ENTRY_TLS_ENTRIES); 164 __lgread(lg, tls, gtls, sizeof(*tls)*GDT_ENTRY_TLS_ENTRIES);
165 fixup_gdt_table(lg, GDT_ENTRY_TLS_MIN, GDT_ENTRY_TLS_MAX+1); 165 fixup_gdt_table(lg, GDT_ENTRY_TLS_MIN, GDT_ENTRY_TLS_MAX+1);
166 lg->changed |= CHANGED_GDT_TLS; 166 lg->changed |= CHANGED_GDT_TLS;
167} 167}
diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c
index ef976ccb4192..9eed12d5a395 100644
--- a/drivers/lguest/x86/core.c
+++ b/drivers/lguest/x86/core.c
@@ -222,7 +222,7 @@ static int emulate_insn(struct lguest *lg)
222 return 0; 222 return 0;
223 223
224 /* Decoding x86 instructions is icky. */ 224 /* Decoding x86 instructions is icky. */
225 lgread(lg, &insn, physaddr, 1); 225 insn = lgread(lg, physaddr, u8);
226 226
227 /* 0x66 is an "operand prefix". It means it's using the upper 16 bits 227 /* 0x66 is an "operand prefix". It means it's using the upper 16 bits
228 of the eax register. */ 228 of the eax register. */
@@ -230,7 +230,7 @@ static int emulate_insn(struct lguest *lg)
230 shift = 16; 230 shift = 16;
231 /* The instruction is 1 byte so far, read the next byte. */ 231 /* The instruction is 1 byte so far, read the next byte. */
232 insnlen = 1; 232 insnlen = 1;
233 lgread(lg, &insn, physaddr + insnlen, 1); 233 insn = lgread(lg, physaddr + insnlen, u8);
234 } 234 }
235 235
236 /* We can ignore the lower bit for the moment and decode the 4 opcodes 236 /* We can ignore the lower bit for the moment and decode the 4 opcodes