ia64/xen-unstable

changeset 8651:71914b64b577

Indirect hypercalls through a hypercall transfer page.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Tue Jan 24 18:05:45 2006 +0100 (2006-01-24)
parents 246b6444c643
children 2b4b1963b76e
files linux-2.6-xen-sparse/arch/xen/i386/kernel/entry.S linux-2.6-xen-sparse/arch/xen/i386/kernel/head.S linux-2.6-xen-sparse/arch/xen/x86_64/kernel/entry.S linux-2.6-xen-sparse/arch/xen/x86_64/kernel/head.S linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c linux-2.6-xen-sparse/include/asm-xen/asm-i386/hypercall.h linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/hypercall.h tools/libxc/xc_linux_build.c tools/libxc/xc_load_elf.c tools/libxc/xg_private.h xen/arch/x86/dom0_ops.c xen/arch/x86/domain_build.c xen/arch/x86/x86_32/traps.c xen/arch/x86/x86_64/traps.c xen/include/asm-x86/domain.h xen/include/public/dom0_ops.h
line diff
     1.1 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/entry.S	Tue Jan 24 17:59:54 2006 +0100
     1.2 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/entry.S	Tue Jan 24 18:05:45 2006 +0100
     1.3 @@ -333,10 +333,8 @@ iret_exc:
     1.4  hypervisor_iret:
     1.5  	andl $~NMI_MASK, EFLAGS(%esp)
     1.6  	RESTORE_REGS
     1.7 -	movl %eax,(%esp)
     1.8 -	movl $__HYPERVISOR_iret,%eax
     1.9 -	int $0x82
    1.10 -	ud2
    1.11 +	addl $4, %esp
    1.12 +	jmp  hypercall_page + (__HYPERVISOR_iret * 32)
    1.13  
    1.14  #if 0 /* XEN */
    1.15  ldt_ss:
     2.1 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/head.S	Tue Jan 24 17:59:54 2006 +0100
     2.2 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/head.S	Tue Jan 24 18:05:45 2006 +0100
     2.3 @@ -5,6 +5,7 @@
     2.4  	.ascii	"GUEST_OS=linux,GUEST_VER=2.6"
     2.5  	.ascii	",XEN_VER=xen-3.0"
     2.6  	.ascii	",VIRT_BASE=0xC0000000"
     2.7 +	.ascii	",HYPERCALL_PAGE=0x104" /* __pa(hypercall_page) >> 12 */
     2.8  #ifdef CONFIG_X86_PAE
     2.9  	.ascii	",PAE=yes"
    2.10  #else
    2.11 @@ -187,6 +188,9 @@ ENTRY(cpu_gdt_table)
    2.12  ENTRY(default_ldt)
    2.13  
    2.14  .org 0x4000
    2.15 +ENTRY(hypercall_page)
    2.16 +
    2.17 +.org 0x5000
    2.18  /*
    2.19   * Real beginning of normal "text" segment
    2.20   */
     3.1 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/entry.S	Tue Jan 24 17:59:54 2006 +0100
     3.2 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/entry.S	Tue Jan 24 18:05:45 2006 +0100
     3.3 @@ -127,15 +127,10 @@
     3.4           *     };
     3.5           * #define VGCF_IN_SYSCALL (1<<8) 
     3.6           */
     3.7 -        .macro HYPERVISOR_IRET flag
     3.8 -        subq $8*4,%rsp                   # reuse rip, cs, rflags, rsp, ss in the stack
     3.9 -        movq %rax,(%rsp)
    3.10 -        movq %r11,1*8(%rsp)
    3.11 -        movq %rcx,2*8(%rsp)              # we saved %rcx upon exceptions
    3.12 -        movq $\flag,3*8(%rsp)
    3.13 -        movq $__HYPERVISOR_iret,%rax
    3.14 -        syscall
    3.15 -        .endm
    3.16 +	.macro HYPERVISOR_IRET flag
    3.17 +	pushq $\flag
    3.18 +	jmp  hypercall_page + (__HYPERVISOR_iret * 32)
    3.19 +	.endm
    3.20  
    3.21          .macro SWITCH_TO_KERNEL ssoff,adjust=0
    3.22  	jc  1f
     4.1 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/head.S	Tue Jan 24 17:59:54 2006 +0100
     4.2 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/head.S	Tue Jan 24 18:05:45 2006 +0100
     4.3 @@ -16,9 +16,11 @@
     4.4  #include <linux/linkage.h>
     4.5  
     4.6  .section __xen_guest
     4.7 -	.ascii	"GUEST_OS=linux,GUEST_VER=2.6,XEN_VER=xen-3.0,VIRT_BASE=0xffffffff80000000"
     4.8 +	.ascii	"GUEST_OS=linux,GUEST_VER=2.6"
     4.9 +	.ascii	",XEN_VER=xen-3.0"
    4.10 +	.ascii	",VIRT_BASE=0xffffffff80000000"
    4.11 +	.ascii	",HYPERCALL_PAGE=0x10d" /* __pa(hypercall_page) >> 12 */
    4.12  	.ascii	",LOADER=generic"
    4.13 -/*	.ascii	",PT_MODE_WRITABLE" */
    4.14  	.byte	0
    4.15                  
    4.16        
    4.17 @@ -227,8 +229,10 @@ ENTRY(empty_bad_pmd_table)
    4.18  ENTRY(level3_physmem_pgt)
    4.19  	.quad	0x0000000000105007		/* -> level2_kernel_pgt (so that __va works even before pagetable_init) */
    4.20  
    4.21 -	
    4.22 -	.org 0xd000
    4.23 +.org 0xd000
    4.24 +ENTRY(hypercall_page)
    4.25 +
    4.26 +.org 0xe000
    4.27  #ifdef CONFIG_ACPI_SLEEP
    4.28  ENTRY(wakeup_level4_pgt)
    4.29  	.quad	0x0000000000102007		/* -> level3_ident_pgt */
     5.1 --- a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c	Tue Jan 24 17:59:54 2006 +0100
     5.2 +++ b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c	Tue Jan 24 18:05:45 2006 +0100
     5.3 @@ -58,7 +58,9 @@ static int privcmd_ioctl(struct inode *i
     5.4  			"movl 16(%%eax),%%esi ;"
     5.5  			"movl 20(%%eax),%%edi ;"
     5.6  			"movl   (%%eax),%%eax ;"
     5.7 -			TRAP_INSTR "; "
     5.8 +			"shll $5,%%eax ;"
     5.9 +			"addl $hypercall_page,%%eax ;"
    5.10 +			"call *%%eax ;"
    5.11  			"popl %%edi; popl %%esi; popl %%edx; "
    5.12  			"popl %%ecx; popl %%ebx"
    5.13  			: "=a" (ret) : "0" (&hypercall) : "memory" );
    5.14 @@ -66,7 +68,10 @@ static int privcmd_ioctl(struct inode *i
    5.15  		{
    5.16  			long ign1, ign2, ign3;
    5.17  			__asm__ __volatile__ (
    5.18 -				"movq %8,%%r10; movq %9,%%r8;" TRAP_INSTR
    5.19 +				"movq %8,%%r10; movq %9,%%r8;"
    5.20 +				"shlq $5,%%rax ;"
    5.21 +				"addq $hypercall_page,%%rax ;"
    5.22 +				"call *%%rax"
    5.23  				: "=a" (ret), "=D" (ign1),
    5.24  				  "=S" (ign2), "=d" (ign3)
    5.25  				: "0" ((unsigned long)hypercall.op), 
    5.26 @@ -75,7 +80,7 @@ static int privcmd_ioctl(struct inode *i
    5.27  				"3" ((unsigned long)hypercall.arg[2]), 
    5.28  				"g" ((unsigned long)hypercall.arg[3]),
    5.29  				"g" ((unsigned long)hypercall.arg[4])
    5.30 -				: "r11","rcx","r8","r10","memory");
    5.31 +				: "r8", "r10", "memory" );
    5.32  		}
    5.33  #elif defined (__ia64__)
    5.34  		__asm__ __volatile__ (
     6.1 --- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/hypercall.h	Tue Jan 24 17:59:54 2006 +0100
     6.2 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/hypercall.h	Tue Jan 24 18:05:45 2006 +0100
     6.3 @@ -34,13 +34,15 @@
     6.4  #include <asm-xen/xen-public/sched.h>
     6.5  #include <asm-xen/xen-public/nmi.h>
     6.6  
     6.7 +#define __STR(x) #x
     6.8 +#define STR(x) __STR(x)
     6.9 +
    6.10  #define _hypercall0(type, name)			\
    6.11  ({						\
    6.12  	long __res;				\
    6.13  	asm volatile (				\
    6.14 -		TRAP_INSTR			\
    6.15 +		"call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
    6.16  		: "=a" (__res)			\
    6.17 -		: "0" (__HYPERVISOR_##name)	\
    6.18  		: "memory" );			\
    6.19  	(type)__res;				\
    6.20  })
    6.21 @@ -49,9 +51,9 @@
    6.22  ({								\
    6.23  	long __res, __ign1;					\
    6.24  	asm volatile (						\
    6.25 -		TRAP_INSTR					\
    6.26 +		"call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
    6.27  		: "=a" (__res), "=b" (__ign1)			\
    6.28 -		: "0" (__HYPERVISOR_##name), "1" ((long)(a1))	\
    6.29 +		: "1" ((long)(a1))				\
    6.30  		: "memory" );					\
    6.31  	(type)__res;						\
    6.32  })
    6.33 @@ -60,10 +62,9 @@
    6.34  ({								\
    6.35  	long __res, __ign1, __ign2;				\
    6.36  	asm volatile (						\
    6.37 -		TRAP_INSTR					\
    6.38 +		"call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
    6.39  		: "=a" (__res), "=b" (__ign1), "=c" (__ign2)	\
    6.40 -		: "0" (__HYPERVISOR_##name), "1" ((long)(a1)),	\
    6.41 -		"2" ((long)(a2))				\
    6.42 +		: "1" ((long)(a1)), "2" ((long)(a2))		\
    6.43  		: "memory" );					\
    6.44  	(type)__res;						\
    6.45  })
    6.46 @@ -72,11 +73,11 @@
    6.47  ({								\
    6.48  	long __res, __ign1, __ign2, __ign3;			\
    6.49  	asm volatile (						\
    6.50 -		TRAP_INSTR					\
    6.51 +		"call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
    6.52  		: "=a" (__res), "=b" (__ign1), "=c" (__ign2), 	\
    6.53  		"=d" (__ign3)					\
    6.54 -		: "0" (__HYPERVISOR_##name), "1" ((long)(a1)),	\
    6.55 -		"2" ((long)(a2)), "3" ((long)(a3))		\
    6.56 +		: "1" ((long)(a1)), "2" ((long)(a2)),		\
    6.57 +		"3" ((long)(a3))				\
    6.58  		: "memory" );					\
    6.59  	(type)__res;						\
    6.60  })
    6.61 @@ -85,12 +86,11 @@
    6.62  ({								\
    6.63  	long __res, __ign1, __ign2, __ign3, __ign4;		\
    6.64  	asm volatile (						\
    6.65 -		TRAP_INSTR					\
    6.66 +		"call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
    6.67  		: "=a" (__res), "=b" (__ign1), "=c" (__ign2),	\
    6.68  		"=d" (__ign3), "=S" (__ign4)			\
    6.69 -		: "0" (__HYPERVISOR_##name), "1" ((long)(a1)),	\
    6.70 -		"2" ((long)(a2)), "3" ((long)(a3)),		\
    6.71 -		"4" ((long)(a4))				\
    6.72 +		: "1" ((long)(a1)), "2" ((long)(a2)),		\
    6.73 +		"3" ((long)(a3)), "4" ((long)(a4))		\
    6.74  		: "memory" );					\
    6.75  	(type)__res;						\
    6.76  })
    6.77 @@ -99,12 +99,12 @@
    6.78  ({								\
    6.79  	long __res, __ign1, __ign2, __ign3, __ign4, __ign5;	\
    6.80  	asm volatile (						\
    6.81 -		TRAP_INSTR					\
    6.82 +		"call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
    6.83  		: "=a" (__res), "=b" (__ign1), "=c" (__ign2),	\
    6.84  		"=d" (__ign3), "=S" (__ign4), "=D" (__ign5)	\
    6.85 -		: "0" (__HYPERVISOR_##name), "1" ((long)(a1)),	\
    6.86 -		"2" ((long)(a2)), "3" ((long)(a3)),		\
    6.87 -		"4" ((long)(a4)), "5" ((long)(a5))		\
    6.88 +		: "1" ((long)(a1)), "2" ((long)(a2)),		\
    6.89 +		"3" ((long)(a3)), "4" ((long)(a4)),		\
    6.90 +		"5" ((long)(a5))				\
    6.91  		: "memory" );					\
    6.92  	(type)__res;						\
    6.93  })
     7.1 --- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/hypercall.h	Tue Jan 24 17:59:54 2006 +0100
     7.2 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/hypercall.h	Tue Jan 24 18:05:45 2006 +0100
     7.3 @@ -37,16 +37,16 @@
     7.4  #include <asm-xen/xen-public/xen.h>
     7.5  #include <asm-xen/xen-public/sched.h>
     7.6  
     7.7 -#define __syscall_clobber "r11","rcx","memory"
     7.8 +#define __STR(x) #x
     7.9 +#define STR(x) __STR(x)
    7.10  
    7.11  #define _hypercall0(type, name)			\
    7.12  ({						\
    7.13  	long __res;				\
    7.14  	asm volatile (				\
    7.15 -		TRAP_INSTR			\
    7.16 +		"call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
    7.17  		: "=a" (__res)			\
    7.18 -		: "0" (__HYPERVISOR_##name)	\
    7.19 -		: __syscall_clobber );		\
    7.20 +		: "memory" );			\
    7.21  	(type)__res;				\
    7.22  })
    7.23  
    7.24 @@ -54,10 +54,10 @@
    7.25  ({								\
    7.26  	long __res, __ign1;					\
    7.27  	asm volatile (						\
    7.28 -		TRAP_INSTR					\
    7.29 +		"call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
    7.30  		: "=a" (__res), "=D" (__ign1)			\
    7.31 -		: "0" (__HYPERVISOR_##name), "1" ((long)(a1))	\
    7.32 -		: __syscall_clobber );				\
    7.33 +		: "1" ((long)(a1))				\
    7.34 +		: "memory" );					\
    7.35  	(type)__res;						\
    7.36  })
    7.37  
    7.38 @@ -65,11 +65,10 @@
    7.39  ({								\
    7.40  	long __res, __ign1, __ign2;				\
    7.41  	asm volatile (						\
    7.42 -		TRAP_INSTR					\
    7.43 +		"call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
    7.44  		: "=a" (__res), "=D" (__ign1), "=S" (__ign2)	\
    7.45 -		: "0" (__HYPERVISOR_##name), "1" ((long)(a1)),	\
    7.46 -		"2" ((long)(a2))				\
    7.47 -		: __syscall_clobber );				\
    7.48 +		: "1" ((long)(a1)), "2" ((long)(a2))		\
    7.49 +		: "memory" );					\
    7.50  	(type)__res;						\
    7.51  })
    7.52  
    7.53 @@ -77,12 +76,12 @@
    7.54  ({								\
    7.55  	long __res, __ign1, __ign2, __ign3;			\
    7.56  	asm volatile (						\
    7.57 -		TRAP_INSTR					\
    7.58 +		"call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
    7.59  		: "=a" (__res), "=D" (__ign1), "=S" (__ign2), 	\
    7.60  		"=d" (__ign3)					\
    7.61 -		: "0" (__HYPERVISOR_##name), "1" ((long)(a1)),	\
    7.62 -		"2" ((long)(a2)), "3" ((long)(a3))		\
    7.63 -		: __syscall_clobber );				\
    7.64 +		: "1" ((long)(a1)), "2" ((long)(a2)),		\
    7.65 +		"3" ((long)(a3))				\
    7.66 +		: "memory" );					\
    7.67  	(type)__res;						\
    7.68  })
    7.69  
    7.70 @@ -90,13 +89,13 @@
    7.71  ({								\
    7.72  	long __res, __ign1, __ign2, __ign3;			\
    7.73  	asm volatile (						\
    7.74 -		"movq %8,%%r10; " TRAP_INSTR			\
    7.75 +		"movq %8,%%r10; "				\
    7.76 +		"call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
    7.77  		: "=a" (__res), "=D" (__ign1), "=S" (__ign2),	\
    7.78  		"=d" (__ign3)					\
    7.79 -		: "0" (__HYPERVISOR_##name), "1" ((long)(a1)),	\
    7.80 -		"2" ((long)(a2)), "3" ((long)(a3)),		\
    7.81 -		"g" ((long)(a4))				\
    7.82 -		: __syscall_clobber, "r10" );			\
    7.83 +		: "1" ((long)(a1)), "2" ((long)(a2)),		\
    7.84 +		"3" ((long)(a3)), "g" ((long)(a4))		\
    7.85 +		: "memory", "r10" );				\
    7.86  	(type)__res;						\
    7.87  })
    7.88  
    7.89 @@ -104,13 +103,14 @@
    7.90  ({								\
    7.91  	long __res, __ign1, __ign2, __ign3;			\
    7.92  	asm volatile (						\
    7.93 -		"movq %8,%%r10; movq %9,%%r8; " TRAP_INSTR	\
    7.94 +		"movq %8,%%r10; movq %9,%%r8; "			\
    7.95 +		"call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
    7.96  		: "=a" (__res), "=D" (__ign1), "=S" (__ign2),	\
    7.97  		"=d" (__ign3)					\
    7.98 -		: "0" (__HYPERVISOR_##name), "1" ((long)(a1)),	\
    7.99 -		"2" ((long)(a2)), "3" ((long)(a3)),		\
   7.100 -		"g" ((long)(a4)), "g" ((long)(a5))		\
   7.101 -		: __syscall_clobber, "r10", "r8" );		\
   7.102 +		: "1" ((long)(a1)), "2" ((long)(a2)),		\
   7.103 +		"3" ((long)(a3)), "g" ((long)(a4)),		\
   7.104 +		"g" ((long)(a5))				\
   7.105 +		: "memory", "r10", "r8" );			\
   7.106  	(type)__res;						\
   7.107  })
   7.108  
     8.1 --- a/tools/libxc/xc_linux_build.c	Tue Jan 24 17:59:54 2006 +0100
     8.2 +++ b/tools/libxc/xc_linux_build.c	Tue Jan 24 18:05:45 2006 +0100
     8.3 @@ -429,10 +429,12 @@ static int setup_guest(int xc_handle,
     8.4                         unsigned int console_evtchn, unsigned long *console_mfn)
     8.5  {
     8.6      unsigned long *page_array = NULL;
     8.7 -    unsigned long count, i;
     8.8 +    unsigned long count, i, hypercall_pfn;
     8.9      start_info_t *start_info;
    8.10      shared_info_t *shared_info;
    8.11      xc_mmu_t *mmu = NULL;
    8.12 +    char *p;
    8.13 +    DECLARE_DOM0_OP;
    8.14      int rc;
    8.15  
    8.16      unsigned long nr_pt_pages;
    8.17 @@ -715,6 +717,20 @@ static int setup_guest(int xc_handle,
    8.18      if ( xc_finish_mmu_updates(xc_handle, mmu) )
    8.19          goto error_out;
    8.20  
    8.21 +    p = strstr(dsi.xen_guest_string, "HYPERCALL_PAGE=");
    8.22 +    if ( p != NULL )
    8.23 +    {
    8.24 +        p += strlen("HYPERCALL_PAGE=");
    8.25 +        hypercall_pfn = strtoul(p, NULL, 16);
    8.26 +        if ( hypercall_pfn >= nr_pages )
    8.27 +            goto error_out;
    8.28 +        op.u.hypercall_init.domain = (domid_t)dom;
    8.29 +        op.u.hypercall_init.mfn    = page_array[hypercall_pfn];
    8.30 +        op.cmd = DOM0_HYPERCALL_INIT;
    8.31 +        if ( xc_dom0_op(xc_handle, &op) )
    8.32 +            goto error_out;
    8.33 +    }
    8.34 +
    8.35      free(mmu);
    8.36      free(page_array);
    8.37  
     9.1 --- a/tools/libxc/xc_load_elf.c	Tue Jan 24 17:59:54 2006 +0100
     9.2 +++ b/tools/libxc/xc_load_elf.c	Tue Jan 24 18:05:45 2006 +0100
     9.3 @@ -120,6 +120,7 @@ static int parseelfimage(char *image,
     9.4  
     9.5          break;
     9.6      }
     9.7 +
     9.8      if ( guestinfo == NULL )
     9.9      {
    9.10  #ifdef __ia64__
    9.11 @@ -130,6 +131,8 @@ static int parseelfimage(char *image,
    9.12  #endif
    9.13      }
    9.14  
    9.15 +    dsi->xen_guest_string = guestinfo;
    9.16 +
    9.17      for ( h = 0; h < ehdr->e_phnum; h++ ) 
    9.18      {
    9.19          phdr = (Elf_Phdr *)(image + ehdr->e_phoff + (h*ehdr->e_phentsize));
    10.1 --- a/tools/libxc/xg_private.h	Tue Jan 24 17:59:54 2006 +0100
    10.2 +++ b/tools/libxc/xg_private.h	Tue Jan 24 18:05:45 2006 +0100
    10.3 @@ -136,6 +136,9 @@ struct domain_setup_info
    10.4      unsigned int  pae_kernel;
    10.5      unsigned long symtab_addr;
    10.6      unsigned long symtab_len;
    10.7 +
    10.8 +    /* __xen_guest info string for convenient loader parsing. */
    10.9 +    char *xen_guest_string;
   10.10  };
   10.11  
   10.12  typedef int (*parseimagefunc)(char *image, unsigned long image_size,
    11.1 --- a/xen/arch/x86/dom0_ops.c	Tue Jan 24 17:59:54 2006 +0100
    11.2 +++ b/xen/arch/x86/dom0_ops.c	Tue Jan 24 18:05:45 2006 +0100
    11.3 @@ -50,9 +50,6 @@ long arch_do_dom0_op(dom0_op_t *op, dom0
    11.4  {
    11.5      long ret = 0;
    11.6  
    11.7 -    if ( !IS_PRIV(current->domain) )
    11.8 -        return -EPERM;
    11.9 -
   11.10      switch ( op->cmd )
   11.11      {
   11.12  
   11.13 @@ -409,6 +406,35 @@ long arch_do_dom0_op(dom0_op_t *op, dom0
   11.14      }
   11.15      break;
   11.16  
   11.17 +    case DOM0_HYPERCALL_INIT:
   11.18 +    {
   11.19 +        struct domain *d; 
   11.20 +        unsigned long mfn = op->u.hypercall_init.mfn;
   11.21 +        void *hypercall_page;
   11.22 +
   11.23 +        ret = -ESRCH;
   11.24 +        if ( unlikely((d = find_domain_by_id(
   11.25 +            op->u.hypercall_init.domain)) == NULL) )
   11.26 +            break;
   11.27 +
   11.28 +        ret = -EACCES;
   11.29 +        if ( !pfn_valid(mfn) ||
   11.30 +             !get_page_and_type(pfn_to_page(mfn), d, PGT_writable_page) )
   11.31 +        {
   11.32 +            put_domain(d);
   11.33 +            break;
   11.34 +        }
   11.35 +
   11.36 +        ret = 0;
   11.37 +
   11.38 +        hypercall_page = map_domain_page(mfn);
   11.39 +        hypercall_page_initialise(hypercall_page);
   11.40 +        unmap_domain_page(hypercall_page);
   11.41 +
   11.42 +        put_domain(d);
   11.43 +    }
   11.44 +    break;
   11.45 +
   11.46      default:
   11.47          ret = -ENOSYS;
   11.48          break;
    12.1 --- a/xen/arch/x86/domain_build.c	Tue Jan 24 17:59:54 2006 +0100
    12.2 +++ b/xen/arch/x86/domain_build.c	Tue Jan 24 18:05:45 2006 +0100
    12.3 @@ -146,6 +146,8 @@ int construct_dom0(struct domain *d,
    12.4      struct pfn_info *page = NULL;
    12.5      start_info_t *si;
    12.6      struct vcpu *v = d->vcpu[0];
    12.7 +    char *p;
    12.8 +    unsigned long hypercall_page;
    12.9  #if defined(__i386__)
   12.10      char *image_start  = (char *)_image_start;  /* use lowmem mappings */
   12.11      char *initrd_start = (char *)_initrd_start; /* use lowmem mappings */
   12.12 @@ -239,7 +241,8 @@ int construct_dom0(struct domain *d,
   12.13                 xen_pae ? "yes" : "no", dom0_pae ? "yes" : "no");
   12.14          return -EINVAL;
   12.15      }
   12.16 -    if (strstr(dsi.xen_section_string, "SHADOW=translate"))
   12.17 +
   12.18 +    if ( strstr(dsi.xen_section_string, "SHADOW=translate") )
   12.19          opt_dom0_translate = 1;
   12.20  
   12.21      /* Align load address to 4MB boundary. */
   12.22 @@ -604,6 +607,23 @@ int construct_dom0(struct domain *d,
   12.23      /* Copy the OS image and free temporary buffer. */
   12.24      (void)loadelfimage(&dsi);
   12.25  
   12.26 +    p = strstr(dsi.xen_section_string, "HYPERCALL_PAGE=");
   12.27 +    if ( p != NULL )
   12.28 +    {
   12.29 +        p += strlen("HYPERCALL_PAGE=");
   12.30 +        hypercall_page = simple_strtoul(p, NULL, 16);
   12.31 +        hypercall_page = dsi.v_start + (hypercall_page << PAGE_SHIFT);
   12.32 +        if ( (hypercall_page < dsi.v_start) || (hypercall_page >= v_end) )
   12.33 +        {
   12.34 +            write_ptbase(current);
   12.35 +            local_irq_enable();
   12.36 +            printk("Invalid HYPERCALL_PAGE field in guest header.\n");
   12.37 +            return -1;
   12.38 +        }
   12.39 +
   12.40 +        hypercall_page_initialise((void *)hypercall_page);
   12.41 +    }
   12.42 +
   12.43      init_domheap_pages(
   12.44          _image_start, (_image_start+image_len+PAGE_SIZE-1) & PAGE_MASK);
   12.45  
    13.1 --- a/xen/arch/x86/x86_32/traps.c	Tue Jan 24 17:59:54 2006 +0100
    13.2 +++ b/xen/arch/x86/x86_32/traps.c	Tue Jan 24 18:05:45 2006 +0100
    13.3 @@ -298,6 +298,33 @@ long do_set_callbacks(unsigned long even
    13.4      return 0;
    13.5  }
    13.6  
    13.7 +void hypercall_page_initialise(void *hypercall_page)
    13.8 +{
    13.9 +    char *p;
   13.10 +    int i;
   13.11 +
   13.12 +    /* Fill in all the transfer points with template machine code. */
   13.13 +    for ( i = 0; i < (PAGE_SIZE / 32); i++ )
   13.14 +    {
   13.15 +        p = (char *)(hypercall_page + (i * 32));
   13.16 +        *(u8  *)(p+ 0) = 0xb8;    /* mov  $<i>,%eax */
   13.17 +        *(u32 *)(p+ 1) = i;
   13.18 +        *(u16 *)(p+ 5) = 0x82cd;  /* int  $0x82 */
   13.19 +        *(u8  *)(p+ 7) = 0xc3;    /* ret */
   13.20 +    }
   13.21 +
   13.22 +    /*
   13.23 +     * HYPERVISOR_iret is special because it doesn't return and expects a 
   13.24 +     * special stack frame. Guests jump at this transfer point instead of 
   13.25 +     * calling it.
   13.26 +     */
   13.27 +    p = (char *)(hypercall_page + (__HYPERVISOR_iret * 32));
   13.28 +    *(u8  *)(p+ 0) = 0x50;    /* push %eax */
   13.29 +    *(u8  *)(p+ 1) = 0xb8;    /* mov  $__HYPERVISOR_iret,%eax */
   13.30 +    *(u32 *)(p+ 2) = __HYPERVISOR_iret;
   13.31 +    *(u16 *)(p+ 6) = 0x82cd;  /* int  $0x82 */
   13.32 +}
   13.33 +
   13.34  /*
   13.35   * Local variables:
   13.36   * mode: C
    14.1 --- a/xen/arch/x86/x86_64/traps.c	Tue Jan 24 17:59:54 2006 +0100
    14.2 +++ b/xen/arch/x86/x86_64/traps.c	Tue Jan 24 18:05:45 2006 +0100
    14.3 @@ -268,6 +268,39 @@ long do_set_callbacks(unsigned long even
    14.4      return 0;
    14.5  }
    14.6  
    14.7 +void hypercall_page_initialise(void *hypercall_page)
    14.8 +{
    14.9 +    char *p;
   14.10 +    int i;
   14.11 +
   14.12 +    /* Fill in all the transfer points with template machine code. */
   14.13 +    for ( i = 0; i < (PAGE_SIZE / 32); i++ )
   14.14 +    {
   14.15 +        p = (char *)(hypercall_page + (i * 32));
   14.16 +        *(u8  *)(p+ 0) = 0x51;    /* push %rcx */
   14.17 +        *(u16 *)(p+ 1) = 0x5341;  /* push %r11 */
   14.18 +        *(u8  *)(p+ 3) = 0xb8;    /* mov  $<i>,%eax */
   14.19 +        *(u32 *)(p+ 4) = i;
   14.20 +        *(u16 *)(p+ 8) = 0x050f;  /* syscall */
   14.21 +        *(u16 *)(p+10) = 0x5b41;  /* pop  %r11 */
   14.22 +        *(u8  *)(p+12) = 0x59;    /* pop  %rcx */
   14.23 +        *(u8  *)(p+13) = 0xc3;    /* ret */
   14.24 +    }
   14.25 +
   14.26 +    /*
   14.27 +     * HYPERVISOR_iret is special because it doesn't return and expects a 
   14.28 +     * special stack frame. Guests jump at this transfer point instead of 
   14.29 +     * calling it.
   14.30 +     */
   14.31 +    p = (char *)(hypercall_page + (__HYPERVISOR_iret * 32));
   14.32 +    *(u8  *)(p+ 0) = 0x50;    /* push %rax */
   14.33 +    *(u8  *)(p+ 1) = 0x51;    /* push %rcx */
   14.34 +    *(u16 *)(p+ 2) = 0x5341;  /* push %r11 */
   14.35 +    *(u8  *)(p+ 4) = 0xb8;    /* mov  $__HYPERVISOR_iret,%eax */
   14.36 +    *(u32 *)(p+ 5) = __HYPERVISOR_iret;
   14.37 +    *(u16 *)(p+ 9) = 0x050f;  /* syscall */
   14.38 +}
   14.39 +
   14.40  /*
   14.41   * Local variables:
   14.42   * mode: C
    15.1 --- a/xen/include/asm-x86/domain.h	Tue Jan 24 17:59:54 2006 +0100
    15.2 +++ b/xen/include/asm-x86/domain.h	Tue Jan 24 18:05:45 2006 +0100
    15.3 @@ -51,6 +51,12 @@ extern void mapcache_init(struct domain 
    15.4  /* x86/64: toggle guest between kernel and user modes. */
    15.5  extern void toggle_guest_mode(struct vcpu *);
    15.6  
    15.7 +/*
    15.8 + * Initialise a hypercall-transfer page. The given pointer must be mapped
    15.9 + * in Xen virtual address space (accesses are not validated or checked).
   15.10 + */
   15.11 +extern void hypercall_page_initialise(void *);
   15.12 +
   15.13  struct arch_domain
   15.14  {
   15.15      l1_pgentry_t *mm_perdomain_pt;
    16.1 --- a/xen/include/public/dom0_ops.h	Tue Jan 24 17:59:54 2006 +0100
    16.2 +++ b/xen/include/public/dom0_ops.h	Tue Jan 24 18:05:45 2006 +0100
    16.3 @@ -425,6 +425,12 @@ typedef struct {
    16.4      uint8_t allow_access;     /* allow (!0) or deny (0) access to range? */
    16.5  } dom0_iomem_permission_t;
    16.6   
    16.7 +#define DOM0_HYPERCALL_INIT   48
    16.8 +typedef struct {
    16.9 +    domid_t  domain;          /* domain to be affected */
   16.10 +    unsigned long mfn;        /* machine frame to be initialised */
   16.11 +} dom0_hypercall_init_t;
   16.12 + 
   16.13  typedef struct {
   16.14      uint32_t cmd;
   16.15      uint32_t interface_version; /* DOM0_INTERFACE_VERSION */
   16.16 @@ -465,6 +471,7 @@ typedef struct {
   16.17          dom0_setdebugging_t      setdebugging;
   16.18          dom0_irq_permission_t    irq_permission;
   16.19          dom0_iomem_permission_t  iomem_permission;
   16.20 +        dom0_hypercall_init_t    hypercall_init;
   16.21          uint8_t                  pad[128];
   16.22      } u;
   16.23  } dom0_op_t;