Rusty Russell | 07ad157 | 2007-07-19 01:49:22 -0700 | [diff] [blame^] | 1 | #include <linux/linkage.h> |
| 2 | #include <linux/lguest.h> |
| 3 | #include <asm/asm-offsets.h> |
| 4 | #include <asm/thread_info.h> |
| 5 | |
| 6 | /* FIXME: Once asm/processor-flags.h goes in, include that */ |
| 7 | #define X86_EFLAGS_IF 0x00000200 |
| 8 | |
| 9 | /* |
| 10 | * This is where we begin: we have a magic signature which the launcher looks |
| 11 | * for. The plan is that the Linux boot protocol will be extended with a |
| 12 | * "platform type" field which will guide us here from the normal entry point, |
| 13 | * but for the moment this suffices. |
| 14 | * |
| 15 | * We put it in .init.text will be discarded after boot. |
| 16 | */ |
| 17 | .section .init.text, "ax", @progbits |
| 18 | .ascii "GenuineLguest" |
| 19 | /* Set up initial stack. */ |
| 20 | movl $(init_thread_union+THREAD_SIZE),%esp |
| 21 | jmp lguest_init |
| 22 | |
| 23 | /* The templates for inline patching. */ |
| 24 | #define LGUEST_PATCH(name, insns...) \ |
| 25 | lgstart_##name: insns; lgend_##name:; \ |
| 26 | .globl lgstart_##name; .globl lgend_##name |
| 27 | |
| 28 | LGUEST_PATCH(cli, movl $0, lguest_data+LGUEST_DATA_irq_enabled) |
| 29 | LGUEST_PATCH(sti, movl $X86_EFLAGS_IF, lguest_data+LGUEST_DATA_irq_enabled) |
| 30 | LGUEST_PATCH(popf, movl %eax, lguest_data+LGUEST_DATA_irq_enabled) |
| 31 | LGUEST_PATCH(pushf, movl lguest_data+LGUEST_DATA_irq_enabled, %eax) |
| 32 | |
| 33 | .text |
| 34 | /* These demark the EIP range where host should never deliver interrupts. */ |
| 35 | .global lguest_noirq_start |
| 36 | .global lguest_noirq_end |
| 37 | |
| 38 | /* |
| 39 | * We move eflags word to lguest_data.irq_enabled to restore interrupt state. |
| 40 | * For page faults, gpfs and virtual interrupts, the hypervisor has saved |
| 41 | * eflags manually, otherwise it was delivered directly and so eflags reflects |
| 42 | * the real machine IF state, ie. interrupts on. Since the kernel always dies |
| 43 | * if it takes such a trap with interrupts disabled anyway, turning interrupts |
| 44 | * back on unconditionally here is OK. |
| 45 | */ |
| 46 | ENTRY(lguest_iret) |
| 47 | pushl %eax |
| 48 | movl 12(%esp), %eax |
| 49 | lguest_noirq_start: |
| 50 | movl %eax,%ss:lguest_data+LGUEST_DATA_irq_enabled |
| 51 | popl %eax |
| 52 | iret |
| 53 | lguest_noirq_end: |