Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-for-linus

* git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-for-linus:
lguest: stop using KVM hypercall mechanism
lguest: workaround cmpxchg8b_emu by ignoring cli in the guest.

+68 -40
+23 -6
arch/x86/include/asm/lguest_hcall.h
··· 28 28 29 29 #ifndef __ASSEMBLY__ 30 30 #include <asm/hw_irq.h> 31 - #include <asm/kvm_para.h> 32 31 33 32 /*G:030 34 33 * But first, how does our Guest contact the Host to ask for privileged 35 34 * operations? There are two ways: the direct way is to make a "hypercall", 36 35 * to make requests of the Host Itself. 37 36 * 38 - * We use the KVM hypercall mechanism, though completely different hypercall 39 - * numbers. Seventeen hypercalls are available: the hypercall number is put in 40 - * the %eax register, and the arguments (when required) are placed in %ebx, 41 - * %ecx, %edx and %esi. If a return value makes sense, it's returned in %eax. 37 + * Our hypercall mechanism uses the highest unused trap code (traps 32 and 38 + * above are used by real hardware interrupts). Seventeen hypercalls are 39 + * available: the hypercall number is put in the %eax register, and the 40 + * arguments (when required) are placed in %ebx, %ecx, %edx and %esi. 41 + * If a return value makes sense, it's returned in %eax. 42 42 * 43 43 * Grossly invalid calls result in Sudden Death at the hands of the vengeful 44 44 * Host, rather than returning failure. This reflects Winston Churchill's 45 45 * definition of a gentleman: "someone who is only rude intentionally". 46 - :*/ 46 + */ 47 + static inline unsigned long 48 + hcall(unsigned long call, 49 + unsigned long arg1, unsigned long arg2, unsigned long arg3, 50 + unsigned long arg4) 51 + { 52 + /* "int" is the Intel instruction to trigger a trap. */ 53 + asm volatile("int $" __stringify(LGUEST_TRAP_ENTRY) 54 + /* The call in %eax (aka "a") might be overwritten */ 55 + : "=a"(call) 56 + /* The arguments are in %eax, %ebx, %ecx, %edx & %esi */ 57 + : "a"(call), "b"(arg1), "c"(arg2), "d"(arg3), "S"(arg4) 58 + /* "memory" means this might write somewhere in memory. 59 + * This isn't true for all calls, but it's safe to tell 60 + * gcc that it might happen so it doesn't get clever. */ 61 + : "memory"); 62 + return call; 63 + } 47 64 48 65 /* Can't use our min() macro here: needs to be a constant */ 49 66 #define LGUEST_IRQS (NR_IRQS < 32 ? NR_IRQS: 32)
+30 -31
arch/x86/lguest/boot.c
··· 115 115 local_irq_save(flags); 116 116 if (lguest_data.hcall_status[next_call] != 0xFF) { 117 117 /* Table full, so do normal hcall which will flush table. */ 118 - kvm_hypercall4(call, arg1, arg2, arg3, arg4); 118 + hcall(call, arg1, arg2, arg3, arg4); 119 119 } else { 120 120 lguest_data.hcalls[next_call].arg0 = call; 121 121 lguest_data.hcalls[next_call].arg1 = arg1; ··· 145 145 * So, when we're in lazy mode, we call async_hcall() to store the call for 146 146 * future processing: 147 147 */ 148 - static void lazy_hcall1(unsigned long call, 149 - unsigned long arg1) 148 + static void lazy_hcall1(unsigned long call, unsigned long arg1) 150 149 { 151 150 if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) 152 - kvm_hypercall1(call, arg1); 151 + hcall(call, arg1, 0, 0, 0); 153 152 else 154 153 async_hcall(call, arg1, 0, 0, 0); 155 154 } 156 155 157 156 /* You can imagine what lazy_hcall2, 3 and 4 look like. :*/ 158 157 static void lazy_hcall2(unsigned long call, 159 - unsigned long arg1, 160 - unsigned long arg2) 158 + unsigned long arg1, 159 + unsigned long arg2) 161 160 { 162 161 if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) 163 - kvm_hypercall2(call, arg1, arg2); 162 + hcall(call, arg1, arg2, 0, 0); 164 163 else 165 164 async_hcall(call, arg1, arg2, 0, 0); 166 165 } 167 166 168 167 static void lazy_hcall3(unsigned long call, 169 - unsigned long arg1, 170 - unsigned long arg2, 171 - unsigned long arg3) 168 + unsigned long arg1, 169 + unsigned long arg2, 170 + unsigned long arg3) 172 171 { 173 172 if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) 174 - kvm_hypercall3(call, arg1, arg2, arg3); 173 + hcall(call, arg1, arg2, arg3, 0); 175 174 else 176 175 async_hcall(call, arg1, arg2, arg3, 0); 177 176 } 178 177 179 178 #ifdef CONFIG_X86_PAE 180 179 static void lazy_hcall4(unsigned long call, 181 - unsigned long arg1, 182 - unsigned long arg2, 183 - unsigned long arg3, 184 - unsigned long arg4) 180 + unsigned long arg1, 181 + unsigned long arg2, 182 + unsigned long arg3, 183 + unsigned long arg4) 185 184 { 186 185 if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) 187 - kvm_hypercall4(call, arg1, arg2, arg3, arg4); 186 + hcall(call, arg1, arg2, arg3, arg4); 188 187 else 189 188 async_hcall(call, arg1, arg2, arg3, arg4); 190 189 } ··· 195 196 :*/ 196 197 static void lguest_leave_lazy_mmu_mode(void) 197 198 { 198 - kvm_hypercall0(LHCALL_FLUSH_ASYNC); 199 + hcall(LHCALL_FLUSH_ASYNC, 0, 0, 0, 0); 199 200 paravirt_leave_lazy_mmu(); 200 201 } 201 202 202 203 static void lguest_end_context_switch(struct task_struct *next) 203 204 { 204 - kvm_hypercall0(LHCALL_FLUSH_ASYNC); 205 + hcall(LHCALL_FLUSH_ASYNC, 0, 0, 0, 0); 205 206 paravirt_end_context_switch(next); 206 207 } 207 208 ··· 285 286 /* Keep the local copy up to date. */ 286 287 native_write_idt_entry(dt, entrynum, g); 287 288 /* Tell Host about this new entry. */ 288 - kvm_hypercall3(LHCALL_LOAD_IDT_ENTRY, entrynum, desc[0], desc[1]); 289 + hcall(LHCALL_LOAD_IDT_ENTRY, entrynum, desc[0], desc[1], 0); 289 290 } 290 291 291 292 /* ··· 299 300 struct desc_struct *idt = (void *)desc->address; 300 301 301 302 for (i = 0; i < (desc->size+1)/8; i++) 302 - kvm_hypercall3(LHCALL_LOAD_IDT_ENTRY, i, idt[i].a, idt[i].b); 303 + hcall(LHCALL_LOAD_IDT_ENTRY, i, idt[i].a, idt[i].b, 0); 303 304 } 304 305 305 306 /* ··· 320 321 struct desc_struct *gdt = (void *)desc->address; 321 322 322 323 for (i = 0; i < (desc->size+1)/8; i++) 323 - kvm_hypercall3(LHCALL_LOAD_GDT_ENTRY, i, gdt[i].a, gdt[i].b); 324 + hcall(LHCALL_LOAD_GDT_ENTRY, i, gdt[i].a, gdt[i].b, 0); 324 325 } 325 326 326 327 /* ··· 333 334 { 334 335 native_write_gdt_entry(dt, entrynum, desc, type); 335 336 /* Tell Host about this new entry. */ 336 - kvm_hypercall3(LHCALL_LOAD_GDT_ENTRY, entrynum, 337 - dt[entrynum].a, dt[entrynum].b); 337 + hcall(LHCALL_LOAD_GDT_ENTRY, entrynum, 338 + dt[entrynum].a, dt[entrynum].b, 0); 338 339 } 339 340 340 341 /* ··· 930 931 } 931 932 932 933 /* Please wake us this far in the future. */ 933 - kvm_hypercall1(LHCALL_SET_CLOCKEVENT, delta); 934 + hcall(LHCALL_SET_CLOCKEVENT, delta, 0, 0, 0); 934 935 return 0; 935 936 } 936 937 ··· 941 942 case CLOCK_EVT_MODE_UNUSED: 942 943 case CLOCK_EVT_MODE_SHUTDOWN: 943 944 /* A 0 argument shuts the clock down. */ 944 - kvm_hypercall0(LHCALL_SET_CLOCKEVENT); 945 + hcall(LHCALL_SET_CLOCKEVENT, 0, 0, 0, 0); 945 946 break; 946 947 case CLOCK_EVT_MODE_ONESHOT: 947 948 /* This is what we expect. */ ··· 1099 1100 /* STOP! Until an interrupt comes in. */ 1100 1101 static void lguest_safe_halt(void) 1101 1102 { 1102 - kvm_hypercall0(LHCALL_HALT); 1103 + hcall(LHCALL_HALT, 0, 0, 0, 0); 1103 1104 } 1104 1105 1105 1106 /* ··· 1111 1112 */ 1112 1113 static void lguest_power_off(void) 1113 1114 { 1114 - kvm_hypercall2(LHCALL_SHUTDOWN, __pa("Power down"), 1115 - LGUEST_SHUTDOWN_POWEROFF); 1115 + hcall(LHCALL_SHUTDOWN, __pa("Power down"), 1116 + LGUEST_SHUTDOWN_POWEROFF, 0, 0); 1116 1117 } 1117 1118 1118 1119 /* ··· 1122 1123 */ 1123 1124 static int lguest_panic(struct notifier_block *nb, unsigned long l, void *p) 1124 1125 { 1125 - kvm_hypercall2(LHCALL_SHUTDOWN, __pa(p), LGUEST_SHUTDOWN_POWEROFF); 1126 + hcall(LHCALL_SHUTDOWN, __pa(p), LGUEST_SHUTDOWN_POWEROFF, 0, 0); 1126 1127 /* The hcall won't return, but to keep gcc happy, we're "done". */ 1127 1128 return NOTIFY_DONE; 1128 1129 } ··· 1161 1162 len = sizeof(scratch) - 1; 1162 1163 scratch[len] = '\0'; 1163 1164 memcpy(scratch, buf, len); 1164 - kvm_hypercall1(LHCALL_NOTIFY, __pa(scratch)); 1165 + hcall(LHCALL_NOTIFY, __pa(scratch), 0, 0, 0); 1165 1166 1166 1167 /* This routine returns the number of bytes actually written. */ 1167 1168 return len; ··· 1173 1174 */ 1174 1175 static void lguest_restart(char *reason) 1175 1176 { 1176 - kvm_hypercall2(LHCALL_SHUTDOWN, __pa(reason), LGUEST_SHUTDOWN_RESTART); 1177 + hcall(LHCALL_SHUTDOWN, __pa(reason), LGUEST_SHUTDOWN_RESTART, 0, 0); 1177 1178 } 1178 1179 1179 1180 /*G:050
+1 -1
arch/x86/lguest/i386_head.S
··· 32 32 */ 33 33 movl $LHCALL_LGUEST_INIT, %eax 34 34 movl $lguest_data - __PAGE_OFFSET, %ebx 35 - .byte 0x0f,0x01,0xc1 /* KVM_HYPERCALL */ 35 + int $LGUEST_TRAP_ENTRY 36 36 37 37 /* Set up the initial stack so we can run C code. */ 38 38 movl $(init_thread_union+THREAD_SIZE),%esp
+2 -2
drivers/lguest/lguest_device.c
··· 178 178 179 179 /* We set the status. */ 180 180 to_lgdev(vdev)->desc->status = status; 181 - kvm_hypercall1(LHCALL_NOTIFY, (max_pfn << PAGE_SHIFT) + offset); 181 + hcall(LHCALL_NOTIFY, (max_pfn << PAGE_SHIFT) + offset, 0, 0, 0); 182 182 } 183 183 184 184 static void lg_set_status(struct virtio_device *vdev, u8 status) ··· 229 229 */ 230 230 struct lguest_vq_info *lvq = vq->priv; 231 231 232 - kvm_hypercall1(LHCALL_NOTIFY, lvq->config.pfn << PAGE_SHIFT); 232 + hcall(LHCALL_NOTIFY, lvq->config.pfn << PAGE_SHIFT, 0, 0, 0); 233 233 } 234 234 235 235 /* An extern declaration inside a C file is bad form. Don't do it. */
+12
drivers/lguest/x86/core.c
··· 288 288 insn = lgread(cpu, physaddr, u8); 289 289 290 290 /* 291 + * Around 2.6.33, the kernel started using an emulation for the 292 + * cmpxchg8b instruction in early boot on many configurations. This 293 + * code isn't paravirtualized, and it tries to disable interrupts. 294 + * Ignore it, which will Mostly Work. 295 + */ 296 + if (insn == 0xfa) { 297 + /* "cli", or Clear Interrupt Enable instruction. Skip it. */ 298 + cpu->regs->eip++; 299 + return 1; 300 + } 301 + 302 + /* 291 303 * 0x66 is an "operand prefix". It means it's using the upper 16 bits 292 304 * of the eax register. 293 305 */