Пример #1
0
void tlb_fill(pagetable_t *pagetable)
{
    if(pagetable == NULL)
	return;

    /* Check that the pagetable can fit into TLB. This is needed until
     we have proper VM system, because the whole pagetable must fit
     into TLB. */
    KERNEL_ASSERT(pagetable->valid_count <= (_tlb_get_maxindex()+1));

    _tlb_write(pagetable->entries, 0, pagetable->valid_count);

    /* Set ASID field in Co-Processor 0 to match thread ID so that
       only entries with the ASID of the current thread will match in
       the TLB hardware. */
    _tlb_set_asid(pagetable->ASID);
}
Пример #2
0
/** Handles an interrupt (exception code 0). All interrupt handlers
 * that are registered for any of the occured interrupts (hardware
 * 0-5, software 0-1) are called. The scheduler is called if a timer
 * interrupt (hardware 5) or a context switch request (software
 * interrupt 0) occured, or if the currently running thread for the
 * processor is the idle thread.
 *
 * @param cause The Cause register from CP0
 */
void interrupt_handle(virtaddr_t cause) {
    int this_cpu, i;

    if(cause & INTERRUPT_CAUSE_SOFTWARE_0) {
        _interrupt_clear_sw0();
    }

    this_cpu = _interrupt_getcpu();

    /* Exceptions should be handled elsewhere: */
    if((cause  & 0x0000007c) != 0) {
        kprintf("Caught exception, cause %.8x, CPU %i\n", cause, this_cpu);
        KERNEL_PANIC("Exception in interrupt_handle");
    }


    /* Call appropiate interrupt handlers.  Handlers cannot be
     * unregistered, so after the first empty * entry all others are
     * also empty.
     */
    for (i=0; i<CONFIG_MAX_DEVICES; i++) {
        if (interrupt_handlers[i].device == NULL)
            break;

        /* If this handler is registered for any of the interrupts
         * that occured, call it.
         */
        if ((cause & interrupt_handlers[i].irq) != 0)
            interrupt_handlers[i].handler(interrupt_handlers[i].device);
    }


    /* Timer interrupt (HW5) or requested context switch (SW0)
     * Also call scheduler if we're running the idle thread.
     */
    if((cause & (INTERRUPT_CAUSE_SOFTWARE_0 |
                 INTERRUPT_CAUSE_HARDWARE_5)) ||
            scheduler_current_thread[this_cpu] == IDLE_THREAD_TID) {
        scheduler_schedule();

        /* Until we have proper VM we must manually fill
           the TLB with pagetable entries before running code using
           given pagetable. Note that this method limits pagetable
           rows (possible mapping pairs) to 16 and can't be used
           with proper pagetables and VM.

           Note that if you remove this call (which you probably do when
           you implement proper VM), you must manually call _tlb_set_asid
           here. See the implementation of tlb_fill on details how to do that.
        */
        pagetable_t* pagetable = thread_get_current_thread_entry()->pagetable;

        if(pagetable == NULL)
            return;

        /* Check that the pagetable can fit into TLB. This is needed until
           we have proper VM system, because the whole pagetable must fit
           into TLB. */
        KERNEL_ASSERT(pagetable->valid_count <= (_tlb_get_maxindex()+1));

        _tlb_write(pagetable->entries, 0, pagetable->valid_count);

        /* Set ASID field in Co-Processor 0 to match thread ID so that
           only entries with the ASID of the current thread will match in
           the TLB hardware. */
        _tlb_set_asid(pagetable->ASID);
    }
}