# © IBM Corp. 2022 # Licensed under and subject to the terms of the CC-BY 4.0 # license (https://creativecommons.org/licenses/by/4.0/legalcode). # Additional rights, including the right to physically implement a softcore # that is compliant with the required sections of the Power ISA # Specification, will be available at no cost via the OpenPOWER Foundation. # This README will be updated with additional information when OpenPOWER's # license is available. # start conversion to simple boot which jumps to bios # this version will work similarly to original fpga test version # the original version did not run from rom; eventually will assume rom and do r/w data copy/init # the rom and test are built into separate memory loads or a single one with addr/data format # boot kernel # set up translations # set up timer facilities # set up threads # call user code # process user rc # todo: # 1. skip_printf_init flag should be threaded .include "defines.s" # constants from linker script, or defsym .ifndef STACKSIZE .set STACKSIZE,_stack_size .endif .ifndef STACK0 .set STACK0,_stack_0 .endif .ifndef STACK1 .set STACK1,_stack_1 .endif .set STACK2, 0 .set STACK3, 0 .ifndef TEST .set TEST,_test_start .endif .section .text .global _start _start: int_000: b boot_start # critical input .align 5 int_020: b . # debug .align 5 int_040: b . # dsi .align 5 int_060: b . # isi .align 5 int_080: b . # external .align 5 int_0A0: b . # alignment .align 5 int_0C0: b . # program .align 5 int_0E0: b . # fp unavailable .align 5 int_100: b . # sc .align 5 int_120: b int_120_handler # apu unavailable .align 5 int_140: b . # decrementer .align 5 int_160: b . # fit .align 5 int_180: b . # watchdog .align 5 int_1A0: b . # dtlb .align 5 int_1C0: b . # itlb .align 5 int_1E0: b . # vector unavailable .align 5 int_200: b . # .align 5 int_220: b . # .align 5 int_240: b . # .align 5 int_260: b . # doorbell .align 5 int_280: b . # doorbell critical .align 5 int_2A0: b . # doorbell guest .align 5 int_2C0: b . # doorbell guest critical .align 5 int_2E0: b . # hvsc .align 8 int_300: b int_300_handler # hvpriv .align 5 int_320: b . # lrat .align 5 int_340: b . # ------------------------------------------------------------------------------------------------------------------------------ # initial translation # both erats: # 00000000 1M: (boot) # 10000000 1M: (test) .align 8 boot_start: mfspr r5,tir # who am i? cmpdi r5,0x00 # skip unless T0 bne init_t123 lis r3,0x8C00 # 32=ecl 36:37=tlbsel (10=i, 11=d) # derat 31 @00000000 li r0,0x001F # entry #31 li r2,0x0015 # word 2 wlc=40:41 rsvd=42 u=44:47 r=48 c=49 wimge=52:56 vf=57 ux/sx=58:59 uw/sw=60:61 ur/sr=62:63 li r4,0 # word 1 rpn(32:51)=32:51 rpn(22:31)=54:63 li r8,0x025F # word 0 epn=32:51 class=52:53 v=54 x=55 size=56:59 thrd=60:63 size: 0001=4K 0011=64K 0101=1M 0111=16M 1010=1G mtspr mmucr0,r3 eratwe r2,r0,2 eratwe r4,r0,1 eratwe r8,r0,0 isync lwz r10,CONFIG+S_ERATW2(r0) # load parms for erat settings # derat 30 @100000000 li r0,0x001E # entry #30 lis r4,0x1000 # word 1 rpn(32:51)=32:51 rpn(22:31)=54:63 li r8,0x025F # word 0 epn=32:51 class=52:53 v=54 x=55 size=56:59 thrd=60:63 size: 0001=4K 0011=64K 0101=1M 0111=16M 1010=1G oris r8,r8,0x1000 eratwe r10,r0,2 eratwe r4,r0,1 eratwe r8,r0,0 isync lis r3,0x8800 # 32=ecl 36:37=tlbsel (10=i, 11=d) # ierat 15 @00000000 li r0,0x000F # entry #15 li r2,0x003F # word 2 wlc=40:41 rsvd=42 u=44:47 r=48 c=49 wimge=52:56 vf=57 ux/sx=58:59 uw/sw=60:61 ur/sr=62:63 li r4,0 # word 1 rpn(32:51)=32:51 rpn(22:31)=54:63 li r8,0x025F # word 0 epn=32:51 class=52:53 v=54 x=55 size=56:59 thrd=60:63 size: 0001=4K 0011=64K 0101=1M 0111=16M 1010=1G mtspr mmucr0,r3 eratwe r2,r0,2 eratwe r4,r0,1 eratwe r8,r0,0 isync # *** leave the init'd entry 14 for MT access to FFFFFFC0 # ierat 13 @10000000 li r0,0x000D # entry #13 lis r4,0x1000 # word 1 rpn(32:51)=32:51 rpn(22:31)=54:63 li r8,0x025F # word 0 epn=32:51 class=52:53 v=54 x=55 size=56:59 thrd=60:63 size: 0001=4K 0011=64K 0101=1M 0111=16M 1010=1G oris r8,r8,0x1000 eratwe r10,r0,2 eratwe r4,r0,1 eratwe r8,r0,0 isync # ------------------------------------------------------------------------------------------------------------------------------ # init # # T0-only # set up any core facilities, then enable the others if config'd init_t0: # switch to 64b lwz r10,CONFIG+S_MSR(r0) mtmsr r10 isync # other init lis r1,0x0300 # icm=gicm=1 mtspr epcr,r1 # set up timer facs li r1,0 # clear mtspr dec,r1 mtspr tbh,r1 mtspr tbl,r1 lis r2,0xFE00 # mask: clear enw,wis,wrs,dis,fis,udis mtspr tsr,r2 mfspr r2,xucr0 andi. r2,r2,0x0200 # set tcs=0 mtspr xucr0,r2 mtspr tsr,r1 # clear tsr mtspr tcr,r1 # disable all timers # set thread configuration lwz r1,CONFIG+S_FLAGS(r0) andi. r1,r1,0xF mtspr tens,r1 # 60:63 = tid 3:0 enabled #not r1,r1 #mtspr tenc,r1 # in case T0 is marked disabled isync b boot_complete # except T0 # just worry about myself init_t123: # switch to 64b lwz r10,CONFIG+S_MSR(r0) mtmsr r10 isync b boot_complete # ------------------------------------------------------------------------------------------------------------------------------ boot_complete: # set up thread and hop to it lwz r1,CONFIG+S_FLAGS(r0) andis. r1,r1,0x8000 # 1=skip initial printf init bne boot_complete_1 bl printf_reset # wipe buffer boot_complete_1: lwz r1,CONFIG+S_FLAGS(r0) lis r2,0x7FFF # clear printf flag ori r2,r2,0xFFFF and r1,r1,r2 stw r1,CONFIG+S_FLAGS(r0) mfspr r5,tir # who am i? sldi r5,r5,6 # 64B offset addi r5,r5,CONFIG+T_CONFIG lwz r11,T_MSR(r5) ld r12,T_STACK(r5) ld r13,T_ENTRY(r5) lwz r1,CONFIG+S_FLAGS(r0) andi. r1,r1,FLAG_EOT_SC beq eot_blr eot_sc: lwz r2,CONFIG+S_EOT_SC(r0) lis r1,0x4400 # 'sc 1' ori r1,r1,0022 std r1,0x0(r2) mtlr r1 # prog will blr to sc b process_start eot_blr: bl 4 mflr r1 addi r1,r1,0x30 # !!!!!!!!!!!!!!! <-- WARNING! mtlr r1 # prog will blr to exec_complete process_start: mtspr srr1,r11 # msr mtspr srr0,r13 # @entry mr r1,r12 # @stack mfspr r3,tir # tid - main(tid) if yall want it mfspr r2,tb std r2,T_TIMER_START(r5) rfi nop # !!!!!!!!!!!!!!! pads for lr calc nop nop # ------------------------------------------------------------------------------------------------------------------------------ exec_complete: # allow blr to here, or it will be entered by sc directly # user blr'd here... sc 1 # hvsc back to sup state exec_complete_sup: mfspr r5,tir # who am i? sldi r5,r5,6 # 64B offset addi r5,r5,CONFIG+T_CONFIG mfspr r2,tb std r2,T_TIMER_END(r5) cmpdi r3,0 # check rc beq pass b fail # ------------------------------------------------------------------------------------------------------------------------------ # dead zone .align 8 fail: b . # ------------------------------------------------------------------------------------------------------------------------------ # happy ending .align 8 pass: b . # ------------------------------------------------------------------------------------------------------------------------------ # dec .align 11 int_800: b . # perf .align 5 int_820: b . .set CONFIG,0x0A00 # ------------------------------------------------------------------------------------------------------------------------------ # config info .align 9 .long 0x8002B000 # sup MSR cm=1 ce=1 ee=1 pr=0 fp=1 me=1 fe=00 de=0 is=0 ds=0 .long 0x80000001 # flags: skip_printf_init=0 eot_sc=27 thr_en=28:31(T3:T0) # LE # .long 0x000000BF # erat w2 (test) # word 2 wlc=40:41 rsvd=42 u=44:47 r=48 c=49 wimge=52:56 vf=57 ux/sx=58:59 uw/sw=60:61 ur/sr=62:63 # BE .long 0x0000003F # erat w2 (test) # word 2 wlc=40:41 rsvd=42 u=44:47 r=48 c=49 wimge=52:56 vf=57 ux/sx=58:59 uw/sw=60:61 ur/sr=62:63 .long 0x10000000 # @user eot sc # per-thread configs (64B each) .align 7 .long 0x8002F000 # usr MSR cm=1 ce=1 ee=1 pr=1 fp=1 me=1 fe=00 de=0 is=0 ds=0 .long 0x00000000 # .long 0x00000000 # .long STACK0 # @stack .long 0x00000000 # .long TEST # @entry .long 0 .long 0x10030000 # @print_start .long 0 .long 0x10031FFF # @print_end .long 0 .long 0x10030000 # print ptr .quad 0 # start tb .quad 0 # end tb .long 0x8002F000 # usr MSR cm=1 ce=1 ee=1 pr=1 fp=1 me=1 fe=00 de=0 is=0 ds=0 .long 0x00000000 # .long 0x00000000 # .long STACK1 # @stack .long 0x00000000 # .long TEST # @entry .long 0 .long 0x10032000 # @print_start .long 0 .long 0x10033FFF # @print_end .long 0 .long 0x10032000 # print ptr .quad 0 # start tb .quad 0 # end tb .long 0x8002F000 # usr MSR cm=1 ce=1 ee=1 pr=1 fp=1 me=1 fe=00 de=0 is=0 ds=0 .long 0x00000000 # flags .long 0x00000000 # .long STACK2 # @stack .long 0x00000000 # .long TEST # @entry .long 0 .long 0x10034000 # @print_start .long 0 .long 0x10035FFF # @print_end .long 0 .long 0x10034000 # print ptr .quad 0 # start tb .quad 0 # end tb .long 0x8002F000 # usr MSR cm=1 ce=1 ee=1 pr=1 fp=1 me=1 fe=00 de=0 is=0 ds=0 .long 0x00000000 # flags .long 0x00000000 # .long STACK3 # @stack .long 0x00000000 # .long TEST # @entry .long 0 .long 0x10036000 # @print_start .long 0 .long 0x10037FFF # @print_end .long 0 .long 0x10036000 # print ptr .quad 0 # start tb .quad 0 # end tb .set S_MSR,0x00 .set S_FLAGS,0x04 .set S_ERATW2,0x08 .set S_EOT_SC,0x0C .set T_CONFIG,0x80 .set T_MSR,0x00 .set T_FLAGS,0x04 .set T_STACK,0x08 .set T_ENTRY,0x10 .set T_TIMER_START,0x30 .set T_TIMER_END,0x38 .set T_PRINTSTART, 0x18 .set T_PRINTEND, 0x20 .set T_PRINTF, 0x28 .set FLAG_EOT_SC,0x10 # ------------------------------------------------------------------------------------------------------------------------------ # other stuff .align 10 # clear buffer and reset pointer to start .align 6 printf_reset: mfspr r5,tir # who am i? sldi r5,r5,6 # 64B offset addi r5,r5,CONFIG+T_CONFIG addi r6,r5,T_PRINTSTART ld r7,0(r6) # buffer start addi r6,r5,T_PRINTEND ld r8,0(r6) # buffer end sub r8,r8,r7 addi r8,r8,1 # num bytes mtctr r8 li r6,0 mr r8,r7 printf_reset_clr: stb r6,0(r8) addi r8,r8,1 bdnz printf_reset_clr addi r8,r5,T_PRINTF std r7,0(r8) # reset ptr blr # hvsc .align 8 # go to exec_complete_sup in sup mode int_300_handler: lwz r0,CONFIG+S_MSR(r0) mtmsr r0 isync b exec_complete_sup # sc .align 8 # r3 is id, remaining are function-specific # not preserving r0, r3-r9 right now # # 0001 whoami # 0010 tick # 0100 putchar r4=c # 0106 printf_mode *NI* # 0107 printf_rst # int_120_handler: mflr r0 cmpdi r3,0x0001 beq sc_whoami cmpdi r3,0x0010 beq sc_tick cmpdi r3,0x100 beq sc_putchar cmpdi r3,0x107 beq sc_printf_rst li r3,-1 mtlr r0 rfi # thread id .align 6 sc_whoami: mfspr r3,tir rfi # tb .align 6 sc_tick: mfspr r3,tb rfi # wrap buffer; could add flag to stop when full, or reset .align 6 sc_putchar: mfspr r5,tir # who am i? sldi r5,r5,6 # 64B offset addi r5,r5,CONFIG+T_CONFIG addi r6,r5,T_PRINTF ld r7,0(r6) # buffer ptr stb r4,0(r7) # store char addi r7,r7,1 addi r8,r5,T_PRINTEND ld r8,0(r8) # buffer end cmpd r7,r8 li r3,0 # rc=normal ble sc_putchar_ok addi r8,r5,T_PRINTSTART ld r7,0(r8) # buffer start li r3,-1 # rc=full sc_putchar_ok: std r7,0(r6) # save ptr rfi # clear buffer and reset pointer to start .align 6 sc_printf_rst: mfctr r3 bl printf_reset mtctr r3 mtlr r0 li r3,0 rfi