Move construct_vmcs to arch_vmx_do_launch.

Currently, since VMX guest is brought up by xen0, construct_vmcs is
executed in xen0 hypervisor context, this is not reasonable.  This=20
patch moves construct_vmcs to arch_vmx_do_launch.

Signed-off-by: Xin Li <xin.b.li@intel.com>
Signed-off-by: Yunhong Jiang <yunhong.jiang@intel.com>
Signed-off-by: Nakajima Jun <nakajima.jun@intel.com>
This commit is contained in:
kaf24@firebug.cl.cam.ac.uk committed 2005-10-07 11:00:56 +01:00
1 parent f16cb294c5
commit 88e2b02038
5 files changed
+116 -154

No files matched your search

+5 -67
View File
@@ -323,47 +323,16 @@ void vcpu_migrate_cpu(struct vcpu *v, int newcpu)
#ifdef CONFIG_VMX
static int vmx_switch_on;
static int vmx_final_setup_guest(
struct vcpu *v, struct vcpu_guest_context *ctxt)
static void vmx_final_setup_guest(struct vcpu *v)
{
int error;
struct cpu_user_regs *regs;
struct vmcs_struct *vmcs;
regs = &ctxt->user_regs;
/*
* Create a new VMCS
*/
if (!(vmcs = alloc_vmcs())) {
printk("Failed to create a new VMCS\n");
return -ENOMEM;
}
memset(&v->arch.arch_vmx, 0, sizeof (struct arch_vmx_struct));
v->arch.arch_vmx.vmcs = vmcs;
error = construct_vmcs(
&v->arch.arch_vmx, regs, ctxt, VMCS_USE_HOST_ENV);
if ( error < 0 )
{
printk("Failed to construct a new VMCS\n");
goto out;
}
v->arch.schedule_tail = arch_vmx_do_launch;
#if defined (__i386__)
v->domain->arch.vmx_platform.real_mode_data =
(unsigned long *) regs->esi;
#endif
if (v == v->domain->vcpu[0]) {
/*
/*
* Required to do this once per domain
* XXX todo: add a seperate function to do these.
*/
memset(&v->domain->shared_info->evtchn_mask[0], 0xff,
memset(&v->domain->shared_info->evtchn_mask[0], 0xff,
sizeof(v->domain->shared_info->evtchn_mask));
/* Put the domain in shadow mode even though we're going to be using
@@ -375,23 +344,6 @@ static int vmx_final_setup_guest(
if (!vmx_switch_on)
vmx_switch_on = 1;
return 0;
out:
free_vmcs(vmcs);
if(v->arch.arch_vmx.io_bitmap_a != 0) {
free_xenheap_pages(
v->arch.arch_vmx.io_bitmap_a, get_order_from_bytes(0x1000));
v->arch.arch_vmx.io_bitmap_a = 0;
}
if(v->arch.arch_vmx.io_bitmap_b != 0) {
free_xenheap_pages(
v->arch.arch_vmx.io_bitmap_b, get_order_from_bytes(0x1000));
v->arch.arch_vmx.io_bitmap_b = 0;
}
v->arch.arch_vmx.vmcs = 0;
return error;
}
#endif
@@ -480,8 +432,7 @@ int arch_set_info_guest(
if ( !pagetable_get_paddr(d->arch.phys_table) )
d->arch.phys_table = v->arch.guest_table;
if ( (rc = vmx_final_setup_guest(v, c)) != 0 )
return rc;
vmx_final_setup_guest(v);
}
update_pagetables(v);
@@ -968,20 +919,7 @@ static void vmx_relinquish_resources(struct vcpu *v)
if ( !VMX_DOMAIN(v) )
return;
BUG_ON(v->arch.arch_vmx.vmcs == NULL);
free_vmcs(v->arch.arch_vmx.vmcs);
if(v->arch.arch_vmx.io_bitmap_a != 0) {
free_xenheap_pages(
v->arch.arch_vmx.io_bitmap_a, get_order_from_bytes(0x1000));
v->arch.arch_vmx.io_bitmap_a = 0;
}
if(v->arch.arch_vmx.io_bitmap_b != 0) {
free_xenheap_pages(
v->arch.arch_vmx.io_bitmap_b, get_order_from_bytes(0x1000));
v->arch.arch_vmx.io_bitmap_b = 0;
}
v->arch.arch_vmx.vmcs = 0;
destroy_vmcs(&v->arch.arch_vmx);
free_monitor_pagetable(v);
rem_ac_timer(&v->domain->arch.vmx_platform.vmx_pit.pit_timer);
}
-2
View File
@@ -47,8 +47,6 @@
int hvm_enabled;
#ifdef CONFIG_VMX
int vmcs_size;
unsigned int opt_vmx_debug_level = 0;
integer_param("vmx_debug", opt_vmx_debug_level);
+106 -74
View File
@@ -37,6 +37,8 @@
#endif
#ifdef CONFIG_VMX
int vmcs_size;
struct vmcs_struct *alloc_vmcs(void)
{
struct vmcs_struct *vmcs;
@@ -51,7 +53,7 @@ struct vmcs_struct *alloc_vmcs(void)
return vmcs;
}
void free_vmcs(struct vmcs_struct *vmcs)
static void free_vmcs(struct vmcs_struct *vmcs)
{
int order;
@@ -59,6 +61,28 @@ void free_vmcs(struct vmcs_struct *vmcs)
free_xenheap_pages(vmcs, order);
}
static int load_vmcs(struct arch_vmx_struct *arch_vmx, u64 phys_ptr)
{
int error;
if ((error = __vmptrld(phys_ptr))) {
clear_bit(ARCH_VMX_VMCS_LOADED, &arch_vmx->flags);
return error;
}
set_bit(ARCH_VMX_VMCS_LOADED, &arch_vmx->flags);
return 0;
}
#if 0
static int store_vmcs(struct arch_vmx_struct *arch_vmx, u64 phys_ptr)
{
/* take the current VMCS */
__vmptrst(phys_ptr);
clear_bit(ARCH_VMX_VMCS_LOADED, &arch_vmx->flags);
return 0;
}
#endif
static inline int construct_vmcs_controls(struct arch_vmx_struct *arch_vmx)
{
int error = 0;
@@ -118,7 +142,7 @@ struct host_execution_env {
#endif
};
static void vmx_setup_platform(struct vcpu *v, struct cpu_user_regs *regs)
static void vmx_setup_platform(struct vcpu *v)
{
int i;
unsigned char e820_map_nr;
@@ -161,9 +185,6 @@ static void vmx_setup_platform(struct vcpu *v, struct cpu_user_regs *regs)
}
unmap_domain_page(p);
if (v->vcpu_id)
return;
/* Initialise shared page */
mpfn = get_mfn_from_pfn(gpfn);
if (mpfn == INVALID_MFN) {
@@ -184,7 +205,7 @@ static void vmx_setup_platform(struct vcpu *v, struct cpu_user_regs *regs)
&v->domain->shared_info->evtchn_mask[0]);
}
void vmx_set_host_env(struct vcpu *v)
static void vmx_set_host_env(struct vcpu *v)
{
unsigned int tr, cpu, error = 0;
struct host_execution_env host_env;
@@ -209,14 +230,13 @@ void vmx_set_host_env(struct vcpu *v)
error |= __vmwrite(HOST_TR_BASE, host_env.tr_base);
}
void vmx_do_launch(struct vcpu *v)
static void vmx_do_launch(struct vcpu *v)
{
/* Update CR3, GDT, LDT, TR */
unsigned int error = 0;
unsigned long pfn = 0;
unsigned long cr0, cr4;
struct pfn_info *page;
struct cpu_user_regs *regs = guest_cpu_user_regs();
__asm__ __volatile__ ("mov %%cr0,%0" : "=r" (cr0) : );
@@ -246,7 +266,7 @@ void vmx_do_launch(struct vcpu *v)
page = (struct pfn_info *) alloc_domheap_page(NULL);
pfn = (unsigned long) (page - frame_table);
vmx_setup_platform(v, regs);
vmx_setup_platform(v);
vmx_set_host_env(v);
@@ -267,8 +287,7 @@ void vmx_do_launch(struct vcpu *v)
/*
* Initially set the same environement as host.
*/
static inline int
construct_init_vmcs_guest(struct cpu_user_regs *regs)
static inline int construct_init_vmcs_guest(cpu_user_regs_t *regs)
{
int error = 0;
union vmcs_arbytes arbytes;
@@ -374,34 +393,33 @@ construct_init_vmcs_guest(struct cpu_user_regs *regs)
return error;
}
static inline int construct_vmcs_host(struct host_execution_env *host_env)
static inline int construct_vmcs_host()
{
int error = 0;
#ifdef __x86_64__
unsigned long fs_base;
unsigned long gs_base;
#endif
unsigned long crn;
/* Host Selectors */
host_env->ds_selector = __HYPERVISOR_DS;
error |= __vmwrite(HOST_ES_SELECTOR, host_env->ds_selector);
error |= __vmwrite(HOST_SS_SELECTOR, host_env->ds_selector);
error |= __vmwrite(HOST_DS_SELECTOR, host_env->ds_selector);
error |= __vmwrite(HOST_ES_SELECTOR, __HYPERVISOR_DS);
error |= __vmwrite(HOST_SS_SELECTOR, __HYPERVISOR_DS);
error |= __vmwrite(HOST_DS_SELECTOR, __HYPERVISOR_DS);
#if defined (__i386__)
error |= __vmwrite(HOST_FS_SELECTOR, host_env->ds_selector);
error |= __vmwrite(HOST_GS_SELECTOR, host_env->ds_selector);
error |= __vmwrite(HOST_FS_BASE, host_env->ds_base);
error |= __vmwrite(HOST_GS_BASE, host_env->ds_base);
error |= __vmwrite(HOST_FS_SELECTOR, __HYPERVISOR_DS);
error |= __vmwrite(HOST_GS_SELECTOR, __HYPERVISOR_DS);
error |= __vmwrite(HOST_FS_BASE, 0);
error |= __vmwrite(HOST_GS_BASE, 0);
#else
rdmsrl(MSR_FS_BASE, host_env->fs_base);
rdmsrl(MSR_GS_BASE, host_env->gs_base);
error |= __vmwrite(HOST_FS_BASE, host_env->fs_base);
error |= __vmwrite(HOST_GS_BASE, host_env->gs_base);
rdmsrl(MSR_FS_BASE, fs_base);
rdmsrl(MSR_GS_BASE, gs_base);
error |= __vmwrite(HOST_FS_BASE, fs_base);
error |= __vmwrite(HOST_GS_BASE, gs_base);
#endif
host_env->cs_selector = __HYPERVISOR_CS;
error |= __vmwrite(HOST_CS_SELECTOR, host_env->cs_selector);
host_env->ds_base = 0;
host_env->cs_base = 0;
error |= __vmwrite(HOST_CS_SELECTOR, __HYPERVISOR_CS);
__asm__ __volatile__ ("mov %%cr0,%0" : "=r" (crn) : );
error |= __vmwrite(HOST_CR0, crn); /* same CR0 */
@@ -423,55 +441,58 @@ static inline int construct_vmcs_host(struct host_execution_env *host_env)
/*
* Need to extend to support full virtualization.
* The variable use_host_env indicates if the new VMCS needs to use
* the same setups as the host has (xenolinux).
*/
int construct_vmcs(struct arch_vmx_struct *arch_vmx,
struct cpu_user_regs *regs,
struct vcpu_guest_context *ctxt,
int use_host_env)
static int construct_vmcs(struct arch_vmx_struct *arch_vmx,
cpu_user_regs_t *regs)
{
int error;
long rc;
u64 vmcs_phys_ptr;
struct host_execution_env host_env;
if (use_host_env != VMCS_USE_HOST_ENV)
return -EINVAL;
memset(&host_env, 0, sizeof(struct host_execution_env));
memset(arch_vmx, 0, sizeof(struct arch_vmx_struct));
/*
* Create a new VMCS
*/
if (!(arch_vmx->vmcs = alloc_vmcs())) {
printk("Failed to create a new VMCS\n");
rc = -ENOMEM;
goto err_out;
}
vmcs_phys_ptr = (u64) virt_to_phys(arch_vmx->vmcs);
if ((error = __vmpclear (vmcs_phys_ptr))) {
if ((error = __vmpclear(vmcs_phys_ptr))) {
printk("construct_vmcs: VMCLEAR failed\n");
return -EINVAL;
rc = -EINVAL;
goto err_out;
}
if ((error = load_vmcs(arch_vmx, vmcs_phys_ptr))) {
printk("construct_vmcs: load_vmcs failed: VMCS = %lx\n",
(unsigned long) vmcs_phys_ptr);
return -EINVAL;
rc = -EINVAL;
goto err_out;
}
if ((error = construct_vmcs_controls(arch_vmx))) {
printk("construct_vmcs: construct_vmcs_controls failed\n");
return -EINVAL;
rc = -EINVAL;
goto err_out;
}
/* host selectors */
if ((error = construct_vmcs_host(&host_env))) {
if ((error = construct_vmcs_host())) {
printk("construct_vmcs: construct_vmcs_host failed\n");
return -EINVAL;
rc = -EINVAL;
goto err_out;
}
/* guest selectors */
if ((error = construct_init_vmcs_guest(regs))) {
printk("construct_vmcs: construct_vmcs_guest failed\n");
return -EINVAL;
rc = -EINVAL;
goto err_out;
}
if ((error |= __vmwrite(EXCEPTION_BITMAP,
MONITOR_DEFAULT_EXCEPTION_BITMAP))) {
printk("construct_vmcs: setting Exception bitmap failed\n");
return -EINVAL;
rc = -EINVAL;
goto err_out;
}
if (regs->eflags & EF_TF)
@@ -480,6 +501,27 @@ int construct_vmcs(struct arch_vmx_struct *arch_vmx,
__vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
return 0;
err_out:
destroy_vmcs(arch_vmx);
return rc;
}
void destroy_vmcs(struct arch_vmx_struct *arch_vmx)
{
if(arch_vmx->vmcs != NULL)
free_vmcs(arch_vmx->vmcs);
if(arch_vmx->io_bitmap_a != 0) {
free_xenheap_pages(
arch_vmx->io_bitmap_a, get_order_from_bytes(0x1000));
arch_vmx->io_bitmap_a = 0;
}
if(arch_vmx->io_bitmap_b != 0) {
free_xenheap_pages(
arch_vmx->io_bitmap_b, get_order_from_bytes(0x1000));
arch_vmx->io_bitmap_b = 0;
}
arch_vmx->vmcs = 0;
}
/*
@@ -506,26 +548,6 @@ int modify_vmcs(struct arch_vmx_struct *arch_vmx,
return 0;
}
int load_vmcs(struct arch_vmx_struct *arch_vmx, u64 phys_ptr)
{
int error;
if ((error = __vmptrld(phys_ptr))) {
clear_bit(ARCH_VMX_VMCS_LOADED, &arch_vmx->flags);
return error;
}
set_bit(ARCH_VMX_VMCS_LOADED, &arch_vmx->flags);
return 0;
}
int store_vmcs(struct arch_vmx_struct *arch_vmx, u64 phys_ptr)
{
/* take the current VMCS */
__vmptrst(phys_ptr);
clear_bit(ARCH_VMX_VMCS_LOADED, &arch_vmx->flags);
return 0;
}
void vm_launch_fail(unsigned long eflags)
{
unsigned long error;
@@ -553,9 +575,19 @@ void arch_vmx_do_resume(struct vcpu *v)
void arch_vmx_do_launch(struct vcpu *v)
{
u64 vmcs_phys_ptr = (u64) virt_to_phys(v->arch.arch_vmx.vmcs);
int error;
cpu_user_regs_t *regs = &current->arch.guest_context.user_regs;
load_vmcs(&v->arch.arch_vmx, vmcs_phys_ptr);
error = construct_vmcs(&v->arch.arch_vmx, regs);
if ( error < 0 )
{
if (v->vcpu_id == 0) {
printk("Failed to construct a new VMCS for BSP.\n");
} else {
printk("Failed to construct a new VMCS for AP %d\n", v->vcpu_id);
}
domain_crash_synchronous();
}
vmx_do_launch(v);
reset_stack_and_jump(vmx_asm_do_launch);
}
+1 -2
View File
@@ -39,7 +39,6 @@ extern void arch_vmx_do_launch(struct vcpu *);
extern void arch_vmx_do_resume(struct vcpu *);
extern void arch_vmx_do_relaunch(struct vcpu *);
extern int vmcs_size;
extern unsigned int cpu_rev;
/*
@@ -449,7 +448,7 @@ static inline void vmx_stts(void)
__vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_NM);
}
/* Works only for ed == current */
/* Works only for vcpu == current */
static inline int vmx_paging_enabled(struct vcpu *v)
{
unsigned long cr0;
+4 -9
View File
@@ -53,6 +53,8 @@ struct vmcs_struct {
unsigned char data [0]; /* vmcs size is read from MSR */
};
extern int vmcs_size;
enum {
VMX_INDEX_MSR_LSTAR = 0,
VMX_INDEX_MSR_STAR,
@@ -94,18 +96,11 @@ struct arch_vmx_struct {
#define ARCH_VMX_VMCS_RESUME 2 /* Needs VMCS resume */
#define ARCH_VMX_IO_WAIT 3 /* Waiting for I/O completion */
void vmx_do_launch(struct vcpu *);
void vmx_do_resume(struct vcpu *);
void vmx_set_host_env(struct vcpu *);
void vmx_do_resume(struct vcpu *);
struct vmcs_struct *alloc_vmcs(void);
void free_vmcs(struct vmcs_struct *);
int load_vmcs(struct arch_vmx_struct *, u64);
int store_vmcs(struct arch_vmx_struct *, u64);
int construct_vmcs(struct arch_vmx_struct *, struct cpu_user_regs *,
struct vcpu_guest_context *, int);
int modify_vmcs(struct arch_vmx_struct *arch_vmx,
struct cpu_user_regs *regs);
void destroy_vmcs(struct arch_vmx_struct *arch_vmx);
#define VMCS_USE_HOST_ENV 1
#define VMCS_USE_SEPARATE_ENV 0
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.