Changeset 623 for trunk/boot/tsar_mips32/boot.c
- Timestamp:
- Mar 6, 2019, 4:37:15 PM (5 years ago)
- File:
-
- 1 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" );
Note: See TracChangeset
for help on using the changeset viewer.