Changes in kernel/generic/src/ipc/irq.c [8486c07:9d58539] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/ipc/irq.c
r8486c07 r9d58539 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 (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])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 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 for (size_t i = 0; i < rangecount; i++) { 89 size_t i; 90 91 for (i = 0; i < rangecount; i++) { 90 92 #ifdef IO_SPACE_BOUNDARY 91 93 if ((void *) ranges[i].base >= IO_SPACE_BOUNDARY) … … 98 100 irq_cmd_t *cmds, size_t cmdcount) 99 101 { 102 uintptr_t *pbase; 103 size_t i, j; 104 100 105 /* Copy the physical base addresses aside. */ 101 uintptr_t *pbase = malloc(rangecount * sizeof(uintptr_t), 0);102 for ( size_ti = 0; i < rangecount; i++)106 pbase = malloc(rangecount * sizeof(uintptr_t), 0); 107 for (i = 0; i < rangecount; i++) 103 108 pbase[i] = ranges[i].base; 104 109 105 110 /* Map the PIO ranges into the kernel virtual address space. */ 106 for ( size_ti = 0; i < rangecount; i++) {111 for (i = 0; i < rangecount; i++) { 107 112 #ifdef IO_SPACE_BOUNDARY 108 113 if ((void *) ranges[i].base < IO_SPACE_BOUNDARY) … … 117 122 } 118 123 } 119 124 120 125 /* Rewrite the pseudocode addresses from physical to kernel virtual. */ 121 for ( size_ti = 0; i < cmdcount; i++) {126 for (i = 0; i < cmdcount; i++) { 122 127 uintptr_t addr; 123 128 size_t size; 124 129 125 130 /* Process only commands that use an address. */ 126 131 switch (cmds[i].cmd) { 127 132 case CMD_PIO_READ_8: 128 129 133 case CMD_PIO_WRITE_8: 134 case CMD_PIO_WRITE_A_8: 130 135 size = 1; 131 136 break; 132 133 134 137 case CMD_PIO_READ_16: 138 case CMD_PIO_WRITE_16: 139 case CMD_PIO_WRITE_A_16: 135 140 size = 2; 136 141 break; 137 138 139 142 case CMD_PIO_READ_32: 143 case CMD_PIO_WRITE_32: 144 case CMD_PIO_WRITE_A_32: 140 145 size = 4; 141 146 break; … … 144 149 continue; 145 150 } 146 151 147 152 addr = (uintptr_t) cmds[i].addr; 148 153 149 size_t j;150 154 for (j = 0; j < rangecount; j++) { 155 151 156 /* Find the matching range. */ 152 157 if (!iswithin(pbase[j], ranges[j].size, addr, size)) 153 158 continue; 154 159 155 160 /* Switch the command to a kernel virtual address. */ 156 161 addr -= pbase[j]; 157 162 addr += ranges[j].base; 158 163 159 164 cmds[i].addr = (void *) addr; 160 165 break; 161 166 } 162 167 163 168 if (j == rangecount) { 164 169 /* … … 171 176 } 172 177 } 173 178 174 179 free(pbase); 175 return EOK;176 }177 178 /** Statically check the top-half pseudocode179 *180 * Check the top-half pseudocode for invalid or unsafe181 * 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 last204 * 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 215 180 return EOK; 216 181 } … … 242 207 irq_pio_range_t *ranges = NULL; 243 208 irq_cmd_t *cmds = NULL; 244 209 245 210 irq_code_t *code = malloc(sizeof(*code), 0); 246 211 int rc = copy_from_uspace(code, ucode, sizeof(*code)); … … 257 222 if (rc != EOK) 258 223 goto error; 259 224 260 225 cmds = malloc(sizeof(code->cmds[0]) * code->cmdcount, 0); 261 226 rc = copy_from_uspace(cmds, code->cmds, … … 263 228 if (rc != EOK) 264 229 goto error; 265 266 rc = code_check(cmds, code->cmdcount); 267 if (rc != EOK) 268 goto error; 269 230 270 231 rc = ranges_map_and_apply(ranges, code->rangecount, cmds, 271 232 code->cmdcount); 272 233 if (rc != EOK) 273 234 goto error; 274 235 275 236 code->ranges = ranges; 276 237 code->cmds = cmds; 277 238 278 239 return code; 279 240 280 241 error: 281 242 if (cmds) 282 243 free(cmds); 283 284 244 if (ranges) 285 245 free(ranges); 286 287 246 free(code); 288 247 return NULL; … … 291 250 /** Register an answerbox as a receiving end for IRQ notifications. 292 251 * 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. 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. 301 259 * 302 260 */ … … 308 266 (sysarg_t) devno 309 267 }; 310 268 311 269 if ((inr < 0) || (inr > last_inr)) 312 270 return ELIMIT; … … 371 329 /** Unregister task from IRQ notification. 372 330 * 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 * 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. 379 335 */ 380 336 int ipc_irq_unregister(answerbox_t *box, inr_t inr, devno_t devno) … … 384 340 (sysarg_t) devno 385 341 }; 386 342 387 343 if ((inr < 0) || (inr > last_inr)) 388 344 return ELIMIT; … … 480 436 /* Remove from the hash table. */ 481 437 hash_table_remove(&irq_uspace_hash_table, key, 2); 482 438 483 439 /* 484 440 * Release both locks so that we can free the pseudo code. … … 486 442 irq_spinlock_unlock(&box->irq_lock, false); 487 443 irq_spinlock_unlock(&irq_uspace_hash_table_lock, true); 488 444 489 445 code_free(irq->notif_cfg.code); 490 446 free(irq); … … 536 492 537 493 for (size_t i = 0; i < code->cmdcount; i++) { 494 uint32_t dstval; 495 538 496 uintptr_t srcarg = code->cmds[i].srcarg; 539 497 uintptr_t dstarg = code->cmds[i].dstarg; 540 498 499 if (srcarg >= IPC_CALL_LEN) 500 break; 501 502 if (dstarg >= IPC_CALL_LEN) 503 break; 504 541 505 switch (code->cmds[i].cmd) { 542 506 case CMD_PIO_READ_8: 543 scratch[dstarg] = 544 pio_read_8((ioport8_t *) code->cmds[i].addr); 507 dstval = pio_read_8((ioport8_t *) code->cmds[i].addr); 508 if (dstarg) 509 scratch[dstarg] = dstval; 545 510 break; 546 511 case CMD_PIO_READ_16: 547 scratch[dstarg] = 548 pio_read_16((ioport16_t *) code->cmds[i].addr); 512 dstval = pio_read_16((ioport16_t *) code->cmds[i].addr); 513 if (dstarg) 514 scratch[dstarg] = dstval; 549 515 break; 550 516 case CMD_PIO_READ_32: 551 scratch[dstarg] = 552 pio_read_32((ioport32_t *) code->cmds[i].addr); 517 dstval = pio_read_32((ioport32_t *) code->cmds[i].addr); 518 if (dstarg) 519 scratch[dstarg] = dstval; 553 520 break; 554 521 case CMD_PIO_WRITE_8: … … 565 532 break; 566 533 case CMD_PIO_WRITE_A_8: 567 pio_write_8((ioport8_t *) code->cmds[i].addr, 568 (uint8_t) scratch[srcarg]); 534 if (srcarg) { 535 pio_write_8((ioport8_t *) code->cmds[i].addr, 536 (uint8_t) scratch[srcarg]); 537 } 569 538 break; 570 539 case CMD_PIO_WRITE_A_16: 571 pio_write_16((ioport16_t *) code->cmds[i].addr, 572 (uint16_t) scratch[srcarg]); 540 if (srcarg) { 541 pio_write_16((ioport16_t *) code->cmds[i].addr, 542 (uint16_t) scratch[srcarg]); 543 } 573 544 break; 574 545 case CMD_PIO_WRITE_A_32: 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; 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 } 584 556 break; 585 557 case CMD_PREDICATE: 586 if ( scratch[srcarg] == 0)558 if ((srcarg) && (!scratch[srcarg])) { 587 559 i += code->cmds[i].value; 588 560 continue; 561 } 589 562 break; 590 563 case CMD_ACCEPT: … … 609 582 { 610 583 ASSERT(irq); 611 584 612 585 ASSERT(interrupts_disabled()); 613 586 ASSERT(irq_spinlock_locked(&irq->lock));
Note:
See TracChangeset
for help on using the changeset viewer.