# HG changeset patch # User Joseph A Townsend # Date 1246300521 25200 # Node ID 33d24b36e077679f50be90f5af5448ecb5d11caa # Parent 4066d8f807e910a6eef1afc227e47d7310002501 6814942 auxiliary CPUs needs to have their stacks saved and restored across suspend/resume diff -r 4066d8f807e9 -r 33d24b36e077 usr/src/uts/i86pc/ml/cpr_wakecode.s --- 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 diff -r 4066d8f807e9 -r 33d24b36e077 usr/src/uts/i86pc/ml/offsets.in --- 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 diff -r 4066d8f807e9 -r 33d24b36e077 usr/src/uts/i86pc/os/cpr_impl.c --- 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); +} diff -r 4066d8f807e9 -r 33d24b36e077 usr/src/uts/i86pc/sys/cpr_wakecode.h --- 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 */