changeset 9989:33d24b36e077

6814942 auxiliary CPUs needs to have their stacks saved and restored across suspend/resume
author Joseph A Townsend <Joseph.Townsend@Sun.COM>
date Mon, 29 Jun 2009 11:35:21 -0700
parents 4066d8f807e9
children 889ca9ca793d
files usr/src/uts/i86pc/ml/cpr_wakecode.s usr/src/uts/i86pc/ml/offsets.in usr/src/uts/i86pc/os/cpr_impl.c usr/src/uts/i86pc/sys/cpr_wakecode.h
diffstat 4 files changed, 117 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/i86pc/ml/cpr_wakecode.s	Mon Jun 29 09:46:17 2009 -0700
+++ b/usr/src/uts/i86pc/ml/cpr_wakecode.s	Mon Jun 29 11:35:21 2009 -0700
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 	
@@ -163,10 +163,14 @@
 	movl    %eax, WC_KGSBASE(%rdi)
 	movl    %edx, WC_KGSBASE+4(%rdi)
 
+	movq	%gs:CPU_ID, %rax	/ save current cpu id
+	movq	%rax, WC_CPU_ID(%rdi)
+
 	pushfq
 	popq	WC_EFLAGS(%rdi)
 
 	wbinvd				/ flush the cache
+	mfence
 
 	movq	$1, %rax		/ at suspend return 1
 
@@ -214,7 +218,11 @@
 	pushfl
 	popl	WC_EFLAGS(%eax)
 
+	pushl	%gs:CPU_ID		/ save current cpu id
+	popl	WC_CPU_ID(%eax)
+
 	wbinvd				/ flush the cache
+	mfence
 
 	movl	$1, %eax		/ at suspend return 1
 	ret
@@ -738,21 +746,34 @@
 	outb    (%dx)
 #endif
 
-/ dummy up a stck so we can make C function calls
-	movq    WC_RSP(%rbx), %rsp
+	/*
+	 * if we are not running on the boot CPU restore stack contents by
+	 * calling i_cpr_restore_stack(curthread, save_stack);
+	 */
+	movq    %rsp, %rbp
+	call	i_cpr_bootcpuid
+	cmpl	%eax, WC_CPU_ID(%rbx)
+	je	2f
+
+	movq	%gs:CPU_THREAD, %rdi
+	movq	WC_SAVED_STACK(%rbx), %rsi
+	call	i_cpr_restore_stack
+2:
+
+	movq    WC_RSP(%rbx), %rsp	/ restore stack pointer
 
 	/*
 	 * APIC initialization
 	 */
-	movq    %rsp, %rbp      /* stack aligned on 16-byte boundary */
+	movq    %rsp, %rbp
 
 	/*
 	 * skip iff function pointer is NULL
 	 */
 	cmpq	$0, ap_mlsetup
-	je	2f
+	je	3f
 	call	*ap_mlsetup
-2:
+3:
 
 	call    *cpr_start_cpu_func
 
@@ -1091,23 +1112,48 @@
 	andl	$-1!0x200, 4(%eax)
 	ltr	WC_TR(%ebx)		/ $UTSS_SEL
 
-	movw	WC_SS(%ebx), %ss	/ lssl	WC_ESP(%ebx), %esp
-	movl	WC_ESP(%ebx), %esp	/ ^ don't use, asm busted! 
+	movw	WC_SS(%ebx), %ss	/ restore segment registers
+	movw	WC_ES(%ebx), %es
+	movw	WC_FS(%ebx), %fs
+	movw	WC_GS(%ebx), %gs
+
+	/*
+	 * set the stack pointer to point into the identity mapped page
+	 * temporarily, so we can make function calls 
+	 */
+	.globl  rm_platter_va
+	movl    rm_platter_va, %eax
+	movl	$WC_STKSTART, %esp
+	addl	%eax, %esp
+	movl	%esp, %ebp
+
+	/*
+	 * if we are not running on the boot CPU restore stack contents by
+	 * calling i_cpr_restore_stack(curthread, save_stack);
+	 */
+	call	i_cpr_bootcpuid
+	cmpl	%eax, WC_CPU_ID(%ebx)
+	je	2f
+
+	pushl	WC_SAVED_STACK(%ebx)
+	pushl	%gs:CPU_THREAD
+	call	i_cpr_restore_stack
+	addl	$0x10, %esp
+2:
+
+	movl	WC_ESP(%ebx), %esp
+	movl	%esp, %ebp
 
 	movl	WC_RETADDR(%ebx), %eax	/ return to caller of wc_save_context
 	movl	%eax, (%esp)
 
-	movw	WC_ES(%ebx), %es	/ restore segment registers
-	movw	WC_FS(%ebx), %fs
-	movw	WC_GS(%ebx), %gs
-
 	/*
 	 * APIC initialization, skip iff function pointer is NULL
 	 */
 	cmpl	$0, ap_mlsetup
-	je	2f
+	je	3f
 	call	*ap_mlsetup
-2:
+3:
 
 	call    *cpr_start_cpu_func
 
--- a/usr/src/uts/i86pc/ml/offsets.in	Mon Jun 29 09:46:17 2009 -0700
+++ b/usr/src/uts/i86pc/ml/offsets.in	Mon Jun 29 11:35:21 2009 -0700
@@ -1,5 +1,5 @@
 \
-\ Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+\ Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 \ Use is subject to license terms.
 \
 \ CDDL HEADER START
@@ -459,6 +459,8 @@
 	wc_cs
 	wc_ds
 	wc_es
+	wc_cpu_id
+	wc_saved_stack
 
 wc_wakecode
 	wc_cpu
--- a/usr/src/uts/i86pc/os/cpr_impl.c	Mon Jun 29 09:46:17 2009 -0700
+++ b/usr/src/uts/i86pc/os/cpr_impl.c	Mon Jun 29 11:35:21 2009 -0700
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -93,6 +93,17 @@
 static int i_cpr_restore_apic(psm_state_request_t *req);
 static int wait_for_set(cpuset_t *set, int who);
 
+static	void i_cpr_save_stack(kthread_t *t, wc_cpu_t *wc_cpu);
+void i_cpr_restore_stack(kthread_t *t, greg_t *save_stack);
+
+#ifdef STACK_GROWTH_DOWN
+#define	CPR_GET_STACK_START(t) ((t)->t_stkbase)
+#define	CPR_GET_STACK_END(t) ((t)->t_stk)
+#else
+#define	CPR_GET_STACK_START(t) ((t)->t_stk)
+#define	CPR_GET_STACK_END(t) ((t)->t_stkbase)
+#endif	/* STACK_GROWTH_DOWN */
+
 /*
  * restart paused slave cpus
  */
@@ -172,12 +183,13 @@
 	psm_state_request_t *papic_state;
 	int resuming;
 	int	ret;
+	wc_cpu_t	*wc_cpu = wc_other_cpus + index;
 
 	PMD(PMD_SX, ("i_cpr_save_context() index = %ld\n", index))
 
 	ASSERT(index < NCPU);
 
-	papic_state = &(wc_other_cpus + index)->wc_apic_state;
+	papic_state = &(wc_cpu)->wc_apic_state;
 
 	ret = i_cpr_platform_alloc(papic_state);
 	ASSERT(ret == 0);
@@ -185,12 +197,14 @@
 	ret = i_cpr_save_apic(papic_state);
 	ASSERT(ret == 0);
 
+	i_cpr_save_stack(curthread, wc_cpu);
+
 	/*
 	 * wc_save_context returns twice, once when susending and
 	 * once when resuming,  wc_save_context() returns 0 when
 	 * suspending and non-zero upon resume
 	 */
-	resuming = (wc_save_context(wc_other_cpus + index) == 0);
+	resuming = (wc_save_context(wc_cpu) == 0);
 
 	/*
 	 * do NOT call any functions after this point, because doing so
@@ -1063,3 +1077,36 @@
 
 	return (1);
 }
+
+static	void
+i_cpr_save_stack(kthread_t *t, wc_cpu_t *wc_cpu)
+{
+	size_t	stack_size;	/* size of stack */
+	caddr_t	start = CPR_GET_STACK_START(t);	/* stack start */
+	caddr_t	end = CPR_GET_STACK_END(t);	/* stack end  */
+
+	stack_size = (size_t)end - (size_t)start;
+
+	if (wc_cpu->wc_saved_stack_size < stack_size) {
+		if (wc_cpu->wc_saved_stack != NULL) {
+			kmem_free(wc_cpu->wc_saved_stack,
+			    wc_cpu->wc_saved_stack_size);
+		}
+		wc_cpu->wc_saved_stack = kmem_zalloc(stack_size, KM_SLEEP);
+		wc_cpu->wc_saved_stack_size = stack_size;
+	}
+
+	bcopy(start, wc_cpu->wc_saved_stack, stack_size);
+}
+
+void
+i_cpr_restore_stack(kthread_t *t, greg_t *save_stack)
+{
+	size_t	stack_size;	/* size of stack */
+	caddr_t	start = CPR_GET_STACK_START(t);	/* stack start */
+	caddr_t	end = CPR_GET_STACK_END(t);	/* stack end  */
+
+	stack_size = (size_t)end - (size_t)start;
+
+	bcopy(save_stack, start, stack_size);
+}
--- a/usr/src/uts/i86pc/sys/cpr_wakecode.h	Mon Jun 29 09:46:17 2009 -0700
+++ b/usr/src/uts/i86pc/sys/cpr_wakecode.h	Mon Jun 29 11:35:21 2009 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -113,6 +113,9 @@
 	uint16_t wc_ds;
 	uint16_t wc_es;
 	psm_state_request_t	wc_apic_state;
+	processorid_t	wc_cpu_id;	/* which CPU are we running on */
+	greg_t	*wc_saved_stack; /* pointer to where stack contents are saved */
+	size_t	wc_saved_stack_size;	/* size of the saved stack */
 
 
 	/* temp stack grows down to here */