2007-07-19 12:49:23 +04:00
# ifndef _LGUEST_H
# define _LGUEST_H
# ifndef __ASSEMBLY__
# include <linux/types.h>
# include <linux/init.h>
# include <linux/stringify.h>
# include <linux/lguest.h>
# include <linux/lguest_launcher.h>
# include <linux/wait.h>
# include <linux/err.h>
# include <asm/semaphore.h>
2007-10-22 05:03:28 +04:00
# include <asm/lguest.h>
2007-07-19 12:49:23 +04:00
void free_pagetables ( void ) ;
int init_pagetables ( struct page * * switcher_page , unsigned int pages ) ;
struct pgdir
{
2007-10-22 05:03:34 +04:00
unsigned long gpgdir ;
2007-10-22 05:03:33 +04:00
pgd_t * pgdir ;
2007-07-19 12:49:23 +04:00
} ;
/* We have two pages shared with guests, per cpu. */
struct lguest_pages
{
/* This is the stack page mapped rw in guest */
char spare [ PAGE_SIZE - sizeof ( struct lguest_regs ) ] ;
struct lguest_regs regs ;
/* This is the host state & guest descriptor page, ro in guest */
struct lguest_ro_state state ;
} __attribute__ ( ( aligned ( PAGE_SIZE ) ) ) ;
# define CHANGED_IDT 1
# define CHANGED_GDT 2
# define CHANGED_GDT_TLS 4 /* Actually a subset of CHANGED_GDT */
# define CHANGED_ALL 3
2008-01-07 16:05:22 +03:00
struct lguest ;
struct lg_cpu {
unsigned int id ;
struct lguest * lg ;
2008-01-07 16:05:34 +03:00
struct task_struct * tsk ;
struct mm_struct * mm ; /* == tsk->mm, but that becomes NULL on exit */
2008-01-07 16:05:27 +03:00
2008-01-07 16:05:35 +03:00
u32 cr2 ;
int ts ;
u32 esp1 ;
u8 ss1 ;
2008-01-18 00:14:46 +03:00
/* Bitmap of what has changed: see CHANGED_* above. */
int changed ;
2008-01-07 16:05:36 +03:00
unsigned long pending_notify ; /* pfn from LHCALL_NOTIFY */
2008-01-07 16:05:32 +03:00
/* At end of a page shared mapped over lguest_pages in guest. */
unsigned long regs_page ;
struct lguest_regs * regs ;
2008-01-18 00:13:26 +03:00
struct lguest_pages * last_pages ;
2008-01-07 16:05:37 +03:00
int cpu_pgd ; /* which pgd this cpu is currently using */
2008-01-07 16:05:27 +03:00
/* If a hypercall was asked for, this points to the arguments. */
struct hcall_args * hcall ;
u32 next_hcall ;
2008-01-07 16:05:28 +03:00
/* Virtual clock device */
struct hrtimer hrt ;
2008-01-07 16:05:29 +03:00
2008-01-07 16:05:34 +03:00
/* Do we need to stop what we're doing and return to userspace? */
int break_out ;
wait_queue_head_t break_wq ;
int halted ;
2008-01-07 16:05:29 +03:00
/* Pending virtual interrupts */
DECLARE_BITMAP ( irqs_pending , LGUEST_IRQS ) ;
2008-01-07 16:05:33 +03:00
struct lg_cpu_arch arch ;
2008-01-07 16:05:22 +03:00
} ;
2007-07-19 12:49:23 +04:00
/* The private info the thread maintains about the guest. */
struct lguest
{
struct lguest_data __user * lguest_data ;
2008-01-07 16:05:22 +03:00
struct lg_cpu cpus [ NR_CPUS ] ;
unsigned int nr_cpus ;
2007-07-19 12:49:23 +04:00
u32 pfn_limit ;
2007-10-22 05:03:26 +04:00
/* This provides the offset to the base of guest-physical
* memory in the Launcher . */
void __user * mem_base ;
2007-10-22 05:03:36 +04:00
unsigned long kernel_address ;
2007-07-19 12:49:23 +04:00
struct pgdir pgdirs [ 4 ] ;
unsigned long noirq_start , noirq_end ;
unsigned int stack_pages ;
u32 tsc_khz ;
/* Dead? */
const char * dead ;
} ;
extern struct mutex lguest_lock ;
/* core.c: */
int lguest_address_ok ( const struct lguest * lg ,
unsigned long addr , unsigned long len ) ;
2008-01-18 00:19:42 +03:00
void __lgread ( struct lg_cpu * , void * , unsigned long , unsigned ) ;
void __lgwrite ( struct lg_cpu * , unsigned long , const void * , unsigned ) ;
2007-10-22 05:24:24 +04:00
2007-10-25 09:02:50 +04:00
/*H:035 Using memory-copy operations like that is usually inconvient, so we
2007-10-22 05:24:24 +04:00
* have the following helper macros which read and write a specific type ( often
* an unsigned long ) .
*
* This reads into a variable of the given type then returns that . */
2008-01-18 00:19:42 +03:00
# define lgread(cpu, addr, type) \
( { type _v ; __lgread ( ( cpu ) , & _v , ( addr ) , sizeof ( _v ) ) ; _v ; } )
2007-10-22 05:24:24 +04:00
/* This checks that the variable is of the given type, then writes it out. */
2008-01-18 00:19:42 +03:00
# define lgwrite(cpu, addr, type, val) \
2007-10-22 05:24:24 +04:00
do { \
typecheck ( type , val ) ; \
2008-01-18 00:19:42 +03:00
__lgwrite ( ( cpu ) , ( addr ) , & ( val ) , sizeof ( val ) ) ; \
2007-10-22 05:24:24 +04:00
} while ( 0 )
/* (end of memory access helper routines) :*/
2008-01-07 16:05:25 +03:00
int run_guest ( struct lg_cpu * cpu , unsigned long __user * user ) ;
2007-07-19 12:49:23 +04:00
2007-10-22 05:03:33 +04:00
/* Helper macros to obtain the first 12 or the last 20 bits, this is only the
* first step in the migration to the kernel types . pte_pfn is already defined
* in the kernel . */
# define pgd_flags(x) (pgd_val(x) & ~PAGE_MASK)
# define pte_flags(x) (pte_val(x) & ~PAGE_MASK)
# define pgd_pfn(x) (pgd_val(x) >> PAGE_SHIFT)
2007-07-19 12:49:23 +04:00
/* interrupts_and_traps.c: */
2008-01-07 16:05:29 +03:00
void maybe_do_interrupt ( struct lg_cpu * cpu ) ;
int deliver_trap ( struct lg_cpu * cpu , unsigned int num ) ;
2008-01-07 16:05:33 +03:00
void load_guest_idt_entry ( struct lg_cpu * cpu , unsigned int i ,
u32 low , u32 hi ) ;
2008-01-07 16:05:35 +03:00
void guest_set_stack ( struct lg_cpu * cpu , u32 seg , u32 esp , unsigned int pages ) ;
void pin_stack_pages ( struct lg_cpu * cpu ) ;
2007-07-19 12:49:23 +04:00
void setup_default_idt_entries ( struct lguest_ro_state * state ,
const unsigned long * def ) ;
2008-01-07 16:05:33 +03:00
void copy_traps ( const struct lg_cpu * cpu , struct desc_struct * idt ,
2007-07-19 12:49:23 +04:00
const unsigned long * def ) ;
2008-01-07 16:05:28 +03:00
void guest_set_clockevent ( struct lg_cpu * cpu , unsigned long delta ) ;
void init_clockdev ( struct lg_cpu * cpu ) ;
2007-10-22 05:03:35 +04:00
bool check_syscall_vector ( struct lguest * lg ) ;
int init_interrupts ( void ) ;
void free_interrupts ( void ) ;
2007-07-19 12:49:23 +04:00
/* segments.c: */
void setup_default_gdt_entries ( struct lguest_ro_state * state ) ;
2008-01-07 16:05:33 +03:00
void setup_guest_gdt ( struct lg_cpu * cpu ) ;
void load_guest_gdt ( struct lg_cpu * cpu , unsigned long table , u32 num ) ;
void guest_load_tls ( struct lg_cpu * cpu , unsigned long tls_array ) ;
void copy_gdt ( const struct lg_cpu * cpu , struct desc_struct * gdt ) ;
void copy_gdt_tls ( const struct lg_cpu * cpu , struct desc_struct * gdt ) ;
2007-07-19 12:49:23 +04:00
/* page_tables.c: */
int init_guest_pagetable ( struct lguest * lg , unsigned long pgtable ) ;
void free_guest_pagetable ( struct lguest * lg ) ;
2008-01-07 16:05:35 +03:00
void guest_new_pagetable ( struct lg_cpu * cpu , unsigned long pgtable ) ;
2007-10-22 05:03:34 +04:00
void guest_set_pmd ( struct lguest * lg , unsigned long gpgdir , u32 i ) ;
2008-01-07 16:05:35 +03:00
void guest_pagetable_clear_all ( struct lg_cpu * cpu ) ;
2008-01-07 16:05:37 +03:00
void guest_pagetable_flush_user ( struct lg_cpu * cpu ) ;
2008-01-18 00:19:42 +03:00
void guest_set_pte ( struct lg_cpu * cpu , unsigned long gpgdir ,
2007-10-22 05:03:33 +04:00
unsigned long vaddr , pte_t val ) ;
2008-01-07 16:05:30 +03:00
void map_switcher_in_guest ( struct lg_cpu * cpu , struct lguest_pages * pages ) ;
2008-01-07 16:05:37 +03:00
int demand_page ( struct lg_cpu * cpu , unsigned long cr2 , int errcode ) ;
void pin_page ( struct lg_cpu * cpu , unsigned long vaddr ) ;
unsigned long guest_pa ( struct lg_cpu * cpu , unsigned long vaddr ) ;
2008-01-18 00:19:42 +03:00
void page_table_guest_data_init ( struct lg_cpu * cpu ) ;
2007-07-19 12:49:23 +04:00
2007-10-22 05:03:28 +04:00
/* <arch>/core.c: */
void lguest_arch_host_init ( void ) ;
void lguest_arch_host_fini ( void ) ;
2008-01-07 16:05:25 +03:00
void lguest_arch_run_guest ( struct lg_cpu * cpu ) ;
2008-01-07 16:05:27 +03:00
void lguest_arch_handle_trap ( struct lg_cpu * cpu ) ;
int lguest_arch_init_hypercalls ( struct lg_cpu * cpu ) ;
int lguest_arch_do_hcall ( struct lg_cpu * cpu , struct hcall_args * args ) ;
2008-01-07 16:05:32 +03:00
void lguest_arch_setup_regs ( struct lg_cpu * cpu , unsigned long start ) ;
2007-10-22 05:03:28 +04:00
/* <arch>/switcher.S: */
extern char start_switcher_text [ ] , end_switcher_text [ ] , switch_to_guest [ ] ;
2007-07-19 12:49:23 +04:00
/* lguest_user.c: */
int lguest_device_init ( void ) ;
void lguest_device_remove ( void ) ;
/* hypercalls.c: */
2008-01-07 16:05:27 +03:00
void do_hypercalls ( struct lg_cpu * cpu ) ;
2008-01-18 00:19:42 +03:00
void write_timestamp ( struct lg_cpu * cpu ) ;
2007-07-19 12:49:23 +04:00
2007-07-26 21:41:03 +04:00
/*L:035
* Let ' s step aside for the moment , to study one important routine that ' s used
* widely in the Host code .
*
2007-10-25 09:02:50 +04:00
* There are many cases where the Guest can do something invalid , like pass crap
2007-07-26 21:41:03 +04:00
* to a hypercall . Since only the Guest kernel can make hypercalls , it ' s quite
* acceptable to simply terminate the Guest and give the Launcher a nicely
* formatted reason . It ' s also simpler for the Guest itself , which doesn ' t
* need to check most hypercalls for " success " ; if you ' re still running , it
* succeeded .
*
* Once this is called , the Guest will never run again , so most Host code can
* call this then continue as if nothing had happened . This means many
* functions don ' t have to explicitly return an error code , which keeps the
* code simple .
*
* It also means that this can be called more than once : only the first one is
* remembered . The only trick is that we still need to kill the Guest even if
* we can ' t allocate memory to store the reason . Linux has a neat way of
* packing error codes into invalid pointers , so we use that here .
*
* Like any macro which uses an " if " , it is safely wrapped in a run - once " do {
* } while ( 0 ) " .
*/
2008-01-18 00:19:42 +03:00
# define kill_guest(cpu, fmt...) \
2007-07-19 12:49:23 +04:00
do { \
2008-01-18 00:19:42 +03:00
if ( ! ( cpu ) - > lg - > dead ) { \
( cpu ) - > lg - > dead = kasprintf ( GFP_ATOMIC , fmt ) ; \
if ( ! ( cpu ) - > lg - > dead ) \
( cpu ) - > lg - > dead = ERR_PTR ( - ENOMEM ) ; \
2007-07-19 12:49:23 +04:00
} \
} while ( 0 )
2007-07-26 21:41:03 +04:00
/* (End of aside) :*/
2007-07-19 12:49:23 +04:00
# endif /* __ASSEMBLY__ */
# endif /* _LGUEST_H */