1.HTML "Adding Application Support for a New Architecture in Plan 9 2.TL 3Adding Application Support for a New Architecture in Plan 9 4.AU 5Bob Flandrena 6bobf@plan9.bell-labs.com 7.SH 8Introduction 9.LP 10Plan 9 has five classes of architecture-dependent software: 11headers, kernels, compilers and loaders, the 12.CW libc 13system library, and a few application programs. In general, 14architecture-dependent programs 15consist of a portable part shared by all architectures and a 16processor-specific portion for each supported architecture. 17The portable code is often compiled and stored in a library 18associated with 19each architecture. A program is built by 20compiling the architecture-specific code and loading it with the 21library. Support for a new architecture is provided 22by building a compiler for the architecture, using it to 23compile the portable code into libraries, 24writing the architecture-specific code, and 25then loading that code with 26the libraries. 27.LP 28This document describes the organization of the architecture-dependent 29code and headers on Plan 9. 30The first section briefly discusses the layout of 31the headers and the source code for the kernels, compilers, loaders, and the 32system library, 33.CW libc . 34The second section provides a detailed 35discussion of the structure of 36.CW libmach , 37a library containing almost 38all architecture-dependent code 39used by application programs. 40The final section describes the steps required to add 41application program support for a new architecture. 42.SH 43Directory Structure 44.PP 45Architecture-dependent information for the new processor 46is stored in the directory tree rooted at \f(CW/\fP\fIm\fP 47where 48.I m 49is the name of the new architecture (e.g., 50.CW mips ). 51The new directory should be initialized with several important 52subdirectories, notably 53.CW bin , 54.CW include , 55and 56.CW lib . 57The directory tree of an existing architecture 58serves as a good model for the new tree. 59The architecture-dependent 60.CW mkfile 61must be stored in the newly created root directory 62for the architecture. It is easiest to copy the 63mkfile for an existing architecture and modify 64it for the new architecture. When the mkfile 65is correct, change the 66.CW OS 67and 68.CW CPUS 69variables in the 70.CW /sys/src/mkfile.proto 71to reflect the addition of the new architecture. 72.SH 73Headers 74.LP 75Architecture-dependent headers are stored in directory 76.CW /\fIm\fP/include 77where 78.I m 79is the name of the architecture (e.g., 80.CW mips ). 81Two header files are required: 82.CW u.h 83and 84.CW ureg.h . 85The first defines fundamental data types, 86bit settings for the floating point 87status and control registers, and 88.CW va_list 89processing which depends on the stack 90model for the architecture. This file 91is best built by copying and modifying the 92.CW u.h 93file from an architecture 94with a similar stack model. 95The 96.CW ureg.h 97file 98contains a structure describing the layout 99of the saved register set for 100the architecture; it is defined by the kernel. 101.LP 102Header file 103.CW /sys/include/a.out.h 104contains the definitions of the magic 105numbers used to identify executables for 106each architecture. When support for a new 107architecture is added, the magic number 108for the architecture must be added to this file. 109.LP 110The header format of a bootable executable is defined by 111each manufacturer. Header file 112.CW /sys/include/bootexec.h 113contains structures describing the headers currently 114supported. If the new architecture uses a common header 115such as COFF, 116the header format is probably already defined, 117but if the bootable header format is non-standard, 118a structure defining the format must be added to this file. 119.LP 120.SH 121Kernel 122.LP 123Although the kernel depends critically on the properties of the underlying 124hardware, most of the 125higher-level kernel functions, including process 126management, paging, pseudo-devices, and some 127networking code, are independent of processor 128architecture. The portable kernel code 129is divided into two parts: that implementing kernel 130functions and that devoted to the boot process. 131Code in the first class is stored in directory 132.CW /sys/src/9/port 133and the portable boot code is stored in 134.CW /sys/src/9/boot . 135Architecture-dependent kernel code is stored in the 136subdirectories of 137.CW /sys/src/9 138named for each architecture. 139.LP 140The relationship between the kernel code and the boot code 141is convoluted and subtle. The portable boot code 142is compiled into a library for each architecture. An architecture-specific 143main program is loaded with the appropriate library and the resulting 144executable is compiled into the kernel where it is executed as 145a user process during the final stages of kernel initialization. The boot process 146performs authentication, attaches the name space root to the appropriate 147file system and starts the 148.CW init 149process. 150.LP 151The organization of the portable kernel source code differs from that 152of most other architecture-specific code. 153Instead of storing the portable code in a library 154and loading it with the architecture-specific 155code, the portable code is compiled directly into 156the directory containing the architecture-specific code 157and linked with the object files built from the source in that directory. 158.LP 159.SH 160Compilers and Loaders 161.LP 162The compiler source code conforms to the usual 163organization: portable code is compiled into a library 164for each architecture 165and the architecture-dependent code is loaded with 166that library. 167The common compiler code is stored in 168.CW /sys/src/cmd/cc . 169The 170.CW mkfile 171in this directory compiles the portable source and 172archives the objects in a library for each architecture. 173The architecture-specific compiler source 174is stored in a subdirectory of 175.CW /sys/src/cmd 176with the same name as the compiler (e.g., 177.CW /sys/src/cmd/vc ). 178.LP 179There is no portable code shared by the loaders. 180Each directory of loader source 181code is self-contained, except for 182a header file and an instruction name table 183included from the 184directory of the associated 185compiler. 186.LP 187.SH 188Libraries 189.LP 190Most C library modules are 191portable; the source code is stored in 192directories 193.CW /sys/src/libc/port 194and 195.CW /sys/src/libc/9sys . 196Architecture-dependent library code 197is stored in the subdirectory of 198.CW /sys/src/libc 199named the same as the target processor. 200Non-portable functions not only 201implement architecture-dependent operations 202but also supply assembly language implementations 203of functions where speed is critical. 204Directory 205.CW /sys/src/libc/9syscall 206is unusual because it 207contains architecture-dependent information 208for all architectures. 209It holds only a header file defining 210the names and numbers of system calls 211and a 212.CW mkfile . 213The 214.CW mkfile 215executes an 216.CW rc 217script that parses the header file, constructs 218assembler language functions implementing the system 219call for each architecture, assembles the code, 220and archives the object files in 221.CW libc . 222The assembler language syntax and the system interface 223differ for each architecture. 224The 225.CW rc 226script in this 227.CW mkfile 228must be modified to support a new architecture. 229.LP 230.SH 231Applications 232.LP 233Application programs process two forms of architecture-dependent 234information: executable images and intermediate object files. 235Almost all processing is on executable files. 236System library 237.CW libmach 238provides functions that convert 239architecture-specific data 240to a portable format so application programs 241can process this data independent of its 242underlying representation. 243Further, when a new architecture is implemented 244almost all code changes 245are confined to the library; 246most affected application programs need only be reloaded. 247The source code for the library is stored in 248.CW /sys/src/libmach . 249.LP 250An application program running on one type of 251processor must be able to interpret 252architecture-dependent information for all 253supported processors. 254For example, a debugger must be able to debug 255the executables of 256all architectures, not just the 257architecture on which it is executing, since 258.CW /proc 259may be imported from a different machine. 260.LP 261A small part of the application library 262provides functions to 263extract symbol references from object files. 264The remainder provides the following processing 265of executable files or memory images: 266.IP \(bu 267Header interpretation. 268.IP \(bu 269Symbol table interpretation. 270.IP \(bu 271Execution context interpretation, such as stack traces 272and stack frame location. 273.IP \(bu 274Instruction interpretation including disassembly and 275instruction size and follow-set calculations. 276.IP \(bu 277Exception and floating point number interpretation. 278.IP \(bu 279Architecture-independent read and write access through a 280relocation map. 281.LP 282Header file 283.CW /sys/include/mach.h 284defines the interfaces to the 285application library. Manual pages 286.I mach (2), 287.I symbol (2), 288and 289.I object (2) 290describe the details of the 291library functions. 292.LP 293Two data structures, called 294.CW Mach 295and 296.CW Machdata , 297contain architecture-dependent parameters and 298a jump table of functions. 299Global variables 300.CW mach 301and 302.CW machdata 303point to the 304.CW Mach 305and 306.CW Machdata 307data structures associated with the target architecture. 308An application determines the target architecture of 309a file or executable image, sets the global pointers 310to the data structures associated with that architecture, 311and subsequently performs all references indirectly through the 312pointers. 313As a result, direct references to the tables for each 314architecture are avoided and the application code intrinsically 315supports all architectures (though only one at a time). 316.LP 317Object file processing is handled similarly: architecture-dependent 318functions identify and 319decode the intermediate files for the processor. 320The application indirectly 321invokes a classification function to identify 322the architecture of the object code and to select the 323appropriate decoding function. Subsequent calls 324then use that function to decode each record. Again, 325the layer of indirection allows the application code 326to support all architectures without modification. 327.LP 328Splitting the architecture-dependent information 329between the 330.CW Mach 331and 332.CW Machdata 333data structures 334allows applications to choose 335an appropriate level of service. Even though an application 336does not directly reference the architecture-specific data structures, 337it must load the 338architecture-dependent tables and code 339for all architectures it supports. The size of this data 340can be substantial and many applications do not require 341the full range of architecture-dependent functionality. 342For example, the 343.CW size 344command does not require the disassemblers for every architecture; 345it only needs to decode the header. 346The 347.CW Mach 348data structure contains a few architecture-specific parameters 349and a description of the processor register set. 350The size of the structure 351varies with the size of the register 352set but is generally small. 353The 354.CW Machdata 355data structure contains 356a jump table of architecture-dependent functions; 357the amount of code and data referenced by this table 358is usually large. 359.SH 360Libmach Source Code Organization 361.LP 362The 363.CW libmach 364library provides four classes of functionality: 365.LP 366.IP "Header and Symbol Table Decoding\ -\ " 367Files 368.CW executable.c 369and 370.CW sym.c 371contain code to interpret the header and 372symbol tables of 373an executable file or executing image. 374Function 375.CW crackhdr 376decodes the header, 377reformats the 378information into an 379.CW Fhdr 380data structure, and points 381global variable 382.CW mach 383to the 384.CW Mach 385data structure of the target architecture. 386The symbol table processing 387uses the data in the 388.CW Fhdr 389structure to decode the symbol table. 390A variety of symbol table access functions then support 391queries on the reformatted table. 392.IP "Debugger Support\ -\ " 393Files named 394.CW \fIm\fP.c , 395where 396.I m 397is the code letter assigned to the architecture, 398contain the initialized 399.CW Mach 400data structure and the definition of the register 401set for each architecture. 402Architecture-specific debugger support functions and 403an initialized 404.CW Machdata 405structure are stored in 406files named 407.CW \fIm\fPdb.c . 408Files 409.CW machdata.c 410and 411.CW setmach.c 412contain debugger support functions shared 413by multiple architectures. 414.IP "Architecture-Independent Access\ -\ " 415Files 416.CW map.c , 417.CW access.c , 418and 419.CW swap.c 420provide accesses through a relocation map 421to data in an executable file or executing image. 422Byte-swapping is performed as needed. Global variables 423.CW mach 424and 425.CW machdata 426must point to the 427.CW Mach 428and 429.CW Machdata 430data structures of the target architecture. 431.IP "Object File Interpretation\ -\ " 432These files contain functions to identify the 433target architecture of an 434intermediate object file 435and extract references to symbols. File 436.CW obj.c 437contains code common to all architectures; 438file 439.CW \fIm\fPobj.c 440contains the architecture-specific source code 441for the machine with code character 442.I m . 443.LP 444The 445.CW Machdata 446data structure is primarily a jump 447table of architecture-dependent debugger support 448functions. Functions select the 449.CW Machdata 450structure for a target architecture based 451on the value of the 452.CW type 453code in the 454.CW Fhdr 455structure or the name of the architecture. 456The jump table provides functions to swap bytes, interpret 457machine instructions, 458perform stack 459traces, find stack frames, format floating point 460numbers, and decode machine exceptions. Some functions, such as 461machine exception decoding, are idiosyncratic and must be 462supplied for each architecture. Others depend 463on the compiler run-time model and several 464architectures may share code common to a model. For 465example, many architectures share the code to 466process the fixed-frame stack model implemented by 467several of the compilers. 468Finally, some 469functions, such as byte-swapping, provide a general capability and 470the jump table need only select an implementation appropriate 471to the architecture. 472.LP 473.SH 474Adding Application Support for a New Architecture 475.LP 476This section describes the 477steps required to add application-level 478support for a new architecture. 479We assume 480the kernel, compilers, loaders and system libraries 481for the new architecture are already in place. This 482implies that a code-character has been assigned and 483that the architecture-specific headers have been 484updated. 485With the exception of two programs, 486application-level changes are confined to header 487files and the source code in 488.CW /sys/src/libmach . 489.LP 490.IP 1. 491Begin by updating the application library 492header file in 493.CW /sys/include/mach.h . 494Add the following symbolic codes to the 495.CW enum 496statement near the beginning of the file: 497.RS 498.IP \(bu 499The processor type code, e.g., 500.CW MSPARC . 501.IP \(bu 502The type of the executable. There are usually 503two codes needed: one for a bootable 504executable (i.e., a kernel) and one for an 505application executable. 506.IP \(bu 507The disassembler type code. Add one entry for 508each supported disassembler for the architecture. 509.IP \(bu 510A symbolic code for the object file. 511.RE 512.LP 513.IP 2. 514In a file name 515.CW /sys/src/libmach/\fIm\fP.c 516(where 517.I m 518is the identifier character assigned to the architecture), 519initialize 520.CW Reglist 521and 522.CW Mach 523data structures with values defining 524the register set and various system parameters. 525The source file for a similar architecture 526can serve as template. 527Most of the fields of the 528.CW Mach 529data structure are obvious 530but a few require further explanation. 531.RS 532.IP "\f(CWkbase\fP\ -\ " 533This field 534contains the address of the kernel 535.CW ublock . 536The debuggers 537assume the first entry of the kernel 538.CW ublock 539points to the 540.CW Proc 541structure for a kernel thread. 542.IP "\f(CWktmask\fP\ -\ " 543This field 544is a bit mask used to calculate the kernel text address from 545the kernel 546.CW ublock 547address. 548The first page of the 549kernel text segment is calculated by 550ANDing 551the negation of this mask with 552.CW kbase . 553.IP "\f(CWkspoff\fP\ -\ " 554This field 555contains the byte offset in the 556.CW Proc 557data structure to the saved kernel 558stack pointer for a suspended kernel thread. This 559is the offset to the 560.CW sched.sp 561field of a 562.CW Proc 563table entry. 564.IP "\f(CWkpcoff\fP\ -\ " 565This field contains the byte offset into the 566.CW Proc 567data structure 568of 569the program counter of a suspended kernel thread. 570This is the offset to 571field 572.CW sched.pc 573in that structure. 574.IP "\f(CWkspdelta\fP and \f(CWkpcdelta\fP\ -\ " 575These fields 576contain corrections to be added to 577the stack pointer and program counter, respectively, 578to properly locate the stack and next 579instruction of a kernel thread. These 580values bias the saved registers retrieved 581from the 582.CW Label 583structure named 584.CW sched 585in the 586.CW Proc 587data structure. 588Most architectures require no bias 589and these fields contain zeros. 590.IP "\f(CWscalloff\fP\ -\ " 591This field 592contains the byte offset of the 593.CW scallnr 594field in the 595.CW ublock 596data structure associated with a process. 597The 598.CW scallnr 599field contains the number of the 600last system call executed by the process. 601The location of the field varies depending on 602the size of the floating point register set 603which precedes it in the 604.CW ublock . 605.RE 606.LP 607.IP 3. 608Add an entry to the initialization of the 609.CW ExecTable 610data structure at the beginning of file 611.CW /sys/src/libmach/executable.c . 612Most architectures 613require two entries: one for 614a normal executable and 615one for a bootable 616image. Each table entry contains: 617.RS 618.IP \(bu 619Magic Number\ \-\ 620The big-endian magic number assigned to the architecture in 621.CW /sys/include/a.out.h . 622.IP \(bu 623Name\ \-\ 624A string describing the executable. 625.IP \(bu 626Executable type code\ \-\ 627The executable code assigned in 628.CW /sys/include/mach.h . 629.IP \(bu 630\f(CWMach\fP pointer\ \-\ 631The address of the initialized 632.CW Mach 633data structure constructed in Step 2. 634You must also add the name of this table to the 635list of 636.CW Mach 637table definitions immediately preceding the 638.CW ExecTable 639initialization. 640.IP \(bu 641Header size\ \-\ 642The number of bytes in the executable file header. 643The size of a normal executable header is always 644.CW sizeof(Exec) . 645The size of a bootable header is 646determined by the size of the structure 647for the architecture defined in 648.CW /sys/include/bootexec.h . 649.IP \(bu 650Byte-swapping function\ \-\ 651The address of 652.CW beswal 653or 654.CW leswal 655for big-endian and little-endian 656architectures, respectively. 657.IP \(bu 658Decoder function\ -\ 659The address of a function to decode the header. 660Function 661.CW adotout 662decodes the common header shared by all normal 663(i.e., non-bootable) executable files. 664The header format of bootable 665executable files is defined by the manufacturer and 666a custom function is almost always 667required to decode it. 668Header file 669.CW /sys/include/bootexec.h 670contains data structures defining the bootable 671headers for all architectures. If the new architecture 672uses an existing format, the appropriate 673decoding function should already be in 674.CW executable.c . 675If the header format is unique, then 676a new function must be added to this file. 677Usually the decoding function for an existing 678architecture can be adopted with minor modifications. 679.RE 680.LP 681.IP 4. 682Write an object file parser and 683store it in file 684.CW /sys/src/libmach/\fIm\fPobj.c 685where 686.I m 687is the identifier character assigned to the architecture. 688Two functions are required: a predicate to identify an 689object file for the architecture and a function to extract 690symbol references from the object code. 691The object code format is obscure but 692it is often possible to adopt the 693code of an existing architecture 694with minor modifications. 695When these 696functions are in hand, insert their addresses 697in the jump table at the beginning of file 698.CW /sys/src/libmach/obj.c . 699.LP 700.IP 5. 701Implement the required debugger support functions and 702initialize the parameters and jump table of the 703.CW Machdata 704data structure for the architecture. 705This code is conventionally stored in 706a file named 707.CW /sys/src/libmach/\fIm\fPdb.c 708where 709.I m 710is the identifier character assigned to the architecture. 711The fields of the 712.CW Machdata 713structure are: 714.RS 715.IP "\f(CWbpinst\fP and \f(CWbpsize\fP\ -\ " 716These fields 717contain the breakpoint instruction and the size 718of the instruction, respectively. 719.IP "\f(CWswab\fP\ -\ " 720This field 721contains the address of a function to 722byte-swap a 16-bit value. Choose 723.CW leswab 724or 725.CW beswab 726for little-endian or big-endian architectures, respectively. 727.IP "\f(CWswal\fP\ -\ " 728This field 729contains the address of a function to 730byte-swap a 32-bit value. Choose 731.CW leswal 732or 733.CW beswal 734for little-endian or big-endian architectures, respectively. 735.IP "\f(CWctrace\fP\ -\ " 736This field 737contains the address of a function to perform a 738C-language stack trace. Two general trace functions, 739.CW risctrace 740and 741.CW cisctrace , 742traverse fixed-frame and relative-frame stacks, 743respectively. If the compiler for the 744new architecture conforms to one of 745these models, select the appropriate function. If the 746stack model is unique, 747supply a custom stack trace function. 748.IP "\f(CWfindframe\fP\ -\ " 749This field 750contains the address of a function to locate the stack 751frame associated with a text address. 752Generic functions 753.CW riscframe 754and 755.CW ciscframe 756process fixed-frame and relative-frame stack 757models. 758.IP "\f(CWufixup\fP\ -\ " 759This field 760contains the address of a function to adjust 761the base address of the register save area. 762Currently, only the 76368020 requires this bias 764to offset over the active 765exception frame. 766.IP "\f(CWexcep\fP\ -\ " 767This field 768contains the address of a function to produce a 769text 770string describing the 771current exception. 772Each architecture stores exception 773information uniquely, so this code must always be supplied. 774.IP "\f(CWbpfix\fP\ -\ " 775This field 776contains the address of a function to adjust an 777address prior to laying down a breakpoint. 778.IP "\f(CWsftos\fP\ -\ " 779This field 780contains the address of a function to convert a single 781precision floating point value 782to a string. Choose 783.CW leieeesftos 784for little-endian 785or 786.CW beieeesftos 787for big-endian architectures. 788.IP "\f(CWdftos\fP\ -\ " 789This field 790contains the address of a function to convert a double 791precision floating point value 792to a string. Choose 793.CW leieeedftos 794for little-endian 795or 796.CW beieeedftos 797for big-endian architectures. 798.IP "\f(CWfoll\fP, \f(CWdas\fP, \f(CWhexinst\fP, and \f(CWinstsize\fP\ -\ " 799These fields point to functions that interpret machine 800instructions. 801They rely on disassembly of the instruction 802and are unique to each architecture. 803.CW Foll 804calculates the follow set of an instruction. 805.CW Das 806disassembles a machine instruction to assembly language. 807.CW Hexinst 808formats a machine instruction as a text 809string of 810hexadecimal digits. 811.CW Instsize 812calculates the size in bytes, of an instruction. 813Once the disassembler is written, the other functions 814can usually be implemented as trivial extensions of it. 815.LP 816It is possible to provide support for a new architecture 817incrementally by filling the jump table entries 818of the 819.CW Machdata 820structure as code is written. In general, if 821a jump table entry contains a zero, application 822programs requiring that function will issue an 823error message instead of attempting to 824call the function. For example, 825the 826.CW foll , 827.CW das , 828.CW hexinst , 829and 830.CW instsize 831jump table slots can be zeroed until a 832disassembler is written. 833Other capabilities, such as 834stack trace or variable inspection, 835can be supplied and will be available to 836the debuggers but attempts to use the 837disassembler will result in an error message. 838.RE 839.IP 6. 840Update the table named 841.CW machines 842near the beginning of 843.CW /sys/src/libmach/setmach.c . 844This table binds the 845file type code and machine name to the 846.CW Mach 847and 848.CW Machdata 849structures of an architecture. 850The names of the initialized 851.CW Mach 852and 853.CW Machdata 854structures built in steps 2 and 5 855must be added to the list of 856structure definitions immediately 857preceding the table initialization. 858If both Plan 9 and 859native disassembly are supported, add 860an entry for each disassembler to the table. The 861entry for the default disassembler (usually 862Plan 9) must be first. 863.IP 7. 864Add an entry describing the architecture to 865the table named 866.CW trans 867near the end of 868.CW /sys/src/cmd/prof.c . 869.RE 870.IP 8. 871Add an entry describing the architecture to 872the table named 873.CW objtype 874near the start of 875.CW /sys/src/cmd/pcc.c . 876.RE 877.IP 9. 878Recompile and install 879all application programs that include header file 880.CW mach.h 881and load with 882.CW libmach.a . 883