Cpupools: hypervisor part
PATCH 1/6 Cpupools: hypervisor part
Signature · 6 lines
-- Juergen Gross Principal Developer Operating Systems TSP ES&S SWE OS6 Telephone: +49 (0) 89 3222 2967 Fujitsu Technology Solutions e-mail: [email protected] Domagkstr. 28 Internet: ts.fujitsu.com D-80807 Muenchen Company details: ts.fujitsu.com/imprint.html
xen/arch/x86/domain_build.c +8 -3
@@ -9,6 +9,7 @@#include <xen/lib.h> #include <xen/ctype.h> #include <xen/sched.h> +#include <xen/sched-if.h> #include <xen/smp.h> #include <xen/delay.h> #include <xen/event.h>
@@ -84,7 +85,7 @@ struct vcpu *__init alloc_dom0_vcpu0(voistruct vcpu *__init alloc_dom0_vcpu0 (void ) {if ( opt_dom0_max_vcpus ==0 ) - opt_dom0_max_vcpus =num_online_cpus (); + opt_dom0_max_vcpus =num_cpupool_cpus (cpupool0);if ( opt_dom0_max_vcpus >MAX_VIRT_CPUS ) opt_dom0_max_vcpus =MAX_VIRT_CPUS ;
@@ -277,7 +278,7 @@ int __init construct_dom0( unsigned long _initrd_start, unsigned long initrd_len, char *cmdline) { - int i, rc, compatible, compat32, order, machine; + int i, cpu, rc, compatible, compat32, order, machine;struct cpu_user_regs *regs;unsigned long pfn, mfn;unsigned long nr_pages;
@@ -776,8 +777,12 @@ int __init construct_dom0(printk ("Dom0 has maximum %u VCPUs\n" , opt_dom0_max_vcpus); + cpu =first_cpu (cpupool0->cpu_valid);for ( i =1 ; i < opt_dom0_max_vcpus; i++ ) - (void )alloc_vcpu (d, i, i %num_online_cpus ()); + { + cpu =cycle_cpu (cpu, cpupool0->cpu_valid); + (void )alloc_vcpu (d, i, cpu); + }/* Set up CR3 value for write_ptbase */ if (paging_mode_enabled (d) )
xen/arch/x86/mm.c +3 -3
@@ -242,7 +242,7 @@ void __init arch_init_memory(void)* Any Xen-heap pages that we will allow to be mapped will have * their domain field set to dom_xen. */ - dom_xen =domain_create (DOMID_XEN , DOMCRF_dummy,0 ); + dom_xen =domain_create (DOMID_XEN ,CPUPOOLID_NONE , DOMCRF_dummy,0 );BUG_ON (dom_xen ==NULL );/*
@@ -250,14 +250,14 @@ void __init arch_init_memory(void)* This domain owns I/O pages that are within the range of the page_info * array. Mappings occur at the priv of the caller. */ - dom_io =domain_create (DOMID_IO , DOMCRF_dummy,0 ); + dom_io =domain_create (DOMID_IO ,CPUPOOLID_NONE , DOMCRF_dummy,0 );BUG_ON (dom_io ==NULL );/* * Initialise our DOMID_IO domain. * This domain owns sharable pages. */ - dom_cow =domain_create (DOMID_COW , DOMCRF_dummy,0 ); + dom_cow =domain_create (DOMID_COW ,CPUPOOLID_NONE , DOMCRF_dummy,0 );BUG_ON (dom_cow ==NULL );/* First 1MB of RAM is historically marked as I/O. */
xen/arch/x86/platform_hypercall.c +3 -2
@@ -19,6 +19,7 @@#include <xen/iocap.h> #include <xen/guest_access.h> #include <xen/acpi.h> +#include <xen/sched-if.h> #include <asm/current.h> #include <public/platform.h> #include <acpi/cpufreq/processor_perf.h>
@@ -407,7 +408,7 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xe g_info = &op->u.pcpu_info;/* spin_trylock() avoids deadlock with stop_machine_run(). */ -if ( !spin_trylock (&cpu_add_remove_lock) ) +if ( !spin_trylock (&cpupool_lock) ) { ret = -EBUSY ;break ;
@@ -430,7 +431,7 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xe g_info->max_present =last_cpu (cpu_present_map); -spin_unlock (&cpu_add_remove_lock); +spin_unlock (&cpupool_lock); ret =copy_to_guest (u_xenpf_op, op,1 ) ? -EFAULT :0 ; }
xen/arch/x86/setup.c +8 -2
@@ -2,6 +2,7 @@#include <xen/init.h> #include <xen/lib.h> #include <xen/sched.h> +#include <xen/sched-if.h> #include <xen/domain.h> #include <xen/serial.h> #include <xen/softirq.h>
@@ -245,7 +246,7 @@ static void __init init_idle_domain(void/* Domain creation requires that scheduler structures are initialised. */ scheduler_init (); - idle_domain =domain_create (IDLE_DOMAIN_ID ,0 ,0 ); + idle_domain =domain_create (IDLE_DOMAIN_ID ,CPUPOOLID_NONE ,0 ,0 );if ( idle_domain ==NULL )BUG (); idle_domain->vcpu = idle_vcpu;
@@ -1093,8 +1094,13 @@ void __init __start_xen(unsigned long mbif ( !tboot_protect_mem_regions () )panic ("Could not protect TXT memory regions\n" ); +/* Create initial cpupool 0. */ + cpupool0 =cpupool_create (0 ,NULL ); +if ( (cpupool0 ==NULL ) ||cpupool0_cpu_assign (cpupool0) ) +panic ("Error creating cpupool 0\n" ); +/* Create initial domain 0. */ - dom0 =domain_create (0 , DOMCRF_s3_integrity,DOM0_SSIDREF ); + dom0 =domain_create (0 ,0 , DOMCRF_s3_integrity,DOM0_SSIDREF );if ( (dom0 ==NULL ) || (alloc_dom0_vcpu0 () ==NULL ) )panic ("Error creating domain 0\n" );
xen/arch/x86/smpboot.c +16 -13
@@ -39,6 +39,7 @@#include <xen/mm.h> #include <xen/domain.h> #include <xen/sched.h> +#include <xen/sched-if.h> #include <xen/irq.h> #include <xen/delay.h> #include <xen/softirq.h>
@@ -105,7 +106,6 @@ DEFINE_PER_CPU(int, cpu_state) = { 0 }; DEFINE_PER_CPU(int, cpu_state) = { 0 };void *stack_base[NR_CPUS ]; -DEFINE_SPINLOCK (cpu_add_remove_lock);/* * The bootstrap kernel entry code has set these up. Save them for
@@ -822,7 +822,7 @@ wakeup_secondary_cpu(int phys_apicid, unextern cpumask_t cpu_initialized;/* -* Caller should hold cpu_add_remove_lock if not called when booting +* Caller should hold cpupool_lock if not called when booting */ int alloc_cpu_id (void ) {
@@ -986,8 +986,10 @@ static int __devinit do_boot_cpu(int api cpucount--;/* Mark the CPU as non-present */ +spin_lock (&cpupool_lock); x86_cpu_to_apicid[cpu] =BAD_APICID ;cpu_clear (cpu, cpu_present_map); +spin_unlock (&cpupool_lock); }else { }
@@ -1307,10 +1309,11 @@ int __cpu_disable(void)sync_local_execstate ();/* It's now safe to remove this processor from the online map */ +cpu_clear (cpu, cpupool0->cpu_valid);cpu_clear (cpu, cpu_online_map);fixup_irqs (); -cpu_disable_scheduler (); +cpu_disable_scheduler (cpu,0 );return 0 ; }
@@ -1344,10 +1347,9 @@ int cpu_down(unsigned int cpu)int err =0 ;/* spin_trylock() avoids deadlock with stop_machine_run(). */ -if (!spin_trylock (&cpu_add_remove_lock)) +if (!spin_trylock (&cpupool_lock))return -EBUSY ; - -if (num_online_cpus () ==1 ) { +if ((!cpu_isset (cpu, cpupool0->cpu_valid)) || (cpus_weight (cpupool0->cpu_valid) ==1 )) { err = -EBUSY ; goto out; }
@@ -1381,7 +1383,7 @@ out: out:if (!err)send_guest_global_virq (dom0,VIRQ_PCPU_STATE ); -spin_unlock (&cpu_add_remove_lock); +spin_unlock (&cpupool_lock);return err; }
@@ -1390,7 +1392,7 @@ int cpu_up(unsigned int cpu)int err =0 ;/* spin_trylock() avoids deadlock with stop_machine_run(). */ -if (!spin_trylock (&cpu_add_remove_lock)) +if (!spin_trylock (&cpupool_lock))return -EBUSY ;if (cpu_online (cpu)) {
@@ -1408,7 +1410,7 @@ out: out:if (!err)send_guest_global_virq (dom0,VIRQ_PCPU_STATE ); -spin_unlock (&cpu_add_remove_lock); +spin_unlock (&cpupool_lock);return err; }
@@ -1494,14 +1496,14 @@ int cpu_add(uint32_t apic_id, uint32_t areturn -EEXIST ;/* spin_trylock() avoids deadlock with stop_machine_run(). */ -if (!spin_trylock (&cpu_add_remove_lock)) +if (!spin_trylock (&cpupool_lock))return -EBUSY ; cpu =mp_register_lapic (apic_id,1 );if (cpu <0 ) { -spin_unlock (&cpu_add_remove_lock); +spin_unlock (&cpupool_lock);return cpu; }
@@ -1518,7 +1520,7 @@ int cpu_add(uint32_t apic_id, uint32_t a "Setup node failed for pxm %x\n", pxm); x86_acpiid_to_apicid[acpi_id] =0xff ;mp_unregister_lapic (apic_id, cpu); -spin_unlock (&cpu_add_remove_lock); +spin_unlock (&cpupool_lock);return node; } apicid_to_node[apic_id] = node;
@@ -1526,7 +1528,7 @@ int cpu_add(uint32_t apic_id, uint32_t asrat_detect_node (cpu);numa_add_cpu (cpu); -spin_unlock (&cpu_add_remove_lock); +spin_unlock (&cpupool_lock);dprintk (XENLOG_INFO ,"Add CPU %x with index %x\n" , apic_id, cpu);return cpu; }
@@ -1570,6 +1572,7 @@ int __devinit __cpu_up(unsigned int cpu)process_pending_softirqs (); } +cpupool_cpu_add (cpu);cpufreq_add_cpu (cpu);return 0 ; }
xen/common/Makefile +1 -0
@@ -1,5 +1,6 @@ obj-y += bitmap.o obj-y += bitmap.o obj-y += cpu.o +obj-y += cpupool.o obj-y += domctl.o obj-y += domain.o obj-y += event_channel.o
xen/common/cpupool.c new file +580 -0
580 lines not on this page · raw message
xen/common/domain.c +8 -1
@@ -150,6 +150,8 @@ struct vcpu *alloc_vcpu(tasklet_init (&v->continue_hypercall_tasklet,NULL ,0 ); +tasklet_init (&v->continue_hypercall_tasklet,NULL ,0 ); +if (is_idle_domain (d) ) { v->runstate.state = RUNSTATE_running;
@@ -212,7 +214,7 @@ custom_param("extra_guest_irqs", parse_ecustom_param ("extra_guest_irqs" , parse_extra_guest_irqs);struct domain *domain_create ( -domid_t domid,unsigned int domcr_flags,ssidref_t ssidref) +domid_t domid,int poolid,unsigned int domcr_flags,ssidref_t ssidref) {struct domain *d, **pd;enum { INIT_xsm =1u <<0 , INIT_rangeset =1u <<1 , INIT_evtchn =1u <<2 ,
@@ -291,6 +293,9 @@ struct domain *domain_create( d->iomem_caps =rangeset_new (d,"I/O Memory" , RANGESETF_prettyprint_hex); d->irq_caps =rangeset_new (d,"Interrupts" ,0 );if ( (d->iomem_caps ==NULL ) || (d->irq_caps ==NULL ) ) + goto fail; + +if (cpupool_add_domain (d, poolid) !=0 ) goto fail;if (sched_init_domain (d) !=0 )
@@ -600,6 +605,8 @@ static void complete_domain_destroy(struarch_domain_destroy (d);rangeset_domain_destroy (d); + +cpupool_rm_domain (d);sched_destroy_domain (d);
xen/common/domctl.c +27 -6
@@ -11,6 +11,7 @@#include <xen/lib.h> #include <xen/mm.h> #include <xen/sched.h> +#include <xen/sched-if.h> #include <xen/domain.h> #include <xen/event.h> #include <xen/domain_page.h>
@@ -140,10 +141,12 @@ void getdomaininfo(struct domain *d, str info->shared_info_frame =mfn_to_gmfn (d,__pa (d->shared_info)>>PAGE_SHIFT );BUG_ON (SHARED_M2P (info->shared_info_frame)); + info->cpupool = d->cpupool ? d->cpupool->cpupool_id :CPUPOOLID_NONE ; +memcpy (info->handle, d->handle,sizeof (xen_domain_handle_t)); } -static unsigned int default_vcpu0_location (void ) +static unsigned int default_vcpu0_location (cpumask_t *online) {struct domain *d;struct vcpu *v;
@@ -173,7 +176,7 @@ static unsigned int default_vcpu0_locatiif (cpus_weight (per_cpu (cpu_sibling_map,0 )) >1 ) cpu =next_cpu (cpu,per_cpu (cpu_sibling_map,0 )); cpu_exclude_map =per_cpu (cpu_sibling_map,0 ); -for_each_online_cpu ( i ) +for_each_cpu_mask (i, *online) {if (cpu_isset (i, cpu_exclude_map) )continue ;
@@ -388,12 +391,14 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domcdomid_t dom;static domid_t rover =0 ;unsigned int domcr_flags; +int pool =0 ; ret = -EINVAL ;if ( supervisor_mode_kernel || (op->u.createdomain.flags & ~(XEN_DOMCTL_CDF_hvm_guest | XEN_DOMCTL_CDF_hap | - XEN_DOMCTL_CDF_s3_integrity | XEN_DOMCTL_CDF_oos_off)) ) + XEN_DOMCTL_CDF_s3_integrity | XEN_DOMCTL_CDF_oos_off | + XEN_DOMCTL_CDF_pool)) )break ; dom = op->domain;
@@ -429,9 +434,15 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc domcr_flags |= DOMCRF_s3_integrity;if ( op->u.createdomain.flags & XEN_DOMCTL_CDF_oos_off ) domcr_flags |= DOMCRF_oos_off; +if ( op->u.createdomain.flags & XEN_DOMCTL_CDF_pool ) + pool = op->u.createdomain.cpupool; + + ret = -EINVAL ; +if ( pool ==CPUPOOLID_NONE ) +break ; ret = -ENOMEM ; - d =domain_create (dom, domcr_flags, op->u.createdomain.ssidref); + d =domain_create (dom, pool, domcr_flags, op->u.createdomain.ssidref);if ( d ==NULL )break ;
@@ -450,6 +461,7 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc {struct domain *d;unsigned int i, max = op->u.max_vcpus.max, cpu; +cpumask_t *online; ret = -ESRCH ;if ( (d =rcu_lock_domain_by_id (op->domain)) ==NULL )
@@ -498,6 +510,7 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc goto maxvcpu_out; ret = -ENOMEM ; + online = (d->cpupool ==NULL ) ? &cpu_online_map : &d->cpupool->cpu_valid;if ( max > d->max_vcpus ) {struct vcpu **vcpus;
@@ -521,8 +534,8 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domccontinue ; cpu = (i ==0 ) ? -default_vcpu0_location () : -cycle_cpu (d->vcpu[i-1 ]->processor, cpu_online_map); +default_vcpu0_location (online) : +cycle_cpu (d->vcpu[i-1 ]->processor, *online);if (alloc_vcpu (d, i, cpu) ==NULL ) goto maxvcpu_out;
@@ -961,6 +974,14 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc }break ; +case XEN_DOMCTL_cpupool_op: + { + ret =cpupool_do_domctl (&op->u.cpupool_op); +if ( (ret ==0 ) &©_to_guest (u_domctl, op,1 ) ) + ret = -EFAULT ; + } +break ; +default : ret =arch_do_domctl (op, u_domctl);break ;
xen/common/sched_credit.c +276 -139
864 lines not on this page · raw message
xen/common/sched_credit2.c +189 -114
607 lines not on this page · raw message
xen/common/sched_sedf.c +104 -52
278 lines not on this page · raw message
xen/common/schedule.c +254 -46
304 lines not on this page · raw message
xen/include/xen/sched-if.h +48 -15
63 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel
Part of the diff is not shown here. View the raw message.
Juergen,
I don't think there's any need to change the domain creation interfaces. Drop new domains into a default pool, and then they can moved out (even immediately) by further control operations. This will avoid changes to the domain-creation public and private interfaces.
Also, you merge the cpu_add_remove_lock into a new cpupool_lock. That's not actually safe since cpu_add_remove_lock is held on entry to stopmachine_run(). Hence I assume now cpupool_lock is, and the only way to avoid deadlock possibilities would be for everyone to only spin_trylock on cpupool_lock, which isn't the case in your patch. Otherwise stopmachine_run can hang waiting for a CPU to enter its smr handler, while that CPU is waiting for the cpupool_lock to be released: a deadlock scenario.
I think you'll really need to find a method of synchronisation with cpu hotplug which does not involve a lock that is held across stopmachine_run(). My first suggestion in this respect would be to take a look at cpu_disable_scheduler(). This function deschedules vcpus from a cpu being offlined, and notice you can go fairly hogwild with minimal locking restrictions because everyone else is in a stopmachine 'safe place' with irqs disabled. So they cannot concurrently conflict with you.
So hooking yourself off cpu_disable_scheduler(), or adding some other new call-out from the end of __cpu_disable(), is quite probably the way to go to update cpupool info, break affinities, or whatever else you need to do.
-- Keir
On 20/04/2010 10:38, "Juergen Gross" <[email protected]> wrote: