svn commit: r301070 - head/sys/arm64/arm64

2016-05-31 Thread Andrew Turner
Author: andrew
Date: Tue May 31 18:45:52 2016
New Revision: 301070
URL: https://svnweb.freebsd.org/changeset/base/301070

Log:
  Allow the kernel to boot on a CPU where the devicetree has numbered it with
  a non-zero ID. To do this we increment the cpuid of any CPUs with a smaller
  devicetree ID by one to stop them conflicting with the boot CPU.
  
  Obtained from:ABT Systems Ltd
  Sponsored by: The FreeBSD Foundation

Modified:
  head/sys/arm64/arm64/mp_machdep.c

Modified: head/sys/arm64/arm64/mp_machdep.c
==
--- head/sys/arm64/arm64/mp_machdep.c   Tue May 31 18:44:33 2016
(r301069)
+++ head/sys/arm64/arm64/mp_machdep.c   Tue May 31 18:45:52 2016
(r301070)
@@ -119,6 +119,13 @@ static uint32_t cpu_reg[MAXCPU][2];
 #endif
 static device_t cpu_list[MAXCPU];
 
+/*
+ * Not all systems boot from the first CPU in the device tree. To work around
+ * this we need to find which CPU we have booted from so when we later
+ * enable the secondary CPUs we skip this one.
+ */
+static int cpu0 = -1;
+
 void mpentry(unsigned long cpuid);
 void init_secondary(uint64_t);
 
@@ -486,6 +493,7 @@ cpu_init_fdt(u_int id, phandle_t node, u
uint64_t target_cpu;
struct pcpu *pcpup;
vm_paddr_t pa;
+   u_int cpuid;
int err;
 
/* Check we are able to start this cpu */
@@ -502,16 +510,19 @@ cpu_init_fdt(u_int id, phandle_t node, u
 #endif
 
/* We are already running on cpu 0 */
-   if (id == 0)
+   if (id == cpu0)
return (1);
 
+   cpuid = id;
+   if (cpuid < cpu0)
+   cpuid++;
 
-   pcpup = &__pcpu[id];
-   pcpu_init(pcpup, id, sizeof(struct pcpu));
+   pcpup = &__pcpu[cpuid];
+   pcpu_init(pcpup, cpuid, sizeof(struct pcpu));
 
-   dpcpu[id - 1] = (void *)kmem_malloc(kernel_arena, DPCPU_SIZE,
+   dpcpu[cpuid - 1] = (void *)kmem_malloc(kernel_arena, DPCPU_SIZE,
M_WAITOK | M_ZERO);
-   dpcpu_init(dpcpu[id - 1], id);
+   dpcpu_init(dpcpu[cpuid - 1], id);
 
target_cpu = reg[0];
if (addr_size == 2) {
@@ -519,21 +530,23 @@ cpu_init_fdt(u_int id, phandle_t node, u
target_cpu |= reg[1];
}
 
-   printf("Starting CPU %u (%lx)\n", id, target_cpu);
+   printf("Starting CPU %u (%lx)\n", cpuid, target_cpu);
pa = pmap_extract(kernel_pmap, (vm_offset_t)mpentry);
 
-   err = psci_cpu_on(target_cpu, pa, id);
+   err = psci_cpu_on(target_cpu, pa, cpuid);
if (err != PSCI_RETVAL_SUCCESS) {
/* Panic here if INVARIANTS are enabled */
-   KASSERT(0, ("Failed to start CPU %u (%lx)\n", id, target_cpu));
+   KASSERT(0, ("Failed to start CPU %u (%lx)\n", id,
+   target_cpu));
 
pcpu_destroy(pcpup);
-   kmem_free(kernel_arena, (vm_offset_t)dpcpu[id - 1], DPCPU_SIZE);
-   dpcpu[id - 1] = NULL;
+   kmem_free(kernel_arena, (vm_offset_t)dpcpu[cpuid - 1],
+   DPCPU_SIZE);
+   dpcpu[cpuid - 1] = NULL;
/* Notify the user that the CPU failed to start */
printf("Failed to start CPU %u (%lx)\n", id, target_cpu);
} else
-   CPU_SET(id, _cpus);
+   CPU_SET(cpuid, _cpus);
 
return (1);
 }
@@ -551,6 +564,7 @@ cpu_mp_start(void)
switch(cpu_enum_method) {
 #ifdef FDT
case CPUS_FDT:
+   KASSERT(cpu0 >= 0, ("Current CPU was not found"));
ofw_cpu_early_foreach(cpu_init_fdt, true);
break;
 #endif
@@ -565,13 +579,34 @@ cpu_mp_announce(void)
 {
 }
 
+static boolean_t
+cpu_find_cpu0_fdt(u_int id, phandle_t node, u_int addr_size, pcell_t *reg)
+{
+   uint64_t mpidr_fdt, mpidr_reg;
+
+   if (cpu0 < 0) {
+   mpidr_fdt = reg[0];
+   if (addr_size == 2) {
+   mpidr_fdt <<= 32;
+   mpidr_fdt |= reg[1];
+   }
+
+   mpidr_reg = READ_SPECIALREG(mpidr_el1);
+
+   if ((mpidr_reg & 0xff00fful) == mpidr_fdt)
+   cpu0 = id;
+   }
+
+   return (TRUE);
+}
+
 void
 cpu_mp_setmaxid(void)
 {
 #ifdef FDT
int cores;
 
-   cores = ofw_cpu_early_foreach(NULL, false);
+   cores = ofw_cpu_early_foreach(cpu_find_cpu0_fdt, false);
if (cores > 0) {
cores = MIN(cores, MAXCPU);
if (bootverbose)
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


Re: svn commit: r301070 - head/sys/arm64/arm64

2016-05-31 Thread John Baldwin
On Tuesday, May 31, 2016 06:45:52 PM Andrew Turner wrote:
> Author: andrew
> Date: Tue May 31 18:45:52 2016
> New Revision: 301070
> URL: https://svnweb.freebsd.org/changeset/base/301070
> 
> Log:
>   Allow the kernel to boot on a CPU where the devicetree has numbered it with
>   a non-zero ID. To do this we increment the cpuid of any CPUs with a smaller
>   devicetree ID by one to stop them conflicting with the boot CPU.
>   
>   Obtained from:  ABT Systems Ltd
>   Sponsored by:   The FreeBSD Foundation

It's a bit more friendly if you can have FreeBSD CPU IDs still represent the
topology of the system if possible.  On x86 we don't always boot from CPU 0
either (in fact, it's an election system so that the APIC ID of the BSP can
vary from boot to boot).  What we do however, is add CPUs from the same
core, then package first after the BSP and then add remaining CPUs as we
normally would.  For x86, the first thread in a package is always chosen as
the BSP, so this is implemented by starting at the APIC ID of the BSP and
assigning CPU IDs to increasing APIC IDs and eventually wrapping back around
to APIC ID 0 to add CPUs from "earlier" packages if we did not boot from
package 0.  However, this means that if you have a system with dual quad-core
CPUs, CPUs 0-3 are always one package and 4-7 are always the other, regardless
of which package is used for booting.  Initially the x86 code did not do that
but just skipped over the BSP when adding APs (so something similar I think to
what you've done here), but that meant that when the second package won the
boot-time election, CPUs 0,5-7 were on one package and 1-4 were on another
package.

-- 
John Baldwin
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"