{"id":331,"date":"2012-01-03T18:29:50","date_gmt":"2012-01-04T00:29:50","guid":{"rendered":"http:\/\/tommysprinkle.com\/txxos\/?p=331"},"modified":"2021-04-17T18:23:41","modified_gmt":"2021-04-17T23:23:41","slug":"nucleus-low-core","status":"publish","type":"post","link":"https:\/\/tommysprinkle.com\/txxos\/?p=331","title":{"rendered":"TXXNUC &#8211; Nucleus Low Core"},"content":{"rendered":"<p>Now we can begin creating our small operating system. \u00a0It starts with the low core module for the nucleus. \u00a0The low core module must be loaded first at location zero. \u00a0When we link edit the nucleus we must make sure it is included first.<\/p>\n<p>It begins with the data for mapping the hardware specific addresses in low memory.<\/p>\n<pre>000000                                1 TXXNUC   CSECT ,\r\n000000 0000000000000578               2          DC    X'00',X'00',AL2(0),AL4(DISPINIT)  INITIAL PSW\r\n000008 0000000000000000               3          DC    D'0'                              RST NEW PSW\r\n                                      4 *\r\n000010 00000000                       5          DC    V(TXXCVT)                         COMM VECT TABLE\r\n000014 00000000                       6          DC    V(TXXMVT)                         MOD  VECT TABLE\r\n                                      7 *\r\n000018 0000000000000000               8          DC    D'0'          EXT OLD PSW\r\n000020 0000000000000000               9          DC    D'0'          SVC OLD PSW\r\n000028 0000000000000000              10          DC    D'0'          PGM OLD PSW\r\n000030 0000000000000000              11          DC    D'0'          MCK OLD PSW\r\n000038 0000000000000000              12          DC    D'0'          I\/O OLD PSW\r\n                                     13 *\r\n000040 0000000000000000              14          DC    D'0'          CHANNEL STATUS WORD\r\n000048 00000000                      15          DC    F'0'          CHANNEL ADDRESS WORD\r\n00004C 00000000                      16          DC    F'0'\r\n000050 00000000                      17          DC    F'0'          INTERVAL TIMER\r\n000054 00000000                      18          DC    F'0'\r\n                                     19 *\r\n000058 0000000000000530              20          DC    X'00',X'00',AL2(0),AL4(EXTHNDLR)  EXT NEW PSW\r\n000060 0000000000000554              21          DC    X'00',X'00',AL2(0),AL4(SVCHNDLR)  SVC NEW PSW\r\n000068 0000000000000520              22          DC    X'00',X'00',AL2(0),AL4(PGMHNDLR)  PGM NEW PSW\r\n000070 0000000000EE0001              23          DC    X'00',X'02',AL2(0),AL4(@E@MCK)    MCK NEW PSW\r\n000078 0000000000000520              24          DC    X'00',X'00',AL2(0),AL4(IOHNDLR)   I\/O NEW PSW<\/pre>\n<p>The restart PSW is the initial PSW that will be loaded by the nucleus loader. \u00a0It will cause execution to begin at DISPINIT &#8211; the dispatcher\u00a0initialization\u00a0routine. \u00a0Locations 16 (x&#8217;10&#8217;) and 20 (x&#8217;14&#8217;) are not used by the CPU so we will use them as pointers. \u00a0Location 16 will point to a control block that contains system related data and pointers (the Communication Vector Table &#8211; or CVT). \u00a0Location 20 will point the the Module Vector Table (MVT) which is a list of pointers to other modules. \u00a0Our system modules in general will not contain a direct pointer V(module) to a module. \u00a0Instead the module address will be obtained from the MVT.<\/p>\n<p>Next we have the OLD PSW areas for external, SVC, program, machine check, and I\/O interruptions. \u00a0This is where the CPU will store the current PSW when an interrupt occurs. \u00a0It is followed by the\u00a0Channel\u00a0Status Word and Channel Address Word. \u00a0The Interval Timer is used to generate an external interrupt. \u00a0A value is loaded into the Interval Timer word. \u00a0The CPU will decrement the value. \u00a0When the timer is expired an external interrupt will be generated.<\/p>\n<p>Finally we define the NEW SVC values for the various interrupts. \u00a0When an interrupt occurs the CPU will load the PSW with the associated value. \u00a0If a machine check occurs we load a disabled wait PSW.<\/p>\n<pre>                            00080    27 LOWCLEN  EQU   *-TXXNUC\r\n                            00380    28 LOWCFILL EQU   1024-LOWCLEN\r\n000080 0000000000000000              29          DC    (LOWCFILL)X'00'\r\n                                     30 *\r\n000400 0000000000000000              32 EXTREGS  DC    16F'0'             EXT INTERRUPT REG SAVE\r\n000440 0000000000000000              33 IOREGS   DC    16F'0'             I\/O INTERRUPT REG SAVE\r\n000480 0000000000000000              34 SVCREGS  DC    16F'0'             SVC INTERRUPT REG SAVE\r\n0004C0 0000000000000000              35 PGMREGS  DC    16F'0'             PGM INTERRUPT REG SAVE<\/pre>\n<p>Next we fill the remainder of memory up to 1k with zeros. \u00a0Beginning at address 1k we define interrupt register save areas. \u00a0This gives us a place to save current register contents when an interrupt occurs. \u00a0Because the save areas are in the first 4k of memory we will \u00a0not need a base register to access them.<\/p>\n<pre>                            00000    39          USING TXXNUC,0      NO BASE REGISTER NEEDED FOR FIRST 4K\r\n                                     48          ENTRY LLDISP\r\n000500                               49 LLDISP   DS    0H\r\n                            00000    50          USING @TCB,R4\r\n                                     51 *\r\n000500 5810 05B8      005B8          52          L     R1,=A(X'80')       RESTART TIMER\r\n000504 5010 0050      00050          53          ST    R1,ITIMER-@LOWCORE              AT DISPATCH\r\n                                     54 *\r\n000508 D207 0518 4018 00518 00018    55          MVC   LLRSTPSW,TCBPSW    COPY TCB PSW INTO LOW CORE\r\n00050E 980F 4020      00020          56          LM    R0,R15,TCBREGS     RESTORE TCB REGISTERS\r\n000512 8200 0518      00518          57          LPSW  LLRSTPSW           DISPATCH\r\n                                     58 *\r\n000516 0000\r\n000518 0000000000000000              60 LLRSTPSW DC    D'0'               DISPATCH PSW\r\n                                     62          DROP  R4<\/pre>\n<p>Now comes our Low Level Dispatch routine. \u00a0We need some code in low memory (first 4k) to restore registers and PSW when returning from an interrupt. \u00a0This code needs to be in low memory so we will not require the use of a base register. \u00a0We start by resetting the Interval Timer. \u00a0When it expires it will interrupt the currently running task so we reset it to give each task the same execution interval. \u00a0On entry to LLDISP Register 4 must contain the address of the TCB to be dispatched. \u00a0First the PSW is copied out of the TCB and into low core. \u00a0Next the registers are restored from the TCB. \u00a0A Load PSW instruction loads the PSW that was saved from the TCB.<\/p>\n<pre>000520                               68 PGMHNDLR DS    0H\r\n000520                               69 IOHNDLR  DS    0H\r\n000520 8200 0528      00528          70          LPSW  WAITPSW\r\n                                     71 *\r\n000528                               72          DS    0D\r\n000528 0002000000EE9999              73 WAITPSW  DC    X'00',X'02',AL2(0),A(X'EE9999')<\/pre>\n<p>For now if a program or I\/O interrupt occurs we will load a wait state PSW. \u00a0Later we will provide interrupt handling for these interrupts.<\/p>\n<pre>000530                               81 EXTHNDLR DS    0H\r\n000530 900F 0400      00400          82          STM   R0,R15,EXTREGS     SAVE REGISTERS\r\n                                     83 *\r\n000534 05C0                          84          BALR  R12,0              ESTABLISH BASE REGISTER\r\n                            00536    85          USING *,R12\r\n                                     86 *\r\n000536 58B0 0010      00010          87          L     R11,16             GET CVT ADDRESS\r\n00053A 5840 B000      00000          88          L     R4,CVTCTCB-@CVT(,R11) GET CURRENT TCB\r\n                            00000    89          USING @TCB,R4\r\n                                     90 *\r\n00053E D207 4018 0018 00018 00018    91          MVC   TCBPSW,EXTOPSW-@LOWCORE  SAVE INT PSW\r\n000544 D23F 4020 0400 00020 00400    92          MVC   TCBREGS(64),EXTREGS      SAVE INT   REGISTERS\r\n                                     93 *\r\n00054A 58B0 0014      00014          94          L     R11,20             GET MVT ADDRESS\r\n\f00054E 58F0 B000      00000          95          L     R15,MVTEXTIR-@MVT(,R11)   GET EXT INTRUPT RTN\r\n000552 07FF                          96          BR    R15                BRANCH\r\n                                     97 *\r\n                                     98          DROP  R4,R12<\/pre>\n<p>Now comes the External Interrupt handler. \u00a0First the contents of the registers are saved into our low core register save area. \u00a0The current TCB address is obtained from the CVT [Current TCB &#8211; CVTCTCB]. \u00a0The interrupt PSW and registers are copied into the TCB. \u00a0The external interrupt routine is located in the MVT and control is passed to it.<\/p>\n<pre>000554                              105 SVCHNDLR DS    0H\r\n000554 900F 0480      00480         106          STM   R0,R15,SVCREGS     SAVE INTERRUPT REGISTERS\r\n                                    107 *\r\n000558 05C0                         108          BALR  R12,0              ESTABLISH\r\n                            0055A   109          USING *,R12                       BASE REGISTER\r\n                                    110 *\r\n00055A 5840 0010      00010         111          L     R4,16              CVT\r\n00055E 5840 4000      00000         112          L     R4,CVTCTCB-@CVT(,R4)  GET CURRENT TCB\r\n                            00000   113          USING @TCB,R4\r\n                                    114 *\r\n000562 D207 4018 0020 00018 00020   115          MVC   TCBPSW,SVCOPSW-@LOWCORE   SAVE INTERRUPT PSW\r\n000568 D23F 4020 0480 00020 00480   116          MVC   TCBREGS(64),SVCREGS       SAVE INTERRUPT REGS\r\n                                    117 *\r\n00056E 58F0 0014      00014         118          L     R15,20             MVT\r\n000572 58F0 F010      00010         119          L     R15,MVTSVCIR-@MVT(,R15)   SVC INTERRUPT RTN\r\n000576 07FF                         120          BR    R15\r\n                                    121 *\r\n                                    123          DROP  R4,R12<\/pre>\n<p>The SVC interrupt handler is the same as the external interrupt handler except it passes control the SVC Interrupt Routine.<\/p>\n<pre>000578                              127 DISPINIT DS    0H\r\n                            00000   128          USING @IPLPARM,R10\r\n                                    129 *\r\n000578 D503 05BC A000 005BC 00000   130          CLC   =C'@IPL',@IPLID\r\n00057E 4780 0586      00586         131          BE    DISPI010\r\n                                    132 *\r\n000582 8200 05A0      005A0         133          LPSW  ERRINIT\r\n                                    134 *\r\n                                    135 *\r\n000586                              136 DISPI010 DS    0H\r\n000586 58F0 0014      00014         137          L     R15,20             MVT ADDRESS\r\n00058A 58F0 F00C      0000C         138          L     R15,MVTDINIT-@MVT(,R15)   DISPATCER INIT ROUTINE\r\n00058E 05EF                         139          BALR  R14,R15            INTIALIZE DISPATCHER\r\n                                    140 *\r\n000590 58F0 0014      00014         141          L     R15,20             MVT ADDRESS\r\n000594 58F0 F004      00004         142          L     R15,MVTDISP-@MVT(,R15)  DISPATCHER ADDRESS\r\n000598 07FF                         143          BR    R15\r\n                                    144 *\r\n0005A0                              146          DS    0D\r\n0005A0 0000000000000002             147 ERRINIT  DC    A(0,2,0,0),A(@E@IPL)<\/pre>\n<p>Finally we have the Dispatcher\u00a0Initialization. \u00a0We expect a pointer to some information from the LOADER (memory size, IPL Device). \u00a0If the IPL Parameters are not valid a wait stat PSW is loaded. \u00a0Once the IPL Parm Block is validated the \u00a0Dispatcher Initialization Module is called. \u00a0After initialization is complete control is passed to the Dispatcher.<\/p>\n<p>[Next &#8211; <a title=\"TXXEXTIR \u2013 External Interrupt Routine\" href=\"http:\/\/tommysprinkle.com\/txxos\/?p=333\">TXXEXTIR &#8211; External Interrupt Routine<\/a>]<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Now we can begin creating our small operating system. \u00a0It starts with the low core module for the nucleus. \u00a0The low core module must be loaded first at location zero. \u00a0When we link edit the nucleus we must make sure &hellip; <a href=\"https:\/\/tommysprinkle.com\/txxos\/?p=331\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"template-page-builder-no-sidebar.php","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[1],"tags":[],"class_list":["post-331","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p1CPQT-5l","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/tommysprinkle.com\/txxos\/index.php?rest_route=\/wp\/v2\/posts\/331","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tommysprinkle.com\/txxos\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tommysprinkle.com\/txxos\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tommysprinkle.com\/txxos\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tommysprinkle.com\/txxos\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=331"}],"version-history":[{"count":5,"href":"https:\/\/tommysprinkle.com\/txxos\/index.php?rest_route=\/wp\/v2\/posts\/331\/revisions"}],"predecessor-version":[{"id":485,"href":"https:\/\/tommysprinkle.com\/txxos\/index.php?rest_route=\/wp\/v2\/posts\/331\/revisions\/485"}],"wp:attachment":[{"href":"https:\/\/tommysprinkle.com\/txxos\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=331"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tommysprinkle.com\/txxos\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=331"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tommysprinkle.com\/txxos\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=331"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}