diff options
Diffstat (limited to 'drivers/lguest/lguest_asm.S')
-rw-r--r-- | drivers/lguest/lguest_asm.S | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/drivers/lguest/lguest_asm.S b/drivers/lguest/lguest_asm.S new file mode 100644 index 000000000000..5ac3d20bb184 --- /dev/null +++ b/drivers/lguest/lguest_asm.S | |||
@@ -0,0 +1,53 @@ | |||
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: | ||