|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH for-next v2 09/10] x86/domain: move PV specific code to pv/domain.c
On 25/04/17 14:52, Wei Liu wrote:
> - fail:
> - pv_domain_destroy(d);
> -
> - return rc;
> -}
> -
> +void paravirt_ctxt_switch_from(struct vcpu *v);
> +void paravirt_ctxt_switch_to(struct vcpu *v);
> int arch_domain_create(struct domain *d, unsigned int domcr_flags,
> struct xen_arch_domainconfig *config)
> {
> @@ -1919,7 +1717,8 @@ static void save_segments(struct vcpu *v)
>
> #define switch_kernel_stack(v) ((void)0)
>
> -static void paravirt_ctxt_switch_from(struct vcpu *v)
> +/* Needed by PV guests */
> +void paravirt_ctxt_switch_from(struct vcpu *v)
> {
Could these be moved up to avoid the forward declarations above?
> diff --git a/xen/arch/x86/pv/Makefile b/xen/arch/x86/pv/Makefile
> index ea94599438..2737824e81 100644
> --- a/xen/arch/x86/pv/Makefile
> +++ b/xen/arch/x86/pv/Makefile
> @@ -1,2 +1,3 @@
> obj-y += hypercall.o
> obj-bin-y += dom0_build.init.o
> +obj-y += domain.o
> diff --git a/xen/arch/x86/pv/domain.c b/xen/arch/x86/pv/domain.c
> new file mode 100644
> index 0000000000..562c3d03f5
> --- /dev/null
> +++ b/xen/arch/x86/pv/domain.c
> @@ -0,0 +1,232 @@
> +/******************************************************************************
> + * arch/x86/pv/domain.c
> + *
> + * PV domain handling
> + */
> +
> +/*
> + * Copyright (C) 1995 Linus Torvalds
> + *
> + * Pentium III FXSR, SSE support
> + * Gareth Hughes <gareth@xxxxxxxxxxx>, May 2000
> + */
> +
> +#include <xen/domain_page.h>
> +#include <xen/errno.h>
> +#include <xen/lib.h>
> +#include <xen/sched.h>
> +
> +static void noreturn continue_nonidle_domain(struct vcpu *v)
> +{
> + check_wakeup_from_wait();
> + mark_regs_dirty(guest_cpu_user_regs());
> + reset_stack_and_jump(ret_from_intr);
> +}
> +
> +static int setup_compat_l4(struct vcpu *v)
> +{
> + struct page_info *pg;
> + l4_pgentry_t *l4tab;
> +
> + pg = alloc_domheap_page(v->domain, MEMF_no_owner);
> + if ( pg == NULL )
> + return -ENOMEM;
> +
> + /* This page needs to look like a pagetable so that it can be shadowed */
.
> + pg->u.inuse.type_info = PGT_l4_page_table|PGT_validated|1;
More spaces please.
> +
> + l4tab = __map_domain_page(pg);
> + clear_page(l4tab);
I know this patch is only code motion, but I really think it would be
safer to defer the type_info update until after we have cleared the page.
> + init_guest_l4_table(l4tab, v->domain, 1);
> + unmap_domain_page(l4tab);
> +
> + v->arch.guest_table = pagetable_from_page(pg);
> + v->arch.guest_table_user = v->arch.guest_table;
> +
> + return 0;
> +}
> +
> +static void release_compat_l4(struct vcpu *v)
> +{
> + if ( !pagetable_is_null(v->arch.guest_table) )
> + free_domheap_page(pagetable_get_page(v->arch.guest_table));
> + v->arch.guest_table = pagetable_null();
> + v->arch.guest_table_user = pagetable_null();
> +}
> +
> +int switch_compat(struct domain *d)
> +{
> + struct vcpu *v;
> + int rc;
> +
> + if ( is_hvm_domain(d) || d->tot_pages != 0 )
> + return -EACCES;
> + if ( is_pv_32bit_domain(d) )
> + return 0;
> +
> + d->arch.has_32bit_shinfo = 1;
> + if ( is_pv_domain(d) )
> + d->arch.is_32bit_pv = 1;
This is_pv_domain() is redundant. I expect this was fallout from
ripping PVH out.
> +
> + for_each_vcpu( d, v )
> + {
> + rc = setup_compat_arg_xlat(v);
> + if ( !rc )
> + rc = setup_compat_l4(v);
> +
> + if ( rc )
> + goto undo_and_fail;
This is odd structuring. Care to rearrange it with two goto's, rather
than inverting the first rc check?
> + }
> +
> + domain_set_alloc_bitsize(d);
> + recalculate_cpuid_policy(d);
> +
> + d->arch.x87_fip_width = 4;
> +
> + return 0;
> +
> + undo_and_fail:
> + d->arch.is_32bit_pv = d->arch.has_32bit_shinfo = 0;
> + for_each_vcpu( d, v )
> + {
> + free_compat_arg_xlat(v);
> + release_compat_l4(v);
> + }
> +
> + return rc;
> +}
> +
> +static int pv_create_gdt_ldt_l1tab(struct domain *d, struct vcpu *v)
> +{
> + return create_perdomain_mapping(d, GDT_VIRT_START(v),
> + 1 << GDT_LDT_VCPU_SHIFT,
This should be 1u, when introduced in patch 1.
> + d->arch.pv_domain.gdt_ldt_l1tab, NULL);
> +}
> +
> +static void pv_destroy_gdt_ldt_l1tab(struct domain *d, struct vcpu *v)
> +{
> + destroy_perdomain_mapping(d, GDT_VIRT_START(v), 1 << GDT_LDT_VCPU_SHIFT);
> +}
> +
> +void pv_vcpu_destroy(struct vcpu *v)
> +{
> + if ( is_pv_32bit_vcpu(v) )
> + {
> + free_compat_arg_xlat(v);
> + release_compat_l4(v);
> + }
> +
> + pv_destroy_gdt_ldt_l1tab(v->domain, v);
> + xfree(v->arch.pv_vcpu.trap_ctxt);
> + v->arch.pv_vcpu.trap_ctxt = NULL;
> +}
> +
> +int pv_vcpu_initialise(struct vcpu *v)
> +{
> + struct domain *d = v->domain;
> + int rc;
> +
> + ASSERT(!is_idle_domain(d));
> +
> + spin_lock_init(&v->arch.pv_vcpu.shadow_ldt_lock);
> +
> + rc = pv_create_gdt_ldt_l1tab(d, v);
> + if ( rc )
> + goto done;
> +
> + BUILD_BUG_ON(NR_VECTORS * sizeof(*v->arch.pv_vcpu.trap_ctxt) >
> + PAGE_SIZE);
> + v->arch.pv_vcpu.trap_ctxt = xzalloc_array(struct trap_info,
> + NR_VECTORS);
> + if ( !v->arch.pv_vcpu.trap_ctxt )
> + {
> + rc = -ENOMEM;
> + goto done;
> + }
> +
> + /* PV guests by default have a 100Hz ticker. */
> + v->periodic_period = MILLISECS(10);
> +
> + v->arch.pv_vcpu.ctrlreg[4] = real_cr4_to_pv_guest_cr4(mmu_cr4_features);
> +
> + if ( is_pv_32bit_domain(d) )
> + {
> + if ( (rc = setup_compat_arg_xlat(v)) )
> + goto done;
> +
> + if ( (rc = setup_compat_l4(v)) )
> + goto done;
> + }
Now the code is split apart like this, this construct looks suspicious.
I suppose it probably copes with the toolstack using
XEN_DOMCTL_set_address_size and XEN_DOMCTL_max_vcpus in either order.
> +
> + done:
> + if ( rc )
> + pv_vcpu_destroy(v);
> + return rc;
> +}
> +
> +void pv_domain_destroy(struct domain *d)
> +{
> + destroy_perdomain_mapping(d, GDT_LDT_VIRT_START,
> + GDT_LDT_MBYTES << (20 - PAGE_SHIFT));
> + xfree(d->arch.pv_domain.cpuidmasks);
> + d->arch.pv_domain.cpuidmasks = NULL;
> + free_xenheap_page(d->arch.pv_domain.gdt_ldt_l1tab);
> + d->arch.pv_domain.gdt_ldt_l1tab = NULL;
> +}
> +
> +
> +extern void paravirt_ctxt_switch_from(struct vcpu *v);
> +extern void paravirt_ctxt_switch_to(struct vcpu *v);
> +
> +int pv_domain_initialise(struct domain *d, unsigned int domcr_flags,
> + struct xen_arch_domainconfig *config)
> +{
> + static const struct arch_csw pv_csw = {
> + .from = paravirt_ctxt_switch_from,
> + .to = paravirt_ctxt_switch_to,
> + .tail = continue_nonidle_domain,
> + };
> + int rc = -ENOMEM;
> +
> + d->arch.pv_domain.gdt_ldt_l1tab =
> + alloc_xenheap_pages(0, MEMF_node(domain_to_node(d)));
> + if ( !d->arch.pv_domain.gdt_ldt_l1tab )
> + goto fail;
> + clear_page(d->arch.pv_domain.gdt_ldt_l1tab);
> +
> + if ( levelling_caps & ~LCAP_faulting )
> + {
> + d->arch.pv_domain.cpuidmasks = xmalloc(struct cpuidmasks);
> + if ( !d->arch.pv_domain.cpuidmasks )
> + goto fail;
> + *d->arch.pv_domain.cpuidmasks = cpuidmask_defaults;
> + }
> +
> + rc = create_perdomain_mapping(d, GDT_LDT_VIRT_START,
> + GDT_LDT_MBYTES << (20 - PAGE_SHIFT),
> + NULL, NULL);
> + if ( rc )
> + goto fail;
> +
> + d->arch.ctxt_switch = &pv_csw;
> +
> + /* 64-bit PV guest by default. */
> + d->arch.is_32bit_pv = d->arch.has_32bit_shinfo = 0;
> +
> + return 0;
> +
> + fail:
> + pv_domain_destroy(d);
> +
> + return rc;
> +}
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * tab-width: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/xen/include/asm-x86/pv/domain.h b/xen/include/asm-x86/pv/domain.h
> new file mode 100644
> index 0000000000..6288ae24df
> --- /dev/null
> +++ b/xen/include/asm-x86/pv/domain.h
> @@ -0,0 +1,30 @@
> +/*
> + * pv/domain.h
> + *
> + * PV guest interface definitions
> + *
> + * Copyright (C) 2017 Wei Liu <wei.liu2@xxxxxxxxxx>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms and conditions of the GNU General Public
> + * License, version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public
> + * License along with this program; If not, see
> <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef __X86_PV_DOMAIN_H__
> +#define __X86_PV_DOMAIN_H__
> +
#ifdef CONFIG_PV
> +void pv_vcpu_destroy(struct vcpu *v);
> +int pv_vcpu_initialise(struct vcpu *v);
> +void pv_domain_destroy(struct domain *d);
> +int pv_domain_initialise(struct domain *d, unsigned int domcr_flags,
> + struct xen_arch_domainconfig *config);
#else
static inline void pv_vcpu_destroy(struct vcpu *v) {};
static inline int pv_vcpu_initialise(struct vcpu *v) { return
-EOPNOTSUPP; };
static inline void pv_domain_destroy(struct domain *d) {};
static inline int pv_domain_initialise(struct domain *d, unsigned int
domcr_flags,
struct xen_arch_domainconfig
*config) { return -EOPNOTSUPP; }
#endif
Please can we try to make new code compatible with eventually turning
off CONFIG_PV and CONFIG_HVM.
~Andrew
> +
> +#endif /* __X86_PV_DOMAIN_H__ */
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |