Beispiel #1
0
static void
dmar_qi_emit_wait_seq(struct dmar_unit *unit, struct dmar_qi_genseq *pseq,
    bool emit_wait)
{
	struct dmar_qi_genseq gsec;
	uint32_t seq;

	KASSERT(pseq != NULL, ("wait descriptor with no place for seq"));
	DMAR_ASSERT_LOCKED(unit);
	if (unit->inv_waitd_seq == 0xffffffff) {
		gsec.gen = unit->inv_waitd_gen;
		gsec.seq = unit->inv_waitd_seq;
		dmar_qi_ensure(unit, 1);
		dmar_qi_emit_wait_descr(unit, gsec.seq, false, true, false);
		dmar_qi_advance_tail(unit);
		while (!dmar_qi_seq_processed(unit, &gsec))
			cpu_spinwait();
		unit->inv_waitd_gen++;
		unit->inv_waitd_seq = 1;
	}
	seq = unit->inv_waitd_seq++;
	pseq->gen = unit->inv_waitd_gen;
	pseq->seq = seq;
	if (emit_wait) {
		dmar_qi_ensure(unit, 1);
		dmar_qi_emit_wait_descr(unit, seq, true, true, false);
	}
}
Beispiel #2
0
static void
dmar_qi_task(void *arg, int pending __unused)
{
	struct dmar_unit *unit;
	struct dmar_map_entry *entry;
	uint32_t ics;

	unit = arg;

	DMAR_LOCK(unit);
	for (;;) {
		entry = TAILQ_FIRST(&unit->tlb_flush_entries);
		if (entry == NULL)
			break;
		if (!dmar_qi_seq_processed(unit, &entry->gseq))
			break;
		TAILQ_REMOVE(&unit->tlb_flush_entries, entry, dmamap_link);
		DMAR_UNLOCK(unit);
		dmar_domain_free_entry(entry, (entry->flags &
		    DMAR_MAP_ENTRY_QI_NF) == 0);
		DMAR_LOCK(unit);
	}
	ics = dmar_read4(unit, DMAR_ICS_REG);
	if ((ics & DMAR_ICS_IWC) != 0) {
		ics = DMAR_ICS_IWC;
		dmar_write4(unit, DMAR_ICS_REG, ics);
	}
	if (unit->inv_seq_waiters > 0)
		wakeup(&unit->inv_seq_waiters);
	DMAR_UNLOCK(unit);
}
Beispiel #3
0
static void
dmar_qi_wait_for_seq(struct dmar_unit *unit, const struct dmar_qi_genseq *gseq)
{

	DMAR_ASSERT_LOCKED(unit);
	unit->inv_seq_waiters++;
	while (!dmar_qi_seq_processed(unit, gseq)) {
		if (cold) {
			cpu_spinwait();
		} else {
			msleep(&unit->inv_seq_waiters, &unit->lock, 0,
			    "dmarse", hz);
		}
	}
	unit->inv_seq_waiters--;
}