arm: SMP boot
PATCH 1/1 arm: SMP boot
This patch series implements SMP boot for arch/arm, as far as getting all CPUs up and running the idle loop.
The first few patches are semi-independent cleanups and improvements, most of which are needed for the SMP patches later.
Cheers,
Tim.
PATCH 1/1 arm: strip xen binary
# HG changeset patch
# User Tim Deegan <[email protected]>
# Date 1330018799 0
# Node ID 4a7c1420913135fbeba361cd9603e748c074cdac # Parent 0c3d19f40ab145d101de84051c3e00eef17fa1cb
arm: strip xen binary
The symbols in it are wrong anyway and will only confuse people who ought to be looking at xen-syms.
xen/arch/arm/Makefile +1 -1
@@ -40,7 +40,7 @@ ALL_OBJS := head.o $(ALL_OBJS) # XXX: VE model loads by VMA so instead of # making a proper ELF we link with LMA == VMA and adjust crudely $(OBJCOPY) --change-addresses +0x80000000 $< $@ - # XXX strip it + $(STRIP) $@ #$(TARGET): $(TARGET)-syms $(efi-y) boot/mkelf32 # ./boot/mkelf32 $(TARGET)-syms $(TARGET) 0x100000 \
PATCH 1/1 arm: implement udelay()
In reply to Tim Deegan# HG changeset patch
# User Tim Deegan <[email protected]>
# Date 1330018799 0
# Node ID ec051056db2b6d37344629e2f01d17240099d5ec # Parent 4a7c1420913135fbeba361cd9603e748c074cdac
arm: implement udelay()
xen/arch/arm/dummy.S +0 -1
@@ -62,5 +62,4 @@ DUMMY(gmfn_to_mfn); DUMMY(hypercall_create_continuation); DUMMY(send_timer_event); DUMMY(share_xen_page_with_privileged_guests); -DUMMY(__udelay); DUMMY(wallclock_time);
xen/arch/arm/time.c +10 -0
@@ -171,6 +171,16 @@ void __cpuinit init_timer_interrupt(voidrequest_irq (30 , timer_interrupt,0 ,"phytimer" ,NULL ); } +/* Wait a set number of microseconds */ +void udelay (unsigned long usecs) +{ +s_time_t deadline =get_s_time () +1000 * (s_time_t ) usecs; +do { +dsb (); +isb (); + }while (get_s_time () - deadline <0 ); +} +/* * Local variables: * mode: C
xen/include/asm-arm/delay.h +1 -2
@@ -1,8 +1,7 @@#ifndef _ARM_DELAY_H#define _ARM_DELAY_H -extern void __udelay (unsigned long usecs); -#define udelay (n) __udelay(n) +extern void udelay (unsigned long usecs);#endif /* defined(_ARM_DELAY_H) */ /*
Re: [PATCH 02 of 10] arm: implement udelay()
Quoted 4 lines · Tim Deegan
arm: implement
udelay()Signed-off-by Tim Deegan <[email protected]>
[...]
Quoted 4 lines
diff -r
4a7c14209131-rec051056db2bxen/arch/arm/time.c
xen/arch/arm/time.c void __cpuinit init_timer_interrupt(void · line 180
Quoted 10 lines
xen/arch/arm/time.c +7
-0@@ -171,6 +171,16 @@ void __cpuinit init_timer_interrupt(voidrequest_irq (30 , timer_interrupt,0 ,"phytimer" ,NULL ); } +/* Wait a set number of microseconds */ +void udelay (unsigned long usecs) +{ +s_time_t deadline =get_s_time () +1000 * (s_time_t ) usecs; + do { + dsb(); + isb();
What are these barriers for?
David
Quoted 6 lines
xen/arch/arm/time.c +3
-0+ }while (get_s_time () - deadline <0 ); +} +/* * Local variables: * mode: C
Re: [PATCH 02 of 10] arm: implement udelay()
Quoted 13 lines · David Vrabel
Quoted 4 lines · Tim Deegan
arm: implement
udelay()Signed-off-by Tim Deegan <[email protected]>[...]
Quoted 7 lines
diff -r
4a7c14209131-rec051056db2bxen/arch/arm/time.cxen/arch/arm/time.c +0
-0@@ -171,6 +171,16 @@ void __cpuinit init_timer_interrupt(voidrequest_irq (30 , timer_interrupt,0 ,"phytimer" ,NULL ); }
Quoted 9 lines
xen/arch/arm/time.c void __cpuinit init_timer_interrupt(void · line 180
Quoted 7 lines
xen/arch/arm/time.c +7
-0+/* Wait a set number of microseconds */ +void udelay (unsigned long usecs) +{ +s_time_t deadline =get_s_time () +1000 * (s_time_t ) usecs; + do { + dsb(); + isb();What are these barriers for?
To make sure the CPU doesn't hoist any instructions past the wait loop. :) They don't really have to be inside the loop body; I can change that if you like.
Tim.
PATCH 1/1 arm: Move some GIC distributor init out of the per-CPU init function
In reply to Tim Deegan# HG changeset patch
# User Tim Deegan <[email protected]>
# Date 1330018799 0
# Node ID 437ad1207a175c9ad376871f3f4c075dbcd5b6e6
# Parent ec051056db2b6d37344629e2f01d17240099d5ec
arm: Move some GIC distributor init out of the per-CPU init function
xen/arch/arm/gic.c +6 -8
@@ -216,14 +216,6 @@ static void __init gic_dist_init(void)for ( i =32 ; i < gic.lines; i +=32 )GICD [GICD_ICENABLER + i /32 ] = ~0ul ; -/* Turn on the distributor */ -GICD [GICD_CTLR ] =GICD_CTL_ENABLE ; -} - -static void __cpuinit gic_cpu_init (void ) -{ -int i; -/* Disable all PPI and enable all SGI */ GICD [GICD_ICENABLER ] =0xffff0000 ;/* Disable all PPI */ GICD [GICD_ISENABLER ] =0x0000ffff ;/* Enable all SGI */
@@ -231,6 +223,12 @@ static void __cpuinit gic_cpu_init(void)for (i =0 ; i <32 ; i +=4 )GICD [GICD_IPRIORITYR + i /4 ] =0xa0a0a0a0 ; +/* Turn on the distributor */ +GICD [GICD_CTLR ] =GICD_CTL_ENABLE ; +} + +static void __cpuinit gic_cpu_init (void ) +{/* Local settings: interface controller */ GICC [GICC_PMR ] =0xff ;/* Don't mask by priority */ GICC [GICC_BPR ] =0 ;/* Finest granularity of priority */
Re: [PATCH 03 of 10] arm: Move some GIC distributor init out of the per-CPU init function
Quoted 17 lines · Tim Deegan
# HG changeset patch
# User Tim Deegan <[email protected]>
# Date 1330018799 0
# Node ID437ad1207a175c9ad376871f3f4c075dbcd5b6e6
# Parentec051056db2b6d37344629e2f01d17240099d5ec
arm: Move some GIC distributor init out of the per-CPU init functionSigned-off-by Tim Deegan <[email protected]>diff -r
ec051056db2b-r437ad1207a17xen/arch/arm/gic.cxen/arch/arm/gic.c +0
-1@@ -216,14 +216,6 @@ static void __init gic_dist_init(void)for ( i =32 ; i < gic.lines; i +=32 )GICD [GICD_ICENABLER + i /32 ] = ~0ul ; -/* Turn on the distributor */
xen/arch/arm/gic.c static void __init gic_dist_init(void) · line 221
Quoted 10 lines
xen/arch/arm/gic.c +0
-7-GICD [GICD_CTLR ] =GICD_CTL_ENABLE ; -} - -static void __cpuinit gic_cpu_init (void ) -{ -int i; -/* Disable all PPI and enable all SGI */ GICD [GICD_ICENABLER ] =0xffff0000 ;/* Disable all PPI */ GICD [GICD_ISENABLER ] =0x0000ffff ;/* Enable all SGI */
PPIs and SGIs are per physical-CPU and therefore, I think, the GICD registers of various sorts which refer to the first 32 interrupts are per physical-CPU as well. IOW moving these from gic_cpu_init to gic_dist_init is wrong?
Quoted 13 lines
xen/arch/arm/gic.c +6
-0@@ -231,6 +223,12 @@ static void __cpuinit gic_cpu_init(void)for (i =0 ; i <32 ; i +=4 )GICD [GICD_IPRIORITYR + i /4 ] =0xa0a0a0a0 ; +/* Turn on the distributor */ +GICD [GICD_CTLR ] =GICD_CTL_ENABLE ; +} + +static void __cpuinit gic_cpu_init (void ) +{/* Local settings: interface controller */ GICC [GICC_PMR ] =0xff ;/* Don't mask by priority */ GICC [GICC_BPR ] =0 ;/* Finest granularity of priority */
Re: [PATCH 03 of 10] arm: Move some GIC distributor init out of the per-CPU init function
Quoted 17 lines · Ian Campbell
Quoted 16 lines · Tim Deegan
# HG changeset patch
# User Tim Deegan <[email protected]>
# Date 1330018799 0
# Node ID437ad1207a175c9ad376871f3f4c075dbcd5b6e6
# Parentec051056db2b6d37344629e2f01d17240099d5ec
arm: Move some GIC distributor init out of the per-CPU init functionSigned-off-by Tim Deegan <[email protected]>diff -r
ec051056db2b-r437ad1207a17xen/arch/arm/gic.cxen/arch/arm/gic.c +0
-0@@ -216,14 +216,6 @@ static void __init gic_dist_init(void)for ( i =32 ; i < gic.lines; i +=32 )GICD [GICD_ICENABLER + i /32 ] = ~0ul ;
Quoted 16 lines
xen/arch/arm/gic.c static void __init gic_dist_init(void) · line 221
Quoted 11 lines
xen/arch/arm/gic.c +0
-8-/* Turn on the distributor */ -GICD [GICD_CTLR ] =GICD_CTL_ENABLE ; -} - -static void __cpuinit gic_cpu_init (void ) -{ -int i; -/* Disable all PPI and enable all SGI */ GICD [GICD_ICENABLER ] =0xffff0000 ;/* Disable all PPI */ GICD [GICD_ISENABLER ] =0x0000ffff ;/* Enable all SGI */ PPIs and SGIs are per physical-CPU and therefore, I think, the GICD registers of various sorts which refer to the first 32 interrupts are per physical-CPU as well. IOW moving these from
gic_cpu_inittogic_dist_initis wrong?
Yep, you're right ISENABLER0 and ICENABLER0 are banked. I'll replace this with a comment explaining that.
Cheers,
Tim.
Re: [PATCH 03 of 10] arm: Move some GIC distributor init out of the per-CPU init function
Quoted 35 lines · Tim Deegan
Quoted 17 lines · Ian Campbell
Quoted 16 lines · Tim Deegan
# HG changeset patch
# User Tim Deegan <[email protected]>
# Date 1330018799 0
# Node ID437ad1207a175c9ad376871f3f4c075dbcd5b6e6
# Parentec051056db2b6d37344629e2f01d17240099d5ec
arm: Move some GIC distributor init out of the per-CPU init functionSigned-off-by Tim Deegan <[email protected]>diff -r
ec051056db2b-r437ad1207a17xen/arch/arm/gic.cxen/arch/arm/gic.c +0
-0@@ -216,14 +216,6 @@ static void __init gic_dist_init(void)for ( i =32 ; i < gic.lines; i +=32 )GICD [GICD_ICENABLER + i /32 ] = ~0ul ;Quoted 16 lines
xen/arch/arm/gic.c static void __init gic_dist_init(void) · line 221
Quoted 11 lines
xen/arch/arm/gic.c +0
-8-/* Turn on the distributor */ -GICD [GICD_CTLR ] =GICD_CTL_ENABLE ; -} - -static void __cpuinit gic_cpu_init (void ) -{ -int i; -/* Disable all PPI and enable all SGI */ GICD [GICD_ICENABLER ] =0xffff0000 ;/* Disable all PPI */ GICD [GICD_ISENABLER ] =0x0000ffff ;/* Enable all SGI */ PPIs and SGIs are per physical-CPU and therefore, I think, the GICD registers of various sorts which refer to the first 32 interrupts are per physical-CPU as well. IOW moving these from
gic_cpu_inittogic_dist_initis wrong?
Quoted 1 line
Yep, you're right ISENABLER0 and ICENABLER0 are banked.
BTW so are GICD_IPRIORITYR0..4 which are initialised just outside the context here. More generally all the per-IRQ registers are banked for the first few which cover the PPIs and SGIs.
Quoted 1 line
I'll replace this with a comment explaining that.
Thanks.
PATCH 1/1 arm: Handle booting on SMP platforms
In reply to Tim Deegan# HG changeset patch
# User Tim Deegan <[email protected]>
# Date 1330018799 0
# Node ID 8f322ab538572e1a12c8ed716ddd5cb4c122e9ed # Parent 437ad1207a175c9ad376871f3f4c075dbcd5b6e6
arm: Handle booting on SMP platforms
Make all non-boot CPUs wait forever instead of trying to boot in parallel.
xen/arch/arm/head.S +13 -0
@@ -61,6 +61,19 @@ start: add r8, r10 /* r8 := paddr(DTB) */ #endif + /* Are we the boot CPU? */ + mrc CP32(r0, MPIDR) + tst r0, #(1<<31) /* Multiprocessor extension supported? */ + beq boot_cpu + tst r0, #(1<<30) /* Uniprocessor system? */ + bne boot_cpu + bics r0, r0, #(0xff << 24) /* Ignore flags */ + beq boot_cpu /* If all other fields are 0, we win */ + +1: wfi + b 1b + +boot_cpu: #ifdef EARLY_UART_ADDRESS /* Say hello */ ldr r11, =EARLY_UART_ADDRESS /* r11 := UART base address */
xen/include/asm-arm/cpregs.h +1 -0
@@ -91,6 +91,7 @@/* Coprocessor 15 */ /* CP15 CR0: CPUID and Cache Type Registers */ +#define MPIDR p15,0,c0,c0,5/* Multiprocessor Affinity Register */ #define ID_PFR0 p15,0,c0,c1,0/* Processor Feature Register 0 */ #define ID_PFR1 p15,0,c0,c1,1/* Processor Feature Register 1 */ #define ID_DFR0 p15,0,c0,c1,2/* Debug Feature Register 0 */
PATCH 1/1 arm: More SMP bringup
In reply to Tim Deegan# HG changeset patch
# User Tim Deegan <[email protected]>
# Date 1330018799 0
# Node ID 1e9c6bd7cc99d1af0107aa927ee2ba03721449b7 # Parent 8f322ab538572e1a12c8ed716ddd5cb4c122e9ed
arm: More SMP bringup
Bring non-boot CPUs up as far as running on the relocated pagetables, one at a time, before the non-relocated copy of Xen gets reused for general memory pools.
Don't yet bring them up into C; that will happen later when stacks are allocated.
xen/arch/arm/gic.c +3 -1
@@ -248,7 +248,7 @@ static void __cpuinit gic_hyp_init(void) }/* Set up the GIC */ -void gic_init (void ) +int __init gic_init (void ) {/* XXX FIXME get this from devicetree */ gic.dbase =GIC_BASE_ADDRESS +GIC_DR_OFFSET ;
@@ -270,6 +270,8 @@ void gic_init(void)gic_hyp_init ();spin_unlock (&gic.lock); + +return gic.cpus; }void gic_route_irqs (void )
xen/arch/arm/gic.h +2 -2
@@ -138,8 +138,8 @@ extern int gic_route_irq_to_guest(struct/* Accept an interrupt from the GIC and dispatch its handler */ extern void gic_interrupt (struct cpu_user_regs *regs,int is_fiq); -/* Bring up the interrupt controller */ -extern void gic_init (void ); +/* Bring up the interrupt controller, and report # cpus attached */ +extern int gic_init (void );/* setup the gic virtual interface for a guest */ extern void gicv_setup (struct domain *d);#endif
xen/arch/arm/head.S +73 -14
152 lines not on this page · raw message
xen/arch/arm/mm.c +12 -9
@@ -36,6 +36,9 @@ lpae_t xen_second[LPAE_ENTRIES*4] __attr static lpae_t xen_fixmap[LPAE_ENTRIES] __attribute__((__aligned__(4096))); static lpae_t xen_xenmap[LPAE_ENTRIES] __attribute__((__aligned__(4096))); +/* Non-boot CPUs use this to find the correct pagetables. */ +uint64_t boot_httbr; +/* Limits of the Xen heap */ unsigned long xenheap_mfn_start, xenheap_mfn_end;unsigned long xenheap_virt_end;
@@ -156,14 +159,6 @@ void __init setup_pagetables(unsigned lolpae_t pte, *p;int i; -if ( boot_phys_offset !=0 ) - { -/* Remove the old identity mapping of the boot paddr */ - pte.bits =0 ; - dest_va = (unsigned long )_start + boot_phys_offset; -write_pte (xen_second +second_linear_offset (dest_va), pte); - } - xen_paddr =device_tree_get_xen_paddr ();/* Map the destination in the boot misc area. */
@@ -186,11 +181,19 @@ void __init setup_pagetables(unsigned lofor ( i =0 ; i <4 ; i++) p[i].pt.base += (phys_offset - boot_phys_offset) >>PAGE_SHIFT ; p = (void *) xen_second + dest_va - (unsigned long ) _start; +if ( boot_phys_offset !=0 ) + { +/* Remove the old identity mapping of the boot paddr */ + pte.bits =0 ; + dest_va = (unsigned long )_start + boot_phys_offset; + p[second_linear_offset (dest_va)] = pte; + }for ( i =0 ; i <4 *LPAE_ENTRIES ; i++)if ( p[i].pt.valid ) p[i].pt.base += (phys_offset - boot_phys_offset) >>PAGE_SHIFT ;/* Change pagetables to the copy in the relocated Xen */ + boot_httbr = (unsigned long ) xen_pgtable + phys_offset; asmvolatile ( STORE_CP64(0, HTTBR) /* Change translation base */ "dsb;" /* Ensure visibility of HTTBR update */
@@ -198,7 +201,7 @@ void __init setup_pagetables(unsigned lo STORE_CP32(0, BPIALL) /* Flush branch predictor */ "dsb;" /* Ensure completion of TLB+BP flush */ "isb;" - : : "r" ((unsigned long) xen_pgtable + phys_offset) : "memory"); + : : "r" (boot_httbr) : "memory"); /* Undo the temporary map */ pte.bits =0 ;
xen/arch/arm/setup.c +28 -6
@@ -44,7 +44,12 @@ static unsigned int __initdata max_cpus/* Xen stack for bringing up the first CPU. */ unsigned char __initdata init_stack[STACK_SIZE] __attribute__((__aligned__(STACK_SIZE))); -extern char __init_begin[], __init_end[], __bss_start[]; +extern const char __init_begin[], __init_end[], __bss_start[]; + +/* Spinlock for serializing CPU bringup */ +unsigned long __initdata boot_gate =1 ; +/* Number of non-boot CPUs ready to enter C */ +unsigned long __initdata ready_cpus =0 ; static __attribute_used__ void init_done(void) {
@@ -151,14 +156,17 @@ static void __init setup_mm(unsigned lonend_boot_allocator (); } +/* C entry point for boot CPU */ void __init start_xen (unsigned long boot_phys_offset,unsigned long arm_type, -unsigned long atag_paddr) - +unsigned long atag_paddr, +unsigned long cpuid) {void *fdt;size_t fdt_size; -int i; +int cpus, i; +paddr_t gate_pa; +unsigned long *gate; fdt = (void *)BOOT_MISC_VIRT_START + (atag_paddr & ((1 <<SECOND_SHIFT ) -1 ));
@@ -174,6 +182,22 @@ void __init start_xen(unsigned long bootconsole_init_preirq ();#endif + cpus =gic_init (); + +printk ("Waiting for %i other CPUs to be ready\n" , cpus -1 ); +/* Bring the other CPUs up to paging before the original +* copy of .text gets overwritten. We need to use the unrelocated +* copy of boot_gate as that's the one the others can see. */ + gate_pa = ((unsigned long ) &boot_gate) + boot_phys_offset; + gate =map_domain_page (gate_pa >>PAGE_SHIFT ) + (gate_pa & ~PAGE_MASK ); + *gate =0 ; +unmap_domain_page (gate); +/* Now send an event to wake the first non-boot CPU */ + asmvolatile ("dsb; isb; sev" ); +/* And wait for them all to be ready. */ +while ( ready_cpus +1 < cpus ) +smp_rmb (); +__set_current ((struct vcpu *)0xfffff000 );/* debug sanity */ idle_vcpu[0 ] = current;set_processor_id (0 );/* needed early, for smp_processor_id() */
@@ -208,8 +232,6 @@ void __init start_xen(unsigned long bootinit_IRQ (); -gic_init (); -gic_route_irqs ();init_maintenance_interrupt ();
Re: [PATCH 05 of 10] arm: More SMP bringup
On Thu, 2012-02-23 at 17:40 +0000, Tim Deegan wrote:
[...]
xen/arch/arm/head.S paging: · line 280
Quoted 8 lines
xen/arch/arm/head.S +8
-0+ /* Signal the next non-boot CPU to come and join us here */ + ldr r0, =boot_gate /* VA of gate */ + add r0, r0, r10 /* PA of gate */ + mov r1, #0 /* (0 == unlocked) */ + str r1, [r0] + dsb + isb + sev
Here we have released the next CPU from the holding pen...
[...]
xen/arch/arm/head.S paging: · line 300
Quoted 6 lines
xen/arch/arm/head.S +6
-0+ /* Non-boot CPUs report that they've got this far */ + ldr r0, =ready_cpus + ldr r1, [r0] /* Read count of ready CPUs */ + add r1, r1, #1 /* ++ */ + str r1, [r0] /* Writeback */ + dsb
... and here we do a non-atomic update of a shared variable.
What prevents the following CPU from catching us up and conflicting here?
Would we be better signalling the next CPU after the increment instead?
Ian.
Re: [PATCH 05 of 10] arm: More SMP bringup
Quoted 23 lines · Ian Campbell
On Thu, 2012-02-23 at 17:40 +0000, Tim Deegan wrote:
[...]xen/arch/arm/head.S paging: · line 280
Quoted 8 lines
xen/arch/arm/head.S +8
-0+ /* Signal the next non-boot CPU to come and join us here */ + ldr r0, =boot_gate /* VA of gate */ + add r0, r0, r10 /* PA of gate */ + mov r1, #0 /* (0 == unlocked) */ + str r1, [r0] + dsb + isb + sevHere we have released the next CPU from the holding pen...
[...]
xen/arch/arm/head.S paging: · line 300
Quoted 6 lines
xen/arch/arm/head.S +6
-0+ /* Non-boot CPUs report that they've got this far */ + ldr r0, =ready_cpus + ldr r1, [r0] /* Read count of ready CPUs */ + add r1, r1, #1 /* ++ */ + str r1, [r0] /* Writeback */ + dsb... and here we do a non-atomic update of a shared variable.
Quoted 4 lines
What prevents the following CPU from catching us up and conflicting here?
Would we be better signalling the next CPU after the increment instead?
Yes, we would. I'll fix that.
Tim.
PATCH 1/1 arm: per-cpu areas
In reply to Tim Deegan# HG changeset patch
# User Tim Deegan <[email protected]>
# Date 1330018799 0
# Node ID 3b1d7a91a2596baca178e8b5610b3cbc299fa5ea # Parent 1e9c6bd7cc99d1af0107aa927ee2ba03721449b7
arm: per-cpu areas
xen/arch/arm/Makefile +1 -0
@@ -13,6 +13,7 @@ obj-y += irq.o obj-y += kernel.o obj-y += mm.o obj-y += p2m.o +obj-y += percpu.o obj-y += guestcopy.o obj-y += setup.o obj-y += time.o
xen/arch/arm/dummy.S +0 -1
@@ -14,7 +14,6 @@ DUMMY(per_cpu__cpu_core_mask); DUMMY(per_cpu__cpu_sibling_mask); DUMMY(node_online_map); DUMMY(smp_send_state_dump); -DUMMY(__per_cpu_offset); /* PIRQ support */ DUMMY(alloc_pirq_struct);
xen/arch/arm/percpu.c new file +85 -0
85 lines not on this page · raw message
xen/include/asm-arm/percpu.h +5 -2
@@ -12,8 +12,11 @@ void percpu_init_areas(void); __attribute__((__section__(".bss.percpu" #suffix))) \ __typeof__(type) per_cpu_##name -#define per_cpu (var, cpu) ((&per_cpu__##var)[cpu?0:0]) -#define __get_cpu_var (var) per_cpu__##var + +#define per_cpu (var, cpu) \ + (*RELOC_HIDE(&per_cpu__##var, __per_cpu_offset[cpu])) +#define __get_cpu_var (var) \ + (*RELOC_HIDE(&per_cpu__##var, get_cpu_info()->per_cpu_offset))#define DECLARE_PER_CPU (type, name) extern __typeof__(type) per_cpu__##name
Re: [PATCH 06 of 10] arm: per-cpu areas
Quoted 8 lines · Tim Deegan
# HG changeset patch
# User Tim Deegan <[email protected]>
# Date 1330018799 0
# Node ID3b1d7a91a2596baca178e8b5610b3cbc299fa5ea# Parent1e9c6bd7cc99d1af0107aa927ee2ba03721449b7
arm: per-cpu areasSigned-off-by Tim Deegan <[email protected]>
I tried to apply this along with #1 and #4 but the result hung at just after freeing initial memory. I expect that's due to missing #2,#3 or #5 rather than a bug here.
With that in mind:
Quoted 129 lines
diff -r
1e9c6bd7cc99-r3b1d7a91a259xen/arch/arm/Makefilexen/arch/arm/Makefile +1
-0@@ -13,6 +13,7 @@ obj-y += irq.o obj-y += kernel.o obj-y += mm.o obj-y += p2m.o +obj-y += percpu.o obj-y += guestcopy.o obj-y += setup.o obj-y += time.odiff -r
1e9c6bd7cc99-r3b1d7a91a259xen/arch/arm/dummy.Sxen/arch/arm/dummy.S +0
-1@@ -14,7 +14,6 @@ DUMMY(per_cpu__cpu_core_mask); DUMMY(per_cpu__cpu_sibling_mask); DUMMY(node_online_map); DUMMY(smp_send_state_dump); -DUMMY(__per_cpu_offset); /* PIRQ support */ DUMMY(alloc_pirq_struct);diff -r
1e9c6bd7cc99-r3b1d7a91a259xen/arch/arm/percpu.cxen/arch/arm/percpu.c new file +85
-0@@ -0,0 +1,85 @@ +#include <xen/config.h> +#include <xen/percpu.h> +#include <xen/cpu.h> +#include <xen/init.h> +#include <xen/mm.h> +#include <xen/rcupdate.h> + +unsigned long __per_cpu_offset[NR_CPUS ]; +#define INVALID_PERCPU_AREA (-(long)__per_cpu_start) +#define PERCPU_ORDER (get_order_from_bytes(__per_cpu_data_end-__per_cpu_start)) + +void __init percpu_init_areas (void ) +{ +unsigned int cpu; +for ( cpu =1 ; cpu <NR_CPUS ; cpu++ ) + __per_cpu_offset[cpu] =INVALID_PERCPU_AREA ; +} + +static int init_percpu_area (unsigned int cpu) +{ +char *p; +if ( __per_cpu_offset[cpu] !=INVALID_PERCPU_AREA ) +return -EBUSY ; +if ( (p =alloc_xenheap_pages (PERCPU_ORDER ,0 )) ==NULL ) +return -ENOMEM ; +memset (p,0 , __per_cpu_data_end - __per_cpu_start); + __per_cpu_offset[cpu] = p - __per_cpu_start; +return 0 ; +} + +struct free_info { +unsigned int cpu; +struct rcu_head rcu; +}; +static DEFINE_PER_CPU(struct free_info, free_info); + +static void _free_percpu_area (struct rcu_head *head) +{ + struct free_info *info = container_of(head, struct free_info, rcu); +unsigned int cpu = info->cpu; +char *p = __per_cpu_start + __per_cpu_offset[cpu]; +free_xenheap_pages (p,PERCPU_ORDER ); + __per_cpu_offset[cpu] =INVALID_PERCPU_AREA ; +} + +static void free_percpu_area (unsigned int cpu) +{ +struct free_info *info = &per_cpu (free_info, cpu); + info->cpu = cpu; +call_rcu (&info->rcu, _free_percpu_area); +} + +static int cpu_percpu_callback ( +struct notifier_block *nfb,unsigned long action,void *hcpu) +{ +unsigned int cpu = (unsigned long )hcpu; +int rc =0 ; + +switch ( action ) + { +case CPU_UP_PREPARE : + rc =init_percpu_area (cpu); +break ; +case CPU_UP_CANCELED : +case CPU_DEAD : +free_percpu_area (cpu); +break ; +default : +break ; + } + +return !rc ?NOTIFY_DONE :notifier_from_errno (rc); +} + +static struct notifier_block cpu_percpu_nfb = { + .notifier_call = cpu_percpu_callback, + .priority =100 /* highest priority */ +}; + +static int __init percpu_presmp_init (void ) +{ +register_cpu_notifier (&cpu_percpu_nfb); +return 0 ; +} +presmp_initcall (percpu_presmp_init);diff -r
1e9c6bd7cc99-r3b1d7a91a259xen/include/asm-arm/percpu.hxen/include/asm-arm/percpu.h +5
-2@@ -12,8 +12,11 @@ void percpu_init_areas(void); __attribute__((__section__(".bss.percpu" #suffix))) \ __typeof__(type) per_cpu_##name -#define per_cpu (var, cpu) ((&per_cpu__##var)[cpu?0:0]) -#define __get_cpu_var (var) per_cpu__##var + +#define per_cpu (var, cpu) \ + (*RELOC_HIDE(&per_cpu__##var, __per_cpu_offset[cpu])) +#define __get_cpu_var (var) \ + (*RELOC_HIDE(&per_cpu__##var, get_cpu_info()->per_cpu_offset))#define DECLARE_PER_CPU (type, name) extern __typeof__(type) per_cpu__##name
PATCH 1/1 arm: start plumbing in SMP bringup in C
In reply to Tim Deegan# HG changeset patch
# User Tim Deegan <[email protected]>
# Date 1330018799 0
# Node ID fd78d23ba19de4129e21cdc7303848b105057227 # Parent 3b1d7a91a2596baca178e8b5610b3cbc299fa5ea
arm: start plumbing in SMP bringup in C
Still a noop, but no longer just a dummy symbol.
xen/arch/arm/dummy.S +0 -3
@@ -7,9 +7,6 @@ x: .word 0xe7f000f0 /* Undefined instruc x: mov pc, lr /* SMP support */ -DUMMY(__cpu_die); -DUMMY(__cpu_disable); -DUMMY(__cpu_up); DUMMY(per_cpu__cpu_core_mask); DUMMY(per_cpu__cpu_sibling_mask); DUMMY(node_online_map);
xen/arch/arm/setup.c +2 -5
@@ -38,9 +38,6 @@#include <asm/setup.h> #include "gic.h" -/* maxcpus: maximum number of CPUs to activate. */ -static unsigned int __initdata max_cpus =NR_CPUS ; -/* Xen stack for bringing up the first CPU. */ unsigned char __initdata init_stack[STACK_SIZE] __attribute__((__aligned__(STACK_SIZE)));
@@ -206,7 +203,7 @@ void __init start_xen(unsigned long bootcpumask_set_cpu (smp_processor_id (), &cpu_online_map);cpumask_set_cpu (smp_processor_id (), &cpu_present_map); -smp_prepare_cpus (max_cpus); +smp_prepare_cpus (cpus);init_xen_time ();
@@ -253,7 +250,7 @@ void __init start_xen(unsigned long bootfor_each_present_cpu ( i ) { -if ( (num_online_cpus () < max_cpus) && !cpu_online (i) ) +if ( (num_online_cpus () < cpus) && !cpu_online (i) ) {int ret =cpu_up (i);if ( ret !=0 )
xen/arch/arm/smpboot.c +33 -8
55 lines not on this page · raw message
Re: [PATCH 07 of 10] arm: start plumbing in SMP bringup in C
Quoted 10 lines · Tim Deegan
# HG changeset patch
# User Tim Deegan <[email protected]>
# Date 1330018799 0
# Node IDfd78d23ba19de4129e21cdc7303848b105057227# Parent3b1d7a91a2596baca178e8b5610b3cbc299fa5ea
arm: start plumbing in SMP bringup in CStill a noop, but no longer just a dummy symbol.
Signed-off-by Tim Deegan <[email protected]>
Quoted 104 lines
diff -r
3b1d7a91a259-rfd78d23ba19dxen/arch/arm/dummy.Sxen/arch/arm/dummy.S +0
-3@@ -7,9 +7,6 @@ x: .word 0xe7f000f0 /* Undefined instruc x: mov pc, lr /* SMP support */ -DUMMY(__cpu_die); -DUMMY(__cpu_disable); -DUMMY(__cpu_up); DUMMY(per_cpu__cpu_core_mask); DUMMY(per_cpu__cpu_sibling_mask); DUMMY(node_online_map);diff -r
3b1d7a91a259-rfd78d23ba19dxen/arch/arm/setup.cxen/arch/arm/setup.c +2
-5@@ -38,9 +38,6 @@#include <asm/setup.h> #include "gic.h" -/* maxcpus: maximum number of CPUs to activate. */ -static unsigned int __initdata max_cpus =NR_CPUS ; -/* Xen stack for bringing up the first CPU. */ unsigned char __initdata init_stack[STACK_SIZE] __attribute__((__aligned__(STACK_SIZE)));@@ -206,7 +203,7 @@ void __init start_xen(unsigned long bootcpumask_set_cpu (smp_processor_id (), &cpu_online_map);cpumask_set_cpu (smp_processor_id (), &cpu_present_map); -smp_prepare_cpus (max_cpus); +smp_prepare_cpus (cpus);init_xen_time ();@@ -253,7 +250,7 @@ void __init start_xen(unsigned long bootfor_each_present_cpu ( i ) { -if ( (num_online_cpus () < max_cpus) && !cpu_online (i) ) +if ( (num_online_cpus () < cpus) && !cpu_online (i) ) {int ret =cpu_up (i);if ( ret !=0 )diff -r
3b1d7a91a259-rfd78d23ba19dxen/arch/arm/smpboot.cxen/arch/arm/smpboot.c +33
-8@@ -19,6 +19,7 @@#include <xen/cpumask.h> #include <xen/smp.h> #include <xen/init.h> +#include <xen/errno.h> cpumask_t cpu_online_map;EXPORT_SYMBOL (cpu_online_map);@@ -30,16 +31,40 @@ EXPORT_SYMBOL(cpu_possible_map);void __init smp_prepare_cpus (unsigned int max_cpus) { -set_processor_id (0 );/* needed early, for smp_processor_id() */ +int i; +set_processor_id (0 );/* needed early, for smp_processor_id() */ -cpumask_clear (&cpu_online_map); -cpumask_clear (&cpu_present_map); -cpumask_clear (&cpu_possible_map); -cpumask_set_cpu (0 , &cpu_online_map); -cpumask_set_cpu (0 , &cpu_present_map); -cpumask_set_cpu (0 , &cpu_possible_map); -return ; +cpumask_clear (&cpu_online_map); +cpumask_set_cpu (0 , &cpu_online_map); + +cpumask_clear (&cpu_possible_map); +for ( i =0 ; i < max_cpus; i++ ) +cpumask_set_cpu (i, &cpu_possible_map); +cpumask_copy (&cpu_present_map, &cpu_possible_map); } + +/* Bring up a non-boot CPU */ +int __cpu_up (unsigned int cpu) +{ +/* Not yet... */ +return -ENODEV ; +} + +/* Shut down the current CPU */ +void __cpu_disable (void ) +{ +/* TODO: take down timers, GIC, &c. */ +BUG (); +} + +/* Wait for a remote CPU to die */ +void __cpu_die (unsigned int cpu) +{ +/* TODO: interlock with __cpu_disable */ +BUG (); +} + +/* * Local variables: * mode: C
PATCH 1/1 arm: Boot secondary CPUs into C
In reply to Tim Deegan# HG changeset patch
# User Tim Deegan <[email protected]>
# Date 1330018799 0
# Node ID d35b52e5fde829dfbaf3da73e0716d004faded2f # Parent fd78d23ba19de4129e21cdc7303848b105057227
arm: Boot secondary CPUs into C
xen/arch/arm/gic.c +9 -1
@@ -241,7 +241,6 @@ static void __cpuinit gic_hyp_init(void) vtr =GICH [GICH_VTR ]; nr_lrs = (vtr &GICH_VTR_NRLRGS ) +1 ; -printk ("GICH: %d list registers available\n" , nr_lrs);GICH [GICH_HCR ] =GICH_HCR_EN ;GICH [GICH_MISR ] =GICH_MISR_EOI ;
@@ -274,6 +273,15 @@ int __init gic_init(void)return gic.cpus; } +/* Set up the per-CPU parts of the GIC for a secondary CPU */ +void __cpuinit gic_init_secondary_cpu (void ) +{ +spin_lock (&gic.lock); +gic_cpu_init (); +gic_hyp_init (); +spin_unlock (&gic.lock); +} +void gic_route_irqs (void ) {/* XXX should get these from DT */
xen/arch/arm/gic.h +2 -0
@@ -140,6 +140,8 @@ extern int gic_route_irq_to_guest(structextern void gic_interrupt (struct cpu_user_regs *regs,int is_fiq);/* Bring up the interrupt controller, and report # cpus attached */ extern int gic_init (void ); +/* Bring up a secondary CPU's per-CPU GIC interface */ +extern void gic_init_secondary_cpu (void );/* setup the gic virtual interface for a guest */ extern void gicv_setup (struct domain *d);#endif
xen/arch/arm/head.S +10 -4
@@ -305,17 +305,23 @@ paging: * and brought up the memory allocator, non-boot CPUs can get their * own stacks and enter C. */ 1: wfe - b 1b + dsb + ldr r0, =smp_up_cpu + ldr r1, [r0] /* Which CPU is being booted? */ + teq r1, r12 /* Is it us? */ + bne 1b launch: - ldr sp, =init_stack /* Supply a stack */ + ldr r0, =init_stacks /* Find the boot-time stack */ + ldr sp, [r0, r12, lsl #2] /* (the one for this CPU) */ add sp, #STACK_SIZE /* (which grows down from the top). */ sub sp, #CPUINFO_sizeof /* Make room for CPU save record */ mov r0, r10 /* Marshal args: - phys_offset */ mov r1, r7 /* - machine type */ mov r2, r8 /* - ATAG address */ - mov r3, r12 /* - CPU ID */ - b start_xen /* and disappear into the land of C */ + movs r3, r12 /* - CPU ID */ + beq start_xen /* and disappear into the land of C */ + b start_secondary /* (to the appropriate entry point) */ /* Fail-stop * r0: string explaining why */
xen/arch/arm/setup.c +2 -3
@@ -38,9 +38,6 @@#include <asm/setup.h> #include "gic.h" -/* Xen stack for bringing up the first CPU. */ -unsigned char __initdata init_stack[STACK_SIZE] __attribute__((__aligned__(STACK_SIZE))); -extern const char __init_begin[], __init_end[], __bss_start[];/* Spinlock for serializing CPU bringup */
@@ -179,6 +176,8 @@ void __init start_xen(unsigned long bootconsole_init_preirq ();#endif +percpu_init_areas (); + cpus =gic_init ();printk ("Waiting for %i other CPUs to be ready\n" , cpus -1 );
xen/arch/arm/smpboot.c +77 -6
110 lines not on this page · raw message
Re: [PATCH 08 of 10] arm: Boot secondary CPUs into C
Quoted 8 lines · Tim Deegan
# HG changeset patch
# User Tim Deegan <[email protected]>
# Date 1330018799 0
# Node IDd35b52e5fde829dfbaf3da73e0716d004faded2f# Parentfd78d23ba19de4129e21cdc7303848b105057227
arm: Boot secondary CPUs into CSigned-off-by Tim Deegan <[email protected]>
I think this need rebasing a bit past the per-vcpu stacks changes so I wont' ack just yet although I like the general shape of it.
xen/arch/arm/smpboot.c EXPORT_SYMBOL(cpu_online_map); · line 42
Quoted 11 lines
xen/arch/arm/smpboot.c +7
-0@@ -28,6 +33,14 @@ EXPORT_SYMBOL(cpu_online_map);cpumask_t cpu_possible_map;EXPORT_SYMBOL (cpu_possible_map); +/* Xen stack for bringing up the first CPU. */ +static unsigned char cpu0_stack[STACK_SIZE] + __attribute__((__aligned__(STACK_SIZE))); + +/* Remember where the boot-time stacks live */ +/* TODO: overhaul this, and get_processor_id(), for per-vcpu stacks */ +unsigned char *init_stacks[NR_CPUS ] = { cpu0_stack,0 };
Do we need to track the per-CPU idle stacks after the CPUs have been brought up?
We are already serialized due to the use of the shared smp_up_cpu so could we get away with a single "smp_bringup_args" area and avoid the NR_CPUS array?
Ian.
PATCH 1/1 arm: SMP CPU shutdown
In reply to Tim Deegan# HG changeset patch
# User Tim Deegan <[email protected]>
# Date 1330018799 0
# Node ID a78bc9b8421492e0545c6d52c7a32b9de9737d61 # Parent d35b52e5fde829dfbaf3da73e0716d004faded2f
arm: SMP CPU shutdown
For completeness, also implelent the CPU shutdown path.
xen/arch/arm/domain.c +4 -6
@@ -31,12 +31,10 @@ void idle_loop(void) {for ( ; ; ) { -/* TODO -if ( cpu_is_offline(smp_processor_id()) ) -play_dead(); -(*pm_idle)(); -BUG(); -*/ +if (cpu_is_offline (smp_processor_id ()) ) +stop_cpu (); + +/* TODO: (*pm_idle)(); */ do_tasklet ();do_softirq (); }
xen/arch/arm/gic.c +19 -0
@@ -235,6 +235,11 @@ static void __cpuinit gic_cpu_init(void)GICC [GICC_CTLR ] =GICC_CTL_ENABLE |GICC_CTL_EOI ;/* Turn on delivery */ } +static void gic_cpu_disable (void ) +{ +GICC [GICC_CTLR ] =0 ; +} +static void __cpuinit gic_hyp_init (void ) {uint32_t vtr;
@@ -246,6 +251,11 @@ static void __cpuinit gic_hyp_init(void)GICH [GICH_MISR ] =GICH_MISR_EOI ; } +static void __cpuinit gic_hyp_disable (void ) +{ +GICH [GICH_HCR ] =0 ; +} +/* Set up the GIC */ int __init gic_init (void ) {
@@ -282,6 +292,15 @@ void __cpuinit gic_init_secondary_cpu(vospin_unlock (&gic.lock); } +/* Shut down the per-CPU GIC interface */ +void gic_disable_cpu (void ) +{ +spin_lock (&gic.lock); +gic_cpu_disable (); +gic_hyp_disable (); +spin_unlock (&gic.lock); +} +void gic_route_irqs (void ) {/* XXX should get these from DT */
xen/arch/arm/gic.h +2 -0
@@ -142,6 +142,8 @@ extern void gic_interrupt(struct cpu_useextern int gic_init (void );/* Bring up a secondary CPU's per-CPU GIC interface */ extern void gic_init_secondary_cpu (void ); +/* Take down a CPU's per-CPU GIC interface */ +extern void gic_disable_cpu (void );/* setup the gic virtual interface for a guest */ extern void gicv_setup (struct domain *d);#endif
xen/arch/arm/smpboot.c +44 -4
72 lines not on this page · raw message
xen/include/asm-arm/smp.h +2 -0
@@ -14,6 +14,8 @@ DECLARE_PER_CPU(cpumask_var_t, cpu_core_#define raw_smp_processor_id () (get_processor_id()) +extern void stop_cpu (void ); +#endif /* * Local variables:
Re: [PATCH 09 of 10] arm: SMP CPU shutdown
Quoted 8 lines · Tim Deegan
# HG changeset patch
# User Tim Deegan <[email protected]>
# Date 1330018799 0
# Node IDa78bc9b8421492e0545c6d52c7a32b9de9737d61# Parentd35b52e5fde829dfbaf3da73e0716d004faded2f
arm: SMP CPU shutdownFor completeness, also implelent the CPU shutdown path.
Does something free the init_stack for a CPU as it goes down?
Alternatively the bring up path could reuse it if the CPU came back but we don't seem to do that either.
Quoted 1 line
Signed-off-by TIm Deegan <[email protected]>
Typo here.
[...]
xen/arch/arm/smpboot.c void __cpuinit start_secondary(unsigned · line 119
Quoted 8 lines
xen/arch/arm/smpboot.c +8
-0+/* It's now safe to remove this processor from the online map */ +cpumask_clear_cpu (cpu, &cpu_online_map); + +if (cpu_disable_scheduler (cpu) ) +BUG (); +mb (); + +/* Return to caller; eventually the IPI mecahnism will unwind and the
mechanism
xen/arch/arm/smpboot.c void __cpuinit start_secondary(unsigned · line 126
Quoted 7 lines
xen/arch/arm/smpboot.c +7
-0+* scheduler will drop to the idle loop, which will call stop_cpu(). */ +} + +void stop_cpu (void ) +{ +local_irq_disable (); + cpu_is_dead =1 ;
Do we lock this variable? What stops multiple CPUs coming down at once?
xen/arch/arm/smpboot.c void __cpuinit start_secondary(unsigned · line 134
Quoted 8 lines
xen/arch/arm/smpboot.c +5
-0+/* Make sure the write happens before we sleep forever */ +dsb (); +isb (); +while (1 ) + asmvolatile ("wfi" ); }/* Bring up a remote CPU */
Ian.
Re: [PATCH 09 of 10] arm: SMP CPU shutdown
Quoted 11 lines · Ian Campbell
Quoted 8 lines · Tim Deegan
# HG changeset patch
# User Tim Deegan <[email protected]>
# Date 1330018799 0
# Node IDa78bc9b8421492e0545c6d52c7a32b9de9737d61# Parentd35b52e5fde829dfbaf3da73e0716d004faded2f
arm: SMP CPU shutdownFor completeness, also implelent the CPU shutdown path.
Does something free the
init_stackfor a CPU as it goes down?
Er, no. :)
Quoted 2 lines
Alternatively the bring up path could reuse it if the CPU came back but we don't seem to do that either.
I'll make it so.
Quoted 3 lines
Quoted 1 line
Signed-off-by TIm Deegan <[email protected]>Typo here.
WHat TYpo? I ALways SIgn MY NAme THat WAy.
Quoted 11 lines
[...]
xen/arch/arm/smpboot.c void __cpuinit start_secondary(unsigned · line 119
Quoted 8 lines
xen/arch/arm/smpboot.c +8
-0+/* It's now safe to remove this processor from the online map */ +cpumask_clear_cpu (cpu, &cpu_online_map); + +if (cpu_disable_scheduler (cpu) ) +BUG (); +mb (); + +/* Return to caller; eventually the IPI mecahnism will unwind and the mechanism
ta.
Quoted 9 lines
xen/arch/arm/smpboot.c void __cpuinit start_secondary(unsigned · line 126
Quoted 7 lines
xen/arch/arm/smpboot.c +7
-0+* scheduler will drop to the idle loop, which will call stop_cpu(). */ +} + +void stop_cpu (void ) +{ +local_irq_disable (); + cpu_is_dead =1 ;Do we lock this variable? What stops multiple CPUs coming down at once?
IIRC that's serialized at a higher level, and the x86 equivalent similarly uses static variables for signalling. Will double-check before I re-send this series (probably next week).
Cheers,
Tim.
PATCH 1/1 arm: Shutdown and reboot
In reply to Tim Deegan# HG changeset patch
# User Tim Deegan <[email protected]>
# Date 1330018799 0
# Node ID 8a2d38ab67ccaf8637e223feb0d0678433974e93 # Parent a78bc9b8421492e0545c6d52c7a32b9de9737d61
arm: Shutdown and reboot
Reboot runes grabbed from linux's SP810 reset function. Doesn't seem to work on the model, though.
xen/arch/arm/shutdown.c +50 -5
@@ -1,18 +1,63 @@#include <xen/config.h> +#include <xen/console.h> +#include <xen/cpu.h> +#include <xen/delay.h> #include <xen/lib.h> +#include <xen/mm.h> +#include <xen/smp.h> + +static void raw_machine_reset (void ) +{ +#ifdef SP810_ADDRESS +/* Use the SP810 system controller to force a reset */ +volatile uint32_t *sp810; +set_fixmap (FIXMAP_MISC ,SP810_ADDRESS >>PAGE_SHIFT ,DEV_SHARED ); + sp810 = ((uint32_t *) + (FIXMAP_ADDR (FIXMAP_MISC ) + (SP810_ADDRESS & ~PAGE_MASK ))); + sp810[0 ] =0x3 ;/* switch to slow mode */ +dsb ();isb (); + sp810[1 ] =0x1 ;/* writing any value to SCSYSSTAT reg will reset system */ +dsb ();isb (); +clear_fixmap (FIXMAP_MISC ); +#endif +} + +static void halt_this_cpu (void *arg) +{ +__cpu_disable (); +stop_cpu (); +}void machine_halt (void ) { -/* TODO: halt */ -while (1 ) ; +watchdog_disable (); +console_start_sync (); +local_irq_enable (); +smp_call_function (halt_this_cpu,NULL ,0 ); +halt_this_cpu (NULL ); }void machine_restart (unsigned int delay_millisecs) { -/* TODO: restart */ -printk ("Cannot restart yet\n" ); -while (1 ); +int timeout =10 ; + +local_irq_enable (); +smp_call_function (halt_this_cpu,NULL ,0 ); +local_irq_disable (); + +mdelay (delay_millisecs); + +/* Wait at most another 10ms for all other CPUs to go offline. */ +while ( (num_online_cpus () >1 ) && (timeout-- >0 ) ) +mdelay (1 ); + +while (1 ) + { +raw_machine_reset (); +mdelay (100 ); + } } +/* * Local variables: * mode: C
xen/include/asm-arm/config.h +3 -0
@@ -119,6 +119,9 @@ extern unsigned long frametable_virt_end#define GIC_CR_OFFSET 0x2000#define GIC_HR_OFFSET 0x4000/* Guess work http://lists.infradead.org/pipermail/linux-arm-kernel/2011-September/064219.html */ #define GIC_VR_OFFSET 0x6000/* Virtual Machine CPU interface) */ +/* Board-specific: base address of system controller */ +#define SP810_ADDRESS 0x1C020000 +#endif /* __ARM_CONFIG_H__ */ /*
Re: [PATCH 10 of 10] arm: Shutdown and reboot
Quoted 11 lines · Tim Deegan
# HG changeset patch
# User Tim Deegan <[email protected]>
# Date 1330018799 0
# Node ID8a2d38ab67ccaf8637e223feb0d0678433974e93# Parenta78bc9b8421492e0545c6d52c7a32b9de9737d61
arm: Shutdown and rebootReboot runes grabbed from linux's SP810 reset function. Doesn't seem to work on the model, though.
Signed-off-by Tim Deegan <[email protected]>
But please add an "XXX get this from device tree" somewhere appropriate ;-)
Quoted 86 lines
diff -r
a78bc9b84214-r8a2d38ab67ccxen/arch/arm/shutdown.cxen/arch/arm/shutdown.c +50
-5@@ -1,18 +1,63 @@#include <xen/config.h> +#include <xen/console.h> +#include <xen/cpu.h> +#include <xen/delay.h> #include <xen/lib.h> +#include <xen/mm.h> +#include <xen/smp.h> + +static void raw_machine_reset (void ) +{ +#ifdef SP810_ADDRESS +/* Use the SP810 system controller to force a reset */ +volatile uint32_t *sp810; +set_fixmap (FIXMAP_MISC ,SP810_ADDRESS >>PAGE_SHIFT ,DEV_SHARED ); + sp810 = ((uint32_t *) + (FIXMAP_ADDR (FIXMAP_MISC ) + (SP810_ADDRESS & ~PAGE_MASK ))); + sp810[0 ] =0x3 ;/* switch to slow mode */ +dsb ();isb (); + sp810[1 ] =0x1 ;/* writing any value to SCSYSSTAT reg will reset system */ +dsb ();isb (); +clear_fixmap (FIXMAP_MISC ); +#endif +} + +static void halt_this_cpu (void *arg) +{ +__cpu_disable (); +stop_cpu (); +}void machine_halt (void ) { -/* TODO: halt */ -while (1 ) ; +watchdog_disable (); +console_start_sync (); +local_irq_enable (); +smp_call_function (halt_this_cpu,NULL ,0 ); +halt_this_cpu (NULL ); }void machine_restart (unsigned int delay_millisecs) { -/* TODO: restart */ -printk ("Cannot restart yet\n" ); -while (1 ); +int timeout =10 ; + +local_irq_enable (); +smp_call_function (halt_this_cpu,NULL ,0 ); +local_irq_disable (); + +mdelay (delay_millisecs); + +/* Wait at most another 10ms for all other CPUs to go offline. */ +while ( (num_online_cpus () >1 ) && (timeout-- >0 ) ) +mdelay (1 ); + +while (1 ) + { +raw_machine_reset (); +mdelay (100 ); + } } +/* * Local variables: * mode: C diff -r
a78bc9b84214-r8a2d38ab67ccxen/include/asm-arm/config.hxen/include/asm-arm/config.h +3
-0@@ -119,6 +119,9 @@ extern unsigned long frametable_virt_end#define GIC_CR_OFFSET 0x2000#define GIC_HR_OFFSET 0x4000/* Guess work http://lists.infradead.org/pipermail/linux-arm-kernel/2011-September/064219.html */ #define GIC_VR_OFFSET 0x6000/* Virtual Machine CPU interface) */ +/* Board-specific: base address of system controller */ +#define SP810_ADDRESS 0x1C020000 +#endif /* __ARM_CONFIG_H__ */ /*
Quoted 5 lines · Tim Deegan
This patch series implements SMP boot for
arch/arm, as far as getting all CPUs up and running the idle loop.The first few patches are semi-independent cleanups and improvements, most of which are needed for the SMP patches later.
I have applied:
01: arm: strip xen binary
04: arm: Handle booting on SMP platforms
I looked at taking a few others but they had dependencies on things which I or others have commented on. I'll go through and ack them as appropriate now.
Ian.
Quoted 2 lines · Tim Deegan
This patch series implements SMP boot for
arch/arm, as far as getting all CPUs up and running the idle loop.
What additional steps are needed when building the model to get an SMP system?
Ideally this would eventually be documented in
http://wiki.xen.org/wiki/Xen_ARMv7_with_Virtualization_Extensions/FastModels but it is probably a bit premature for that right now.
I think it is sufficient to do the following after opening the project ("sgcanvas <SGPROJ>") and before clicking the "Build" button.
* Right click the header of the "cluster" in the diagram (the top bit of the box which says "cluster" in it)
* Select "Object Properties" from the context menu
* In the "Parameters" tab update the "num_cores" variable, e.g. to "0x4"
* Click build and continue as usual.
Do that sound about right? It appears to work for me at least. I've not applied all your patches so I can't see how many processors there really are.
Ian.
Quoted 13 lines · Ian Campbell
Quoted 2 lines · Tim Deegan
This patch series implements SMP boot for
arch/arm, as far as getting all CPUs up and running the idle loop.What additional steps are needed when building the model to get an SMP system?
Ideally this would eventually be documented in
http://wiki.xen.org/wiki/Xen_ARMv7_with_Virtualization_Extensions/FastModels but it is probably a bit premature for that right now.I think it is sufficient to do the following after opening the project ("sgcanvas <SGPROJ>") and before clicking the "Build" button.
Quoted 6 lines
* Right click the header of the "cluster" in the diagram (the top bit of the box which says "cluster" in it)
* Select "Object Properties" from the context menu
* In the "Parameters" tab update the "num_cores" variable, e.g. to "0x4"
* Click build and continue as usual.
Yes, that is exactly what I did.
Tim.