Ejemplo n.º 1
0
Archivo: apic.c Proyecto: ksandstr/mung
/* EOI is actually sent to the local APIC, not the I/O APIC as the function's
 * name would indicate.
 */
static void ioapic_send_eoi(int irq)
{
	assert(!x86_irq_is_enabled());
	struct lapic_info *apic = &cpu_apics[0];
	/* the specs say that 0 is the right thing to write here. */
	mm_outl(apic->base_addr + APIC_EOI, 0);
}
Ejemplo n.º 2
0
Archivo: apic.c Proyecto: ksandstr/mung
/* there are at most 256 32-bit registers in a pre-2013 IOAPIC. */
static inline void ioapic_write(
	struct ioapic_info *ioa,
	uint8_t address,
	uint32_t value)
{
	assert(!x86_irq_is_enabled());
	mm_outb(ioa->base_addr + 0, address);	/* IOREGSEL */
	mm_outl(ioa->base_addr + 0x10, value);	/* IOWIN */
}
Ejemplo n.º 3
0
static irq_handler_fn choose_handler(int vecn)
{
	assert(!x86_irq_is_enabled());
	irq_handler_fn handler = NULL;
	if(vecn == 0x20) handler = &on_preempt;
	else if(vecn <= max_irq_handler) handler = irq_handlers[vecn];
	if(handler == NULL) handler = &int_trigger;
	return handler;
}
Ejemplo n.º 4
0
Archivo: apic.c Proyecto: ksandstr/mung
static void ioapic_mask_irq(int irq)
{
	assert(!x86_irq_is_enabled());
	struct ioapic_info *ioa = &global_ioapics[irq / 24];
	int vec = irq % 24;

	uint32_t ctl = ioapic_read(ioa, IOREDTBL(vec) + 0);
	ctl |= 1 << 16;
	ioapic_write(ioa, IOREDTBL(vec) + 0, ctl);
}
Ejemplo n.º 5
0
void isr_irq_bottom(struct x86_exregs *regs)
{
	assert(!x86_irq_is_enabled());

	int vecn = regs->reason;
	(*global_pic.send_eoi)(vecn - 0x20);

	irq_handler_fn handler = choose_handler(vecn);
	if(handler == &int_trigger) {
		(*global_pic.mask_irq)(vecn - 0x20);
		vecn = -vecn;
	}

	if(irq_in_kernel(regs) && !kernel_irq_ok) {
		/* kernel code was interrupted. mark and proceed. */
		irq_defer(vecn);
	} else if(irq_in_kernel(regs)) {
		/* the idling kernel was interrupted. */
		assert(kernel_irq_ok);
		kernel_irq_ok = false;
		x86_irq_enable();
		struct thread *next = (*handler)(vecn);
		x86_irq_disable();
		if(irq_defer_active) save_user_ex(regs);
		return_from_irq(next);
		/* going back to schedule(). */
		kernel_irq_ok = true;
	} else {
		/* userspace was interrupted. */
		assert(!kernel_irq_ok);
		assert(vecn > max_irq_handler
			|| deferred_vecs[vecn] == 0);
		x86_irq_enable();
		struct thread *next = (*handler)(vecn);
		x86_irq_disable();
		if(irq_defer_active) save_user_ex(regs);
		return_from_irq(next);
		/* if return_from_irq() returned, current thread wasn't preempted. */
	}
}
Ejemplo n.º 6
0
/* call latent interrupt handlers, resolve preemptions, return the winner.
 * caller must check for retval == current && I ∈ current.PreemptFlags, and
 * engage max_delay as appropriate.
 */
struct thread *irq_call_deferred(struct thread *next)
{
	assert(!x86_irq_is_enabled());
	assert(!kernel_irq_ok);

	/* initialize resolution state, feed it a primary event. */
	struct thread *current = get_current_thread();
	void *cur_utcb = current != NULL ? thread_get_utcb(current) : NULL;
	next = sched_resolve_next(current, cur_utcb, current, next);

	int n_defer_masks = (max_irq_handler + WORD_BITS) / WORD_BITS, n_done;
	do {
		if(!irq_defer_active) break;
		n_done = 0;
		for(int i=0; i < n_defer_masks; i++) {
			L4_Word_t m = defer_set_masks[i];
			while(m != 0) {
				int b = ffsl(m) - 1;
				assert(b >= 0);
				m &= ~(1ul << b);
				int vecn = i * WORD_BITS + b;
				int n_defers = deferred_vecs[vecn];
				assert(n_defers > 0);
				irq_handler_fn handler = choose_handler(vecn);
				deferred_vecs[vecn] = 0;
				defer_set_masks[i] &= ~(1ul << b);

				x86_irq_enable();
				next = sched_resolve_next(current, cur_utcb, next,
					(*handler)(n_defers > 1 ? -vecn : vecn));
				x86_irq_disable();
				n_done++;
			}
		}
	} while(n_done > 0);
	irq_defer_active = false;

	return next;
}
Ejemplo n.º 7
0
static void irq_defer(int vec_num)
{
	assert(!x86_irq_is_enabled());
	assert(abs(vec_num) <= max_irq_handler);	/* to solve, fix PIC init */

	vec_num = abs(vec_num);
	irq_defer_active = true;
	defer_set_masks[vec_num / WORD_BITS] |= 1ul << (vec_num % WORD_BITS);

	/* handle unsigned wraparound. */
	if(unlikely(deferred_vecs[vec_num] == 0xff)) {
		deferred_vecs[vec_num] = 1;
	}

	if(++deferred_vecs[vec_num] > 1) {
		/* TODO: translate bare vector numbers to IRQ, or redefine mask_irq to
		 * map vector numbers.
		 */
		if(vec_num >= 0x20 && vec_num <= 0x2f) {
			(*global_pic.mask_irq)(vec_num - 0x20);
		}
	}
}
Ejemplo n.º 8
0
Archivo: apic.c Proyecto: ksandstr/mung
static inline uint32_t ioapic_read(struct ioapic_info *ioa, uint8_t address)
{
	assert(!x86_irq_is_enabled());
	mm_outb(ioa->base_addr + 0, address);
	return mm_inl(ioa->base_addr + 0x10);
}