Like the system call in Linux, XEN also offer this mechanism named HYPERCALL, hypercall page is a memory page which store the hypercall code, every hypercall
code segment should not larger than 32B, every hypercall has a number to identify
itself, so use this number we can locate the hypercall code segment in the
hypercall page, such as the number is 13, ok , the code segment address is:
address = hypercall_page + 13*32
In this document we will talk about the process of how to establish the hypercall page,
so we can comprehend the hypercall.
In the source of xen we can find the function named: hypercall_page_initialise:
- //xen/arch/x86/x86_32/traps.c
-
void hypercall_page_initialise(struct domain *d, void *hypercall_page)
-
{
-
memset(hypercall_page, 0xCC, PAGE_SIZE);
-
if ( is_hvm_domain(d) )
-
hvm_hypercall_page_initialise(d, hypercall_page);
-
else if ( supervisor_mode_kernel )
-
hypercall_page_initialise_ring0_kernel(hypercall_page);
-
else
-
hypercall_page_initialise_ring1_kernel(hypercall_page);
-
}
According to the parameter this function to initialize the hypercall_page separately,
we'll not analyse it at present, at first, we will see who call this function, from
the source code, there are two branch:
1:--->libxl_create_xenpv_qemu--->libxl_create_device_model
--->libxl_create_stubdom--->libxl_domain_build
--->build_pv--->xc_dom_linux_build--->xc_linux_build_internal--->xc_dom_boot_image
--->(./tools/libxc/xc_dom_boot.c)setup_hypercall_page--->do_domctl
--->arch_do_domctl(XEN_DOMCTL_hypercall_init)--->hypercall_page_initialise
2:xen/arch/x86/boot/x86_32.S -->__start_xen--->construct_dom0--->hypercall_page_initialise
From the call path, we can know the first call path was called when XEN want to create
a domU, while the second was called when the dom0 was created.
Secondly, let's analyse the hypercall_page_initialise itself. The first branch is for HVM domU.
hvm_hypercall_page_initialise(d, hypercall_page);
- xen/arch/x86/hvm/hvm.c
- /* Initialise a hypercall transfer page for a VMX domain using paravirtualised drivers. */
-
void hvm_hypercall_page_initialise(struct domain *d,
-
void *hypercall_page)
-
{
-
hvm_latch_shinfo_size(d);
-
hvm_funcs.init_hypercall_page(d, hypercall_page);
-
}
./xen/arch/x86/cpu/intel.c
__start_xen--->early_cpu_init--->intel_cpu_init--->init_intel--->start_vmx--->hvm_enable(set up the hvm_function_table, in this
struct, there is an init_hypercall_page function, in this context that is
initialized with vmx_init_hypercall_page):
- //one of the implementation of init_hypercall_page
- static void vmx_init_hypercall_page(struct domain *d, void *hypercall_page)
- {
- char *p;
- int i;
- for ( i = 0; i < (PAGE_SIZE / 32); i++ )
- {
- p = (char *)(hypercall_page + (i * 32));
- *(u8 *)(p + 0) = 0xb8; /* mov imm32, %eax */
- *(u32 *)(p + 1) = i;
- *(u8 *)(p + 5) = 0x0f; /* vmcall */
- *(u8 *)(p + 6) = 0x01;
- *(u8 *)(p + 7) = 0xc1;
- *(u8 *)(p + 8) = 0xc3; /* ret */
- }
- /* Don't support HYPERVISOR_iret at the moment */
- *(u16 *)(hypercall_page + (__HYPERVISOR_iret * 32)) = 0x0b0f; /* ud2 */
- }
阅读(914) | 评论(1) | 转发(0) |