- Timestamp:
- 2012-11-06T21:03:44Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 338810f
- Parents:
- de73242 (diff), 94795812 (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:
-
- 19 added
- 51 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/Makefile
rde73242 refdfebc 196 196 generic/src/console/chardev.c \ 197 197 generic/src/console/console.c \ 198 generic/src/console/prompt.c \ 198 199 generic/src/cpu/cpu.c \ 199 200 generic/src/ddi/ddi.c \ … … 256 257 generic/src/ipc/ipc.c \ 257 258 generic/src/ipc/sysipc.c \ 259 generic/src/ipc/sysipc_ops.c \ 260 generic/src/ipc/ops/clnestab.c \ 261 generic/src/ipc/ops/conctmeto.c \ 262 generic/src/ipc/ops/concttome.c \ 263 generic/src/ipc/ops/connclone.c \ 264 generic/src/ipc/ops/dataread.c \ 265 generic/src/ipc/ops/datawrite.c \ 266 generic/src/ipc/ops/debug.c \ 267 generic/src/ipc/ops/sharein.c \ 268 generic/src/ipc/ops/shareout.c \ 269 generic/src/ipc/ops/stchngath.c \ 258 270 generic/src/ipc/ipcrsc.c \ 259 271 generic/src/ipc/irq.c \ -
kernel/arch/amd64/src/asm.S
rde73242 refdfebc 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
rde73242 refdfebc 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
rde73242 refdfebc 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
rde73242 refdfebc 1 1 .code32 2 2 vesa_init_protected: 3 cli 3 4 cld 4 5 -
kernel/arch/arm32/Makefile.inc
rde73242 refdfebc 33 33 ATSIGN = % 34 34 35 GCC_CFLAGS += -march=armv4 35 GCC_CFLAGS += -march=armv4 -fno-omit-frame-pointer -mapcs-frame 36 36 37 37 BITS = 32 -
kernel/arch/arm32/include/istate.h
rde73242 refdfebc 49 49 /** Struct representing CPU state saved when an exception occurs. */ 50 50 typedef struct istate { 51 uint32_t dummy; 51 52 uint32_t spsr; 52 53 uint32_t sp; -
kernel/arch/arm32/src/exc_handler.S
rde73242 refdfebc 130 130 stmfd r13!, {r2} 131 131 2: 132 sub sp, sp, #4 132 133 .endm 133 134 134 135 .macro LOAD_REGS_FROM_STACK 136 add sp, sp, #4 135 137 ldmfd r13!, {r0} 136 138 msr spsr, r0 -
kernel/arch/arm32/src/exception.c
rde73242 refdfebc 123 123 124 124 asm volatile ( 125 "mrc p15, 0, %[control_reg], c1, c 1"125 "mrc p15, 0, %[control_reg], c1, c0" 126 126 : [control_reg] "=r" (control_reg) 127 127 ); … … 131 131 132 132 asm volatile ( 133 "mcr p15, 0, %[control_reg], c1, c 1"133 "mcr p15, 0, %[control_reg], c1, c0" 134 134 :: [control_reg] "r" (control_reg) 135 135 ); -
kernel/arch/arm32/src/mach/integratorcp/integratorcp.c
rde73242 refdfebc 38 38 #include <console/chardev.h> 39 39 #include <genarch/drivers/pl050/pl050.h> 40 #include <genarch/drivers/arm926_uart/arm926_uart.h> 40 41 #include <genarch/kbrd/kbrd.h> 42 #include <genarch/srln/srln.h> 41 43 #include <console/console.h> 42 44 #include <sysinfo/sysinfo.h> … … 53 55 #include <print.h> 54 56 57 55 58 #define SDRAM_SIZE (sdram[((*(uint32_t *)(ICP_CMCR+ICP_SDRAMCR_OFFSET) & ICP_SDRAM_MASK) >> 2)]) 56 static icp_hw_map_t icp_hw_map; 57 static irq_t icp_timer_irq; 59 60 static struct { 61 icp_hw_map_t hw_map; 62 irq_t timer_irq; 63 arm926_uart_t uart; 64 } icp; 65 66 67 58 68 struct arm_machine_ops icp_machine_ops = { 59 69 icp_init, … … 70 80 71 81 static bool hw_map_init_called = false; 72 static bool vga_init = false;73 82 uint32_t sdram[8] = { 74 83 16777216, /* 16mb */ … … 89 98 void icp_vga_init(void) 90 99 { 91 *(uint32_t*)((char *)(icp _hw_map.cmcr)+0x14) = 0xA05F0000;92 *(uint32_t*)((char *)(icp _hw_map.cmcr)+0x1C) = 0x12C11000;93 *(uint32_t*)icp _hw_map.vga = 0x3F1F3F9C;94 *(uint32_t*)((char *)(icp _hw_map.vga) + 0x4) = 0x080B61DF;95 *(uint32_t*)((char *)(icp _hw_map.vga) + 0x8) = 0x067F3800;96 *(uint32_t*)((char *)(icp _hw_map.vga) + 0x10) = ICP_FB;97 *(uint32_t *)((char *)(icp _hw_map.vga) + 0x1C) = 0x182B;98 *(uint32_t*)((char *)(icp _hw_map.cmcr)+0xC) = 0x33805000;100 *(uint32_t*)((char *)(icp.hw_map.cmcr)+0x14) = 0xA05F0000; 101 *(uint32_t*)((char *)(icp.hw_map.cmcr)+0x1C) = 0x12C11000; 102 *(uint32_t*)icp.hw_map.vga = 0x3F1F3F9C; 103 *(uint32_t*)((char *)(icp.hw_map.vga) + 0x4) = 0x080B61DF; 104 *(uint32_t*)((char *)(icp.hw_map.vga) + 0x8) = 0x067F3800; 105 *(uint32_t*)((char *)(icp.hw_map.vga) + 0x10) = ICP_FB; 106 *(uint32_t *)((char *)(icp.hw_map.vga) + 0x1C) = 0x182B; 107 *(uint32_t*)((char *)(icp.hw_map.cmcr)+0xC) = 0x33805000; 99 108 100 109 } … … 103 112 static inline uint32_t icp_irqc_get_sources(void) 104 113 { 105 return *((uint32_t *) icp _hw_map.irqc);114 return *((uint32_t *) icp.hw_map.irqc); 106 115 } 107 116 … … 113 122 static inline void icp_irqc_mask(uint32_t irq) 114 123 { 115 *((uint32_t *) icp _hw_map.irqc_mask) = (1 << irq);124 *((uint32_t *) icp.hw_map.irqc_mask) = (1 << irq); 116 125 } 117 126 … … 123 132 static inline void icp_irqc_unmask(uint32_t irq) 124 133 { 125 *((uint32_t *) icp _hw_map.irqc_unmask) |= (1 << irq);126 } 127 128 /** Initializes icp _hw_map. */134 *((uint32_t *) icp.hw_map.irqc_unmask) |= (1 << irq); 135 } 136 137 /** Initializes icp.hw_map. */ 129 138 void icp_init(void) 130 139 { 131 icp _hw_map.uart = km_map(ICP_UART, PAGE_SIZE,132 PAGE_WRITE | PAGE_NOT_CACHEABLE); 133 icp _hw_map.kbd_ctrl = km_map(ICP_KBD, PAGE_SIZE, PAGE_NOT_CACHEABLE);134 icp _hw_map.kbd_stat = icp_hw_map.kbd_ctrl + ICP_KBD_STAT;135 icp _hw_map.kbd_data = icp_hw_map.kbd_ctrl + ICP_KBD_DATA;136 icp _hw_map.kbd_intstat = icp_hw_map.kbd_ctrl + ICP_KBD_INTR_STAT;137 icp _hw_map.rtc = km_map(ICP_RTC, PAGE_SIZE,138 PAGE_WRITE | PAGE_NOT_CACHEABLE); 139 icp _hw_map.rtc1_load = icp_hw_map.rtc + ICP_RTC1_LOAD_OFFSET;140 icp _hw_map.rtc1_read = icp_hw_map.rtc + ICP_RTC1_READ_OFFSET;141 icp _hw_map.rtc1_ctl = icp_hw_map.rtc + ICP_RTC1_CTL_OFFSET;142 icp _hw_map.rtc1_intrclr = icp_hw_map.rtc + ICP_RTC1_INTRCLR_OFFSET;143 icp _hw_map.rtc1_bgload = icp_hw_map.rtc + ICP_RTC1_BGLOAD_OFFSET;144 icp _hw_map.rtc1_intrstat = icp_hw_map.rtc + ICP_RTC1_INTRSTAT_OFFSET;145 146 icp _hw_map.irqc = km_map(ICP_IRQC, PAGE_SIZE,147 PAGE_WRITE | PAGE_NOT_CACHEABLE); 148 icp _hw_map.irqc_mask = icp_hw_map.irqc + ICP_IRQC_MASK_OFFSET;149 icp _hw_map.irqc_unmask = icp_hw_map.irqc + ICP_IRQC_UNMASK_OFFSET;150 icp _hw_map.cmcr = km_map(ICP_CMCR, PAGE_SIZE,151 PAGE_WRITE | PAGE_NOT_CACHEABLE); 152 icp _hw_map.sdramcr = icp_hw_map.cmcr + ICP_SDRAMCR_OFFSET;153 icp _hw_map.vga = km_map(ICP_VGA, PAGE_SIZE,140 icp.hw_map.uart = km_map(ICP_UART, PAGE_SIZE, 141 PAGE_WRITE | PAGE_NOT_CACHEABLE); 142 icp.hw_map.kbd_ctrl = km_map(ICP_KBD, PAGE_SIZE, PAGE_NOT_CACHEABLE); 143 icp.hw_map.kbd_stat = icp.hw_map.kbd_ctrl + ICP_KBD_STAT; 144 icp.hw_map.kbd_data = icp.hw_map.kbd_ctrl + ICP_KBD_DATA; 145 icp.hw_map.kbd_intstat = icp.hw_map.kbd_ctrl + ICP_KBD_INTR_STAT; 146 icp.hw_map.rtc = km_map(ICP_RTC, PAGE_SIZE, 147 PAGE_WRITE | PAGE_NOT_CACHEABLE); 148 icp.hw_map.rtc1_load = icp.hw_map.rtc + ICP_RTC1_LOAD_OFFSET; 149 icp.hw_map.rtc1_read = icp.hw_map.rtc + ICP_RTC1_READ_OFFSET; 150 icp.hw_map.rtc1_ctl = icp.hw_map.rtc + ICP_RTC1_CTL_OFFSET; 151 icp.hw_map.rtc1_intrclr = icp.hw_map.rtc + ICP_RTC1_INTRCLR_OFFSET; 152 icp.hw_map.rtc1_bgload = icp.hw_map.rtc + ICP_RTC1_BGLOAD_OFFSET; 153 icp.hw_map.rtc1_intrstat = icp.hw_map.rtc + ICP_RTC1_INTRSTAT_OFFSET; 154 155 icp.hw_map.irqc = km_map(ICP_IRQC, PAGE_SIZE, 156 PAGE_WRITE | PAGE_NOT_CACHEABLE); 157 icp.hw_map.irqc_mask = icp.hw_map.irqc + ICP_IRQC_MASK_OFFSET; 158 icp.hw_map.irqc_unmask = icp.hw_map.irqc + ICP_IRQC_UNMASK_OFFSET; 159 icp.hw_map.cmcr = km_map(ICP_CMCR, PAGE_SIZE, 160 PAGE_WRITE | PAGE_NOT_CACHEABLE); 161 icp.hw_map.sdramcr = icp.hw_map.cmcr + ICP_SDRAMCR_OFFSET; 162 icp.hw_map.vga = km_map(ICP_VGA, PAGE_SIZE, 154 163 PAGE_WRITE | PAGE_NOT_CACHEABLE); 155 164 … … 164 173 { 165 174 icp_irqc_mask(ICP_TIMER_IRQ); 166 *((uint32_t*) icp _hw_map.rtc1_load) = frequency;167 *((uint32_t*) icp _hw_map.rtc1_bgload) = frequency;168 *((uint32_t*) icp _hw_map.rtc1_ctl) = ICP_RTC_CTL_VALUE;175 *((uint32_t*) icp.hw_map.rtc1_load) = frequency; 176 *((uint32_t*) icp.hw_map.rtc1_bgload) = frequency; 177 *((uint32_t*) icp.hw_map.rtc1_ctl) = ICP_RTC_CTL_VALUE; 169 178 icp_irqc_unmask(ICP_TIMER_IRQ); 170 179 } … … 172 181 static irq_ownership_t icp_timer_claim(irq_t *irq) 173 182 { 174 if (icp _hw_map.rtc1_intrstat) {175 *((uint32_t*) icp _hw_map.rtc1_intrclr) = 1;183 if (icp.hw_map.rtc1_intrstat) { 184 *((uint32_t*) icp.hw_map.rtc1_intrclr) = 1; 176 185 return IRQ_ACCEPT; 177 186 } else … … 200 209 static void icp_timer_irq_init(void) 201 210 { 202 irq_initialize(&icp _timer_irq);203 icp _timer_irq.devno = device_assign_devno();204 icp _timer_irq.inr = ICP_TIMER_IRQ;205 icp _timer_irq.claim = icp_timer_claim;206 icp _timer_irq.handler = icp_timer_irq_handler;207 208 irq_register(&icp _timer_irq);211 irq_initialize(&icp.timer_irq); 212 icp.timer_irq.devno = device_assign_devno(); 213 icp.timer_irq.inr = ICP_TIMER_IRQ; 214 icp.timer_irq.claim = icp_timer_claim; 215 icp.timer_irq.handler = icp_timer_irq_handler; 216 217 irq_register(&icp.timer_irq); 209 218 } 210 219 … … 231 240 232 241 if (hw_map_init_called) { 233 *size = (sdram[((*(uint32_t *)icp _hw_map.sdramcr &242 *size = (sdram[((*(uint32_t *)icp.hw_map.sdramcr & 234 243 ICP_SDRAM_MASK) >> 2)]); 235 244 } else { … … 286 295 { 287 296 #ifdef CONFIG_FB 297 static bool vga_init = false; 288 298 if (!vga_init) { 289 299 icp_vga_init(); … … 304 314 stdout_wire(fbdev); 305 315 #endif 316 #ifdef CONFIG_ARM926_UART 317 if (arm926_uart_init(&icp.uart, ARM926_UART0_IRQ, 318 ARM926_UART0_BASE_ADDRESS, sizeof(arm926_uart_regs_t))) 319 stdout_wire(&icp.uart.outdev); 320 #endif 306 321 } 307 322 … … 310 325 311 326 pl050_t *pl050 = malloc(sizeof(pl050_t), FRAME_ATOMIC); 312 pl050->status = (ioport8_t *)icp _hw_map.kbd_stat;313 pl050->data = (ioport8_t *)icp _hw_map.kbd_data;314 pl050->ctrl = (ioport8_t *)icp _hw_map.kbd_ctrl;327 pl050->status = (ioport8_t *)icp.hw_map.kbd_stat; 328 pl050->data = (ioport8_t *)icp.hw_map.kbd_data; 329 pl050->ctrl = (ioport8_t *)icp.hw_map.kbd_ctrl; 315 330 316 331 pl050_instance_t *pl050_instance = pl050_init(pl050, ICP_KBD_IRQ); … … 335 350 ICP_KBD); 336 351 352 #ifdef CONFIG_ARM926_UART 353 srln_instance_t *srln_instance = srln_init(); 354 if (srln_instance) { 355 indev_t *sink = stdin_wire(); 356 indev_t *srln = srln_wire(srln_instance, sink); 357 arm926_uart_input_wire(&icp.uart, srln); 358 icp_irqc_unmask(ARM926_UART0_IRQ); 359 } 360 #endif 337 361 } 338 362 -
kernel/arch/arm32/src/mm/page_fault.c
rde73242 refdfebc 77 77 } 78 78 79 /** Decides whether the instruction is load/store or not.80 *81 * @param instr Instruction82 *83 * @return true when instruction is load/store, false otherwise84 *85 */86 static inline bool is_load_store_instruction(instruction_t instr)87 {88 /* load store immediate offset */89 if (instr.type == 0x2)90 return true;91 92 /* load store register offset */93 if ((instr.type == 0x3) && (instr.bit4 == 0))94 return true;95 96 /* load store multiple */97 if (instr.type == 0x4)98 return true;99 100 /* oprocessor load/store */101 if (instr.type == 0x6)102 return true;103 104 return false;105 }106 107 /** Decides whether the instruction is swap or not.108 *109 * @param instr Instruction110 *111 * @return true when instruction is swap, false otherwise112 */113 static inline bool is_swap_instruction(instruction_t instr)114 {115 /* swap, swapb instruction */116 if ((instr.type == 0x0) &&117 ((instr.opcode == 0x8) || (instr.opcode == 0xa)) &&118 (instr.access == 0x0) && (instr.bits567 == 0x4) && (instr.bit4 == 1))119 return true;120 121 return false;122 }123 124 79 /** Decides whether read or write into memory is requested. 125 80 * … … 128 83 * 129 84 * @return Type of access into memory, PF_ACCESS_EXEC if no memory access is 130 * 85 * requested. 131 86 */ 132 87 static pf_access_t get_memory_access_type(uint32_t instr_addr, … … 146 101 } 147 102 148 /* load store instructions */ 149 if (is_load_store_instruction(instr)) { 150 if (instr.access == 1) { 151 return PF_ACCESS_READ; 152 } else { 153 return PF_ACCESS_WRITE; 103 /* See ARM Architecture reference manual ARMv7-A and ARMV7-R edition 104 * A5.3 (PDF p. 206) */ 105 static const struct { 106 uint32_t mask; 107 uint32_t value; 108 pf_access_t access; 109 } ls_inst[] = { 110 /* Store word/byte */ 111 { 0x0e100000, 0x04000000, PF_ACCESS_WRITE }, /*STR(B) imm*/ 112 { 0x0e100010, 0x06000000, PF_ACCESS_WRITE }, /*STR(B) reg*/ 113 /* Load word/byte */ 114 { 0x0e100000, 0x04100000, PF_ACCESS_READ }, /*LDR(B) imm*/ 115 { 0x0e100010, 0x06100000, PF_ACCESS_READ }, /*LDR(B) reg*/ 116 /* Store half-word/dual A5.2.8 */ 117 { 0x0e1000b0, 0x000000b0, PF_ACCESS_WRITE }, /*STRH imm reg*/ 118 /* Load half-word/dual A5.2.8 */ 119 { 0x0e0000f0, 0x000000d0, PF_ACCESS_READ }, /*LDRH imm reg*/ 120 { 0x0e1000b0, 0x001000b0, PF_ACCESS_READ }, /*LDRH imm reg*/ 121 /* Block data transfer, Store */ 122 { 0x0e100000, 0x08000000, PF_ACCESS_WRITE }, /* STM variants */ 123 { 0x0e100000, 0x08100000, PF_ACCESS_READ }, /* LDM variants */ 124 /* Swap */ 125 { 0x0fb00000, 0x01000000, PF_ACCESS_WRITE }, 126 }; 127 const uint32_t inst = *(uint32_t*)instr_addr; 128 for (unsigned i = 0; i < sizeof(ls_inst) / sizeof(ls_inst[0]); ++i) { 129 if ((inst & ls_inst[i].mask) == ls_inst[i].value) { 130 return ls_inst[i].access; 154 131 } 155 }156 157 /* swap, swpb instruction */158 if (is_swap_instruction(instr)) {159 return PF_ACCESS_WRITE;160 132 } 161 133 162 134 panic("page_fault - instruction doesn't access memory " 163 135 "(instr_code: %#0" PRIx32 ", badvaddr:%p).", 164 instr_union.pc, (void *) badvaddr); 165 166 return PF_ACCESS_EXEC; 136 inst, (void *) badvaddr); 167 137 } 168 138 -
kernel/arch/ia32/src/boot/multiboot.S
rde73242 refdfebc 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
rde73242 refdfebc 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
rde73242 refdfebc 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
rde73242 refdfebc 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
rde73242 refdfebc 1 1 .code32 2 2 vesa_init_protected: 3 cli 3 4 cld 4 5 -
kernel/arch/ia32/src/smp/apic.c
rde73242 refdfebc 259 259 } 260 260 261 #define DELIVS_PENDING_SILENT_RETRIES 4 262 263 static void l_apic_wait_for_delivery(void) 264 { 265 icr_t icr; 266 unsigned retries = 0; 267 268 do { 269 if (retries++ > DELIVS_PENDING_SILENT_RETRIES) { 270 retries = 0; 271 #ifdef CONFIG_DEBUG 272 printf("IPI is pending.\n"); 273 #endif 274 delay(20); 275 } 276 icr.lo = l_apic[ICRlo]; 277 } while (icr.delivs == DELIVS_PENDING); 278 279 } 280 261 281 /** Send all CPUs excluding CPU IPI vector. 262 282 * … … 279 299 280 300 l_apic[ICRlo] = icr.lo; 281 282 icr.lo = l_apic[ICRlo]; 283 if (icr.delivs == DELIVS_PENDING) { 284 #ifdef CONFIG_DEBUG 285 printf("IPI is pending.\n"); 286 #endif 287 } 301 302 l_apic_wait_for_delivery(); 288 303 289 304 return apic_poll_errors(); … … 327 342 return 0; 328 343 344 l_apic_wait_for_delivery(); 345 329 346 icr.lo = l_apic[ICRlo]; 330 if (icr.delivs == DELIVS_PENDING) {331 #ifdef CONFIG_DEBUG332 printf("IPI is pending.\n");333 #endif334 }335 336 347 icr.delmod = DELMOD_INIT; 337 348 icr.destmod = DESTMOD_PHYS; -
kernel/arch/ia64/Makefile.inc
rde73242 refdfebc 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
rde73242 refdfebc 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
rde73242 refdfebc 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/arch/sparc64/src/smp/sun4u/ipi.c
rde73242 refdfebc 124 124 (void) interrupts_disable(); 125 125 } 126 } while ( done);126 } while (!done); 127 127 128 128 preemption_enable(); -
kernel/genarch/Makefile.inc
rde73242 refdfebc 91 91 endif 92 92 93 ifeq ($(CONFIG_ARM926_UART),y) 94 GENARCH_SOURCES += \ 95 genarch/src/drivers/arm926_uart/arm926_uart.c 96 endif 97 93 98 ifeq ($(CONFIG_S3C24XX_IRQC),y) 94 99 GENARCH_SOURCES += \ -
kernel/genarch/include/multiboot/multiboot.h
rde73242 refdfebc 99 99 100 100 extern void multiboot_extract_command(char *, size_t, const char *); 101 extern void multiboot_extract_argument(char *, size_t, const char *); 101 102 extern void multiboot_info_parse(uint32_t, const multiboot_info_t *); 102 103 -
kernel/genarch/src/multiboot/multiboot.c
rde73242 refdfebc 71 71 } 72 72 73 /** Extract arguments from the multiboot module command line. 74 * 75 * @param buf Destination buffer (will be always NULL-terminated). 76 * @param size Size of destination buffer (in bytes). 77 * @param cmd_line Input string (the command line). 78 * 79 */ 80 void multiboot_extract_argument(char *buf, size_t size, const char *cmd_line) 81 { 82 /* Start after first space. */ 83 const char *start = str_chr(cmd_line, ' '); 84 if (start == NULL) { 85 str_cpy(buf, size, ""); 86 return; 87 } 88 89 const char *end = cmd_line + str_size(cmd_line); 90 91 /* Skip the space(s). */ 92 while (start != end) { 93 if (start[0] == ' ') 94 start++; 95 else 96 break; 97 } 98 99 str_ncpy(buf, size, start, (size_t) (end - start)); 100 } 101 73 102 static void multiboot_modules(uint32_t count, multiboot_module_t *mods) 74 103 { … … 84 113 multiboot_extract_command(init.tasks[init.cnt].name, 85 114 CONFIG_TASK_NAME_BUFLEN, MULTIBOOT_PTR(mods[i].string)); 86 } else 115 multiboot_extract_argument(init.tasks[init.cnt].arguments, 116 CONFIG_TASK_ARGUMENTS_BUFLEN, MULTIBOOT_PTR(mods[i].string)); 117 } else { 87 118 init.tasks[init.cnt].name[0] = 0; 119 init.tasks[init.cnt].arguments[0] = 0; 120 } 88 121 89 122 init.cnt++; -
kernel/genarch/src/multiboot/multiboot2.c
rde73242 refdfebc 49 49 multiboot_extract_command(init.tasks[init.cnt].name, 50 50 CONFIG_TASK_NAME_BUFLEN, module->string); 51 multiboot_extract_argument(init.tasks[init.cnt].arguments, 52 CONFIG_TASK_ARGUMENTS_BUFLEN, module->string); 51 53 52 54 init.cnt++; -
kernel/generic/include/config.h
rde73242 refdfebc 47 47 #define CONFIG_INIT_TASKS 32 48 48 #define CONFIG_TASK_NAME_BUFLEN 32 49 #define CONFIG_TASK_ARGUMENTS_BUFLEN 64 50 51 /** 52 * Maximum buffer size allowed for IPC_M_DATA_WRITE and IPC_M_DATA_READ 53 * requests. 54 */ 55 #define DATA_XFER_LIMIT (64 * 1024) 49 56 50 57 #ifndef __ASM__ … … 56 63 size_t size; 57 64 char name[CONFIG_TASK_NAME_BUFLEN]; 65 char arguments[CONFIG_TASK_ARGUMENTS_BUFLEN]; 58 66 } init_task_t; 59 67 -
kernel/generic/include/debug.h
rde73242 refdfebc 37 37 38 38 #include <panic.h> 39 #include <symtab .h>39 #include <symtab_lookup.h> 40 40 41 41 #define CALLER ((uintptr_t) __builtin_return_address(0)) -
kernel/generic/include/interrupt.h
rde73242 refdfebc 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
rde73242 refdfebc 65 65 mutex_t lock; 66 66 link_t link; 67 struct task *caller; 67 68 struct answerbox *callee; 68 69 ipc_phone_state_t state; … … 72 73 typedef struct answerbox { 73 74 IRQ_SPINLOCK_DECLARE(lock); 75 76 /** Answerbox is active until it enters cleanup. */ 77 bool active; 74 78 75 79 struct task *task; 76 80 77 81 waitq_t wq; 78 79 /** Linkage for the list of task's synchronous answerboxes. */80 link_t sync_box_link;81 82 82 83 /** Phones connected to this answerbox. */ … … 109 110 110 111 typedef struct { 111 link_t link; 112 /** 113 * Task link. 114 * Valid only when the call is not forgotten. 115 * Protected by the task's active_calls_lock. 116 */ 117 link_t ta_link; 118 119 atomic_t refcnt; 120 121 /** Answerbox link. */ 122 link_t ab_link; 112 123 113 124 unsigned int flags; 125 126 /** Protects the forget member. */ 127 SPINLOCK_DECLARE(forget_lock); 128 129 /** 130 * True if the caller 'forgot' this call and donated it to the callee. 131 * Forgotten calls are discarded upon answering (the answer is not 132 * delivered) and answered calls cannot be forgotten. Forgotten calls 133 * also do not figure on the task's active call list. 134 * 135 * We keep this separate from the flags so that it is not necessary 136 * to take a lock when accessing them. 137 */ 138 bool forget; 139 140 /** True if the call is in the active list. */ 141 bool active; 114 142 115 /** Identification of the caller. */ 143 /** 144 * Identification of the caller. 145 * Valid only when the call is not forgotten. 146 */ 116 147 struct task *sender; 117 148 118 /* 119 * The caller box is different from sender->answerbox 120 * for synchronous calls. 121 */ 122 answerbox_t *callerbox; 149 /** Phone which was used to send the call. */ 150 phone_t *caller_phone; 123 151 124 152 /** Private data to internal IPC. */ … … 127 155 /** Data passed from/to userspace. */ 128 156 ipc_data_t data; 129 157 158 /** Method as it was sent in the request. */ 159 sysarg_t request_method; 160 130 161 /** Buffer for IPC_M_DATA_WRITE and IPC_M_DATA_READ. */ 131 162 uint8_t *buffer; 132 133 /*134 * The forward operation can masquerade the caller phone. For those135 * cases, we must keep it aside so that the answer is processed136 * correctly.137 */138 phone_t *caller_phone;139 163 } call_t; 140 164 … … 145 169 extern call_t *ipc_call_alloc(unsigned int); 146 170 extern void ipc_call_free(call_t *); 171 extern void ipc_call_hold(call_t *); 172 extern void ipc_call_release(call_t *); 147 173 148 174 extern int ipc_call(phone_t *, call_t *); 149 extern int ipc_call_sync(phone_t *, call_t *);150 175 extern call_t *ipc_wait_for_call(answerbox_t *, uint32_t, unsigned int); 151 176 extern int ipc_forward(call_t *, phone_t *, answerbox_t *, unsigned int); 152 177 extern void ipc_answer(answerbox_t *, call_t *); 178 extern void _ipc_answer_free_call(call_t *, bool); 153 179 154 extern void ipc_phone_init(phone_t * );155 extern voidipc_phone_connect(phone_t *, answerbox_t *);180 extern void ipc_phone_init(phone_t *, struct task *); 181 extern bool ipc_phone_connect(phone_t *, answerbox_t *); 156 182 extern int ipc_phone_hangup(phone_t *); 157 183 … … 161 187 extern void ipc_backsend_err(phone_t *, call_t *, sysarg_t); 162 188 extern void ipc_answerbox_slam_phones(answerbox_t *, bool); 163 extern void ipc_cleanup_call_list( list_t *);189 extern void ipc_cleanup_call_list(answerbox_t *, list_t *); 164 190 165 191 extern void ipc_print_task(task_id_t); -
kernel/generic/include/ipc/ipcrsc.h
rde73242 refdfebc 40 40 41 41 extern call_t *get_call(sysarg_t); 42 extern int phone_get(sysarg_t, phone_t **); 42 43 extern int phone_alloc(task_t *); 43 extern voidphone_connect(int, answerbox_t *);44 extern bool phone_connect(int, answerbox_t *); 44 45 extern void phone_dealloc(int); 45 46 -
kernel/generic/include/ipc/irq.h
rde73242 refdfebc 37 37 38 38 /** Maximum number of IPC IRQ programmed I/O ranges. */ 39 #define IRQ_MAX_RANGE_COUNT 39 #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
rde73242 refdfebc 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/lib/elf_load.h
rde73242 refdfebc 42 42 * ELF error return codes 43 43 */ 44 #define EE_OK 0/* No error */45 #define EE_INVALID 1/* Invalid ELF image */46 #define EE_MEMORY 2/* Cannot allocate address space */47 #define EE_INCOMPATIBLE 3/* ELF image is not compatible with current architecture */48 #define EE_UNSUPPORTED 4/* Non-supported ELF (e.g. dynamic ELFs) */49 #define EE_LOADER 5/* The image is actually a program loader. */50 #define EE_IRRECOVERABLE 644 #define EE_OK 0 /* No error */ 45 #define EE_INVALID 1 /* Invalid ELF image */ 46 #define EE_MEMORY 2 /* Cannot allocate address space */ 47 #define EE_INCOMPATIBLE 3 /* ELF image is not compatible with current architecture */ 48 #define EE_UNSUPPORTED 4 /* Non-supported ELF (e.g. dynamic ELFs) */ 49 #define EE_LOADER 5 /* The image is actually a program loader. */ 50 #define EE_IRRECOVERABLE 6 /* Irrecoverable error. */ 51 51 52 52 /** 53 53 * This flags is passed when running the loader, otherwise elf_load() 54 54 * would return with a EE_LOADER error code. 55 *56 55 */ 57 56 #define ELD_F_NONE 0 -
kernel/generic/include/macros.h
rde73242 refdfebc 52 52 uint64_t sz2) 53 53 { 54 uint64_t e1 = s1 + sz1; 55 uint64_t e2 = s2 + sz2; 56 57 return ((s1 < e2) && (s2 < e1)); 54 uint64_t e1 = s1 + sz1 - 1; 55 uint64_t e2 = s2 + sz2 - 1; 56 57 /* both sizes are non-zero */ 58 if (sz1 && sz2) 59 return ((s1 <= e2) && (s2 <= e1)); 60 61 /* one size is non-zero */ 62 if (sz2) 63 return ((s1 >= s2) && (s1 <= e2)); 64 if (sz1) 65 return ((s2 >= s1) && (s2 <= e1)); 66 67 /* both are zero */ 68 return (s1 == s2); 58 69 } 59 70 … … 119 130 | ((((uint64_t) (up)) & UINT32_C(0xffffffff)) << 32)) 120 131 132 /* Test for sum overflow. */ 133 #define overflows(a, b) \ 134 ((a) + (b) < (a)) 135 136 /* Test for sum overflow into positive numbers. */ 137 #define overflows_into_positive(a, b) \ 138 (overflows((a), (b)) && ((a) + (b) > 0)) 139 121 140 /** Pseudorandom generator 122 141 * -
kernel/generic/include/print.h
rde73242 refdfebc 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
rde73242 refdfebc 91 91 92 92 /* IPC stuff */ 93 answerbox_t answerbox; /**< Communication endpoint */ 93 94 /** Receiving communication endpoint */ 95 answerbox_t answerbox; 96 97 /** Sending communication endpoints */ 94 98 phone_t phones[IPC_MAX_PHONES]; 95 stats_ipc_t ipc_info; /**< IPC statistics */ 96 list_t sync_boxes; /**< List of synchronous answerboxes. */ 99 100 /** Spinlock protecting the active_calls list. */ 101 SPINLOCK_DECLARE(active_calls_lock); 102 103 /** 104 * List of all calls sent by this task that have not yet been 105 * answered. 106 */ 107 list_t active_calls; 108 97 109 event_t events[EVENT_TASK_END - EVENT_END]; 110 111 /** IPC statistics */ 112 stats_ipc_t ipc_info; 98 113 99 114 #ifdef CONFIG_UDEBUG -
kernel/generic/include/symtab.h
rde73242 refdfebc 36 36 #define KERN_SYMTAB_H_ 37 37 38 #include <typedefs.h> 38 #include <symtab_lookup.h> 39 #include <console/chardev.h> 39 40 40 #define MAX_SYMBOL_NAME 6441 42 struct symtab_entry {43 uint64_t address_le;44 char symbol_name[MAX_SYMBOL_NAME];45 };46 47 extern int symtab_name_lookup(uintptr_t, const char **, uintptr_t *);48 extern const char *symtab_fmt_name_lookup(uintptr_t);49 extern int symtab_addr_lookup(const char *, uintptr_t *);50 41 extern void symtab_print_search(const char *); 51 extern int symtab_compl(char *, size_t); 52 53 #ifdef CONFIG_SYMTAB 54 55 /** Symtable linked together by build process 56 * 57 */ 58 extern struct symtab_entry symbol_table[]; 59 60 #endif /* CONFIG_SYMTAB */ 42 extern int symtab_compl(char *, size_t, indev_t *); 61 43 62 44 #endif -
kernel/generic/src/console/kconsole.c
rde73242 refdfebc 43 43 #include <console/chardev.h> 44 44 #include <console/cmd.h> 45 #include <console/prompt.h> 45 46 #include <print.h> 46 47 #include <panic.h> … … 201 202 * 202 203 */ 203 NO_TRACE static int cmdtab_compl(char *input, size_t size )204 NO_TRACE static int cmdtab_compl(char *input, size_t size, indev_t *indev) 204 205 { 205 206 const char *name = input; 206 207 207 208 size_t found = 0; 209 210 /* 211 * Maximum Match Length: Length of longest matching common 212 * substring in case more than one match is found. 213 */ 214 size_t max_match_len = size; 215 size_t max_match_len_tmp = size; 216 size_t input_len = str_length(input); 208 217 link_t *pos = NULL; 209 218 const char *hint; 210 219 char *output = malloc(MAX_CMDLINE, 0); 220 size_t hints_to_show = MAX_TAB_HINTS - 1; 221 size_t total_hints_shown = 0; 222 bool continue_showing_hints = true; 211 223 212 224 output[0] = 0; … … 218 230 pos = pos->next; 219 231 found++; 232 } 233 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 */ 238 if (found > MAX_TAB_HINTS) { 239 printf("\n"); 240 continue_showing_hints = 241 console_prompt_display_all_hints(indev, found); 220 242 } 221 243 … … 225 247 while (cmdtab_search_one(name, &pos)) { 226 248 cmd_info_t *hlp = list_get_instance(pos, cmd_info_t, link); 227 printf("%s (%s)\n", hlp->name, hlp->description); 249 250 if (continue_showing_hints) { 251 printf("%s (%s)\n", hlp->name, hlp->description); 252 --hints_to_show; 253 ++total_hints_shown; 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); 259 } 260 } 261 228 262 pos = pos->next; 229 } 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 269 max_match_len = max_match_len_tmp; 270 } 271 272 /* Keep only the characters common in all completions */ 273 output[max_match_len] = 0; 230 274 } 231 275 … … 280 324 continue; 281 325 282 /* Find the beginning of the word 283 and copy it to tmp */ 326 /* 327 * Find the beginning of the word 328 * and copy it to tmp 329 */ 284 330 size_t beg; 285 331 for (beg = position - 1; (beg > 0) && (!isspace(current[beg])); … … 294 340 if (beg == 0) { 295 341 /* Command completion */ 296 found = cmdtab_compl(tmp, STR_BOUNDS(MAX_CMDLINE) );342 found = cmdtab_compl(tmp, STR_BOUNDS(MAX_CMDLINE), indev); 297 343 } else { 298 344 /* Symbol completion */ 299 found = symtab_compl(tmp, STR_BOUNDS(MAX_CMDLINE) );345 found = symtab_compl(tmp, STR_BOUNDS(MAX_CMDLINE), indev); 300 346 } 301 347 302 348 if (found == 0) 303 349 continue; 304 305 if (found > 1) { 306 /* No unique hint, list was printed */ 307 printf("%s> ", prompt); 308 printf("%ls", current); 309 print_cc('\b', wstr_length(current) - position); 310 continue; 311 } 312 313 /* We have a hint */ 314 350 351 /* 352 * We have hints, possibly many. In case of more than one hint, 353 * tmp will contain the common prefix. 354 */ 315 355 size_t off = 0; 316 356 size_t i = 0; … … 318 358 if (!wstr_linsert(current, ch, position + i, MAX_CMDLINE)) 319 359 break; 360 320 361 i++; 321 362 } 363 364 if (found > 1) { 365 /* No unique hint, list was printed */ 366 printf("%s> ", prompt); 367 printf("%ls", current); 368 position += str_length(tmp); 369 print_cc('\b', wstr_length(current) - position); 370 continue; 371 } 372 373 /* We have a hint */ 322 374 323 375 printf("%ls", current + position); … … 540 592 /** Parse command line. 541 593 * 542 * @param cmdline Command line as read from input device. 594 * @param cmdline Command line as read from input device. 543 595 * @param size Size (in bytes) of the string. 544 596 * -
kernel/generic/src/debug/symtab.c
rde73242 refdfebc 43 43 #include <typedefs.h> 44 44 #include <errno.h> 45 #include <console/prompt.h> 45 46 46 47 /** Get name of a symbol that seems most likely to correspond to address. … … 209 210 * 210 211 */ 211 int symtab_compl(char *input, size_t size )212 int symtab_compl(char *input, size_t size, indev_t *indev) 212 213 { 213 214 #ifdef CONFIG_SYMTAB … … 227 228 char output[MAX_SYMBOL_NAME]; 228 229 230 /* 231 * Maximum Match Length: Length of longest matching common substring in 232 * case more than one match is found. 233 */ 234 size_t max_match_len = size; 235 size_t max_match_len_tmp = size; 236 size_t input_len = str_length(input); 237 char *sym_name; 238 size_t hints_to_show = MAX_TAB_HINTS - 1; 239 size_t total_hints_shown = 0; 240 bool continue_showing_hints = true; 241 229 242 output[0] = 0; 243 244 while ((hint = symtab_search_one(name, &pos))) 245 pos++; 246 247 pos = 0; 230 248 231 249 while ((hint = symtab_search_one(name, &pos))) { … … 235 253 pos++; 236 254 found++; 255 } 256 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 */ 261 if (found > MAX_TAB_HINTS) { 262 printf("\n"); 263 continue_showing_hints = 264 console_prompt_display_all_hints(indev, found); 237 265 } 238 266 … … 241 269 pos = 0; 242 270 while (symtab_search_one(name, &pos)) { 243 printf("%s\n", symbol_table[pos].symbol_name);271 sym_name = symbol_table[pos].symbol_name; 244 272 pos++; 273 274 if (continue_showing_hints) { 275 /* We are still showing hints */ 276 printf("%s\n", sym_name); 277 --hints_to_show; 278 ++total_hints_shown; 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); 284 } 285 } 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 292 max_match_len = max_match_len_tmp; 245 293 } 294 295 /* Keep only the characters common in all completions */ 296 output[max_match_len] = 0; 246 297 } 247 298 -
kernel/generic/src/interrupt/interrupt.c
rde73242 refdfebc 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/event.c
rde73242 refdfebc 163 163 call->data.task_id = TASK ? TASK->taskid : 0; 164 164 165 irq_spinlock_lock(&event->answerbox->irq_lock, true); 166 list_append(&call->link, &event->answerbox->irq_notifs); 167 irq_spinlock_unlock(&event->answerbox->irq_lock, true); 168 169 waitq_wakeup(&event->answerbox->wq, WAKEUP_FIRST); 165 irq_spinlock_lock(&event->answerbox->irq_lock, 166 true); 167 list_append(&call->ab_link, 168 &event->answerbox->irq_notifs); 169 irq_spinlock_unlock(&event->answerbox->irq_lock, 170 true); 171 172 waitq_wakeup(&event->answerbox->wq, 173 WAKEUP_FIRST); 170 174 171 175 if (mask) -
kernel/generic/src/ipc/ipc.c
rde73242 refdfebc 45 45 #include <ipc/kbox.h> 46 46 #include <ipc/event.h> 47 #include <ipc/sysipc_ops.h> 48 #include <ipc/sysipc_priv.h> 47 49 #include <errno.h> 48 50 #include <mm/slab.h> … … 71 73 { 72 74 memsetb(call, sizeof(*call), 0); 73 call->callerbox = &TASK->answerbox; 74 call->sender = TASK; 75 spinlock_initialize(&call->forget_lock, "forget_lock"); 76 call->active = false; 77 call->forget = false; 78 call->sender = NULL; 75 79 call->buffer = NULL; 80 } 81 82 void ipc_call_hold(call_t *call) 83 { 84 atomic_inc(&call->refcnt); 85 } 86 87 void ipc_call_release(call_t *call) 88 { 89 if (atomic_predec(&call->refcnt) == 0) { 90 if (call->buffer) 91 free(call->buffer); 92 slab_free(ipc_call_slab, call); 93 } 76 94 } 77 95 … … 84 102 * 85 103 * @return If flags permit it, return NULL, or initialized kernel 86 * call structure .104 * call structure with one reference. 87 105 * 88 106 */ … … 90 108 { 91 109 call_t *call = slab_alloc(ipc_call_slab, flags); 92 if (call) 110 if (call) { 93 111 _ipc_call_init(call); 112 ipc_call_hold(call); 113 } 94 114 95 115 return call; … … 103 123 void ipc_call_free(call_t *call) 104 124 { 105 /* Check to see if we have data in the IPC_M_DATA_SEND buffer. */ 106 if (call->buffer) 107 free(call->buffer); 108 slab_free(ipc_call_slab, call); 125 ipc_call_release(call); 109 126 } 110 127 … … 120 137 irq_spinlock_initialize(&box->irq_lock, "ipc.box.irqlock"); 121 138 waitq_initialize(&box->wq); 122 link_initialize(&box->sync_box_link);123 139 list_initialize(&box->connected_phones); 124 140 list_initialize(&box->calls); … … 134 150 * @param phone Initialized phone structure. 135 151 * @param box Initialized answerbox structure. 136 * 137 */ 138 void ipc_phone_connect(phone_t *phone, answerbox_t *box) 139 { 152 * @return True if the phone was connected, false otherwise. 153 */ 154 bool ipc_phone_connect(phone_t *phone, answerbox_t *box) 155 { 156 bool active; 157 140 158 mutex_lock(&phone->lock); 141 142 phone->state = IPC_PHONE_CONNECTED;143 phone->callee = box;144 145 159 irq_spinlock_lock(&box->lock, true); 146 list_append(&phone->link, &box->connected_phones); 160 161 active = box->active; 162 if (active) { 163 phone->state = IPC_PHONE_CONNECTED; 164 phone->callee = box; 165 list_append(&phone->link, &box->connected_phones); 166 } 167 147 168 irq_spinlock_unlock(&box->lock, true); 148 149 169 mutex_unlock(&phone->lock); 170 171 return active; 150 172 } 151 173 … … 153 175 * 154 176 * @param phone Phone structure to be initialized. 155 * 156 */ 157 void ipc_phone_init(phone_t *phone) 177 * @param caller Owning task. 178 * 179 */ 180 void ipc_phone_init(phone_t *phone, task_t *caller) 158 181 { 159 182 mutex_initialize(&phone->lock, MUTEX_PASSIVE); 183 phone->caller = caller; 160 184 phone->callee = NULL; 161 185 phone->state = IPC_PHONE_FREE; … … 163 187 } 164 188 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 189 /** Answer a message which was not dispatched and is not listed in any queue. 209 190 * … … 212 193 * 213 194 */ 214 static void _ipc_answer_free_call(call_t *call, bool selflocked) 215 { 216 answerbox_t *callerbox = call->callerbox; 217 bool do_lock = ((!selflocked) || callerbox != (&TASK->answerbox)); 218 195 void _ipc_answer_free_call(call_t *call, bool selflocked) 196 { 219 197 /* Count sent answer */ 220 198 irq_spinlock_lock(&TASK->lock, true); 221 199 TASK->ipc_info.answer_sent++; 222 200 irq_spinlock_unlock(&TASK->lock, true); 201 202 spinlock_lock(&call->forget_lock); 203 if (call->forget) { 204 /* This is a forgotten call and call->sender is not valid. */ 205 spinlock_unlock(&call->forget_lock); 206 ipc_call_free(call); 207 return; 208 } else { 209 /* 210 * If the call is still active, i.e. it was answered 211 * in a non-standard way, remove the call from the 212 * sender's active call list. 213 */ 214 if (call->active) { 215 spinlock_lock(&call->sender->active_calls_lock); 216 list_remove(&call->ta_link); 217 spinlock_unlock(&call->sender->active_calls_lock); 218 } 219 } 220 spinlock_unlock(&call->forget_lock); 221 222 answerbox_t *callerbox = &call->sender->answerbox; 223 bool do_lock = ((!selflocked) || (callerbox != &TASK->answerbox)); 223 224 224 225 call->flags |= IPC_CALL_ANSWERED; 225 226 226 if (call->flags & IPC_CALL_FORWARDED) {227 if (call->caller_phone) {228 /* Demasquerade the caller phone. */229 call->data.phone = call->caller_phone;230 }231 }232 233 227 call->data.task_id = TASK->taskid; 234 228 … … 236 230 irq_spinlock_lock(&callerbox->lock, true); 237 231 238 list_append(&call-> link, &callerbox->answers);232 list_append(&call->ab_link, &callerbox->answers); 239 233 240 234 if (do_lock) … … 254 248 /* Remove from active box */ 255 249 irq_spinlock_lock(&box->lock, true); 256 list_remove(&call-> link);250 list_remove(&call->ab_link); 257 251 irq_spinlock_unlock(&box->lock, true); 258 252 259 253 /* Send back answer */ 260 254 _ipc_answer_free_call(call, false); 255 } 256 257 static void _ipc_call_actions_internal(phone_t *phone, call_t *call) 258 { 259 task_t *caller = phone->caller; 260 261 atomic_inc(&phone->active_calls); 262 call->caller_phone = phone; 263 call->sender = caller; 264 265 call->active = true; 266 spinlock_lock(&caller->active_calls_lock); 267 list_append(&call->ta_link, &caller->active_calls); 268 spinlock_unlock(&caller->active_calls_lock); 269 270 call->data.phone = phone; 271 call->data.task_id = caller->taskid; 261 272 } 262 273 … … 273 284 void ipc_backsend_err(phone_t *phone, call_t *call, sysarg_t err) 274 285 { 275 call->data.phone = phone; 276 atomic_inc(&phone->active_calls); 286 _ipc_call_actions_internal(phone, call); 277 287 IPC_SET_RETVAL(call->data, err); 278 288 _ipc_answer_free_call(call, false); … … 288 298 static void _ipc_call(phone_t *phone, answerbox_t *box, call_t *call) 289 299 { 300 task_t *caller = phone->caller; 301 290 302 /* Count sent ipc call */ 291 irq_spinlock_lock(&TASK->lock, true); 292 TASK->ipc_info.call_sent++; 293 irq_spinlock_unlock(&TASK->lock, true); 294 295 if (!(call->flags & IPC_CALL_FORWARDED)) { 296 atomic_inc(&phone->active_calls); 297 call->data.phone = phone; 298 call->data.task_id = TASK->taskid; 299 } 303 irq_spinlock_lock(&caller->lock, true); 304 caller->ipc_info.call_sent++; 305 irq_spinlock_unlock(&caller->lock, true); 306 307 if (!(call->flags & IPC_CALL_FORWARDED)) 308 _ipc_call_actions_internal(phone, call); 300 309 301 310 irq_spinlock_lock(&box->lock, true); 302 list_append(&call-> link, &box->calls);311 list_append(&call->ab_link, &box->calls); 303 312 irq_spinlock_unlock(&box->lock, true); 304 313 … … 320 329 if (phone->state != IPC_PHONE_CONNECTED) { 321 330 mutex_unlock(&phone->lock); 322 if (call->flags & IPC_CALL_FORWARDED) { 323 IPC_SET_RETVAL(call->data, EFORWARD); 324 _ipc_answer_free_call(call, false); 325 } else { 331 if (!(call->flags & IPC_CALL_FORWARDED)) { 326 332 if (phone->state == IPC_PHONE_HUNGUP) 327 333 ipc_backsend_err(phone, call, EHANGUP); … … 370 376 call_t *call = ipc_call_alloc(0); 371 377 IPC_SET_IMETHOD(call->data, IPC_M_PHONE_HUNGUP); 378 call->request_method = IPC_M_PHONE_HUNGUP; 372 379 call->flags |= IPC_CALL_DISCARD_ANSWER; 373 380 _ipc_call(phone, box, call); … … 401 408 TASK->ipc_info.forwarded++; 402 409 irq_spinlock_pass(&TASK->lock, &oldbox->lock); 403 list_remove(&call-> link);410 list_remove(&call->ab_link); 404 411 irq_spinlock_unlock(&oldbox->lock, true); 405 412 406 413 if (mode & IPC_FF_ROUTE_FROM_ME) { 407 if (!call->caller_phone)408 call->caller_phone = call->data.phone;409 414 call->data.phone = newphone; 410 415 call->data.task_id = TASK->taskid; … … 451 456 452 457 request = list_get_instance(list_first(&box->irq_notifs), 453 call_t, link);454 list_remove(&request-> link);458 call_t, ab_link); 459 list_remove(&request->ab_link); 455 460 456 461 irq_spinlock_unlock(&box->irq_lock, false); … … 461 466 /* Handle asynchronous answers */ 462 467 request = list_get_instance(list_first(&box->answers), 463 call_t, link);464 list_remove(&request-> link);465 atomic_dec(&request-> data.phone->active_calls);468 call_t, ab_link); 469 list_remove(&request->ab_link); 470 atomic_dec(&request->caller_phone->active_calls); 466 471 } else if (!list_empty(&box->calls)) { 467 472 /* Count received call */ … … 470 475 /* Handle requests */ 471 476 request = list_get_instance(list_first(&box->calls), 472 call_t, link);473 list_remove(&request-> link);477 call_t, ab_link); 478 list_remove(&request->ab_link); 474 479 475 480 /* Append request to dispatch queue */ 476 list_append(&request-> link, &box->dispatched_calls);481 list_append(&request->ab_link, &box->dispatched_calls); 477 482 } else { 478 483 /* This can happen regularly after ipc_cleanup */ … … 494 499 /** Answer all calls from list with EHANGUP answer. 495 500 * 501 * @param box Answerbox with the list. 496 502 * @param lst Head of the list to be cleaned up. 497 * 498 */ 499 void ipc_cleanup_call_list(list_t *lst) 500 { 503 */ 504 void ipc_cleanup_call_list(answerbox_t *box, list_t *lst) 505 { 506 irq_spinlock_lock(&box->lock, true); 501 507 while (!list_empty(lst)) { 502 call_t *call = list_get_instance(list_first(lst), call_t, link); 503 if (call->buffer) 504 free(call->buffer); 505 506 list_remove(&call->link); 507 508 call_t *call = list_get_instance(list_first(lst), call_t, 509 ab_link); 510 511 list_remove(&call->ab_link); 512 513 irq_spinlock_unlock(&box->lock, true); 514 515 if (lst == &box->calls) 516 SYSIPC_OP(request_process, call, box); 517 518 ipc_data_t old = call->data; 508 519 IPC_SET_RETVAL(call->data, EHANGUP); 520 answer_preprocess(call, &old); 509 521 _ipc_answer_free_call(call, true); 510 } 522 523 irq_spinlock_lock(&box->lock, true); 524 } 525 irq_spinlock_unlock(&box->lock, true); 511 526 } 512 527 … … 546 561 mutex_unlock(&phone->lock); 547 562 irq_spinlock_unlock(&box->lock, true); 548 563 564 // FIXME: phone can become deallocated at any time now 565 549 566 /* 550 567 * Send one message to the answerbox for each … … 554 571 */ 555 572 IPC_SET_IMETHOD(call->data, IPC_M_PHONE_HUNGUP); 573 call->request_method = IPC_M_PHONE_HUNGUP; 556 574 call->flags |= IPC_CALL_DISCARD_ANSWER; 557 575 _ipc_call(phone, box, call); … … 574 592 } 575 593 594 static void ipc_forget_all_active_calls(void) 595 { 596 call_t *call; 597 598 restart: 599 spinlock_lock(&TASK->active_calls_lock); 600 if (list_empty(&TASK->active_calls)) { 601 /* 602 * We are done, there are no more active calls. 603 * Nota bene: there may still be answers waiting for pick up. 604 */ 605 spinlock_unlock(&TASK->active_calls_lock); 606 return; 607 } 608 609 call = list_get_instance(list_first(&TASK->active_calls), call_t, 610 ta_link); 611 612 if (!spinlock_trylock(&call->forget_lock)) { 613 /* 614 * Avoid deadlock and let async_answer() or 615 * _ipc_answer_free_call() win the race to dequeue the first 616 * call on the list. 617 */ 618 spinlock_unlock(&TASK->active_calls_lock); 619 goto restart; 620 } 621 622 /* 623 * Forget the call and donate it to the task which holds up the answer. 624 */ 625 626 call->forget = true; 627 call->sender = NULL; 628 list_remove(&call->ta_link); 629 630 /* 631 * The call may be freed by _ipc_answer_free_call() before we are done 632 * with it; to avoid working with a destroyed call_t structure, we 633 * must hold a reference to it. 634 */ 635 ipc_call_hold(call); 636 637 spinlock_unlock(&call->forget_lock); 638 spinlock_unlock(&TASK->active_calls_lock); 639 640 atomic_dec(&call->caller_phone->active_calls); 641 642 SYSIPC_OP(request_forget, call); 643 644 ipc_call_release(call); 645 646 goto restart; 647 } 648 649 /** Wait for all answers to asynchronous calls to arrive. */ 650 static void ipc_wait_for_all_answered_calls(void) 651 { 652 call_t *call; 653 size_t i; 654 655 restart: 656 /* 657 * Go through all phones, until they are all free. 658 * Locking is needed as there may be connection handshakes in progress. 659 */ 660 for (i = 0; i < IPC_MAX_PHONES; i++) { 661 phone_t *phone = &TASK->phones[i]; 662 663 mutex_lock(&phone->lock); 664 if ((phone->state == IPC_PHONE_HUNGUP) && 665 (atomic_get(&phone->active_calls) == 0)) { 666 phone->state = IPC_PHONE_FREE; 667 phone->callee = NULL; 668 } 669 670 /* 671 * We might have had some IPC_PHONE_CONNECTING phones at the 672 * beginning of ipc_cleanup(). Depending on whether these were 673 * forgotten or answered, they will eventually enter the 674 * IPC_PHONE_FREE or IPC_PHONE_CONNECTED states, respectively. 675 * In the latter case, the other side may slam the open phones 676 * at any time, in which case we will get an IPC_PHONE_SLAMMED 677 * phone. 678 */ 679 if ((phone->state == IPC_PHONE_CONNECTED) || 680 (phone->state == IPC_PHONE_SLAMMED)) { 681 mutex_unlock(&phone->lock); 682 ipc_phone_hangup(phone); 683 /* 684 * Now there may be one extra active call, which needs 685 * to be forgotten. 686 */ 687 ipc_forget_all_active_calls(); 688 goto restart; 689 } 690 691 /* 692 * If the hangup succeeded, it has sent a HANGUP message, the 693 * IPC is now in HUNGUP state, we wait for the reply to come 694 */ 695 if (phone->state != IPC_PHONE_FREE) { 696 mutex_unlock(&phone->lock); 697 break; 698 } 699 700 mutex_unlock(&phone->lock); 701 } 702 703 /* Got into cleanup */ 704 if (i == IPC_MAX_PHONES) 705 return; 706 707 call = ipc_wait_for_call(&TASK->answerbox, SYNCH_NO_TIMEOUT, 708 SYNCH_FLAGS_NONE); 709 ASSERT(call->flags & (IPC_CALL_ANSWERED | IPC_CALL_NOTIF)); 710 711 SYSIPC_OP(answer_process, call); 712 713 ipc_call_free(call); 714 goto restart; 715 } 716 576 717 /** Clean up all IPC communication of the current task. 577 718 * … … 582 723 void ipc_cleanup(void) 583 724 { 725 /* 726 * Mark the answerbox as inactive. 727 * 728 * The main purpose for doing this is to prevent any pending callback 729 * connections from getting established beyond this point. 730 */ 731 irq_spinlock_lock(&TASK->answerbox.lock, true); 732 TASK->answerbox.active = false; 733 irq_spinlock_unlock(&TASK->answerbox.lock, true); 734 584 735 /* Disconnect all our phones ('ipc_phone_hangup') */ 585 size_t i; 586 for (i = 0; i < IPC_MAX_PHONES; i++) 736 for (size_t i = 0; i < IPC_MAX_PHONES; i++) 587 737 ipc_phone_hangup(&TASK->phones[i]); 588 738 … … 602 752 603 753 /* Answer all messages in 'calls' and 'dispatched_calls' queues */ 604 irq_spinlock_lock(&TASK->answerbox.lock, true); 605 ipc_cleanup_call_list(&TASK->answerbox.dispatched_calls); 606 ipc_cleanup_call_list(&TASK->answerbox.calls); 607 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 623 /* Wait for all answers to asynchronous calls to arrive */ 624 while (true) { 625 /* 626 * Go through all phones, until they are all FREE 627 * Locking is not needed, no one else should modify 628 * it when we are in cleanup 629 */ 630 for (i = 0; i < IPC_MAX_PHONES; i++) { 631 if (TASK->phones[i].state == IPC_PHONE_HUNGUP && 632 atomic_get(&TASK->phones[i].active_calls) == 0) { 633 TASK->phones[i].state = IPC_PHONE_FREE; 634 TASK->phones[i].callee = NULL; 635 } 636 637 /* 638 * Just for sure, we might have had some 639 * IPC_PHONE_CONNECTING phones 640 */ 641 if (TASK->phones[i].state == IPC_PHONE_CONNECTED) 642 ipc_phone_hangup(&TASK->phones[i]); 643 644 /* 645 * If the hangup succeeded, it has sent a HANGUP 646 * message, the IPC is now in HUNGUP state, we 647 * wait for the reply to come 648 */ 649 650 if (TASK->phones[i].state != IPC_PHONE_FREE) 651 break; 652 } 653 654 /* Got into cleanup */ 655 if (i == IPC_MAX_PHONES) 656 break; 657 658 call_t *call = ipc_wait_for_call(&TASK->answerbox, SYNCH_NO_TIMEOUT, 659 SYNCH_FLAGS_NONE); 660 ASSERT((call->flags & IPC_CALL_ANSWERED) || 661 (call->flags & IPC_CALL_NOTIF)); 662 663 ipc_call_free(call); 664 } 754 ipc_cleanup_call_list(&TASK->answerbox, &TASK->answerbox.calls); 755 ipc_cleanup_call_list(&TASK->answerbox, 756 &TASK->answerbox.dispatched_calls); 757 758 ipc_forget_all_active_calls(); 759 ipc_wait_for_all_answered_calls(); 665 760 } 666 761 … … 674 769 ipc_answerbox_slab = slab_cache_create("answerbox_t", 675 770 sizeof(answerbox_t), 0, NULL, NULL, 0); 771 } 772 773 774 static void ipc_print_call_list(list_t *list) 775 { 776 list_foreach(*list, cur) { 777 call_t *call = list_get_instance(cur, call_t, ab_link); 778 779 #ifdef __32_BITS__ 780 printf("%10p ", call); 781 #endif 782 783 #ifdef __64_BITS__ 784 printf("%18p ", call); 785 #endif 786 787 spinlock_lock(&call->forget_lock); 788 789 printf("%-8" PRIun " %-6" PRIun " %-6" PRIun " %-6" PRIun 790 " %-6" PRIun " %-6" PRIun " %-7x", 791 IPC_GET_IMETHOD(call->data), IPC_GET_ARG1(call->data), 792 IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data), 793 IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data), 794 call->flags); 795 796 if (call->forget) { 797 printf(" ? (call forgotten)\n"); 798 } else { 799 printf(" %" PRIu64 " (%s)\n", 800 call->sender->taskid, call->sender->name); 801 } 802 803 spinlock_unlock(&call->forget_lock); 804 } 676 805 } 677 806 … … 747 876 748 877 printf(" --- incomming calls ---\n"); 749 list_foreach(task->answerbox.calls, cur) { 750 call_t *call = list_get_instance(cur, call_t, link); 751 752 #ifdef __32_BITS__ 753 printf("%10p ", call); 754 #endif 755 756 #ifdef __64_BITS__ 757 printf("%18p ", call); 758 #endif 759 760 printf("%-8" PRIun " %-6" PRIun " %-6" PRIun " %-6" PRIun 761 " %-6" PRIun " %-6" PRIun " %-7x %" PRIu64 " (%s)\n", 762 IPC_GET_IMETHOD(call->data), IPC_GET_ARG1(call->data), 763 IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data), 764 IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data), 765 call->flags, call->sender->taskid, call->sender->name); 766 } 767 878 ipc_print_call_list(&task->answerbox.calls); 768 879 printf(" --- dispatched calls ---\n"); 769 list_foreach(task->answerbox.dispatched_calls, cur) { 770 call_t *call = list_get_instance(cur, call_t, link); 771 772 #ifdef __32_BITS__ 773 printf("%10p ", call); 774 #endif 775 776 #ifdef __64_BITS__ 777 printf("%18p ", call); 778 #endif 779 780 printf("%-8" PRIun " %-6" PRIun " %-6" PRIun " %-6" PRIun 781 " %-6" PRIun " %-6" PRIun " %-7x %" PRIu64 " (%s)\n", 782 IPC_GET_IMETHOD(call->data), IPC_GET_ARG1(call->data), 783 IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data), 784 IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data), 785 call->flags, call->sender->taskid, call->sender->name); 786 } 787 880 ipc_print_call_list(&task->answerbox.dispatched_calls); 788 881 printf(" --- incoming answers ---\n"); 789 list_foreach(task->answerbox.answers, cur) { 790 call_t *call = list_get_instance(cur, call_t, link); 791 792 #ifdef __32_BITS__ 793 printf("%10p ", call); 794 #endif 795 796 #ifdef __64_BITS__ 797 printf("%18p ", call); 798 #endif 799 800 printf("%-8" PRIun " %-6" PRIun " %-6" PRIun " %-6" PRIun 801 " %-6" PRIun " %-6" PRIun " %-7x %" PRIu64 " (%s)\n", 802 IPC_GET_IMETHOD(call->data), IPC_GET_ARG1(call->data), 803 IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data), 804 IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data), 805 call->flags, call->sender->taskid, call->sender->name); 806 } 882 ipc_print_call_list(&task->answerbox.answers); 807 883 808 884 irq_spinlock_unlock(&task->answerbox.lock, false); -
kernel/generic/src/ipc/ipcrsc.c
rde73242 refdfebc 132 132 #include <ipc/ipcrsc.h> 133 133 #include <debug.h> 134 #include <abi/errno.h> 134 135 135 136 /** Find call_t * in call table according to callid. … … 151 152 152 153 list_foreach(TASK->answerbox.dispatched_calls, lst) { 153 call_t *call = list_get_instance(lst, call_t, link);154 call_t *call = list_get_instance(lst, call_t, ab_link); 154 155 if ((sysarg_t) call == callid) { 155 156 result = call; … … 162 163 } 163 164 165 /** Get phone from the current task by ID. 166 * 167 * @param phoneid Phone ID. 168 * @param phone Place to store pointer to phone. 169 * 170 * @return EOK on success, EINVAL if ID is invalid. 171 * 172 */ 173 int phone_get(sysarg_t phoneid, phone_t **phone) 174 { 175 if (phoneid >= IPC_MAX_PHONES) 176 return EINVAL; 177 178 *phone = &TASK->phones[phoneid]; 179 return EOK; 180 } 181 164 182 /** Allocate new phone slot in the specified task. 165 183 * … … 176 194 size_t i; 177 195 for (i = 0; i < IPC_MAX_PHONES; i++) { 178 if ((task->phones[i].state == IPC_PHONE_HUNGUP) && 179 (atomic_get(&task->phones[i].active_calls) == 0)) 180 task->phones[i].state = IPC_PHONE_FREE; 196 phone_t *phone = &task->phones[i]; 197 198 if ((phone->state == IPC_PHONE_HUNGUP) && 199 (atomic_get(&phone->active_calls) == 0)) 200 phone->state = IPC_PHONE_FREE; 181 201 182 if ( task->phones[i].state == IPC_PHONE_FREE) {183 task->phones[i].state = IPC_PHONE_CONNECTING;202 if (phone->state == IPC_PHONE_FREE) { 203 phone->state = IPC_PHONE_CONNECTING; 184 204 break; 185 205 } … … 223 243 * @param phoneid Phone handle to be connected. 224 244 * @param box Answerbox to which to connect the phone handle. 245 * @return True if the phone was connected, false otherwise. 225 246 * 226 247 * The procedure _enforces_ that the user first marks the phone … … 229 250 * 230 251 */ 231 voidphone_connect(int phoneid, answerbox_t *box)252 bool phone_connect(int phoneid, answerbox_t *box) 232 253 { 233 254 phone_t *phone = &TASK->phones[phoneid]; 234 255 235 256 ASSERT(phone->state == IPC_PHONE_CONNECTING); 236 ipc_phone_connect(phone, box);257 return ipc_phone_connect(phone, box); 237 258 } 238 259 -
kernel/generic/src/ipc/irq.c
rde73242 refdfebc 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 134 128 case CMD_PIO_WRITE_8: 129 case CMD_PIO_WRITE_A_8: 135 130 size = 1; 136 131 break; 137 138 139 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 143 144 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); … … 466 510 { 467 511 irq_spinlock_lock(&irq->notif_cfg.answerbox->irq_lock, false); 468 list_append(&call-> link, &irq->notif_cfg.answerbox->irq_notifs);512 list_append(&call->ab_link, &irq->notif_cfg.answerbox->irq_notifs); 469 513 irq_spinlock_unlock(&irq->notif_cfg.answerbox->irq_lock, false); 470 514 … … 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/kbox.c
rde73242 refdfebc 48 48 { 49 49 /* 50 * Not really needed, just to be consistent with the meaning of 51 * answerbox_t.active. 52 */ 53 irq_spinlock_lock(&TASK->kb.box.lock, true); 54 TASK->kb.box.active = false; 55 irq_spinlock_unlock(&TASK->kb.box.lock, true); 56 57 /* 50 58 * Only hold kb.cleanup_lock while setting kb.finished - 51 59 * this is enough. … … 88 96 89 97 /* Answer all messages in 'calls' and 'dispatched_calls' queues. */ 90 irq_spinlock_lock(&TASK->kb.box.lock, true); 91 ipc_cleanup_call_list(&TASK->kb.box.dispatched_calls); 92 ipc_cleanup_call_list(&TASK->kb.box.calls); 93 irq_spinlock_unlock(&TASK->kb.box.lock, true); 98 ipc_cleanup_call_list(&TASK->kb.box, &TASK->kb.box.calls); 99 ipc_cleanup_call_list(&TASK->kb.box, &TASK->kb.box.dispatched_calls); 94 100 } 95 101 … … 162 168 while (!done) { 163 169 call_t *call = ipc_wait_for_call(&TASK->kb.box, SYNCH_NO_TIMEOUT, 164 170 SYNCH_FLAGS_NONE); 165 171 166 172 if (call == NULL) … … 236 242 237 243 /* Connect the newly allocated phone to the kbox */ 238 ipc_phone_connect(&TASK->phones[newphid], &task->kb.box);244 (void) ipc_phone_connect(&TASK->phones[newphid], &task->kb.box); 239 245 240 246 if (task->kb.thread != NULL) { -
kernel/generic/src/ipc/sysipc.c
rde73242 refdfebc 34 34 35 35 #include <arch.h> 36 #include <proc/task.h>37 #include <proc/thread.h>38 36 #include <errno.h> 39 37 #include <memstr.h> 40 #include <debug.h>41 38 #include <ipc/ipc.h> 42 39 #include <abi/ipc/methods.h> 43 40 #include <ipc/sysipc.h> 41 #include <ipc/sysipc_ops.h> 42 #include <ipc/sysipc_priv.h> 44 43 #include <ipc/irq.h> 45 44 #include <ipc/ipcrsc.h> … … 47 46 #include <ipc/kbox.h> 48 47 #include <synch/waitq.h> 49 #include <udebug/udebug_ipc.h>50 48 #include <arch/interrupt.h> 51 49 #include <syscall/copy.h> 52 50 #include <security/cap.h> 53 51 #include <console/console.h> 54 #include <mm/as.h>55 52 #include <print.h> 56 53 #include <macros.h> 57 54 58 /**59 * Maximum buffer size allowed for IPC_M_DATA_WRITE and IPC_M_DATA_READ60 * requests.61 */62 #define DATA_XFER_LIMIT (64 * 1024)63 64 55 #define STRUCT_TO_USPACE(dst, src) copy_to_uspace((dst), (src), sizeof(*(src))) 65 66 /** Get phone from the current task by ID.67 *68 * @param phoneid Phone ID.69 * @param phone Place to store pointer to phone.70 *71 * @return EOK on success, EINVAL if ID is invalid.72 *73 */74 static int phone_get(sysarg_t phoneid, phone_t **phone)75 {76 if (phoneid >= IPC_MAX_PHONES)77 return EINVAL;78 79 *phone = &TASK->phones[phoneid];80 return EOK;81 }82 56 83 57 /** Decide if the interface and method is a system method. … … 181 155 * @param olddata Saved data of the request. 182 156 * 183 * @return Return 0 on success or an error code. 184 * 185 */ 186 static inline int answer_preprocess(call_t *answer, ipc_data_t *olddata) 187 { 157 * @return Return EOK on success or a negative error code. 158 * 159 */ 160 int answer_preprocess(call_t *answer, ipc_data_t *olddata) 161 { 162 int rc = EOK; 163 164 spinlock_lock(&answer->forget_lock); 165 if (answer->forget) { 166 /* 167 * This is a forgotten call and answer->sender is not valid. 168 */ 169 spinlock_unlock(&answer->forget_lock); 170 171 SYSIPC_OP(answer_cleanup, answer, olddata); 172 return rc; 173 } else { 174 ASSERT(answer->active); 175 176 /* 177 * Mark the call as inactive to prevent _ipc_answer_free_call() 178 * from attempting to remove the call from the active list 179 * itself. 180 */ 181 answer->active = false; 182 183 /* 184 * Remove the call from the sender's active call list. 185 * We enforce this locking order so that any potential 186 * concurrently executing forget operation is forced to 187 * release its active_calls_lock and lose the race to 188 * forget this soon to be answered call. 189 */ 190 spinlock_lock(&answer->sender->active_calls_lock); 191 list_remove(&answer->ta_link); 192 spinlock_unlock(&answer->sender->active_calls_lock); 193 } 194 spinlock_unlock(&answer->forget_lock); 195 188 196 if ((native_t) IPC_GET_RETVAL(answer->data) == EHANGUP) { 189 /* In case of forward, hangup the forwared phone, 190 * not the originator 191 */ 192 mutex_lock(&answer->data.phone->lock); 193 irq_spinlock_lock(&TASK->answerbox.lock, true); 194 if (answer->data.phone->state == IPC_PHONE_CONNECTED) { 195 list_remove(&answer->data.phone->link); 196 answer->data.phone->state = IPC_PHONE_SLAMMED; 197 phone_t *phone = answer->caller_phone; 198 mutex_lock(&phone->lock); 199 if (phone->state == IPC_PHONE_CONNECTED) { 200 irq_spinlock_lock(&phone->callee->lock, true); 201 list_remove(&phone->link); 202 phone->state = IPC_PHONE_SLAMMED; 203 irq_spinlock_unlock(&phone->callee->lock, true); 197 204 } 198 irq_spinlock_unlock(&TASK->answerbox.lock, true); 199 mutex_unlock(&answer->data.phone->lock); 205 mutex_unlock(&phone->lock); 200 206 } 201 207 202 208 if (!olddata) 203 return 0; 204 205 if (IPC_GET_IMETHOD(*olddata) == IPC_M_CONNECTION_CLONE) { 206 int phoneid = IPC_GET_ARG1(*olddata); 207 phone_t *phone = &TASK->phones[phoneid]; 208 209 if (IPC_GET_RETVAL(answer->data) != EOK) { 210 /* 211 * The recipient of the cloned phone rejected the offer. 212 * In this case, the connection was established at the 213 * request time and therefore we need to slam the phone. 214 * We don't merely hangup as that would result in 215 * sending IPC_M_HUNGUP to the third party on the 216 * other side of the cloned phone. 217 */ 218 mutex_lock(&phone->lock); 219 if (phone->state == IPC_PHONE_CONNECTED) { 220 irq_spinlock_lock(&phone->callee->lock, true); 221 list_remove(&phone->link); 222 phone->state = IPC_PHONE_SLAMMED; 223 irq_spinlock_unlock(&phone->callee->lock, true); 224 } 225 mutex_unlock(&phone->lock); 226 } 227 } else if (IPC_GET_IMETHOD(*olddata) == IPC_M_CLONE_ESTABLISH) { 228 phone_t *phone = (phone_t *) IPC_GET_ARG5(*olddata); 229 230 if (IPC_GET_RETVAL(answer->data) != EOK) { 231 /* 232 * The other party on the cloned phoned rejected our 233 * request for connection on the protocol level. 234 * We need to break the connection without sending 235 * IPC_M_HUNGUP back. 236 */ 237 mutex_lock(&phone->lock); 238 if (phone->state == IPC_PHONE_CONNECTED) { 239 irq_spinlock_lock(&phone->callee->lock, true); 240 list_remove(&phone->link); 241 phone->state = IPC_PHONE_SLAMMED; 242 irq_spinlock_unlock(&phone->callee->lock, true); 243 } 244 mutex_unlock(&phone->lock); 245 } 246 } else if (IPC_GET_IMETHOD(*olddata) == IPC_M_CONNECT_TO_ME) { 247 int phoneid = IPC_GET_ARG5(*olddata); 248 249 if (IPC_GET_RETVAL(answer->data) != EOK) { 250 /* The connection was not accepted */ 251 phone_dealloc(phoneid); 252 } else { 253 /* The connection was accepted */ 254 phone_connect(phoneid, &answer->sender->answerbox); 255 /* Set 'phone hash' as arg5 of response */ 256 IPC_SET_ARG5(answer->data, 257 (sysarg_t) &TASK->phones[phoneid]); 258 } 259 } else if (IPC_GET_IMETHOD(*olddata) == IPC_M_CONNECT_ME_TO) { 260 /* If the users accepted call, connect */ 261 if (IPC_GET_RETVAL(answer->data) == EOK) { 262 ipc_phone_connect((phone_t *) IPC_GET_ARG5(*olddata), 263 &TASK->answerbox); 264 } 265 } else if (IPC_GET_IMETHOD(*olddata) == IPC_M_SHARE_OUT) { 266 if (!IPC_GET_RETVAL(answer->data)) { 267 /* Accepted, handle as_area receipt */ 268 269 irq_spinlock_lock(&answer->sender->lock, true); 270 as_t *as = answer->sender->as; 271 irq_spinlock_unlock(&answer->sender->lock, true); 272 273 uintptr_t dst_base = (uintptr_t) -1; 274 int rc = as_area_share(as, IPC_GET_ARG1(*olddata), 275 IPC_GET_ARG2(*olddata), AS, IPC_GET_ARG3(*olddata), 276 &dst_base, IPC_GET_ARG1(answer->data)); 277 278 if (rc == EOK) 279 rc = copy_to_uspace((void *) IPC_GET_ARG2(answer->data), 280 &dst_base, sizeof(dst_base)); 281 282 IPC_SET_RETVAL(answer->data, rc); 283 return rc; 284 } 285 } else if (IPC_GET_IMETHOD(*olddata) == IPC_M_SHARE_IN) { 286 if (!IPC_GET_RETVAL(answer->data)) { 287 irq_spinlock_lock(&answer->sender->lock, true); 288 as_t *as = answer->sender->as; 289 irq_spinlock_unlock(&answer->sender->lock, true); 290 291 uintptr_t dst_base = (uintptr_t) -1; 292 int rc = as_area_share(AS, IPC_GET_ARG1(answer->data), 293 IPC_GET_ARG1(*olddata), as, IPC_GET_ARG2(answer->data), 294 &dst_base, IPC_GET_ARG3(answer->data)); 295 IPC_SET_ARG4(answer->data, dst_base); 296 IPC_SET_RETVAL(answer->data, rc); 297 } 298 } else if (IPC_GET_IMETHOD(*olddata) == IPC_M_DATA_READ) { 299 ASSERT(!answer->buffer); 300 if (!IPC_GET_RETVAL(answer->data)) { 301 /* The recipient agreed to send data. */ 302 uintptr_t src = IPC_GET_ARG1(answer->data); 303 uintptr_t dst = IPC_GET_ARG1(*olddata); 304 size_t max_size = IPC_GET_ARG2(*olddata); 305 size_t size = IPC_GET_ARG2(answer->data); 306 if (size && size <= max_size) { 307 /* 308 * Copy the destination VA so that this piece of 309 * information is not lost. 310 */ 311 IPC_SET_ARG1(answer->data, dst); 312 313 answer->buffer = malloc(size, 0); 314 int rc = copy_from_uspace(answer->buffer, 315 (void *) src, size); 316 if (rc) { 317 IPC_SET_RETVAL(answer->data, rc); 318 free(answer->buffer); 319 answer->buffer = NULL; 320 } 321 } else if (!size) { 322 IPC_SET_RETVAL(answer->data, EOK); 323 } else { 324 IPC_SET_RETVAL(answer->data, ELIMIT); 325 } 326 } 327 } else if (IPC_GET_IMETHOD(*olddata) == IPC_M_DATA_WRITE) { 328 ASSERT(answer->buffer); 329 if (!IPC_GET_RETVAL(answer->data)) { 330 /* The recipient agreed to receive data. */ 331 uintptr_t dst = (uintptr_t)IPC_GET_ARG1(answer->data); 332 size_t size = (size_t)IPC_GET_ARG2(answer->data); 333 size_t max_size = (size_t)IPC_GET_ARG2(*olddata); 334 335 if (size <= max_size) { 336 int rc = copy_to_uspace((void *) dst, 337 answer->buffer, size); 338 if (rc) 339 IPC_SET_RETVAL(answer->data, rc); 340 } else { 341 IPC_SET_RETVAL(answer->data, ELIMIT); 342 } 343 } 344 free(answer->buffer); 345 answer->buffer = NULL; 346 } else if (IPC_GET_IMETHOD(*olddata) == IPC_M_STATE_CHANGE_AUTHORIZE) { 347 if (!IPC_GET_RETVAL(answer->data)) { 348 /* The recipient authorized the change of state. */ 349 phone_t *recipient_phone; 350 task_t *other_task_s; 351 task_t *other_task_r; 352 int rc; 353 354 rc = phone_get(IPC_GET_ARG1(answer->data), 355 &recipient_phone); 356 if (rc != EOK) { 357 IPC_SET_RETVAL(answer->data, ENOENT); 358 return ENOENT; 359 } 360 361 mutex_lock(&recipient_phone->lock); 362 if (recipient_phone->state != IPC_PHONE_CONNECTED) { 363 mutex_unlock(&recipient_phone->lock); 364 IPC_SET_RETVAL(answer->data, EINVAL); 365 return EINVAL; 366 } 367 368 other_task_r = recipient_phone->callee->task; 369 other_task_s = (task_t *) IPC_GET_ARG5(*olddata); 370 371 /* 372 * See if both the sender and the recipient meant the 373 * same third party task. 374 */ 375 if (other_task_r != other_task_s) { 376 IPC_SET_RETVAL(answer->data, EINVAL); 377 rc = EINVAL; 378 } else { 379 rc = event_task_notify_5(other_task_r, 380 EVENT_TASK_STATE_CHANGE, false, 381 IPC_GET_ARG1(*olddata), 382 IPC_GET_ARG2(*olddata), 383 IPC_GET_ARG3(*olddata), 384 LOWER32(olddata->task_id), 385 UPPER32(olddata->task_id)); 386 IPC_SET_RETVAL(answer->data, rc); 387 } 388 389 mutex_unlock(&recipient_phone->lock); 390 return rc; 391 } 392 } 393 394 return 0; 395 } 396 397 static void phones_lock(phone_t *p1, phone_t *p2) 398 { 399 if (p1 < p2) { 400 mutex_lock(&p1->lock); 401 mutex_lock(&p2->lock); 402 } else if (p1 > p2) { 403 mutex_lock(&p2->lock); 404 mutex_lock(&p1->lock); 405 } else 406 mutex_lock(&p1->lock); 407 } 408 409 static void phones_unlock(phone_t *p1, phone_t *p2) 410 { 411 mutex_unlock(&p1->lock); 412 if (p1 != p2) 413 mutex_unlock(&p2->lock); 209 return rc; 210 211 return SYSIPC_OP(answer_preprocess, answer, olddata); 414 212 } 415 213 … … 424 222 static int request_preprocess(call_t *call, phone_t *phone) 425 223 { 426 switch (IPC_GET_IMETHOD(call->data)) { 427 case IPC_M_CONNECTION_CLONE: { 428 phone_t *cloned_phone; 429 if (phone_get(IPC_GET_ARG1(call->data), &cloned_phone) != EOK) 430 return ENOENT; 431 432 phones_lock(cloned_phone, phone); 433 434 if ((cloned_phone->state != IPC_PHONE_CONNECTED) || 435 phone->state != IPC_PHONE_CONNECTED) { 436 phones_unlock(cloned_phone, phone); 437 return EINVAL; 438 } 439 440 /* 441 * We can be pretty sure now that both tasks exist and we are 442 * connected to them. As we continue to hold the phone locks, 443 * we are effectively preventing them from finishing their 444 * potential cleanup. 445 * 446 */ 447 int newphid = phone_alloc(phone->callee->task); 448 if (newphid < 0) { 449 phones_unlock(cloned_phone, phone); 450 return ELIMIT; 451 } 452 453 ipc_phone_connect(&phone->callee->task->phones[newphid], 454 cloned_phone->callee); 455 phones_unlock(cloned_phone, phone); 456 457 /* Set the new phone for the callee. */ 458 IPC_SET_ARG1(call->data, newphid); 459 break; 460 } 461 case IPC_M_CLONE_ESTABLISH: 462 IPC_SET_ARG5(call->data, (sysarg_t) phone); 463 break; 464 case IPC_M_CONNECT_ME_TO: { 465 int newphid = phone_alloc(TASK); 466 if (newphid < 0) 467 return ELIMIT; 468 469 /* Set arg5 for server */ 470 IPC_SET_ARG5(call->data, (sysarg_t) &TASK->phones[newphid]); 471 call->flags |= IPC_CALL_CONN_ME_TO; 472 call->priv = newphid; 473 break; 474 } 475 case IPC_M_SHARE_OUT: { 476 size_t size = as_area_get_size(IPC_GET_ARG1(call->data)); 477 if (!size) 478 return EPERM; 479 480 IPC_SET_ARG2(call->data, size); 481 break; 482 } 483 case IPC_M_DATA_READ: { 484 size_t size = IPC_GET_ARG2(call->data); 485 if (size > DATA_XFER_LIMIT) { 486 int flags = IPC_GET_ARG3(call->data); 487 if (flags & IPC_XF_RESTRICT) 488 IPC_SET_ARG2(call->data, DATA_XFER_LIMIT); 489 else 490 return ELIMIT; 491 } 492 break; 493 } 494 case IPC_M_DATA_WRITE: { 495 uintptr_t src = IPC_GET_ARG1(call->data); 496 size_t size = IPC_GET_ARG2(call->data); 497 498 if (size > DATA_XFER_LIMIT) { 499 int flags = IPC_GET_ARG3(call->data); 500 if (flags & IPC_XF_RESTRICT) { 501 size = DATA_XFER_LIMIT; 502 IPC_SET_ARG2(call->data, size); 503 } else 504 return ELIMIT; 505 } 506 507 call->buffer = (uint8_t *) malloc(size, 0); 508 int rc = copy_from_uspace(call->buffer, (void *) src, size); 509 if (rc != 0) { 510 free(call->buffer); 511 return rc; 512 } 513 514 break; 515 } 516 case IPC_M_STATE_CHANGE_AUTHORIZE: { 517 phone_t *sender_phone; 518 task_t *other_task_s; 519 520 if (phone_get(IPC_GET_ARG5(call->data), &sender_phone) != EOK) 521 return ENOENT; 522 523 mutex_lock(&sender_phone->lock); 524 if (sender_phone->state != IPC_PHONE_CONNECTED) { 525 mutex_unlock(&sender_phone->lock); 526 return EINVAL; 527 } 528 529 other_task_s = sender_phone->callee->task; 530 531 mutex_unlock(&sender_phone->lock); 532 533 /* Remember the third party task hash. */ 534 IPC_SET_ARG5(call->data, (sysarg_t) other_task_s); 535 break; 536 } 537 #ifdef CONFIG_UDEBUG 538 case IPC_M_DEBUG: 539 return udebug_request_preprocess(call, phone); 540 #endif 541 default: 542 break; 543 } 544 545 return 0; 224 call->request_method = IPC_GET_IMETHOD(call->data); 225 return SYSIPC_OP(request_preprocess, call, phone); 546 226 } 547 227 … … 561 241 IPC_SET_RETVAL(call->data, EFORWARD); 562 242 563 if (call->flags & IPC_CALL_CONN_ME_TO) { 564 if (IPC_GET_RETVAL(call->data)) 565 phone_dealloc(call->priv); 566 else 567 IPC_SET_ARG5(call->data, call->priv); 568 } 569 570 if (call->buffer) { 571 /* 572 * This must be an affirmative answer to IPC_M_DATA_READ 573 * or IPC_M_DEBUG/UDEBUG_M_MEM_READ... 574 * 575 */ 576 uintptr_t dst = IPC_GET_ARG1(call->data); 577 size_t size = IPC_GET_ARG2(call->data); 578 int rc = copy_to_uspace((void *) dst, call->buffer, size); 579 if (rc) 580 IPC_SET_RETVAL(call->data, rc); 581 free(call->buffer); 582 call->buffer = NULL; 583 } 584 } 243 SYSIPC_OP(answer_process, call); 244 } 245 585 246 586 247 /** Do basic kernel processing of received call request. … … 595 256 static int process_request(answerbox_t *box, call_t *call) 596 257 { 597 if (IPC_GET_IMETHOD(call->data) == IPC_M_CONNECT_TO_ME) { 598 int phoneid = phone_alloc(TASK); 599 if (phoneid < 0) { /* Failed to allocate phone */ 600 IPC_SET_RETVAL(call->data, ELIMIT); 601 ipc_answer(box, call); 602 return -1; 603 } 604 605 IPC_SET_ARG5(call->data, phoneid); 606 } 607 608 switch (IPC_GET_IMETHOD(call->data)) { 609 case IPC_M_DEBUG: 610 return -1; 611 default: 612 break; 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 than 621 * 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 will 629 * 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 beyond 650 * 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_UDEBUG 660 udebug_stoppable_begin(); 661 #endif 662 rc = ipc_call_sync(phone, call); 663 #ifdef CONFIG_UDEBUG 664 udebug_stoppable_end(); 665 #endif 666 667 if (rc != EOK) { 668 /* The call will be freed by ipc_cleanup(). */ 669 return rc; 670 } 671 672 process_answer(call); 673 } else 674 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 the 689 * 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_UDEBUG 713 udebug_stoppable_begin(); 714 #endif 715 rc = ipc_call_sync(phone, call); 716 #ifdef CONFIG_UDEBUG 717 udebug_stoppable_end(); 718 #endif 719 720 if (rc != EOK) { 721 /* The call will be freed by ipc_cleanup(). */ 722 return rc; 723 } 724 725 process_answer(call); 726 } else 727 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 734 return 0; 258 return SYSIPC_OP(request_process, call, box); 735 259 } 736 260 … … 864 388 { 865 389 call_t *call = get_call(callid); 390 phone_t *phone; 391 bool need_old = answer_need_old(call); 392 bool after_forward = false; 393 ipc_data_t old; 394 int rc; 395 866 396 if (!call) 867 397 return ENOENT; 868 398 399 if (need_old) 400 old = call->data; 401 402 if (phone_get(phoneid, &phone) != EOK) { 403 rc = ENOENT; 404 goto error; 405 } 406 407 if (!method_is_forwardable(IPC_GET_IMETHOD(call->data))) { 408 rc = EPERM; 409 goto error; 410 } 411 869 412 call->flags |= IPC_CALL_FORWARDED; 870 871 phone_t *phone;872 if (phone_get(phoneid, &phone) != EOK) {873 IPC_SET_RETVAL(call->data, EFORWARD);874 ipc_answer(&TASK->answerbox, call);875 return ENOENT;876 }877 878 if (!method_is_forwardable(IPC_GET_IMETHOD(call->data))) {879 IPC_SET_RETVAL(call->data, EFORWARD);880 ipc_answer(&TASK->answerbox, call);881 return EPERM;882 }883 413 884 414 /* … … 916 446 } 917 447 918 return ipc_forward(call, phone, &TASK->answerbox, mode); 448 rc = ipc_forward(call, phone, &TASK->answerbox, mode); 449 if (rc != EOK) { 450 after_forward = true; 451 goto error; 452 } 453 454 return EOK; 455 456 error: 457 IPC_SET_RETVAL(call->data, EFORWARD); 458 (void) answer_preprocess(call, need_old ? &old : NULL); 459 if (after_forward) 460 _ipc_answer_free_call(call, false); 461 else 462 ipc_answer(&TASK->answerbox, call); 463 464 return rc; 919 465 } 920 466 -
kernel/generic/src/lib/str.c
rde73242 refdfebc 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/main/kinit.c
rde73242 refdfebc 69 69 #include <str.h> 70 70 #include <sysinfo/stats.h> 71 #include <sysinfo/sysinfo.h> 71 72 #include <align.h> 72 73 … … 179 180 program_t programs[CONFIG_INIT_TASKS]; 180 181 182 // FIXME: do not propagate arguments through sysinfo 183 // but pass them directly to the tasks 184 for (i = 0; i < init.cnt; i++) { 185 const char *arguments = init.tasks[i].arguments; 186 if (str_length(arguments) == 0) 187 continue; 188 if (str_length(init.tasks[i].name) == 0) 189 continue; 190 size_t arguments_size = str_size(arguments); 191 192 void *arguments_copy = malloc(arguments_size, 0); 193 if (arguments_copy == NULL) 194 continue; 195 memcpy(arguments_copy, arguments, arguments_size); 196 197 char item_name[CONFIG_TASK_NAME_BUFLEN + 15]; 198 snprintf(item_name, CONFIG_TASK_NAME_BUFLEN + 15, 199 "init_args.%s", init.tasks[i].name); 200 201 sysinfo_set_item_data(item_name, NULL, arguments_copy, arguments_size); 202 } 203 181 204 for (i = 0; i < init.cnt; i++) { 182 205 if (init.tasks[i].paddr % FRAME_SIZE) { -
kernel/generic/src/mm/as.c
rde73242 refdfebc 285 285 /** Check area conflicts with other areas. 286 286 * 287 * @param as Address space. 288 * @param addr Starting virtual address of the area being tested. 289 * @param count Number of pages in the area being tested. 290 * @param avoid Do not touch this area. 287 * @param as Address space. 288 * @param addr Starting virtual address of the area being tested. 289 * @param count Number of pages in the area being tested. 290 * @param guarded True if the area being tested is protected by guard pages. 291 * @param avoid Do not touch this area. 291 292 * 292 293 * @return True if there is no conflict, false otherwise. … … 294 295 */ 295 296 NO_TRACE static bool check_area_conflicts(as_t *as, uintptr_t addr, 296 size_t count, as_area_t *avoid)297 size_t count, bool guarded, as_area_t *avoid) 297 298 { 298 299 ASSERT((addr % PAGE_SIZE) == 0); 299 300 ASSERT(mutex_locked(&as->lock)); 301 302 /* 303 * If the addition of the supposed area address and size overflows, 304 * report conflict. 305 */ 306 if (overflows_into_positive(addr, P2SZ(count))) 307 return false; 300 308 301 309 /* … … 304 312 if (overlaps(addr, P2SZ(count), (uintptr_t) NULL, PAGE_SIZE)) 305 313 return false; 306 314 307 315 /* 308 316 * The leaf node is found in O(log n), where n is proportional to … … 328 336 if (area != avoid) { 329 337 mutex_lock(&area->lock); 330 338 339 /* 340 * If at least one of the two areas are protected 341 * by the AS_AREA_GUARD flag then we must be sure 342 * that they are separated by at least one unmapped 343 * page. 344 */ 345 int const gp = (guarded || 346 (area->flags & AS_AREA_GUARD)) ? 1 : 0; 347 348 /* 349 * The area comes from the left neighbour node, which 350 * means that there already are some areas in the leaf 351 * node, which in turn means that adding gp is safe and 352 * will not cause an integer overflow. 353 */ 331 354 if (overlaps(addr, P2SZ(count), area->base, 355 P2SZ(area->pages + gp))) { 356 mutex_unlock(&area->lock); 357 return false; 358 } 359 360 mutex_unlock(&area->lock); 361 } 362 } 363 364 node = btree_leaf_node_right_neighbour(&as->as_area_btree, leaf); 365 if (node) { 366 area = (as_area_t *) node->value[0]; 367 368 if (area != avoid) { 369 int gp; 370 371 mutex_lock(&area->lock); 372 373 gp = (guarded || (area->flags & AS_AREA_GUARD)) ? 1 : 0; 374 if (gp && overflows(addr, P2SZ(count))) { 375 /* 376 * Guard page not needed if the supposed area 377 * is adjacent to the end of the address space. 378 * We already know that the following test is 379 * going to fail... 380 */ 381 gp--; 382 } 383 384 if (overlaps(addr, P2SZ(count + gp), area->base, 332 385 P2SZ(area->pages))) { 333 386 mutex_unlock(&area->lock); … … 339 392 } 340 393 341 node = btree_leaf_node_right_neighbour(&as->as_area_btree, leaf);342 if (node) {343 area = (as_area_t *) node->value[0];344 345 if (area != avoid) {346 mutex_lock(&area->lock);347 348 if (overlaps(addr, P2SZ(count), area->base,349 P2SZ(area->pages))) {350 mutex_unlock(&area->lock);351 return false;352 }353 354 mutex_unlock(&area->lock);355 }356 }357 358 394 /* Second, check the leaf node. */ 359 395 btree_key_t i; 360 396 for (i = 0; i < leaf->keys; i++) { 361 397 area = (as_area_t *) leaf->value[i]; 398 int agp; 399 int gp; 362 400 363 401 if (area == avoid) … … 365 403 366 404 mutex_lock(&area->lock); 367 368 if (overlaps(addr, P2SZ(count), area->base, 369 P2SZ(area->pages))) { 405 406 gp = (guarded || (area->flags & AS_AREA_GUARD)) ? 1 : 0; 407 agp = gp; 408 409 /* 410 * Sanitize the two possible unsigned integer overflows. 411 */ 412 if (gp && overflows(addr, P2SZ(count))) 413 gp--; 414 if (agp && overflows(area->base, P2SZ(area->pages))) 415 agp--; 416 417 if (overlaps(addr, P2SZ(count + gp), area->base, 418 P2SZ(area->pages + agp))) { 370 419 mutex_unlock(&area->lock); 371 420 return false; … … 392 441 * this function. 393 442 * 394 * @param as Address space. 395 * @param bound Lowest address bound. 396 * @param size Requested size of the allocation. 443 * @param as Address space. 444 * @param bound Lowest address bound. 445 * @param size Requested size of the allocation. 446 * @param guarded True if the allocation must be protected by guard pages. 397 447 * 398 448 * @return Address of the beginning of unmapped address space area. … … 401 451 */ 402 452 NO_TRACE static uintptr_t as_get_unmapped_area(as_t *as, uintptr_t bound, 403 size_t size )453 size_t size, bool guarded) 404 454 { 405 455 ASSERT(mutex_locked(&as->lock)); … … 423 473 /* First check the bound address itself */ 424 474 uintptr_t addr = ALIGN_UP(bound, PAGE_SIZE); 425 if ((addr >= bound) && 426 (check_area_conflicts(as, addr, pages, NULL))) 427 return addr; 475 if (addr >= bound) { 476 if (guarded) { 477 /* Leave an unmapped page between the lower 478 * bound and the area's start address. 479 */ 480 addr += P2SZ(1); 481 } 482 483 if (check_area_conflicts(as, addr, pages, guarded, NULL)) 484 return addr; 485 } 428 486 429 487 /* Eventually check the addresses behind each area */ … … 439 497 addr = 440 498 ALIGN_UP(area->base + P2SZ(area->pages), PAGE_SIZE); 499 500 if (guarded || area->flags & AS_AREA_GUARD) { 501 /* We must leave an unmapped page 502 * between the two areas. 503 */ 504 addr += P2SZ(1); 505 } 506 441 507 bool avail = 442 508 ((addr >= bound) && (addr >= area->base) && 443 (check_area_conflicts(as, addr, pages, area)));509 (check_area_conflicts(as, addr, pages, guarded, area))); 444 510 445 511 mutex_unlock(&area->lock); … … 481 547 if (size == 0) 482 548 return NULL; 483 549 484 550 size_t pages = SIZE2FRAMES(size); 485 551 … … 487 553 if ((flags & AS_AREA_EXEC) && (flags & AS_AREA_WRITE)) 488 554 return NULL; 555 556 bool const guarded = flags & AS_AREA_GUARD; 489 557 490 558 mutex_lock(&as->lock); 491 559 492 560 if (*base == (uintptr_t) -1) { 493 *base = as_get_unmapped_area(as, bound, size );561 *base = as_get_unmapped_area(as, bound, size, guarded); 494 562 if (*base == (uintptr_t) -1) { 495 563 mutex_unlock(&as->lock); … … 497 565 } 498 566 } 499 500 if (!check_area_conflicts(as, *base, pages, NULL)) { 567 568 if (overflows_into_positive(*base, size)) 569 return NULL; 570 571 if (!check_area_conflicts(as, *base, pages, guarded, NULL)) { 501 572 mutex_unlock(&as->lock); 502 573 return NULL; … … 776 847 /* 777 848 * Growing the area. 849 */ 850 851 if (overflows_into_positive(address, P2SZ(pages))) 852 return EINVAL; 853 854 /* 778 855 * Check for overlaps with other address space areas. 779 856 */ 780 if (!check_area_conflicts(as, address, pages, area)) { 857 bool const guarded = area->flags & AS_AREA_GUARD; 858 if (!check_area_conflicts(as, address, pages, guarded, area)) { 781 859 mutex_unlock(&area->lock); 782 860 mutex_unlock(&as->lock); -
kernel/generic/src/proc/task.c
rde73242 refdfebc 156 156 157 157 list_initialize(&task->threads); 158 list_initialize(&task->sync_boxes);159 158 160 159 ipc_answerbox_init(&task->answerbox, task); … … 162 161 size_t i; 163 162 for (i = 0; i < IPC_MAX_PHONES; i++) 164 ipc_phone_init(&task->phones[i]); 163 ipc_phone_init(&task->phones[i], task); 164 165 spinlock_initialize(&task->active_calls_lock, "active_calls_lock"); 166 list_initialize(&task->active_calls); 165 167 166 168 #ifdef CONFIG_UDEBUG … … 204 206 event_task_init(task); 205 207 208 task->answerbox.active = true; 209 206 210 #ifdef CONFIG_UDEBUG 207 211 /* Init debugging stuff */ … … 209 213 210 214 /* Init kbox stuff */ 215 task->kb.box.active = true; 211 216 task->kb.finished = false; 212 217 #endif … … 214 219 if ((ipc_phone_0) && 215 220 (container_check(ipc_phone_0->task->container, task->container))) 216 ipc_phone_connect(&task->phones[0], ipc_phone_0);221 (void) ipc_phone_connect(&task->phones[0], ipc_phone_0); 217 222 218 223 btree_create(&task->futexes); -
kernel/generic/src/syscall/syscall.c
rde73242 refdfebc 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.