- Timestamp:
- 2012-08-31T17:30:29Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 2be2506a
- Parents:
- e0d5bc5 (diff), 0d57c3e (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - Location:
- kernel
- Files:
-
- 1 added
- 28 edited
-
arch/amd64/src/asm.S (modified) (2 diffs)
-
arch/amd64/src/boot/multiboot.S (modified) (3 diffs)
-
arch/amd64/src/boot/multiboot2.S (modified) (2 diffs)
-
arch/amd64/src/boot/vesa_ret.inc (modified) (1 diff)
-
arch/ia32/src/boot/multiboot.S (modified) (3 diffs)
-
arch/ia32/src/boot/multiboot2.S (modified) (2 diffs)
-
arch/ia32/src/boot/vesa_prot.inc (modified) (1 diff)
-
arch/ia32/src/boot/vesa_real.inc (modified) (1 diff)
-
arch/ia32/src/boot/vesa_ret.inc (modified) (1 diff)
-
arch/ia64/Makefile.inc (modified) (1 diff)
-
arch/mips32/Makefile.inc (modified) (2 diffs)
-
arch/mips64/Makefile.inc (modified) (2 diffs)
-
generic/include/interrupt.h (modified) (2 diffs)
-
generic/include/ipc/ipc.h (modified) (3 diffs)
-
generic/include/ipc/irq.h (modified) (1 diff)
-
generic/include/ipc/sysipc.h (modified) (1 diff)
-
generic/include/print.h (modified) (1 diff)
-
generic/include/printf/verify.h (added)
-
generic/include/proc/task.h (modified) (1 diff)
-
generic/src/console/kconsole.c (modified) (6 diffs)
-
generic/src/console/prompt.c (modified) (5 diffs)
-
generic/src/debug/symtab.c (modified) (5 diffs)
-
generic/src/interrupt/interrupt.c (modified) (3 diffs)
-
generic/src/ipc/ipc.c (modified) (5 diffs)
-
generic/src/ipc/irq.c (modified) (18 diffs)
-
generic/src/ipc/sysipc.c (modified) (1 diff)
-
generic/src/lib/str.c (modified) (3 diffs)
-
generic/src/proc/task.c (modified) (1 diff)
-
generic/src/syscall/syscall.c (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
kernel/arch/amd64/src/asm.S
re0d5bc5 r96e01fbc 362 362 */ 363 363 call syscall_handler 364 364 365 /* 366 * Test if the saved return address is canonical and not-kernel. 367 * We do this by looking at the 16 most significant bits 368 * of the saved return address (two bytes at offset 6). 369 */ 370 testw $0xffff, ISTATE_OFFSET_RIP+6(%rsp) 371 jnz bad_rip 372 365 373 cli 366 374 … … 388 396 sysretq 389 397 398 bad_rip: 399 movq %rsp, %rdi 400 movabs $bad_rip_msg, %rsi 401 xorb %al, %al 402 callq fault_from_uspace 403 /* not reached */ 404 405 bad_rip_msg: 406 .asciz "Invalid instruction pointer." 407 390 408 /** Print Unicode character to EGA display. 391 409 * -
kernel/arch/amd64/src/boot/multiboot.S
re0d5bc5 r96e01fbc 76 76 77 77 multiboot_image_start: 78 cli 78 79 cld 79 80 … … 81 82 movl $START_STACK, %esp 82 83 83 /* Initialize Global Descriptor Table register */ 84 /* 85 * Initialize Global Descriptor Table and 86 * Interrupt Descriptor Table registers 87 */ 84 88 lgdtl bootstrap_gdtr 89 lidtl bootstrap_idtr 85 90 86 91 /* Kernel data + stack */ … … 645 650 .section K_DATA_START, "aw", @progbits 646 651 652 .global bootstrap_idtr 653 bootstrap_idtr: 654 .word 0 655 .long 0 656 647 657 .global bootstrap_gdtr 648 658 bootstrap_gdtr: -
kernel/arch/amd64/src/boot/multiboot2.S
re0d5bc5 r96e01fbc 116 116 117 117 multiboot2_image_start: 118 cli 118 119 cld 119 120 … … 121 122 movl $START_STACK, %esp 122 123 123 /* Initialize Global Descriptor Table register */ 124 /* 125 * Initialize Global Descriptor Table and 126 * Interrupt Descriptor Table registers 127 */ 124 128 lgdtl bootstrap_gdtr 129 lidtl bootstrap_idtr 125 130 126 131 /* Kernel data + stack */ -
kernel/arch/amd64/src/boot/vesa_ret.inc
re0d5bc5 r96e01fbc 1 1 .code32 2 2 vesa_init_protected: 3 cli 3 4 cld 4 5 -
kernel/arch/ia32/src/boot/multiboot.S
re0d5bc5 r96e01fbc 73 73 74 74 multiboot_image_start: 75 cli 75 76 cld 76 77 … … 78 79 movl $START_STACK, %esp 79 80 80 /* Initialize Global Descriptor Table register */ 81 /* 82 * Initialize Global Descriptor Table and 83 * Interrupt Descriptor Table registers 84 */ 81 85 lgdtl bootstrap_gdtr 86 lidtl bootstrap_idtr 82 87 83 88 /* Kernel data + stack */ … … 701 706 page_directory: 702 707 .space 4096, 0 708 709 .global bootstrap_idtr 710 bootstrap_idtr: 711 .word 0 712 .long 0 703 713 704 714 .global bootstrap_gdtr -
kernel/arch/ia32/src/boot/multiboot2.S
re0d5bc5 r96e01fbc 114 114 115 115 multiboot2_image_start: 116 cli 116 117 cld 117 118 … … 119 120 movl $START_STACK, %esp 120 121 121 /* Initialize Global Descriptor Table register */ 122 /* 123 * Initialize Global Descriptor Table and 124 * Interrupt Descriptor Table registers 125 */ 122 126 lgdtl bootstrap_gdtr 127 lidtl bootstrap_idtr 123 128 124 129 /* Kernel data + stack */ -
kernel/arch/ia32/src/boot/vesa_prot.inc
re0d5bc5 r96e01fbc 88 88 /* Returned back to protected mode */ 89 89 90 /* 91 * Initialize Global Descriptor Table and 92 * Interrupt Descriptor Table registers 93 */ 94 lgdtl bootstrap_gdtr 95 lidtl bootstrap_idtr 96 90 97 movzx %ax, %ecx 91 98 mov %ecx, KA2PA(bfb_scanline) -
kernel/arch/ia32/src/boot/vesa_real.inc
re0d5bc5 r96e01fbc 30 30 .code32 31 31 vesa_init: 32 lidtl vesa_idtr 32 33 jmp $GDT_SELECTOR(VESA_INIT_DES), $vesa_init_real - vesa_init 34 35 vesa_idtr: 36 .word 0x3ff 37 .long 0 33 38 34 39 .code16 -
kernel/arch/ia32/src/boot/vesa_ret.inc
re0d5bc5 r96e01fbc 1 1 .code32 2 2 vesa_init_protected: 3 cli 3 4 cld 4 5 -
kernel/arch/ia64/Makefile.inc
re0d5bc5 r96e01fbc 30 30 BFD_ARCH = ia64-elf64 31 31 32 CMN1 = -mconstant-gp -fno-unwind-tables -mfixed-range=f32-f127 32 # 33 # FIXME: 34 # 35 # The -fno-selective-scheduling and -fno-selective-scheduling2 options 36 # should be removed as soon as a bug in GCC concerning unchecked 37 # speculative loads is fixed. 38 # 39 # See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53975 for reference. 40 # 41 42 CMN1 = -mconstant-gp -fno-unwind-tables -mfixed-range=f32-f127 -fno-selective-scheduling -fno-selective-scheduling2 33 43 GCC_CFLAGS += $(CMN1) 34 44 ICC_CFLAGS += $(CMN1) -
kernel/arch/mips32/Makefile.inc
re0d5bc5 r96e01fbc 29 29 BFD_ARCH = mips 30 30 BFD = binary 31 GCC_CFLAGS += -m no-abicalls -G 0 -fno-zero-initialized-in-bss -mips3 -mabi=3231 GCC_CFLAGS += -msoft-float -mno-abicalls -G 0 -fno-zero-initialized-in-bss -mips3 -mabi=32 32 32 33 33 BITS = 32 … … 48 48 BFD_NAME = elf32-tradlittlemips 49 49 ENDIANESS = LE 50 GCC_CFLAGS += -mhard-float51 50 endif 52 51 -
kernel/arch/mips64/Makefile.inc
re0d5bc5 r96e01fbc 29 29 BFD_ARCH = mips:4000 30 30 BFD = binary 31 GCC_CFLAGS += -m no-abicalls -G 0 -fno-zero-initialized-in-bss -mips3 -mabi=6431 GCC_CFLAGS += -msoft-float -mno-abicalls -G 0 -fno-zero-initialized-in-bss -mips3 -mabi=64 32 32 AFLAGS = -64 33 33 … … 40 40 BFD_NAME = elf64-tradlittlemips 41 41 ENDIANESS = LE 42 GCC_CFLAGS += -mhard-float43 42 endif 44 43 -
kernel/generic/include/interrupt.h
re0d5bc5 r96e01fbc 38 38 #include <arch/interrupt.h> 39 39 #include <print.h> 40 #include <stdarg.h> 40 41 #include <typedefs.h> 41 42 #include <proc/task.h> … … 58 59 extern exc_table_t exc_table[]; 59 60 61 extern void fault_from_uspace(istate_t *, const char *, ...) 62 PRINTF_ATTRIBUTE(2, 3); 60 63 extern void fault_if_from_uspace(istate_t *, const char *, ...) 61 64 PRINTF_ATTRIBUTE(2, 3); -
kernel/generic/include/ipc/ipc.h
re0d5bc5 r96e01fbc 77 77 waitq_t wq; 78 78 79 /** Linkage for the list of task's synchronous answerboxes. */80 link_t sync_box_link;81 82 79 /** Phones connected to this answerbox. */ 83 80 list_t connected_phones; … … 116 113 struct task *sender; 117 114 118 /*119 * The caller box is different from sender->answerbox120 * for synchronous calls.121 */122 answerbox_t *callerbox;123 124 115 /** Private data to internal IPC. */ 125 116 sysarg_t priv; … … 147 138 148 139 extern int ipc_call(phone_t *, call_t *); 149 extern int ipc_call_sync(phone_t *, call_t *);150 140 extern call_t *ipc_wait_for_call(answerbox_t *, uint32_t, unsigned int); 151 141 extern int ipc_forward(call_t *, phone_t *, answerbox_t *, unsigned int); -
kernel/generic/include/ipc/irq.h
re0d5bc5 r96e01fbc 37 37 38 38 /** Maximum number of IPC IRQ programmed I/O ranges. */ 39 #define IRQ_MAX_RANGE_COUNT 839 #define IRQ_MAX_RANGE_COUNT 8 40 40 41 41 /** Maximum length of IPC IRQ program. */ 42 #define IRQ_MAX_PROG_SIZE 2 042 #define IRQ_MAX_PROG_SIZE 256 43 43 44 44 #include <ipc/ipc.h> -
kernel/generic/include/ipc/sysipc.h
re0d5bc5 r96e01fbc 40 40 #include <typedefs.h> 41 41 42 extern sysarg_t sys_ipc_call_sync_fast(sysarg_t, sysarg_t, sysarg_t,43 sysarg_t, sysarg_t, ipc_data_t *);44 extern sysarg_t sys_ipc_call_sync_slow(sysarg_t, ipc_data_t *, ipc_data_t *);45 42 extern sysarg_t sys_ipc_call_async_fast(sysarg_t, sysarg_t, sysarg_t, 46 43 sysarg_t, sysarg_t, sysarg_t); -
kernel/generic/include/print.h
re0d5bc5 r96e01fbc 38 38 #include <typedefs.h> 39 39 #include <stdarg.h> 40 41 #ifndef NVERIFY_PRINTF 42 43 #define PRINTF_ATTRIBUTE(start, end) \ 44 __attribute__((format(gnu_printf, start, end))) 45 46 #else /* NVERIFY_PRINTF */ 47 48 #define PRINTF_ATTRIBUTE(start, end) 49 50 #endif /* NVERIFY_PRINTF */ 40 #include <printf/verify.h> 51 41 52 42 #define EOF (-1) -
kernel/generic/include/proc/task.h
re0d5bc5 r96e01fbc 94 94 phone_t phones[IPC_MAX_PHONES]; 95 95 stats_ipc_t ipc_info; /**< IPC statistics */ 96 list_t sync_boxes; /**< List of synchronous answerboxes. */97 96 event_t events[EVENT_TASK_END - EVENT_END]; 98 97 -
kernel/generic/src/console/kconsole.c
re0d5bc5 r96e01fbc 202 202 * 203 203 */ 204 NO_TRACE static int cmdtab_compl(char *input, size_t size, indev_t * indev)204 NO_TRACE static int cmdtab_compl(char *input, size_t size, indev_t *indev) 205 205 { 206 206 const char *name = input; 207 207 208 208 size_t found = 0; 209 /* Maximum Match Length : Length of longest matching common substring in 210 case more than one match is found */ 209 210 /* 211 * Maximum Match Length: Length of longest matching common 212 * substring in case more than one match is found. 213 */ 211 214 size_t max_match_len = size; 212 215 size_t max_match_len_tmp = size; … … 229 232 } 230 233 231 /* If possible completions are more than MAX_TAB_HINTS, ask user whether to display them or not. */ 234 /* 235 * If the number of possible completions is more than MAX_TAB_HINTS, 236 * ask the user whether to display them or not. 237 */ 232 238 if (found > MAX_TAB_HINTS) { 233 239 printf("\n"); 234 continue_showing_hints = console_prompt_display_all_hints(indev, found); 240 continue_showing_hints = 241 console_prompt_display_all_hints(indev, found); 235 242 } 236 243 … … 240 247 while (cmdtab_search_one(name, &pos)) { 241 248 cmd_info_t *hlp = list_get_instance(pos, cmd_info_t, link); 242 249 243 250 if (continue_showing_hints) { 244 251 printf("%s (%s)\n", hlp->name, hlp->description); 245 252 --hints_to_show; 246 253 ++total_hints_shown; 247 248 if (hints_to_show == 0 && total_hints_shown != found) { /* Time to ask user to continue */ 249 continue_showing_hints = console_prompt_more_hints(indev, &hints_to_show); 254 255 if ((hints_to_show == 0) && (total_hints_shown != found)) { 256 /* Ask user to continue */ 257 continue_showing_hints = 258 console_prompt_more_hints(indev, &hints_to_show); 250 259 } 251 260 } 252 261 253 262 pos = pos->next; 254 for(max_match_len_tmp = 0; output[max_match_len_tmp] == hlp->name[input_len + max_match_len_tmp] 255 && max_match_len_tmp < max_match_len; ++max_match_len_tmp); 263 264 for (max_match_len_tmp = 0; 265 (output[max_match_len_tmp] == 266 hlp->name[input_len + max_match_len_tmp]) && 267 (max_match_len_tmp < max_match_len); ++max_match_len_tmp); 268 256 269 max_match_len = max_match_len_tmp; 257 270 } 258 /* keep only the characters common in all completions */ 271 272 /* Keep only the characters common in all completions */ 259 273 output[max_match_len] = 0; 260 274 } … … 310 324 continue; 311 325 312 /* Find the beginning of the word 313 and copy it to tmp */ 326 /* 327 * Find the beginning of the word 328 * and copy it to tmp 329 */ 314 330 size_t beg; 315 331 for (beg = position - 1; (beg > 0) && (!isspace(current[beg])); … … 333 349 continue; 334 350 335 /* We have hints, may be many. In case of more than one hint, 336 tmp will contain the common prefix. */ 351 /* 352 * We have hints, possibly many. In case of more than one hint, 353 * tmp will contain the common prefix. 354 */ 337 355 size_t off = 0; 338 356 size_t i = 0; … … 340 358 if (!wstr_linsert(current, ch, position + i, MAX_CMDLINE)) 341 359 break; 360 342 361 i++; 343 362 } -
kernel/generic/src/console/prompt.c
re0d5bc5 r96e01fbc 43 43 * @param indev Where to read characters from. 44 44 * @param hints Number of hints that would be displayed. 45 * 45 46 * @return Whether to print all hints. 47 * 46 48 */ 47 49 bool console_prompt_display_all_hints(indev_t *indev, size_t hints) … … 49 51 ASSERT(indev); 50 52 ASSERT(hints > 0); 51 52 printf("Display all %zu possibilities? (y or n) ", hints);53 53 54 printf("Display all %zu possibilities? (y or n) ", hints); 55 54 56 while (true) { 55 57 wchar_t answer = indev_pop_character(indev); 56 57 if ( answer == 'y' || answer == 'Y') {58 printf(" y");58 59 if ((answer == 'y') || (answer == 'Y')) { 60 printf("y"); 59 61 return true; 60 62 } 61 62 if ( answer == 'n' || answer == 'N') {63 printf(" n");63 64 if ((answer == 'n') || (answer == 'N')) { 65 printf("n"); 64 66 return false; 65 67 } … … 71 73 * When the function returns false, @p display_hints is set to zero. 72 74 * 73 * @param[in] indevWhere to read characters from.75 * @param[in] indev Where to read characters from. 74 76 * @param[out] display_hints How many hints to display. 77 * 75 78 * @return Whether to display more hints. 79 * 76 80 */ 77 81 bool console_prompt_more_hints(indev_t *indev, size_t *display_hints) … … 79 83 ASSERT(indev); 80 84 ASSERT(display_hints != NULL); 81 85 82 86 printf("--More--"); 83 87 while (true) { 84 88 wchar_t continue_showing_hints = indev_pop_character(indev); 85 89 /* Display a full page again? */ 86 if ( continue_showing_hints == 'y'87 || continue_showing_hints == 'Y'88 || continue_showing_hints == ' ') {90 if ((continue_showing_hints == 'y') || 91 (continue_showing_hints == 'Y') || 92 (continue_showing_hints == ' ')) { 89 93 *display_hints = MAX_TAB_HINTS - 1; 90 94 break; 91 95 } 92 96 93 97 /* Stop displaying hints? */ 94 if ( continue_showing_hints == 'n'95 || continue_showing_hints == 'N'96 || continue_showing_hints == 'q'97 || continue_showing_hints == 'Q') {98 if ((continue_showing_hints == 'n') || 99 (continue_showing_hints == 'N') || 100 (continue_showing_hints == 'q') || 101 (continue_showing_hints == 'Q')) { 98 102 *display_hints = 0; 99 103 break; 100 104 } 101 105 102 106 /* Show one more hint? */ 103 107 if (continue_showing_hints == '\n') { … … 106 110 } 107 111 } 108 112 109 113 /* Delete the --More-- option */ 110 114 printf("\r \r"); 111 115 112 116 return *display_hints > 0; 113 117 } -
kernel/generic/src/debug/symtab.c
re0d5bc5 r96e01fbc 210 210 * 211 211 */ 212 int symtab_compl(char *input, size_t size, indev_t * indev)212 int symtab_compl(char *input, size_t size, indev_t *indev) 213 213 { 214 214 #ifdef CONFIG_SYMTAB … … 227 227 const char *hint; 228 228 char output[MAX_SYMBOL_NAME]; 229 /* Maximum Match Length : Length of longest matching common substring in 230 case more than one match is found */ 229 230 /* 231 * Maximum Match Length: Length of longest matching common substring in 232 * case more than one match is found. 233 */ 231 234 size_t max_match_len = size; 232 235 size_t max_match_len_tmp = size; … … 238 241 239 242 output[0] = 0; 240 241 while ((hint = symtab_search_one(name, &pos))) { 242 ++pos; 243 } 244 243 244 while ((hint = symtab_search_one(name, &pos))) 245 pos++; 246 245 247 pos = 0; 246 248 … … 253 255 } 254 256 255 /* If possible completions are more than MAX_TAB_HINTS, ask user whether to display them or not. */ 257 /* 258 * If the number of possible completions is more than MAX_TAB_HINTS, 259 * ask the user whether to display them or not. 260 */ 256 261 if (found > MAX_TAB_HINTS) { 257 262 printf("\n"); 258 continue_showing_hints = console_prompt_display_all_hints(indev, found); 263 continue_showing_hints = 264 console_prompt_display_all_hints(indev, found); 259 265 } 260 266 … … 265 271 sym_name = symbol_table[pos].symbol_name; 266 272 pos++; 267 268 if (continue_showing_hints) { /* We are still showing hints */ 273 274 if (continue_showing_hints) { 275 /* We are still showing hints */ 269 276 printf("%s\n", sym_name); 270 277 --hints_to_show; 271 278 ++total_hints_shown; 272 273 if (hints_to_show == 0 && total_hints_shown != found) { /* Time to ask user to continue */ 274 continue_showing_hints = console_prompt_more_hints(indev, &hints_to_show); 279 280 if ((hints_to_show == 0) && (total_hints_shown != found)) { 281 /* Ask the user to continue */ 282 continue_showing_hints = 283 console_prompt_more_hints(indev, &hints_to_show); 275 284 } 276 285 } 277 278 for(max_match_len_tmp = 0; output[max_match_len_tmp] == sym_name[input_len + max_match_len_tmp] 279 && max_match_len_tmp < max_match_len; ++max_match_len_tmp); 286 287 for (max_match_len_tmp = 0; 288 (output[max_match_len_tmp] == 289 sym_name[input_len + max_match_len_tmp]) && 290 (max_match_len_tmp < max_match_len); ++max_match_len_tmp); 291 280 292 max_match_len = max_match_len_tmp; 281 293 } 282 /* keep only the characters common in all completions */ 294 295 /* Keep only the characters common in all completions */ 283 296 output[max_match_len] = 0; 284 297 } -
kernel/generic/src/interrupt/interrupt.c
re0d5bc5 r96e01fbc 50 50 #include <panic.h> 51 51 #include <print.h> 52 #include <stdarg.h> 52 53 #include <symtab.h> 53 54 #include <proc/thread.h> … … 165 166 } 166 167 167 /** Terminate thread and task if exception came from userspace. 168 * 169 */ 170 NO_TRACE void fault_if_from_uspace(istate_t *istate, const char *fmt, ...) 171 { 172 if (!istate_from_uspace(istate)) 173 return; 174 168 static NO_TRACE void fault_from_uspace_core(istate_t *istate, const char *fmt, va_list args) 169 { 175 170 printf("Task %s (%" PRIu64 ") killed due to an exception at " 176 171 "program counter %p.\n", TASK->name, TASK->taskid, … … 181 176 182 177 printf("Kill message: "); 178 vprintf(fmt, args); 179 printf("\n"); 180 181 task_kill_self(true); 182 } 183 184 /** Terminate thread and task after the exception came from userspace. 185 * 186 */ 187 NO_TRACE void fault_from_uspace(istate_t *istate, const char *fmt, ...) 188 { 189 va_list args; 190 191 va_start(args, fmt); 192 fault_from_uspace_core(istate, fmt, args); 193 va_end(args); 194 } 195 196 /** Terminate thread and task if exception came from userspace. 197 * 198 */ 199 NO_TRACE void fault_if_from_uspace(istate_t *istate, const char *fmt, ...) 200 { 201 if (!istate_from_uspace(istate)) 202 return; 183 203 184 204 va_list args; 185 205 va_start(args, fmt); 186 vprintf(fmt, args);206 fault_from_uspace_core(istate, fmt, args); 187 207 va_end(args); 188 printf("\n");189 190 task_kill_self(true);191 208 } 192 209 -
kernel/generic/src/ipc/ipc.c
re0d5bc5 r96e01fbc 71 71 { 72 72 memsetb(call, sizeof(*call), 0); 73 call->callerbox = &TASK->answerbox;74 73 call->sender = TASK; 75 74 call->buffer = NULL; … … 120 119 irq_spinlock_initialize(&box->irq_lock, "ipc.box.irqlock"); 121 120 waitq_initialize(&box->wq); 122 link_initialize(&box->sync_box_link);123 121 list_initialize(&box->connected_phones); 124 122 list_initialize(&box->calls); … … 163 161 } 164 162 165 /** Helper function to facilitate synchronous calls.166 *167 * @param phone Destination kernel phone structure.168 * @param request Call structure with request.169 *170 * @return EOK on success or EINTR if the sleep was interrupted.171 *172 */173 int ipc_call_sync(phone_t *phone, call_t *request)174 {175 answerbox_t *sync_box = slab_alloc(ipc_answerbox_slab, 0);176 ipc_answerbox_init(sync_box, TASK);177 178 /*179 * Put the answerbox on the TASK's list of synchronous answerboxes so180 * that it can be cleaned up if the call is interrupted.181 */182 irq_spinlock_lock(&TASK->lock, true);183 list_append(&sync_box->sync_box_link, &TASK->sync_boxes);184 irq_spinlock_unlock(&TASK->lock, true);185 186 /* We will receive data in a special box. */187 request->callerbox = sync_box;188 189 ipc_call(phone, request);190 if (!ipc_wait_for_call(sync_box, SYNCH_NO_TIMEOUT,191 SYNCH_FLAGS_INTERRUPTIBLE)) {192 /* The answerbox and the call will be freed by ipc_cleanup(). */193 return EINTR;194 }195 196 /*197 * The answer arrived without interruption so we can remove the198 * answerbox from the TASK's list of synchronous answerboxes.199 */200 irq_spinlock_lock(&TASK->lock, true);201 list_remove(&sync_box->sync_box_link);202 irq_spinlock_unlock(&TASK->lock, true);203 204 slab_free(ipc_answerbox_slab, sync_box);205 return EOK;206 }207 208 163 /** Answer a message which was not dispatched and is not listed in any queue. 209 164 * … … 214 169 static void _ipc_answer_free_call(call_t *call, bool selflocked) 215 170 { 216 answerbox_t *callerbox = call->callerbox;171 answerbox_t *callerbox = &call->sender->answerbox; 217 172 bool do_lock = ((!selflocked) || callerbox != (&TASK->answerbox)); 218 173 … … 606 561 ipc_cleanup_call_list(&TASK->answerbox.calls); 607 562 irq_spinlock_unlock(&TASK->answerbox.lock, true); 608 609 /* Wait for all answers to interrupted synchronous calls to arrive */610 ipl_t ipl = interrupts_disable();611 while (!list_empty(&TASK->sync_boxes)) {612 answerbox_t *box = list_get_instance(613 list_first(&TASK->sync_boxes), answerbox_t, sync_box_link);614 615 list_remove(&box->sync_box_link);616 call_t *call = ipc_wait_for_call(box, SYNCH_NO_TIMEOUT,617 SYNCH_FLAGS_NONE);618 ipc_call_free(call);619 slab_free(ipc_answerbox_slab, box);620 }621 interrupts_restore(ipl);622 563 623 564 /* Wait for all answers to asynchronous calls to arrive */ -
kernel/generic/src/ipc/irq.c
re0d5bc5 r96e01fbc 39 39 * when interrupt is detected. The application may provide a simple 'top-half' 40 40 * handler as part of its registration, which can perform simple operations 41 * (read/write port/memory, add information to notification ipcmessage).41 * (read/write port/memory, add information to notification IPC message). 42 42 * 43 43 * The structure of a notification message is as follows: 44 44 * - IMETHOD: interface and method as registered by 45 45 * the SYS_IRQ_REGISTER syscall 46 * - ARG1: payload modified by a 'top-half' handler 47 * - ARG2: payload modified by a 'top-half' handler 48 * - ARG3: payload modified by a 'top-half' handler 49 * - ARG4: payload modified by a 'top-half' handler 50 * - ARG5: payload modified by a 'top-half' handler 46 * - ARG1: payload modified by a 'top-half' handler (scratch[1]) 47 * - ARG2: payload modified by a 'top-half' handler (scratch[2]) 48 * - ARG3: payload modified by a 'top-half' handler (scratch[3]) 49 * - ARG4: payload modified by a 'top-half' handler (scratch[4]) 50 * - ARG5: payload modified by a 'top-half' handler (scratch[5]) 51 51 * - in_phone_hash: interrupt counter (may be needed to assure correct order 52 52 * in multithreaded drivers) … … 87 87 static void ranges_unmap(irq_pio_range_t *ranges, size_t rangecount) 88 88 { 89 size_t i; 90 91 for (i = 0; i < rangecount; i++) { 89 for (size_t i = 0; i < rangecount; i++) { 92 90 #ifdef IO_SPACE_BOUNDARY 93 91 if ((void *) ranges[i].base >= IO_SPACE_BOUNDARY) … … 100 98 irq_cmd_t *cmds, size_t cmdcount) 101 99 { 102 uintptr_t *pbase;103 size_t i, j;104 105 100 /* Copy the physical base addresses aside. */ 106 pbase = malloc(rangecount * sizeof(uintptr_t), 0);107 for ( i = 0; i < rangecount; i++)101 uintptr_t *pbase = malloc(rangecount * sizeof(uintptr_t), 0); 102 for (size_t i = 0; i < rangecount; i++) 108 103 pbase[i] = ranges[i].base; 109 104 110 105 /* Map the PIO ranges into the kernel virtual address space. */ 111 for ( i = 0; i < rangecount; i++) {106 for (size_t i = 0; i < rangecount; i++) { 112 107 #ifdef IO_SPACE_BOUNDARY 113 108 if ((void *) ranges[i].base < IO_SPACE_BOUNDARY) … … 122 117 } 123 118 } 124 119 125 120 /* Rewrite the pseudocode addresses from physical to kernel virtual. */ 126 for ( i = 0; i < cmdcount; i++) {121 for (size_t i = 0; i < cmdcount; i++) { 127 122 uintptr_t addr; 128 123 size_t size; 129 124 130 125 /* Process only commands that use an address. */ 131 126 switch (cmds[i].cmd) { 132 127 case CMD_PIO_READ_8: 133 case CMD_PIO_WRITE_8:134 case CMD_PIO_WRITE_A_8:128 case CMD_PIO_WRITE_8: 129 case CMD_PIO_WRITE_A_8: 135 130 size = 1; 136 131 break; 137 case CMD_PIO_READ_16:138 case CMD_PIO_WRITE_16:139 case CMD_PIO_WRITE_A_16:132 case CMD_PIO_READ_16: 133 case CMD_PIO_WRITE_16: 134 case CMD_PIO_WRITE_A_16: 140 135 size = 2; 141 136 break; 142 case CMD_PIO_READ_32:143 case CMD_PIO_WRITE_32:144 case CMD_PIO_WRITE_A_32:137 case CMD_PIO_READ_32: 138 case CMD_PIO_WRITE_32: 139 case CMD_PIO_WRITE_A_32: 145 140 size = 4; 146 141 break; … … 149 144 continue; 150 145 } 151 146 152 147 addr = (uintptr_t) cmds[i].addr; 153 148 149 size_t j; 154 150 for (j = 0; j < rangecount; j++) { 155 156 151 /* Find the matching range. */ 157 152 if (!iswithin(pbase[j], ranges[j].size, addr, size)) 158 153 continue; 159 154 160 155 /* Switch the command to a kernel virtual address. */ 161 156 addr -= pbase[j]; 162 157 addr += ranges[j].base; 163 158 164 159 cmds[i].addr = (void *) addr; 165 160 break; 166 161 } 167 162 168 163 if (j == rangecount) { 169 164 /* … … 176 171 } 177 172 } 178 173 179 174 free(pbase); 175 return EOK; 176 } 177 178 /** Statically check the top-half pseudocode 179 * 180 * Check the top-half pseudocode for invalid or unsafe 181 * constructs. 182 * 183 */ 184 static int code_check(irq_cmd_t *cmds, size_t cmdcount) 185 { 186 for (size_t i = 0; i < cmdcount; i++) { 187 /* 188 * Check for accepted ranges. 189 */ 190 if (cmds[i].cmd >= CMD_LAST) 191 return EINVAL; 192 193 if (cmds[i].srcarg >= IPC_CALL_LEN) 194 return EINVAL; 195 196 if (cmds[i].dstarg >= IPC_CALL_LEN) 197 return EINVAL; 198 199 switch (cmds[i].cmd) { 200 case CMD_PREDICATE: 201 /* 202 * Check for control flow overflow. 203 * Note that jumping just beyond the last 204 * command is a correct behaviour. 205 */ 206 if (i + cmds[i].value > cmdcount) 207 return EINVAL; 208 209 break; 210 default: 211 break; 212 } 213 } 214 180 215 return EOK; 181 216 } … … 207 242 irq_pio_range_t *ranges = NULL; 208 243 irq_cmd_t *cmds = NULL; 209 244 210 245 irq_code_t *code = malloc(sizeof(*code), 0); 211 246 int rc = copy_from_uspace(code, ucode, sizeof(*code)); … … 222 257 if (rc != EOK) 223 258 goto error; 224 259 225 260 cmds = malloc(sizeof(code->cmds[0]) * code->cmdcount, 0); 226 261 rc = copy_from_uspace(cmds, code->cmds, … … 228 263 if (rc != EOK) 229 264 goto error; 230 265 266 rc = code_check(cmds, code->cmdcount); 267 if (rc != EOK) 268 goto error; 269 231 270 rc = ranges_map_and_apply(ranges, code->rangecount, cmds, 232 271 code->cmdcount); 233 272 if (rc != EOK) 234 273 goto error; 235 274 236 275 code->ranges = ranges; 237 276 code->cmds = cmds; 238 277 239 278 return code; 240 279 241 280 error: 242 281 if (cmds) 243 282 free(cmds); 283 244 284 if (ranges) 245 285 free(ranges); 286 246 287 free(code); 247 288 return NULL; … … 250 291 /** Register an answerbox as a receiving end for IRQ notifications. 251 292 * 252 * @param box Receiving answerbox. 253 * @param inr IRQ number. 254 * @param devno Device number. 255 * @param imethod Interface and method to be associated with the 256 * notification. 257 * @param ucode Uspace pointer to top-half pseudocode. 258 * @return EOK on success or a negative error code. 293 * @param box Receiving answerbox. 294 * @param inr IRQ number. 295 * @param devno Device number. 296 * @param imethod Interface and method to be associated with the 297 * notification. 298 * @param ucode Uspace pointer to top-half pseudocode. 299 * 300 * @return EOK on success or a negative error code. 259 301 * 260 302 */ … … 266 308 (sysarg_t) devno 267 309 }; 268 310 269 311 if ((inr < 0) || (inr > last_inr)) 270 312 return ELIMIT; … … 329 371 /** Unregister task from IRQ notification. 330 372 * 331 * @param box Answerbox associated with the notification. 332 * @param inr IRQ number. 333 * @param devno Device number. 334 * @return EOK on success or a negative error code. 373 * @param box Answerbox associated with the notification. 374 * @param inr IRQ number. 375 * @param devno Device number. 376 * 377 * @return EOK on success or a negative error code. 378 * 335 379 */ 336 380 int ipc_irq_unregister(answerbox_t *box, inr_t inr, devno_t devno) … … 340 384 (sysarg_t) devno 341 385 }; 342 386 343 387 if ((inr < 0) || (inr > last_inr)) 344 388 return ELIMIT; … … 436 480 /* Remove from the hash table. */ 437 481 hash_table_remove(&irq_uspace_hash_table, key, 2); 438 482 439 483 /* 440 484 * Release both locks so that we can free the pseudo code. … … 442 486 irq_spinlock_unlock(&box->irq_lock, false); 443 487 irq_spinlock_unlock(&irq_uspace_hash_table_lock, true); 444 488 445 489 code_free(irq->notif_cfg.code); 446 490 free(irq); … … 492 536 493 537 for (size_t i = 0; i < code->cmdcount; i++) { 494 uint32_t dstval;495 496 538 uintptr_t srcarg = code->cmds[i].srcarg; 497 539 uintptr_t dstarg = code->cmds[i].dstarg; 498 540 499 if (srcarg >= IPC_CALL_LEN)500 break;501 502 if (dstarg >= IPC_CALL_LEN)503 break;504 505 541 switch (code->cmds[i].cmd) { 506 542 case CMD_PIO_READ_8: 507 dstval = pio_read_8((ioport8_t *) code->cmds[i].addr); 508 if (dstarg) 509 scratch[dstarg] = dstval; 543 scratch[dstarg] = 544 pio_read_8((ioport8_t *) code->cmds[i].addr); 510 545 break; 511 546 case CMD_PIO_READ_16: 512 dstval = pio_read_16((ioport16_t *) code->cmds[i].addr); 513 if (dstarg) 514 scratch[dstarg] = dstval; 547 scratch[dstarg] = 548 pio_read_16((ioport16_t *) code->cmds[i].addr); 515 549 break; 516 550 case CMD_PIO_READ_32: 517 dstval = pio_read_32((ioport32_t *) code->cmds[i].addr); 518 if (dstarg) 519 scratch[dstarg] = dstval; 551 scratch[dstarg] = 552 pio_read_32((ioport32_t *) code->cmds[i].addr); 520 553 break; 521 554 case CMD_PIO_WRITE_8: … … 532 565 break; 533 566 case CMD_PIO_WRITE_A_8: 534 if (srcarg) { 535 pio_write_8((ioport8_t *) code->cmds[i].addr, 536 (uint8_t) scratch[srcarg]); 537 } 567 pio_write_8((ioport8_t *) code->cmds[i].addr, 568 (uint8_t) scratch[srcarg]); 538 569 break; 539 570 case CMD_PIO_WRITE_A_16: 540 if (srcarg) { 541 pio_write_16((ioport16_t *) code->cmds[i].addr, 542 (uint16_t) scratch[srcarg]); 543 } 571 pio_write_16((ioport16_t *) code->cmds[i].addr, 572 (uint16_t) scratch[srcarg]); 544 573 break; 545 574 case CMD_PIO_WRITE_A_32: 546 if (srcarg) { 547 pio_write_32((ioport32_t *) code->cmds[i].addr, 548 (uint32_t) scratch[srcarg]); 549 } 550 break; 551 case CMD_BTEST: 552 if ((srcarg) && (dstarg)) { 553 dstval = scratch[srcarg] & code->cmds[i].value; 554 scratch[dstarg] = dstval; 555 } 575 pio_write_32((ioport32_t *) code->cmds[i].addr, 576 (uint32_t) scratch[srcarg]); 577 break; 578 case CMD_LOAD: 579 scratch[dstarg] = code->cmds[i].value; 580 break; 581 case CMD_AND: 582 scratch[dstarg] = scratch[srcarg] & 583 code->cmds[i].value; 556 584 break; 557 585 case CMD_PREDICATE: 558 if ( (srcarg) && (!scratch[srcarg])) {586 if (scratch[srcarg] == 0) 559 587 i += code->cmds[i].value; 560 continue; 561 } 588 562 589 break; 563 590 case CMD_ACCEPT: … … 582 609 { 583 610 ASSERT(irq); 584 611 585 612 ASSERT(interrupts_disabled()); 586 613 ASSERT(irq_spinlock_locked(&irq->lock)); -
kernel/generic/src/ipc/sysipc.c
re0d5bc5 r96e01fbc 612 612 break; 613 613 } 614 615 return 0;616 }617 618 /** Make a fast call over IPC, wait for reply and return to user.619 *620 * This function can handle only three arguments of payload, but is faster than621 * the generic function (i.e. sys_ipc_call_sync_slow()).622 *623 * @param phoneid Phone handle for the call.624 * @param imethod Interface and method of the call.625 * @param arg1 Service-defined payload argument.626 * @param arg2 Service-defined payload argument.627 * @param arg3 Service-defined payload argument.628 * @param data Address of user-space structure where the reply call will629 * be stored.630 *631 * @return 0 on success.632 * @return ENOENT if there is no such phone handle.633 *634 */635 sysarg_t sys_ipc_call_sync_fast(sysarg_t phoneid, sysarg_t imethod,636 sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, ipc_data_t *data)637 {638 phone_t *phone;639 if (phone_get(phoneid, &phone) != EOK)640 return ENOENT;641 642 call_t *call = ipc_call_alloc(0);643 IPC_SET_IMETHOD(call->data, imethod);644 IPC_SET_ARG1(call->data, arg1);645 IPC_SET_ARG2(call->data, arg2);646 IPC_SET_ARG3(call->data, arg3);647 648 /*649 * To achieve deterministic behavior, zero out arguments that are beyond650 * the limits of the fast version.651 */652 IPC_SET_ARG4(call->data, 0);653 IPC_SET_ARG5(call->data, 0);654 655 int res = request_preprocess(call, phone);656 int rc;657 658 if (!res) {659 #ifdef CONFIG_UDEBUG660 udebug_stoppable_begin();661 #endif662 rc = ipc_call_sync(phone, call);663 #ifdef CONFIG_UDEBUG664 udebug_stoppable_end();665 #endif666 667 if (rc != EOK) {668 /* The call will be freed by ipc_cleanup(). */669 return rc;670 }671 672 process_answer(call);673 } else674 IPC_SET_RETVAL(call->data, res);675 676 rc = STRUCT_TO_USPACE(&data->args, &call->data.args);677 ipc_call_free(call);678 if (rc != 0)679 return rc;680 681 return 0;682 }683 684 /** Make a synchronous IPC call allowing to transmit the entire payload.685 *686 * @param phoneid Phone handle for the call.687 * @param request User-space address of call data with the request.688 * @param reply User-space address of call data where to store the689 * answer.690 *691 * @return Zero on success or an error code.692 *693 */694 sysarg_t sys_ipc_call_sync_slow(sysarg_t phoneid, ipc_data_t *request,695 ipc_data_t *reply)696 {697 phone_t *phone;698 if (phone_get(phoneid, &phone) != EOK)699 return ENOENT;700 701 call_t *call = ipc_call_alloc(0);702 int rc = copy_from_uspace(&call->data.args, &request->args,703 sizeof(call->data.args));704 if (rc != 0) {705 ipc_call_free(call);706 return (sysarg_t) rc;707 }708 709 int res = request_preprocess(call, phone);710 711 if (!res) {712 #ifdef CONFIG_UDEBUG713 udebug_stoppable_begin();714 #endif715 rc = ipc_call_sync(phone, call);716 #ifdef CONFIG_UDEBUG717 udebug_stoppable_end();718 #endif719 720 if (rc != EOK) {721 /* The call will be freed by ipc_cleanup(). */722 return rc;723 }724 725 process_answer(call);726 } else727 IPC_SET_RETVAL(call->data, res);728 729 rc = STRUCT_TO_USPACE(&reply->args, &call->data.args);730 ipc_call_free(call);731 if (rc != 0)732 return rc;733 614 734 615 return 0; -
kernel/generic/src/lib/str.c
re0d5bc5 r96e01fbc 456 456 * 457 457 * Do a char-by-char comparison of two NULL-terminated strings. 458 * The strings are considered equal iff they consist of the same 459 * characters on the minimum of their lengths. 458 * The strings are considered equal iff their length is equal 459 * and both strings consist of the same sequence of characters. 460 * 461 * A string S1 is less than another string S2 if it has a character with 462 * lower value at the first character position where the strings differ. 463 * If the strings differ in length, the shorter one is treated as if 464 * padded by characters with a value of zero. 460 465 * 461 466 * @param s1 First string to compare. 462 467 * @param s2 Second string to compare. 463 468 * 464 * @return 0 if the strings are equal, -1 if first is smaller,465 * 1 if second smaller.469 * @return 0 if the strings are equal, -1 if the first is less than the second, 470 * 1 if the second is less than the first. 466 471 * 467 472 */ … … 494 499 * 495 500 * Do a char-by-char comparison of two NULL-terminated strings. 496 * The strings are considered equal iff they consist of the same 497 * characters on the minimum of their lengths and the length limit. 501 * The strings are considered equal iff 502 * min(str_length(s1), max_len) == min(str_length(s2), max_len) 503 * and both strings consist of the same sequence of characters, 504 * up to max_len characters. 505 * 506 * A string S1 is less than another string S2 if it has a character with 507 * lower value at the first character position where the strings differ. 508 * If the strings differ in length, the shorter one is treated as if 509 * padded by characters with a value of zero. Only the first max_len 510 * characters are considered. 498 511 * 499 512 * @param s1 First string to compare. … … 501 514 * @param max_len Maximum number of characters to consider. 502 515 * 503 * @return 0 if the strings are equal, -1 if first is smaller,504 * 1 if second smaller.516 * @return 0 if the strings are equal, -1 if the first is less than the second, 517 * 1 if the second is less than the first. 505 518 * 506 519 */ -
kernel/generic/src/proc/task.c
re0d5bc5 r96e01fbc 156 156 157 157 list_initialize(&task->threads); 158 list_initialize(&task->sync_boxes);159 158 160 159 ipc_answerbox_init(&task->answerbox, task); -
kernel/generic/src/syscall/syscall.c
re0d5bc5 r96e01fbc 151 151 152 152 /* IPC related syscalls. */ 153 (syshandler_t) sys_ipc_call_sync_fast,154 (syshandler_t) sys_ipc_call_sync_slow,155 153 (syshandler_t) sys_ipc_call_async_fast, 156 154 (syshandler_t) sys_ipc_call_async_slow,
Note:
See TracChangeset
for help on using the changeset viewer.
