- Timestamp:
- Aug 7, 2012, 6:37:49 PM (12 years ago)
- Location:
- soft/giet_vm
- Files:
-
- 15 added
- 3 deleted
- 31 edited
Legend:
- Unmodified
- Added
- Removed
-
soft/giet_vm/Makefile
r178 r189 5 5 DU=mipsel-unknown-elf-objdump 6 6 7 #current directory absolute path 8 SOFT_PATH = $(shell pwd)/ 7 SYS_OBJS = build/sys/vm_handler.o \ 8 build/sys/sys_handler.o \ 9 build/sys/giet.o \ 10 build/sys/switch.o \ 11 build/sys/common.o \ 12 build/sys/ctx_handler.o \ 13 build/sys/drivers.o \ 14 build/sys/exc_handler.o \ 15 build/sys/irq_handler.o \ 16 build/sys/kernel_init.o 9 17 10 SYS_DIR = sys 11 LIB_DIR = libs 12 BOOT_DIR = boot 18 BOOT_OBJS = build/boot/reset.o \ 19 build/boot/boot_init.o 13 20 14 BOOT_PATH = $(SOFT_PATH)$(BOOT_DIR) 15 SYS_PATH = $(SOFT_PATH)$(SYS_DIR) 16 LIB_PATH = $(SOFT_PATH)$(LIB_DIR) 17 XML_PATH = $(SOFT_PATH)xml/ 18 MEMO_PATH = $(SOFT_PATH)memo/ 19 BUILD_PATH = $(SOFT_PATH)build/ 20 ELF_PATH = $(SOFT_PATH)build/ 21 APP_PATH = $(SOFT_PATH)apps/ 21 DISPLAY_OBJS = build/display/main.o \ 22 build/libs/stdio.o \ 23 build/libs/utils.o 22 24 23 #list of all applications directory 24 APP_DIRS = $(shell ls -d $(APP_PATH)/*/ ) 25 ROUTER_OBJS = build/router/main.o \ 26 build/libs/mwmr_channel.o \ 27 build/libs/stdio.o \ 28 build/libs/utils.o 25 29 26 SYS_OBJS_LIST = \ 27 vm_handler.o \ 28 sys_handler.o \ 29 giet.o \ 30 switch.o \ 31 common.o \ 32 ctx_handler.o \ 33 drivers.o \ 34 exc_handler.o \ 35 irq_handler.o \ 36 kernel_init.o 30 HELLO_OBJS = build/hello/main.o \ 31 build/libs/stdio.o \ 32 build/libs/utils.o 37 33 38 BOOT_OBJS_LIST = reset.o \ 39 boot_handler.o 40 41 #LIB_SRCS = $(wildcard $(LIB_DIR)/*.c) 42 LIB_OBJS_LIST = stdio.o \ 43 mwmr_channel.o \ 44 barrier.o \ 45 spin_lock.o 46 47 LIB_OBJS = $(patsubst %,$(LIB_DIR)/%,$(LIB_OBJS_LIST)) 48 SYS_OBJS = $(patsubst %,$(SYS_DIR)/%,$(SYS_OBJS_LIST)) 49 BOOT_OBJS = $(patsubst %,$(BOOT_DIR)/%,$(BOOT_OBJS_LIST)) 50 34 PGCD_OBJS = build/pgcd/main.o \ 35 build/libs/stdio.o \ 36 build/libs/utils.o 51 37 52 38 CFLAGS=-Wall -ffreestanding -mno-gpopt -mips32 -g 53 39 54 SYS_INCLUDE = -I$(SYS_PATH) -I$(XML_PATH) -I$(LIB_PATH) -I. 55 BOOT_INCLUDE = -I$(BOOT_PATH) -I$(XML_PATH) -I$(LIB_PATH) -I. 56 LIB_INCLUDE = -I$(LIB_PATH) -I$(XML_PATH) -I. 57 APP_INCLUDE = -I$(LIB_PATH) -I$(XML_PATH) -I$(SOFT_PATH) 40 INCLUDE = -Iboot -Isys -Ixml -Ilibs -I. 58 41 59 42 TRASH= /dev/null||true 60 43 61 .PHONY: apps prepare 62 63 all: prepare soft.elf 44 all: soft.elf 64 45 65 ## merge all *.elf to soft.elf 66 soft.elf: boot.elf sys.elf map.bin apps 67 $(MAKE) -C $(MEMO_PATH) 68 $(MEMO_PATH)/memo.x map.bin 69 $(DU) -D $@ > $(BUILD_PATH)$@.txt 70 71 ## prepare the environement 72 prepare: 73 @mkdir $(BUILD_PATH) 2>$(TRASH) 74 @mkdir $(ELF_PATH) 2>$(TRASH) 75 @mkdir $(BUILD_PATH)/$(BOOT_DIR) 2>$(TRASH) 76 @mkdir $(BUILD_PATH)/$(LIB_DIR) 2>$(TRASH) 77 @mkdir $(BUILD_PATH)/$(SYS_DIR) 2>$(TRASH) 46 ## merge all *.elf and map.bin to soft.elf 47 soft.elf: build/boot/boot.elf \ 48 build/sys/sys.elf \ 49 build/display/display.elf \ 50 build/router/router.elf \ 51 build/pgcd/pgcd.elf \ 52 build/hello/hello.elf \ 53 map.bin 54 $(MAKE) -C memo 55 memo/memo.x map.bin 56 $(DU) -D $@ > build$@.txt 78 57 79 58 ### mapping compilation 80 59 map.bin: map.xml 81 $(MAKE) -C $(XML_PATH)82 $(XML_PATH)/xml2bin $(SOFT_PATH)map.xml $(SOFT_PATH)map.bin60 $(MAKE) -C xml 61 xml/xml2bin map.xml map.bin 83 62 84 63 ### system compilation 85 sys.elf: $(SYS_OBJS) $(SYS_PATH)/sys.ld86 (cd $(BUILD_PATH); $(LD) -o $@ -T $(SYS_PATH)/sys.ld $(SYS_OBJS))87 (cd $(BUILD_PATH); $(DU) -D $@ > $@.txt)64 build/sys/sys.elf: $(SYS_OBJS) sys/sys.ld 65 $(LD) -o $@ -T sys/sys.ld $(SYS_OBJS) 66 $(DU) -D $@ > $@.txt 88 67 89 $(SYS_DIR)/%.o: $(SYS_DIR)/%.c90 $(CC) $( SYS_INCLUDE) $(CFLAGS) -c -o $(BUILD_PATH)/$@ $<68 build/sys/%.o: sys/%.c 69 $(CC) $(INCLUDE) $(CFLAGS) -c -o $@ $< 91 70 92 $(SYS_DIR)/%.o: $(SYS_DIR)/%.s 93 $(CC) $(SYS_INCLUDE) $(CFLAGS) -c -o $(BUILD_PATH)/$@ $< 94 95 $(SYS_DIR)/%.o: $(SYS_DIR)/%.S 96 $(CC) $(SYS_INCLUDE) $(CFLAGS) -c -o $(BUILD_PATH)/$@ $< 71 build/sys/%.o: sys/%.s 72 $(CC) $(INCLUDE) $(CFLAGS) -c -o $@ $< 97 73 98 74 ### boot compilation 99 b oot.elf: $(BOOT_OBJS) $(BOOT_PATH)/boot.ld100 (cd $(BUILD_PATH); $(LD) -o $@ -T $(BOOT_PATH)/boot.ld $(BOOT_OBJS))101 (cd $(BUILD_PATH); $(DU) -D $@ > $@.txt)75 build/boot/boot.elf: $(BOOT_OBJS) boot/boot.ld 76 $(LD) -o $@ -T boot/boot.ld $(BOOT_OBJS) 77 $(DU) -D $@ > $@.txt 102 78 103 $(BOOT_DIR)/%.o: $(BOOT_DIR)/%.c104 $(CC) $( BOOT_INCLUDE) $(CFLAGS) -c -o $(BUILD_PATH)/$@ $<79 build/boot/%.o: boot/%.c 80 $(CC) $(INCLUDE) $(CFLAGS) -c -o $@ $< 105 81 106 $(BOOT_DIR)/%.o: $(BOOT_DIR)/%.s 107 $(CC) $( BOOT_INCLUDE) $(CFLAGS) -c -o $(BUILD_PATH)/$@ $<82 build/boot/%.o: boot/%.S 83 $(CC) $(INCLUDE) $(CFLAGS) -c -o $@ $< 108 84 109 $(BOOT_DIR)/%.o: $(BOOT_DIR)/%.S 110 $(CC) $(BOOT_INCLUDE) $(CFLAGS) -c -o $(BUILD_PATH)/$@ $< 85 ### display compilation 86 build/display/display.elf: $(DISPLAY_OBJS) display/display.ld 87 $(LD) -o $@ -T display/display.ld $(DISPLAY_OBJS) 88 $(DU) -D $@ > $@.txt 89 90 build/display/main.o: display/main.c 91 $(CC) $(INCLUDE) $(CFLAGS) -c -o $@ $< 92 93 ### router compilation 94 build/router/router.elf: $(ROUTER_OBJS) router/router.ld 95 $(LD) -o $@ -T router/router.ld $(ROUTER_OBJS) 96 $(DU) -D $@ > $@.txt 97 98 build/router/main.o: router/main.c 99 $(CC) $(INCLUDE) $(CFLAGS) -c -o $@ $< 100 101 ### hello compilation 102 build/hello/hello.elf: $(HELLO_OBJS) hello/hello.ld 103 $(LD) -o $@ -T hello/hello.ld $(HELLO_OBJS) 104 $(DU) -D $@ > $@.txt 105 106 build/hello/main.o: hello/main.c 107 $(CC) $(INCLUDE) $(CFLAGS) -c -o $@ $< 108 109 ### pgcd compilation 110 build/pgcd/pgcd.elf: $(PGCD_OBJS) pgcd/pgcd.ld 111 $(LD) -o $@ -T pgcd/pgcd.ld $(PGCD_OBJS) 112 $(DU) -D $@ > $@.txt 113 114 build/pgcd/main.o: pgcd/main.c 115 $(CC) $(INCLUDE) $(CFLAGS) -c -o $@ $< 111 116 112 117 ### libs compilation 113 $(LIB_DIR)/%.o: $(LIB_DIR)/%.c114 $(CC) $(CFLAGS) $( LIB_INCLUDE) -c -o $(BUILD_PATH)/$@ $<118 build/libs/utils.o: libs/utils.c 119 $(CC) $(CFLAGS) $(INCLUDE) -c -o $@ $< 115 120 116 ### applications 117 apps: $(LIB_OBJS) 118 @echo "---------------------------------------------- BUILDING APPS ---------------------------------------------------------" 119 set -e; for d in $(APP_DIRS); do $(MAKE) -f config.mk -C $$d ; echo "Compiling $$d"; done 121 build/libs/stdio.o: libs/stdio.c 122 $(CC) $(CFLAGS) $(INCLUDE) -c -o $@ $< 123 124 build/libs/mwmr_channel.o: libs/mwmr_channel.c 125 $(CC) $(CFLAGS) $(INCLUDE) -c -o $@ $< 126 120 127 121 128 ### clean 122 129 clean: 123 rm -f *.o *.elf *.bin *.txt core *~ 2>$(TRASH) 124 $(MAKE) -s clean -C $(XML_PATH) 2>$(TRASH) 125 $(MAKE) -s clean -C $(MEMO_PATH) 2>$(TRASH) 126 rm -r $(BUILD_PATH) 2>$(TRASH) 127 rm -r $(ELF_PATH) 2>$(TRASH) 128 set -e; for d in $(APP_DIRS); do $(MAKE) clean -f config.mk -C $$d ; done 130 rm -f *.o *.elf *.bin *.txt core *~ 2>$(TRASH) 131 $(MAKE) -s clean -C $(XML_PATH) 2>$(TRASH) 132 $(MAKE) -s clean -C $(MEMO_PATH) 2>$(TRASH) 133 rm -r build/boot/* 2>$(TRASH) 134 rm -r build/sys/* 2>$(TRASH) 135 rm -r build/libs/* 2>$(TRASH) 136 rm -r build/pgcd/* 2>$(TRASH) 137 rm -r build/hello/* 2>$(TRASH) 138 rm -r build/display/* 2>$(TRASH) 139 rm -r build/router/* 2>$(TRASH) -
soft/giet_vm/boot/boot.ld
r167 r189 3 3 *****************************************************************************/ 4 4 5 /* The vsegs used in the boot phase must respect identity mapping: 6 physical address = virtual address */ 5 /* 6 The following (virtual) addresses are specific for the boot phase. 7 They must respect identity mapping: physical address = virtual address 8 */ 7 9 8 10 seg_boot_base = 0xBFC00000; /* boot code */ … … 12 14 seg_mapping_base = 0xBFC0C000; /* boot mapping_info */ 13 15 16 /* 17 The following (virtual) addresse are defined and used by the kernel. 18 They are not constrained to respect identity mapping. 19 */ 20 14 21 seg_kernel_init_base = 0x80090000; /* system init entry */ 15 22 16 seg_tty_base = 0x90000000; /* TTY device: for debug purpose! */ 23 seg_tty_base = 0x90000000; /* TTY device */ 24 seg_timer_base = 0x91000000; /* Timer device */ 25 seg_ioc_base = 0x92000000; /* Block device */ 26 seg_dma_base = 0x93000000; /* DMA device */ 27 seg_gcd_base = 0x95000000; /* GCD device */ 28 seg_fb_base = 0x96000000; /* FrameBuffer device */ 29 seg_iob_base = 0x9E000000; /* IO Bridge device */ 30 seg_icu_base = 0x9F000000; /* ICU or XICU device */ 17 31 18 32 /* 19 *Grouping sections into segments for boot code and data20 33 Grouping sections into segments for boot code and data 34 */ 21 35 22 36 SECTIONS 23 37 { 24 /* *contain both data and code sections */38 /* contain both data and code sections */ 25 39 . = seg_boot_base; 26 40 seg_boot : -
soft/giet_vm/boot/reset.S
r173 r189 7 7 /* running one or several multi-tasks software application(s) defined in */ 8 8 /* the mapping_info data-structure. */ 9 /* Procesor 0 uses the mapping_info data structure to build all page tables */ 10 /* before jumping to the kernel_init code. */ 9 /* Procesor 0 uses the mapping_info data structure to statically initialize */ 10 /* the kernel structures: */ 11 /* - build page tables for all vspaces */ 12 /* - initializes the vobjs not initialized by GCC */ 13 /* - initialize the schedulers and task contexts for all processeurs */ 14 /* - initialize the peripherals */ 11 15 /* Other processors are waiting until the mapping_info signature has been */ 12 /* modified by processor 0 (done while executing kernel_init code). */ 16 /* modified by processor 0. */ 17 /* */ 13 18 /* Implementation note: */ 14 19 /* The entry point is 0xbfc00000, but the actual boot code starts at address */ … … 43 48 .align 2 44 49 .org EXCEP_ORG 50 45 51 boot_excep: 46 la a0, boot_error_string 47 jal boot_puts 52 53 # get the lock protecting TTY0 54 la k0, boot_tty0_lock 55 ll k1, 0(k0) 56 bnez k1, boot_excep 57 li k1, 1 58 sc k1, 0(k0) 59 beqz k1, boot_excep 60 nop 61 62 # display error messages on TTY0 63 la a0, boot_error_string 64 jal boot_puts 48 65 nop 49 66 mfc0 a0, CP0_TIME 50 jal boot_putw67 jal boot_putw 51 68 nop 52 la a0, boot_lf_string53 jal boot_puts54 nop 55 56 la a0, boot_pid_string57 jal boot_puts69 la a0, boot_lf_string 70 jal boot_puts 71 nop 72 73 la a0, boot_pid_string 74 jal boot_puts 58 75 nop 59 76 mfc0 k0, CP0_PROCID 60 77 andi a0, k0, 0xFFF 61 jal boot_putw62 nop 63 la a0, boot_lf_string64 jal boot_puts65 nop 66 67 la a0, boot_epc_string68 jal boot_puts78 jal boot_putw 79 nop 80 la a0, boot_lf_string 81 jal boot_puts 82 nop 83 84 la a0, boot_epc_string 85 jal boot_puts 69 86 nop 70 87 mfc0 a0, CP0_EPC 71 jal boot_putw72 nop 73 la a0, boot_lf_string74 jal boot_puts75 nop 76 77 la a0, boot_cr_string78 jal boot_puts88 jal boot_putw 89 nop 90 la a0, boot_lf_string 91 jal boot_puts 92 nop 93 94 la a0, boot_cr_string 95 jal boot_puts 79 96 nop 80 97 mfc0 a0, CP0_CR 81 jal boot_putw82 nop 83 la a0, boot_lf_string84 jal boot_puts85 nop 86 87 la a0, boot_sr_string88 jal boot_puts98 jal boot_putw 99 nop 100 la a0, boot_lf_string 101 jal boot_puts 102 nop 103 104 la a0, boot_sr_string 105 jal boot_puts 89 106 nop 90 107 mfc0 a0, CP0_SR 91 jal boot_putw92 nop 93 la a0, boot_lf_string94 jal boot_puts95 nop 96 97 la a0, boot_bar_string98 jal boot_puts108 jal boot_putw 109 nop 110 la a0, boot_lf_string 111 jal boot_puts 112 nop 113 114 la a0, boot_bar_string 115 jal boot_puts 99 116 nop 100 117 mfc0 a0, CP0_BAR 101 jal boot_putw 102 nop 103 la a0, boot_lf_string 104 jal boot_puts 105 nop 106 118 jal boot_putw 119 nop 120 la a0, boot_lf_string 121 jal boot_puts 122 nop 123 124 # release the lock 125 la k0, boot_tty0_lock 126 li k1, 0 127 sw k1, 0(k0) 128 129 # exit 107 130 j boot_exit 108 131 nop … … 115 138 116 139 boot_start: 117 /* get the procid */ 140 141 # get the procid 118 142 mfc0 k0, CP0_PROCID 119 andi k0, k0, 0xFFF /* no more than 4096 processors... */120 121 /* Only processor 0 does init */122 bne k0, zero, boot_wait_signature123 nop 124 125 /* Processor 0 get a temporary stack */143 andi k0, k0, 0xFFF # no more than 4096 processors 144 145 # Only processor 0 does init 146 bne k0, zero, boot_wait_signature 147 nop 148 149 # Processor 0 get a temporary stack 126 150 la sp, seg_boot_stack_base 127 addiu sp, sp, 0x3000 /* SP <= seg_boot_stack + 12K */128 129 /* Processor 0 initialises all Page Tables */130 jal boot_ pt_init151 addiu sp, sp, 0x3000 # SP <= seg_boot_stack + 12K 152 153 # Processor 0 initialises all kernel structures 154 jal boot_init 131 155 nop 132 156 133 /* jump to kernel_init */157 # jump to kernel_init 134 158 j boot_to_kernel_init 135 159 nop … … 137 161 boot_wait_signature: 138 162 139 /* all other processors are waiting signature change */140 la 141 cache 0x11, 0(k0) /* invalidate local cache copy */142 lw k0, 0(k0) /* k0 <= mapping_info[0] */143 li k1,OUT_MAPPING_SIGNATURE144 bne 163 # all other processors are waiting signature change 164 la k0, seg_mapping_base 165 cache 0x11, 0(k0) # invalidate local cache copy 166 lw k0, 0(k0) # k0 <= mapping_info[0] 167 li k1, OUT_MAPPING_SIGNATURE 168 bne k1, k0, boot_wait_signature 145 169 nop 146 170 147 /* all other processors get a temporary stack of 256 bytes */171 # all other processors initialise SP register: temporary stack of 256 bytes 148 172 la sp, seg_boot_stack_base 149 173 addiu sp, sp, 0x3100 … … 151 175 andi k0, k0, 0xFFF 152 176 sll k0, k0, 8 153 addu sp, sp, k0 /* SP <= seg_boot_stack_base + 12K + (pid+1)*256 */177 addu sp, sp, k0 # SP <= seg_boot_stack_base + 12K + (pid+1)*256 154 178 155 179 boot_to_kernel_init: 156 180 157 /* all processors initialize PTPR with PTAB[0] */ 158 la k1, _ptabs 181 # all processors initialise SCHED register with boot_schedulers_paddr[pid] 182 mfc0 k0, CP0_PROCID 183 andi k0, k0, 0xFFF 184 sll k0, k0, 2 # k0 <= 4*pid 185 la k1, boot_schedulers_paddr 186 addu k1, k1, k0 # k1 <= &boot_scheduler_paddr[pid] 187 lw k1, 0(k1) 188 mtc0 k1, CP0_SCHED 189 190 # all processors initialize PTPR register with boot_ptabs_paddr[0] 191 la k1, boot_ptabs_paddr 159 192 lw k1, 0(k1) 160 193 srl k1, k1, 13 161 mtc2 k1, CP2_PTPR /* PTPR <= _ptabs[0] */162 163 /* all processors activate MMU */194 mtc2 k1, CP2_PTPR 195 196 # all processors activate MMU 164 197 li k1, 0xF 165 mtc2 k1, CP2_MODE /* MODE register */166 167 /* jump to kernel_init */198 mtc2 k1, CP2_MODE 199 200 # all processors jump to kernel_init 168 201 la k0, seg_kernel_init_base 169 202 j k0 170 203 nop 171 204 172 boot_error_string: .asciiz "\n[BOOT] Fatal Error in reset.Sat cycle "205 boot_error_string: .asciiz "\n[BOOT] Fatal Error at cycle " 173 206 boot_pid_string: .asciiz " PID = " 174 207 boot_sr_string: .asciiz " SR = " … … 178 211 boot_lf_string: .asciiz "\n" 179 212 180 .set reorder 181 182 213 boot_tty0_lock: .word 0 214 215 .set reorder 216 217 -
soft/giet_vm/giet_config.h
r180 r189 12 12 /* Debug parameters */ 13 13 14 #define BOOT_DEBUG_VIEW 0 /* display the mapping_info on system TTY */ 15 #define BOOT_DEBUG_PT 0 /* display the page tables after mapping */ 16 #define INIT_DEBUG_CTX 0 /* display the task contexts after mapping */ 17 #define GIET_DEBUG_SWITCH 0 /* Trace context switchs */ 14 #define BOOT_DEBUG_PT 0 /* display page tables initialisation on TTY0 */ 15 #define BOOT_DEBUG_VOBJS 0 /* display vobjs initialisation on TTY0 */ 16 #define BOOT_DEBUG_SCHED 0 /* display schedulers initialisation on TTY0 */ 17 #define BOOT_DEBUG_PERI 0 /* display peripherals initialisation on TTY0 */ 18 19 #define GIET_DEBUG_INIT 0 /* display parallel kernel initialisation on TTY0 */ 20 #define GIET_DEBUG_SWITCH 0 /* display context switchs on TTY0 */ 18 21 19 22 … … 24 27 #define NB_CLUSTERS 1 /* number of clusters */ 25 28 #define CLUSTER_SPAN 0 /* address increment between clusters */ 26 #define NB_PROCS 4 /* max number of processors per cluster */ 27 #define NB_TIMERS 4 /* number of timers per cluster */ 28 #define NB_DMAS 1 /* total number of DMA channels */ 29 #define NB_TTYS 8 /* total number of TTY terminals */ 30 #define NB_IOC 1 /* total number of IOC channels */ 29 #define NB_PROCS_MAX 4 /* max number of processors per cluster */ 30 #define NB_TIMERS_MAX 0 /* max number of user timers per cluster */ 31 #define NB_DMAS_MAX 1 /* max number of DMA channels per cluster*/ 32 #define NB_TTYS 8 /* total number of TTY channels */ 33 #define NB_IOCS 1 /* total number of IOC channels */ 34 #define NB_NICS 1 /* total number of NIC channels */ 31 35 32 36 /* software parameters */ 33 37 34 #define GIET_NB_TASKS_MAX 4 /* max number of tasks per processor */35 38 #define GIET_NB_VSPACE_MAX 4 /* max number of virtual spaces */ 36 #define GIET_TICK_VALUE 16384/* context switch period (number of cycles) */39 #define GIET_TICK_VALUE 0x4000 /* context switch period (number of cycles) */ 37 40 #define GIET_IOMMU_ACTIVE 0 /* The IOMMU vspace is defined */ 41 #define GIET_USE_XICU 0 /* Use the XICU interrupt controler */ 38 42 39 43 #endif -
soft/giet_vm/libs/mwmr_channel.c
r178 r189 33 33 #include <mwmr_channel.h> 34 34 #include <stdio.h> 35 #include <common.h>36 35 37 36 ////////////////////////////////////////////////////////////////////////////// … … 74 73 // after a random delay. 75 74 ////////////////////////////////////////////////////////////////////////////// 76 void mwmr_write( mwmr_channel_t* 77 const unsigned int*buffer,78 unsigned int 75 void mwmr_write( mwmr_channel_t* mwmr, 76 unsigned int* buffer, 77 unsigned int nitems ) 79 78 { 80 79 unsigned int x; … … 86 85 unsigned int ptw; // channel ptw 87 86 88 if(nitems == 0) 89 return; 90 91 assert(buffer && "mwmr write: Empty buffer");87 if(nitems == 0) return; 88 89 // address virtuelle 0 is illegal... 90 assert(buffer && "mwmr read: Empty buffer"); 92 91 93 92 while(1) … … 163 162 unsigned int ptr; // channel ptw 164 163 165 if(nitems == 0) 166 return; 167 164 if(nitems == 0) return; 165 166 // address virtuelle 0 is illegal... 168 167 assert(buffer && "mwmr read: Empty buffer"); 169 168 -
soft/giet_vm/libs/mwmr_channel.h
r179 r189 20 20 unsigned int sts; // number of words available 21 21 unsigned int depth; // max number of words in the channel 22 unsigned int width; // number of word in an item22 unsigned int width; // number of words in an item 23 23 unsigned int lock; // exclusive access lock 24 unsigned int data[1 ]; // circular buffer24 unsigned int data[1018]; // circular buffer 25 25 } mwmr_channel_t; 26 26 … … 29 29 ////////////////////////////////////////////////////////////////////////////// 30 30 31 void mwmr_write( mwmr_channel_t* 32 const unsigned int*buffer,33 unsigned int 31 void mwmr_write( mwmr_channel_t* mwmr, 32 unsigned int* buffer, 33 unsigned int nitems ); 34 34 35 35 void mwmr_read( mwmr_channel_t* mwmr, -
soft/giet_vm/libs/spin_lock.c
r178 r189 10 10 // It is a simple binary lock, without waiting queue. 11 11 // 12 // The lock_acquire(), lock_try_acquire() and lock_release() functions do 13 // not require a system call. 12 // The lock_acquire() and lock_release() functions do not require a system call. 13 // The barrier itself must have been allocated in a non cacheable segment, 14 // if the platform does not provide hardwate cache coherence. 14 15 // 15 16 // ALL locks must be defined in the mapping_info data structure, 16 17 // to be initialised by the GIET in the boot phase. 17 18 // The vobj_get_vbase() system call (defined in stdio.c and stdio.h files) 18 // can be used to get the virtual base address of the lock fro mit's name.19 // can be used to get the virtual base address of the lock fro it's name. 19 20 /////////////////////////////////////////////////////////////////////////////////// 20 21 … … 64 65 } 65 66 66 //////////////////////////////////////////////////////////////////////////////67 // lock_try_acquire()68 //////////////////////////////////////////////////////////////////////////////69 int lock_try_acquire( giet_lock_t* lock )70 {71 register int ret = 0;72 register unsigned int* plock = &lock->value;73 74 asm volatile ("ll $2, 0(%1) \n" // $2 <= _locks_lock75 "bnez $2, _lock_done \n" // exitif busy76 "li $3, 1 \n" // prepare argument for sc77 "sc $3, 0(%1) \n" // try to set _locks_busy78 "xori %0, $3, 1 \n" // ret = !$379 "_lock_done: \n"80 :"=r"(ret)81 :"r"(plock)82 :"$2","$3");83 return ret;84 } -
soft/giet_vm/libs/spin_lock.h
r178 r189 27 27 void lock_release( giet_lock_t* lock ); 28 28 29 // return 0 if success30 int lock_try_acquire( giet_lock_t* lock );31 32 29 #endif 33 30 -
soft/giet_vm/libs/srl.h
r178 r189 19 19 #include "libsrl/srl_hw_helpers.h" 20 20 21 #include "libsrl/srl_args.h"22 23 21 //kernel use! 24 22 //#include "libsrl/srl_mwmr_sys.h" 25 23 24 /* port, APP_NAME, TASK */ 25 # define GET_MWMR(port) \ 26 ({ \ 27 srl_mwmr_t _mwmr; \ 28 if( vobj_get_vbase( APP_NAME , #port, MWMR, (unsigned int*)&_mwmr ) ) \ 29 { \ 30 srl_log_printf( NONE, "\n[ERROR] in "TASK" task :\n"); \ 31 srl_log_printf( NONE, " undefined <"#port"> channel: %d\n", _mwmr); \ 32 srl_log_printf( TRACE, "*** &"#port" = %x\n\n", (unsigned int)_mwmr ); \ 33 exit();/*srl?*/ \ 34 }else \ 35 srl_log_printf( TRACE, "%s:%d: arg of %s for %s,from %s; &"#port" = %x\n\n", __FILE__, __LINE__, APP_NAME, TASK,#port, (unsigned int)_mwmr ); \ 36 _mwmr;\ 37 }) 26 38 27 39 #endif -
soft/giet_vm/libs/stdio.h
r178 r189 8 8 #ifndef _STDIO_H 9 9 #define _STDIO_H 10 11 #include <mapping_info.h>12 #include <common.h>13 10 14 11 /* MIPS32 related functions */ … … 64 61 void giet_exit(); 65 62 unsigned int giet_rand(); 66 unsigned int ctx_switch();63 unsigned int giet_ctx_switch(); 67 64 unsigned int giet_procnumber(); 68 65 66 #endif 69 67 70 #endif -
soft/giet_vm/map.xml
r185 r189 2 2 3 3 <mapping_info signature = "0xdeadbeef" 4 name = " c1_v2_G12"4 name = "1C_4P_FOUR" 5 5 clusters = "1" 6 ttys = "8"7 fbs = "1"8 6 vspaces = "4" 9 7 globals = "13" > … … 11 9 <clusterset> 12 10 <cluster index = "0" > 13 <pseg name = "PSEG_ROM" 14 type = "ROM" 15 base = "0xbfc00000" 16 length = "0x00010000" /> 17 18 <pseg name = "PSEG_RAU" 19 type = "RAM" 20 base = "0x00000000" 21 length = "0x01000000" /> 22 23 <pseg name = "PSEG_RAK" 24 type = "RAM" 25 base = "0x80000000" 26 length = "0x00100000" /> 27 28 <pseg name = "PSEG_TTY" 29 type = "PERI" 30 base = "0x90000000" 31 length = "0x00001000" /> 32 33 <pseg name = "PSEG_TIM" 34 type = "PERI" 35 base = "0x91000000" 36 length = "0x00001000" /> 37 38 <pseg name = "PSEG_IOC" 39 type = "PERI" 40 base = "0x92000000" 41 length = "0x00001000" /> 42 43 <pseg name = "PSEG_DMA" 44 type = "PERI" 45 base = "0x93000000" 46 length = "0x00001000" /> 47 48 <pseg name = "PSEG_FBF" 49 type = "PERI" 50 base = "0x96000000" 51 length = "0x00004000" /> 52 53 <pseg name = "PSEG_ICU" 54 type = "PERI" 55 base = "0x9F000000" 56 length = "0x00001000" /> 11 <pseg name = "PSEG_ROM" 12 type = "ROM" 13 base = "0xbfc00000" 14 length = "0x00010000" /> 15 16 <pseg name = "PSEG_RAM" 17 type = "RAM" 18 base = "0x01000000" 19 length = "0x01000000" /> 20 21 <pseg name = "PSEG_TTY" 22 type = "PERI" 23 base = "0x90000000" 24 length = "0x00001000" /> 25 26 <pseg name = "PSEG_TIM" 27 type = "PERI" 28 base = "0x90100000" 29 length = "0x00001000" /> 30 31 <pseg name = "PSEG_IOC" 32 type = "PERI" 33 base = "0x90200000" 34 length = "0x00001000" /> 35 36 <pseg name = "PSEG_DMA" 37 type = "PERI" 38 base = "0x90300000" 39 length = "0x00001000" /> 40 41 <pseg name = "PSEG_FBF" 42 type = "PERI" 43 base = "0x90600000" 44 length = "0x00004000" /> 45 46 <pseg name = "PSEG_ICU" 47 type = "PERI" 48 base = "0x90700000" 49 length = "0x00001000" /> 50 51 <pseg name = "PSEG_COP" 52 type = "PERI" 53 base = "0x90800000" 54 length = "0x00001000" /> 55 57 56 <proc index = "0" > 57 <irq type = "HARD" 58 icuid = "0" 59 isr = "ISR_SWITCH" /> 60 61 <irq type = "HARD" 62 icuid = "8" 63 isr = "ISR_DMA" 64 channel = "0" /> 65 66 <irq type = "HARD" 67 icuid = "9" 68 isr = "ISR_DMA" 69 channel = "1" /> 70 71 <irq type = "HARD" 72 icuid = "10" 73 isr = "ISR_DMA" 74 channel = "2" /> 75 76 <irq type = "HARD" 77 icuid = "11" 78 isr = "ISR_DMA" 79 channel = "3" /> 80 81 <irq type = "HARD" 82 icuid = "12" 83 isr = "ISR_DMA" 84 channel = "4" /> 85 86 <irq type = "HARD" 87 icuid = "13" 88 isr = "ISR_DMA" 89 channel = "5" /> 90 91 <irq type = "HARD" 92 icuid = "14" 93 isr = "ISR_DMA" 94 channel = "6" /> 95 96 <irq type = "HARD" 97 icuid = "15" 98 isr = "ISR_DMA" 99 channel = "7" /> 100 101 <irq type = "HARD" 102 icuid = "16" 103 isr = "ISR_TTY" 104 channel = "0" /> 105 106 <irq type = "HARD" 107 icuid = "17" 108 isr = "ISR_TTY" 109 channel = "1" /> 110 111 <irq type = "HARD" 112 icuid = "18" 113 isr = "ISR_TTY" 114 channel = "2" /> 115 116 <irq type = "HARD" 117 icuid = "19" 118 isr = "ISR_TTY" 119 channel = "3" /> 120 121 <irq type = "HARD" 122 icuid = "20" 123 isr = "ISR_TTY" 124 channel = "4" /> 125 126 <irq type = "HARD" 127 icuid = "21" 128 isr = "ISR_TTY" 129 channel = "5" /> 130 131 <irq type = "HARD" 132 icuid = "22" 133 isr = "ISR_TTY" 134 channel = "6" /> 135 136 <irq type = "HARD" 137 icuid = "23" 138 isr = "ISR_TTY" 139 channel = "7" /> 140 141 <irq type = "HARD" 142 icuid = "24" 143 isr = "ISR_TTY" 144 channel = "8" /> 145 146 <irq type = "HARD" 147 icuid = "25" 148 isr = "ISR_TTY" 149 channel = "9" /> 150 151 <irq type = "HARD" 152 icuid = "26" 153 isr = "ISR_TTY" 154 channel = "10" /> 155 156 <irq type = "HARD" 157 icuid = "27" 158 isr = "ISR_TTY" 159 channel = "11" /> 160 161 <irq type = "HARD" 162 icuid = "28" 163 isr = "ISR_TTY" 164 channel = "12" /> 165 166 <irq type = "HARD" 167 icuid = "29" 168 isr = "ISR_TTY" 169 channel = "13" /> 170 171 <irq type = "HARD" 172 icuid = "30" 173 isr = "ISR_TTY" 174 channel = "14" /> 175 176 <irq type = "HARD" 177 icuid = "31" 178 isr = "ISR_IOC" /> 58 179 </proc> 180 59 181 <proc index = "1" > 182 <irq type = "HARD" 183 icuid = "1" 184 isr = "ISR_SWITCH" /> 60 185 </proc> 186 61 187 <proc index = "2" > 188 <irq type = "HARD" 189 icuid = "2" 190 isr = "ISR_SWITCH" /> 62 191 </proc> 192 63 193 <proc index = "3" > 194 <irq type = "HARD" 195 icuid = "3" 196 isr = "ISR_SWITCH" /> 64 197 </proc> 198 199 <periph type = "IOC" 200 psegname = "PSEG_IOC" 201 channels = "1" /> 202 203 <periph type = "TTY" 204 psegname = "PSEG_TTY" 205 channels = "2" /> 206 207 <periph type = "DMA" 208 psegname = "PSEG_DMA" 209 channels = "1" /> 210 211 <periph type = "TIM" 212 psegname = "PSEG_TIM" 213 channels = "8" /> 214 215 <periph type = "FBF" 216 psegname = "PSEG_FBF" /> 217 218 <coproc name = "COP0" 219 psegname = "PSEG_COP" > 220 221 <port direction = "TO_COPROC" 222 vspacename = "router" 223 vobjname = "mwmr_in" /> 224 225 <port direction = "FROM_COPROC" 226 vspacename = "router" 227 vobjname = "mwmr_out" /> 228 </coproc> 65 229 </cluster> 66 230 </clusterset> … … 69 233 <vseg name = "seg_boot_code_data" 70 234 vbase = "0xbfc00000" 71 mode = "CX __"72 235 mode = "CXW_" 236 clusterid = "0" 73 237 psegname = "PSEG_ROM" 74 238 ident = "1" > … … 76 240 type = "ELF" 77 241 length = "0x00008000" 78 binpath = "build/boot .elf" />242 binpath = "build/boot/boot.elf" /> 79 243 </vseg> 80 244 … … 82 246 vbase = "0xbfc08000" 83 247 mode = "C_W_" 84 248 clusterid = "0" 85 249 psegname = "PSEG_ROM" 86 250 ident = "1" > … … 93 257 vbase = "0xbfc0c000" 94 258 mode = "C_W_" 95 259 clusterid = "0" 96 260 psegname = "PSEG_ROM" 97 261 ident = "1" > … … 105 269 vbase = "0x80000000" 106 270 mode = "CX__" 107 clusterid = "0" 108 psegname = "PSEG_RAU" 109 ident = "0" > 110 <vobj name = "seg_kernel_code" 111 type = "ELF" 112 length = "0x00010000" 113 binpath = "build/sys.elf" 114 /> 271 clusterid = "0" 272 psegname = "PSEG_RAM" > 273 <vobj name = "seg_kernel_code" 274 type = "ELF" 275 length = "0x00010000" 276 binpath = "build/sys/sys.elf" /> 115 277 </vseg> 116 278 … … 118 280 vbase = "0x80010000" 119 281 mode = "C_W_" 120 clusterid = "0" 121 psegname = "PSEG_RAU" 122 ident = "O" > 282 clusterid = "0" 283 psegname = "PSEG_RAM" > 123 284 <vobj name = "seg_kernel_data" 124 285 type = "ELF" 125 286 length = "0x00040000" 126 binpath = "build/sys .elf" />287 binpath = "build/sys/sys.elf" /> 127 288 </vseg> 128 289 … … 130 291 vbase = "0x80080000" 131 292 mode = "__W_" 132 clusterid = "0" 133 psegname = "PSEG_RAU" 134 ident = "0" > 293 clusterid = "0" 294 psegname = "PSEG_RAM" > 135 295 <vobj name = "seg_kernel_uncdata" 136 296 type = "ELF" 137 297 length = "0x00010000" 138 binpath = "build/sys .elf" />298 binpath = "build/sys/sys.elf" /> 139 299 </vseg> 140 300 … … 142 302 vbase = "0x80090000" 143 303 mode = "CX__" 144 clusterid = "0" 145 psegname = "PSEG_RAU" 146 ident = "0" > 304 clusterid = "0" 305 psegname = "PSEG_RAM" > 147 306 <vobj name = "seg_kernel_init" 148 307 type = "ELF" 149 308 length = "0x00010000" 150 binpath = "build/sys .elf" />309 binpath = "build/sys/sys.elf" /> 151 310 </vseg> 152 311 … … 155 314 vbase = "0x90000000" 156 315 mode = "__W_" 157 clusterid = "0" 158 psegname = "PSEG_TTY" 159 ident = "1" > 316 clusterid = "0" 317 psegname = "PSEG_TTY" > 160 318 <vobj name = "tty" 161 319 type = "PERI" … … 166 324 vbase = "0x91000000" 167 325 mode = "__W_" 168 clusterid = "0" 169 psegname = "PSEG_TIM" 170 ident = "1" > 326 clusterid = "0" 327 psegname = "PSEG_TIM" > 171 328 <vobj name = "timer" 172 329 type = "PERI" … … 177 334 vbase = "0x92000000" 178 335 mode = "__W_" 179 clusterid = "0" 180 psegname = "PSEG_IOC" 181 ident = "1" > 336 clusterid = "0" 337 psegname = "PSEG_IOC" > 182 338 <vobj name = "ioc" 183 339 type = "PERI" … … 188 344 vbase = "0x93000000" 189 345 mode = "__W_" 190 clusterid = "0" 191 psegname = "PSEG_DMA" 192 ident = "1" > 346 clusterid = "0" 347 psegname = "PSEG_DMA" > 193 348 <vobj name = "dma" 194 349 type = "PERI" … … 199 354 vbase = "0x96000000" 200 355 mode = "__W_" 201 clusterid = "0" 202 psegname = "PSEG_FBF" 203 ident = "1" > 356 clusterid = "0" 357 psegname = "PSEG_FBF" > 204 358 <vobj name = "fb" 205 359 type = "PERI" … … 210 364 vbase = "0x9F000000" 211 365 mode = "__W_" 212 clusterid = "0" 213 psegname = "PSEG_ICU" 214 ident = "1" > 366 clusterid = "0" 367 psegname = "PSEG_ICU" > 215 368 <vobj name = "icu" 216 369 type = "PERI" … … 226 379 vbase = "0x00800000" 227 380 mode = "__WU" 228 229 psegname = "PSEG_RA U" >381 clusterid = "0" 382 psegname = "PSEG_RAM" > 230 383 <vobj name = "seg_data_router" 231 384 type = "ELF" 232 385 length = "0x00010000" 233 binpath = "build/router .elf" />386 binpath = "build/router/router.elf" /> 234 387 </vseg> 235 388 … … 237 390 vbase = "0x00400000" 238 391 mode = "CX_U" 239 240 psegname = "PSEG_RA U" >392 clusterid = "0" 393 psegname = "PSEG_RAM" > 241 394 <vobj name = "seg_code_router" 242 395 type = "ELF" 243 396 length = "0x00010000" 244 binpath = "build/router .elf" />397 binpath = "build/router/router.elf" /> 245 398 </vseg> 246 399 … … 248 401 vbase = "0x00300000" 249 402 mode = "C___" 250 251 psegname = "PSEG_RA U" >403 clusterid = "0" 404 psegname = "PSEG_RAM" > 252 405 <vobj name = "ptab_router" 253 406 type = "PTAB" … … 259 412 vbase = "0x00010000" 260 413 mode = "C_WU" 261 262 psegname = "PSEG_RA U" >414 clusterid = "0" 415 psegname = "PSEG_RAM" > 263 416 <vobj name = "stack_producer" 264 417 type = "BUFFER" … … 269 422 vbase = "0x00020000" 270 423 mode = "C_WU" 271 272 psegname = "PSEG_RA U" >424 clusterid = "0" 425 psegname = "PSEG_RAM" > 273 426 <vobj name = "stack_consumer" 274 427 type = "BUFFER" … … 279 432 vbase = "0x00030000" 280 433 mode = "C_WU" 281 282 psegname = "PSEG_RA U" >434 clusterid = "0" 435 psegname = "PSEG_RAM" > 283 436 <vobj name = "stack_router_A" 284 437 type = "BUFFER" … … 289 442 vbase = "0x00040000" 290 443 mode = "C_WU" 291 292 psegname = "PSEG_RA U" >444 clusterid = "0" 445 psegname = "PSEG_RAM" > 293 446 <vobj name = "stack_router_B" 294 447 type = "BUFFER" … … 299 452 vbase = "0x00050000" 300 453 mode = "__WU" 301 302 psegname = "PSEG_RA U" >454 clusterid = "0" 455 psegname = "PSEG_RAM" > 303 456 <vobj name = "mwmr_in" 304 457 type = "MWMR" 305 length = "0x00000020" 306 458 length = "0x00000020" 459 init = "1" /> 307 460 <vobj name = "mwmr_out" 308 461 type = "MWMR" 309 length = "0x00000020" 310 462 length = "0x00000020" 463 init = "1" /> 311 464 </vseg> 312 465 … … 346 499 vbase = "0x00800000" 347 500 mode = "C_WU" 348 349 psegname = "PSEG_RA U" >501 clusterid = "0" 502 psegname = "PSEG_RAM" > 350 503 <vobj name = "seg_data_hello" 351 504 type = "ELF" 352 505 length = "0x00010000" 353 binpath = "build/hello .elf" />506 binpath = "build/hello/hello.elf" /> 354 507 </vseg> 355 508 … … 357 510 vbase = "0x00400000" 358 511 mode = "CX_U" 359 360 psegname = "PSEG_RA U" >512 clusterid = "0" 513 psegname = "PSEG_RAM" > 361 514 <vobj name = "seg_code_hello" 362 515 type = "ELF" 363 516 length = "0x00010000" 364 binpath = "build/hello .elf" />517 binpath = "build/hello/hello.elf" /> 365 518 </vseg> 366 519 … … 368 521 vbase = "0x00300000" 369 522 mode = "C___" 370 371 psegname = "PSEG_RA U" >523 clusterid = "0" 524 psegname = "PSEG_RAM" > 372 525 <vobj name = "ptab" 373 526 type = "PTAB" … … 379 532 vbase = "0x00000000" 380 533 mode = "C_WU" 381 382 psegname = "PSEG_RA U" >534 clusterid = "0" 535 psegname = "PSEG_RAM" > 383 536 <vobj name = "stack" 384 537 type = "BUFFER" … … 401 554 vbase = "0x00800000" 402 555 mode = "C_WU" 403 404 psegname = "PSEG_RA U" >556 clusterid = "0" 557 psegname = "PSEG_RAM" > 405 558 <vobj name = "seg_data_pgcd" 406 559 type = "ELF" 407 560 length = "0x00010000" 408 binpath = "build/pgcd .elf" />561 binpath = "build/pgcd/pgcd.elf" /> 409 562 </vseg> 410 563 … … 412 565 vbase = "0x00300000" 413 566 mode = "C___" 414 415 psegname = "PSEG_RA U" >567 clusterid = "0" 568 psegname = "PSEG_RAM" > 416 569 <vobj name = "ptab" 417 570 type = "PTAB" … … 423 576 vbase = "0x00400000" 424 577 mode = "CX_U" 425 426 psegname = "PSEG_RA U" >578 clusterid = "0" 579 psegname = "PSEG_RAM" > 427 580 <vobj name = "seg_code_pgcd" 428 581 type = "ELF" 429 582 length = "0x00010000" 430 binpath = "build/pgcd .elf" />583 binpath = "build/pgcd/pgcd.elf" /> 431 584 </vseg> 432 585 … … 434 587 vbase = "0x00000000" 435 588 mode = "C_WU" 436 437 psegname = "PSEG_RA U" >589 clusterid = "0" 590 psegname = "PSEG_RAM" > 438 591 <vobj name = "stack" 439 592 type = "BUFFER" … … 455 608 vbase = "0x00800000" 456 609 mode = "C_WU" 457 458 psegname = "PSEG_RA U" >610 clusterid = "0" 611 psegname = "PSEG_RAM" > 459 612 <vobj name = "seg_data_display" 460 613 type = "ELF" 461 614 length = "0x00010000" 462 binpath = "build/display .elf" />615 binpath = "build/display/display.elf" /> 463 616 </vseg> 464 617 … … 466 619 vbase = "0x00300000" 467 620 mode = "C___" 468 469 psegname = "PSEG_RA U" >621 clusterid = "0" 622 psegname = "PSEG_RAM" > 470 623 <vobj name = "ptab" 471 624 type = "PTAB" … … 477 630 vbase = "0x00400000" 478 631 mode = "CX_U" 479 480 psegname = "PSEG_RA U" >632 clusterid = "0" 633 psegname = "PSEG_RAM" > 481 634 <vobj name = "seg_code_display" 482 635 type = "ELF" 483 636 length = "0x00010000" 484 binpath = "build/display .elf" />637 binpath = "build/display/display.elf" /> 485 638 </vseg> 486 639 … … 488 641 vbase = "0x00000000" 489 642 mode = "C_WU" 490 491 psegname = "PSEG_RA U" >643 clusterid = "0" 644 psegname = "PSEG_RAM" > 492 645 <vobj name = "stack_display" 493 646 type = "BUFFER" … … 501 654 startid = "0" 502 655 usetty = "1" 503 usefb 656 usefbdma = "1" /> 504 657 </vspace> 505 658 -
soft/giet_vm/sys/common.c
r166 r189 11 11 #include <sys_handler.h> 12 12 #include <common.h> 13 #include <ctx_handler.h> 13 14 #include <drivers.h> 14 15 #include <stdarg.h> 15 16 16 //////////////////////////////////////////////////////////////////////////// 17 // _get_lock() 17 /////////////////////////////////////////////////////////////////////////////////// 18 // Global variables 19 /////////////////////////////////////////////////////////////////////////////////// 20 21 // current context cache TODO 22 23 // SR save (used by _it_mask() / it_restore() 24 unsigned int _status_register_save; 25 26 /////////////////////////////////////////////////////////////////////////////////// 27 // _get_sched() 28 // Access CP0 and returns scheduler physical address. 29 /////////////////////////////////////////////////////////////////////////////////// 30 inline unsigned int _get_sched() 31 { 32 unsigned int ret; 33 asm volatile ( "mfc0 %0, $22" 34 : "=r"(ret) ); 35 return ret; 36 } 37 /////////////////////////////////////////////////////////////////////////////////// 38 // _get_ptpr() 39 // Access CP2 and returns PTPR register. 40 /////////////////////////////////////////////////////////////////////////////////// 41 inline unsigned int _get_ptpr() 42 { 43 unsigned int ret; 44 asm volatile ( "mfc2 %0, $0" 45 : "=r"(ret) ); 46 return ret; 47 } 48 /////////////////////////////////////////////////////////////////////////////////// 49 // _get_epc() 50 // Access CP0 and returns EPC register. 51 /////////////////////////////////////////////////////////////////////////////////// 52 inline unsigned int _get_epc() 53 { 54 unsigned int ret; 55 asm volatile ( "mfc0 %0, $14" 56 : "=r"(ret) ); 57 return ret; 58 } 59 /////////////////////////////////////////////////////////////////////////////////// 60 // _get_bar() 61 // Access CP0 and returns BAR register. 62 /////////////////////////////////////////////////////////////////////////////////// 63 inline unsigned int _get_bvar() 64 { 65 unsigned int ret; 66 asm volatile ( "mfc0 %0, $8" 67 : "=r"(ret) ); 68 return ret; 69 } 70 /////////////////////////////////////////////////////////////////////////////////// 71 // _get_cr() 72 // Access CP0 and returns CR register. 73 /////////////////////////////////////////////////////////////////////////////////// 74 inline unsigned int _get_cause() 75 { 76 unsigned int ret; 77 asm volatile ( "mfc0 %0, $13" 78 : "=r"(ret) ); 79 return ret; 80 } 81 /////////////////////////////////////////////////////////////////////////////////// 82 // _get_sr() 83 // Access CP0 and returns SR register. 84 /////////////////////////////////////////////////////////////////////////////////// 85 inline unsigned int _get_sr() 86 { 87 unsigned int ret; 88 asm volatile ( "mfc0 %0, $12" 89 : "=r"(ret) ); 90 return ret; 91 } 92 /////////////////////////////////////////////////////////////////////////////////// 93 // _it_mask() 94 // Access CP0 and mask IRQs 95 /////////////////////////////////////////////////////////////////////////////////// 96 inline void _it_mask() 97 { 98 unsigned int sr_value; 99 asm volatile( "li $3, 0xFFFFFFFE \n" 100 "mfc0 %0, $12 \n" 101 "and $3, $3, %0 \n" 102 "mtc0 $3, $12 \n" 103 : "=r"(sr_value) : : "$3" ); 104 _status_register_save = sr_value; 105 } 106 /////////////////////////////////////////////////////////////////////////////////// 107 // _it_enable() 108 // Access CP0 and enable IRQs 109 /////////////////////////////////////////////////////////////////////////////////// 110 inline void _it_restore() 111 { 112 unsigned int sr_value = _status_register_save; 113 asm volatile( "mtc0 %0, $12 \n" 114 : : "r"(sr_value) ); 115 } 116 //////////////////////////////////////////////////////////////////////////// 117 // _get_lock() 118 // Takes a lock with an ll/sc atomic access. 119 // A pseudo random delay is introduced before retry in case of miss 120 // (delay average value = 100 cycles) 18 121 //////////////////////////////////////////////////////////////////////////// 19 122 inline void _get_lock( unsigned int* plock ) 20 123 { 21 register unsigned int delay = ( _proctime() & 0xF) << 4;124 register unsigned int delay = ( _proctime() ^ _procid()<<4 ) & 0xFF; 22 125 23 126 asm volatile ( … … 49 152 50 153 //////////////////////////////////////////////////////////////////////////// 51 // _puts()52 // used for system code debug / it uses TTY0154 // _puts() 155 // display a string on TTY0 / used for system code debugand log 53 156 //////////////////////////////////////////////////////////////////////////// 54 157 void _puts(char *buffer) … … 64 167 } 65 168 //////////////////////////////////////////////////////////////////////////// 66 // _putw()67 // used for system code debug / it uses TTY0169 // _putw() 170 // display an int (hexa) on TTY0 / used for system code debug and log 68 171 //////////////////////////////////////////////////////////////////////////// 69 172 void _putw(unsigned int val) … … 85 188 } 86 189 //////////////////////////////////////////////////////////////////////////// 87 // _strncmp() 190 // _putd() 191 // display an int (decimal) on TTY0 / used for system code debug and log 192 //////////////////////////////////////////////////////////////////////////// 193 void _putd(unsigned int val) 194 { 195 static const char DecTab[] = "0123456789"; 196 char buf[11]; 197 unsigned int i; 198 unsigned int first; 199 200 buf[10] = 0; 201 202 for (i = 0; i < 10; i++) 203 { 204 if ((val != 0) || (i == 0)) 205 { 206 buf[9-i] = DecTab[val % 10]; 207 first = 9-i; 208 } 209 else 210 { 211 break; 212 } 213 val /= 10; 214 } 215 _puts( &buf[first] ); 216 } 217 //////////////////////////////////////////////////////////////////////////// 218 // _strncmp() 88 219 // compare two strings s1 & s2 (no more than n characters) 89 220 //////////////////////////////////////////////////////////////////////////// … … 101 232 } 102 233 //////////////////////////////////////////////////////////////////////////// 103 // _dcache_buf_invalidate()234 // _dcache_buf_invalidate() 104 235 // Invalidate all data cache lines corresponding to a memory 105 236 // buffer (identified by an address and a size). … … 126 257 } 127 258 } 128 /////////////////////////////////////////////////////////////////////////////////// 129 // _itoa_dec() 130 // Convert a 32-bit unsigned integer to a string of ten decimal characters. 131 /////////////////////////////////////////////////////////////////////////////////// 132 void _itoa_dec(unsigned int val, char *buf) 133 { 134 const static char dectab[] = "0123456789"; 135 unsigned int i; 136 137 for (i = 0; i < 10; i++) 138 { 139 if ((val != 0) || (i == 0)) 140 buf[9-i] = dectab[val % 10]; 141 else 142 buf[9-i] = 0x20; 143 val /= 10; 144 } 145 } 146 /////////////////////////////////////////////////////////////////////////////////// 147 // _itoa_hex() 148 // Convert a 32-bit unsigned integer to a string of eight hexadecimal characters. 149 /////////////////////////////////////////////////////////////////////////////////// 150 void _itoa_hex(unsigned int val, char *buf) 151 { 152 const static char hexatab[] = "0123456789ABCD"; 153 unsigned int i; 154 155 for (i = 0; i < 8; i++) 156 { 157 buf[7-i] = hexatab[val % 16]; 158 val /= 16; 159 } 160 } 161 /////////////////////////////////////////////////////////////////////////////////// 162 // _get_ptpr() 163 // Access CP2 and returns PTPR register. 164 /////////////////////////////////////////////////////////////////////////////////// 165 inline unsigned int _get_ptpr() 166 { 167 unsigned int ret; 168 asm volatile("mfc2 %0, $0" : "=r"(ret)); 169 return ret; 170 } 171 /////////////////////////////////////////////////////////////////////////////////// 172 // _get_epc() 173 // Access CP0 and returns EPC register. 174 /////////////////////////////////////////////////////////////////////////////////// 175 inline unsigned int _get_epc() 176 { 177 unsigned int ret; 178 asm volatile("mfc0 %0, $14" : "=r"(ret)); 179 return ret; 180 } 181 /////////////////////////////////////////////////////////////////////////////////// 182 // _get_bar() 183 // Access CP0 and returns BAR register. 184 /////////////////////////////////////////////////////////////////////////////////// 185 inline unsigned int _get_bar() 186 { 187 unsigned int ret; 188 asm volatile("mfc0 %0, $8" : "=r"(ret)); 189 return ret; 190 } 191 /////////////////////////////////////////////////////////////////////////////////// 192 // _get_cr() 193 // Access CP0 and returns CR register. 194 /////////////////////////////////////////////////////////////////////////////////// 195 inline unsigned int _get_cause() 196 { 197 unsigned int ret; 198 asm volatile("mfc0 %0, $13" : "=r"(ret)); 199 return ret; 200 } 201 202 /////////////////////////////////////////////////////////////////////////////////// 203 // _it_mask() 204 // Access CP0 and mask IRQs 205 /////////////////////////////////////////////////////////////////////////////////// 206 inline void _it_mask() 207 { 208 asm volatile( 209 "lui $27, 0xFFFF \n" 210 "ori $27, $27, 0xFFFE \n" 211 "mfc0 $26, $12 \n" 212 "and $26, $26, $27 \n" 213 "mtc0 $26, $12 \n" 214 ::: "$26", "$27" 215 ); 216 } 217 /////////////////////////////////////////////////////////////////////////////////// 218 // _it_enable() 219 // Access CP0 and enable IRQs 220 /////////////////////////////////////////////////////////////////////////////////// 221 inline void _it_enable() 222 { 223 asm volatile( 224 "mfc0 $26, $12 \n" 225 "ori $26, $26, 1 \n" 226 "mtc0 $26, $12 \n" 227 ::: "$26" 228 ); 259 //////////////////////////////////////////////////////////////////////////// 260 // _physical_read_access() 261 // This function makes a physical read access to a 32 bits word in memory, 262 // after a temporary DTLB desactivation. 263 //////////////////////////////////////////////////////////////////////////// 264 unsigned int _physical_read_access(unsigned int* paddr) 265 { 266 unsigned int value; 267 268 asm volatile( "li $3, 0xFFFFFFFE \n" 269 "mfc0 $2, $12 \n" /* $2 <= SR */ 270 "and $3, $3, $2 \n" 271 "mtc0 $3, $12 \n" /* interrupt masked */ 272 "li $3, 0xB \n" 273 "mtc2 $3, $1 \n" /* DTLB off */ 274 275 "lw %0, 0(%1) \n" /* entry <= *pslot */ 276 277 "li $3, 0xF \n" 278 "mtc2 $3, $1 \n" /* DTLB on */ 279 "mtc0 $2, $12 \n" /* restore SR */ 280 : "=r"(value) 281 : "r"(paddr) 282 : "$2", "$3" ); 283 return value; 284 } 285 //////////////////////////////////////////////////////////////////////////// 286 // _physical_write_access() 287 // This function makes a physical write access to a 32 bits word in memory, 288 // after a temporary DTLB desactivation. 289 //////////////////////////////////////////////////////////////////////////// 290 void _physical_write_access(unsigned int* paddr, unsigned int value) 291 { 292 asm volatile( "li $3, 0xFFFFFFFE \n" 293 "mfc0 $2, $12 \n" /* $26 <= SR */ 294 "and $3, $3, $2 \n" 295 "mtc0 $3, $12 \n" /* interrupt masked */ 296 "li $3, 0xB \n" 297 "mtc2 $3, $1 \n" /* DTLB off */ 298 299 "sw %0, 0(%1) \n" /* entry <= *pslot */ 300 301 "li $3, 0xF \n" 302 "mtc2 $3, $1 \n" /* DTLB on */ 303 "mtc0 $2, $12 \n" /* restore SR */ 304 : 305 : "r"(value), "r"(paddr) 306 : "$2", "$3" ); 307 } 308 //////////////////////////////////////////////////////////////////////////// 309 // _get_tasks_number() 310 // This function returns the number of tasks allocated to processor. 311 //////////////////////////////////////////////////////////////////////////// 312 unsigned int _get_tasks_number() 313 { 314 static_scheduler_t* psched = (static_scheduler_t*)_get_sched(); 315 return _physical_read_access( &(psched->tasks) ); 316 } 317 //////////////////////////////////////////////////////////////////////////// 318 // _get_current_task_id() 319 // This function returns the index of the currently running task. 320 //////////////////////////////////////////////////////////////////////////// 321 unsigned int _get_current_task_id() 322 { 323 static_scheduler_t* psched = (static_scheduler_t*)_get_sched(); 324 return _physical_read_access( &(psched->current) ); 325 } 326 /////////////////////////////////////////////////////////////////////////////// 327 // _get_current_context_slot() 328 // This function returns the global TTY index for the currently running task. 329 /////////////////////////////////////////////////////////////////////////////// 330 unsigned int _get_current_context_slot(unsigned int slot_id) 331 { 332 static_scheduler_t* psched = (static_scheduler_t*)_get_sched(); 333 unsigned int current = _physical_read_access( &(psched->current) ); 334 return _physical_read_access( &(psched->context[current][slot_id]) ); 335 } 336 /////////////////////////////////////////////i////////////////////////////////// 337 // _get_interrupt_vector_entry() 338 // This function returns the interrupt_vector entry defined by argument index. 339 //////////////////////////////////////////////////////////////////////////////// 340 unsigned int _get_interrupt_vector_entry( unsigned int index ) 341 { 342 static_scheduler_t* psched = (static_scheduler_t*)_get_sched(); 343 return _physical_read_access( &(psched->interrupt_vector[index]) ); 344 } 345 //////////////////////////////////////////////////////////////////////////// 346 // _set_current_task_id() 347 // This function returns the index of the currently running task. 348 //////////////////////////////////////////////////////////////////////////// 349 void _set_current_task_id( unsigned int value ) 350 { 351 static_scheduler_t* psched = (static_scheduler_t*)_get_sched(); 352 _physical_write_access( &(psched->current), value ); 229 353 } 230 354 … … 283 407 } 284 408 285 -
soft/giet_vm/sys/common.h
r166 r189 32 32 /////////////////////////////////////////////////////////////////////////////////// 33 33 34 void _puts(char *string); 35 void _putw(unsigned int val); 34 void _puts(char *string); 35 void _putw(unsigned int val); 36 void _putd(unsigned int val); 36 37 37 unsigned int 38 unsigned int _strncmp(const char* s1, const char* s2, unsigned int n); 38 39 39 void 40 void _dcache_buf_invalidate(const void *buffer, unsigned int size); 40 41 41 void 42 void 42 void _itoa_dec(unsigned int val, char* buf); 43 void _itoa_hex(unsigned int val, char* buf); 43 44 44 unsigned int _get_epc(); 45 unsigned int _get_ptpr(); 46 unsigned int _get_bar(); 47 unsigned int _get_cr(); 45 void _dtlb_off(void); 46 void _dtlb_on(void); 48 47 49 void _get_lock(unsigned int* lock); 50 void _release_lock(unsigned int* lock); 48 void _it_mask(void); 49 void _it_enable(void); 50 51 unsigned int _get_epc(void); 52 unsigned int _get_ptpr(void); 53 unsigned int _get_bvar(void); 54 unsigned int _get_cr(void); 55 unsigned int _get_sched(void); 56 57 unsigned int _get_current_context_slot(unsigned int index); 58 unsigned int _get_interrupt_vector_entry(unsigned int index); 59 unsigned int _get_current_task_id(void); 60 unsigned int _get_tasks_number(void); 61 62 void _set_current_task_id( unsigned int value); 63 64 void _get_lock(unsigned int* lock); 65 void _release_lock(unsigned int* lock); 51 66 52 67 mapping_cluster_t* _get_cluster_base( mapping_header_t* header ); -
soft/giet_vm/sys/ctx_handler.c
r167 r189 1 /////////////////////////////////////////////////////////////////////////////////// 1 /////////////////////////////////////////////////////////////////////////////////////// 2 2 // File : ctx_handler.c 3 3 // Date : 01/04/2012 4 4 // Authors : alain greiner & joel porquet 5 5 // Copyright (c) UPMC-LIP6 6 //////////////////////////////////////////////////////////////////////////////////// 7 // The ctx_handler.h and ctx_handler.c files are part of the GIET nano-kernel.6 /////////////////////////////////////////////////////////////////////////////////////// 7 // The ctx_handler.h and ctx_handler.c files are part of the GIET-VM nano-kernel. 8 8 // This code is used to support context switch when several tasks are executing 9 9 // in time multiplexing on a single processor. 10 10 // The tasks must be statically allocated to a processor in the boot phase, and 11 // there is one private scheduler per processor: NB_CLUSTERS * NB_PROCS 12 // Each sheduler contains up to NB_TASKS_MAX contexts. 13 //////////////////////////////////////////////////////////////////////////////////// 14 // A task context is an array of 64 words = 256 bytes. 15 // It contains copies of processor registers, when the task is not running, 16 // and some general informations associated to the task. 17 // 18 // - It contains GPR[i], generally stored in slot (i). $0, *26 & $27 are not saved. 19 // - It contains HI & LO registers. 20 // - It contains CP0 registers: EPC, SR, CR. 21 // - It contains CP2 registers : PTPR and MODE. 22 // - It contains the TTY global index, the FBDMA global index, the virtual base 23 // address of the page table (PTAB), and the task global index (TASK). 24 // 25 // ctx[0]<- SR|ctx[8] <- $8 |ctx[16]<- $16|ctx[24]<- $24|ctx[32]<- EPC |ctx[40]<- TTY 26 // ctx[1]<- $1|ctx[9] <- $9 |ctx[17]<- $17|ctx[25]<- $25|ctx[33]<- CR |ctx[41]<- FBDMA 27 // ctx[2]<- $2|ctx[10]<- $10|ctx[18]<- $18|ctx[26]<- LO |ctx[34]<- *** |ctx[42]<- PTAB 28 // ctx[3]<- $3|ctx[11]<- $11|ctx[19]<- $19|ctx[27]<- HI |ctx[35]<- PTPR|ctx[43]<- TASK 29 // ctx[4]<- $4|ctx[12]<- $12|ctx[20]<- $20|ctx[28]<- $28|ctx[36]<- MODE|ctx[44]<- *** 30 // ctx[5]<- $5|ctx[13]<- $13|ctx[21]<- $21|ctx[29]<- SP |ctx[37]<- *** |ctx[45]<- *** 31 // ctx[6]<- $6|ctx[14]<- $14|ctx[22]<- $22|ctx[30]<- $30|ctx[38]<- *** |ctx[46]<- *** 32 // ctx[7]<- $7|ctx[15]<- $15|ctx[23]<- $23|ctx[31]<- RA |ctx[39]<- *** |ctx[47]<- *** 33 ///////////////////////////////////////////////////////////////////////////////////// 11 // there is one private scheduler per processor. 12 // Each sheduler contains up to 15 task contexts. 13 /////////////////////////////////////////////////////////////////////////////////////// 34 14 35 15 #include <giet_config.h> … … 40 20 #include <sys_handler.h> 41 21 42 extern void _task_switch(unsigned int *, unsigned int *); 43 44 ///////////////////////////////////////////////////////////////////////////////// 45 // Global variables : array of schedulers (one scheduler per processor) 46 ///////////////////////////////////////////////////////////////////////////////// 47 48 __attribute__((section (".kdata"))) static_scheduler_t _scheduler[NB_CLUSTERS * NB_PROCS]; 22 /////////////////////////////////////////////////////////////////////////////////////// 23 // A task context is an array of 64 words = 256 bytes. 24 // It contains copies of processor registers (when the task is preempted), 25 // and some general informations associated to the task. 26 // 27 // - It contains GPR[i], generally stored in slot (i). $0, *26 & $27 are not saved. 28 // - It contains HI & LO registers. 29 // - It contains CP0 registers: EPC, SR, CR, SCHED 30 // - It contains CP2 registers : PTPR and MODE. 31 // - It contains TTY global index, the FBDMA global index, the virtual base 32 // address of the page table (PTAB), and the task global index (TASK). 33 // 34 // ctx[0]<- SR|ctx[8] <- $8 |ctx[16]<- $16|ctx[24]<- $24|ctx[32]<- EPC |ctx[40]<- TTY 35 // ctx[1]<- $1|ctx[9] <- $9 |ctx[17]<- $17|ctx[25]<- $25|ctx[33]<- CR |ctx[41]<- FBDMA 36 // ctx[2]<- $2|ctx[10]<- $10|ctx[18]<- $18|ctx[26]<- LO |ctx[34]<- *** |ctx[42]<- PTAB 37 // ctx[3]<- $3|ctx[11]<- $11|ctx[19]<- $19|ctx[27]<- HI |ctx[35]<- PTPR|ctx[43]<- TASK 38 // ctx[4]<- $4|ctx[12]<- $12|ctx[20]<- $20|ctx[28]<- $28|ctx[36]<- MODE|ctx[44]<- SCHED 39 // ctx[5]<- $5|ctx[13]<- $13|ctx[21]<- $21|ctx[29]<- SP |ctx[37]<- *** |ctx[45]<- TIMER 40 // ctx[6]<- $6|ctx[14]<- $14|ctx[22]<- $22|ctx[30]<- $30|ctx[38]<- *** |ctx[46]<- *** 41 // ctx[7]<- $7|ctx[15]<- $15|ctx[23]<- $23|ctx[31]<- RA |ctx[39]<- *** |ctx[47]<- *** 42 //////////////////////////////////////////////////////////////////////////////////////// 43 44 extern void _task_switch(unsigned int*, unsigned int*); 49 45 50 46 ///////////////////////////////////////////////////////////////////////////////// … … 52 48 // This function performs a context switch between the running task 53 49 // and another task, using a round-robin sheduling policy. 54 // It use the global variable scheduler[] : array indexed by the procid, 55 // that contains NB_CLUSTERS * NB_PROCS entries. 56 // The return address contained in $31 is saved in the _current task context 50 // 51 // It desactivate the DTLB, to directly access the scheduler using 52 // the physical address stored in register CP0_SCHED. 53 // All the context switch procedure is executed with interrupts masked. 54 // 55 // The return address contained in $31 is saved in the current task context 57 56 // (in the ctx[31] slot), and the function actually returns to the address 58 // contained in the ctx[31] slot of the new task context. To perform the 59 // actual switch, it calls the _task_switch function written in assembly language. 57 // contained in the ctx[31] slot of the next task context. 60 58 ///////////////////////////////////////////////////////////////////////////////// 61 59 void _ctx_switch() 62 60 { 63 unsigned char curr_task_id; 64 unsigned char next_task_id; 65 66 unsigned int *curr_context; 67 unsigned int *next_context; 68 69 unsigned int proc_id = _procid(); 70 unsigned int tasks = _scheduler[proc_id].tasks; 71 72 // return if only one task */ 73 if ( tasks <= 1) return; 74 75 // compute the task context base address for the current task 76 curr_task_id = _scheduler[proc_id].current; 77 curr_context = &(_scheduler[proc_id].context[curr_task_id][0]); 61 unsigned int tasks; 62 unsigned int curr_task_id; 63 unsigned int next_task_id; 64 unsigned int *curr_ctx_paddr; 65 unsigned int *next_ctx_paddr; 66 67 // get scheduler physical address 68 static_scheduler_t* psched = (static_scheduler_t*)_get_sched(); 69 70 // get number of tasks allocated to scheduler 71 tasks = _get_tasks_number(); 72 73 // no switch if only one task 74 if ( tasks > 1) 75 { 76 // compute the context physical address for the current task 77 curr_task_id = _get_current_task_id(); 78 curr_ctx_paddr = &(psched->context[curr_task_id][0]); 78 79 79 // select the next task using a round-robin schedulingpolicy80 next_task_id = (curr_task_id + 1) % tasks;80 // select the next task using a round-robin policy 81 next_task_id = (curr_task_id + 1) % tasks; 81 82 82 // compute the task context base address for the next task 83 next_context = &(_scheduler[proc_id].context[next_task_id][0]); 83 // compute the context physical address for the next task 84 next_ctx_paddr = &(psched->context[next_task_id][0]); 85 86 // update the scheduler state 87 _set_current_task_id( next_task_id ); 84 88 85 89 #if GIET_DEBUG_SWITCH 86 90 _get_lock( &_tty_put_lock ); 87 91 _puts( "\n[GIET] Context switch for processor "); 88 _putw( proc_id);92 _putw( _procid() ); 89 93 _puts( " at cycle "); 90 94 _putw( _proctime() ); … … 102 106 #endif 103 107 104 // update the scheduler state, and makes the task switch 105 _scheduler[proc_id].current = next_task_id; 106 _task_switch( curr_context, next_context ); 107 108 // makes the task switch 109 _task_switch( curr_ctx_paddr, next_ctx_paddr ); 110 111 /* 112 asm volatile( "ori $27, $0, 0xB \n" 113 "mtc2 $27, $1 \n" // desactivate DTLB 114 115 "add $27, %0, $0 \n" // $27 <= &curr_ctx 116 117 "mfc0 $26, $12 \n" // $26 <= SR 118 "sw $26, 0*4($27) \n" // ctx[0] <= SR 119 ".set noat \n" 120 "sw $1, 1*4($27) \n" // ctx[1] <= $1 121 ".set at \n" 122 "sw $2, 2*4($27) \n" // ctx[2] <= $2 123 "sw $3, 3*4($27) \n" // ctx[3] <= $3 124 "sw $4, 4*4($27) \n" // ctx[4] <= $4 125 "sw $5, 5*4($27) \n" // ctx[5] <= $5 126 "sw $6, 6*4($27) \n" // ctx[6] <= $6 127 "sw $7, 7*4($27) \n" // ctx[7] <= $7 128 "sw $8, 8*4($27) \n" // ctx[8] <= $8 129 "sw $9, 9*4($27) \n" // ctx[9] <= $9 130 "sw $10, 10*4($27) \n" // ctx[10] <= $10 131 "sw $11, 11*4($27) \n" // ctx[11] <= $11 132 "sw $12, 12*4($27) \n" // ctx[12] <= $12 133 "sw $13, 13*4($27) \n" // ctx[13] <= $13 134 "sw $14, 14*4($27) \n" // ctx[14] <= $14 135 "sw $15, 15*4($27) \n" // ctx[15] <= $15 136 "sw $16, 16*4($27) \n" // ctx[16] <= $16 137 "sw $17, 17*4($27) \n" // ctx[17] <= $17 138 "sw $18, 18*4($27) \n" // ctx[18] <= $18 139 "sw $19, 19*4($27) \n" // ctx[19] <= $19 140 "sw $20, 20*4($27) \n" // ctx[20] <= $20 141 "sw $21, 21*4($27) \n" // ctx[21] <= $21 142 "sw $22, 22*4($27) \n" // ctx[22] <= $22 143 "sw $23, 23*4($27) \n" // ctx[23] <= $23 144 "sw $24, 24*4($27) \n" // ctx[24] <= $24 145 "sw $25, 25*4($27) \n" // ctx[25] <= $25 146 "mflo $26 \n" 147 "sw $26, 26*4($27) \n" // ctx[26] <= LO 148 "mfhi $26 \n" 149 "sw $26, 27*4($27) \n" // ctx[27] <= H1 150 "sw $28, 28*4($27) \n" // ctx[28] <= $28 151 "sw $29, 29*4($27) \n" // ctx[29] <= $29 152 "sw $30, 30*4($27) \n" // ctx[30] <= $30 153 "sw $31, 31*4($27) \n" // ctx[31] <= $31 154 "mfc0 $26, $14 \n" 155 "sw $26, 32*4($27) \n" // ctx[32] <= EPC 156 "mfc0 $26, $13 \n" 157 "sw $26, 33*4($27) \n" // ctx[33] <= CR 158 "mfc2 $26, $0 \n" 159 "sw $26, 35*4($27) \n" // ctx[35] <= PTPR 160 161 "add $27, %1, $0 \n" // $27<= &next_ctx 162 163 "lw $26, 35*4($27) \n" 164 "mtc2 $26, $0 \n" // restore PTPR 165 "lw $26, 0*4($27) \n" 166 "mtc0 $26, $12 \n" // restore SR 167 ".set noat \n" 168 "lw $1, 1*4($27) \n" // restore $1 169 ".set at \n" 170 "lw $2, 2*4($27) \n" // restore $2 171 "lw $3, 3*4($27) \n" // restore $3 172 "lw $4, 4*4($27) \n" // restore $4 173 "lw $5, 5*4($27) \n" // restore $5 174 "lw $6, 6*4($27) \n" // restore $6 175 "lw $7, 7*4($27) \n" // restore $7 176 "lw $8, 8*4($27) \n" // restore $8 177 "lw $9, 9*4($27) \n" // restore $9 178 "lw $10, 10*4($27) \n" // restore $10 179 "lw $11, 11*4($27) \n" // restore $11 180 "lw $12, 12*4($27) \n" // restore $12 181 "lw $13, 13*4($27) \n" // restore $13 182 "lw $14, 14*4($27) \n" // restore $14 183 "lw $15, 15*4($27) \n" // restore $15 184 "lw $16, 16*4($27) \n" // restore $16 185 "lw $17, 17*4($27) \n" // restore $17 186 "lw $18, 18*4($27) \n" // restore $18 187 "lw $19, 19*4($27) \n" // restore $19 188 "lw $20, 20*4($27) \n" // restore $20 189 "lw $21, 21*4($27) \n" // restore $21 190 "lw $22, 22*4($27) \n" // restore $22 191 "lw $23, 23*4($27) \n" // restore $23 192 "lw $24, 24*4($27) \n" // restore $24 193 "lw $25, 25*4($27) \n" // restore $25 194 "lw $26, 26*4($27) \n" 195 "mtlo $26 \n" // restore LO 196 "lw $26, 27*4($27) \n" 197 "mthi $26 \n" // restore HI 198 "lw $28, 28*4($27) \n" // restore $28 199 "lw $29, 29*4($27) \n" // restore $29 200 "lw $30, 30*4($27) \n" // restore $30 201 "lw $31, 31*4($27) \n" // restore $31 202 "lw $26, 32*4($27) \n" 203 "mtc0 $26, $14 \n" // restore EPC 204 "lw $26, 33*4($27) \n" 205 "mtc0 $26, $13 \n" // restore CR 206 207 "ori $27, $0, 0xF \n" 208 "mtc2 $27, $1 \n" // activate DTLB 209 : 210 : "r"(curr_ctx_paddr), "r"(next_ctx_paddr) 211 : "$1" , "$4" ,"$5" ,"$6" ,"$7" ,"$8" ,"$9" ,"$10", 212 "$11","$12","$13","$14","$15","$16","$17","$18","$19","$20", 213 "$21","$22","$23","$24","$25","$26","$27", "$29", 214 "$31" ); 215 */ 216 } 108 217 } // end _ctx_switch 109 218 -
soft/giet_vm/sys/ctx_handler.h
r167 r189 10 10 typedef struct static_scheduler_s 11 11 { 12 unsigned int context[GIET_NB_TASKS_MAX][64]; // task contexts 13 unsigned int tasks; // actual number of tasks 14 unsigned int current; // current task index 12 unsigned int context[15][64]; // at most 15 task contexts 13 unsigned int tasks; // actual number of tasks 14 unsigned int current; // current task index 15 unsigned int interrupt_vector[32]; // interrupt vector 15 16 } static_scheduler_t; 16 17 … … 32 33 #define CTX_PTAB_ID 42 33 34 #define CTX_TASK_ID 43 34 35 #define CTX_SCHED_ID 44 36 #define CTX_TIMER_ID 45 35 37 36 38 ////////////////////////////////////////////////////////////////////////////////// -
soft/giet_vm/sys/drivers.c
r169 r189 5 5 // Copyright (c) UPMC-LIP6 6 6 /////////////////////////////////////////////////////////////////////////////////// 7 // The drivers.c and drivers.h files are part ot the GIET nano kernel.7 // The drivers.c and drivers.h files are part ot the GIET-VM nano kernel. 8 8 // They contains the drivers for the peripherals available in the SoCLib library: 9 9 // - vci_multi_tty … … 11 11 // - vci_multi_dma 12 12 // - vci_multi_icu 13 // - vci_xicu 13 14 // - vci_gcd 14 15 // - vci_frame_buffer … … 16 17 // 17 18 // The following global parameters must be defined in the giet_config.h file: 18 // - NB_CLUSTERS : number of clusters 19 // - NB_PROCS : number of PROCS per cluster 20 // - NB_TIMERS : number of TIMERS per cluster 21 // - NB_DMAS : number of DMA channels 22 // - NB_TTYS : number of TTY terminals 23 // - NB_TIMERS : number of TIMERS per cluster 24 // - CLUSTER_SPAN : address increment between clusters 19 // - NB_CLUSTERS 20 // - NB_PROCS_MAX 21 // - NB_TIMERS_MAX 22 // - NB_DMAS_MAX 23 // - NB_TTYS 25 24 // 26 25 // The following base addresses must be defined in the sys.ld file: … … 43 42 #include <ctx_handler.h> 44 43 45 #if !defined(NB_PROCS)46 # error: You must define NB_PROCS in 'giet_config.h' file!47 #endif48 44 #if !defined(NB_CLUSTERS) 49 # error: You must define NB_CLUSTERS in 'giet_config.h' file! 50 #endif 45 # error: You must define NB_CLUSTERS in 'giet_config.h' file 46 #endif 47 48 #if !defined(NB_PROCS_MAX) 49 # error: You must define NB_PROCS_MAX in 'giet_config.h' file 50 #endif 51 52 #if (NB_PROCS_MAX > 8) 53 # error: NB_PROCS_MAX cannot be larger than 8! 54 #endif 55 51 56 #if !defined(CLUSTER_SPAN) 52 # error: You must define CLUSTER_SPAN in 'giet_config.h' file! 53 #endif 57 # error: You must define CLUSTER_SPAN in 'giet_config.h' file 58 #endif 59 54 60 #if !defined(NB_TTYS) 55 # error: You must define NB_TTYS in 'giet_config.h' file! 56 #endif 57 #if !defined(NB_DMAS) 58 # error: You must define NB_DMAS in 'giet_config.h' file! 59 #endif 60 #if !defined(NB_TIMERS) 61 # error: You must define NB_TIMERS in 'giet_config.h' file! 61 # error: You must define NB_TTYS in 'giet_config.h' file 62 62 #endif 63 63 … … 66 66 #endif 67 67 68 #if (NB_TIMERS < NB_PROCS) 69 # error: NB_TIMERS must be larger or equal to NB_PROCS! 70 #endif 71 72 #if (NB_PROCS > 8) 73 # error: NB_PROCS cannot be larger than 8! 74 #endif 75 76 #if (NB_DMAS < 1) 77 # error: NB_DMAS cannot be 0! 78 #endif 79 80 81 ///////////////////////////////////////////////////////////////////////////// 82 // Global (uncachable) variables 83 ///////////////////////////////////////////////////////////////////////////// 68 #if !defined(NB_DMAS_MAX) 69 # error: You must define NB_DMAS_MAX in 'giet_config.h' file 70 #endif 71 72 #if (NB_DMAS_MAX < 1) 73 # error: NB_DMAS_MAX cannot be 0! 74 #endif 75 76 #if !defined(NB_TIMERS_MAX) 77 # error: You must define NB_TIMERS_MAX in 'giet_config.h' file 78 #endif 79 80 #if ( (NB_TIMERS_MAX + NB_PROCS_MAX) > 32 ) 81 # error: NB_TIMERS_MAX + NB_PROCS_MAX cannot be larger than 32 82 #endif 83 84 #if !defined(NB_IOCS) 85 # error: You must define NB_IOCS in 'giet_config.h' file 86 #endif 87 88 #if ( NB_IOCS > 1 ) 89 # error: NB_IOCS cannot be larger than 1 90 #endif 91 84 92 85 93 #define in_unckdata __attribute__((section (".unckdata"))) 86 94 87 // IOC variables 88 in_unckdata volatile unsigned char _ioc_status = 0; 89 in_unckdata volatile unsigned char _ioc_done = 0; 90 in_unckdata unsigned int _ioc_lock = 0; 91 in_unckdata unsigned int _ioc_iommu_ix1 = 0; 92 in_unckdata unsigned int _ioc_iommu_npages; 93 94 // DMA variables 95 in_unckdata volatile unsigned int _dma_status[NB_DMAS]; 96 in_unckdata volatile unsigned char _dma_busy[NB_DMAS] = { [0 ... NB_DMAS-1] = 0 }; 97 in_unckdata volatile unsigned char _dma_iommu_ix1 = 1; 98 in_unckdata volatile unsigned char _dma_iommu_npages[NB_DMAS]; 95 96 ////////////////////////////////////////////////////////////////////////////// 97 // VciMultiTimer driver 98 ////////////////////////////////////////////////////////////////////////////// 99 // There is one multi_timer (or xicu) component per cluster. 100 // The global index is cluster_id*(NB_PROCS_MAX+NB_TIMERS_MAX) + local_id 101 // There is two types of timers: 102 // - "system" timers : one per processor, used for context switch. 103 // local_id in [0, NB_PROCS_MAX-1], 104 // - "user" timers : requested by the task in the mapping_info data structure. 105 // local_id in [NB_PROC_MAX, NB_PROCS_MAX+NB_TIMERS_MAX-1], 106 // For each user timer, the tty_id is stored in the context of the task 107 // and must be explicitely defined in the boot code. 108 // These timers can be implemented in a vci_multi_timer component 109 // or in a vci_xicu component (depending on the GIET_USE_XICU parameter). 110 ////////////////////////////////////////////////////////////////////////////// 111 112 // User Timer signaling variables 113 114 #if (NB_TIMERS_MAX > 0) 115 in_unckdata volatile unsigned char _user_timer_event[NB_CLUSTERS*NB_TIMERS_MAX] 116 = { [0 ... ((NB_CLUSTERS*NB_TIMERS_MAX)-1)] = 0 }; 117 #endif 118 119 ////////////////////////////////////////////////////////////////////////////// 120 // _timer_access() 121 // This function is the only way to access a timer device. 122 // It can be a multi-timer component or an xicu component. 123 // It can be used by the kernel to initialise a "system" timer, 124 // or by a task (through a system call) to configure an "user" timer. 125 // Returns 0 if success, > 0 if error. 126 ////////////////////////////////////////////////////////////////////////////// 127 unsigned int _timer_access( unsigned int read, 128 unsigned int cluster_id, 129 unsigned int local_id, 130 unsigned int register_id, 131 unsigned int* buffer ) 132 { 133 // parameters checking 134 if ( register_id >= TIMER_SPAN) return 1; 135 if ( cluster_id >= NB_CLUSTERS) return 1; 136 if ( local_id >= NB_TIMERS_MAX + NB_PROCS_MAX ) return 1; 137 138 #if GIET_USE_XICU 139 140 unsigned int* timer_address = //TODO 141 142 #else 143 144 unsigned int* timer_address = (unsigned int*)&seg_timer_base + 145 (cluster_id * CLUSTER_SPAN) + 146 (local_id * TIMER_SPAN); 147 #endif 148 149 if (read) *buffer = timer_address[register_id]; // read word 150 else timer_address[register_id] = *buffer; // write word 151 return 0; 152 } 153 ////////////////////////////////////////////////////////////////////////////// 154 // _timer_write() 155 // This function implements a write access to a "user" timer register. 156 // It gets the cluster_id and local_id from the global index stored in 157 // the task context and use the timer_access() function to make the write. 158 // Returns 0 if success, > 0 if error. 159 ////////////////////////////////////////////////////////////////////////////// 160 unsigned int _timer_write( unsigned int register_id, 161 unsigned int value ) 162 { 163 unsigned int buffer = value; 164 unsigned int timer_id = _get_current_context_slot(CTX_TIMER_ID); 165 unsigned int cluster_id = timer_id / (NB_PROCS_MAX + NB_TIMERS_MAX); 166 unsigned int local_id = timer_id % (NB_PROCS_MAX + NB_TIMERS_MAX); 167 168 // checking user timer 169 if ( local_id < NB_PROCS_MAX ) 170 { 171 return 2; 172 } 173 else 174 { 175 return _timer_access ( 0, // write access 176 cluster_id, 177 local_id, 178 register_id, 179 &buffer ); 180 } 181 } 182 ////////////////////////////////////////////////////////////////////////////// 183 // _timer_read() 184 // This function implements a read access to a "user" timer register. 185 // It gets the cluster_id and local_id from the global index stored in 186 // the task context and use the timer_access() function to make the read. 187 // Returns 0 if success, > 0 if error. 188 ////////////////////////////////////////////////////////////////////////////// 189 unsigned int _timer_read( unsigned int register_id, 190 unsigned int* buffer ) 191 { 192 unsigned int timer_id = _get_current_context_slot(CTX_TIMER_ID); 193 unsigned int cluster_id = timer_id / (NB_PROCS_MAX + NB_TIMERS_MAX); 194 unsigned int local_id = timer_id % (NB_PROCS_MAX + NB_TIMERS_MAX); 195 196 // checking user timer 197 if ( local_id < NB_PROCS_MAX ) 198 { 199 return 2; 200 } 201 else 202 { 203 return _timer_access ( 1, // read access 204 cluster_id, 205 local_id, 206 register_id, 207 buffer ); 208 } 209 } 210 ///////////////////////////////////////////////////////////////////////////////// 211 // _timer_check() 212 ///////////////////////////////////////////////////////////////////////////////// 213 214 ///////////////////////////////////////////////////////////////////////////////// 215 // VciMultiTty driver 216 ///////////////////////////////////////////////////////////////////////////////// 217 // There is only one multi_tty controler in the architecture. 218 // The total number of TTYs is defined by the configuration parameter NB_TTYS. 219 // The "system" terminal is TTY[0]. 220 // The "user" TTYs are allocated to applications by the GIET in the boot phase, 221 // as defined in the mapping_info data structure. The corresponding tty_id must 222 // be stored in the context of the task by the boot code. 223 // The TTY address is : seg_tty_base + tty_id*TTY_SPAN 224 ///////////////////////////////////////////////////////////////////////////////// 99 225 100 226 // TTY variables 101 227 in_unckdata volatile unsigned char _tty_get_buf[NB_TTYS]; 102 228 in_unckdata volatile unsigned char _tty_get_full[NB_TTYS] = { [0 ... NB_TTYS-1] = 0 }; 103 in_unckdata unsigned int _tty_put_lock = 0; 104 105 ////////////////////////////////////////////////////////////////////////////// 106 // VciMultiTimer driver 107 ////////////////////////////////////////////////////////////////////////////// 108 // There is one MULTI-TIMER component per cluster. 109 // The number of timers per cluster must be larger or equal to the number 110 // processors (NB_TIMERS >= NB_PROCS), because each processor uses a private 111 // yimer for context switch. 112 // The total number of timers is NB_CLUSTERS * NB_TIMERS 113 // The global timer index = cluster_id*NB_TIMERS + timer_id 114 ////////////////////////////////////////////////////////////////////////////// 115 116 ////////////////////////////////////////////////////////////////////////////// 117 // _timer_write() 118 // 119 // Write a 32-bit word in a memory mapped register of a timer device, 120 // identified by the cluster index and the local timer index. 121 // Returns 0 if success, > 0 if error. 122 ////////////////////////////////////////////////////////////////////////////// 123 unsigned int _timer_write( unsigned int cluster_index, 124 unsigned int timer_index, 125 unsigned int register_index, 126 unsigned int value ) 127 { 128 unsigned int* timer_address; 129 130 // parameters checking 131 if ( register_index >= TIMER_SPAN) return 1; 132 if ( cluster_index >= NB_CLUSTERS) return 1; 133 if ( timer_index >= NB_TIMERS ) return 1; 134 135 timer_address = (unsigned int*)&seg_timer_base + 136 ( cluster_index * CLUSTER_SPAN ) + 137 ( timer_index * TIMER_SPAN ); 138 139 timer_address[register_index] = value; // write word 140 141 return 0; 142 } 143 144 ////////////////////////////////////////////////////////////////////////////// 145 // _timer_read() 146 // 147 // Read a 32-bit word in a memory mapped register of a timer device, 148 // identified by the cluster index and the local timer index. 149 // Returns 0 if success, > 0 if error. 150 ////////////////////////////////////////////////////////////////////////////// 151 unsigned int _timer_read(unsigned int cluster_index, 152 unsigned int timer_index, 153 unsigned int register_index, 154 unsigned int *buffer) 155 { 156 unsigned int *timer_address; 157 158 // parameters checking 159 if ( register_index >= TIMER_SPAN) return 1; 160 if ( cluster_index >= NB_CLUSTERS) return 1; 161 if ( timer_index >= NB_TIMERS ) return 1; 162 163 timer_address = (unsigned int*)&seg_timer_base + 164 ( cluster_index * CLUSTER_SPAN ) + 165 ( timer_index * TIMER_SPAN ); 166 167 *buffer = timer_address[register_index]; // read word 168 169 return 0; 170 } 171 229 in_unckdata unsigned int _tty_put_lock = 0; // protect kernel TTY[0] 230 231 //////////////////////////////////////////////////////////////////////////////// 232 // _tty_error() 233 //////////////////////////////////////////////////////////////////////////////// 234 void _tty_error() 235 { 236 unsigned int task_id = _get_current_task_id(); 237 unsigned int proc_id = _procid(); 238 239 _get_lock(&_tty_put_lock); 240 _puts("\n[GIET ERROR] TTY index too large for task "); 241 _putw( task_id ); 242 _puts(" on processor "); 243 _putw( proc_id ); 244 _puts("\n"); 245 _release_lock(&_tty_put_lock); 246 } 172 247 ///////////////////////////////////////////////////////////////////////////////// 173 // VciMultiTty driver 174 ///////////////////////////////////////////////////////////////////////////////// 175 // The total number of TTYs is defined by the configuration parameter NB_TTYS. 176 // The system terminal is TTY[0]. 177 // The TTYs are allocated to applications by the GIET in the boot phase. 178 // The nummber of TTYs allocated to each application, and used by each 179 // task can be defined in the mapping_info data structure. 180 // For each user task, the tty_id is stored in the context of the task (slot 34), 181 // and must be explicitely defined in the boot code. 182 // The TTY address is always computed as : seg_tty_base + tty_id*TTY_SPAN 183 /////////////////////////////////////////////////////////////////////////////////// 184 185 ////////////////////////////////////////////////////////////////////////////// 186 // _tty_write() 187 // 248 // _tty_write() 188 249 // Write one or several characters directly from a fixed-length user buffer to 189 250 // the TTY_WRITE register of the TTY controler. … … 192 253 // the transfer as soon as the TTY_STATUS[WRITE] bit is set. 193 254 // The function returns the number of characters that have been written. 194 ////////////////////////////////////////////////////////////////////////////// 255 ///////////////////////////////////////////////////////////////////////////////// 195 256 unsigned int _tty_write( const char *buffer, 196 257 unsigned int length) 197 258 { 198 volatile unsigned int *tty_address; 199 200 unsigned int proc_id; 201 unsigned int task_id; 202 unsigned int tty_id; 203 unsigned int nwritten; 204 205 proc_id = _procid(); 206 207 task_id = _scheduler[proc_id].current; 208 tty_id = _scheduler[proc_id].context[task_id][CTX_TTY_ID]; 209 210 tty_address = (unsigned int*)&seg_tty_base + tty_id*TTY_SPAN; 259 unsigned int nwritten; 260 261 unsigned int tty_id = _get_current_context_slot(CTX_TTY_ID); 262 if ( tty_id >= NB_TTYS ) 263 { 264 _tty_error(); 265 return 0; 266 } 267 268 unsigned int* tty_address = (unsigned int*)&seg_tty_base + tty_id*TTY_SPAN; 211 269 212 270 for (nwritten = 0; nwritten < length; nwritten++) … … 221 279 return nwritten; 222 280 } 223 224 281 ////////////////////////////////////////////////////////////////////////////// 225 // _tty_read_irq() 226 // 282 // _tty_read_irq() 227 283 // This non-blocking function uses the TTY_GET_IRQ[tty_id] interrupt and 228 284 // the associated kernel buffer, that has been written by the ISR. … … 235 291 unsigned int length) 236 292 { 237 unsigned int proc_id; 238 unsigned int task_id; 239 unsigned int tty_id; 240 unsigned int ret; 241 242 proc_id = _procid(); 243 task_id = _scheduler[proc_id].current; 244 tty_id = _scheduler[proc_id].context[task_id][CTX_TTY_ID]; 293 unsigned int tty_id = _get_current_context_slot(CTX_TTY_ID); 294 295 if ( tty_id >= NB_TTYS ) 296 { 297 _tty_error(); 298 return 0; 299 } 245 300 246 301 if (_tty_get_full[tty_id] == 0) 247 302 { 248 ret =0;303 return 0; 249 304 } 250 305 else … … 252 307 *buffer = _tty_get_buf[tty_id]; 253 308 _tty_get_full[tty_id] = 0; 254 ret = 1; 255 } 256 return ret; 257 } 258 259 //////////////////////////////////////////////////////////////////////////////// 260 // _tty_read() 261 // 309 return 1; 310 } 311 } 312 //////////////////////////////////////////////////////////////////////////////// 313 // _tty_read() 262 314 // This non-blocking function fetches one character directly from the TTY_READ 263 315 // register of the TTY controler, and writes this character to the user buffer. … … 268 320 unsigned int length) 269 321 { 270 volatile unsigned int *tty_address; 271 272 unsigned int proc_id; 273 unsigned int task_id; 274 unsigned int tty_id; 275 276 proc_id = _procid(); 277 task_id = _scheduler[proc_id].current; 278 tty_id = _scheduler[proc_id].context[task_id][CTX_TTY_ID]; 279 280 tty_address = (unsigned int*)&seg_tty_base + tty_id*TTY_SPAN; 281 282 if ((tty_address[TTY_STATUS] & 0x1) != 0x1) return 0; 283 284 *buffer = (char)tty_address[TTY_READ]; 285 return 1; 286 } 287 288 //////////////////////////////////////////////////////////////////////////////// 289 // VciMultiIcu driver 290 //////////////////////////////////////////////////////////////////////////////// 291 // There is in principle one MULTI-ICU component per cluster, and the 292 // number of independant ICUs is equal to NB_PROCS, because there is 293 // one ICU per processor. 294 //////////////////////////////////////////////////////////////////////////////// 295 296 //////////////////////////////////////////////////////////////////////////////// 297 // _icu_write() 298 // 322 unsigned int tty_id = _get_current_context_slot(CTX_TTY_ID); 323 if ( tty_id >= NB_TTYS ) 324 { 325 _tty_error(); 326 return 0; 327 } 328 329 unsigned int* tty_address = (unsigned int*)&seg_tty_base + tty_id*TTY_SPAN; 330 331 if ((tty_address[TTY_STATUS] & 0x1) != 0x1) 332 { 333 return 0; 334 } 335 else 336 { 337 *buffer = (char)tty_address[TTY_READ]; 338 return 1; 339 } 340 } 341 342 //////////////////////////////////////////////////////////////////////////////// 343 // VciMultiIcu and VciXicu drivers 344 //////////////////////////////////////////////////////////////////////////////// 345 // There is in principle one vci_multi_icu (or vci_xicu) component per cluster, 346 // and the number of independant ICUs is equal to NB_PROCS_MAX, because there is 347 // one private interrupr controler per processor. 348 //////////////////////////////////////////////////////////////////////////////// 349 350 //////////////////////////////////////////////////////////////////////////////// 351 // _icu_write() 299 352 // Write a 32-bit word in a memory mapped register of the MULTI_ICU device, 300 353 // identified by the cluster index, and a processor local index. … … 306 359 unsigned int value ) 307 360 { 308 unsigned int *icu_address; 361 #if GIET_USE_XICU 362 363 #else 309 364 310 365 // parameters checking 311 366 if ( register_index >= ICU_SPAN) return 1; 312 367 if ( cluster_index >= NB_CLUSTERS) return 1; 313 if ( proc_index >= NB_PROCS )return 1;314 315 icu_address = (unsigned int*)&seg_icu_base +316 ( cluster_index * CLUSTER_SPAN) +317 ( proc_index * ICU_SPAN);368 if ( proc_index >= NB_PROCS_MAX ) return 1; 369 370 unsigned int *icu_address = (unsigned int*)&seg_icu_base + 371 (cluster_index * CLUSTER_SPAN) + 372 (proc_index * ICU_SPAN); 318 373 319 374 icu_address[register_index] = value; // write word 320 375 return 0; 321 } 322 323 //////////////////////////////////////////////////////////////////////////////// 324 // _icu_read()325 // 376 377 #endif 378 } 379 //////////////////////////////////////////////////////////////////////////////// 380 // _icu_read() 326 381 // Read a 32-bit word in a memory mapped register of the MULTI_ICU device, 327 382 // identified by the cluster index and a processor local index. … … 333 388 unsigned int* buffer ) 334 389 { 335 unsigned int *icu_address; 390 #if GIET_USE_XICU 391 392 #else 336 393 337 394 // parameters checking 338 395 if ( register_index >= ICU_SPAN) return 1; 339 396 if ( cluster_index >= NB_CLUSTERS) return 1; 340 if ( proc_index >= NB_PROCS )return 1;341 342 icu_address = (unsigned int*)&seg_icu_base +343 ( cluster_index * CLUSTER_SPAN) +344 ( proc_index * ICU_SPAN);397 if ( proc_index >= NB_PROCS_MAX ) return 1; 398 399 unsigned int *icu_address = (unsigned int*)&seg_icu_base + 400 (cluster_index * CLUSTER_SPAN) + 401 (proc_index * ICU_SPAN); 345 402 346 403 *buffer = icu_address[register_index]; // read word 347 404 return 0; 405 406 #endif 348 407 } 349 408 … … 357 416 358 417 //////////////////////////////////////////////////////////////////////////////// 359 // _gcd_write() 360 // 418 // _gcd_write() 361 419 // Write a 32-bit word in a memory mapped register of the GCD coprocessor. 362 420 // Returns 0 if success, > 0 if error. … … 376 434 return 0; 377 435 } 378 379 //////////////////////////////////////////////////////////////////////////////// 380 // _gcd_read() 381 // 436 //////////////////////////////////////////////////////////////////////////////// 437 // _gcd_read() 382 438 // Read a 32-bit word in a memory mapped register of the GCD coprocessor. 383 439 // Returns 0 if success, > 0 if error. … … 448 504 /////////////////////////////////////////////////////////////////////////////// 449 505 506 // IOC global variables 507 in_unckdata volatile unsigned int _ioc_status = 0; 508 in_unckdata volatile unsigned int _ioc_done = 0; 509 in_unckdata unsigned int _ioc_lock = 0; 510 in_unckdata unsigned int _ioc_iommu_ix1 = 0; 511 in_unckdata unsigned int _ioc_iommu_npages; 512 450 513 /////////////////////////////////////////////////////////////////////////////// 451 // _ioc_get_lock() 452 // 453 // This blocking helper is used by '_ioc_read()' and '_ioc_write()' functions 454 // to get _ioc_lock using atomic LL/SC. 455 /////////////////////////////////////////////////////////////////////////////// 456 static inline void _ioc_get_lock() 457 { 458 register unsigned int delay = (_proctime() & 0xF) << 4; 459 register unsigned int *plock = (unsigned int*)&_ioc_lock; 460 461 asm volatile ( 462 "_ioc_llsc: \n" 463 "ll $2, 0(%0) \n" /* $2 <= _ioc_lock current value */ 464 "bnez $2, _ioc_delay \n" /* delay if _ioc_lock already taken */ 465 "li $3, 1 \n" /* $3 <= argument for sc */ 466 "sc $3, 0(%0) \n" /* try to set _ioc_lock */ 467 "bnez $3, _ioc_ok \n" /* exit if atomic */ 468 "_ioc_delay: \n" 469 "move $4, %1 \n" /* $4 <= delay */ 470 "_ioc_loop: \n" 471 "beqz $4, _ioc_loop \n" /* test end delay */ 472 "addi $4, $4, -1 \n" /* $4 <= $4 - 1 */ 473 "j _ioc_llsc \n" /* retry ll */ 474 "nop \n" 475 "_ioc_ok: \n" 476 : 477 :"r"(plock), "r"(delay) 478 :"$2", "$3", "$4"); 479 } 480 481 /////////////////////////////////////////////////////////////////////////////// 482 // _ioc_access() 514 // _ioc_access() 483 515 // This function transfer data between a memory buffer and the block device. 484 516 // The buffer lentgth is (count*block_size) bytes. 485 //486 517 // Arguments are: 487 518 // - to_mem : from external storage to memory when non 0 … … 503 534 unsigned int ix2; // page index in IOMMU PT1 page table 504 535 unsigned int addr; // buffer address for IOC peripheral 505 unsigned int user_ptp; // page table pointer in user space506 unsigned int ko; // bool returned by _v2p_translate()507 536 unsigned int ppn_first; // first physical page number for user buffer 508 unsigned int ltid; // current task local index509 static_scheduler_t* psched; // pointer on the current task scheduler510 537 511 538 // check buffer alignment … … 517 544 518 545 // get user space page table virtual address 519 psched = &_scheduler[_procid()]; 520 ltid = psched->current; 521 user_ptp = psched->context[ltid][CTX_PTAB_ID]; 546 unsigned int user_pt_vbase = _get_current_context_slot(CTX_PTAB_ID); 522 547 523 548 user_vpn_min = user_vaddr >> 12; … … 529 554 { 530 555 // get ppn and flags for each vpn 531 ko = _v2p_translate( (page_table_t*)user_ptp,532 vpn,533 &ppn,534 &flags );556 unsigned int ko = _v2p_translate( (page_table_t*)user_pt_vbase, 557 vpn, 558 &ppn, 559 &flags ); 535 560 536 561 // check access rights … … 573 598 574 599 // get the lock on ioc device 575 _ ioc_get_lock();600 _get_lock( &_ioc_lock ); 576 601 577 602 // peripheral configuration … … 584 609 return 0; 585 610 } 586 587 611 ///////////////////////////////////////////////////////////////////////////////// 588 612 // _ioc_completed() … … 630 654 return ret; 631 655 } 632 633 656 /////////////////////////////////////////////////////////////////////////////// 634 // _ioc_read()657 // _ioc_read() 635 658 // Transfer data from the block device to a memory buffer in user space. 636 659 // - lba : first block index on the block device … … 643 666 unsigned int count ) 644 667 { 645 return _ioc_access( 1, // read 668 return _ioc_access( 1, // read access 646 669 lba, 647 670 (unsigned int)buffer, 648 671 count ); 649 672 } 650 651 673 /////////////////////////////////////////////////////////////////////////////// 652 // _ioc_write()674 // _ioc_write() 653 675 // Transfer data from a memory buffer in user space to the block device. 654 676 // - lba : first block index on the block device … … 661 683 unsigned int count ) 662 684 { 663 return _ioc_access( 0, // write 685 return _ioc_access( 0, // write access 664 686 lba, 665 687 (unsigned int)buffer, … … 668 690 669 691 ////////////////////////////////////////////////////////////////////////////////// 692 // VciMultiDma driver 693 ////////////////////////////////////////////////////////////////////////////////// 694 // The DMA controllers are physically distributed in the clusters. 695 // There is (NB_CLUSTERS * NB_DMAS_MAX) channels, indexed by a global index: 696 // dma_id = cluster_id * NB_DMA_MAX + loc_id 697 // 698 // As a DMA channel can be used by several tasks, each DMA channel is protected 699 // by a specific lock: _dma_lock[dma_id] 700 // The signalisation between the OS and the DMA uses the _dma_done[dma_id] 701 // synchronisation variables (set by the ISR, and reset by the OS). 702 // The transfer status is copied by the ISR in the _dma_status[dma_id] variables. 703 // 704 // These DMA channels can be used by the FB driver, or by the NIC driver. 705 ////////////////////////////////////////////////////////////////////////////////// 706 707 #if (NB_DMAS_MAX > 0) 708 in_unckdata unsigned int _dma_lock[NB_DMAS_MAX * NB_CLUSTERS] 709 = { [0 ... (NB_DMAS_MAX * NB_CLUSTERS)-1] = 0 }; 710 711 in_unckdata volatile unsigned int _dma_done[NB_DMAS_MAX * NB_CLUSTERS] 712 = { [0 ... (NB_DMAS_MAX * NB_CLUSTERS)-1] = 0 }; 713 714 in_unckdata volatile unsigned int _dma_status[NB_DMAS_MAX * NB_CLUSTERS]; 715 716 in_unckdata unsigned int _dma_iommu_ix1 = 1; 717 718 in_unckdata unsigned int _dma_iommu_npages[NB_DMAS_MAX * NB_CLUSTERS]; 719 #endif 720 721 ////////////////////////////////////////////////////////////////////////////////// 670 722 // VciFrameBuffer driver 671 723 ////////////////////////////////////////////////////////////////////////////////// 724 // The vci_frame_buffer device can be accessed directly by software with memcpy(), 725 // or it can be accessed through a multi-channels DMA component: 726 // 672 727 // The '_fb_sync_write' and '_fb_sync_read' functions use a memcpy strategy to 673 728 // implement the transfer between a data buffer (user space) and the frame … … 675 730 // 676 731 // The '_fb_write()', '_fb_read()' and '_fb_completed()' functions use the DMA 677 // coprocessor to transfer data between the user buffer and the frame buffer. 678 // These functions use a polling policy to test the global variables _dma_busy[i] 679 // and detect the transfer completion. 680 // There is NB_DMA channels, that are indexed by the dma_id stored in the 681 // task context. 682 // The _dma_busy[i] synchronisation variables (one per channel) are set by the OS, 683 // and reset by the DMA ISR. 732 // controlers (distributed in the clusters) to transfer data 733 // between the user buffer and the frame buffer. A DMA channel is 734 // allocated to each task requesting it in the mapping_info data structure. 684 735 ////////////////////////////////////////////////////////////////////////////////// 685 736 … … 697 748 unsigned int length ) 698 749 { 699 volatile unsigned char *fb_address;700 750 701 751 // buffer must be mapped in user space 702 752 if ( ((unsigned int)buffer + length ) >= 0x80000000 ) 753 { 703 754 return 1; 704 705 fb_address = (unsigned char*)&seg_fb_base + offset;706 707 // buffer copy708 memcpy((void*)fb_address, (void*)buffer, length);709 710 return 0;755 } 756 else 757 { 758 unsigned char *fb_address = (unsigned char*)&seg_fb_base + offset; 759 memcpy((void*)fb_address, (void*)buffer, length); 760 return 0; 761 } 711 762 } 712 763 … … 724 775 unsigned int length ) 725 776 { 726 volatile unsigned char *fb_address;727 728 777 // buffer must be mapped in user space 729 778 if ( ((unsigned int)buffer + length ) >= 0x80000000 ) 779 { 730 780 return 1; 731 732 fb_address = (unsigned char*)&seg_fb_base + offset;733 734 // buffer copy735 memcpy((void*)buffer, (void*)fb_address, length);736 737 return 0;738 } 739 740 ////////////////////////////////////////////////////////////////////////////////// 741 // _fb_ access()742 // Transfer data between a memory buffer and the frame_buffer deviceusing DMA.743 // - to_ mem : from frame buffer to memorywhen true.781 } 782 else 783 { 784 unsigned char *fb_address = (unsigned char*)&seg_fb_base + offset; 785 memcpy((void*)buffer, (void*)fb_address, length); 786 return 0; 787 } 788 } 789 790 ////////////////////////////////////////////////////////////////////////////////// 791 // _fb_dma_access() 792 // Transfer data between a user buffer and the frame_buffer using DMA. 793 // - to_user : from frame buffer to user buffer when true. 744 794 // - offset : offset (in bytes) in the frame buffer. 745 795 // - user_vaddr : virtual base address of the memory buffer. … … 747 797 // The memory buffer must be mapped in user address space and word-aligned. 748 798 // The user buffer length must be multiple of 4 bytes. 749 // Returns 0 if success, > 0 if error. 750 ////////////////////////////////////////////////////////////////////////////////// 751 unsigned int _fb_access( unsigned int to_mem, 752 unsigned int offset, 753 unsigned int user_vaddr, 754 unsigned int length ) 755 { 756 static_scheduler_t* psched; // pointer on the current task scheduler 757 unsigned char* fb_base; // frame buffer base address 758 unsigned int* dma_base; // dma component base address 759 unsigned int task_id; // task local index (for scheduler) 760 unsigned int dma_id; // DMA channel index 761 unsigned int vpn; // current virtual page number 762 unsigned int flags; // protection flags 763 unsigned int ppn; // current physical page number 764 unsigned int buf_base; // buffer base address for DMA access 765 unsigned int ppn_first; // first physical page index for user buffer 766 767 fb_base = (unsigned char*)&seg_fb_base + offset; 768 769 psched = &_scheduler[_procid()]; 770 task_id = psched->current; 771 dma_id = psched->context[task_id][CTX_FBDMA_ID]; 772 dma_base = (unsigned int*)&seg_dma_base + (dma_id * DMA_SPAN); 773 774 // check buffer address and ength alignment 775 if ( user_vaddr & 0x3 ) return 1; 776 if ( length & 0x3 ) return 1; 799 // Me must compute the physical base addresses for both the frame buffer 800 // and the user buffer before programming the DMA transfer. 801 // The GIET being fully static, we don't need to split the transfer in 4Kbytes 802 // pages, because the user buffer is contiguous in physical space. 803 // Returns 0 if success, > 0 if error. 804 ////////////////////////////////////////////////////////////////////////////////// 805 unsigned int _fb_dma_access( unsigned int to_user, 806 unsigned int offset, 807 unsigned int user_vaddr, 808 unsigned int length ) 809 { 810 unsigned int ko; // unsuccessfull V2P translation 811 unsigned int flags; // protection flags 812 unsigned int ppn; // physical page number 813 unsigned int user_pbase; // user buffer pbase address 814 unsigned int fb_pbase; // frame buffer pbase address 815 816 // get DMA channel and compute DMA vbase address 817 unsigned int dma_id = _get_current_context_slot(CTX_FBDMA_ID); 818 unsigned int cluster_id = dma_id / NB_DMAS_MAX; 819 unsigned int loc_id = dma_id % NB_DMAS_MAX; 820 unsigned int* dma_base = (unsigned int*)&seg_dma_base + 821 (cluster_id * CLUSTER_SPAN) + 822 (loc_id * DMA_SPAN); 823 824 // check user buffer address and length alignment 825 if ( (user_vaddr & 0x3) || (length & 0x3) ) 826 { 827 _puts("[GIET ERROR] in _fbdma_access() : user buffer not word aligned\n"); 828 return 1; 829 } 777 830 778 831 // get user space page table virtual address 779 unsigned int user_ptp = psched->context[task_id][CTX_PTAB_ID]; 780 832 unsigned int user_ptab = _get_current_context_slot(CTX_PTAB_ID); 833 834 // compute frame buffer pbase address 835 unsigned int fb_vaddr = (unsigned int)&seg_fb_base + offset; 836 837 ko = _v2p_translate( (page_table_t*)user_ptab, 838 (fb_vaddr >> 12), 839 &ppn, 840 &flags ); 841 fb_pbase = (ppn << 12) | (fb_vaddr & 0x00000FFF); 842 843 if ( ko ) 844 { 845 _puts("[GIET ERROR] in _fbdma_access() : frame buffer unmapped\n"); 846 return 2; 847 } 848 849 // Compute user buffer pbase address 850 ko = _v2p_translate( (page_table_t*)user_ptab, 851 (user_vaddr >> 12), 852 &ppn, 853 &flags ); 854 user_pbase = (ppn << 12) | (user_vaddr & 0x00000FFF); 855 856 if ( ko ) 857 { 858 _puts("[GIET ERROR] in _fbdma_access() : user buffer unmapped\n"); 859 return 3; 860 } 861 if ( (flags & PTE_U) == 0 ) 862 { 863 _puts("[GIET ERROR] in _fbdma_access() : user buffer not in user space\n"); 864 return 4; 865 } 866 if ( ( (flags & PTE_W) == 0 ) && to_user ) 867 { 868 _puts("[GIET ERROR] in _fbdma_access() : user buffer not writable\n"); 869 return 5; 870 } 871 872 873 874 /* 875 // loop on all virtual pages covering the user buffer 781 876 unsigned int user_vpn_min = user_vaddr >> 12; 782 877 unsigned int user_vpn_max = (user_vaddr + length - 1) >> 12; 783 878 unsigned int ix2 = 0; 784 879 unsigned int ix1 = _dma_iommu_ix1 + dma_id; 785 unsigned int ko; 786 unsigned int i; 787 788 // loop on all virtual pages covering the user buffer 880 789 881 for ( vpn = user_vpn_min ; vpn <= user_vpn_max ; vpn++ ) 790 882 { 791 883 // get ppn and flags for each vpn 792 ko = _v2p_translate( (page_table_t*)user_ptp,793 vpn,794 &ppn,795 &flags );884 unsigned int ko = _v2p_translate( (page_table_t*)user_pt_vbase, 885 vpn, 886 &ppn, 887 &flags ); 796 888 797 889 // check access rights 798 if ( ko ) return 2; // unmapped799 if ( (flags & PTE_U) == 0 ) return 3; // not in user space800 if ( ( (flags & PTE_W) == 0 ) && to_ mem ) return 4; // not writable890 if ( ko ) return 3; // unmapped 891 if ( (flags & PTE_U) == 0 ) return 4; // not in user space 892 if ( ( (flags & PTE_W) == 0 ) && to_user ) return 5; // not writable 801 893 802 894 // save first ppn value … … 816 908 else // no IOMMU : check that physical pages are contiguous 817 909 { 818 if ( (ppn - ppn_first) != ix2 ) return 5; // split physical buffer910 if ( (ppn - ppn_first) != ix2 ) return 6; // split physical buffer 819 911 } 820 912 … … 823 915 } // end for vpn 824 916 825 // register the number of pages to be unmapped 917 // register the number of pages to be unmapped if iommu activated 826 918 _dma_iommu_npages[dma_id] = (user_vpn_max - user_vpn_min) + 1; 827 919 920 */ 828 921 // invalidate data cache in case of memory write 829 if ( to_mem ) _dcache_buf_invalidate( (void*)user_vaddr, length ); 830 831 // compute buffer base address for DMA depending on IOMMU activation 832 if ( GIET_IOMMU_ACTIVE ) buf_base = ( ix1 ) << 21 | (user_vaddr & 0xFFF); 833 else buf_base = (ppn_first << 12) | (user_vaddr & 0xFFF); 834 835 836 // waiting until DMA device is available 837 while (_dma_busy[dma_id] != 0) 838 { 839 // busy wait with a pseudo random delay between bus access 840 unsigned int delay = (_proctime() & 0xF) << 4; 841 for (i = 0; i < delay; i++) 842 asm volatile("nop"); 843 } 844 845 _dma_busy[dma_id] = 1; 922 if ( to_user ) _dcache_buf_invalidate( (void*)user_vaddr, length ); 923 924 // get the lock 925 _get_lock( &_dma_lock[dma_id] ); 846 926 847 927 // DMA configuration 848 dma_base[DMA_IRQ_DISABLE] = 0; 849 if ( to_mem ) 850 { 851 dma_base[DMA_SRC] = (unsigned int)fb_base; 852 dma_base[DMA_DST] = (unsigned int)buf_base; 928 if ( to_user ) 929 { 930 dma_base[DMA_SRC] = (unsigned int)fb_pbase; 931 dma_base[DMA_DST] = (unsigned int)user_pbase; 853 932 } 854 933 else 855 934 { 856 dma_base[DMA_SRC] = (unsigned int) buf_base;857 dma_base[DMA_DST] = (unsigned int)fb_ base;935 dma_base[DMA_SRC] = (unsigned int)user_pbase; 936 dma_base[DMA_DST] = (unsigned int)fb_pbase; 858 937 } 859 938 dma_base[DMA_LEN] = (unsigned int)length; … … 873 952 unsigned int length ) 874 953 { 875 return _fb_ access( 0, // write to frame buffer876 offset,877 (unsigned int)buffer,878 length );954 return _fb_dma_access( 0, // write to frame buffer 955 offset, 956 (unsigned int)buffer, 957 length ); 879 958 } 880 959 … … 891 970 unsigned int length ) 892 971 { 893 return _fb_ access( 1, // read from frame buffer894 offset,895 (unsigned int)buffer,896 length );972 return _fb_dma_access( 1, // read from frame buffer 973 offset, 974 (unsigned int)buffer, 975 length ); 897 976 } 898 977 … … 906 985 unsigned int _fb_completed() 907 986 { 908 static_scheduler_t* psched = &_scheduler[_procid()]; 909 unsigned int task_id = psched->current; 910 911 volatile unsigned int dma_id = psched->context[task_id][CTX_FBDMA_ID]; 987 unsigned int dma_id = _get_current_context_slot(CTX_FBDMA_ID); 912 988 913 989 // busy waiting with a pseudo random delay between bus access 914 while (_dma_ busy[dma_id] != 0)990 while (_dma_done[dma_id] == 0) 915 991 { 916 992 unsigned int i; 917 unsigned int delay = ( _proctime() & 0xF) << 4;993 unsigned int delay = ( _proctime() ^ _procid()<<4 ) & 0xFF; 918 994 for (i = 0; i < delay; i++) 919 995 asm volatile("nop"); … … 938 1014 } 939 1015 1016 // reset synchronization variables 1017 _dma_lock[dma_id] = 0; 1018 _dma_done[dma_id] = 0; 1019 940 1020 return _dma_status[dma_id]; 941 1021 } -
soft/giet_vm/sys/drivers.h
r166 r189 10 10 11 11 /////////////////////////////////////////////////////////////////////////////////// 12 // Global variables for interaction with ISRs12 // Timer access functions (used for both vci_multi_timer and vci_xicu) 13 13 /////////////////////////////////////////////////////////////////////////////////// 14 14 15 extern volatile unsigned int _dma_status[]; 16 extern volatile unsigned char _dma_busy[]; 15 extern volatile unsigned char _timer_event[]; 17 16 18 extern volatile unsigned char _ioc_status; 19 extern volatile unsigned char _ioc_done; 20 extern unsigned int _ioc_lock; 17 unsigned int _timer_access( unsigned int read, // reas if non 0 18 unsigned int cluster_id, 19 unsigned int local_id, 20 unsigned int register_id, 21 unsigned int* buffer); 22 23 unsigned int _timer_read( unsigned int register_id, 24 unsigned int* buffer); 25 26 unsigned int _timer_write( unsigned int register_id, 27 unsigned int value); 28 29 /////////////////////////////////////////////////////////////////////////////////// 30 // TTY access functions and variables 31 /////////////////////////////////////////////////////////////////////////////////// 21 32 22 33 extern volatile unsigned char _tty_get_buf[]; 23 34 extern volatile unsigned char _tty_get_full[]; 24 35 extern unsigned int _tty_put_lock; 25 26 ///////////////////////////////////////////////////////////////////////////////////27 // Prototypes of the external functions.28 ///////////////////////////////////////////////////////////////////////////////////29 30 unsigned int _timer_write( unsigned int cluster_id,31 unsigned int timer_id,32 unsigned int register_id,33 unsigned int value);34 35 unsigned int _timer_read( unsigned int cluster_id,36 unsigned int timer_id,37 unsigned int register_id,38 unsigned int* buffer);39 40 unsigned int _icu_write( unsigned int cluster_id,41 unsigned int proc_id,42 unsigned int register_id,43 unsigned int value);44 45 unsigned int _icu_read( unsigned int cluster_id,46 unsigned int proc_id,47 unsigned int register_id,48 unsigned int* buffer);49 36 50 37 unsigned int _tty_write( const char* buffer, … … 56 43 unsigned int _tty_read_irq( char* buffer, 57 44 unsigned int length); 45 46 /////////////////////////////////////////////////////////////////////////////////// 47 // ICU access functions (both vci_multi_icu and vci_xicu) 48 /////////////////////////////////////////////////////////////////////////////////// 49 50 unsigned int _icu_read( unsigned int cluster_id, 51 unsigned int proc_id, 52 unsigned int register_id, 53 unsigned int* buffer); 54 55 unsigned int _icu_write( unsigned int cluster_id, 56 unsigned int proc_id, 57 unsigned int register_id, 58 unsigned int value ); 59 60 /////////////////////////////////////////////////////////////////////////////////// 61 // IOC access functions and variables (vci_block_device) 62 /////////////////////////////////////////////////////////////////////////////////// 63 64 extern volatile unsigned int _ioc_status; 65 extern volatile unsigned int _ioc_done; 66 extern unsigned int _ioc_lock; 67 extern unsigned int _ioc_iommu_ix1; 68 extern unsigned int _ioc_iommu_npages; 69 58 70 59 71 unsigned int _ioc_write( unsigned int lba, … … 67 79 unsigned int _ioc_completed(); 68 80 69 unsigned int _gcd_write( unsigned int register_index, 70 unsigned int value); 81 /////////////////////////////////////////////////////////////////////////////////// 82 // Multi DMA variables (vci_multi_dma) 83 /////////////////////////////////////////////////////////////////////////////////// 84 85 extern volatile unsigned int _dma_status[]; 86 extern volatile unsigned int _dma_done[]; 87 extern unsigned int _dma_lock[]; 88 extern unsigned int _dma_iommu_ix1; 89 extern unsigned int _dma_iommu_npages[]; 71 90 72 unsigned int _gcd_read( unsigned int register_index, 73 unsigned int* buffer); 74 91 /////////////////////////////////////////////////////////////////////////////////// 92 // Frame Buffer access functions (vci_frame_buffer) 93 /////////////////////////////////////////////////////////////////////////////////// 94 75 95 unsigned int _fb_sync_write(unsigned int offset, 76 96 const void* buffer, … … 91 111 unsigned int _fb_completed(); 92 112 113 /////////////////////////////////////////////////////////////////////////////////// 114 // GCD access functions 115 /////////////////////////////////////////////////////////////////////////////////// 116 117 unsigned int _gcd_write( unsigned int register_index, 118 unsigned int value); 119 120 unsigned int _gcd_read( unsigned int register_index, 121 unsigned int* buffer); 122 123 93 124 #endif 94 125 -
soft/giet_vm/sys/exc_handler.c
r158 r189 32 32 33 33 /////////////////////////////////////////////////////////////////////////////////// 34 // Initialize the exception vector according to CR code34 // Initialize the exception vector indexed by the CR XCODE field 35 35 /////////////////////////////////////////////////////////////////////////////////// 36 36 const _exc_func_t _cause_vector[16] = { … … 67 67 static void _cause(unsigned int msg_cause) 68 68 { 69 unsigned int epc;70 unsigned int bar;71 unsigned int cause;72 73 asm volatile("mfc0 %0, $14" : "=r"(epc));74 asm volatile("mfc0 %0, $8 " : "=r"(bar));75 asm volatile("mfc0 %0, $13" : "=r"(cause));76 77 69 _puts( (char*)(exc_message_causes[msg_cause]) ); 78 _puts("\nEPC = "); 79 _putw( epc ); 80 _puts("\nBAR = "); 81 _putw( bar ); 82 _puts("\nCAUSE = "); 83 _putw( cause ); 70 _puts("\n - Cycle : "); 71 _putd( _proctime() ); 72 _puts("\n - Processor : "); 73 _putd( _procid() ); 74 _puts("\n - Task : "); 75 _putd( _get_current_task_id() ); 76 _puts("\n - EPC : "); 77 _putw( _get_epc() ); 78 _puts("\n - BVAR : "); 79 _putw( _get_bvar() ); 84 80 _puts("\n"); 85 86 81 _exit(); 87 82 } -
soft/giet_vm/sys/giet.s
r165 r189 126 126 sw $27, 22*4($29) /* save EPC */ 127 127 128 la $26, _i nt_demux128 la $26, _irq_demux 129 129 jalr $26 /* jump to a C function to find the proper ISR */ 130 130 -
soft/giet_vm/sys/irq_handler.c
r169 r189 2 2 // File : irq_handler.c 3 3 // Date : 01/04/2012 4 // Author : alain greiner and joel porquet4 // Author : alain greiner 5 5 // Copyright (c) UPMC-LIP6 6 6 /////////////////////////////////////////////////////////////////////////////////// 7 // The irq_handler.c and irq_handler.h files are part of the GIET nano-kernel.8 // They contain the code of the _i nt_demux function that handle9 // the ICU (Interupt Controler Unit), and the various ISRs associated10 // to the CoCLibperipherals.7 // The irq_handler.c and irq_handler.h files are part of the GIET-VM nano-kernel. 8 // They contain the code of the _irq_demux() function that access the XICU or 9 // ICU component (Interupt Controler Unit), and the various ISRs (Interrupt 10 // Service Routine) associated to the peripherals. 11 11 /////////////////////////////////////////////////////////////////////////////////// 12 12 … … 20 20 21 21 /////////////////////////////////////////////////////////////////////////////////// 22 // Initialize the whole interrupt vector with the default ISR 23 /////////////////////////////////////////////////////////////////////////////////// 24 25 __attribute__((section (".kdata"))) _isr_func_t _interrupt_vector[32] = 26 { [0 ... 31] = &_isr_default }; 27 28 /////////////////////////////////////////////////////////////////////////////////// 29 // _int_demux() 30 // This functions uses an external ICU component (Interrupt Controler Unit) 31 // that concentrates up to 32 input interrupts lines. This component 32 // can support up to NB_PROCS output IRQ. 22 // _irq_demux() 23 // This function uses the ICU or XICU component (Interrupt Controler Unit) 24 // to get the interrupt vector entry. There is one ICU or XICU component per 25 // cluster, and this component can support up to NB_PROCS_MAX output IRQs. 26 // It returns the highest priority active interrupt index (smaller 27 // indexes have the highest priority). 28 // Any value larger than 31 means "no active interrupt", and no ISR is executed. 33 29 // 34 // Th is component returns the highest priority active interrupt index (smaller35 // indexes have the highest priority) by reading the ICU_IT_VECTOR register.36 // Any value larger than 31 means "no active interrupt", and the default ISR37 // (that does nothing) is executed.30 // There is one interrupt vector per processor (stored in the scheduler associated 31 // to the processor. Each interrupt vector entry contains two 16 bits fields: 32 // - isr_id : defines the type of ISR to be executed. 33 // - channel_id : defines the specific channel for multi-channels peripherals. 38 34 // 39 // The interrupt vector (32 ISR addresses array stored at _interrupt_vector 40 // address) is initialised with the default ISR address. The actual ISR 41 // addresses are supposed to be written in the interrupt vector array 42 // during system initialisation. 43 /////////////////////////////////////////////////////////////////////////////////// 44 void _int_demux(void) 45 { 46 int interrupt_index; 47 _isr_func_t isr; 48 unsigned int pid = _procid(); 49 50 // retrieves the highest priority active interrupt index 51 if (!_icu_read( pid / NB_PROCS, 52 pid % NB_PROCS, 35 // If the peripheral is replicated in clusters (TIMER or DMA), the channel_id is 36 // a global index : channel_id = cluster_id * NB_CHANNELS_MAX + loc_id 37 /////////////////////////////////////////////////////////////////////////////////// 38 void _irq_demux() 39 { 40 unsigned int pid = _procid(); 41 unsigned int irq_id; 42 43 // get the highest priority active IRQ index 44 45 #if GIET_USE_XICU 46 47 #else 48 49 if ( _icu_read( pid / NB_PROCS_MAX, 50 pid % NB_PROCS_MAX, 53 51 ICU_IT_VECTOR, 54 (unsigned int*)&interrupt_index) )52 &irq_id ) ) 55 53 { 56 if (interrupt_index == -1) // no interrupt is active 57 return; 58 59 isr = _interrupt_vector[interrupt_index]; 60 isr(); 61 } 62 else 63 { 64 _puts("\n[GIET ERROR] In _demux function : wrong arguments in _icu_read()\n"); 54 _puts("\n[GIET ERROR] wrong _icu_read in _irq_demux() function\n"); 65 55 _exit(); 66 56 } 57 58 #endif 59 60 if ( irq_id < 32 ) // do nothing if no interrupt active 61 { 62 unsigned int entry = _get_interrupt_vector_entry(irq_id); 63 unsigned int isr_id = entry & 0x000000FF; 64 unsigned int channel_id = (entry>>16) & 0x0000FFFF; 65 if ( isr_id == ISR_SWITCH ) _isr_switch(); 66 else if ( isr_id == ISR_IOC ) _isr_ioc(); 67 else if ( isr_id == ISR_DMA ) _isr_dma( channel_id ); 68 else if ( isr_id == ISR_TTY ) _isr_tty( channel_id ); 69 else if ( isr_id == ISR_TIMER ) _isr_timer( channel_id ); 70 else _isr_default(); 71 } 67 72 } 68 73 /////////////////////////////////////////////////////////////////////////////////// 69 74 // _isr_default() 70 75 // The default ISR is called when no specific ISR has been installed in the 71 // interrupt vector. It simply displays a message on TTY0.76 // interrupt vector. It simply displays a message on kernel TTY[0]. 72 77 /////////////////////////////////////////////////////////////////////////////////// 73 78 void _isr_default() 74 79 { 75 _puts("\n\n!!! Default ISR!!!\n");80 _puts("\n\n!!! Strange... Default ISR activated !!!\n"); 76 81 } 77 82 78 83 /////////////////////////////////////////////////////////////////////////////////// 79 84 // _isr_dma() 80 // This ISR handles up to 8 IRQs generated by 8 independant channels of the 81 // multi_dma component. It acknowledges the interrupt and reset the synchronisation 82 // variable _dma_busy[i], after copying the status into the _dma_status[i] variable. 83 /////////////////////////////////////////////////////////////////////////////////// 84 void _isr_dma_indexed( unsigned int dma_id ) 85 { 86 volatile unsigned int* dma_address; 85 // This ISR handles all IRQs generated by the multi-channels DMA controlers. 86 // The multi_dma components can be distributed in the clusters. 87 // The channel_id argument is the global DMA channel index. 88 // channel_id = cluster_id*NB_DMAS_MAX + loc_id 89 // - The ISR saves the transfert status in _dma_status[channel_id]. 90 // - It acknowledges the interrupt to reinitialize the DMA controler. 91 // - it resets the synchronisation variable _dma_busy[channel_id]. 92 /////////////////////////////////////////////////////////////////////////////////// 93 void _isr_dma( unsigned int channel_id ) 94 { 95 // compute cluster_id and loc_id 96 unsigned int cluster_id = channel_id / NB_DMAS_MAX; 97 unsigned int loc_id = channel_id % NB_DMAS_MAX; 87 98 88 99 // compute DMA channel address 89 dma_address = (unsigned int*)&seg_dma_base + (dma_id * DMA_SPAN); 100 unsigned int* dma_address = (unsigned int*)&seg_dma_base + 101 (loc_id * DMA_SPAN) + 102 (cluster_id * CLUSTER_SPAN); 90 103 91 104 // save DMA channel status 92 _dma_status[ dma_id] = dma_address[DMA_LEN]; /* save status */105 _dma_status[channel_id] = dma_address[DMA_LEN]; 93 106 94 107 // reset DMA channel 95 dma_address[DMA_RESET] = 0; /* reset IRQ */108 dma_address[DMA_RESET] = 0; 96 109 97 110 // release DMA channel 98 _dma_busy[dma_id] = 0; /* release DMA */ 99 } 100 101 void _isr_dma_0() { _isr_dma_indexed(0); } 102 void _isr_dma_1() { _isr_dma_indexed(1); } 103 void _isr_dma_2() { _isr_dma_indexed(2); } 104 void _isr_dma_3() { _isr_dma_indexed(3); } 105 void _isr_dma_4() { _isr_dma_indexed(4); } 106 void _isr_dma_5() { _isr_dma_indexed(5); } 107 void _isr_dma_6() { _isr_dma_indexed(6); } 108 void _isr_dma_7() { _isr_dma_indexed(7); } 111 _dma_done[channel_id] = 1; 112 } 109 113 110 114 /////////////////////////////////////////////////////////////////////////////////// 111 115 // _isr_ioc() 112 // There is only one IOC controler shared by all tasks. It acknowledge the IRQ113 // using the ioc base address, save the status, and set the _ioc_done variable114 // to signal completion.116 // There is only one IOC controler shared by all tasks. 117 // - The ISR save the status and acknowledge the IRQ. 118 // - It sets the _ioc_done variable to signal completion. 115 119 /////////////////////////////////////////////////////////////////////////////////// 116 120 void _isr_ioc() 117 121 { 118 volatile unsigned int* ioc_address; 119 120 ioc_address = (unsigned int*)&seg_ioc_base; 122 unsigned int* ioc_address = (unsigned int*)&seg_ioc_base; 121 123 122 124 _ioc_status = ioc_address[BLOCK_DEVICE_STATUS]; /* save status & reset IRQ */ … … 125 127 126 128 /////////////////////////////////////////////////////////////////////////////////// 127 // _isr_timer_* (* = 0,1,2,3,4,5,6,7) 128 // This ISR handles up to 8 IRQs generated by 8 independant timers. 129 // It acknowledges the IRQ on TIMER[*] and displays a message on TTY0 130 /////////////////////////////////////////////////////////////////////////////////// 131 void _isr_timer_indexed(unsigned int timer_id) 132 { 133 volatile unsigned int *timer_address; 134 135 timer_address = (unsigned int*)&seg_timer_base + (timer_id * TIMER_SPAN); 136 137 timer_address[TIMER_RESETIRQ] = 0; /* reset IRQ */ 138 139 _puts("\n\n!!! Interrupt timer received from timer "); 140 _putw( timer_id ); 141 _puts(" at cycle "); 142 _putw( _proctime() ); 143 _puts("\n\n"); 144 } 145 146 void _isr_timer_0() { _isr_timer_indexed(0); } 147 void _isr_timer_1() { _isr_timer_indexed(1); } 148 void _isr_timer_2() { _isr_timer_indexed(2); } 149 void _isr_timer_3() { _isr_timer_indexed(3); } 150 void _isr_timer_4() { _isr_timer_indexed(4); } 151 void _isr_timer_5() { _isr_timer_indexed(5); } 152 void _isr_timer_6() { _isr_timer_indexed(6); } 153 void _isr_timer_7() { _isr_timer_indexed(7); } 154 155 /////////////////////////////////////////////////////////////////////////////////// 156 // _isr_tty_get_* (* = 0,1,2,3,4,5,6,7,9,10,11,12,13,14,15) 157 // The Giet supports up to 16 TTY terminals. 158 // These 16 ISRs handle the up to 16 IRQs associated to 16 independant 159 // terminals, signaling that a character is available. 160 // There is one communication buffer _tty_get_buf[tty_id] per terminal. 161 // The sychronisation variable _tty_get_full[tty_id], is set by the ISR, 129 // _isr_timer() 130 // This ISR handles the IRQs generated by the "user" timers (the IRQs 131 // generated by the "system" timers should be handled by the _isr_switch(). 132 // These timers are distributed in all clusters, and can be implemented 133 // in a vci_multi_timer component, or in a vci_xicu component. 134 // The channel_id argument is the global channel index: 135 // channel_id = cluster_id*(NB_TIMERS_MAX+NB_PROCS_MAX) + loc_id 136 // The user timer local index is (loc_id - NB_PROCS_MAX). 137 // 138 // The ISR acknowledges the IRQ and registers the event in the proper entry 139 // of the _timer_event[] array. 140 // A log message is displayed on the kernel terminal. 141 /////////////////////////////////////////////////////////////////////////////////// 142 void _isr_timer(unsigned int channel_id) 143 { 144 145 unsigned int cluster_id = channel_id / (NB_TIMERS_MAX + NB_PROCS_MAX); 146 unsigned int loc_id = channel_id % (NB_TIMERS_MAX + NB_PROCS_MAX); 147 148 if (loc_id < NB_PROCS_MAX ) 149 { 150 _puts("[GIET ERROR] Receiving a user timer IRQ for a system timer\n"); 151 _puts(" cluster = "); 152 _putw(cluster_id); 153 _puts(" / local_id = "); 154 _putw(loc_id); 155 } 156 157 #if GIET_USE_XICU 158 159 // TODO 160 161 #else 162 163 // compute Timer address 164 unsigned int* timer_address = (unsigned int*)&seg_timer_base + 165 (loc_id * TIMER_SPAN) + 166 (cluster_id * CLUSTER_SPAN); 167 168 // reset IRQ 169 timer_address[TIMER_RESETIRQ] = 0; 170 171 #endif 172 173 #if NB_TIMERS_MAX 174 // register the event 175 _timer_event[(cluster_id*NB_TIMERS_MAX) + (loc_id - NB_PROCS_MAX)] = 1; 176 #endif 177 178 // display a message on TTY 0 179 _puts("[GIET] User Timer IRQ / cluster = "); 180 _putw(cluster_id); 181 _puts(" / timer = "); 182 _putw(loc_id - NB_PROCS_MAX); 183 _puts("\n"); 184 } 185 186 /////////////////////////////////////////////////////////////////////////////////// 187 // _isr_tty() 188 // This ISR handles the IRQs generated by the multi_tty controler, 189 // signaling that a character is available. 190 // There is one single multi_tty component controling all TTYs, and the tty_id 191 // argument is the global TTY index. 192 // There is one communication buffer _tty_buf[tty_id] per terminal. 193 // The sychronisation variable _tty_full[tty_id], is set by the ISR, 162 194 // and reset by the OS. 163 195 // A character is lost if the buffer is full when the ISR is executed. 164 196 /////////////////////////////////////////////////////////////////////////////////// 165 void _isr_tty_get_indexed(unsigned int tty_id) 166 { 167 volatile unsigned int *tty_address; 168 169 /* compute terminal base address */ 170 tty_address = (unsigned int*)&seg_tty_base + (tty_id * TTY_SPAN); 171 172 /* save character and reset IRQ */ 197 void _isr_tty(unsigned int tty_id) 198 { 199 // compute terminal base address 200 unsigned int *tty_address = (unsigned int*)&seg_tty_base + (tty_id * TTY_SPAN); 201 202 // save character and reset IRQ 173 203 _tty_get_buf[tty_id] = (unsigned char)tty_address[TTY_READ]; 174 204 175 / * signals character available */205 // signals character available 176 206 _tty_get_full[tty_id] = 1; 177 207 } 178 179 void _isr_tty_get_0() { _isr_tty_get_indexed(0); }180 void _isr_tty_get_1() { _isr_tty_get_indexed(1); }181 void _isr_tty_get_2() { _isr_tty_get_indexed(2); }182 void _isr_tty_get_3() { _isr_tty_get_indexed(3); }183 void _isr_tty_get_4() { _isr_tty_get_indexed(4); }184 void _isr_tty_get_5() { _isr_tty_get_indexed(5); }185 void _isr_tty_get_6() { _isr_tty_get_indexed(6); }186 void _isr_tty_get_7() { _isr_tty_get_indexed(7); }187 void _isr_tty_get_8() { _isr_tty_get_indexed(8); }188 void _isr_tty_get_9() { _isr_tty_get_indexed(9); }189 void _isr_tty_get_10() { _isr_tty_get_indexed(10); }190 void _isr_tty_get_11() { _isr_tty_get_indexed(11); }191 void _isr_tty_get_12() { _isr_tty_get_indexed(12); }192 void _isr_tty_get_13() { _isr_tty_get_indexed(13); }193 void _isr_tty_get_14() { _isr_tty_get_indexed(14); }194 void _isr_tty_get_15() { _isr_tty_get_indexed(15); }195 208 196 209 ///////////////////////////////////////////////////////////////////////////////////// 197 210 // _isr_switch 198 // This ISR is in charge of context switch. 199 // It acknowledges the IRQ on TIMER[proc_id] and calls the _ctx_switch() function. 211 // This ISR is in charge of context switch, and handle the IRQs generated by 212 // the "system" timers. 213 // The IRQs can be generated by the MULTI_TIMER component or by the XICU component, 214 // that are distributed in all clusters. 215 // The ISR acknowledges the IRQ and calls the _ctx_switch() function. 200 216 ///////////////////////////////////////////////////////////////////////////////////// 201 217 void _isr_switch() 202 218 { 203 volatile unsigned int *timer_address; 204 unsigned int proc_id; 205 206 proc_id = _procid(); 207 timer_address = (unsigned int*)&seg_timer_base + (proc_id * TIMER_SPAN); 208 209 timer_address[TIMER_RESETIRQ] = 0; /* reset IRQ */ 219 // get cluster index and proc local index 220 unsigned int pid = _procid(); 221 unsigned int loc_id = pid % NB_PROCS_MAX; 222 unsigned int cluster_id = pid / NB_PROCS_MAX; 223 224 #if GIET_USE_XICU 225 226 unsigned int* timer_address = // TODO 227 228 #else 229 230 // compute Timer address 231 unsigned int* timer_address = (unsigned int*)&seg_timer_base + 232 (loc_id * TIMER_SPAN) + 233 (cluster_id * CLUSTER_SPAN); 234 235 // reset IRQ 236 timer_address[TIMER_RESETIRQ] = 0; 237 238 #endif 239 240 // performs the context switch 210 241 _ctx_switch(); 211 } 212 242 243 } 244 -
soft/giet_vm/sys/irq_handler.h
r165 r189 2 2 #define _IRQ_HANDLER_H 3 3 4 /* 5 * Interrupt Vector Table (indexed by interrupt index) 6 * 7 * 32 entries corresponding to 32 ISR addresses 8 */ 4 enum 5 { 6 ISR_DEFAULT = 0, 7 ISR_SWITCH = 1, 8 ISR_TTY = 2, 9 ISR_DMA = 3, 10 ISR_IOC = 4, 11 ISR_TIMER = 5, 12 }; 9 13 10 typedef void (*_isr_func_t)(void);11 extern _isr_func_t _interrupt_vector[32];12 14 13 /* 14 * Prototypes of the Interrupt Service Routines (ISRs) supported by the GIET. 15 * - they must be installed in reset.s 16 */ 15 /////////////////////////////////////////////////////////////////////////////// 16 // Prototypes of the Interrupt Service Routines (ISRs) supported by the GIET. 17 /////////////////////////////////////////////////////////////////////////////// 18 19 void _irq_demux(); 17 20 18 21 void _isr_default(); 19 20 void _isr_dma_0();21 void _isr_dma_1();22 void _isr_dma_2();23 void _isr_dma_3();24 void _isr_dma_4();25 void _isr_dma_5();26 void _isr_dma_6();27 void _isr_dma_7();28 29 22 void _isr_ioc(); 30 31 void _isr_timer_0(); 32 void _isr_timer_1(); 33 void _isr_timer_2(); 34 void _isr_timer_3(); 35 void _isr_timer_4(); 36 void _isr_timer_5(); 37 void _isr_timer_6(); 38 void _isr_timer_7(); 39 40 void _isr_tty_get(); 41 void _isr_tty_get_0(); 42 void _isr_tty_get_1(); 43 void _isr_tty_get_2(); 44 void _isr_tty_get_3(); 45 void _isr_tty_get_4(); 46 void _isr_tty_get_5(); 47 void _isr_tty_get_6(); 48 void _isr_tty_get_7(); 49 void _isr_tty_get_8(); 50 void _isr_tty_get_9(); 51 void _isr_tty_get_10(); 52 void _isr_tty_get_11(); 53 void _isr_tty_get_12(); 54 void _isr_tty_get_13(); 55 void _isr_tty_get_14(); 56 void _isr_tty_get_15(); 57 23 void _isr_timer( unsigned int channel ); 24 void _isr_dma( unsigned int channel ); 25 void _isr_tty( unsigned int channel ); 58 26 void _isr_switch(); 59 27 -
soft/giet_vm/sys/kernel_init.c
r185 r189 5 5 // Copyright (c) UPMC-LIP6 6 6 //////////////////////////////////////////////////////////////////////////////////// 7 // FIXME8 7 // The kernel_init.c files is part of the GIET-VM nano-kernel. 9 // It contains the kernel entry point for the second phase of system initialisation:10 // all processors are jumping to _kernel_init, but P[0] is first because other11 // processors are blocked until P[0] complete initilisation of task contexts,12 // vobjs and peripherals.13 // All procs in this phase have their MMU activated, because each processor P[i]14 // must initialise registers SP, SR, PTPR and EPC with informations stored15 // in _scheduler[i].8 // It contains the kernel entry point for the last step of system initialisation. 9 // All procs in this phase have their MMU activated, and are running in parallel. 10 // - each processor updates its own scheduler, to replace the ISR index 11 // by the actual ISR virtual address, and set its own entry in the 12 // kernel _schedulers_paddr[] array. 13 // - each processor initialises the SP, SR, PTPR, EPC registers, and starts 14 // its private Timer, before jumping to the user code with an eret. 16 15 //////////////////////////////////////////////////////////////////////////////////// 17 16 18 17 #include <common.h> 18 #include <irq_handler.h> 19 19 #include <ctx_handler.h> 20 20 #include <sys_handler.h> … … 29 29 #include <drivers.h> 30 30 31 #define in_kinit __attribute__((section (".kinit")))32 33 31 /////////////////////////////////////////////////////////////////////////////////// 34 // array of pointers on the page tables 35 // (both physical and virtual addresses) 32 // Kernel Global variables 36 33 /////////////////////////////////////////////////////////////////////////////////// 37 34 38 __attribute__((section (".kdata"))) unsigned int _kernel_ptabs_paddr[GIET_NB_VSPACE_MAX];39 __attribute__((section (".kdata"))) unsigned int _kernel_ptabs_vaddr[GIET_NB_VSPACE_MAX];35 __attribute__((section (".kdata"))) 36 page_table_t* _ptabs_paddr[GIET_NB_VSPACE_MAX]; 40 37 41 /////////////////////////////////////////////////////////////////////////////////// 42 // declarations required to avoid forward references 43 /////////////////////////////////////////////////////////////////////////////////// 38 __attribute__((section (".kdata"))) 39 page_table_t* _ptabs_vaddr[GIET_NB_VSPACE_MAX]; 44 40 45 void _kernel_ptabs_init(void); 46 void _kernel_vobjs_init(void); 47 void _kernel_tasks_init(void); 48 void _kernel_peripherals_init(void); 49 void _kernel_interrupt_vector_init(void); 50 void _kernel_start_all_procs(void); 41 __attribute__((section (".kdata"))) 42 static_scheduler_t* _schedulers_paddr[NB_CLUSTERS*NB_PROCS_MAX]; 51 43 52 44 ////////////////////////////////////////////////////////////////////////////////// 53 // This function is the entry point for the secondstep of the boot sequence.45 // This function is the entry point for the last step of the boot sequence. 54 46 ////////////////////////////////////////////////////////////////////////////////// 55 in_kinitvoid _kernel_init()47 __attribute__((section (".kinit"))) void _kernel_init() 56 48 { 57 49 // values to be written in registers … … 61 53 unsigned int epc_value; 62 54 63 unsigned int pid = _procid(); 55 unsigned int proc_id = _procid(); 56 unsigned int cluster_id = proc_id / NB_PROCS_MAX; 57 unsigned int lpid = proc_id % NB_PROCS_MAX; 64 58 65 // only processor 0 executes system initialisation 66 if ( pid == 0 ) 59 // step 1 : Initialise scheduler physical addresses array 60 61 // get scheduler physical address from register 62 static_scheduler_t* psched = (static_scheduler_t*)_get_sched(); 63 _schedulers_paddr[proc_id] = psched; 64 65 #if GIET_DEBUG_INIT 66 _get_lock(&_tty_put_lock); 67 _puts("\n[GIET DEBUG] step 1 for processor "); 68 _putw( proc_id ); 69 _puts("\n"); 70 _puts("- scheduler pbase = "); 71 _putw( (unsigned int)psched ); 72 _puts("\n"); 73 _release_lock(&_tty_put_lock); 74 #endif 75 76 // step 2 : compute and set ICU mask 77 unsigned int irq_id; 78 unsigned int mask = 0; 79 for ( irq_id = 0 ; irq_id < 32 ; irq_id++ ) 67 80 { 68 _kernel_ptabs_init(); 69 /* must be called after the initialisation of ptabs */ 70 _kernel_vobjs_init(); 71 _kernel_tasks_init(); 72 _kernel_interrupt_vector_init(); 73 _kernel_peripherals_init(); 74 _kernel_start_all_procs(); 81 unsigned int entry = _get_interrupt_vector_entry(irq_id); 82 if ( entry ) mask = mask | 0x1<< irq_id; 75 83 } 84 _icu_write( cluster_id, 85 lpid, 86 ICU_MASK_SET, 87 mask ); 88 89 #if GIET_DEBUG_INIT 90 _get_lock(&_tty_put_lock); 91 _puts("\n[GIET DEBUG] step 2 for processor "); 92 _putw( proc_id ); 93 _puts("\n"); 94 _puts("- ICU mask = "); 95 _putw( mask ); 96 _puts("\n"); 97 _release_lock(&_tty_put_lock); 98 #endif 76 99 77 // each processor initialises it's SP, SR, PTPR, and EPC registers78 // from values defined in _scheduler[pid], starts it's private79 // context switch timer (if there is more than one task allocated)80 // and jumps to user code.81 // It does nothing, and keep idle if no task allocated.82 100 83 static_scheduler_t* sched = &_scheduler[pid];101 // step 3 : TODO initialise page table addresse arrays 84 102 85 if ( sched->tasks ) // at leat one task allocated 103 104 // step 4 : start TICK timer if more than one task 105 unsigned int tasks = _get_tasks_number(); 106 if ( tasks > 1 ) 107 { 108 unsigned int period = GIET_TICK_VALUE; 109 unsigned int mode = 0x3; 110 _timer_access( 0, // write access 111 cluster_id, 112 proc_id, 113 TIMER_PERIOD, 114 &period ); 115 _timer_access( 0, // write access 116 cluster_id, 117 proc_id, 118 TIMER_MODE, 119 &mode ); 120 121 #if GIET_DEBUG_INIT 122 _get_lock(&_tty_put_lock); 123 _puts("\n[GIET DEBUG] Step 4 for processor "); 124 _putw( proc_id ); 125 _puts("\n"); 126 _puts("- TICK period = "); 127 _putd( period ); 128 _puts("\n"); 129 _release_lock(&_tty_put_lock); 130 #endif 131 132 } 133 134 // step 5 : each processor initialises SP, SR, PTPR, EPC, registers 135 // with the values corresponding to the first allocated task, 136 // It does nothing, and keep idle if no task allocated. 137 138 if ( tasks ) // at leat one task allocated 86 139 { 87 140 // initialise registers 88 sp_value = sched->context[0][CTX_SP_ID];89 sr_value = sched->context[0][CTX_SR_ID];90 ptpr_value = sched->context[0][CTX_PTPR_ID];91 epc_value = sched->context[0][CTX_EPC_ID];141 sp_value = _get_current_context_slot(CTX_SP_ID); 142 sr_value = _get_current_context_slot(CTX_SR_ID); 143 ptpr_value = _get_current_context_slot(CTX_PTPR_ID); 144 epc_value = _get_current_context_slot(CTX_EPC_ID); 92 145 93 // start TICK timer 94 if ( sched->tasks > 1 ) 95 { 96 unsigned int cluster_id = pid / NB_PROCS; 97 unsigned int proc_id = pid % NB_PROCS; 98 _timer_write( cluster_id, proc_id, TIMER_PERIOD, GIET_TICK_VALUE ); 99 _timer_write( cluster_id, proc_id, TIMER_MODE , 0x3 ); 100 } 146 #if GIET_DEBUG_INIT 147 _get_lock(&_tty_put_lock); 148 _puts("\n[GIET DEBUG] step 5 for processor "); 149 _putw( proc_id ); 150 _puts("\n"); 151 _puts("- sp = "); 152 _putw( sp_value ); 153 _puts("\n"); 154 _puts("- sr = "); 155 _putw( sr_value ); 156 _puts("\n"); 157 _puts("- ptpr = "); 158 _putw( ptpr_value<<13 ); 159 _puts("\n"); 160 _puts("- epc = "); 161 _putw( epc_value ); 162 _puts("\n"); 163 _release_lock(&_tty_put_lock); 164 #endif 101 165 } 102 166 else // no task allocated … … 104 168 _get_lock( &_tty_put_lock ); 105 169 _puts("\n No task allocated to processor "); 106 _putw( p id );170 _putw( proc_id ); 107 171 _puts(" => keep idle\n"); 108 172 _release_lock ( &_tty_put_lock ); … … 117 181 } 118 182 183 // set critical registers and jump to user code 119 184 asm volatile ( 120 185 "move $29, %0 \n" /* SP <= ctx[CTX_SP_ID] */ … … 128 193 129 194 } // end _kernel_init() 130 131 //////////////////////////////////////////////////////////////////////////////////132 // This function wakeup all processors.133 // It should be executed by P[0] when the kernel initialisation is done.134 //////////////////////////////////////////////////////////////////////////////////135 in_kinit void _kernel_start_all_procs()136 {137 mapping_header_t* header = (mapping_header_t*)&seg_mapping_base;138 139 _puts("\n[INIT] Starting parallel execution at cycle : ");140 _putw( _proctime() );141 _puts("\n");142 143 header->signature = OUT_MAPPING_SIGNATURE;144 }145 146 //////////////////////////////////////////////////////////////////////////////////147 // _eret()148 // The address of this function is used to initialise the return address (RA)149 // in all task contexts (when the task has never been executed.150 //////////////////////////////////////////////////////////////////////////////////151 in_kinit void _eret()152 {153 asm volatile("eret \n"154 "nop");155 }156 157 ///////////////////////////////////////////////////////////////////////////////158 // used to access user space159 ///////////////////////////////////////////////////////////////////////////////160 void _set_ptpr(unsigned int vspace_id)161 {162 unsigned int ptpr = ((unsigned int)_kernel_ptabs_paddr[vspace_id]) >> 13;163 asm volatile("mtc2 %0, $0"::"r"(ptpr));164 }165 166 ///////////////////////////////////////////////////////////////////////////////167 // This function initialises the _kernel_ptabs_paddr[] array indexed by the vspace_id,168 // and containing the base addresses of all page tables.169 // This _kernel_ptabs_paddr[] array is used to initialise the task contexts.170 ///////////////////////////////////////////////////////////////////////////////171 in_kinit void _kernel_ptabs_init()172 {173 mapping_header_t* header = (mapping_header_t*)&seg_mapping_base;174 mapping_vspace_t* vspace = _get_vspace_base( header );175 mapping_vobj_t* vobj = _get_vobj_base( header );176 177 unsigned int vspace_id;178 unsigned int vobj_id;179 180 // loop on the vspaces181 for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )182 {183 char ptab_found = 0;184 185 #if INIT_DEBUG_CTX186 _puts("[INIT] --- ptabs initialisation in vspace ");187 _puts(vspace[vspace_id].name);188 _puts("\n");189 #endif190 // loop on the vobjs and get the ptpr191 for(vobj_id= vspace[vspace_id].vobj_offset;192 vobj_id < (vspace[vspace_id].vobj_offset+ vspace[vspace_id].vobjs);193 vobj_id++)194 {195 if(vobj[vobj_id].type == VOBJ_TYPE_PTAB)196 {197 if( ptab_found )198 {199 _puts("\n[INIT ERROR] Only one PTAB for by vspace ");200 _putw( vspace_id );201 _exit();202 }203 204 ptab_found = 1;205 _kernel_ptabs_paddr[vspace_id] = vobj[vobj_id].paddr;206 _kernel_ptabs_vaddr[vspace_id] = vobj[vobj_id].vaddr;207 208 #if INIT_DEBUG_CTX209 _puts("[INIT] PTAB address = ");210 _putw(_kernel_ptabs_paddr[vspace_id]);211 _puts("\n");212 #endif213 }214 215 }216 217 if( !ptab_found )218 {219 _puts("\n[INIT ERROR] Missing PTAB for vspace ");220 _putw( vspace_id );221 _exit();222 }223 }224 225 _puts("\n[INIT] Ptabs initialisation completed at cycle : ");226 _putw( _proctime() );227 _puts("\n");228 229 } // end kernel_ptabs_init()230 231 ///////////////////////////////////////////////////////////////////////////////232 // This function initializes all private vobjs defined in the vspaces,233 // such as mwmr channels, barriers and locks, depending on the vobj type.234 // (Most of the vobjs are not known, and not initialised by the compiler).235 ///////////////////////////////////////////////////////////////////////////////236 in_kinit void _kernel_vobjs_init()237 {238 mapping_header_t* header = (mapping_header_t*)&seg_mapping_base;239 mapping_vspace_t* vspace = _get_vspace_base( header );240 mapping_vobj_t* vobj = _get_vobj_base( header );241 242 unsigned int vspace_id;243 unsigned int vobj_id;244 245 // loop on the vspaces246 for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )247 {248 249 #if INIT_DEBUG_CTX250 _puts("[INIT] --- vobjs initialisation in vspace ");251 _puts(vspace[vspace_id].name);252 _puts("\n");253 #endif254 /** Set the current vspace ptpr to initialise the vobjs */255 _set_ptpr(vspace_id);256 257 // loop on the vobjs and get the ptpr258 for(vobj_id= vspace[vspace_id].vobj_offset;259 vobj_id < (vspace[vspace_id].vobj_offset+ vspace[vspace_id].vobjs);260 vobj_id++)261 {262 switch( vobj[vobj_id].type )263 {264 case VOBJ_TYPE_PTAB: // initialise page table pointers array265 {266 break;//already handled267 }268 case VOBJ_TYPE_MWMR: // storage capacity is (vobj.length/4 - 5) words269 {270 mwmr_channel_t* mwmr = (mwmr_channel_t*)(vobj[vobj_id].vaddr);271 mwmr->ptw = 0;272 mwmr->ptr = 0;273 mwmr->sts = 0;274 mwmr->depth = ((vobj[vobj_id].length>>2) - 6);//6= number of entry in the strucure275 mwmr->width = vobj[vobj_id].init;276 mwmr->lock = 0;277 #if INIT_DEBUG_CTX278 _puts("[INIT] MWMR channel ");279 _puts( vobj[vobj_id].name);280 _puts(" / depth = ");281 _putw( mwmr->depth );282 _puts("\n");283 #endif284 break;285 }286 case VOBJ_TYPE_ELF: // initialisation done by the loader287 {288 289 #if INIT_DEBUG_CTX290 _puts("[INIT] ELF section ");291 _puts( vobj[vobj_id].name);292 _puts(" / length = ");293 _putw( vobj[vobj_id].length );294 _puts("\n");295 #endif296 break;297 }298 case VOBJ_TYPE_BARRIER: // init is the number of participants299 {300 giet_barrier_t* barrier = (giet_barrier_t*)(vobj[vobj_id].vaddr);301 barrier->count = 0;302 barrier->init = vobj[vobj_id].init;303 #if INIT_DEBUG_CTX304 _puts(" BARRIER ");305 _puts( vobj[vobj_id].name);306 _puts(" / init_value = ");307 _putw( barrier->init );308 _puts("\n");309 #endif310 break;311 }312 case VOBJ_TYPE_LOCK: // init is "not taken"313 {314 unsigned int* lock = (unsigned int*)(vobj[vobj_id].vaddr);315 *lock = 0;316 #if INIT_DEBUG_CTX317 _puts(" LOCK ");318 _puts( vobj[vobj_id].name);319 _puts("\n");320 #endif321 break;322 }323 case VOBJ_TYPE_BUFFER: // nothing to do324 {325 326 #if INIT_DEBUG_CTX327 _puts(" BUFFER ");328 _puts( vobj[vobj_id].name);329 _puts(" / length = ");330 _putw( vobj[vobj_id].length );331 _puts("\n");332 #endif333 break;334 }335 default:336 {337 _puts("\n[INIT ERROR] illegal vobj of name ");338 _puts(vobj[vobj_id].name);339 _puts(" / in vspace = ");340 _puts(vobj[vobj_id].name);341 _puts("\n ");342 _exit();343 }344 } // end switch type345 } // end loop on vobjs346 } // end loop on vspaces347 348 _puts("\n[INIT] Vobjs initialisation completed at cycle : ");349 _putw( _proctime() );350 _puts("\n");351 352 } // end kernel_vobjs_init()353 354 ///////////////////////////////////////////////////////////////////////////////355 // This function maps a given task, defined in a given vspace356 // on the processor allocated in the mapping_info structure,357 // and initialises the task context.358 // There is one scheduler per processor, and processor can be shared359 // by several applications running in different vspaces.360 // There is one private context array handled by each scheduler.361 //362 // The following values must be initialised in all task contexts:363 // - sp stack pointer = stack_base + stack_length364 // - ra return address = &_eret365 // - epc start address = start_vector[task->startid]366 // - sr status register = OxFF13367 // - tty TTY terminal index (global index)368 // - fb FB_DMA channel index (global index)369 // - ptpr page table base address / 8K370 // - mode mmu_mode = 0xF (TLBs and caches activated)371 // - ptab page table virtual address372 ////////////////////////////////////////////////////////////////////////////////373 in_kinit void _task_map( unsigned int task_id, // global index374 unsigned int vspace_id, // global index375 unsigned int tty_id, // TTY index376 unsigned int fbdma_id ) // FBDMA index377 {378 mapping_header_t* header = (mapping_header_t*)&seg_mapping_base;379 380 mapping_task_t* task = _get_task_base(header);381 mapping_vspace_t* vspace = _get_vspace_base(header);382 mapping_vobj_t* vobj = _get_vobj_base( header );383 384 /** Set the current vspace ptpr before acessing the memory */385 _set_ptpr(vspace_id);386 387 // values to be initialised in task context388 unsigned int ra = (unsigned int)&_eret;389 unsigned int sr = 0x0000FF13;390 unsigned int tty = tty_id;391 unsigned int fb = fbdma_id;392 unsigned int ptpr = _kernel_ptabs_paddr[vspace_id] >> 13;393 unsigned int ptab = _kernel_ptabs_vaddr[vspace_id];394 unsigned int mode = 0xF;395 unsigned int sp;396 unsigned int epc;397 398 // EPC : Get the (virtual) base address of the start_vector containing399 // the start addresses for all tasks defined in a vspace.400 mapping_vobj_t* vobj_data = &vobj[vspace[vspace_id].vobj_offset +401 vspace[vspace_id].start_offset];402 unsigned int* start_vector = (unsigned int*)vobj_data->vaddr;403 epc = start_vector[task[task_id].startid];404 405 // SP : Get the vobj containing the stack406 unsigned int vobj_id = task[task_id].vobjlocid + vspace[vspace_id].vobj_offset;407 sp = vobj[vobj_id].vaddr + vobj[vobj_id].length;408 409 // compute global processor index410 unsigned int proc_id = task[task_id].clusterid * NB_PROCS + task[task_id].proclocid;411 412 // compute and check local task index413 unsigned int ltid = _scheduler[proc_id].tasks;414 if ( ltid >= GIET_NB_TASKS_MAX )415 {416 _puts("\n[INIT ERROR] : too much tasks allocated to processor ");417 _putw( proc_id );418 _puts("\n");419 _exit();420 }421 422 // update number of tasks allocated to scheduler423 _scheduler[proc_id].tasks = ltid + 1;424 425 // initializes the task context426 _scheduler[proc_id].context[ltid][CTX_SR_ID] = sr;427 _scheduler[proc_id].context[ltid][CTX_SP_ID] = sp;428 _scheduler[proc_id].context[ltid][CTX_RA_ID] = ra;429 _scheduler[proc_id].context[ltid][CTX_EPC_ID] = epc;430 _scheduler[proc_id].context[ltid][CTX_PTPR_ID] = ptpr;431 _scheduler[proc_id].context[ltid][CTX_MODE_ID] = mode;432 _scheduler[proc_id].context[ltid][CTX_TTY_ID] = tty;433 _scheduler[proc_id].context[ltid][CTX_FBDMA_ID] = fb;434 _scheduler[proc_id].context[ltid][CTX_PTAB_ID] = ptab;435 _scheduler[proc_id].context[ltid][CTX_TASK_ID] = task_id;436 437 #if INIT_DEBUG_CTX438 _puts("Task ");439 _puts( task[task_id].name );440 _puts(" allocated to processor ");441 _putw( proc_id );442 _puts(" / ltid = ");443 _putw( ltid );444 _puts("\n");445 446 _puts(" - SR = ");447 _putw( sr );448 _puts(" saved at ");449 _putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_SR_ID] );450 _puts("\n");451 452 _puts(" - RA = ");453 _putw( ra );454 _puts(" saved at ");455 _putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_RA_ID] );456 _puts("\n");457 458 _puts(" - SP = ");459 _putw( sp );460 _puts(" saved at ");461 _putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_SP_ID] );462 _puts("\n");463 464 _puts(" - EPC = ");465 _putw( epc );466 _puts(" saved at ");467 _putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_EPC_ID] );468 _puts("\n");469 470 _puts(" - PTPR = ");471 _putw( ptpr<<13 );472 _puts(" saved at ");473 _putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_PTPR_ID] );474 _puts("\n");475 476 _puts(" - TTY = ");477 _putw( tty );478 _puts(" saved at ");479 _putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_TTY_ID] );480 _puts("\n");481 482 _puts(" - FB = ");483 _putw( fb );484 _puts(" saved at ");485 _putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_FBDMA_ID] );486 _puts("\n");487 488 _puts(" - PTAB = ");489 _putw( ptab );490 _puts(" saved at ");491 _putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_PTAB_ID] );492 _puts("\n");493 #endif494 495 } // end _task_map()496 497 ///////////////////////////////////////////////////////////////////////////////498 // This function initialises all task contexts and processors schedulers.499 // It sets the default values for all schedulers (tasks <= 0, current <= 0).500 // Finally, it scan all tasks in all vspaces to initialise the schedulers,501 // and the tasks contexts, as defined in the mapping_info data structure.502 // A global TTY index and a global FB channel are allocated if required.503 // TTY[0] is reserved for the kernel.504 ///////////////////////////////////////////////////////////////////////////////505 in_kinit void _kernel_tasks_init()506 {507 mapping_header_t* header = (mapping_header_t*)&seg_mapping_base;508 mapping_cluster_t* cluster = _get_cluster_base( header );509 mapping_vspace_t* vspace = _get_vspace_base( header );510 mapping_task_t* task = _get_task_base( header );511 512 unsigned int base_tty_id = 1; // TTY index allocator513 unsigned int base_fb_id = 0; // FB channel index allocator514 515 unsigned int cluster_id;516 unsigned int proc_id;517 unsigned int vspace_id;518 unsigned int task_id;519 520 // initialise the schedulers (not done by the compiler)521 for ( cluster_id = 0 ; cluster_id < header->clusters ; cluster_id++ )522 {523 for ( proc_id = 0 ; proc_id < cluster[cluster_id].procs ; proc_id++ )524 {525 if ( proc_id >= NB_PROCS )526 {527 _puts("\n[INIT ERROR] The number of processors in cluster ");528 _putw( cluster_id );529 _puts(" is larger than NB_PROCS \n");530 _exit();531 }532 _scheduler[cluster_id*NB_PROCS+proc_id].tasks = 0;533 _scheduler[cluster_id*NB_PROCS+proc_id].current = 0;534 }535 }536 537 // loop on the virtual spaces538 for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )539 {540 541 #if INIT_DEBUG_CTX542 _puts("\n[INIT] mapping tasks in vspace ");543 _puts(vspace[vspace_id].name);544 _puts("\n");545 #endif546 // loop on the tasks547 for ( task_id = vspace[vspace_id].task_offset ;548 task_id < (vspace[vspace_id].task_offset + vspace[vspace_id].tasks) ;549 task_id++ )550 {551 unsigned int tty_id = 0xFFFFFFFF;552 unsigned int fb_id = 0xFFFFFFFF;553 if ( task[task_id].use_tty )554 {555 tty_id = base_tty_id;556 base_tty_id++;557 }558 if ( task[task_id].use_fb )559 {560 fb_id = base_fb_id;561 base_fb_id++;562 }563 _task_map( task_id, // global task index564 vspace_id, // vspace index565 tty_id, // global tty index566 fb_id ); // global fbdma index567 } // end loop on tasks568 } // end oop on vspaces569 570 _puts("\n[INIT] Task Contexts initialisation completed at cycle ");571 _putw( _proctime() );572 _puts("\n");573 574 #if INIT_DEBUG_CTX575 for ( cluster_id = 0 ; cluster_id < header->clusters ; cluster_id++ )576 {577 _puts("\nCluster ");578 _putw( cluster_id );579 _puts("\n");580 for ( proc_id = 0 ; proc_id < cluster[cluster_id].procs ; proc_id++ )581 {582 unsigned int ltid; // local task index583 unsigned int gtid; // global task index584 unsigned int pid = cluster_id * NB_PROCS + proc_id;585 586 _puts(" - processor ");587 _putw( pid );588 _puts("\n");589 for ( ltid = 0 ; ltid < _scheduler[pid].tasks ; ltid++ )590 {591 gtid = _scheduler[pid].context[ltid][CTX_TASK_ID];592 _puts(" task : ");593 _puts( task[gtid].name );594 _puts("\n");595 }596 }597 }598 #endif599 600 } // end _kernel_task_init()601 602 ////////////////////////////////////////////////////////////////////////////////603 // This function intializes the external periherals such as the IOB component604 // (I/O bridge, containing the IOMMU, the IOC (external disk controller),605 // the NIC (external network controller), the FBDMA (frame buffer controller),606 ////////////////////////////////////////////////////////////////////////////////607 in_kinit void _kernel_peripherals_init()608 {609 /////////////////////610 // IOC peripheral611 // we simply activate the IOC interrupts...612 if ( NB_IOC )613 {614 unsigned int* ioc_address = (unsigned int*)&seg_ioc_base;615 ioc_address[BLOCK_DEVICE_IRQ_ENABLE] = 1;616 }617 618 /////////////////////619 // FBDMA peripheral620 // we simply activate the DMA interrupts...621 if ( NB_DMAS )622 {623 unsigned int* dma_address = (unsigned int*)&seg_dma_base;624 dma_address[DMA_IRQ_DISABLE] = 0;625 }626 627 /////////////////////628 // IOB peripheral629 // must be initialised in case of IOMMU630 if ( GIET_IOMMU_ACTIVE )631 {632 unsigned int* iob_address = (unsigned int*)&seg_iob_base;633 634 // define IPI address mapping the IOC interrupt ...TODO...635 636 // set IOMMU page table address637 iob_address[IOB_IOMMU_PTPR] = (unsigned int)(&_iommu_ptab);638 639 // activate IOMMU640 iob_address[IOB_IOMMU_ACTIVE] = 1;641 }642 643 _puts("\n[INIT] Peripherals initialisation completed at cycle ");644 _putw( _proctime() );645 _puts("\n");646 647 } // end _kernel_peripherals_init()648 649 ////////////////////////////////////////////////////////////////////////////////650 // This function intialises the interrupt vector, and initialises651 // the ICU mask registers for all processors in all clusters.652 // It strongly depends on the actual peripheral hardware wiring.653 // In this peculiar version, all clusters are identical,654 // the number of processors per cluster cannot be larger than 8.655 // Processor 0 handle all interrupts corresponding to TTYs, DMAs and IOC656 // (ICU inputs from from IRQ[8] to IRQ[31]). Only the 8 TIMER interrupts657 // (ICU iputs IRQ[0] to IRQ[7]), that are used for context switching658 // are distributed to the 8 processors.659 ////////////////////////////////////////////////////////////////////////////////660 in_kinit void _kernel_interrupt_vector_init()661 {662 mapping_header_t* header = (mapping_header_t*)&seg_mapping_base;663 mapping_cluster_t* cluster = _get_cluster_base( header );664 665 unsigned int cluster_id;666 unsigned int proc_id;667 668 // ICU mask values (up to 8 processors per cluster)669 unsigned int icu_mask[8] = { 0xFFFFFF01,670 0x00000002,671 0x00000004,672 0x00000008,673 0x00000010,674 0x00000020,675 0x00000040,676 0x00000080 };677 678 // initialise ICUs for each processor in each cluster679 for ( cluster_id = 0 ; cluster_id < header->clusters ; cluster_id++ )680 {681 for ( proc_id = 0 ; proc_id < cluster[cluster_id].procs ; proc_id++ )682 {683 _icu_write( cluster_id, proc_id, ICU_MASK_SET, icu_mask[proc_id] );684 }685 }686 687 // initialize Interrupt vector688 689 _interrupt_vector[0] = &_isr_switch;690 _interrupt_vector[1] = &_isr_switch;691 _interrupt_vector[2] = &_isr_switch;692 _interrupt_vector[3] = &_isr_switch;693 _interrupt_vector[4] = &_isr_switch;694 _interrupt_vector[5] = &_isr_switch;695 _interrupt_vector[6] = &_isr_switch;696 _interrupt_vector[7] = &_isr_switch;697 698 _interrupt_vector[8] = &_isr_dma_0;699 _interrupt_vector[9] = &_isr_dma_1;700 _interrupt_vector[10] = &_isr_dma_2;701 _interrupt_vector[11] = &_isr_dma_3;702 _interrupt_vector[12] = &_isr_dma_4;703 _interrupt_vector[13] = &_isr_dma_5;704 _interrupt_vector[14] = &_isr_dma_6;705 _interrupt_vector[15] = &_isr_dma_7;706 707 _interrupt_vector[16] = &_isr_tty_get_0;708 _interrupt_vector[17] = &_isr_tty_get_1;709 _interrupt_vector[18] = &_isr_tty_get_2;710 _interrupt_vector[19] = &_isr_tty_get_3;711 _interrupt_vector[20] = &_isr_tty_get_4;712 _interrupt_vector[21] = &_isr_tty_get_5;713 _interrupt_vector[22] = &_isr_tty_get_6;714 _interrupt_vector[23] = &_isr_tty_get_7;715 _interrupt_vector[24] = &_isr_tty_get_8;716 _interrupt_vector[25] = &_isr_tty_get_9;717 _interrupt_vector[26] = &_isr_tty_get_10;718 _interrupt_vector[27] = &_isr_tty_get_11;719 _interrupt_vector[28] = &_isr_tty_get_12;720 _interrupt_vector[29] = &_isr_tty_get_13;721 _interrupt_vector[30] = &_isr_tty_get_14;722 723 _interrupt_vector[31] = &_isr_ioc;724 725 _puts("\n[INIT] Interrupt vector initialisation completed at cycle ");726 _putw( _proctime() );727 _puts("\n");728 729 } // end _kernel_interrup_vector_init() -
soft/giet_vm/sys/mips32_registers.h
r167 r189 53 53 #define CP0_EPC $14 54 54 #define CP0_PROCID $15,1 55 #define CP0_SCHED $22 55 56 56 57 /* CP2 registers */ -
soft/giet_vm/sys/switch.s
r158 r189 1 1 /****************************************************************************** 2 * This function receives two arguments representing addresses of task 3 * contexts, respectively for the current running task to be descheduled and 4 * for the next task to be scheduled. 2 * This function receives two arguments that are the current task context 3 * physical addresses and the next task context physical address. 5 4 ******************************************************************************/ 6 5 … … 11 10 _task_switch: 12 11 12 /* desactivate DTLB */ 13 ori $27, $0, 0xB 14 mtc2 $27, $1 /* DTLB desactivated */ 15 13 16 /* save _current task context */ 14 15 17 add $27, $4, $0 /* $27 <= &context[curr_task_id] */ 16 18 … … 58 60 mfc2 $26, $0 59 61 sw $26, 35*4($27) /* ctx[35] <= PTPR */ 60 mfc2 $26, $161 sw $26, 36*4($27) /* ctx[36] <= MODE */62 62 63 63 /* restore next task context */ 64 65 64 add $27, $5, $0 /* $27<= &context[next_task_id] */ 66 65 67 66 lw $26, 35*4($27) 68 67 mtc2 $26, $0 /* restore PTPR */ 69 lw $26, 36*4($27)70 mtc2 $26, $1 /* restore MODE */71 68 lw $26, 0*4($27) 72 69 mtc0 $26, $12 /* restore SR */ … … 111 108 mtc0 $26, $13 /* restore CR */ 112 109 113 jr $31 /* returns to caller */ 110 /* activate DTLB */ 111 ori $27, $0, 0xF 112 mtc2 $27, $1 113 114 /* returns to caller */ 115 jr $31 114 116 115 117 .endfunc -
soft/giet_vm/sys/sys_handler.c
r167 r189 75 75 void _exit() 76 76 { 77 /* 77 78 unsigned int date = _proctime(); 79 78 80 unsigned int proc_id = _procid(); 79 unsigned int task_id = _scheduler[proc_id].current; 81 82 unsigned int task_id = _get_current_task_id(); 80 83 81 84 // print death message 85 _get_lock(&_tty_put_lock); 82 86 _puts("\n\n!!! Exit task "); 83 87 _putw( task_id ); … … 87 91 _putw( date ); 88 92 _puts("\n\n"); 89 93 _release_lock(&_tty_put_lock); 94 */ 95 90 96 /* infinite loop */ 91 97 while (1) asm volatile("nop"); -
soft/giet_vm/sys/vm_handler.c
r184 r189 118 118 119 119 // gets ppn_value and flags_value, after temporary DTLB desactivation 120 asm volatile ( 121 "li $27, 0xFFFFFFFE \n" /* Mask for IE bits */ 122 "mfc0 $8, $12 \n" /* $8 <= SR */ 123 "and $26, $8, $27 \n" /* $26 <= SR && 0xFFFFFFE */ 124 "mtc0 $26, $12 \n" /* disable Interrupts */ 120 asm volatile ( "li $27, 0xFFFFFFFE \n" /* Mask for IE bits */ 121 "mfc0 $26, $12 \n" /* save SR */ 122 "and $27, $26, $27 \n" 123 "mtc0 $27, $12 \n" /* disable Interrupts */ 124 125 "li $27, 0xB \n" 126 "mtc2 $27, $1 \n" /* DTLB unactivated */ 125 127 126 128 "move $27, %2 \n" /* $27 <= pte2 */ 127 "li $26, 0xB \n" /* DTLB unactivated */128 "mtc2 $26, $1 \n"129 129 "lw %0, 0($27) \n" /* read flags */ 130 130 "lw %1, 4($27) \n" /* read ppn */ 131 "li $26, 0xF \n"132 "mtc2 $26, $1 \n" /* DTLB activated */133 131 134 "or $26, $8, $0 \n" /* SR previous state */ 132 "li $27, 0xF \n" 133 "mtc2 $27, $1 \n" /* DTLB activated */ 134 135 "mtc0 $26, $12 \n" /* restore SR */ 135 136 :"=r"(flags_value), "=r"(ppn_value) 136 137 :"r"(pte2) -
soft/giet_vm/sys/vm_handler.h
r180 r189 53 53 typedef struct PageTable 54 54 { 55 unsigned int pt1[PT1_SIZE/4]; // PT1 (index is ix1) 56 unsigned int pt2[1][PT2_SIZE/4]; // PT2s (index is 2*ix2) 57 /* The number `1` is onmy here to indicate to the compiler that this is a table 58 ** of two dimension and the actual value is computed dynamically(see boot_handler.c)*/ 55 unsigned int pt1[PT1_SIZE/4]; // PT1 (index is ix1) 56 unsigned int pt2[GIET_NB_PT2_MAX][PT2_SIZE/4]; // PT2s (index is 2*ix2) 59 57 } page_table_t; 60 58 -
soft/giet_vm/xml/Makefile
r181 r189 3 3 4 4 bin2xml: xml_driver.c mapping_info.h 5 gcc -Wall -g -I. xml_driver.c -o bin2xml5 gcc -Wall -g -I. -I../sys xml_driver.c -o bin2xml 6 6 7 7 xml2bin: xml_parser.c mapping_info.h 8 gcc -Wall -g -I. -I /usr/include/libxml2 xml_parser.c -o xml2bin -lxml28 gcc -Wall -g -I. -I../sys -I/usr/include/libxml2 xml_parser.c -o xml2bin -lxml2 9 9 10 10 test: -
soft/giet_vm/xml/mapping_info.h
r181 r189 13 13 // a fixed size header, and 6 variable size arrays: 14 14 // 15 // - mapping_header_t header (MAPPING_HEADER_SIZE) 16 // - mapping_cluster_t cluster[clusters] (MAPPING_CLUSTER_SIZE * clusters) 17 // - mapping_pseg_t pseg[psegs] (MAPPING_PSEG_SIZE * psegs) 18 // - mapping_vspace_t vspace[vspaces] (MAPPING_VSPACE_SIZE * vspaces) 19 // - mapping_vseg_t vseg[vsegs] (MAPPING_VSEG_SIZE * vsegs) 20 // - mapping_vseg_t vobj[vsegs] (MAPPING_VOBJ_SIZE * vsegs) 21 // - mapping_task_t task[tasks] (MAPPING_TASK_SIZE * tasks) 22 // 23 // The number of clusters and the number of vspaces are defined in the header. 24 // The number of psegs are defined in each cluster. 25 // The number of vsegs, tasks ans mwmrs are defined in each vspace. 15 // - mapping_cluster_t cluster[] 16 // - mapping_pseg_t pseg[] 17 // - mapping_vspace_t vspace[] 18 // - mapping_vseg_t vseg[] 19 // - mapping_vseg_t vobj[] 20 // - mapping_task_t task[] 21 // - mapping_irq_t irq[irqs] 22 // - mapping_coproc_t coproc[] 23 // - mapping_cp_port_t cp_port[] 24 // - mapping_periph_t periph[] 26 25 // 27 26 // It is intended to be stored in the boot ROM at address MAPPING_BOOT_BASE. 28 // For each cluster, the base address of the first pseg descriptor29 // is defined by a pseg_offset relative to MAPPING_BOOT_BASE.30 // For each vspace, the base address of the first vseg descriptor31 // is defined by a vseg_offset relative to MAPPING_BOOT_BASE.32 // For each vspace, the base address of the first task desciptor33 // is defined by a task_offset relative to MAPPING_BOOT_BASE.34 // For each vspace, the base address of the first mwmr desciptor35 // is defined by a mwmr_offset relative to MAPPING_BOOT_BASE.36 27 //////////////////////////////////////////////////////////////////////////// 37 28 … … 49 40 #define MAPPING_IRQ_SIZE sizeof(mapping_irq_t) 50 41 #define MAPPING_COPROC_SIZE sizeof(mapping_coproc_t) 51 #define MAPPING_CP_PORT_SIZE sizeof(mapping_coproc_port_t) 52 #define MAPPING_CP_REG_SIZE sizeof(mapping_coproc_reg_t) 42 #define MAPPING_CP_PORT_SIZE sizeof(mapping_cp_port_t) 53 43 54 44 #define C_MODE_MASK 0b1000 // cacheable … … 81 71 enum 82 72 { 83 IRQ_TYPE_HARD = 0, // hardware interrupt (peripheral) 84 IRQ_TYPE_SOFT = 1, // software interrupt (IPI) 85 }; 86 87 enum 88 { 89 ISR_SWITCH = 0, 90 ISR_IOC = 1, 91 ISR_FBDMA = 2, 92 ISR_TTY = 3, 93 }; 94 95 enum 96 { 97 REG_TYPE_STATUS = 0, // status register 98 REG_TYPE_CONFIG = 1, // config register 73 PERIPH_TYPE_IOC = 0, 74 PERIPH_TYPE_TTY = 1, 75 PERIPH_TYPE_TIM = 2, 76 PERIPH_TYPE_DMA = 3, 77 PERIPH_TYPE_FBF = 4, 78 PERIPH_TYPE_NIC = 5, 79 PERIPH_TYPE_IOB = 6, 99 80 }; 100 81 … … 106 87 107 88 /////////////////////////////// 89 108 90 typedef struct mapping_header_s 109 91 { 110 92 unsigned int signature; // must contain MAPPING_SIGNATURE 111 93 unsigned int clusters; // number of clusters 112 unsigned int ttys; // number of TTY terminals113 unsigned int fbs; // number of FBDMA channels114 94 unsigned int globals; // number of vsegs mapped in all vspaces 115 95 unsigned int vspaces; // number of virtual spaces 96 97 unsigned int tty_clusterid; // index of cluster containing TTY controler 98 unsigned int ioc_clusterid; // index of cluster containing IOC controler 99 unsigned int nic_clusterid; // index of cluster containing NIC controler 100 unsigned int fbf_clusterid; // index of cluster containing FBF controler 101 116 102 unsigned int psegs; // total number of physical segments (for all clusters) 117 103 unsigned int vsegs; // total number of virtual segments (for all vspaces) 118 104 unsigned int vobjs; // total number of virtual objects (for all vspaces) 119 105 unsigned int tasks; // total number of tasks (for all vspaces) 120 unsigned int procs; // total number of procs 121 unsigned int irqs; // total number of irqs 122 unsigned int coprocs; // total number of coprocs 123 unsigned int cp_ports; // total number of cp_ports 124 unsigned int cp_regs; // total number of cp_regss 106 unsigned int procs; // total number of procs (for all clusters) 107 unsigned int irqs; // total number of irqs (for all processors) 108 unsigned int coprocs; // total number of coprocs (for all clusters) 109 unsigned int cp_ports; // total number of cp_ports (for all coprocs) 110 unsigned int periphs; // total number of peripherals (for all clusters) 111 125 112 char name[32]; // mapping name 126 113 } mapping_header_t; … … 129 116 typedef struct mapping_cluster_s 130 117 { 118 unsigned int psegs; // number of psegs in cluster 119 unsigned int pseg_offset; // index of first pseg in pseg set 120 131 121 unsigned int procs; // number of processors in cluster 132 122 unsigned int proc_offset; // index of first proc in proc set 123 133 124 unsigned int coprocs; // number of coprocessors in cluster 134 125 unsigned int coproc_offset; // index of first coproc in coproc set 135 unsigned int psegs; // number of psegs in cluster 136 unsigned int pseg_offset; // index of first pseg in pseg set 126 127 unsigned int periphs; // number of peripherals in cluster 128 unsigned int periph_offset; // index of first coproc in coproc set 137 129 } mapping_cluster_t; 138 130 … … 183 175 unsigned int vobjlocid; // stack vobj index in vspace 184 176 unsigned int startid; // index in start_vector 185 unsigned int use_tty; // TTY terminal required 186 unsigned int use_fb; // DMA channel to frame buffer required 177 unsigned int use_tty; // TTY terminal required (global) 178 unsigned int use_nic; // NIC channel required (global) 179 unsigned int use_timer; // user timer required (local) 180 unsigned int use_fbdma; // DMA channel to frame buffer required (local) 187 181 } mapping_task_t; 188 182 … … 210 204 typedef struct mapping_irq_s 211 205 { 212 unsigned int type; // HW_IRQ /SW_IRQ206 unsigned int type; // 0 => HW_IRQ / 1 => SW_IRQ 213 207 unsigned int icuid; // IRQ Index for the ICU component 214 208 unsigned int isr; // Interrupt Service Routine Index 215 209 unsigned int channel; // Channel Index (for multi-cannels peripherals) 216 217 unsigned int cluster_id; // physical cluster index218 unsigned int proclocid; // processor local index (inside cluster)219 210 } mapping_irq_t; 220 211 … … 226 217 unsigned int ports; // number of MWMR ports used by coprocessor 227 218 unsigned int port_offset; // index of first MWMR port used by coprocessor 228 unsigned int regs; // number of config/status registers229 unsigned int reg_offset; // index of first register230 219 } mapping_coproc_t; 231 220 232 //////////////////////////////// ///////233 typedef struct mapping_c oproc_port_s221 //////////////////////////////// 222 typedef struct mapping_cp_port_s 234 223 { 235 224 unsigned int direction; // TO_COPROC == 0 / FROM_COPROC == 1 236 unsigned int vspaceid; // global index of the vspace containing the MWMR channel 237 unsigned int vobjlocid; // local(to vspace) index of the vobj containing the MWMR channel 238 } mapping_coproc_port_t; 239 240 /////////////////////////////////// 241 typedef struct mapping_coproc_reg_s 242 { 243 char name[32]; // register name 244 unsigned int type; // STATUS = 0 / CONFIG == 1 245 unsigned int loc_id; // register index in coprocessor (word offset) 246 unsigned int channel_id; // channel index in coprocessor (page offset) 247 unsigned int value; // initialisation value 248 } mapping_coproc_reg_t; 225 unsigned int vspaceid; // index of the vspace containing the MWMR channel 226 unsigned int vobjlocid; // local index of the vobj containing the MWMR channel 227 } mapping_cp_port_t; 228 229 /////////////////////////////// 230 typedef struct mapping_periph_s 231 { 232 unsigned int type; // IOC / TTY / TIM / DMA / FBF / NIC / IOB 233 unsigned int psegid; // pseg index in cluster 234 unsigned int channels; // number of channels 235 } mapping_periph_t; 236 249 237 250 238 #endif -
soft/giet_vm/xml/xml_driver.c
r181 r189 17 17 #include <mapping_info.h> 18 18 19 ///////////////////////////////////////////////////// 20 void buildXml( mapping_header_t* header, FILE* fpout )19 ////////////////////////////////////////////////////// 20 void buildXml( mapping_header_t* header, FILE* fpout ) 21 21 { 22 23 22 const char* vobj_type[] = 24 23 { … … 30 29 "LOCK", // Spin-Lock 31 30 "BUFFER", // Any "no intialiasation needed" objects (stacks...) 32 "BARRIER" // Barrier31 "BARRIER", // Barrier 33 32 }; 34 33 … … 37 36 "RAM", 38 37 "ROM", 39 "PERI" 38 "PERI", 40 39 }; 41 40 … … 43 42 { 44 43 "HARD", 45 "SOFT" 44 "SOFT", 46 45 }; 47 46 48 47 const char* isr_type[] = 49 48 { 49 "ISR_DEFAULT", 50 "ISR_SWITCH", 51 "ISR_TTY", 52 "ISR_DMA", 50 53 "ISR_IOC", 51 "ISR_FBDMA", 52 "ISR_TTY" 53 }; 54 55 const char* reg_type[] = 56 { 57 "STATUS", 58 "CONFIG" 54 "ISR_TIMER", 55 }; 56 57 const char* periph_type[] = 58 { 59 "IOC", 60 "TTY", 61 "TIM", 62 "DMA", 63 "FBF", 64 "NIC", 65 "IOB", 59 66 }; 60 67 … … 62 69 { 63 70 "TO_COPROC", 64 "FROM_COPROC" 71 "FROM_COPROC", 65 72 }; 66 73 … … 81 88 "CX_U", 82 89 "CXW_", 83 "CXWU" 90 "CXWU", 84 91 }; 85 92 … … 94 101 unsigned int coproc_id; 95 102 unsigned int port_id; 96 unsigned int reg_id;97 98 mapping_cluster_t* 99 mapping_pseg_t* 100 mapping_vspace_t* 101 mapping_vseg_t* 102 mapping_vobj_t* 103 mapping_task_t* 104 mapping_proc_t* 105 mapping_irq_t* 106 mapping_coproc_t* 107 mapping_c oproc_port_t* cp_port;108 mapping_ coproc_reg_t* cp_reg;103 unsigned int periph_id; 104 105 mapping_cluster_t* cluster; 106 mapping_pseg_t* pseg; 107 mapping_vspace_t* vspace; 108 mapping_vseg_t* vseg; 109 mapping_vobj_t* vobj; 110 mapping_task_t* task; 111 mapping_proc_t* proc; 112 mapping_irq_t* irq; 113 mapping_coproc_t* coproc; 114 mapping_cp_port_t* cp_port; 115 mapping_periph_t* periph; 109 116 110 117 // computes the base adresss for clusters array, … … 147 154 MAPPING_VSEG_SIZE*header->vsegs ); 148 155 149 // computes the base address thearray156 // computes the base address for procs array 150 157 proc = (mapping_proc_t*) ((char*)header + 151 158 MAPPING_HEADER_SIZE + … … 157 164 MAPPING_TASK_SIZE*header->tasks); 158 165 159 // computes the base address the array 160 irq = (mapping_irq_t*) ((char*)header + 161 MAPPING_HEADER_SIZE + 162 MAPPING_CLUSTER_SIZE*header->clusters + 163 MAPPING_PSEG_SIZE*header->psegs + 164 MAPPING_VSPACE_SIZE*header->vspaces + 165 MAPPING_VOBJ_SIZE*header->vobjs + 166 MAPPING_VSEG_SIZE*header->vsegs+ 167 MAPPING_TASK_SIZE*header->tasks+ 168 MAPPING_PROC_SIZE*header->procs 169 ); 170 171 // computes the base address the array 172 coproc = (mapping_coproc_t*) ((char*)header + 173 MAPPING_HEADER_SIZE + 174 MAPPING_CLUSTER_SIZE*header->clusters + 175 MAPPING_PSEG_SIZE*header->psegs + 176 MAPPING_VSPACE_SIZE*header->vspaces + 177 MAPPING_VOBJ_SIZE*header->vobjs + 178 MAPPING_VSEG_SIZE*header->vsegs+ 179 MAPPING_TASK_SIZE*header->tasks+ 180 MAPPING_PROC_SIZE*header->procs+ 181 MAPPING_IRQ_SIZE*header->irqs 182 ); 183 184 // computes the base address the array 185 cp_port = (mapping_coproc_port_t*) ((char*)header + 186 MAPPING_HEADER_SIZE + 187 MAPPING_CLUSTER_SIZE*header->clusters + 188 MAPPING_PSEG_SIZE*header->psegs + 189 MAPPING_VSPACE_SIZE*header->vspaces + 190 MAPPING_VOBJ_SIZE*header->vobjs + 191 MAPPING_VSEG_SIZE*header->vsegs+ 192 MAPPING_TASK_SIZE*header->tasks+ 193 MAPPING_PROC_SIZE*header->procs+ 194 MAPPING_IRQ_SIZE*header->irqs+ 195 MAPPING_COPROC_SIZE*header->coprocs 196 ); 197 198 // computes the base address the array 199 cp_reg = (mapping_coproc_reg_t*) ((char*)header + 200 MAPPING_HEADER_SIZE + 201 MAPPING_CLUSTER_SIZE*header->clusters + 202 MAPPING_PSEG_SIZE*header->psegs + 203 MAPPING_VSPACE_SIZE*header->vspaces + 204 MAPPING_VOBJ_SIZE*header->vobjs + 205 MAPPING_VSEG_SIZE*header->vsegs+ 206 MAPPING_TASK_SIZE*header->tasks+ 207 MAPPING_PROC_SIZE*header->procs+ 208 MAPPING_IRQ_SIZE*header->irqs+ 209 MAPPING_COPROC_SIZE*header->coprocs+ 210 MAPPING_CP_PORT_SIZE*header->cp_ports 211 ); 166 // computes the base address for irqs array 167 irq = (mapping_irq_t*) ((char*)header + 168 MAPPING_HEADER_SIZE + 169 MAPPING_CLUSTER_SIZE*header->clusters + 170 MAPPING_PSEG_SIZE*header->psegs + 171 MAPPING_VSPACE_SIZE*header->vspaces + 172 MAPPING_VOBJ_SIZE*header->vobjs + 173 MAPPING_VSEG_SIZE*header->vsegs + 174 MAPPING_TASK_SIZE*header->tasks + 175 MAPPING_PROC_SIZE*header->procs); 176 177 // computes the base address for coprocs array 178 coproc = (mapping_coproc_t*) ((char*)header + 179 MAPPING_HEADER_SIZE + 180 MAPPING_CLUSTER_SIZE*header->clusters + 181 MAPPING_PSEG_SIZE*header->psegs + 182 MAPPING_VSPACE_SIZE*header->vspaces + 183 MAPPING_VOBJ_SIZE*header->vobjs + 184 MAPPING_VSEG_SIZE*header->vsegs + 185 MAPPING_TASK_SIZE*header->tasks + 186 MAPPING_PROC_SIZE*header->procs + 187 MAPPING_IRQ_SIZE*header->irqs); 188 189 // computes the base address for cp_ports array 190 cp_port = (mapping_cp_port_t*)((char*)header + 191 MAPPING_HEADER_SIZE + 192 MAPPING_CLUSTER_SIZE*header->clusters + 193 MAPPING_PSEG_SIZE*header->psegs + 194 MAPPING_VSPACE_SIZE*header->vspaces + 195 MAPPING_VOBJ_SIZE*header->vobjs + 196 MAPPING_VSEG_SIZE*header->vsegs + 197 MAPPING_TASK_SIZE*header->tasks + 198 MAPPING_PROC_SIZE*header->procs + 199 MAPPING_IRQ_SIZE*header->irqs + 200 MAPPING_COPROC_SIZE*header->coprocs); 201 202 // computes the base address for periphs array 203 periph = (mapping_periph_t*) ((char*)header + 204 MAPPING_HEADER_SIZE + 205 MAPPING_CLUSTER_SIZE*header->clusters + 206 MAPPING_PSEG_SIZE*header->psegs + 207 MAPPING_VSPACE_SIZE*header->vspaces + 208 MAPPING_VOBJ_SIZE*header->vobjs + 209 MAPPING_VSEG_SIZE*header->vsegs + 210 MAPPING_TASK_SIZE*header->tasks + 211 MAPPING_PROC_SIZE*header->procs + 212 MAPPING_IRQ_SIZE*header->irqs + 213 MAPPING_COPROC_SIZE*header->coprocs + 214 MAPPING_CP_PORT_SIZE*header->cp_ports); 215 216 ///////////////////////// header ///////////////////////////////////////////// 212 217 213 218 fprintf( fpout, "<?xml version = \"1.0\"?>\n\n"); 214 215 ///////////////////////// header /////////////////////////////////////////////216 219 217 220 fprintf( fpout, "<mapping_info signature = \"0x%x\"\n", header->signature); 218 221 fprintf( fpout, " name = \"%s\"\n", header->name); 219 222 fprintf( fpout, " clusters = \"%d\"\n", header->clusters); 220 fprintf( fpout, " ttys = \"%d\"\n", header->ttys);221 fprintf( fpout, " fbs = \"%d\"\n", header->fbs);222 223 fprintf( fpout, " vspaces = \"%d\"\n", header->vspaces); 223 224 fprintf( fpout, " globals = \"%d\" >\n\n", header->globals); … … 238 239 fprintf( fpout, " length = \"0x%x\" />\n", pseg[pseg_id].length); 239 240 } 241 242 ///////////////////// processors ///////////////////////////////////////////// 243 240 244 for ( proc_id = cluster[cluster_id].proc_offset ; 241 245 proc_id < cluster[cluster_id].proc_offset + cluster[cluster_id].procs ; … … 253 257 } 254 258 259 260 ///////////////////// coprocessors /////////////////////////////////////////// 261 255 262 for ( coproc_id = cluster[cluster_id].coproc_offset ; 256 263 coproc_id < cluster[cluster_id].coproc_offset + cluster[cluster_id].coprocs ; … … 266 273 fprintf( fpout, " vobjname = \"%s\" />\n", vobj[vobj_id].name); 267 274 } 268 for ( reg_id = coproc[coproc_id].reg_offset ;269 reg_id < coproc[coproc_id].reg_offset+coproc[coproc_id].regs ;270 reg_id++ )271 {272 fprintf( fpout, " <reg name = \"%s\"\n", cp_reg[reg_id].name);273 fprintf( fpout, " type = \"%s\"\n", reg_type[cp_reg[reg_id].type]);274 fprintf( fpout, " value = \"0x%x\"\n", cp_reg[reg_id].value);275 fprintf( fpout, " channel = \"0x%x\"\n", cp_reg[reg_id].channel_id);276 fprintf( fpout, " index = \"0x%x\" />\n", cp_reg[reg_id].loc_id);277 }278 275 fprintf( fpout, " </coproc>\n" ); 276 } 277 278 ///////////////////// periphs /////////////////////////////////////////////// 279 280 for ( periph_id = cluster[cluster_id].periph_offset ; 281 periph_id < cluster[cluster_id].periph_offset + cluster[cluster_id].periphs ; 282 periph_id++ ) 283 { 284 fprintf( fpout, " <periph type = \"%s\"\n", periph_type[periph[periph_id].type]); 285 fprintf( fpout, " psegname = \"%s\"\n", pseg[periph[periph_id].psegid].name); 286 fprintf( fpout, " channels = \"%d\" />\n", periph[periph_id].channels); 279 287 } 280 288 fprintf( fpout, " </cluster>\n" ); … … 356 364 fprintf( fpout, " startid = \"%d\"\n", task[task_id].startid); 357 365 fprintf( fpout, " usetty = \"%d\"\n", task[task_id].use_tty); 358 fprintf( fpout, " usefb = \"%d\" />\n\n", task[task_id].use_fb); 366 fprintf( fpout, " usenic = \"%d\"\n", task[task_id].use_nic); 367 fprintf( fpout, " usetimer = \"%d\"\n", task[task_id].use_timer); 368 fprintf( fpout, " usefbma = \"%d\" />\n\n", task[task_id].use_fbdma); 359 369 } 360 370 fprintf( fpout, " </vspace>\n\n"); -
soft/giet_vm/xml/xml_parser.c
r188 r189 20 20 #include <libxml/xmlreader.h> 21 21 #include <mapping_info.h> 22 #include <irq_handler.h> 22 23 23 24 #define MAX_CLUSTERS 1024 … … 32 33 #define MAX_COPROCS 4096 33 34 #define MAX_CP_PORTS 8192 34 #define MAX_ CP_REGS 819235 #define MAX_PERIPHS 8192 35 36 36 37 #define XML_PARSER_DEBUG 0 … … 49 50 mapping_proc_t* proc[MAX_PROCS]; // proc array 50 51 mapping_irq_t* irq[MAX_IRQS]; // irq array 51 mapping_coproc_t* coproc[MAX_COPROCS]; // coproc array 52 mapping_coproc_port_t* cp_port[MAX_CP_PORTS]; // coproc port array 53 mapping_coproc_reg_t* cp_reg[MAX_CP_REGS]; // coproc reg array 54 55 typedef struct vobj_ref_s 56 { 57 char vspace_name[32]; 58 char vobj_name[32]; 59 }vobj_ref_t; 60 61 // This arrray is useful to temporary save the a vobj referece 62 // formed by a vspace_name and a vobj_name (struct vobj_ref_s). 63 // This arry will be used to set the attribute vobj_id of coproc_port 64 // once all the vspace have been parsed. 65 vobj_ref_t* cp_port_vobj_ref[MAX_CP_PORTS]; 52 mapping_coproc_t* coproc[MAX_COPROCS]; // coproc array 53 mapping_cp_port_t* cp_port[MAX_CP_PORTS]; // coproc port array 54 mapping_periph_t* periph[MAX_PERIPHS]; // peripheral array 55 56 // Index for the various arrays 66 57 67 58 unsigned int cluster_index = 0; … … 82 73 unsigned int cp_port_loc_index = 0; 83 74 84 unsigned int cp_reg_index = 0;85 unsigned int cp_reg_loc_index = 0;75 unsigned int periph_index = 0; 76 unsigned int periph_loc_index = 0; 86 77 87 78 unsigned int vseg_index = 0; 88 79 unsigned int vseg_loc_index = 0; 80 89 81 unsigned int task_index = 0; 90 82 unsigned int task_loc_index = 0; 83 91 84 unsigned int vobj_index = 0; 92 85 unsigned int vobj_loc_index = 0; 93 86 unsigned int vobj_count = 0; 94 87 95 unsigned int tty_index = 1; 96 unsigned int fb_index = 0; 97 88 /////////////////////////////////////////////////////////////////////// 89 // This arrray is useful to build a temporary list of vobj references. 90 // The struct vobj_ref_s is formed by a vspace_name and a vobj_name. 91 // This array is used to set the attribute vobj_id of a cp_port 92 // once all the vspace have been parsed. 93 94 typedef struct vobj_ref_s 95 { 96 char vspace_name[32]; 97 char vobj_name[32]; 98 }vobj_ref_t; 99 100 vobj_ref_t* cp_port_vobj_ref[MAX_CP_PORTS]; 101 102 98 103 ////////////////////////////////////////////////// 99 104 unsigned int getIntValue( xmlTextReaderPtr reader, … … 183 188 //////////////////////////////////////////// 184 189 int getVspaceId( char* vspace_name) 185 ////////////////////////////////////////////186 190 { 187 191 unsigned int vspace_id; … … 201 205 char* vobj_name, 202 206 unsigned int vspace_max) 203 ////////////////////////////////////////////204 207 { 205 208 unsigned int vobj_id; … … 235 238 #endif 236 239 237 cp_port[cp_port_index] = (mapping_c oproc_port_t*)malloc(sizeof(mapping_coproc_port_t));240 cp_port[cp_port_index] = (mapping_cp_port_t*)malloc(sizeof(mapping_cp_port_t)); 238 241 cp_port_vobj_ref[cp_port_index] = (vobj_ref_t*)malloc(sizeof(vobj_ref_t)); 239 242 … … 251 254 else 252 255 { 253 printf("[XML ERROR] illegal <direction> for c oproc_port %d in cluster %d\n",256 printf("[XML ERROR] illegal <direction> for cp_port %d in cluster %d\n", 254 257 cp_port_index, cluster_index); 255 258 exit(1); … … 258 261 else 259 262 { 260 printf("[XML ERROR] missing <direction> for c oproc_port %d in cluster %d\n",263 printf("[XML ERROR] missing <direction> for cp_port %d in cluster %d\n", 261 264 cp_port_index, cluster_index); 262 265 exit(1); … … 274 277 else 275 278 { 276 printf("[XML ERROR] missing <vspacename> for c oproc_port %d in cluster %d\n",279 printf("[XML ERROR] missing <vspacename> for cp_port %d in cluster %d\n", 277 280 cp_port_index, cluster_index); 278 281 exit(1); … … 290 293 else 291 294 { 292 printf("[XML ERROR] missing <vobjname> for c oproc_port %d in cluster %d\n",295 printf("[XML ERROR] missing <vobjname> for cp_port %d in cluster %d\n", 293 296 cp_port_index, cluster_index); 294 297 exit(1); … … 300 303 } // end cpPortNode() 301 304 302 ///////////////////////////////////////// 303 void cpRegNode ( xmlTextReaderPtr reader )304 ///////////////////////////////////////// 305 /////////////////////////////////////////// 306 void periphNode ( xmlTextReaderPtr reader ) 307 /////////////////////////////////////////// 305 308 { 306 309 char* str; 307 310 unsigned int value; 308 unsigned int 311 unsigned int ok; 309 312 310 313 if ( xmlTextReaderNodeType(reader) == XML_READER_TYPE_END_ELEMENT ) return; 311 314 312 /* TWO: check source file consistency if possible */ 313 if ( cp_reg_index >= MAX_CP_REGS ) 314 { 315 printf("[XML ERROR] The number of regs (for coprocs) is larger than %d\n", MAX_CP_REGS); 316 } 317 318 #if XML_PARSER_DEBUG 319 printf("\n reg %d\n", cp_reg_index); 320 #endif 321 322 /* THIRD*/ 323 cp_reg[cp_reg_index] = (mapping_coproc_reg_t*)malloc(sizeof(mapping_coproc_reg_t)); 324 325 /* FOURTH: read all attribute*/ 326 327 /////////// get name attribute 328 str = getStringValue( reader, "name", &ok ); 329 #if XML_PARSER_DEBUG 330 printf(" name = %s\n", str); 331 #endif 315 if ( periph_index >= MAX_PERIPHS ) 316 { 317 printf("[XML ERROR] The number of periphs is larger than %d\n", MAX_PERIPHS); 318 } 319 320 #if XML_PARSER_DEBUG 321 printf("\n periph %d\n", periph_index); 322 #endif 323 324 periph[periph_index] = (mapping_periph_t*)malloc(sizeof(mapping_periph_t)); 325 326 /////////// get type attribute 327 str = getStringValue( reader, "type", &ok ); 332 328 if ( ok ) 333 329 { 334 strncpy(cp_reg[cp_reg_index]->name, str, 31); 335 } 336 else 337 { 338 printf("[XML ERROR] illegal or missing <name> for coproc_reg %d in cluster %d\n", 339 cp_reg_index, cluster_index); 340 exit(1); 341 } 330 #if XML_PARSER_DEBUG 331 printf(" type = %s\n", str); 332 #endif 333 unsigned int error = 0; 334 335 // The TTY, IOC, NIC, FBF and IOB peripherals cannot be replicated 336 if ( strcmp( str, "IOC" ) == 0 ) 337 { 338 periph[periph_index]->type = PERIPH_TYPE_IOC; 339 if ( header->ioc_clusterid == 0xFFFFFFFF) header->ioc_clusterid = cluster_index; 340 else error = 1; 341 } 342 else if ( strcmp( str, "TTY" ) == 0 ) 343 { 344 periph[periph_index]->type = PERIPH_TYPE_TTY; 345 if ( header->ioc_clusterid == 0xFFFFFFFF) header->ioc_clusterid = cluster_index; 346 else error = 1; 347 } 348 else if ( strcmp( str, "FBF" ) == 0 ) 349 { 350 periph[periph_index]->type = PERIPH_TYPE_FBF; 351 if ( header->ioc_clusterid == 0xFFFFFFFF) header->ioc_clusterid = cluster_index; 352 else error = 1; 353 } 354 else if ( strcmp( str, "NIC" ) == 0 ) 355 { 356 periph[periph_index]->type = PERIPH_TYPE_NIC; 357 if ( header->ioc_clusterid == 0xFFFFFFFF) header->ioc_clusterid = cluster_index; 358 else error = 1; 359 } 360 // The TIM, DMA and IOB peripherals can be replicated in several clusters 361 else if ( strcmp( str, "TIM" ) == 0 ) 362 { 363 periph[periph_index]->type = PERIPH_TYPE_TIM; 364 } 365 else if ( strcmp( str, "DMA" ) == 0 ) 366 { 367 periph[periph_index]->type = PERIPH_TYPE_DMA; 368 } 369 else if ( strcmp( str, "IOB" ) == 0 ) 370 { 371 periph[periph_index]->type = PERIPH_TYPE_IOB; 372 } 373 else 374 { 375 printf("[XML ERROR] illegal <type> for peripheral %d in cluster %d\n", 376 periph_loc_index, cluster_index); 377 exit(1); 378 } 379 } 380 else 381 { 382 printf("[XML ERROR] missing <type> for peripheral %d in cluster %d\n", 383 periph_loc_index, cluster_index); 384 exit(1); 385 } 386 387 ///////// get channels attribute (optionnal : 1 if missing) 388 value = getIntValue( reader, "channels", &ok ); 389 if ( ok ) 390 { 391 #if XML_PARSER_DEBUG 392 printf(" channels = %d\n", value); 393 #endif 394 periph[periph_index]->channels = value; 395 } 396 else 397 { 398 periph[periph_index]->channels = 1; 399 } 400 401 /////////// get psegname attribute 402 str = getStringValue(reader,"psegname", &ok); 403 if ( ok == 0 ) 404 { 405 printf("[XML ERROR] illegal or missing <psegname> for coproc %d in cluster %d\n", 406 coproc_index, cluster_index); 407 exit(1); 408 } 409 410 /////////// set psegid attribute 411 int index = getPsegId( cluster_index, str ); 412 if ( index >= 0 ) 413 { 414 #if XML_PARSER_DEBUG 415 printf(" clusterid = %d\n", cluster_index); 416 printf(" psegname = %s\n", str); 417 printf(" psegid = %d\n", index); 418 #endif 419 periph[periph_index]->psegid = index; 420 assert(pseg[index]->type == PSEG_TYPE_PERI && 421 "peripheral psegname attribute must refer to a pseg of type PERI" ); 422 } 423 else 424 { 425 printf("[XML ERROR] pseg not found for periph %d / clusterid = %d / psegname = %s\n", 426 periph_loc_index, cluster_index, str ); 427 exit(1); 428 } 342 429 343 ///////// get type attribute 344 str = getStringValue( reader, "type", &ok ); 345 if ( ok ) 346 { 347 #if XML_PARSER_DEBUG 348 printf(" type = %s\n", str); 349 #endif 350 if ( strcmp(str, "STATUS") ) cp_reg[cp_reg_index]->type = REG_TYPE_STATUS; 351 else if ( strcmp(str, "CONFIG") ) cp_reg[cp_reg_index]->type = REG_TYPE_CONFIG; 352 else 353 { 354 printf("[XML ERROR] illegal <type> for coproc_reg %d in cluster %d\n", 355 cp_reg_index, cluster_index); 356 exit(1); 357 } 358 } 359 else 360 { 361 printf("[XML ERROR] missing <type> for coproc_reg %d in cluster %d\n", 362 cp_reg_index, cluster_index); 363 exit(1); 364 } 365 366 ///////// get value attribute 367 value = getIntValue(reader, "value", &ok); 368 if ( ok ) 369 { 370 #if XML_PARSER_DEBUG 371 printf(" value = %d\n", value); 372 #endif 373 cp_reg[cp_reg_index]->value = value; 374 } 375 else 376 { 377 printf("[XML ERROR] illegal or missing <value> for coproc_reg %d in cluster %d\n", 378 cp_reg_index, cluster_index); 379 exit(1); 380 } 381 382 ///////// get channel attribute 383 value = getIntValue(reader, "channel", &ok); 384 if ( ok ) 385 { 386 #if XML_PARSER_DEBUG 387 printf(" channel = %d\n", value); 388 #endif 389 cp_reg[cp_reg_index]->channel_id = value; 390 } 391 else 392 { 393 printf("[XML ERROR] illegal or missing <channel> for coproc_reg %d in cluster %d\n", 394 cp_reg_index, cluster_index); 395 exit(1); 396 } 397 398 ///////// get index attribute 399 value = getIntValue(reader, "index", &ok); 400 if ( ok ) 401 { 402 #if XML_PARSER_DEBUG 403 printf(" index = %d\n", value); 404 #endif 405 cp_reg[cp_reg_index]->loc_id = value; 406 } 407 else 408 { 409 printf("[XML ERROR] illegal or missing <index> for coproc_reg %d in cluster %d\n", 410 cp_reg_index, cluster_index); 411 exit(1); 412 } 413 414 cp_reg_index++; 415 cp_reg_loc_index++; 416 417 } // end cpRegNode() 430 periph_index++; 431 periph_loc_index++; 432 433 } // end periphNode 418 434 419 435 ///////////////////////////////////////// … … 425 441 426 442 cp_port_loc_index = 0; 427 cp_reg_loc_index = 0;428 443 429 444 if ( xmlTextReaderNodeType(reader) == XML_READER_TYPE_END_ELEMENT ) return; … … 439 454 440 455 coproc[coproc_index] = (mapping_coproc_t*)malloc(sizeof(mapping_coproc_t)); 441 442 456 443 457 /////////// get name attribute … … 485 499 } 486 500 487 ////////// set port_offset and reg_offset attribute501 ////////// set port_offset 488 502 coproc[coproc_index]->port_offset = cp_port_index; 489 coproc[coproc_index]->reg_offset = cp_reg_index; 490 491 #if XML_PARSER_DEBUG 492 printf(" port_offset = %d\n", cp_port_index); 493 printf(" reg_offset = %d\n", cp_reg_index); 503 504 #if XML_PARSER_DEBUG 505 printf(" port_offset = %d\n", cp_port_index); 494 506 #endif 495 507 … … 499 511 const char* tag = (const char*)xmlTextReaderConstName(reader); 500 512 501 if ( strcmp(tag,"port") == 0 ) cpPortNode(reader); 502 else if ( strcmp(tag,"reg") == 0 ) cpRegNode(reader); 503 else if ( strcmp(tag,"#text" ) == 0 ) { } 504 else if ( strcmp(tag,"#comment") == 0 ); 505 else if ( strcmp(tag,"coproc") == 0 ) 513 if ( strcmp(tag, "port") == 0 ) cpPortNode(reader); 514 else if ( strcmp(tag, "#text") == 0 ) { } 515 else if ( strcmp(tag, "#comment") == 0 ) { } 516 else if ( strcmp(tag, "coproc") == 0 ) 506 517 { 507 518 coproc[coproc_index]->ports = cp_port_loc_index; 508 coproc[coproc_index]->regs = cp_reg_loc_index;509 519 coproc_loc_index++; 510 520 coproc_index++; … … 548 558 printf(" type = %s\n", str); 549 559 #endif 550 if ( strcmp(str, "HARD") ) irq[irq_index]->type = IRQ_TYPE_HARD;551 else if ( strcmp(str, "SOFT") ) irq[irq_index]->type = IRQ_TYPE_SOFT;560 if ( strcmp(str, "HARD") == 0 ) irq[irq_index]->type = 0; 561 else if ( strcmp(str, "SOFT") == 0 ) irq[irq_index]->type = 1; 552 562 else 553 563 { … … 564 574 } 565 575 566 ///////// get i rqid attribute576 ///////// get icuid attribute 567 577 value = getIntValue(reader, "icuid", &ok); 568 578 if ( ok ) … … 593 603 printf(" isr = %s\n", str); 594 604 #endif 595 if ( strcmp(str, "ISR_SWITCH") ) irq[irq_index]->isr = ISR_SWITCH; 596 else if ( strcmp(str, "ISR_IOC") ) irq[irq_index]->isr = ISR_IOC; 597 else if ( strcmp(str, "ISR_FBDMA") ) irq[irq_index]->isr = ISR_FBDMA; 598 else if ( strcmp(str, "ISR_TTY") ) irq[irq_index]->isr = ISR_TTY; 605 if ( strcmp(str, "ISR_SWITCH" ) == 0 ) irq[irq_index]->isr = ISR_SWITCH; 606 else if ( strcmp(str, "ISR_IOC" ) == 0 ) irq[irq_index]->isr = ISR_IOC; 607 else if ( strcmp(str, "ISR_DMA" ) == 0 ) irq[irq_index]->isr = ISR_DMA; 608 else if ( strcmp(str, "ISR_TTY" ) == 0 ) irq[irq_index]->isr = ISR_TTY; 609 else if ( strcmp(str, "ISR_TIMER" ) == 0 ) irq[irq_index]->isr = ISR_TIMER; 599 610 else 600 611 { … … 603 614 exit(1); 604 615 } 616 #if XML_PARSER_DEBUG 617 printf(" isrnum = %d\n", irq[irq_index]->isr); 618 #endif 605 619 } 606 620 else … … 664 678 ////////// set irq_offset attribute 665 679 proc[proc_index]->irq_offset = irq_index; 680 666 681 #if XML_PARSER_DEBUG 667 682 printf(" irq_offset = %d\n", irq_index); … … 673 688 const char* tag = (const char*)xmlTextReaderConstName(reader); 674 689 675 if ( strcmp(tag, "irq")== 0 ) irqNode(reader);676 else if ( strcmp(tag, "#text")== 0 ) { }677 else if ( strcmp(tag, "#comment") == 0 );678 else if ( strcmp(tag, "proc")== 0 )690 if ( strcmp(tag, "irq") == 0 ) irqNode(reader); 691 else if ( strcmp(tag, "#text") == 0 ) { } 692 else if ( strcmp(tag, "#comment") == 0 ) { } 693 else if ( strcmp(tag, "proc") == 0 ) 679 694 { 680 695 proc[proc_index]->irqs = irq_loc_index; … … 817 832 } 818 833 819 /////////// get use _tty attribute (optionnal : 0 if missing)834 /////////// get usetty attribute (optionnal : 0 if missing) 820 835 value = getIntValue(reader,"usetty", &ok); 821 836 if ( ok ) … … 824 839 printf(" usetty = %x\n", value); 825 840 #endif 826 if ( (value != 0) && (tty_index >= header->ttys) )827 {828 printf("[XML ERROR] The tty index is too large for task (%d,%d)\n",829 vspace_index, task_loc_index);830 exit(1);831 }832 841 task[task_index]->use_tty = value; 833 if (value != 0) tty_index++;834 842 } 835 843 else … … 838 846 } 839 847 840 /////////// get use_fb attribute (optionnal : 0 if missing) 841 value = getIntValue(reader,"usefb", &ok); 842 if ( ok ) 843 { 844 #if XML_PARSER_DEBUG 845 printf(" usefb = %x\n", value); 846 #endif 847 if ( (value != 0) && (fb_index >= header->fbs) ) 848 { 849 printf("[XML ERROR] The fb channel index is too large for task (%d,%d)\n", 850 vspace_index, task_loc_index); 851 exit(1); 852 } 853 task[task_index]->use_fb = value; 854 if (value != 0) fb_index++; 848 /////////// get usenic attribute (optionnal : 0 if missing) 849 value = getIntValue(reader,"usenic", &ok); 850 if ( ok ) 851 { 852 #if XML_PARSER_DEBUG 853 printf(" usenic = %x\n", value); 854 #endif 855 task[task_index]->use_nic = value; 855 856 } 856 857 else 857 858 { 858 task[task_index]->use_fb = 0; 859 task[task_index]->use_nic = 0; 860 } 861 862 /////////// get usetimer attribute (optionnal : 0 if missing) 863 value = getIntValue(reader,"usetimer", &ok); 864 if ( ok ) 865 { 866 #if XML_PARSER_DEBUG 867 printf(" usetimer = %x\n", value); 868 #endif 869 task[task_index]->use_timer = value; 870 } 871 else 872 { 873 task[task_index]->use_timer = 0; 874 } 875 876 /////////// get usefbdma attribute (optionnal : 0 if missing) 877 value = getIntValue(reader,"usefbdma", &ok); 878 if ( ok ) 879 { 880 #if XML_PARSER_DEBUG 881 printf(" usefbdma = %x\n", value); 882 #endif 883 task[task_index]->use_fbdma = value; 884 } 885 else 886 { 887 task[task_index]->use_fbdma = 0; 859 888 } 860 889 … … 865 894 ////////////////////////////////////////// 866 895 void vobjNode ( xmlTextReaderPtr reader ) 896 ////////////////////////////////////////// 867 897 { 868 898 unsigned int ok; … … 986 1016 else 987 1017 { 988 if((vobj[vobj_index]->type == VOBJ_TYPE_MWMR || vobj[vobj_index]->type == VOBJ_TYPE_BARRIER )) 1018 if( (vobj[vobj_index]->type == VOBJ_TYPE_MWMR) || 1019 (vobj[vobj_index]->type == VOBJ_TYPE_BARRIER) ) 989 1020 { 990 1021 printf("[XML ERROR] illegal or missing <value> attribute for vobj (%d,%d). \ … … 1003 1034 ////////////////////////////////////////// 1004 1035 void vsegNode ( xmlTextReaderPtr reader ) 1036 ////////////////////////////////////////// 1005 1037 { 1006 1038 unsigned int ok; … … 1144 1176 const char* tag = (const char*)xmlTextReaderConstName(reader); 1145 1177 1146 if ( strcmp(tag,"vobj") == 0 ) vobjNode(reader); 1147 else if ( strcmp(tag,"#text" ) == 0 ) { } 1148 else if ( strcmp(tag,"vseg") == 0 ) 1178 if ( strcmp(tag, "vobj") == 0 ) vobjNode(reader); 1179 else if ( strcmp(tag, "#text" ) == 0 ) { } 1180 else if ( strcmp(tag, "#comment") == 0 ) { } 1181 else if ( strcmp(tag, "vseg") == 0 ) 1149 1182 { 1150 1183 vseg[vseg_index]->vobjs = vobj_count; … … 1164 1197 ////////////////////////////////////////// 1165 1198 void vspaceNode( xmlTextReaderPtr reader ) 1199 ////////////////////////////////////////// 1166 1200 { 1167 1201 char* str; … … 1233 1267 const char* tag = (const char*)xmlTextReaderConstName(reader); 1234 1268 1235 if ( strcmp(tag, "vseg")== 0 ) vsegNode(reader);1236 else if ( strcmp(tag, "task")== 0 ) taskNode(reader);1237 else if ( strcmp(tag, "#text")== 0 ) { }1238 else if ( strcmp(tag, "#comment") == 0 );1239 else if ( strcmp(tag, "vspace")== 0 )1269 if ( strcmp(tag, "vseg") == 0 ) vsegNode(reader); 1270 else if ( strcmp(tag, "task") == 0 ) taskNode(reader); 1271 else if ( strcmp(tag, "#text") == 0 ) { } 1272 else if ( strcmp(tag, "#comment") == 0 ) { } 1273 else if ( strcmp(tag, "vspace") == 0 ) 1240 1274 { 1241 1275 vspace[vspace_index]->vobjs = vobj_loc_index; … … 1288 1322 ////////////////////////////////////////// 1289 1323 void psegNode ( xmlTextReaderPtr reader ) 1324 ////////////////////////////////////////// 1290 1325 { 1291 1326 unsigned int ok; … … 1379 1414 ///////////////////////////////////////////// 1380 1415 void clusterNode ( xmlTextReaderPtr reader ) 1416 ///////////////////////////////////////////// 1381 1417 { 1382 1418 unsigned int ok; … … 1385 1421 proc_loc_index = 0; 1386 1422 coproc_loc_index = 0; 1387 cluster[cluster_index]= 0;1423 periph_loc_index = 0; 1388 1424 1389 1425 if ( xmlTextReaderNodeType(reader) == XML_READER_TYPE_END_ELEMENT ) return; … … 1402 1438 cluster[cluster_index] = (mapping_cluster_t*)malloc(sizeof(mapping_cluster_t)); 1403 1439 1404 /////////// getindex attribute (optional)1440 /////////// check cluster index attribute (optional) 1405 1441 value = getIntValue(reader,"index",&ok); 1406 1442 if ( ok && (value != cluster_index) ) … … 1411 1447 } 1412 1448 1413 1414 ////////// set pseg_offset attribute 1415 cluster[cluster_index]->pseg_offset = pseg_index; 1416 cluster[cluster_index]->proc_offset = proc_index; 1449 ////////// set offsets 1450 cluster[cluster_index]->pseg_offset = pseg_index; 1451 cluster[cluster_index]->proc_offset = proc_index; 1417 1452 cluster[cluster_index]->coproc_offset = coproc_index; 1418 #if XML_PARSER_DEBUG 1419 printf(" pseg_offset = %d\n", pseg_index); 1420 printf(" proc_offset = %d\n", proc_index); 1453 cluster[cluster_index]->periph_offset = periph_index; 1454 1455 #if XML_PARSER_DEBUG 1456 printf(" pseg_offset = %d\n", pseg_index); 1457 printf(" proc_offset = %d\n", proc_index); 1421 1458 printf(" coproc_offset = %d\n", coproc_index); 1422 #endif 1423 1424 ////////// get psegs, coproc and/or procs 1459 printf(" periph_offset = %d\n", coproc_index); 1460 #endif 1461 1462 ////////// get psegs, procs, coprocs and periphs 1425 1463 int status = xmlTextReaderRead(reader); 1426 1464 … … 1429 1467 const char* tag = (const char*)xmlTextReaderConstName(reader); 1430 1468 1431 if ( strcmp(tag, "pseg") == 0 ) psegNode(reader); 1432 else if ( strcmp(tag, "proc") == 0 ) procNode(reader); 1433 else if ( strcmp(tag, "coproc") == 0 ) coprocNode(reader); 1434 else if ( strcmp(tag, "#text") == 0 ) { } 1435 else if ( strcmp(tag,"#comment") == 0 ); 1436 else if ( strcmp(tag, "cluster") == 0 ) 1437 { 1438 #if XML_PARSER_DEBUG 1469 if ( strcmp(tag, "pseg") == 0 ) psegNode(reader); 1470 else if ( strcmp(tag, "proc") == 0 ) procNode(reader); 1471 else if ( strcmp(tag, "coproc") == 0 ) coprocNode(reader); 1472 else if ( strcmp(tag, "periph") == 0 ) periphNode(reader); 1473 else if ( strcmp(tag, "#text") == 0 ) { } 1474 else if ( strcmp(tag, "#comment") == 0 ) { } 1475 else if ( strcmp(tag, "cluster") == 0 ) 1476 { 1477 cluster[cluster_index]->procs = proc_loc_index; 1478 cluster[cluster_index]->coprocs = coproc_loc_index; 1479 cluster[cluster_index]->periphs = periph_loc_index; 1480 1481 // cluster[cluster_index]psegs update is done in psegNode(), 1482 // because the coprocNode() call to getPsegId() need it 1483 1484 #if XML_PARSER_DEBUG 1485 printf(" psegs = %d\n", cluster[cluster_index]->psegs); 1486 printf(" procs = %d\n", cluster[cluster_index]->procs); 1487 printf(" coprocs = %d\n", cluster[cluster_index]->coprocs); 1488 printf(" periphs = %d\n", cluster[cluster_index]->periphs); 1439 1489 printf(" end cluster %d\n", cluster_index); 1440 1490 #endif 1441 cluster[cluster_index]->procs = proc_loc_index;1442 cluster[cluster_index]->coprocs = coproc_loc_index;1443 //psegs = pseg_loc_index is done in psegNode(), so coprocNode() call to getPsegId() success1444 1491 cluster_index++; 1445 1492 return; … … 1451 1498 ////////////////////////////////////////////// 1452 1499 void clusterSetNode( xmlTextReaderPtr reader ) 1500 ////////////////////////////////////////////// 1453 1501 { 1454 1502 if ( xmlTextReaderNodeType(reader) == XML_READER_TYPE_END_ELEMENT ) return; … … 1463 1511 const char* tag = (const char*)xmlTextReaderConstName(reader); 1464 1512 1465 if ( strcmp(tag, "cluster")== 0 ) clusterNode(reader);1466 else if ( strcmp(tag, "#text")== 0 ) { }1467 else if ( strcmp(tag, "#comment") == 0 );1468 else if ( strcmp(tag, "clusterset") == 0 )1513 if ( strcmp(tag, "cluster") == 0 ) clusterNode(reader); 1514 else if ( strcmp(tag, "#text") == 0 ) { } 1515 else if ( strcmp(tag, "#comment") == 0 ) { } 1516 else if ( strcmp(tag, "clusterset") == 0 ) 1469 1517 { 1470 1518 // checking source file consistency … … 1479 1527 printf(" end cluster set\n\n"); 1480 1528 #endif 1481 header->psegs = pseg_index;1482 header->procs = proc_index;1483 header->irqs = irq_index;1484 header->coprocs = coproc_index;1529 header->psegs = pseg_index; 1530 header->procs = proc_index; 1531 header->irqs = irq_index; 1532 header->coprocs = coproc_index; 1485 1533 header->cp_ports = cp_port_index; 1486 header->cp_regs = cp_reg_index;1487 1534 return; 1488 1535 } … … 1499 1546 ///////////////////////////////////////////// 1500 1547 void globalSetNode( xmlTextReaderPtr reader ) 1548 ///////////////////////////////////////////// 1501 1549 { 1502 1550 if ( xmlTextReaderNodeType(reader) == XML_READER_TYPE_END_ELEMENT ) return; … … 1511 1559 const char* tag = (const char*)xmlTextReaderConstName(reader); 1512 1560 1513 if ( strcmp(tag, "vseg") == 0) vsegNode(reader);1514 else if ( strcmp(tag, "#text" )== 0 ) { }1515 else if ( strcmp(tag, "#comment") == 0 );1516 else if ( strcmp(tag, "globalset") == 0)1561 if ( strcmp(tag, "vseg") == 0 ) vsegNode(reader); 1562 else if ( strcmp(tag, "#text" ) == 0 ) { } 1563 else if ( strcmp(tag, "#comment") == 0 ) { } 1564 else if ( strcmp(tag, "globalset") == 0 ) 1517 1565 { 1518 1566 // checking source file consistency … … 1542 1590 ///////////////////////////////////////////// 1543 1591 void vspaceSetNode( xmlTextReaderPtr reader ) 1592 ///////////////////////////////////////////// 1544 1593 { 1545 1594 if ( xmlTextReaderNodeType(reader) == XML_READER_TYPE_END_ELEMENT ) return; … … 1554 1603 const char* tag = (const char*)xmlTextReaderConstName(reader); 1555 1604 1556 if ( strcmp(tag, "vspace") == 0) vspaceNode(reader);1557 else if ( strcmp(tag, "#text") == 0 ) { }1558 else if ( strcmp(tag, "#comment") == 0 );1559 else if ( strcmp(tag, "vspaceset") == 0)1605 if ( strcmp(tag, "vspace" ) == 0 ) vspaceNode(reader); 1606 else if ( strcmp(tag, "#text" ) == 0 ) { } 1607 else if ( strcmp(tag, "#comment" ) == 0 ) { } 1608 else if ( strcmp(tag, "vspaceset") == 0 ) 1560 1609 { 1561 1610 // checking source file consistency … … 1584 1633 ////////////////////////////////////////// 1585 1634 void headerNode(xmlTextReaderPtr reader ) 1635 ////////////////////////////////////////// 1586 1636 { 1587 1637 char* name; … … 1632 1682 } 1633 1683 1634 ///////// get ttys attribute1635 value = getIntValue(reader, "ttys", &ok);1636 if ( ok )1637 {1638 #if XML_PARSER_DEBUG1639 printf(" ttys = %d\n", value);1640 #endif1641 header->ttys = value;1642 }1643 else1644 {1645 printf("[XML ERROR] illegal or missing <ttys> attribute in header\n");1646 exit(1);1647 }1648 1649 ///////// get fbs attribute1650 value = getIntValue(reader, "fbs", &ok);1651 if ( ok )1652 {1653 #if XML_PARSER_DEBUG1654 printf(" fbs = %d\n", value);1655 #endif1656 header->fbs = value;1657 }1658 else1659 {1660 printf("[XML ERROR] illegal or missing <fbs> attribute in header\n");1661 exit(1);1662 }1663 1664 1684 ///////// get vspaces attribute 1665 1685 value = getIntValue(reader, "vspaces", &ok); … … 1702 1722 } 1703 1723 1724 //////// initialise non replicated peripherals cluster_id 1725 header->tty_clusterid = 0xFFFFFFFF; 1726 header->nic_clusterid = 0xFFFFFFFF; 1727 header->ioc_clusterid = 0xFFFFFFFF; 1728 header->fbf_clusterid = 0xFFFFFFFF; 1729 1730 ///////// set signature 1704 1731 header->signature = IN_MAPPING_SIGNATURE; 1705 1732 … … 1709 1736 const char* tag = (const char*)xmlTextReaderConstName(reader); 1710 1737 1711 if ( strcmp(tag, "clusterset") == 0 ) clusterSetNode(reader);1712 else if ( strcmp(tag, "globalset") == 0 ) globalSetNode(reader);1713 else if ( strcmp(tag, "vspaceset") == 0 ) vspaceSetNode(reader);1714 else if ( strcmp(tag, "#text") == 0 ) ;1715 else if ( strcmp(tag, "#comment") == 0 ) ;1716 else if ( strcmp(tag, "mapping_info") == 0 )1738 if ( strcmp(tag, "clusterset") == 0 ) clusterSetNode(reader); 1739 else if ( strcmp(tag, "globalset") == 0 ) globalSetNode(reader); 1740 else if ( strcmp(tag, "vspaceset") == 0 ) vspaceSetNode(reader); 1741 else if ( strcmp(tag, "#text") == 0 ) { } 1742 else if ( strcmp(tag, "#comment") == 0 ) { } 1743 else if ( strcmp(tag, "mapping_info") == 0 ) 1717 1744 { 1718 1745 #if XML_PARSER_DEBUG … … 1730 1757 } // end headerNode() 1731 1758 1759 /////////////////////////////////////// 1732 1760 void BuildTable( int fdout, 1733 1761 const char* type, … … 1735 1763 unsigned int elem_size, 1736 1764 char** table) 1765 //////////////////////////////////////// 1737 1766 { 1738 1767 unsigned int i; … … 1758 1787 /////////////////////////// 1759 1788 void buildBin( int fdout ) 1789 /////////////////////////// 1760 1790 { 1761 1791 unsigned int vspace_id; … … 1823 1853 } 1824 1854 1825 // write tasks 1855 // write tasks array 1826 1856 BuildTable(fdout, "task", task_index, sizeof(mapping_task_t), (char**) task); 1827 //building proc 1857 //building procs array 1828 1858 BuildTable(fdout, "proc", proc_index, sizeof(mapping_proc_t), (char**) proc); 1829 //building irq 1859 //building irqs array 1830 1860 BuildTable(fdout, "irq", irq_index, sizeof(mapping_irq_t), (char**)irq); 1831 //building coproc 1861 //building coprocs array 1832 1862 BuildTable(fdout, "coproc", coproc_index, sizeof(mapping_coproc_t), (char**)coproc); 1833 //building cp_port 1834 BuildTable(fdout, "cp_port", cp_port_index, sizeof(mapping_c oproc_port_t),(char**) cp_port);1835 //building cp_reg1836 BuildTable(fdout, " cp_reg", cp_reg_index, sizeof(mapping_coproc_reg_t), (char**)cp_reg);1863 //building cp_ports array 1864 BuildTable(fdout, "cp_port", cp_port_index, sizeof(mapping_cp_port_t),(char**) cp_port); 1865 //building periphs array 1866 BuildTable(fdout, "periph", periph_index, sizeof(mapping_periph_t), (char**)periph); 1837 1867 1838 1868 } // end buildBin() 1839 1869 1840 ///////////////////////////////////////// 1841 // this function set the value of vobj_id 1842 // of the coproc_ports. 1843 /////////////////// 1870 /////////////////////////////////////////////////////////////////////// 1871 // this function set the value the vobj_id fiels of all cp_ports 1872 /////////////////////////////////////////////////////////////////////// 1844 1873 void prepareBuild() 1845 1874 { … … 1850 1879 if ( vspace_id < 0 ) 1851 1880 { 1852 printf("[XML ERROR] illegal <vspacename> for c oproc_port %d,\n",1881 printf("[XML ERROR] illegal <vspacename> for cp_port %d,\n", 1853 1882 i); 1854 1883 exit(1); … … 1856 1885 cp_port[i]->vspaceid = vspace_id; 1857 1886 1858 int vobj_id = getVobjLocId( vspace_id, cp_port_vobj_ref[i]->vobj_name, vspace[vspace_id]->vobjs ); 1887 int vobj_id = getVobjLocId( vspace_id, 1888 cp_port_vobj_ref[i]->vobj_name, 1889 vspace[vspace_id]->vobjs ); 1859 1890 if ( vobj_id >= 0 ) 1860 1891 { 1861 #if XML_PARSER_DEBUG 1862 printf("coproc_port = %d\n", i); 1892 1893 #if XML_PARSER_DEBUG 1894 printf("\ncp_port = %d\n", i); 1863 1895 printf(" vspace_name = %s\n", cp_port_vobj_ref[i]->vspace_name); 1864 1896 printf(" vobj_name = %s\n", cp_port_vobj_ref[i]->vobj_name); … … 1866 1898 #endif 1867 1899 cp_port[i]->vobjlocid = vobj_id; 1868 assert((vobj[ vspace[vspace_id]->vobj_offset + vobj_id]->type == VOBJ_TYPE_MWMR) && "coproc ports has to refere to a vobj of type MWMR"); 1900 1901 assert((vobj[ vspace[vspace_id]->vobj_offset + vobj_id]->type == VOBJ_TYPE_MWMR) 1902 && "coproc ports has to refere to a vobj of type MWMR"); 1869 1903 } 1870 1904 else 1871 1905 { 1872 printf("[XML ERROR] illegal <vobjname> for c oproc_port %d,\n",1906 printf("[XML ERROR] illegal <vobjname> for cp_port %d,\n", 1873 1907 i); 1874 1908 exit(1); 1875 1909 } 1876 1877 1910 } 1878 1911 } … … 1880 1913 ///////////////////////////////////// 1881 1914 int main ( int argc, char* argv[] ) 1915 ///////////////////////////////////// 1882 1916 { 1883 1917 if ( argc < 3 ) … … 1913 1947 } 1914 1948 else 1915 if ( strcmp(tag,"#comment") == 0 );// a way to skips comment1916 else1917 1949 { 1918 1950 printf("[XML ERROR] Wrong file type: \"%s\"\n", argv[1]);
Note: See TracChangeset
for help on using the changeset viewer.