From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([140.186.70.92]:52227) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Qji3L-0002D6-Lk for qemu-devel@nongnu.org; Wed, 20 Jul 2011 21:27:55 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Qji38-0003qD-HF for qemu-devel@nongnu.org; Wed, 20 Jul 2011 21:27:49 -0400 Received: from cantor2.suse.de ([195.135.220.15]:57991 helo=mx2.suse.de) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Qji37-0003ph-Od for qemu-devel@nongnu.org; Wed, 20 Jul 2011 21:27:38 -0400 From: Alexander Graf Date: Thu, 21 Jul 2011 03:27:12 +0200 Message-Id: <1311211654-14326-2-git-send-email-agraf@suse.de> In-Reply-To: <1311211654-14326-1-git-send-email-agraf@suse.de> References: <1311211654-14326-1-git-send-email-agraf@suse.de> Subject: [Qemu-devel] [PATCH 01/23] PPC: Add secondary CPU spinning code List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: QEMU-devel Developers Cc: Scott Wood When directly starting an SMP system with -kernel on PPC e500, we need to simulate the spin table code from u-boot. This code adds a small c file plus generated .elf file that enable secondary CPUs to spin just like they would with u-boot. Signed-off-by: Alexander Graf --- pc-bios/ppc_spin.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++ pc-bios/ppc_spin.elf | Bin 0 -> 66553 bytes 2 files changed, 97 insertions(+), 0 deletions(-) create mode 100644 pc-bios/ppc_spin.c create mode 100755 pc-bios/ppc_spin.elf diff --git a/pc-bios/ppc_spin.c b/pc-bios/ppc_spin.c new file mode 100644 index 0000000..e46a6a7 --- /dev/null +++ b/pc-bios/ppc_spin.c @@ -0,0 +1,97 @@ +#include +#include + +/* + * Secondary CPU spin code + * + * Compile using: gcc -m32 -nostdlib ppc_spin.c -o ppc_spin.elf -Os \ + * -fno-stack-protector -Wl,-Ttext,0x7700000 + */ + +/* Initialize stack pointer */ +asm ( +" .global _start \n" +" _start: \n" +" addis 1, 3, 0x10000@h \n" +" b spin \n"); + +typedef struct spin_info { + uint32_t addr_hi; + uint32_t addr; + uint32_t r3_hi; + uint32_t r3; + uint32_t resv; + uint32_t pir; + uint32_t r6_hi; + uint32_t r6; +} SpinInfo; + +#define __stringify_1(x...) #x +#define __stringify(x...) __stringify_1(x) + +#define mfspr(rn) ({unsigned long rval; \ + asm volatile("mfspr %0," __stringify(rn) \ + : "=r" (rval)); rval;}) +#define mtspr(rn, v) asm volatile("mtspr " __stringify(rn) ",%0" : : "r" (v)\ + : "memory") +static inline void mtdec(unsigned long v) +{ + asm volatile("mtdec %0" : : "r" (v)); +} + +static inline void mtmsr(unsigned long msr) +{ + asm("mtmsr %0" : : "r"(msr)); +} + +#define __MASK(X) (1UL<<(X)) +#define MSR_WE_LG 18 /* Wait State Enable */ +#define MSR_EE_LG 15 /* External Interrupt Enable */ +#define MSR_WE __MASK(MSR_WE_LG) /* Wait State Enable */ +#define MSR_EE __MASK(MSR_EE_LG) /* External Interrupt Enable */ +#define SPR_PIR 0x11E +#define SPR_HID0 (0x3F0) +#define SPR_BOOKE_IVOR10 (0x19A) +#define SPR_BOOKE_IVPR (0x03F) + +void loop(void); + +__attribute__((noreturn)) void spin(unsigned long ptr) +{ + volatile SpinInfo *info = (void*)ptr; + uint32_t pir = mfspr(SPR_PIR); + __attribute__((noreturn)) void (*entry)( + unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, + unsigned long r7, unsigned long r8, unsigned long r9); + unsigned long dec_p = (unsigned long)loop; + + info->pir = pir; + info->r3 = pir; + info->addr = 1; + info->r6 = 0; + + /* we don't want to keep the other CPUs from running, so set the IVOR for + DEC to our loop and only check for info->addr every other cycle */ + + mtspr(SPR_HID0, 0x00E00000); + mtspr(SPR_BOOKE_IVOR10, dec_p & 0xfff); + mtspr(SPR_BOOKE_IVPR, dec_p & ~0xfff); +loop: + asm volatile (".global loop\n" + " loop:" : : : "memory", "cc"); + + if (info->addr & 1) { + /* wait until addr is valid */ + mtdec(0x100000); + mtmsr(MSR_WE|MSR_EE); + /* should never reach here */ + while(1) { } + } + + asm volatile (""); + + mtspr(SPR_HID0, 0); + info->pir = pir; + entry = (void*)(unsigned long)info->addr; + entry(info->r3, 0, 0, info->r6, 64 * 1024 * 1024, 0, 0); +} diff --git a/pc-bios/ppc_spin.elf b/pc-bios/ppc_spin.elf new file mode 100755 index 0000000000000000000000000000000000000000..71c872b2d4685100b0050d549735662d7d763e08 GIT binary patch literal 66553 zcmeIvJ#14~6u|Lw?Uy)KGdMIt2pAq}1Q;n#1dNoR(27QsO65DrK&xW>rNk<+U+tGR zRgG$Ot}0q}>d-PEFED0dXJcVxWa(Zcm>A4Cetr(1EQs}gt>bs@Irqcw=U>iU_`;=} zj7CbPHFueCP$`IWzYQ~AJUJ>^8MnTE#MTVgJ*2}=zL}v-mq`a-TNY5 zHTv(W9kR=?yS-iNln_7w0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILKmY**K2Tus6LDXPcz+%0|KIuUz*c7>)w|0_^$uw(8J;H7 z8tL?53le4_n)tpfA0TzU(PQro%W9|uP&eSFVq{GTY0|_oD5F* z->g+CvxVZx*>bDYsI2>~+7I=1z1i^R3UenG=DwA)dhFC%V^f?aSG-4 z$yA?7?@Y7be>tiu;k49Bq1C*tqEC2ui literal 0 HcmV?d00001 -- 1.6.0.2