Changeset 623 for trunk/boot/tsar_mips32
- Timestamp:
- Mar 6, 2019, 4:37:15 PM (6 years ago)
- Location:
- trunk/boot/tsar_mips32
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/boot/tsar_mips32/boot.c
r578 r623 3 3 * 4 4 * Authors : Vu Son (2016) 5 * Alain Greiner (2016, 2017,2018)5 * Alain Greiner (2016,2017,2018,2019) 6 6 * 7 7 * Copyright (c) UPMC Sorbonne Universites … … 26 26 * This file contains the ALMOS-MKH. boot-loader for the TSAR architecture. * 27 27 * * 28 * It supports clusterised shared memory multi-processor architectures,*28 * It supports a clusterised, shared memory, multi-processor architecture, * 29 29 * where each processor core is identified by a composite index [cxy,lid] * 30 30 * with one physical memory bank per cluster. * 31 31 * * 32 32 * The 'boot.elf' file (containing the boot-loader binary code) is stored * 33 * on disk and is loaded into memory by core[0,0] (cxy = 0 / lid = 0),*34 * and is copied in each other cluter by the local CP0 (lid = 0].*33 * on disk (not in the FAT file system), and must be loaded into memory by * 34 * the preloader running on the core[0][0] (cxy = 0 / lid = 0). * 35 35 * * 36 * 1) The boot-loader first phase is executed by core[0,0], while * 37 * all other cores are waiting in the preloader. * 38 * It does the following tasks: * 39 * - load into the memory bank of cluster 0 the 'arch_info.bin' * 40 * file (containing the hardware architecture description) and the * 41 * 'kernel.elf' file, at temporary locations, * 42 * - initializes the 'boot_info_t' structure in cluster(0,0) * 43 * (there is 1 'boot_info_t' per cluster), which contains both * 44 * global and cluster specific information that will be used for * 45 * kernel initialisation. * 46 * - activate CP0s in all other clusters, using IPIs. * 47 * - wait completion reports from CP0s on a global barrier. * 36 * The main task of the boot-loader is to load in the first physical page * 37 * of each cluster a copy of the kernel code (segments "kcode" and "kdata") * 38 * and to build - in each cluster - a cluster specific description of the * 39 * hardware archtecture, stored in the "kdata" segment as the boot_info_t * 40 * structure. The "kernel.elf" and "arch_info.bin" files are supposed to be * 41 * stored on disk in a FAT32 file system. * 48 42 * * 49 * 2) The boot-loader second phase is then executed in parallel by all * 50 * CP0s (other than core[0,0]). Each CP0 performs the following tasks: * 51 * - copies into the memory bank of the local cluster the 'boot.elf', * 52 * the 'arch_info.bin' (at the same addresses as the 'boot.elf' and * 53 * the 'arch_info.bin' in the memory bank of the cluster(0,0), and * 54 * the kernel image (at address 0x0), * 55 * - initializes the 'boot_info_t' structure of the local cluster, * 56 * - activate all other cores in the same cluster (CPi). * 57 * - wait local CPi completion reports on a local barrier. * 58 * - report completion on the global barrier. * 43 * All cores contribute to the boot procedure, but all cores are not * 44 * simultaneously active: * 45 * - in a first phase, only core[0][0] is running (core 0 in cluster 0). * 46 * - in a second phase, only core[cxy][0] is running in each cluster. * 47 * - in last phase, all core[cxy][lid] are running. * 59 48 * * 60 * 3) The boot-loader third phase is executed in parallel by all cores. * 61 * In each cluster (i) the CP0 * 62 * - activates the other cores of cluster(i), * 63 * - blocks on the local barrier waiting for all local CPi to report * 64 * completion on the local barrier, * 65 * - moves the local kernel image from the temporary location to the * 66 * address 0x0, (erasing the preloader code). * 49 * Finally, all cores jump to the kernel_init() function that makes the * 50 * actual kernel initialisation. * 67 51 * * 68 * 4) All cores jump to kern_init() (maybe not at the same time). * 52 * Implementation note: * * * 53 * To allows each core to use the local copy of both the boot code and the * 54 * kernel code, the boot-loader builds a minimal and temporary BPT (Boot * 55 * Page Table) containing only two big pages: page[0] maps the kernel code, * 56 * and page 1 maps the boot code. * 69 57 ****************************************************************************/ 70 58 … … 96 84 ****************************************************************************/ 97 85 86 // the Boot Page Table contains two PTE1, and should be aligned on 8 Kbytes 87 88 uint32_t boot_pt[2] __attribute__((aligned(2048))); 89 98 90 // synchronization variables. 99 91 100 volatile boot_remote_spinlock_t tty0_lock; // protect TTY0 access101 volatile boot_remote_barrier_t global_barrier; // synchronize CP0 cores102 volatile boot_remote_barrier_t local_barrier; // synchronize cores in one cluster103 uint32_t active_c p0s_nr; // number of expected CP0s92 volatile boot_remote_spinlock_t tty0_lock; // protect TTY0 access 93 volatile boot_remote_barrier_t global_barrier; // synchronize CP0 cores 94 volatile boot_remote_barrier_t local_barrier; // synchronize cores in one cluster 95 uint32_t active_cores_nr; // number of expected CP0s 104 96 105 97 // kernel segments layout variables … … 114 106 uint32_t kernel_entry; // kernel entry point 115 107 116 // Functions called by boot_entry.S108 // Functions 117 109 118 110 extern void boot_entry( void ); // boot_loader entry point … … 738 730 739 731 /********************************************************************************* 740 * This function is called by all CP0 to activate the other CPi cores.732 * This function is called by all CP0s to activate the other CPi cores. 741 733 * @ boot_info : pointer to local 'boot_info_t' structure. 742 734 *********************************************************************************/ … … 761 753 } // boot_wake_local_cores() 762 754 755 /********************************************************************************* 756 * This function is called by all core[cxy][0] to initialize the Boot Page Table: 757 * map two local big pages for the boot code and kernel code. 758 * @ cxy : local cluster identifier. 759 *********************************************************************************/ 760 void boot_page_table_init( cxy_t cxy ) 761 { 762 // set PTE1 in slot[0] for kernel code 763 uint32_t kernel_attr = 0x8A800000; // flagss : V,C,X,G 764 uint32_t kernel_ppn1 = (cxy << 20) >> 9; // big physical page index == 0 765 boot_pt[0] = kernel_attr | kernel_ppn1; 766 767 // set PTE1 in slot[1] for boot code (no global flag) 768 uint32_t boot_attr = 0x8A000000; // flags : V,C,X 769 uint32_t boot_ppn1 = ((cxy << 20) + 512) >> 9; // big physical page index == 1 770 boot_pt[1] = boot_attr | boot_ppn1; 771 } 772 773 /********************************************************************************* 774 * This function is called by all cores to activate the instruction MMU, 775 * and use the local copy of boot code. 776 *********************************************************************************/ 777 void boot_activate_ins_mmu( cxy_t cxy ) 778 { 779 // set mmu_ptpr register 780 uint32_t ptpr = ((uint32_t)boot_pt >> 13) | (cxy << 19); 781 asm volatile ( "mtc2 %0, $0 \n" : : "r" (ptpr) ); 782 783 // set ITLB bit in mmu_mode 784 asm volatile ( "mfc2 $26, $1 \n" 785 "ori $26, $26, 0x8 \n" 786 "mtc2 $26, $1 \n" ); 787 } 763 788 764 789 /********************************************************************************* … … 776 801 if (lid == 0) 777 802 { 778 /************************************ ****************779 * PHASE A : only CP0 in boot clusterexecutes it780 *************************************************** /781 if (cxy == BOOT_CORE_CXY)803 /************************************i********************** 804 * PHASE Sequencial : only core[0][0] executes it 805 **********************************************************/ 806 if (cxy == 0) 782 807 { 783 808 boot_printf("\n[BOOT] core[%x,%d] enters at cycle %d\n", … … 833 858 boot_check_core(boot_info, lid); 834 859 835 // Activate other CP0s / get number of active CP0s 836 active_cp0s_nr = boot_wake_all_cp0s() + 1; 860 // TO BE DONE 861 // core[0][0] identity maps two big pages for the boot and kernel code, 862 // boot_page_table_init( 0 ); 863 864 // TO BE DONE 865 // core[0][0] activates the instruction MMU to use the local copy of boot code 866 // boot_activate_ins_mmu( 0 ); 867 868 // Activate other core[cxy][0] / get number of activated cores 869 active_cores_nr = boot_wake_all_cp0s() + 1; 837 870 838 871 // Wait until all clusters (i.e all CP0s) ready to enter kernel. 839 872 boot_remote_barrier( XPTR( BOOT_CORE_CXY , &global_barrier ) , 840 active_c p0s_nr );873 active_cores_nr ); 841 874 842 875 // activate other local cores 843 876 boot_wake_local_cores( boot_info ); 844 845 // display address extensions846 // uint32_t cp2_data_ext;847 // uint32_t cp2_ins_ext;848 // asm volatile( "mfc2 %0, $24" : "=&r" (cp2_data_ext) );849 // asm volatile( "mfc2 %0, $25" : "=&r" (cp2_ins_ext) );850 // boot_printf("\n[BOOT] core[%x,%d] CP2_DATA_EXT = %x / CP2_INS_EXT = %x\n",851 // cxy , lid , cp2_data_ext , cp2_ins_ext );852 877 853 878 // Wait until all local cores in cluster ready … … 855 880 boot_info->cores_nr ); 856 881 } 857 /****************************************************************** 858 * PHASE B : all CP0s other than CP0 in boot clusterexecute it859 ***************************************************************** /882 /************************************************************************** 883 * PHASE partially parallel : all core[cxy][0] with (cxy != 0) execute it 884 **************************************************************************/ 860 885 else 861 886 { 862 // at this point, all INSTRUCTION address extension registers 863 // point on cluster(0,0), but the DATA extension registers point 864 // already on the local cluster to use the local stack. 865 // To access the bootloader global variables we must first copy 866 // the boot code (data and instructions) in the local cluster. 887 // at this point, the DATA extension registers point 888 // already on the local cluster cxy to use the local stack, 889 // but all cores must access the code stored in cluster 0 890 891 // Each CP0 copies the boot code (data and instructions) 892 // from the cluster 0 to the local cluster. 867 893 boot_remote_memcpy( XPTR( cxy , BOOT_BASE ), 868 894 XPTR( BOOT_CORE_CXY , BOOT_BASE ), 869 895 BOOT_MAX_SIZE ); 870 896 871 // from now, it is safe to refer to the boot codeglobal variables897 // from now, it is safe to refer to the boot global variables 872 898 boot_printf("\n[BOOT] core[%x,%d] replicated boot code at cycle %d\n", 873 899 cxy , lid , boot_get_proctime() ); 874 900 875 // switch to the INSTRUCTION local memory space, to avoid contention. 876 // asm volatile("mtc2 %0, $25" :: "r"(cxy)); 877 878 // Copy the arch_info.bin file into the local memory. 901 // TO BE DONE 902 // Each core identity maps two big pages for the boot and kernel code, 903 // boot_page_table_init( cxy ); 904 905 // Each core activates the instruction MMU to use the local copy of boot code 906 // boot_activate_ins_mmu( cxy ); 907 908 // Each CP0 copies the arch_info.bin into the local memory. 879 909 boot_remote_memcpy(XPTR(cxy, ARCHINFO_BASE), 880 910 XPTR(BOOT_CORE_CXY, ARCHINFO_BASE), … … 884 914 cxy , lid , boot_get_proctime() ); 885 915 886 // Copythe kcode segment into local memory916 // Each CP0 copies the kcode segment into local memory 887 917 boot_remote_memcpy( XPTR( cxy , seg_kcode_base ), 888 918 XPTR( BOOT_CORE_CXY , seg_kcode_base ), 889 919 seg_kcode_size ); 890 920 891 // Copythe kdata segment into local memory921 // Each CP0 copies the kdata segment into local memory 892 922 boot_remote_memcpy( XPTR( cxy , seg_kdata_base ), 893 923 XPTR( BOOT_CORE_CXY , seg_kdata_base ), 894 924 seg_kdata_size ); 895 925 896 // Copy the kentry segment into local memory 926 // [TO BE REMOVED<D-°> 927 // Each CP0 copies the kentry segment into local memory 897 928 boot_remote_memcpy( XPTR( cxy , seg_kentry_base ), 898 929 XPTR( BOOT_CORE_CXY , seg_kentry_base ), … … 902 933 cxy , lid , boot_get_proctime() ); 903 934 904 // Get local boot_info_t structure base address.935 // Each CP0 get local boot_info_t structure base address. 905 936 boot_info = (boot_info_t*)seg_kdata_base; 906 937 907 // Initializelocal boot_info_t structure.938 // Each CP0 initializes local boot_info_t structure. 908 939 boot_info_init( boot_info , cxy ); 909 940 … … 911 942 cxy , lid , boot_get_proctime() ); 912 943 913 // Checkcore information.944 // Each CP0 checks core information. 914 945 boot_check_core( boot_info , lid ); 915 946 916 // get number of active clusters from BOOT_CORE cluster917 uint32_t count = boot_remote_lw( XPTR( BOOT_CORE_CXY , &active_cp0s_nr ) );918 919 // Wait until all clusters (i.e all CP0s) ready to enter kernel947 // Each CP0 get number of active clusters from BOOT_CORE cluster 948 uint32_t count = boot_remote_lw( XPTR( 0 , &active_cores_nr ) ); 949 950 // Wait until all clusters (i.e all CP0s) ready 920 951 boot_remote_barrier( XPTR( BOOT_CORE_CXY , &global_barrier ) , count ); 921 952 922 953 // activate other local cores 923 954 boot_wake_local_cores( boot_info ); 924 925 // display address extensions926 // uint32_t cp2_data_ext;927 // uint32_t cp2_ins_ext;928 // asm volatile( "mfc2 %0, $24" : "=&r" (cp2_data_ext) );929 // asm volatile( "mfc2 %0, $25" : "=&r" (cp2_ins_ext) );930 // boot_printf("\n[BOOT] core[%x,%d] CP2_DATA_EXT = %x / CP2_INS_EXT = %x\n",931 // cxy , lid , cp2_data_ext , cp2_ins_ext );932 955 933 956 // Wait until all local cores in cluster ready … … 938 961 else 939 962 { 940 /*************************************************************** 941 * PHASE C: all non CP0 cores in all clustersexecute it942 ************************************************************** /943 944 // Switch to the INSTRUCTIONS local memory space 945 // to avoid contention at the boot cluster. 946 asm volatile("mtc2 %0, $25" :: "r"(cxy));963 /*********************************************************************** 964 * PHASE fully parallel : all cores[cxy][lid] with (lid! = 0) execute it 965 **********************************************************************/ 966 967 // TO BE DONE 968 // each core activate the instruction MMU to use the local copy of the boot code 969 // boot_activate_ins_mmu( cxy ); 947 970 948 971 // Get local boot_info_t structure base address. … … 952 975 boot_check_core(boot_info, lid); 953 976 954 // display address extensions955 // uint32_t cp2_data_ext;956 // uint32_t cp2_ins_ext;957 // asm volatile( "mfc2 %0, $24" : "=&r" (cp2_data_ext) );958 // asm volatile( "mfc2 %0, $25" : "=&r" (cp2_ins_ext) );959 // boot_printf("\n[BOOT] core[%x,%d] CP2_DATA_EXT = %x / CP2_INS_EXT = %x\n",960 // cxy , lid , cp2_data_ext , cp2_ins_ext );961 962 977 // Wait until all local cores in cluster ready 963 978 boot_remote_barrier( XPTR( cxy , &local_barrier ) , boot_info->cores_nr ); 964 979 } 965 980 981 // the "kernel_entry" global variable, set by boot_kernel_load() define 982 // the adress of the kernel_init() function. 966 983 // Each core initialise the following registers before jumping to kernel: 967 // - sp_29 : stack pointer on idle thread, 968 // - c0_sr : reset BEV bit 969 // - a0_04 : pointer on boot_info structure 970 // - c0_ebase : kentry_base(and jump to kernel_entry. 971 984 // - gr_29 : stack pointer / kernel stack allocated in idle thread descriptor, 985 // - c0_sr : status register / reset BEV bit 986 // - gr_04 : kernel_init() argument / pointer on boot_info structure 987 // - c0_ebase : kentry_base 988 989 // compute "sp" from base address of idle thread descriptors array and lid. 972 990 // The array of idle-thread descriptors is allocated in the kdata segment, 973 // just after the boot_info structure 974 uint32_t sp; 991 // just after the boot_info structure. 975 992 uint32_t base; 976 993 uint32_t offset = sizeof( boot_info_t ); 977 994 uint32_t pmask = CONFIG_PPM_PAGE_MASK; 978 995 uint32_t psize = CONFIG_PPM_PAGE_SIZE; 979 980 // compute base address of idle thread descriptors array981 996 if( offset & pmask ) base = seg_kdata_base + (offset & ~pmask) + psize; 982 997 else base = seg_kdata_base + offset; 983 984 // compute stack pointer 985 sp = base + ((lid + 1) * CONFIG_THREAD_DESC_SIZE) - 16; 998 uint32_t sp = base + ((lid + 1) * CONFIG_THREAD_DESC_SIZE) - 16; 999 1000 // get "ebase" from kerneL_info 1001 uint32_t ebase = boot_info->kentry_base; 1002 1003 // TO BE DONE 1004 // The cp0_ebase will not be set by the assenbly code below 1005 // when the kentry segment will be removed => done in kernel init 986 1006 987 1007 asm volatile( "mfc0 $27, $12 \n" … … 997 1017 : "r"(boot_info) , 998 1018 "r"(sp) , 999 "r"( boot_info->kentry_base) ,1019 "r"(ebase) , 1000 1020 "r"(kernel_entry) 1001 1021 : "$26" , "$27" , "$29" , "$4" ); -
trunk/boot/tsar_mips32/boot_entry.S
r439 r623 23 23 24 24 /********************************************************************************************** 25 * This file contains the entry point of the ALMOS-MK boot-loader for TSAR architecture .*26 * It supports a generic multi-clusters / multi-processors architecture*25 * This file contains the entry point of the ALMOS-MK boot-loader for TSAR architecture, * 26 * that is a generic multi-clusters / multi-processors architecture. * 27 27 * * 28 28 * - The number of clusters is defined by the (X_SIZE, Y_SIZE) parameters in the * … … 31 31 * hard_config.h file (up to 4 processors per cluster). * 32 32 * * 33 * This assembly code is executed by all cores. It has 2 versions (in order to see if the * 34 * contention created by the ARCHINFO core descriptor table scanning loops is acceptable): * 35 * with or without the assumption that the core hardware identifier gid has a fixed format: * 33 * This assembly code is executed by all cores, but at the same time, because all cores * 34 * are not simultaneously activated. It makes the assuption that the CPO register containing * 35 * the core gid (global hardware identifier) has a fixed format: * 36 * gid == (((x << Y_WIDTH) + y) << P_WIDTH) + lid * 36 37 * * 37 * - Version with fixed format: gid == (((x << Y_WIDTH) + y) << PADDR_WIDTH) + lid * 38 * It does 3 things: * 39 * + It initializes the stack pointer depending on the lid extracted from the gid, * 40 * using the BOOT_STACK_BASE and BOOT_STACK_SIZE parameters defined in the * 41 * 'boot_config.h' file, * 42 * + It changes the value of the address extension registers using the cxy extracted * 43 * from the gid, * 44 * + It jumps to the boot_loader() function defined in the 'boot.c' file and passes 2 * 45 * arguments which are the cxy and lid of each core to this function. * 46 * * 47 * - Version without fixed format * 48 * It has to perform an additional step in order to extract the (cxy,lid) values from the * 49 * arch_info.bin structure that has been loaded in the cluster (0,0) memory by the bscpu. * 50 * + Each core other than the bscpu scans the core descriptor table in the arch_info.bin * 51 * structure to make an associative search on the (gid), and get the (cxy,lid). * 52 * + It initializes the stack pointer depending on the lid, using the BOOT_STACK_BASE * 53 * and BOOT_STACK_SIZE parameters defined in the 'boot_config.h' file, * 54 * + It changes the value of the address extension registers using cxy obtained * 55 * previously, * 56 * + It jumps to the boot_loader() function defined in the 'boot.c' file and passes 2 * 57 * arguments which are the cxy and lid of each core to this function. * 38 * It does 3 things: * 39 * - It initializes the stack pointer depending on the lid extracted from the gid, * 40 * using the BOOT_STACK_BASE and BOOT_STACK_SIZE parameters defined in the * 41 * 'boot_config.h' file, * 42 * - It changes the value of the DATA address extension register using the cxy extracted * 43 * from the gid, * 44 * - It jumps to the boot_loader() function defined in the 'boot.c' file, passing the two * 45 * arguments (cxy and lid). * 58 46 *********************************************************************************************/ 59 47 … … 72 60 boot_entry: 73 61 74 #if USE_FIXED_FORMAT 75 76 /************* 77 * VERSION 1 * 78 *************/ 79 80 /* 81 * Get (cxy, lid) values from gid contained in coprocessor0 register. 82 */ 62 /* Get (cxy, lid) values from gid contained in CP0 register */ 83 63 84 64 mfc0 k0, CP0_PROCID … … 87 67 srl t2, k0, P_WIDTH /* t2 <= cxy */ 88 68 89 /* Initialize stack pointer from previously retrievedlid value */69 /* Initialize stack pointer from lid value */ 90 70 91 71 la t0, BOOT_STACK_BASE /* t0 <= BOOT_STACK_BASE */ … … 93 73 multu k1, t1 94 74 mflo k0 /* k0 <= BOOT_STACK_SIZE * lid */ 95 subu sp, t0, k0 /* P[cxy,lid] s tack top initialized*/75 subu sp, t0, k0 /* P[cxy,lid] sp initialized */ 96 76 97 /* Switch to local DSPACE by changing the value of the address extension register s*/77 /* Switch to local DSPACE by changing the value of the address extension register */ 98 78 99 79 mtc2 t2, CP2_DATA_PADDR_EXT 100 80 101 /* Jump to boot_loader() function after passing 2 arguments in the registers*/81 /* Jump to boot_loader() function after passing (cxy,lid) arguments in the registers */ 102 82 103 83 or a0, zero, t1 /* a0 <= lid */ … … 107 87 nop 108 88 109 #else110 111 /*************112 * VERSION 2 *113 *************/114 115 /* Test if this is bscpu */116 117 mfc0 k0, CP0_PROCID118 andi k0, k0, 0xFFF /* k0 <= gid */119 120 li t1, BOOT_CORE_GID /* t1 <= bscpu gid */121 or t3, zero, zero /* t3 <= bscpu lid = 0 */122 beq k0, t1, bscpu_exit /* if bscpu, skip scanning core tbl */123 li t4, BOOT_CORE_CXY /* t4 <= bscpu cxy */124 125 /* Get base address of the core descriptor table in 'arch_info.bin' file */126 127 la t0, ARCHINFO_BASE /* t0 <= ARCHINFO_BASE */128 li t1, 0x80 /* t1 <= ARCHINFO_HEADER_SIZE */129 addu t2, t0, t1 /* t2 <= ARCHINFO_CORE_BASE */130 131 /* scan the core descriptor table if this is not bscpu. TODO If not found? */132 133 li t3, 0x8 /* t3 <= ARCHINFO_CORE_SIZE */134 135 scanning_core_table:136 lw t1, 0(t2) /* t1 <= archinfo_core.gid */137 bne t1, k0, scanning_core_table /* if (t1 != k0) => loop */138 addu t2, t2, t3 /* t2 <= @ next archinfo_core */139 140 /* Get (cxy, lid) values from the found core descriptor */141 142 lw t3, -8(t2) /* t3 <= lid */143 lw t4, -4(t2) /* t4 <= cxy */144 145 /* Initialize stack pointer from previously retrieved lid value */146 147 bscpu_exit:148 la t0, BOOT_STACK_BASE /* t0 <= BOOT_STACK_BASE */149 li k1, BOOT_STACK_SIZE /* k1 <= BOOT_STACK_SIZE */150 multu k1, t3151 mflo k0 /* k0 <= BOOT_STACK_SIZE * lid */152 subu sp, t0, k0 /* P[cxy,lid] stack top initialized */153 154 /* Switch to local DSPACE by changing the value of the address extension registers */155 156 mtc2 t4, CP2_DATA_PADDR_EXT157 158 /* Jumping to boot_loader() function after passing 2 arguments in registers */159 160 or a0, zero, t3 /* a0 <= lid */161 or a1, zero, t4 /* a1 <= cxy */162 la ra, boot_loader163 jr ra164 nop165 166 #endif167 168 89 .end boot_entry 169 90
Note: See TracChangeset
for help on using the changeset viewer.