2007-07-19 15:49:22 +07:00
|
|
|
#include <linux/linkage.h>
|
|
|
|
#include <linux/lguest.h>
|
|
|
|
#include <asm/asm-offsets.h>
|
|
|
|
#include <asm/thread_info.h>
|
2007-07-20 19:12:56 +07:00
|
|
|
#include <asm/processor-flags.h>
|
2007-07-19 15:49:22 +07:00
|
|
|
|
|
|
|
/*
|
|
|
|
* This is where we begin: we have a magic signature which the launcher looks
|
|
|
|
* for. The plan is that the Linux boot protocol will be extended with a
|
|
|
|
* "platform type" field which will guide us here from the normal entry point,
|
2007-07-19 15:49:23 +07:00
|
|
|
* but for the moment this suffices. We pass the virtual address of the boot
|
|
|
|
* info to lguest_init().
|
2007-07-19 15:49:22 +07:00
|
|
|
*
|
|
|
|
* We put it in .init.text will be discarded after boot.
|
|
|
|
*/
|
|
|
|
.section .init.text, "ax", @progbits
|
|
|
|
.ascii "GenuineLguest"
|
|
|
|
/* Set up initial stack. */
|
|
|
|
movl $(init_thread_union+THREAD_SIZE),%esp
|
2007-07-19 15:49:23 +07:00
|
|
|
movl %esi, %eax
|
|
|
|
addl $__PAGE_OFFSET, %eax
|
2007-07-19 15:49:22 +07:00
|
|
|
jmp lguest_init
|
|
|
|
|
|
|
|
/* The templates for inline patching. */
|
|
|
|
#define LGUEST_PATCH(name, insns...) \
|
|
|
|
lgstart_##name: insns; lgend_##name:; \
|
|
|
|
.globl lgstart_##name; .globl lgend_##name
|
|
|
|
|
|
|
|
LGUEST_PATCH(cli, movl $0, lguest_data+LGUEST_DATA_irq_enabled)
|
|
|
|
LGUEST_PATCH(sti, movl $X86_EFLAGS_IF, lguest_data+LGUEST_DATA_irq_enabled)
|
|
|
|
LGUEST_PATCH(popf, movl %eax, lguest_data+LGUEST_DATA_irq_enabled)
|
|
|
|
LGUEST_PATCH(pushf, movl lguest_data+LGUEST_DATA_irq_enabled, %eax)
|
|
|
|
|
|
|
|
.text
|
|
|
|
/* These demark the EIP range where host should never deliver interrupts. */
|
|
|
|
.global lguest_noirq_start
|
|
|
|
.global lguest_noirq_end
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We move eflags word to lguest_data.irq_enabled to restore interrupt state.
|
|
|
|
* For page faults, gpfs and virtual interrupts, the hypervisor has saved
|
|
|
|
* eflags manually, otherwise it was delivered directly and so eflags reflects
|
|
|
|
* the real machine IF state, ie. interrupts on. Since the kernel always dies
|
|
|
|
* if it takes such a trap with interrupts disabled anyway, turning interrupts
|
|
|
|
* back on unconditionally here is OK.
|
|
|
|
*/
|
|
|
|
ENTRY(lguest_iret)
|
|
|
|
pushl %eax
|
|
|
|
movl 12(%esp), %eax
|
|
|
|
lguest_noirq_start:
|
|
|
|
movl %eax,%ss:lguest_data+LGUEST_DATA_irq_enabled
|
|
|
|
popl %eax
|
|
|
|
iret
|
|
|
|
lguest_noirq_end:
|