Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 14 Dec 1996 14:51:50 -0700
From:      Steve Passe <smp@csn.net>
To:        Steve Passe <smp@csn.net>
Cc:        haertel@ichips.intel.com, peter@spinner.dialix.com, dg@root.com, smp@freebsd.org, toor@dyson.iquest.net
Subject:   Re: some questions concerning TLB shootdowns in FreeBSD 
Message-ID:  <199612142151.OAA17577@clem.systemsix.com>
In-Reply-To: Your message of "Sat, 14 Dec 1996 11:55:18 MST." <199612141855.LAA16724@clem.systemsix.com> 

next in thread | previous in thread | raw e-mail | index | archive | help
Hi,

so here is a suggested set of code for the TLB sync problem.  There is one
problem with it (that I currently see, surely others also!) in that the
target CPUs can't service their IPI as the invoking CPU holds the mp_lock.
So for now lets pretend that we have a separate lock for IPIs called
ipi_lock, which is manipulated via get_ipilock()/rel_ipilock().

---
usage by the invoking CPU:

	startRendezvous();		/* setup a rendezvous */

	/* 
	 * at this point the other CPUs are all spinning on the end lock
	 * so the code can safely muck with PTD/PTE entries...
	 */

	invltlb();			/* CPU flushes local TLB */

	endRendezvous();		/* end the rendezvous */

---
usage by the invoked CPUs, ie the routine invoked by the IPI:

ipi_invltlb(void)
{
    u_long	temp;

    doRendezvous();			/* declare our arrival and wait */

    __asm __volatile("movl %%cr3, %0; movl %0, %%cr3" : "=r" (temp)
			 : : "memory");
}

----------------------------------- cut -------------------------------------
/* rendezvous.s */

	.text
	.align	4

#define SMP_INVLTLB_IPI		(ICU_OFFSET+27)

/*
 * invoking CPU sets up rendezvous
 */
ENTRY(startRendezvous)
	call	_get_ipilock			/* only one CPU at a time */

	movl	_mp_ncpus, %eax			/* # of CPUs to sync */
	decl	%eax				/* count ourself */
	movl	%eax, _rendezvousCount		/* init the downcounter */
	movl	%eax, _rendezvousEnd		/* init the release lock */

	pushl	SMP_INVLTLB_IPI
	call	_allButSelfIPI
	addl	$4, %esp

	call	_rel_ipilock			/* now safe for other CPUs */

1:	cmpl	$0, _rendezvousCount		/* check current value */
	jnz	1b				/* somebody not here yet */

	call	_get_ipilock			/* is this necessary??? */
	ret

/*
 * invoking CPU releases all other CPUs
 */
ENTRY(endRendezvous)
	movl	$0, _rendezvousEnd
	call	_rel_ipilock			/* is this necessary??? */
	ret

/*
 * invoked CPUs enter and wait for end
 */
ENTRY(doRendezvous)
	call	_rel_ipilock			/* allow other CPUs to IPI */

	lock					/* ensure atomic operation */
	decl	_rendezvousCount		/* declare our arrival */

1:	cmpl	$0, _rendezvousEnd		/* test for end */
	jnz	1b				/* not yet, spin */

	call	_get_ipilock			/* safe exit from IPI */
	ret

	.data
	ALIGN_DATA

	.globl _rendezvousCount
_rendezvousCount:
	.long 0

	.globl _rendezvousEnd
_rendezvousEnd:
	.long 0

----------------------------------- cut -------------------------------------

--
Steve Passe	| powered by
smp@csn.net	|            FreeBSD




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199612142151.OAA17577>