Module Name:    src
Committed By:   rmind
Date:           Thu Mar 17 04:46:29 UTC 2011

Modified Files:
        src/sys/arch/amd64/amd64 [rmind-uvmplock]: cpufunc.S genassym.cf
            vector.S
        src/sys/arch/i386/i386 [rmind-uvmplock]: genassym.cf i386func.S
            vector.S
        src/sys/arch/x86/include [rmind-uvmplock]: pmap.h
        src/sys/arch/x86/x86 [rmind-uvmplock]: cpu.c pmap.c pmap_tlb.c

Log Message:
- Fix tlbflushg() to behave like tlbflush(), if page global extension (PGE)
  is not (yet) enabled.  This fixes the issue of stale TLB entry, experienced
  early on boot, when PGE is not yet set on primary CPU.
- Rewrite i386/amd64 TLB interrupt handlers in C (only stubs are in assembly),
  which simplifies and unifies (under x86) code, plus fixes few bugs.
- cpu_attach: remove assignment to cpus_running, as primary CPU might not be
  attached first, which causes reset (and thus missed secondary CPUs).


To generate a diff of this commit:
cvs rdiff -u -r1.16.4.1 -r1.16.4.2 src/sys/arch/amd64/amd64/cpufunc.S
cvs rdiff -u -r1.43.4.3 -r1.43.4.4 src/sys/arch/amd64/amd64/genassym.cf
cvs rdiff -u -r1.33.2.3 -r1.33.2.4 src/sys/arch/amd64/amd64/vector.S
cvs rdiff -u -r1.85.2.3 -r1.85.2.4 src/sys/arch/i386/i386/genassym.cf
cvs rdiff -u -r1.15 -r1.15.20.1 src/sys/arch/i386/i386/i386func.S
cvs rdiff -u -r1.53.2.3 -r1.53.2.4 src/sys/arch/i386/i386/vector.S
cvs rdiff -u -r1.29.2.8 -r1.29.2.9 src/sys/arch/x86/include/pmap.h
cvs rdiff -u -r1.69.2.3 -r1.69.2.4 src/sys/arch/x86/x86/cpu.c
cvs rdiff -u -r1.105.2.12 -r1.105.2.13 src/sys/arch/x86/x86/pmap.c
cvs rdiff -u -r1.1.2.4 -r1.1.2.5 src/sys/arch/x86/x86/pmap_tlb.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/amd64/amd64/cpufunc.S
diff -u src/sys/arch/amd64/amd64/cpufunc.S:1.16.4.1 src/sys/arch/amd64/amd64/cpufunc.S:1.16.4.2
--- src/sys/arch/amd64/amd64/cpufunc.S:1.16.4.1	Sat Mar  5 20:49:14 2011
+++ src/sys/arch/amd64/amd64/cpufunc.S	Thu Mar 17 04:46:29 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpufunc.S,v 1.16.4.1 2011/03/05 20:49:14 rmind Exp $	*/
+/*	$NetBSD: cpufunc.S,v 1.16.4.2 2011/03/17 04:46:29 rmind Exp $	*/
 
 /*-
  * Copyright (c) 1998, 2007, 2008 The NetBSD Foundation, Inc.
@@ -136,10 +136,14 @@
  * modify the PSE, PGE, or PAE flag."
  *
  * (the alternatives not quoted above are not an option here.)
+ *
+ * If PGE is not in use, we reload CR3.
  */
 #ifndef XEN
 ENTRY(tlbflushg)
 	movq	%cr4, %rax
+	testq	$CR4_PGE, %rax
+	jz	1f
 	movq	%rax, %rdx
 	andq	$~CR4_PGE, %rdx
 	movq	%rdx, %cr4
@@ -147,6 +151,7 @@
 	ret
 
 ENTRY(tlbflush)
+1:
 	movq	%cr3, %rax
 	movq	%rax, %cr3
 	ret

Index: src/sys/arch/amd64/amd64/genassym.cf
diff -u src/sys/arch/amd64/amd64/genassym.cf:1.43.4.3 src/sys/arch/amd64/amd64/genassym.cf:1.43.4.4
--- src/sys/arch/amd64/amd64/genassym.cf:1.43.4.3	Sat Mar  5 20:49:15 2011
+++ src/sys/arch/amd64/amd64/genassym.cf	Thu Mar 17 04:46:29 2011
@@ -1,4 +1,4 @@
-#	$NetBSD: genassym.cf,v 1.43.4.3 2011/03/05 20:49:15 rmind Exp $
+#	$NetBSD: genassym.cf,v 1.43.4.4 2011/03/17 04:46:29 rmind Exp $
 
 #
 # Copyright (c) 1998, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -136,8 +136,6 @@
 define	KERNTEXTOFF_LO		KERNTEXTOFF_LO
 define	KERNTEXTOFF		KERNTEXTOFF
 
-define	PG_G			PG_G
-
 define	NBPG			NBPG
 
 define	L4_SLOT_KERNBASE	L4_SLOT_KERNBASE
@@ -230,8 +228,6 @@
 define	CPU_INFO_WANT_PMAPLOAD	offsetof(struct cpu_info, ci_want_pmapload)
 define	CPU_INFO_TLBSTATE	offsetof(struct cpu_info, ci_tlbstate)
 define	TLBSTATE_VALID		TLBSTATE_VALID
-define	TLBSTATE_LAZY		TLBSTATE_LAZY
-define	TLBSTATE_STALE		TLBSTATE_STALE
 define	CPU_INFO_TLB_EVCNT	offsetof(struct cpu_info, ci_tlb_evcnt)
 define	CPU_INFO_CURLWP		offsetof(struct cpu_info, ci_curlwp)
 define	CPU_INFO_CURLDT		offsetof(struct cpu_info, ci_curldt)
@@ -352,14 +348,6 @@
 define	RW_READER		RW_READER
 define	RW_WRITER		RW_WRITER
 
-define	TM_PENDING		offsetof(struct pmap_tlb_mailbox, tm_pending)
-define	TP_COUNT		offsetof(struct pmap_tlb_packet, tp_count)
-define	TP_VA			offsetof(struct pmap_tlb_packet, tp_va)
-define	TP_USERMASK		offsetof(struct pmap_tlb_packet, tp_usermask)
-define	TP_PTE			offsetof(struct pmap_tlb_packet, tp_pte)
-
-define	PM_CPUS			offsetof(struct pmap, pm_cpus)
-
 define	EV_COUNT		offsetof(struct evcnt, ev_count)
 
 define	OPTERON_MSR_PASSCODE	OPTERON_MSR_PASSCODE

Index: src/sys/arch/amd64/amd64/vector.S
diff -u src/sys/arch/amd64/amd64/vector.S:1.33.2.3 src/sys/arch/amd64/amd64/vector.S:1.33.2.4
--- src/sys/arch/amd64/amd64/vector.S:1.33.2.3	Sat Mar  5 20:49:15 2011
+++ src/sys/arch/amd64/amd64/vector.S	Thu Mar 17 04:46:29 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: vector.S,v 1.33.2.3 2011/03/05 20:49:15 rmind Exp $	*/
+/*	$NetBSD: vector.S,v 1.33.2.4 2011/03/17 04:46:29 rmind Exp $	*/
 
 /*-
  * Copyright (c) 1998, 2007, 2008 The NetBSD Foundation, Inc.
@@ -479,97 +479,12 @@
  * TLB shootdown handler.
  */
 IDTVEC(intr_lapic_tlb)
-	/* Save state and ack the interrupt. */
-	testq	$SEL_UPL,8(%rsp)
-	jz	0f
-	swapgs
-0:
-	pushq	%rax
-	pushq	%rbx
-	pushq	%rdi
-	pushq	%rsi
-	pushq	%rdx
-	pushq	%rcx
-	pushq	%r8
-	pushq	%r9
+	pushq	$0
+	pushq	$T_ASTFLT
+	INTRENTRY
 	movl	$0, _C_LABEL(local_apic)+LAPIC_EOI
-
-	/* Find out what we need to invalidate. */
-	leaq	_C_LABEL(pmap_tlb_packet)(%rip), %rbx
-	movswq	TP_COUNT(%rbx), %rcx
-	cmpq	$-1, %rcx
-	je	5f
-	leaq	TP_VA(%rbx), %rdx
-1:
-	/* Invalidate a single page or a range of pages. */
-	movq	(%rdx), %rax
-	invlpg	(%rax)
-	addq	$8, %rdx
-	decq	%rcx
-	jg	1b
-2:
-	/*
-	 * Check the current TLB state.  If we do not want further
-	 * invalidations for this pmap, then take the CPU out of
-	 * the pmap's bitmask.
-	 */
-	movl	CPUVAR(CPUMASK), %eax
-	cmpl	$TLBSTATE_LAZY, CPUVAR(TLBSTATE)
-	jne	3f
-	testl	%eax, TP_USERMASK(%rbx)
-	jz	3f
-	movl	CPUVAR(PMAP), %edx
-	movl	%eax, %ecx
-	notl	%ecx
-	lock
-	andl	%ecx, PM_CPUS(%edx)
-	movl	$TLBSTATE_STALE, CPUVAR(TLBSTATE)
-3:
-	/* Ack the request, restore state & return. */
-	lock
-	xorl	%eax, _C_LABEL(pmap_tlb_mailbox)+TM_PENDING
-	popq	%r9
-	popq	%r8
-	popq	%rcx
-	popq	%rdx
-	popq	%rsi
-	popq	%rdi
-	popq	%rbx
-	popq	%rax
-	testq	$SEL_UPL, 8(%rsp)
-	jz	4f
-	swapgs
-4:
-	iretq
-5:
-	/*
-	 * Note that caller-save registers might be modified (all saved in the
-	 * beginning).  Only %rbx value must be preserved for the 2f context.
-	 */
-
-	/* Get the emap generation number. */
-	callq	_C_LABEL(uvm_emap_gen_return)
-	movq	%rax, %rdi
-
-	/* Which entries we are invalidating? */
-	testw	$PG_G, TP_PTE(%rbx)
-	jnz	6f
-
-	/* a) Invalidating user TLB entries only. */
-	movq	%cr3, %rax
-	movq	%rax, %cr3
-	jmp	7f
-6:
-	/* b) Invalidating user and kernel TLB entries. */
-	movq	%cr4, %rax
-	movq	%rax, %rdx
-	andq	$~CR4_PGE, %rdx
-	movq	%rdx, %cr4
-	movq	%rax, %cr4
-7:
-	/* Perform emap update, pass the generation number. */
-	callq	_C_LABEL(uvm_emap_update)
-	jmp	2b
+	callq	_C_LABEL(pmap_tlb_intr)
+	INTRFASTEXIT
 
 #endif /* !XEN */
 

Index: src/sys/arch/i386/i386/genassym.cf
diff -u src/sys/arch/i386/i386/genassym.cf:1.85.2.3 src/sys/arch/i386/i386/genassym.cf:1.85.2.4
--- src/sys/arch/i386/i386/genassym.cf:1.85.2.3	Sat Mar  5 20:50:39 2011
+++ src/sys/arch/i386/i386/genassym.cf	Thu Mar 17 04:46:29 2011
@@ -1,4 +1,4 @@
-#	$NetBSD: genassym.cf,v 1.85.2.3 2011/03/05 20:50:39 rmind Exp $
+#	$NetBSD: genassym.cf,v 1.85.2.4 2011/03/17 04:46:29 rmind Exp $
 
 #
 # Copyright (c) 1998, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -160,7 +160,6 @@
 define	PG_V			PG_V
 define	PG_KW			PG_KW
 define	PG_KR			PG_KR
-define	PG_G			PG_G
 define	PGEX_U			PGEX_U
 
 define	L2_SLOT_KERNBASE	pl2_pi(KERNBASE)
@@ -288,8 +287,6 @@
 define	CPU_INFO_WANT_PMAPLOAD	offsetof(struct cpu_info, ci_want_pmapload)
 define	CPU_INFO_TLBSTATE	offsetof(struct cpu_info, ci_tlbstate)
 define	TLBSTATE_VALID		TLBSTATE_VALID
-define	TLBSTATE_LAZY		TLBSTATE_LAZY
-define	TLBSTATE_STALE		TLBSTATE_STALE
 define	CPU_INFO_TLB_EVCNT	offsetof(struct cpu_info, ci_tlb_evcnt)
 define	CPU_INFO_CURLWP		offsetof(struct cpu_info, ci_curlwp)
 define	CPU_INFO_FPCURLWP	offsetof(struct cpu_info, ci_fpcurlwp)
@@ -424,14 +421,6 @@
 define	RW_READER		RW_READER
 define	RW_WRITER		RW_WRITER
 
-define	TM_PENDING		offsetof(struct pmap_tlb_mailbox, tm_pending)
-define	TP_COUNT		offsetof(struct pmap_tlb_packet, tp_count)
-define	TP_VA			offsetof(struct pmap_tlb_packet, tp_va)
-define	TP_USERMASK		offsetof(struct pmap_tlb_packet, tp_usermask)
-define	TP_PTE			offsetof(struct pmap_tlb_packet, tp_pte)
-
-define	PM_CPUS			offsetof(struct pmap, pm_cpus)
-
 define	EV_COUNT		offsetof(struct evcnt, ev_count)
 
 define	OPTERON_MSR_PASSCODE	OPTERON_MSR_PASSCODE

Index: src/sys/arch/i386/i386/i386func.S
diff -u src/sys/arch/i386/i386/i386func.S:1.15 src/sys/arch/i386/i386/i386func.S:1.15.20.1
--- src/sys/arch/i386/i386/i386func.S:1.15	Sun May 25 15:56:12 2008
+++ src/sys/arch/i386/i386/i386func.S	Thu Mar 17 04:46:29 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: i386func.S,v 1.15 2008/05/25 15:56:12 chs Exp $	*/
+/*	$NetBSD: i386func.S,v 1.15.20.1 2011/03/17 04:46:29 rmind Exp $	*/
 
 /*-
  * Copyright (c) 1998, 2007, 2008 The NetBSD Foundation, Inc.
@@ -36,7 +36,7 @@
  */
 
 #include <machine/asm.h>
-__KERNEL_RCSID(0, "$NetBSD: i386func.S,v 1.15 2008/05/25 15:56:12 chs Exp $");
+__KERNEL_RCSID(0, "$NetBSD: i386func.S,v 1.15.20.1 2011/03/17 04:46:29 rmind Exp $");
 
 #include <machine/specialreg.h>
 #include <machine/segments.h>
@@ -99,13 +99,12 @@
  *
  * (the alternatives not quoted above are not an option here.)
  *
- * If PGE is not in use, we reload CR3 for the benefit of
- * pre-P6-family processors.
+ * If PGE is not in use, we reload CR3.
  */
 ENTRY(tlbflushg)
-	testl	$CPUID_PGE, _C_LABEL(cpu_feature)
-	jz	1f
 	movl	%cr4, %eax
+	testl	$CR4_PGE, %eax
+	jz	1f
 	movl	%eax, %edx
 	andl	$~CR4_PGE, %edx
 	movl	%edx, %cr4

Index: src/sys/arch/i386/i386/vector.S
diff -u src/sys/arch/i386/i386/vector.S:1.53.2.3 src/sys/arch/i386/i386/vector.S:1.53.2.4
--- src/sys/arch/i386/i386/vector.S:1.53.2.3	Sat Mar  5 20:50:41 2011
+++ src/sys/arch/i386/i386/vector.S	Thu Mar 17 04:46:29 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: vector.S,v 1.53.2.3 2011/03/05 20:50:41 rmind Exp $	*/
+/*	$NetBSD: vector.S,v 1.53.2.4 2011/03/17 04:46:29 rmind Exp $	*/
 
 /*
  * Copyright 2002 (c) Wasabi Systems, Inc.
@@ -65,7 +65,7 @@
  */
 
 #include <machine/asm.h>
-__KERNEL_RCSID(0, "$NetBSD: vector.S,v 1.53.2.3 2011/03/05 20:50:41 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vector.S,v 1.53.2.4 2011/03/17 04:46:29 rmind Exp $");
 
 #include "opt_ddb.h"
 #include "opt_multiprocessor.h"
@@ -187,91 +187,12 @@
  * TLB shootdown handler.
  */
 IDTVEC(intr_lapic_tlb)
-	/* Save state and ack the interrupt. */
-	pushl	%eax
-	pushl	%ebx
-	pushl	%ecx
-	pushl	%edx
-	pushl	%ds
-	pushl	%fs
-	movl	$GSEL(GDATA_SEL, SEL_KPL), %eax
-	movl	$GSEL(GCPU_SEL, SEL_KPL), %edx
-	mov	%ax, %ds
-	mov	%dx, %fs
+	pushl	$0
+	pushl	$T_ASTFLT
+	INTRENTRY
 	movl	$0, _C_LABEL(local_apic)+LAPIC_EOI
-
-	/* Find out what we need to invalidate. */
-	leal	_C_LABEL(pmap_tlb_packet), %ebx
-	movswl	TP_COUNT(%ebx), %ecx
-	cmpl	$-1, %ecx
-	je	4f
-	leal	TP_VA(%ebx), %edx
-1:
-	/* Invalidate a single page or a range of pages. */
-	movl	(%edx), %eax
-	invlpg	(%eax)
-	addl	$4, %edx
-	decl	%ecx
-	jg	1b
-2:
-	/*
-	 * Check the current TLB state.  If we do not want further
-	 * invalidations for this pmap, then take the CPU out of
-	 * the pmap's bitmask.
-	 */
-	movl	CPUVAR(CPUMASK), %eax
-	cmpl	$TLBSTATE_LAZY, CPUVAR(TLBSTATE)
-	jne	3f
-	testl	%eax, TP_USERMASK(%ebx)
-	jz	3f
-	movl	CPUVAR(PMAP), %edx
-	movl	%eax, %ecx
-	notl	%ecx
-	lock
-	andl	%ecx, PM_CPUS(%edx)
-	movl	$TLBSTATE_STALE, CPUVAR(TLBSTATE)
-3:
-	/* Ack the request, restore state & return. */
-	lock
-	xorl	%eax, _C_LABEL(pmap_tlb_mailbox)+TM_PENDING
-	popl	%fs
-	popl	%ds
-	popl	%edx
-	popl	%ecx
-	popl	%ebx
-	popl	%eax
-	iret
-4:
-	/*
-	 * Note that caller-save registers might be modified (all saved in the
-	 * beginning).  Only %ebx value must be preserved for the 2b context.
-	 */
-
-	/* Get the emap generation number. */
-	call	_C_LABEL(uvm_emap_gen_return)
-	movl	%eax, %ecx
-
-	/* Which entries we are invalidating? */
-	testw	$PG_G, TP_PTE(%ebx)
-	jnz	5f
-
-	/* a) Invalidating user TLB entries only. */
-	movl	%cr3, %eax
-	movl	%eax, %cr3
-	jmp	6f
-5:
-	/* b) Invalidating user and kernel TLB entries. */
-	movl	%cr4, %eax
-	movl	%eax, %edx
-	andl	$~CR4_PGE, %edx
-	movl	%edx, %cr4
-	movl	%eax, %cr4
-6:
-	/* Perform emap update, pass the generation number. */
-	pushl	%ecx
-	call	_C_LABEL(uvm_emap_update)
-	addl	$4, %esp
-	jmp	2b
+	call	_C_LABEL(pmap_tlb_intr)
+	INTRFASTEXIT
 IDTVEC_END(intr_lapic_tlb)
 
 #if defined(DDB)

Index: src/sys/arch/x86/include/pmap.h
diff -u src/sys/arch/x86/include/pmap.h:1.29.2.8 src/sys/arch/x86/include/pmap.h:1.29.2.9
--- src/sys/arch/x86/include/pmap.h:1.29.2.8	Tue Mar  8 23:27:50 2011
+++ src/sys/arch/x86/include/pmap.h	Thu Mar 17 04:46:28 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmap.h,v 1.29.2.8 2011/03/08 23:27:50 rmind Exp $	*/
+/*	$NetBSD: pmap.h,v 1.29.2.9 2011/03/17 04:46:28 rmind Exp $	*/
 
 /*
  * Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -266,6 +266,7 @@
 void		pmap_tlb_init(void);
 void		pmap_tlb_shootdown(pmap_t, vaddr_t, pt_entry_t, tlbwhy_t);
 void		pmap_tlb_shootnow(void);
+void		pmap_tlb_intr(void);
 
 #define	__HAVE_PMAP_EMAP
 
@@ -459,33 +460,6 @@
  */
 #define	POOL_VTOPHYS(va)	vtophys((vaddr_t) (va))
 
-/*
- * TLB shootdown structures.
- */
-
-struct pmap_tlb_packet {
-#ifdef _LP64
-	uintptr_t		tp_va[14];	/* whole struct: 128 bytes */
-#else
-	uintptr_t		tp_va[13];	/* whole struct: 64 bytes */
-#endif
-	uint16_t		tp_count;
-	uint16_t		tp_pte;
-	uint32_t		tp_cpumask;
-	uint32_t		tp_usermask;
-};
-
-/* No more than N seperate invlpg. */
-#define	TP_MAXVA		6
-
-struct pmap_tlb_mailbox {
-	volatile uint32_t	tm_pending;
-	volatile uint32_t	tm_gen;
-	uint32_t		tm_usergen;
-	uint32_t		tm_globalgen;
-	char			tm_pad[64 - sizeof(uintptr_t) * 4];
-};
-
 #endif /* _KERNEL */
 
 #endif /* _X86_PMAP_H_ */

Index: src/sys/arch/x86/x86/cpu.c
diff -u src/sys/arch/x86/x86/cpu.c:1.69.2.3 src/sys/arch/x86/x86/cpu.c:1.69.2.4
--- src/sys/arch/x86/x86/cpu.c:1.69.2.3	Sat Mar  5 20:52:29 2011
+++ src/sys/arch/x86/x86/cpu.c	Thu Mar 17 04:46:28 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpu.c,v 1.69.2.3 2011/03/05 20:52:29 rmind Exp $	*/
+/*	$NetBSD: cpu.c,v 1.69.2.4 2011/03/17 04:46:28 rmind Exp $	*/
 
 /*-
  * Copyright (c) 2000, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -62,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.69.2.3 2011/03/05 20:52:29 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.69.2.4 2011/03/17 04:46:28 rmind Exp $");
 
 #include "opt_ddb.h"
 #include "opt_mpbios.h"		/* for MPDEBUG */
@@ -354,7 +354,6 @@
 		cpu_init_tss(ci);
 	} else {
 		KASSERT(ci->ci_data.cpu_idlelwp != NULL);
-		cpus_running = (1 << cpu_index(ci));
 	}
 
 	ci->ci_cpumask = (1 << cpu_index(ci));

Index: src/sys/arch/x86/x86/pmap.c
diff -u src/sys/arch/x86/x86/pmap.c:1.105.2.12 src/sys/arch/x86/x86/pmap.c:1.105.2.13
--- src/sys/arch/x86/x86/pmap.c:1.105.2.12	Tue Mar  8 23:26:35 2011
+++ src/sys/arch/x86/x86/pmap.c	Thu Mar 17 04:46:29 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmap.c,v 1.105.2.12 2011/03/08 23:26:35 rmind Exp $	*/
+/*	$NetBSD: pmap.c,v 1.105.2.13 2011/03/17 04:46:29 rmind Exp $	*/
 
 /*-
  * Copyright (c) 2008, 2010 The NetBSD Foundation, Inc.
@@ -171,7 +171,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.105.2.12 2011/03/08 23:26:35 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.105.2.13 2011/03/17 04:46:29 rmind Exp $");
 
 #include "opt_user_ldt.h"
 #include "opt_lockdebug.h"
@@ -4301,9 +4301,7 @@
 	 * Initiate any pending TLB shootdowns.  Wait for them to
 	 * complete before returning control to the caller.
 	 */
-	if (((struct pmap_tlb_packet *)curcpu()->ci_pmap_data)->tp_count) {
-		pmap_tlb_shootnow();
-	}
+	pmap_tlb_shootnow();
 	KPREEMPT_ENABLE(l);
 
 	/*

Index: src/sys/arch/x86/x86/pmap_tlb.c
diff -u src/sys/arch/x86/x86/pmap_tlb.c:1.1.2.4 src/sys/arch/x86/x86/pmap_tlb.c:1.1.2.5
--- src/sys/arch/x86/x86/pmap_tlb.c:1.1.2.4	Tue Mar  8 23:41:09 2011
+++ src/sys/arch/x86/x86/pmap_tlb.c	Thu Mar 17 04:46:29 2011
@@ -1,11 +1,11 @@
-/*	$NetBSD: pmap_tlb.c,v 1.1.2.4 2011/03/08 23:41:09 rmind Exp $	*/
+/*	$NetBSD: pmap_tlb.c,v 1.1.2.5 2011/03/17 04:46:29 rmind Exp $	*/
 
 /*-
- * Copyright (c) 2008, 2010 The NetBSD Foundation, Inc.
+ * Copyright (c) 2008-2011 The NetBSD Foundation, Inc.
  * All rights reserved.
  *
  * This code is derived from software contributed to The NetBSD Foundation
- * by Andrew Doran.
+ * by Andrew Doran and Mindaugas Rasiukevicius.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -35,12 +35,12 @@
  * TLB shootdowns are hard interrupts that operate outside the SPL framework:
  * They do not need to be blocked, provided that the pmap module gets the
  * order of events correct.  The calls are made by poking the LAPIC directly.
- * The stub to handle the interrupts is short and does one of the following:
- * invalidate a set of pages, all user TLB entries or the entire TLB.
+ * The interrupt handler is short and does one of the following:  invalidate
+ * a set of pages, all user TLB entries or the entire TLB.
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap_tlb.c,v 1.1.2.4 2011/03/08 23:41:09 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap_tlb.c,v 1.1.2.5 2011/03/17 04:46:29 rmind Exp $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -57,11 +57,38 @@
 #include <x86/i82489var.h>
 
 /*
+ * TLB shootdown structures.
+ */
+
+typedef struct {
+#ifdef _LP64
+	uintptr_t		tp_va[14];	/* whole struct: 128 bytes */
+#else
+	uintptr_t		tp_va[13];	/* whole struct: 64 bytes */
+#endif
+	uint16_t		tp_count;
+	uint16_t		tp_pte;
+	uint32_t		tp_cpumask;
+	uint32_t		tp_usermask;
+} pmap_tlb_packet_t;
+
+/* No more than N seperate invlpg. */
+#define	TP_MAXVA		6
+
+typedef struct {
+	volatile uint32_t	tm_pending;
+	volatile uint32_t	tm_gen;
+	uint32_t		tm_usergen;
+	uint32_t		tm_globalgen;
+	char			tm_pad[64 - sizeof(uintptr_t) * 4];
+} pmap_tlb_mailbox_t;
+
+/*
  * TLB shootdown state.
  */
 static struct evcnt		pmap_tlb_evcnt		__cacheline_aligned;
-struct pmap_tlb_packet		pmap_tlb_packet		__cacheline_aligned;
-struct pmap_tlb_mailbox		pmap_tlb_mailbox	__cacheline_aligned;
+static pmap_tlb_packet_t	pmap_tlb_packet		__cacheline_aligned;
+static pmap_tlb_mailbox_t	pmap_tlb_mailbox	__cacheline_aligned;
 
 /*
  * TLB shootdown statistics.
@@ -93,15 +120,16 @@
 void
 pmap_tlb_init(void)
 {
-	int i = 0;
 
-	memset(&pmap_tlb_packet, 0, sizeof(struct pmap_tlb_packet));
-	memset(&pmap_tlb_mailbox, 0, sizeof(struct pmap_tlb_mailbox));
+	memset(&pmap_tlb_packet, 0, sizeof(pmap_tlb_packet_t));
+	memset(&pmap_tlb_mailbox, 0, sizeof(pmap_tlb_mailbox_t));
 
 	evcnt_attach_dynamic(&pmap_tlb_evcnt, EVCNT_TYPE_INTR,
 	    NULL, "TLB", "shootdown");
 
 #ifdef TLBSTATS
+	int i;
+
 	for (i = 0; i < TLBSHOOT__MAX; i++) {
 		evcnt_attach_dynamic(&tlbstat_local[i], EVCNT_TYPE_MISC,
 		    NULL, "tlbshoot local", tlbstat_name[i]);
@@ -148,13 +176,37 @@
 #endif
 }
 
+static inline void
+pmap_tlb_invalidate(pmap_tlb_packet_t *tp)
+{
+	int i;
+
+	/* Find out what we need to invalidate. */
+	if (tp->tp_count == (uint16_t)-1) {
+		u_int egen = uvm_emap_gen_return();
+		if (tp->tp_pte & PG_G) {
+			/* Invalidating user and kernel TLB entries. */
+			tlbflushg();
+		} else {
+			/* Invalidating user TLB entries only. */
+			tlbflush();
+		}
+		uvm_emap_update(egen);
+	} else {
+		/* Invalidating a single page or a range of pages. */
+		for (i = tp->tp_count - 1; i >= 0; i--) {
+			pmap_update_pg(tp->tp_va[i]);
+		}
+	}
+}
+
 /*
  * pmap_tlb_shootdown: invalidate a page on all CPUs using pmap 'pm'
  */
 void
 pmap_tlb_shootdown(struct pmap *pm, vaddr_t va, pt_entry_t pte, tlbwhy_t why)
 {
-	struct pmap_tlb_packet *tp;
+	pmap_tlb_packet_t *tp;
 	int s;
 
 	KASSERT((pte & PG_G) == 0 || pm == pmap_kernel());
@@ -175,7 +227,7 @@
 	 * Add the shootdown operation to our pending set.
 	 */ 
 	s = splvm();
-	tp = (struct pmap_tlb_packet *)curcpu()->ci_pmap_data;
+	tp = (pmap_tlb_packet_t *)curcpu()->ci_pmap_data;
 
 	/* Whole address flush will be needed if PG_G is set. */
 	CTASSERT(PG_G == (uint16_t)PG_G);
@@ -215,18 +267,24 @@
 void
 pmap_tlb_shootnow(void)
 {
-	struct pmap_tlb_packet *tp;
-	struct pmap_tlb_mailbox *tm;
+	pmap_tlb_packet_t *tp;
+	pmap_tlb_mailbox_t *tm;
 	struct cpu_info *ci;
 	uint32_t remote;
 	uintptr_t gen;
-	int s, i, count;
+	int s;
 
 	KASSERT(kpreempt_disabled());
 
-	s = splvm();
 	ci = curcpu();
-	tp = (struct pmap_tlb_packet *)ci->ci_pmap_data;
+	tp = (pmap_tlb_packet_t *)ci->ci_pmap_data;
+
+	/* Pre-check first. */
+	if (tp->tp_count == 0) {
+		return;
+	}
+
+	s = splvm();
 	if (tp->tp_count == 0) {
 		splx(s);
 		return;
@@ -239,7 +297,7 @@
 	if (remote != 0) {
 		CPU_INFO_ITERATOR cii;
 		struct cpu_info *lci;
-		int err;
+		int count, err;
 		/*
 		 * Gain ownership of the shootdown mailbox.  We must stay
 		 * at IPL_VM once we own it or could deadlock against an
@@ -298,19 +356,7 @@
 	 * perform local shootdowns and do not forget to update emap gen.
 	 */
 	if ((tp->tp_cpumask & ci->ci_cpumask) != 0) {
-		if (tp->tp_count == (uint16_t)-1) {
-			u_int egen = uvm_emap_gen_return();
-			if ((tp->tp_pte & PG_G) != 0) {
-				tlbflushg();
-			} else {
-				tlbflush();
-			}
-			uvm_emap_update(egen);
-		} else {
-			for (i = tp->tp_count - 1; i >= 0; i--) {
-				pmap_update_pg(tp->tp_va[i]);
-			}
-		}
+		pmap_tlb_invalidate(tp);
 	}
 
 	/*
@@ -332,9 +378,43 @@
 	 * processed by remote CPUs.
 	 */
 	if (remote != 0 && tm->tm_pending != 0) {
-		count = SPINLOCK_BACKOFF_MIN;
+		int count = SPINLOCK_BACKOFF_MIN;
 		while (tm->tm_pending != 0 && tm->tm_gen == gen) {
 			SPINLOCK_BACKOFF(count);
 		}
 	}
 }
+
+/*
+ * pmap_tlb_ipi: pmap shootdown interrupt handler to invalidate TLB entries.
+ *
+ * => Called from IPI only.
+ */
+void
+pmap_tlb_intr(void)
+{
+	pmap_tlb_packet_t *tp = &pmap_tlb_packet;
+	pmap_tlb_mailbox_t *tm;
+	struct cpu_info *ci;
+	uint32_t cm;
+
+	pmap_tlb_invalidate(tp);
+
+	/*
+	 * Check the current TLB state.  If we do not want further
+	 * invalidations for this pmap, then take the CPU out of
+	 * the pmap's bitmask.
+	 */
+	ci = curcpu();
+	cm = ci->ci_cpumask;
+	if (ci->ci_tlbstate == TLBSTATE_LAZY && (tp->tp_usermask & cm) != 0) {
+		struct pmap *pm = ci->ci_pmap;
+
+		atomic_and_32(&pm->pm_cpus, ~cm);
+		ci->ci_tlbstate = TLBSTATE_STALE;
+	}
+
+	/* Ack the request. */
+	tm = &pmap_tlb_mailbox;
+	atomic_and_32(&tm->tm_pending, ~cm);
+}

Reply via email to