All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00 of 10] arm: SMP boot
@ 2012-02-23 17:40 Tim Deegan
  2012-02-23 17:40 ` [PATCH 01 of 10] arm: strip xen binary Tim Deegan
                   ` (11 more replies)
  0 siblings, 12 replies; 27+ messages in thread
From: Tim Deegan @ 2012-02-23 17:40 UTC (permalink / raw)
  To: xen-devel; +Cc: Stefano Stabellini, Ian Campbell

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.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 01 of 10] arm: strip xen binary
  2012-02-23 17:40 [PATCH 00 of 10] arm: SMP boot Tim Deegan
@ 2012-02-23 17:40 ` Tim Deegan
  2012-02-23 17:40 ` [PATCH 02 of 10] arm: implement udelay() Tim Deegan
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 27+ messages in thread
From: Tim Deegan @ 2012-02-23 17:40 UTC (permalink / raw)
  To: xen-devel; +Cc: Stefano Stabellini, Ian Campbell

# HG changeset patch
# User Tim Deegan <tim@xen.org>
# 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.

Signed-off-by: Tim Deegan <tim@xen.org>

diff -r 0c3d19f40ab1 -r 4a7c14209131 xen/arch/arm/Makefile
--- a/xen/arch/arm/Makefile	Mon Feb 20 22:16:32 2012 +0100
+++ b/xen/arch/arm/Makefile	Thu Feb 23 17:39:59 2012 +0000
@@ -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 \

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 02 of 10] arm: implement udelay()
  2012-02-23 17:40 [PATCH 00 of 10] arm: SMP boot Tim Deegan
  2012-02-23 17:40 ` [PATCH 01 of 10] arm: strip xen binary Tim Deegan
@ 2012-02-23 17:40 ` Tim Deegan
  2012-02-23 19:03   ` David Vrabel
  2012-02-23 17:40 ` [PATCH 03 of 10] arm: Move some GIC distributor init out of the per-CPU init function Tim Deegan
                   ` (9 subsequent siblings)
  11 siblings, 1 reply; 27+ messages in thread
From: Tim Deegan @ 2012-02-23 17:40 UTC (permalink / raw)
  To: xen-devel; +Cc: Stefano Stabellini, Ian Campbell

# HG changeset patch
# User Tim Deegan <tim@xen.org>
# Date 1330018799 0
# Node ID ec051056db2b6d37344629e2f01d17240099d5ec
# Parent  4a7c1420913135fbeba361cd9603e748c074cdac
arm: implement udelay()

Signed-off-by: Tim Deegan <tim@xen.org>

diff -r 4a7c14209131 -r ec051056db2b xen/arch/arm/dummy.S
--- a/xen/arch/arm/dummy.S	Thu Feb 23 17:39:59 2012 +0000
+++ b/xen/arch/arm/dummy.S	Thu Feb 23 17:39:59 2012 +0000
@@ -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);
diff -r 4a7c14209131 -r ec051056db2b xen/arch/arm/time.c
--- a/xen/arch/arm/time.c	Thu Feb 23 17:39:59 2012 +0000
+++ b/xen/arch/arm/time.c	Thu Feb 23 17:39:59 2012 +0000
@@ -171,6 +171,16 @@ void __cpuinit init_timer_interrupt(void
     request_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
diff -r 4a7c14209131 -r ec051056db2b xen/include/asm-arm/delay.h
--- a/xen/include/asm-arm/delay.h	Thu Feb 23 17:39:59 2012 +0000
+++ b/xen/include/asm-arm/delay.h	Thu Feb 23 17:39:59 2012 +0000
@@ -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) */
 /*

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 03 of 10] arm: Move some GIC distributor init out of the per-CPU init function
  2012-02-23 17:40 [PATCH 00 of 10] arm: SMP boot Tim Deegan
  2012-02-23 17:40 ` [PATCH 01 of 10] arm: strip xen binary Tim Deegan
  2012-02-23 17:40 ` [PATCH 02 of 10] arm: implement udelay() Tim Deegan
@ 2012-02-23 17:40 ` Tim Deegan
  2012-02-27 17:32   ` Ian Campbell
  2012-02-23 17:40 ` [PATCH 04 of 10] arm: Handle booting on SMP platforms Tim Deegan
                   ` (8 subsequent siblings)
  11 siblings, 1 reply; 27+ messages in thread
From: Tim Deegan @ 2012-02-23 17:40 UTC (permalink / raw)
  To: xen-devel; +Cc: Stefano Stabellini, Ian Campbell

# HG changeset patch
# User Tim Deegan <tim@xen.org>
# Date 1330018799 0
# Node ID 437ad1207a175c9ad376871f3f4c075dbcd5b6e6
# Parent  ec051056db2b6d37344629e2f01d17240099d5ec
arm: Move some GIC distributor init out of the per-CPU init function

Signed-off-by: Tim Deegan <tim@xen.org>

diff -r ec051056db2b -r 437ad1207a17 xen/arch/arm/gic.c
--- a/xen/arch/arm/gic.c	Thu Feb 23 17:39:59 2012 +0000
+++ b/xen/arch/arm/gic.c	Thu Feb 23 17:39:59 2012 +0000
@@ -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 */

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 04 of 10] arm: Handle booting on SMP platforms
  2012-02-23 17:40 [PATCH 00 of 10] arm: SMP boot Tim Deegan
                   ` (2 preceding siblings ...)
  2012-02-23 17:40 ` [PATCH 03 of 10] arm: Move some GIC distributor init out of the per-CPU init function Tim Deegan
@ 2012-02-23 17:40 ` Tim Deegan
  2012-02-23 17:40 ` [PATCH 05 of 10] arm: More SMP bringup Tim Deegan
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 27+ messages in thread
From: Tim Deegan @ 2012-02-23 17:40 UTC (permalink / raw)
  To: xen-devel; +Cc: Stefano Stabellini, Ian Campbell

# HG changeset patch
# User Tim Deegan <tim@xen.org>
# 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.

Signed-off-by: Tim Deegan <tim@xen.org>

diff -r 437ad1207a17 -r 8f322ab53857 xen/arch/arm/head.S
--- a/xen/arch/arm/head.S	Thu Feb 23 17:39:59 2012 +0000
+++ b/xen/arch/arm/head.S	Thu Feb 23 17:39:59 2012 +0000
@@ -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 */
diff -r 437ad1207a17 -r 8f322ab53857 xen/include/asm-arm/cpregs.h
--- a/xen/include/asm-arm/cpregs.h	Thu Feb 23 17:39:59 2012 +0000
+++ b/xen/include/asm-arm/cpregs.h	Thu Feb 23 17:39:59 2012 +0000
@@ -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 */

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 05 of 10] arm: More SMP bringup
  2012-02-23 17:40 [PATCH 00 of 10] arm: SMP boot Tim Deegan
                   ` (3 preceding siblings ...)
  2012-02-23 17:40 ` [PATCH 04 of 10] arm: Handle booting on SMP platforms Tim Deegan
@ 2012-02-23 17:40 ` Tim Deegan
  2012-02-23 19:16   ` Ian Campbell
  2012-02-23 17:40 ` [PATCH 06 of 10] arm: per-cpu areas Tim Deegan
                   ` (6 subsequent siblings)
  11 siblings, 1 reply; 27+ messages in thread
From: Tim Deegan @ 2012-02-23 17:40 UTC (permalink / raw)
  To: xen-devel; +Cc: Stefano Stabellini, Ian Campbell

# HG changeset patch
# User Tim Deegan <tim@xen.org>
# 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.

Signed-off-by: Tim Deegan <tim@xen.org>

diff -r 8f322ab53857 -r 1e9c6bd7cc99 xen/arch/arm/gic.c
--- a/xen/arch/arm/gic.c	Thu Feb 23 17:39:59 2012 +0000
+++ b/xen/arch/arm/gic.c	Thu Feb 23 17:39:59 2012 +0000
@@ -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)
diff -r 8f322ab53857 -r 1e9c6bd7cc99 xen/arch/arm/gic.h
--- a/xen/arch/arm/gic.h	Thu Feb 23 17:39:59 2012 +0000
+++ b/xen/arch/arm/gic.h	Thu Feb 23 17:39:59 2012 +0000
@@ -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
diff -r 8f322ab53857 -r 1e9c6bd7cc99 xen/arch/arm/head.S
--- a/xen/arch/arm/head.S	Thu Feb 23 17:39:59 2012 +0000
+++ b/xen/arch/arm/head.S	Thu Feb 23 17:39:59 2012 +0000
@@ -62,22 +62,36 @@ start:
 #endif
 
 	/* Are we the boot CPU? */
+	mov   r12, #0                /* r12 := CPU ID */
 	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 */
+	bics  r12, r0, #(0xff << 24) /* Mask out flags to get CPU ID */
+	beq   boot_cpu               /* If we're CPU 0, boot now */
 
-1:	wfi
-	b     1b
-	
+	/* Non-boot CPUs wait here to be woken up one at a time.
+	 * This is basically an open-coded spin-lock to serialize. */
+	ldr   r0, =boot_gate         /* VA of gate */
+	add   r0, r0, r10            /* PA of gate */
+	mov   r1, #1                 /* (1 == locked) */
+1:	wfe
+	ldrex r2, [r0]               /* Linked read of current value */
+	teq   r2, #0                 /* (0 == unlocked) */
+	strexeq r2, r1, [r0]         /* Matching update -> locked */
+	teq   r2, #0                 /* (0 == succeeded) */
+	bne   1b
+
 boot_cpu:
 #ifdef EARLY_UART_ADDRESS
-	/* Say hello */
 	ldr   r11, =EARLY_UART_ADDRESS  /* r11 := UART base address */
-	bl    init_uart
+	teq   r12, #0                   /* CPU 0 sets up the UART too */
+	bleq  init_uart
+	PRINT("- CPU ")
+	mov   r0, r12
+	bl    putn
+	PRINT(" booting -\r\n")
 #endif
 
 	/* Check that this CPU has Hyp mode */
@@ -85,7 +99,6 @@ boot_cpu:
 	and   r0, r0, #0xf000        /* Bits 12-15 define virt extensions */
 	teq   r0, #0x1000            /* Must == 0x1 or may be incompatible */
 	beq   1f
-	bl    putn
 	PRINT("- CPU doesn't support the virtualization extensions -\r\n")
 	b     fail
 1:
@@ -185,6 +198,10 @@ hyp:
 	mov   r5, #0                 /* r4:r5 is paddr (xen_pagetable) */
 	mcrr  CP64(r4, r5, HTTBR)
 
+	/* Non-boot CPUs don't need to rebuild the pagetable */
+	teq   r12, #0
+	bne   pt_ready
+	
 	/* Build the baseline idle pagetable's first-level entries */
 	ldr   r1, =xen_second
 	add   r1, r1, r10            /* r1 := paddr (xen_second) */
@@ -226,6 +243,7 @@ hyp:
 	add   r4, r4, #8
 	strd  r2, r3, [r1, r4]       /* Map it in the early boot slot */
 
+pt_ready:
 	PRINT("- Turning on paging -\r\n")
 
 	ldr   r1, =paging            /* Explicit vaddr, not RIP-relative */
@@ -238,7 +256,7 @@ hyp:
 paging:
 
 #ifdef EARLY_UART_ADDRESS
-	/* Recover the UART address in the new address space */
+	/* Recover the UART address in the new address space. */
 	lsl   r11, #11
 	lsr   r11, #11               /* UART base's offset from 2MB base */
 	adr   r0, start
@@ -246,14 +264,57 @@ paging:
 	add   r11, r11, r0           /* r11 := vaddr (UART base address) */
 #endif
 
-	PRINT("- Entering C -\r\n")
+	PRINT("- Ready -\r\n")
 
+	/* The boot CPU should go straight into C now */
+	teq   r12, #0
+	beq   launch
+
+	/* 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
+
+	/* Move on to the relocated pagetables */
+	mov   r0, #0
+	ldr   r4, =boot_httbr        /* VA of HTTBR value stashed by CPU 0 */
+	add   r4, r4, r10            /* PA of it */
+	ldrd  r4, r5, [r4]           /* Actual value */
+	mcrr  CP64(r4, r5, HTTBR)
+	mcr   CP32(r0, TLBIALLH)     /* Flush hypervisor TLB */
+	mcr   CP32(r0, BPIALL)       /* Flush branch predictor */
+	dsb                          /* Ensure completion of TLB+BP flush */
+	isb
+ 	/* Now, the UART is in its proper fixmap address */
+	ldrne r11, =FIXMAP_ADDR(FIXMAP_CONSOLE)
+
+	/* 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
+
+	/* Here, the non-boot CPUs must wait again -- they're now running on
+	 * the boot CPU's pagetables so it's safe for the boot CPU to
+	 * overwrite the non-relocated copy of Xen.  Once it's done that,
+	 * and brought up the memory allocator, non-boot CPUs can get their
+	 * own stacks and enter C. */
+1:	wfe
+	b 1b
+
+launch:	
 	ldr   sp, =init_stack        /* Supply a stack */
 	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 */
 
 /* Fail-stop
@@ -288,7 +349,7 @@ puts:
 	tst   r2, #0x8               /* Check BUSY bit */
 	bne   puts                   /* Wait for the UART to be ready */
 	ldrb  r2, [r0], #1           /* Load next char */
-	teq   r2, #0                 /* Exit on nul*/
+	teq   r2, #0                 /* Exit on nul */
 	moveq pc, lr
 	str   r2, [r11]              /* -> UARTDR (Data Register) */
 	b     puts
@@ -308,10 +369,8 @@ 1:	ldr   r2, [r11, #0x18]       /* <- UA
 	lsl   r0, #4                 /* Roll it through one nybble at a time */
 	subs  r3, r3, #1
 	bne   1b
-	adr   r0, crlf               /* Finish with a newline */
-	b     puts
+	mov   pc, lr
 
-crlf:	.asciz "\r\n"
 hex:	.ascii "0123456789abcdef"
 	.align 2
 
diff -r 8f322ab53857 -r 1e9c6bd7cc99 xen/arch/arm/mm.c
--- a/xen/arch/arm/mm.c	Thu Feb 23 17:39:59 2012 +0000
+++ b/xen/arch/arm/mm.c	Thu Feb 23 17:39:59 2012 +0000
@@ -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 lo
     lpae_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 lo
     for ( 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;
     asm volatile (
         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;
diff -r 8f322ab53857 -r 1e9c6bd7cc99 xen/arch/arm/setup.c
--- a/xen/arch/arm/setup.c	Thu Feb 23 17:39:59 2012 +0000
+++ b/xen/arch/arm/setup.c	Thu Feb 23 17:39:59 2012 +0000
@@ -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 lon
     end_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 boot
     console_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 */
+    asm volatile("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 boot
 
     init_IRQ();
 
-    gic_init();
-
     gic_route_irqs();
 
     init_maintenance_interrupt();

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 06 of 10] arm: per-cpu areas
  2012-02-23 17:40 [PATCH 00 of 10] arm: SMP boot Tim Deegan
                   ` (4 preceding siblings ...)
  2012-02-23 17:40 ` [PATCH 05 of 10] arm: More SMP bringup Tim Deegan
@ 2012-02-23 17:40 ` Tim Deegan
  2012-02-28 10:25   ` Ian Campbell
  2012-02-23 17:40 ` [PATCH 07 of 10] arm: start plumbing in SMP bringup in C Tim Deegan
                   ` (5 subsequent siblings)
  11 siblings, 1 reply; 27+ messages in thread
From: Tim Deegan @ 2012-02-23 17:40 UTC (permalink / raw)
  To: xen-devel; +Cc: Stefano Stabellini, Ian Campbell

# HG changeset patch
# User Tim Deegan <tim@xen.org>
# Date 1330018799 0
# Node ID 3b1d7a91a2596baca178e8b5610b3cbc299fa5ea
# Parent  1e9c6bd7cc99d1af0107aa927ee2ba03721449b7
arm: per-cpu areas

Signed-off-by: Tim Deegan <tim@xen.org>

diff -r 1e9c6bd7cc99 -r 3b1d7a91a259 xen/arch/arm/Makefile
--- a/xen/arch/arm/Makefile	Thu Feb 23 17:39:59 2012 +0000
+++ b/xen/arch/arm/Makefile	Thu Feb 23 17:39:59 2012 +0000
@@ -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
diff -r 1e9c6bd7cc99 -r 3b1d7a91a259 xen/arch/arm/dummy.S
--- a/xen/arch/arm/dummy.S	Thu Feb 23 17:39:59 2012 +0000
+++ b/xen/arch/arm/dummy.S	Thu Feb 23 17:39:59 2012 +0000
@@ -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 -r 3b1d7a91a259 xen/arch/arm/percpu.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/arm/percpu.c	Thu Feb 23 17:39:59 2012 +0000
@@ -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 -r 3b1d7a91a259 xen/include/asm-arm/percpu.h
--- a/xen/include/asm-arm/percpu.h	Thu Feb 23 17:39:59 2012 +0000
+++ b/xen/include/asm-arm/percpu.h	Thu Feb 23 17:39:59 2012 +0000
@@ -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

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 07 of 10] arm: start plumbing in SMP bringup in C
  2012-02-23 17:40 [PATCH 00 of 10] arm: SMP boot Tim Deegan
                   ` (5 preceding siblings ...)
  2012-02-23 17:40 ` [PATCH 06 of 10] arm: per-cpu areas Tim Deegan
@ 2012-02-23 17:40 ` Tim Deegan
  2012-02-28 10:27   ` Ian Campbell
  2012-02-23 17:40 ` [PATCH 08 of 10] arm: Boot secondary CPUs into C Tim Deegan
                   ` (4 subsequent siblings)
  11 siblings, 1 reply; 27+ messages in thread
From: Tim Deegan @ 2012-02-23 17:40 UTC (permalink / raw)
  To: xen-devel; +Cc: Stefano Stabellini, Ian Campbell

# HG changeset patch
# User Tim Deegan <tim@xen.org>
# 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.

Signed-off-by: Tim Deegan <tim@xen.org>

diff -r 3b1d7a91a259 -r fd78d23ba19d xen/arch/arm/dummy.S
--- a/xen/arch/arm/dummy.S	Thu Feb 23 17:39:59 2012 +0000
+++ b/xen/arch/arm/dummy.S	Thu Feb 23 17:39:59 2012 +0000
@@ -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 -r fd78d23ba19d xen/arch/arm/setup.c
--- a/xen/arch/arm/setup.c	Thu Feb 23 17:39:59 2012 +0000
+++ b/xen/arch/arm/setup.c	Thu Feb 23 17:39:59 2012 +0000
@@ -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 boot
     cpumask_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 boot
 
     for_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 -r fd78d23ba19d xen/arch/arm/smpboot.c
--- a/xen/arch/arm/smpboot.c	Thu Feb 23 17:39:59 2012 +0000
+++ b/xen/arch/arm/smpboot.c	Thu Feb 23 17:39:59 2012 +0000
@@ -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

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 08 of 10] arm: Boot secondary CPUs into C
  2012-02-23 17:40 [PATCH 00 of 10] arm: SMP boot Tim Deegan
                   ` (6 preceding siblings ...)
  2012-02-23 17:40 ` [PATCH 07 of 10] arm: start plumbing in SMP bringup in C Tim Deegan
@ 2012-02-23 17:40 ` Tim Deegan
  2012-02-28 10:34   ` Ian Campbell
  2012-02-23 17:40 ` [PATCH 09 of 10] arm: SMP CPU shutdown Tim Deegan
                   ` (3 subsequent siblings)
  11 siblings, 1 reply; 27+ messages in thread
From: Tim Deegan @ 2012-02-23 17:40 UTC (permalink / raw)
  To: xen-devel; +Cc: Stefano Stabellini, Ian Campbell

# HG changeset patch
# User Tim Deegan <tim@xen.org>
# Date 1330018799 0
# Node ID d35b52e5fde829dfbaf3da73e0716d004faded2f
# Parent  fd78d23ba19de4129e21cdc7303848b105057227
arm: Boot secondary CPUs into C

Signed-off-by: Tim Deegan <tim@xen.org>

diff -r fd78d23ba19d -r d35b52e5fde8 xen/arch/arm/gic.c
--- a/xen/arch/arm/gic.c	Thu Feb 23 17:39:59 2012 +0000
+++ b/xen/arch/arm/gic.c	Thu Feb 23 17:39:59 2012 +0000
@@ -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 */
diff -r fd78d23ba19d -r d35b52e5fde8 xen/arch/arm/gic.h
--- a/xen/arch/arm/gic.h	Thu Feb 23 17:39:59 2012 +0000
+++ b/xen/arch/arm/gic.h	Thu Feb 23 17:39:59 2012 +0000
@@ -140,6 +140,8 @@ extern int gic_route_irq_to_guest(struct
 extern 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
diff -r fd78d23ba19d -r d35b52e5fde8 xen/arch/arm/head.S
--- a/xen/arch/arm/head.S	Thu Feb 23 17:39:59 2012 +0000
+++ b/xen/arch/arm/head.S	Thu Feb 23 17:39:59 2012 +0000
@@ -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 */
diff -r fd78d23ba19d -r d35b52e5fde8 xen/arch/arm/setup.c
--- a/xen/arch/arm/setup.c	Thu Feb 23 17:39:59 2012 +0000
+++ b/xen/arch/arm/setup.c	Thu Feb 23 17:39:59 2012 +0000
@@ -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 boot
     console_init_preirq();
 #endif
 
+    percpu_init_areas();
+
     cpus = gic_init();
 
     printk("Waiting for %i other CPUs to be ready\n", cpus - 1);
diff -r fd78d23ba19d -r d35b52e5fde8 xen/arch/arm/smpboot.c
--- a/xen/arch/arm/smpboot.c	Thu Feb 23 17:39:59 2012 +0000
+++ b/xen/arch/arm/smpboot.c	Thu Feb 23 17:39:59 2012 +0000
@@ -16,10 +16,15 @@
  * GNU General Public License for more details.
  */
 
+#include <xen/cpu.h>
 #include <xen/cpumask.h>
+#include <xen/errno.h>
+#include <xen/init.h>
+#include <xen/mm.h>
+#include <xen/sched.h>
 #include <xen/smp.h>
-#include <xen/init.h>
-#include <xen/errno.h>
+#include <xen/softirq.h>
+#include "gic.h"
 
 cpumask_t cpu_online_map;
 EXPORT_SYMBOL(cpu_online_map);
@@ -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 };
+
 void __init
 smp_prepare_cpus (unsigned int max_cpus)
 {
@@ -43,11 +56,43 @@ smp_prepare_cpus (unsigned int max_cpus)
     cpumask_copy(&cpu_present_map, &cpu_possible_map);
 }
 
-/* Bring up a non-boot CPU */
-int __cpu_up(unsigned int cpu)
+/* Shared state for coordinating CPU bringup */
+unsigned long smp_up_cpu = 0;
+
+/* Boot the current CPU */
+void __cpuinit start_secondary(unsigned long boot_phys_offset,
+                               unsigned long arm_type,
+                               unsigned long atag_paddr,
+                               unsigned long cpuid)
 {
-    /* Not yet... */
-    return -ENODEV;
+    memset(get_cpu_info(), 0, sizeof (struct cpu_info));
+
+    /* TODO: handle boards where CPUIDs are not contiguous */
+    set_processor_id(cpuid);
+
+    /* Setup Hyp vector base */
+    WRITE_CP32((uint32_t) hyp_traps_vector, HVBAR);
+
+    dprintk(XENLOG_DEBUG, "CPU %li awake.\n", cpuid);
+
+    gic_init_secondary_cpu();
+
+    set_current(idle_vcpu[cpuid]);
+    this_cpu(curr_vcpu) = current;
+
+    /* Run local notifiers */
+    notify_cpu_starting(cpuid);
+    wmb();
+
+    /* Now report this CPU is up */
+    cpumask_set_cpu(cpuid, &cpu_online_map);
+    wmb();
+
+    local_irq_enable();
+
+    dprintk(XENLOG_DEBUG, "CPU %li booted.\n", cpuid);
+
+    startup_cpu_idle_loop();
 }
 
 /* Shut down the current CPU */
@@ -57,6 +102,32 @@ void __cpu_disable(void)
     BUG();
 }
 
+/* Bring up a remote CPU */
+int __cpu_up(unsigned int cpu)
+{
+    unsigned char *stack;
+
+    /* Remote CPU needs a stack to boot on. */
+    stack = alloc_xenheap_pages(STACK_ORDER, 0);
+    if ( !stack )
+        return -ENOMEM;
+    ASSERT(init_stacks[cpu] == NULL);
+    init_stacks[cpu] = stack;
+
+    /* Unblock the CPU.  It should be waiting in the loop in head.S
+     * for an event to arrive when smp_up_cpu matches its cpuid. */
+    smp_up_cpu = cpu;
+    asm volatile("dsb; isb; sev");
+
+    while ( !cpu_online(cpu) )
+    {
+        cpu_relax();
+        process_pending_softirqs();
+    }
+
+    return 0;
+}
+
 /* Wait for a remote CPU to die */
 void __cpu_die(unsigned int cpu)
 {

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 09 of 10] arm: SMP CPU shutdown
  2012-02-23 17:40 [PATCH 00 of 10] arm: SMP boot Tim Deegan
                   ` (7 preceding siblings ...)
  2012-02-23 17:40 ` [PATCH 08 of 10] arm: Boot secondary CPUs into C Tim Deegan
@ 2012-02-23 17:40 ` Tim Deegan
  2012-02-28 10:38   ` Ian Campbell
  2012-02-23 17:40 ` [PATCH 10 of 10] arm: Shutdown and reboot Tim Deegan
                   ` (2 subsequent siblings)
  11 siblings, 1 reply; 27+ messages in thread
From: Tim Deegan @ 2012-02-23 17:40 UTC (permalink / raw)
  To: xen-devel; +Cc: Stefano Stabellini, Ian Campbell

# HG changeset patch
# User Tim Deegan <tim@xen.org>
# Date 1330018799 0
# Node ID a78bc9b8421492e0545c6d52c7a32b9de9737d61
# Parent  d35b52e5fde829dfbaf3da73e0716d004faded2f
arm: SMP CPU shutdown

For completeness, also implelent the CPU shutdown path.

Signed-off-by: TIm Deegan <tim@xen.org>

diff -r d35b52e5fde8 -r a78bc9b84214 xen/arch/arm/domain.c
--- a/xen/arch/arm/domain.c	Thu Feb 23 17:39:59 2012 +0000
+++ b/xen/arch/arm/domain.c	Thu Feb 23 17:39:59 2012 +0000
@@ -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();
     }
diff -r d35b52e5fde8 -r a78bc9b84214 xen/arch/arm/gic.c
--- a/xen/arch/arm/gic.c	Thu Feb 23 17:39:59 2012 +0000
+++ b/xen/arch/arm/gic.c	Thu Feb 23 17:39:59 2012 +0000
@@ -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(vo
     spin_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 */
diff -r d35b52e5fde8 -r a78bc9b84214 xen/arch/arm/gic.h
--- a/xen/arch/arm/gic.h	Thu Feb 23 17:39:59 2012 +0000
+++ b/xen/arch/arm/gic.h	Thu Feb 23 17:39:59 2012 +0000
@@ -142,6 +142,8 @@ extern void gic_interrupt(struct cpu_use
 extern 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
diff -r d35b52e5fde8 -r a78bc9b84214 xen/arch/arm/smpboot.c
--- a/xen/arch/arm/smpboot.c	Thu Feb 23 17:39:59 2012 +0000
+++ b/xen/arch/arm/smpboot.c	Thu Feb 23 17:39:59 2012 +0000
@@ -18,6 +18,7 @@
 
 #include <xen/cpu.h>
 #include <xen/cpumask.h>
+#include <xen/delay.h>
 #include <xen/errno.h>
 #include <xen/init.h>
 #include <xen/mm.h>
@@ -58,6 +59,7 @@ smp_prepare_cpus (unsigned int max_cpus)
 
 /* Shared state for coordinating CPU bringup */
 unsigned long smp_up_cpu = 0;
+static bool_t cpu_is_dead = 0;
 
 /* Boot the current CPU */
 void __cpuinit start_secondary(unsigned long boot_phys_offset,
@@ -98,8 +100,35 @@ void __cpuinit start_secondary(unsigned 
 /* Shut down the current CPU */
 void __cpu_disable(void)
 {
-    /* TODO: take down timers, GIC, &c. */
-    BUG();
+    unsigned int cpu = get_processor_id();
+
+    local_irq_disable();
+    gic_disable_cpu();
+    /* Allow any queued timer interrupts to get serviced */
+    local_irq_enable();
+    mdelay(1);
+    local_irq_disable();
+
+    /* 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 
+     * scheduler will drop to the idle loop, which will call stop_cpu(). */
+}
+
+void stop_cpu(void)
+{
+    local_irq_disable();
+    cpu_is_dead = 1;
+    /* Make sure the write happens before we sleep forever */
+    dsb();
+    isb();
+    while ( 1 ) 
+        asm volatile("wfi");
 }
 
 /* Bring up a remote CPU */
@@ -131,8 +160,19 @@ int __cpu_up(unsigned int cpu)
 /* Wait for a remote CPU to die */
 void __cpu_die(unsigned int cpu)
 {
-    /* TODO: interlock with __cpu_disable */
-    BUG();
+    unsigned int i = 0;
+
+    while ( !cpu_is_dead )
+    {
+        mdelay(100);
+        cpu_relax();
+        process_pending_softirqs();
+        if ( (++i % 10) == 0 )
+            printk(KERN_ERR "CPU %u still not dead...\n", cpu);
+        mb();
+    }
+    cpu_is_dead = 0;
+    mb();
 }
 
 
diff -r d35b52e5fde8 -r a78bc9b84214 xen/include/asm-arm/smp.h
--- a/xen/include/asm-arm/smp.h	Thu Feb 23 17:39:59 2012 +0000
+++ b/xen/include/asm-arm/smp.h	Thu Feb 23 17:39:59 2012 +0000
@@ -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:

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 10 of 10] arm: Shutdown and reboot
  2012-02-23 17:40 [PATCH 00 of 10] arm: SMP boot Tim Deegan
                   ` (8 preceding siblings ...)
  2012-02-23 17:40 ` [PATCH 09 of 10] arm: SMP CPU shutdown Tim Deegan
@ 2012-02-23 17:40 ` Tim Deegan
  2012-02-28 10:39   ` Ian Campbell
  2012-02-28 10:18 ` [PATCH 00 of 10] arm: SMP boot Ian Campbell
  2012-02-29 14:36 ` Ian Campbell
  11 siblings, 1 reply; 27+ messages in thread
From: Tim Deegan @ 2012-02-23 17:40 UTC (permalink / raw)
  To: xen-devel; +Cc: Stefano Stabellini, Ian Campbell

# HG changeset patch
# User Tim Deegan <tim@xen.org>
# 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.

Signed-off-by: Tim Deegan <tim@xen.org>

diff -r a78bc9b84214 -r 8a2d38ab67cc xen/arch/arm/shutdown.c
--- a/xen/arch/arm/shutdown.c	Thu Feb 23 17:39:59 2012 +0000
+++ b/xen/arch/arm/shutdown.c	Thu Feb 23 17:39:59 2012 +0000
@@ -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 -r 8a2d38ab67cc xen/include/asm-arm/config.h
--- a/xen/include/asm-arm/config.h	Thu Feb 23 17:39:59 2012 +0000
+++ b/xen/include/asm-arm/config.h	Thu Feb 23 17:39:59 2012 +0000
@@ -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__ */
 /*

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 02 of 10] arm: implement udelay()
  2012-02-23 17:40 ` [PATCH 02 of 10] arm: implement udelay() Tim Deegan
@ 2012-02-23 19:03   ` David Vrabel
  2012-02-27 19:19     ` Tim Deegan
  0 siblings, 1 reply; 27+ messages in thread
From: David Vrabel @ 2012-02-23 19:03 UTC (permalink / raw)
  To: Tim Deegan; +Cc: xen-devel, Stefano Stabellini, Ian Campbell

On 23/02/12 17:40, Tim Deegan wrote:
> arm: implement udelay()
> 
> Signed-off-by: Tim Deegan <tim@xen.org>
> 
[...]
> diff -r 4a7c14209131 -r ec051056db2b xen/arch/arm/time.c
> --- a/xen/arch/arm/time.c	Thu Feb 23 17:39:59 2012 +0000
> +++ b/xen/arch/arm/time.c	Thu Feb 23 17:39:59 2012 +0000
> @@ -171,6 +171,16 @@ void __cpuinit init_timer_interrupt(void
>      request_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

> +    } while ( get_s_time() - deadline < 0 );
> +}
> +
>  /*
>   * Local variables:
>   * mode: C

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 05 of 10] arm: More SMP bringup
  2012-02-23 17:40 ` [PATCH 05 of 10] arm: More SMP bringup Tim Deegan
@ 2012-02-23 19:16   ` Ian Campbell
  2012-02-27 19:20     ` Tim Deegan
  0 siblings, 1 reply; 27+ messages in thread
From: Ian Campbell @ 2012-02-23 19:16 UTC (permalink / raw)
  To: Tim Deegan; +Cc: xen-devel, Stefano Stabellini

On Thu, 2012-02-23 at 17:40 +0000, Tim Deegan wrote:
[...]
> +	/* 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...

[...]
> +	/* 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.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 03 of 10] arm: Move some GIC distributor init out of the per-CPU init function
  2012-02-23 17:40 ` [PATCH 03 of 10] arm: Move some GIC distributor init out of the per-CPU init function Tim Deegan
@ 2012-02-27 17:32   ` Ian Campbell
  2012-02-27 19:30     ` Tim Deegan
  0 siblings, 1 reply; 27+ messages in thread
From: Ian Campbell @ 2012-02-27 17:32 UTC (permalink / raw)
  To: Tim Deegan; +Cc: xen-devel, Stefano Stabellini

On Thu, 2012-02-23 at 17:40 +0000, Tim Deegan wrote:
> # HG changeset patch
> # User Tim Deegan <tim@xen.org>
> # Date 1330018799 0
> # Node ID 437ad1207a175c9ad376871f3f4c075dbcd5b6e6
> # Parent  ec051056db2b6d37344629e2f01d17240099d5ec
> arm: Move some GIC distributor init out of the per-CPU init function
> 
> Signed-off-by: Tim Deegan <tim@xen.org>
> 
> diff -r ec051056db2b -r 437ad1207a17 xen/arch/arm/gic.c
> --- a/xen/arch/arm/gic.c	Thu Feb 23 17:39:59 2012 +0000
> +++ b/xen/arch/arm/gic.c	Thu Feb 23 17:39:59 2012 +0000
> @@ -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 */

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?


> @@ -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 */

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 02 of 10] arm: implement udelay()
  2012-02-23 19:03   ` David Vrabel
@ 2012-02-27 19:19     ` Tim Deegan
  0 siblings, 0 replies; 27+ messages in thread
From: Tim Deegan @ 2012-02-27 19:19 UTC (permalink / raw)
  To: David Vrabel; +Cc: xen-devel, Stefano Stabellini, Ian Campbell

At 19:03 +0000 on 23 Feb (1330023834), David Vrabel wrote:
> On 23/02/12 17:40, Tim Deegan wrote:
> > arm: implement udelay()
> > 
> > Signed-off-by: Tim Deegan <tim@xen.org>
> > 
> [...]
> > diff -r 4a7c14209131 -r ec051056db2b xen/arch/arm/time.c
> > --- a/xen/arch/arm/time.c	Thu Feb 23 17:39:59 2012 +0000
> > +++ b/xen/arch/arm/time.c	Thu Feb 23 17:39:59 2012 +0000
> > @@ -171,6 +171,16 @@ void __cpuinit init_timer_interrupt(void
> >      request_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?

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.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 05 of 10] arm: More SMP bringup
  2012-02-23 19:16   ` Ian Campbell
@ 2012-02-27 19:20     ` Tim Deegan
  0 siblings, 0 replies; 27+ messages in thread
From: Tim Deegan @ 2012-02-27 19:20 UTC (permalink / raw)
  To: Ian Campbell; +Cc: xen-devel, Stefano Stabellini

At 19:16 +0000 on 23 Feb (1330024560), Ian Campbell wrote:
> On Thu, 2012-02-23 at 17:40 +0000, Tim Deegan wrote:
> [...]
> > +	/* 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...
> 
> [...]
> > +	/* 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?

Yes, we would.  I'll fix that.

Tim.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 03 of 10] arm: Move some GIC distributor init out of the per-CPU init function
  2012-02-27 17:32   ` Ian Campbell
@ 2012-02-27 19:30     ` Tim Deegan
  2012-02-28 10:24       ` Ian Campbell
  0 siblings, 1 reply; 27+ messages in thread
From: Tim Deegan @ 2012-02-27 19:30 UTC (permalink / raw)
  To: Ian Campbell; +Cc: xen-devel, Stefano Stabellini

At 17:32 +0000 on 27 Feb (1330363933), Ian Campbell wrote:
> On Thu, 2012-02-23 at 17:40 +0000, Tim Deegan wrote:
> > # HG changeset patch
> > # User Tim Deegan <tim@xen.org>
> > # Date 1330018799 0
> > # Node ID 437ad1207a175c9ad376871f3f4c075dbcd5b6e6
> > # Parent  ec051056db2b6d37344629e2f01d17240099d5ec
> > arm: Move some GIC distributor init out of the per-CPU init function
> > 
> > Signed-off-by: Tim Deegan <tim@xen.org>
> > 
> > diff -r ec051056db2b -r 437ad1207a17 xen/arch/arm/gic.c
> > --- a/xen/arch/arm/gic.c	Thu Feb 23 17:39:59 2012 +0000
> > +++ b/xen/arch/arm/gic.c	Thu Feb 23 17:39:59 2012 +0000
> > @@ -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 */
> 
> 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?

Yep, you're right ISENABLER0 and ICENABLER0 are banked.  I'll replace
this with a comment explaining that.

Cheers,

Tim.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 00 of 10] arm: SMP boot
  2012-02-23 17:40 [PATCH 00 of 10] arm: SMP boot Tim Deegan
                   ` (9 preceding siblings ...)
  2012-02-23 17:40 ` [PATCH 10 of 10] arm: Shutdown and reboot Tim Deegan
@ 2012-02-28 10:18 ` Ian Campbell
  2012-02-29 14:36 ` Ian Campbell
  11 siblings, 0 replies; 27+ messages in thread
From: Ian Campbell @ 2012-02-28 10:18 UTC (permalink / raw)
  To: Tim Deegan; +Cc: xen-devel, Stefano Stabellini

On Thu, 2012-02-23 at 17:40 +0000, Tim Deegan wrote:
> 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.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 03 of 10] arm: Move some GIC distributor init out of the per-CPU init function
  2012-02-27 19:30     ` Tim Deegan
@ 2012-02-28 10:24       ` Ian Campbell
  0 siblings, 0 replies; 27+ messages in thread
From: Ian Campbell @ 2012-02-28 10:24 UTC (permalink / raw)
  To: Tim Deegan; +Cc: xen-devel, Stefano Stabellini

On Mon, 2012-02-27 at 19:30 +0000, Tim Deegan wrote:
> At 17:32 +0000 on 27 Feb (1330363933), Ian Campbell wrote:
> > On Thu, 2012-02-23 at 17:40 +0000, Tim Deegan wrote:
> > > # HG changeset patch
> > > # User Tim Deegan <tim@xen.org>
> > > # Date 1330018799 0
> > > # Node ID 437ad1207a175c9ad376871f3f4c075dbcd5b6e6
> > > # Parent  ec051056db2b6d37344629e2f01d17240099d5ec
> > > arm: Move some GIC distributor init out of the per-CPU init function
> > > 
> > > Signed-off-by: Tim Deegan <tim@xen.org>
> > > 
> > > diff -r ec051056db2b -r 437ad1207a17 xen/arch/arm/gic.c
> > > --- a/xen/arch/arm/gic.c	Thu Feb 23 17:39:59 2012 +0000
> > > +++ b/xen/arch/arm/gic.c	Thu Feb 23 17:39:59 2012 +0000
> > > @@ -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 */
> > 
> > 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?
> 
> 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.

>  I'll replace this with a comment explaining that.

Thanks.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 06 of 10] arm: per-cpu areas
  2012-02-23 17:40 ` [PATCH 06 of 10] arm: per-cpu areas Tim Deegan
@ 2012-02-28 10:25   ` Ian Campbell
  0 siblings, 0 replies; 27+ messages in thread
From: Ian Campbell @ 2012-02-28 10:25 UTC (permalink / raw)
  To: Tim Deegan; +Cc: xen-devel, Stefano Stabellini

On Thu, 2012-02-23 at 17:40 +0000, Tim Deegan wrote:
> # HG changeset patch
> # User Tim Deegan <tim@xen.org>
> # Date 1330018799 0
> # Node ID 3b1d7a91a2596baca178e8b5610b3cbc299fa5ea
> # Parent  1e9c6bd7cc99d1af0107aa927ee2ba03721449b7
> arm: per-cpu areas
> 
> Signed-off-by: Tim Deegan <tim@xen.org>

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:
Acked-by: Ian Campbell <ian.campbell@citrix.com>

> 
> diff -r 1e9c6bd7cc99 -r 3b1d7a91a259 xen/arch/arm/Makefile
> --- a/xen/arch/arm/Makefile	Thu Feb 23 17:39:59 2012 +0000
> +++ b/xen/arch/arm/Makefile	Thu Feb 23 17:39:59 2012 +0000
> @@ -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
> diff -r 1e9c6bd7cc99 -r 3b1d7a91a259 xen/arch/arm/dummy.S
> --- a/xen/arch/arm/dummy.S	Thu Feb 23 17:39:59 2012 +0000
> +++ b/xen/arch/arm/dummy.S	Thu Feb 23 17:39:59 2012 +0000
> @@ -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 -r 3b1d7a91a259 xen/arch/arm/percpu.c
> --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
> +++ b/xen/arch/arm/percpu.c	Thu Feb 23 17:39:59 2012 +0000
> @@ -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 -r 3b1d7a91a259 xen/include/asm-arm/percpu.h
> --- a/xen/include/asm-arm/percpu.h	Thu Feb 23 17:39:59 2012 +0000
> +++ b/xen/include/asm-arm/percpu.h	Thu Feb 23 17:39:59 2012 +0000
> @@ -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
>  

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 07 of 10] arm: start plumbing in SMP bringup in C
  2012-02-23 17:40 ` [PATCH 07 of 10] arm: start plumbing in SMP bringup in C Tim Deegan
@ 2012-02-28 10:27   ` Ian Campbell
  0 siblings, 0 replies; 27+ messages in thread
From: Ian Campbell @ 2012-02-28 10:27 UTC (permalink / raw)
  To: Tim Deegan; +Cc: xen-devel, Stefano Stabellini

On Thu, 2012-02-23 at 17:40 +0000, Tim Deegan wrote:
> # HG changeset patch
> # User Tim Deegan <tim@xen.org>
> # 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.
> 
> Signed-off-by: Tim Deegan <tim@xen.org>

Acked-by: Ian Campbell <ian.campbell@citrix.com>

> diff -r 3b1d7a91a259 -r fd78d23ba19d xen/arch/arm/dummy.S
> --- a/xen/arch/arm/dummy.S	Thu Feb 23 17:39:59 2012 +0000
> +++ b/xen/arch/arm/dummy.S	Thu Feb 23 17:39:59 2012 +0000
> @@ -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 -r fd78d23ba19d xen/arch/arm/setup.c
> --- a/xen/arch/arm/setup.c	Thu Feb 23 17:39:59 2012 +0000
> +++ b/xen/arch/arm/setup.c	Thu Feb 23 17:39:59 2012 +0000
> @@ -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 boot
>      cpumask_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 boot
>  
>      for_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 -r fd78d23ba19d xen/arch/arm/smpboot.c
> --- a/xen/arch/arm/smpboot.c	Thu Feb 23 17:39:59 2012 +0000
> +++ b/xen/arch/arm/smpboot.c	Thu Feb 23 17:39:59 2012 +0000
> @@ -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

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 08 of 10] arm: Boot secondary CPUs into C
  2012-02-23 17:40 ` [PATCH 08 of 10] arm: Boot secondary CPUs into C Tim Deegan
@ 2012-02-28 10:34   ` Ian Campbell
  0 siblings, 0 replies; 27+ messages in thread
From: Ian Campbell @ 2012-02-28 10:34 UTC (permalink / raw)
  To: Tim Deegan; +Cc: xen-devel, Stefano Stabellini

On Thu, 2012-02-23 at 17:40 +0000, Tim Deegan wrote:
> # HG changeset patch
> # User Tim Deegan <tim@xen.org>
> # Date 1330018799 0
> # Node ID d35b52e5fde829dfbaf3da73e0716d004faded2f
> # Parent  fd78d23ba19de4129e21cdc7303848b105057227
> arm: Boot secondary CPUs into C
> 
> Signed-off-by: Tim Deegan <tim@xen.org>

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.

> @@ -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.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 09 of 10] arm: SMP CPU shutdown
  2012-02-23 17:40 ` [PATCH 09 of 10] arm: SMP CPU shutdown Tim Deegan
@ 2012-02-28 10:38   ` Ian Campbell
  2012-02-28 18:13     ` Tim Deegan
  0 siblings, 1 reply; 27+ messages in thread
From: Ian Campbell @ 2012-02-28 10:38 UTC (permalink / raw)
  To: Tim Deegan; +Cc: xen-devel, Stefano Stabellini

On Thu, 2012-02-23 at 17:40 +0000, Tim Deegan wrote:
> # HG changeset patch
> # User Tim Deegan <tim@xen.org>
> # Date 1330018799 0
> # Node ID a78bc9b8421492e0545c6d52c7a32b9de9737d61
> # Parent  d35b52e5fde829dfbaf3da73e0716d004faded2f
> arm: SMP CPU shutdown
> 
> For 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.

> Signed-off-by: TIm Deegan <tim@xen.org>

Typo here.

[...]
> +    /* 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

> +     * 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?

> +    /* Make sure the write happens before we sleep forever */
> +    dsb();
> +    isb();
> +    while ( 1 ) 
> +        asm volatile("wfi");
>  }
>  
>  /* Bring up a remote CPU */

Ian.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 10 of 10] arm: Shutdown and reboot
  2012-02-23 17:40 ` [PATCH 10 of 10] arm: Shutdown and reboot Tim Deegan
@ 2012-02-28 10:39   ` Ian Campbell
  0 siblings, 0 replies; 27+ messages in thread
From: Ian Campbell @ 2012-02-28 10:39 UTC (permalink / raw)
  To: Tim Deegan; +Cc: xen-devel, Stefano Stabellini

On Thu, 2012-02-23 at 17:40 +0000, Tim Deegan wrote:
> # HG changeset patch
> # User Tim Deegan <tim@xen.org>
> # 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.
> 
> Signed-off-by: Tim Deegan <tim@xen.org>

Acked-by: Ian Campbell <ian.campbell@citrix.com>

But please add an "XXX get this from device tree" somewhere
appropriate ;-)

> 
> diff -r a78bc9b84214 -r 8a2d38ab67cc xen/arch/arm/shutdown.c
> --- a/xen/arch/arm/shutdown.c	Thu Feb 23 17:39:59 2012 +0000
> +++ b/xen/arch/arm/shutdown.c	Thu Feb 23 17:39:59 2012 +0000
> @@ -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 -r 8a2d38ab67cc xen/include/asm-arm/config.h
> --- a/xen/include/asm-arm/config.h	Thu Feb 23 17:39:59 2012 +0000
> +++ b/xen/include/asm-arm/config.h	Thu Feb 23 17:39:59 2012 +0000
> @@ -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__ */
>  /*

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 09 of 10] arm: SMP CPU shutdown
  2012-02-28 10:38   ` Ian Campbell
@ 2012-02-28 18:13     ` Tim Deegan
  0 siblings, 0 replies; 27+ messages in thread
From: Tim Deegan @ 2012-02-28 18:13 UTC (permalink / raw)
  To: Ian Campbell; +Cc: xen-devel, Stefano Stabellini

At 10:38 +0000 on 28 Feb (1330425518), Ian Campbell wrote:
> On Thu, 2012-02-23 at 17:40 +0000, Tim Deegan wrote:
> > # HG changeset patch
> > # User Tim Deegan <tim@xen.org>
> > # Date 1330018799 0
> > # Node ID a78bc9b8421492e0545c6d52c7a32b9de9737d61
> > # Parent  d35b52e5fde829dfbaf3da73e0716d004faded2f
> > arm: SMP CPU shutdown
> > 
> > For completeness, also implelent the CPU shutdown path.
> 
> Does something free the init_stack for a CPU as it goes down?

Er, no. :)  

> 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. 

> > Signed-off-by: TIm Deegan <tim@xen.org>
> 
> Typo here.

WHat TYpo? I ALways SIgn MY NAme THat WAy.

> [...]
> > +    /* 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.

> > +     * 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.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 00 of 10] arm: SMP boot
  2012-02-23 17:40 [PATCH 00 of 10] arm: SMP boot Tim Deegan
                   ` (10 preceding siblings ...)
  2012-02-28 10:18 ` [PATCH 00 of 10] arm: SMP boot Ian Campbell
@ 2012-02-29 14:36 ` Ian Campbell
  2012-02-29 22:22   ` Tim Deegan
  11 siblings, 1 reply; 27+ messages in thread
From: Ian Campbell @ 2012-02-29 14:36 UTC (permalink / raw)
  To: Tim Deegan; +Cc: xen-devel, Stefano Stabellini

On Thu, 2012-02-23 at 17:40 +0000, Tim Deegan wrote:
> 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.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 00 of 10] arm: SMP boot
  2012-02-29 14:36 ` Ian Campbell
@ 2012-02-29 22:22   ` Tim Deegan
  0 siblings, 0 replies; 27+ messages in thread
From: Tim Deegan @ 2012-02-29 22:22 UTC (permalink / raw)
  To: Ian Campbell; +Cc: xen-devel, Stefano Stabellini

At 14:36 +0000 on 29 Feb (1330526182), Ian Campbell wrote:
> On Thu, 2012-02-23 at 17:40 +0000, Tim Deegan wrote:
> > 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.

Yes, that is exactly what I did. 

Tim.

^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2012-02-29 22:22 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-02-23 17:40 [PATCH 00 of 10] arm: SMP boot Tim Deegan
2012-02-23 17:40 ` [PATCH 01 of 10] arm: strip xen binary Tim Deegan
2012-02-23 17:40 ` [PATCH 02 of 10] arm: implement udelay() Tim Deegan
2012-02-23 19:03   ` David Vrabel
2012-02-27 19:19     ` Tim Deegan
2012-02-23 17:40 ` [PATCH 03 of 10] arm: Move some GIC distributor init out of the per-CPU init function Tim Deegan
2012-02-27 17:32   ` Ian Campbell
2012-02-27 19:30     ` Tim Deegan
2012-02-28 10:24       ` Ian Campbell
2012-02-23 17:40 ` [PATCH 04 of 10] arm: Handle booting on SMP platforms Tim Deegan
2012-02-23 17:40 ` [PATCH 05 of 10] arm: More SMP bringup Tim Deegan
2012-02-23 19:16   ` Ian Campbell
2012-02-27 19:20     ` Tim Deegan
2012-02-23 17:40 ` [PATCH 06 of 10] arm: per-cpu areas Tim Deegan
2012-02-28 10:25   ` Ian Campbell
2012-02-23 17:40 ` [PATCH 07 of 10] arm: start plumbing in SMP bringup in C Tim Deegan
2012-02-28 10:27   ` Ian Campbell
2012-02-23 17:40 ` [PATCH 08 of 10] arm: Boot secondary CPUs into C Tim Deegan
2012-02-28 10:34   ` Ian Campbell
2012-02-23 17:40 ` [PATCH 09 of 10] arm: SMP CPU shutdown Tim Deegan
2012-02-28 10:38   ` Ian Campbell
2012-02-28 18:13     ` Tim Deegan
2012-02-23 17:40 ` [PATCH 10 of 10] arm: Shutdown and reboot Tim Deegan
2012-02-28 10:39   ` Ian Campbell
2012-02-28 10:18 ` [PATCH 00 of 10] arm: SMP boot Ian Campbell
2012-02-29 14:36 ` Ian Campbell
2012-02-29 22:22   ` Tim Deegan

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.