Esempio n. 1
0
void
M68KVMTranslationMap::Flush()
{
	if (fInvalidPagesCount <= 0)
		return;

	Thread* thread = thread_get_current_thread();
	thread_pin_to_current_cpu(thread);

	if (fInvalidPagesCount > PAGE_INVALIDATE_CACHE_SIZE) {
		// invalidate all pages
		TRACE("flush_tmap: %d pages to invalidate, invalidate all\n",
			fInvalidPagesCount);

		if (fIsKernelMap) {
			arch_cpu_global_TLB_invalidate();
			smp_send_broadcast_ici(SMP_MSG_GLOBAL_INVALIDATE_PAGES, 0, 0, 0,
				NULL, SMP_MSG_FLAG_SYNC);
		} else {
			cpu_status state = disable_interrupts();
			arch_cpu_user_TLB_invalidate();
			restore_interrupts(state);

			int cpu = smp_get_current_cpu();
			CPUSet cpuMask = PagingStructures()->active_on_cpus;
			cpuMask.ClearBit(cpu);

			if (!cpuMask.IsEmpty()) {
				smp_send_multicast_ici(cpuMask, SMP_MSG_USER_INVALIDATE_PAGES,
					0, 0, 0, NULL, SMP_MSG_FLAG_SYNC);
			}
		}
	} else {
		TRACE("flush_tmap: %d pages to invalidate, invalidate list\n",
			fInvalidPagesCount);

		arch_cpu_invalidate_TLB_list(fInvalidPages, fInvalidPagesCount);

		if (fIsKernelMap) {
			smp_send_broadcast_ici(SMP_MSG_INVALIDATE_PAGE_LIST,
				(addr_t)fInvalidPages, fInvalidPagesCount, 0, NULL,
				SMP_MSG_FLAG_SYNC);
		} else {
			int cpu = smp_get_current_cpu();
			CPUSet cpuMask = PagingStructures()->active_on_cpus;
			cpuMask.ClearBit(cpu);

			if (!cpuMask.IsEmpty()) {
				smp_send_multicast_ici(cpuMask, SMP_MSG_INVALIDATE_PAGE_LIST,
					(addr_t)fInvalidPages, fInvalidPagesCount, 0, NULL,
					SMP_MSG_FLAG_SYNC);
			}
		}
	}
	fInvalidPagesCount = 0;

	thread_unpin_from_current_cpu(thread);
}
Esempio n. 2
0
static int smp_process_pending_ici(int curr_cpu)
{
    struct smp_msg *msg;
    bool do_halt = false;
    int source_mailbox = 0;
    int retval = INT_NO_RESCHEDULE;

    msg = smp_check_for_message(curr_cpu, &source_mailbox);
    if(msg == 0)
        return retval;

    //	dprintf("  message = %d\n", msg->message);
    switch(msg->message) {
    case SMP_MSG_INVL_PAGE_RANGE:
        arch_cpu_invalidate_TLB_range((addr_t)msg->data, (addr_t)msg->data2);
        break;
    case SMP_MSG_INVL_PAGE_LIST:
        arch_cpu_invalidate_TLB_list((addr_t *)msg->data, (int)msg->data2);
        break;
    case SMP_MSG_GLOBAL_INVL_PAGE:
        //arch_cpu_global_TLB_invalidate();
        invltlb();
        break;
    case SMP_MSG_RESCHEDULE:
        retval = INT_RESCHEDULE;
        break;
    case SMP_MSG_CPU_HALT:
        do_halt = true;
        SHOW_INFO( 0, "cpu %d halted!", curr_cpu);
        break;
    case SMP_MSG_1:
    default:
        SHOW_ERROR( 0, "smp_intercpu_int_handler: got unknown message %d", msg->message);
    }

    // finish dealing with this message, possibly removing it from the list
    smp_finish_message_processing(curr_cpu, msg, source_mailbox);

    // special case for the halt message
    // we otherwise wouldn't have gotten the opportunity to clean up
    if(do_halt) {
        //int_disable_interrupts();
        hal_cli();
        halt();
        for(;;);
    }

    return retval;
}
Esempio n. 3
0
static status_t
process_pending_ici(int32 currentCPU)
{
	mailbox_source sourceMailbox;
	struct smp_msg* msg = check_for_message(currentCPU, sourceMailbox);
	if (msg == NULL)
		return B_ENTRY_NOT_FOUND;

	TRACE(("  cpu %ld message = %ld\n", currentCPU, msg->message));

	bool haltCPU = false;

	switch (msg->message) {
		case SMP_MSG_INVALIDATE_PAGE_RANGE:
			arch_cpu_invalidate_TLB_range(msg->data, msg->data2);
			break;
		case SMP_MSG_INVALIDATE_PAGE_LIST:
			arch_cpu_invalidate_TLB_list((addr_t*)msg->data, (int)msg->data2);
			break;
		case SMP_MSG_USER_INVALIDATE_PAGES:
			arch_cpu_user_TLB_invalidate();
			break;
		case SMP_MSG_GLOBAL_INVALIDATE_PAGES:
			arch_cpu_global_TLB_invalidate();
			break;
		case SMP_MSG_CPU_HALT:
			haltCPU = true;
			break;
		case SMP_MSG_CALL_FUNCTION:
		{
			smp_call_func func = (smp_call_func)msg->data_ptr;
			func(msg->data, currentCPU, msg->data2, msg->data3);
			break;
		}
		case SMP_MSG_RESCHEDULE:
		{
			cpu_ent* cpu = thread_get_current_thread()->cpu;
			cpu->invoke_scheduler = true;
			cpu->invoke_scheduler_if_idle = false;
			break;
		}
		case SMP_MSG_RESCHEDULE_IF_IDLE:
		{
			cpu_ent* cpu = thread_get_current_thread()->cpu;
			if (!cpu->invoke_scheduler) {
				cpu->invoke_scheduler = true;
				cpu->invoke_scheduler_if_idle = true;
			}
			break;
		}

		default:
			dprintf("smp_intercpu_int_handler: got unknown message %" B_PRId32 "\n",
				msg->message);
			break;
	}

	// finish dealing with this message, possibly removing it from the list
	finish_message_processing(currentCPU, msg, sourceMailbox);

	// special case for the halt message
	if (haltCPU)
		debug_trap_cpu_in_kdl(currentCPU, false);

	return B_OK;
}