On Sat, Aug 13, 2016 at 08:26:30PM +0200, Mark Kettenis wrote: > On Cortex-A7 there is a magic SMP bit in the Auxiliary Control > Register that "Enables coherent requests to the processor". The > Cortex-A7 Technical Reference Manual mentions that: > > When coherent requests are disabled: > > * loads to cacheable memory are not cached by the processor. > > So effectively, not setting the bit means that we would be running the > CPU with its caches disabled. We do attempt to set this bit, but the > code actually toggled the bit. So if the firmware had set the bit, > like it does on my Banana Pi, we would unset it. The result was that > the CPU was running at glacial speed. > > Now the Cortex-A7 TRM also has the following note: > > You must ensure this bit is set to 1 before the caches and MMU are > enabled, or any cache and TLB maintenance operations are > performed. The only time this bit is set to 0 is during a processor > power-down sequence. > > So we really should be setting the Auxiliary Control Register before > we enable the MMU and caches by setting the System Control Register. > The diff below fixes these issues and brings in some symbolic > constants for the Auxiliary Control Register bits from NetBSD. > > Tested on both Cortex-A9 and Cortex-A7. > > ok?
yes ok, but the defines should really be ACTLR not AUXCTL to match the arm docs. Interesting that cortex a53/a57/a72 don't have a smp/coherency bit. Comparing to the FreeBSD code they also set/mask cortex a15: set (1U << 31) "snoop delayed exclusive handling" cortex a9: mask (1 << 7) "exclusive L1/L2 cache control" cortex a8: set/mask (1 << 1) Enable L2 cache mask (1 << 0) L1 data cache hardware alias support enabled cortex a5: mask (1 << 7) disable exclusive L1/L2 cache control https://svnweb.freebsd.org/base/head/sys/arm/arm/cpuinfo.c?revision=HEAD&view=markup > > > Index: arch/arm/arm/cpufunc.c > =================================================================== > RCS file: /cvs/src/sys/arch/arm/arm/cpufunc.c,v > retrieving revision 1.44 > diff -u -p -r1.44 cpufunc.c > --- arch/arm/arm/cpufunc.c 10 Aug 2016 21:22:43 -0000 1.44 > +++ arch/arm/arm/cpufunc.c 13 Aug 2016 18:23:39 -0000 > @@ -568,6 +568,26 @@ armv7_setup() > uint32_t auxctrl, auxctrlmask; > uint32_t cpuctrl, cpuctrlmask; > > + auxctrl = auxctrlmask = 0; > + > + switch (cputype & CPU_ID_CORTEX_MASK) { > + case CPU_ID_CORTEX_A5: > + case CPU_ID_CORTEX_A9: > + /* Cache and TLB maintenance broadcast */ > +#ifdef notyet > + auxctrlmask |= CORTEXA9_AUXCTL_FW; > + auxctrl |= CORTEXA9_AUXCTL_FW; > +#endif > + /* FALLTHROUGH */ > + case CPU_ID_CORTEX_A7: > + case CPU_ID_CORTEX_A15: > + case CPU_ID_CORTEX_A17: > + /* Set SMP to allow LDREX/STREX */ > + auxctrlmask |= CORTEXA9_AUXCTL_SMP; > + auxctrl |= CORTEXA9_AUXCTL_SMP; > + break; > + } > + > cpuctrlmask = CPU_CONTROL_MMU_ENABLE > | CPU_CONTROL_AFLT_ENABLE > | CPU_CONTROL_DC_ENABLE > @@ -590,29 +610,16 @@ armv7_setup() > /* Clear out the cache */ > cpu_idcache_wbinv_all(); > > + /* > + * Set the auxilliary control register first, as the SMP bit > + * needs to be set to 1 before the caches and the MMU are > + * enabled. > + */ > + cpu_auxcontrol(auxctrlmask, auxctrl); > + > /* Set the control register */ > curcpu()->ci_ctrl = cpuctrl; > cpu_control(cpuctrlmask, cpuctrl); > - > - auxctrl = auxctrlmask = 0; > - > - switch (cputype & CPU_ID_CORTEX_MASK) { > - case CPU_ID_CORTEX_A5: > - case CPU_ID_CORTEX_A9: > - /* Cache and TLB maintenance broadcast */ > -#ifdef notyet > - auxctrl |= (1 << 0); > -#endif > - /* FALLTHROUGH */ > - case CPU_ID_CORTEX_A7: > - case CPU_ID_CORTEX_A15: > - case CPU_ID_CORTEX_A17: > - /* Set SMP to allow LDREX/STREX */ > - auxctrl |= (1 << 6); > - break; > - } > - > - cpu_auxcontrol(auxctrlmask, auxctrl); > > /* And again. */ > cpu_idcache_wbinv_all(); > Index: arch/arm/include/armreg.h > =================================================================== > RCS file: /cvs/src/sys/arch/arm/include/armreg.h,v > retrieving revision 1.33 > diff -u -p -r1.33 armreg.h > --- arch/arm/include/armreg.h 6 Aug 2016 16:46:25 -0000 1.33 > +++ arch/arm/include/armreg.h 13 Aug 2016 18:23:39 -0000 > @@ -269,6 +269,16 @@ > #define XSCALE_AUXCTL_MD_WT 0x00000020 /* mini-D$ wt, read-allocate */ > #define XSCALE_AUXCTL_MD_MASK 0x00000030 > > +/* Cortex-A9 Auxiliary Control Register (CP15 register 1, opcode 1) */ > +#define CORTEXA9_AUXCTL_FW (1 << 0) /* Cache and TLB updates broadcast */ > +#define CORTEXA9_AUXCTL_L2PE (1 << 1) /* Prefetch hint enable */ > +#define CORTEXA9_AUXCTL_L1PE (1 << 2) /* Data prefetch hint enable */ > +#define CORTEXA9_AUXCTL_WR_ZERO (1 << 3) /* Ena. write full line of 0s > mode */ > +#define CORTEXA9_AUXCTL_SMP (1 << 6) /* Coherency is active */ > +#define CORTEXA9_AUXCTL_EXCL (1 << 7) /* Exclusive cache bit */ > +#define CORTEXA9_AUXCTL_ONEWAY (1 << 8) /* Allocate in on cache way > only */ > +#define CORTEXA9_AUXCTL_PARITY (1 << 9) /* Support parity checking */ > + > /* Cache type register definitions */ > #define CPU_CT_ISIZE(x) ((x) & 0xfff) /* I$ info */ > #define CPU_CT_DSIZE(x) (((x) >> 12) & 0xfff) /* D$ info */ >
