From 69aeb16c07a1aeba0e22d6c5d44c4dd9004145d7 Mon Sep 17 00:00:00 2001 From: drochner Date: Thu, 22 Aug 2013 19:50:54 +0000 Subject: [PATCH] -extend the pcu(9) API by a function which saves all context on the current CPU, and use it if a CPU is taken offline -add a bool argument to pcu_discard which tells whether the internal "LWP has used the coprocessor" flag should be set or reset. The flag is reported by pcu_used_p(). If set, future accesses should use the state stored in the PCB. If reset, it should be reset to default. The former case is useful for setmcontext(). With that, it should not be necessary anymore to manage the "FPU used" state by an additional MD variable. approved by matt --- sys/arch/alpha/include/alpha.h | 4 ++-- sys/arch/arm/vfp/vfp_init.c | 6 +++--- sys/arch/mips/mips/mips_dsp.c | 6 +++--- sys/arch/mips/mips/mips_fpu.c | 6 +++--- sys/arch/powerpc/include/altivec.h | 4 ++-- sys/arch/powerpc/include/fpu.h | 4 ++-- sys/arch/powerpc/oea/altivec.c | 6 +++--- sys/arch/powerpc/powerpc/fpu.c | 6 +++--- sys/kern/kern_cpu.c | 9 +++++++-- sys/kern/subr_pcu.c | 27 ++++++++++++++++++++++----- sys/sys/pcu.h | 5 +++-- 11 files changed, 53 insertions(+), 30 deletions(-) diff --git a/sys/arch/alpha/include/alpha.h b/sys/arch/alpha/include/alpha.h index 6abf3785aced..16a62597a8ae 100644 --- a/sys/arch/alpha/include/alpha.h +++ b/sys/arch/alpha/include/alpha.h @@ -1,4 +1,4 @@ -/* $NetBSD: alpha.h,v 1.31 2012/12/26 19:13:19 matt Exp $ */ +/* $NetBSD: alpha.h,v 1.32 2013/08/22 19:50:54 drochner Exp $ */ /* * Copyright (c) 1988 University of Utah. @@ -128,7 +128,7 @@ fpu_save(void) static inline void fpu_discard(void) { - pcu_discard(&fpu_ops); + pcu_discard(&fpu_ops, false); } void alpha_patch(bool); diff --git a/sys/arch/arm/vfp/vfp_init.c b/sys/arch/arm/vfp/vfp_init.c index 526ae7574bb4..723f374e7d98 100644 --- a/sys/arch/arm/vfp/vfp_init.c +++ b/sys/arch/arm/vfp/vfp_init.c @@ -1,4 +1,4 @@ -/* $NetBSD: vfp_init.c,v 1.23 2013/08/18 06:28:18 matt Exp $ */ +/* $NetBSD: vfp_init.c,v 1.24 2013/08/22 19:50:54 drochner Exp $ */ /* * Copyright (c) 2008 ARM Ltd @@ -601,7 +601,7 @@ vfp_savecontext(void) void vfp_discardcontext(void) { - pcu_discard(&arm_vfp_ops); + pcu_discard(&arm_vfp_ops, false); } void @@ -656,7 +656,7 @@ vfp_getcontext(struct lwp *l, mcontext_t *mcp, int *flagsp) void vfp_setcontext(struct lwp *l, const mcontext_t *mcp) { - pcu_discard(&arm_vfp_ops); + pcu_discard(&arm_vfp_ops, true); struct pcb * const pcb = lwp_getpcb(l); l->l_md.md_flags |= MDLWP_VFPUSED; pcb->pcb_vfp.vfp_fpscr = mcp->__fpu.__vfpregs.__vfp_fpscr; diff --git a/sys/arch/mips/mips/mips_dsp.c b/sys/arch/mips/mips/mips_dsp.c index 2d1db189f848..7b25d8311a27 100644 --- a/sys/arch/mips/mips/mips_dsp.c +++ b/sys/arch/mips/mips/mips_dsp.c @@ -1,4 +1,4 @@ -/* $NetBSD: mips_dsp.c,v 1.2 2012/12/26 19:17:48 matt Exp $ */ +/* $NetBSD: mips_dsp.c,v 1.3 2013/08/22 19:50:54 drochner Exp $ */ /*- * Copyright (c) 2011 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: mips_dsp.c,v 1.2 2012/12/26 19:17:48 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: mips_dsp.c,v 1.3 2013/08/22 19:50:54 drochner Exp $"); #include "opt_multiprocessor.h" @@ -60,7 +60,7 @@ const pcu_ops_t mips_dsp_ops = { void dsp_discard(void) { - pcu_discard(&mips_dsp_ops); + pcu_discard(&mips_dsp_ops, false); } void diff --git a/sys/arch/mips/mips/mips_fpu.c b/sys/arch/mips/mips/mips_fpu.c index e9e5df595a73..05795a063b0b 100644 --- a/sys/arch/mips/mips/mips_fpu.c +++ b/sys/arch/mips/mips/mips_fpu.c @@ -1,4 +1,4 @@ -/* $NetBSD: mips_fpu.c,v 1.10 2012/12/26 19:15:16 matt Exp $ */ +/* $NetBSD: mips_fpu.c,v 1.11 2013/08/22 19:50:54 drochner Exp $ */ /*- * Copyright (c) 2010 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: mips_fpu.c,v 1.10 2012/12/26 19:15:16 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: mips_fpu.c,v 1.11 2013/08/22 19:50:54 drochner Exp $"); #include "opt_multiprocessor.h" @@ -60,7 +60,7 @@ const pcu_ops_t mips_fpu_ops = { void fpu_discard(void) { - pcu_discard(&mips_fpu_ops); + pcu_discard(&mips_fpu_ops, false); } void diff --git a/sys/arch/powerpc/include/altivec.h b/sys/arch/powerpc/include/altivec.h index 9b7f0b139109..04cd5a744588 100644 --- a/sys/arch/powerpc/include/altivec.h +++ b/sys/arch/powerpc/include/altivec.h @@ -1,4 +1,4 @@ -/* $NetBSD: altivec.h,v 1.15 2011/05/02 06:29:23 matt Exp $ */ +/* $NetBSD: altivec.h,v 1.16 2013/08/22 19:50:54 drochner Exp $ */ /*- * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -68,7 +68,7 @@ vec_save(void) static inline void vec_discard(void) { - pcu_discard(&vec_ops); + pcu_discard(&vec_ops, false); } void vec_load_from_vreg(const struct vreg *); diff --git a/sys/arch/powerpc/include/fpu.h b/sys/arch/powerpc/include/fpu.h index 001bd9ba91c5..13412d84308b 100644 --- a/sys/arch/powerpc/include/fpu.h +++ b/sys/arch/powerpc/include/fpu.h @@ -1,4 +1,4 @@ -/* $NetBSD: fpu.h,v 1.19 2011/05/19 08:22:38 kiyohara Exp $ */ +/* $NetBSD: fpu.h,v 1.20 2013/08/22 19:50:54 drochner Exp $ */ /*- * Copyright (C) 1996 Wolfgang Solfrank. @@ -106,7 +106,7 @@ fpu_save(void) static inline void fpu_discard(void) { - pcu_discard(&fpu_ops); + pcu_discard(&fpu_ops, false); } void fpu_load_from_fpreg(const struct fpreg *); diff --git a/sys/arch/powerpc/oea/altivec.c b/sys/arch/powerpc/oea/altivec.c index 28f3b5389d9e..98618851f273 100644 --- a/sys/arch/powerpc/oea/altivec.c +++ b/sys/arch/powerpc/oea/altivec.c @@ -1,4 +1,4 @@ -/* $NetBSD: altivec.c,v 1.26 2012/12/26 19:05:03 matt Exp $ */ +/* $NetBSD: altivec.c,v 1.27 2013/08/22 19:50:54 drochner Exp $ */ /* * Copyright (C) 1996 Wolfgang Solfrank. @@ -32,7 +32,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: altivec.c,v 1.26 2012/12/26 19:05:03 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: altivec.c,v 1.27 2013/08/22 19:50:54 drochner Exp $"); #include "opt_multiprocessor.h" @@ -164,7 +164,7 @@ vec_restore_from_mcontext(struct lwp *l, const mcontext_t *mcp) KASSERT(l == curlwp); /* we don't need to save the state, just drop it */ - pcu_discard(&vec_ops); + pcu_discard(&vec_ops, true); memcpy(pcb->pcb_vr.vreg, &mcp->__vrf.__vrs, sizeof (pcb->pcb_vr.vreg)); pcb->pcb_vr.vscr = mcp->__vrf.__vscr; pcb->pcb_vr.vrsave = mcp->__vrf.__vrsave; diff --git a/sys/arch/powerpc/powerpc/fpu.c b/sys/arch/powerpc/powerpc/fpu.c index 716de6a85f7c..045cba78a05d 100644 --- a/sys/arch/powerpc/powerpc/fpu.c +++ b/sys/arch/powerpc/powerpc/fpu.c @@ -1,4 +1,4 @@ -/* $NetBSD: fpu.c,v 1.32 2012/12/26 19:05:03 matt Exp $ */ +/* $NetBSD: fpu.c,v 1.33 2013/08/22 19:50:54 drochner Exp $ */ /* * Copyright (C) 1996 Wolfgang Solfrank. @@ -32,7 +32,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.32 2012/12/26 19:05:03 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.33 2013/08/22 19:50:54 drochner Exp $"); #include "opt_multiprocessor.h" @@ -242,7 +242,7 @@ fpu_restore_from_mcontext(lwp_t *l, const mcontext_t *mcp) #ifdef PPC_HAVE_FPU /* we don't need to save the state, just drop it */ if (l == curlwp) - pcu_discard(&fpu_ops); + pcu_discard(&fpu_ops, true); #endif (void)memcpy(&pcb->pcb_fpu.fpreg, &mcp->__fpregs.__fpu_regs, sizeof (pcb->pcb_fpu.fpreg)); diff --git a/sys/kern/kern_cpu.c b/sys/kern/kern_cpu.c index bd976cba073b..8ce42532f132 100644 --- a/sys/kern/kern_cpu.c +++ b/sys/kern/kern_cpu.c @@ -1,4 +1,4 @@ -/* $NetBSD: kern_cpu.c,v 1.59 2012/10/17 20:19:55 drochner Exp $ */ +/* $NetBSD: kern_cpu.c,v 1.60 2013/08/22 19:50:55 drochner Exp $ */ /*- * Copyright (c) 2007, 2008, 2009, 2010, 2012 The NetBSD Foundation, Inc. @@ -56,7 +56,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: kern_cpu.c,v 1.59 2012/10/17 20:19:55 drochner Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_cpu.c,v 1.60 2013/08/22 19:50:55 drochner Exp $"); #include "opt_cpu_ucode.h" #include "opt_compat_netbsd.h" @@ -79,6 +79,7 @@ __KERNEL_RCSID(0, "$NetBSD: kern_cpu.c,v 1.59 2012/10/17 20:19:55 drochner Exp $ #include #include #include +#include #include @@ -389,6 +390,10 @@ cpu_xc_offline(struct cpu_info *ci) } mutex_exit(proc_lock); +#if PCU_UNIT_COUNT > 0 + pcu_save_all_on_cpu(); +#endif + #ifdef __HAVE_MD_CPU_OFFLINE cpu_offline_md(); #endif diff --git a/sys/kern/subr_pcu.c b/sys/kern/subr_pcu.c index 3e37b010b8a1..8dbd29845450 100644 --- a/sys/kern/subr_pcu.c +++ b/sys/kern/subr_pcu.c @@ -1,4 +1,4 @@ -/* $NetBSD: subr_pcu.c,v 1.14 2012/12/31 01:20:05 matt Exp $ */ +/* $NetBSD: subr_pcu.c,v 1.15 2013/08/22 19:50:55 drochner Exp $ */ /*- * Copyright (c) 2011 The NetBSD Foundation, Inc. @@ -57,7 +57,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: subr_pcu.c,v 1.14 2012/12/31 01:20:05 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: subr_pcu.c,v 1.15 2013/08/22 19:50:55 drochner Exp $"); #include #include @@ -385,20 +385,25 @@ pcu_load(const pcu_ops_t *pcu) /* * pcu_discard: discard the PCU state of current LWP. + * If the "usesw" flag is set, pcu_used_p() will return "true". */ void -pcu_discard(const pcu_ops_t *pcu) +pcu_discard(const pcu_ops_t *pcu, bool usesw) { const u_int id = pcu->pcu_id; lwp_t * const l = curlwp; KASSERT(!cpu_intr_p() && !cpu_softintr_p()); + if (usesw) + l->l_pcu_used[PCU_USER] |= (1 << id); + else + l->l_pcu_used[PCU_USER] &= ~(1 << id); + if (__predict_true(l->l_pcu_cpu[id] == NULL)) { return; } pcu_lwp_op(pcu, l, PCU_RELEASE); - l->l_pcu_used[PCU_USER] &= ~(1 << id); } /* @@ -418,6 +423,18 @@ pcu_save(const pcu_ops_t *pcu) pcu_lwp_op(pcu, l, PCU_SAVE | PCU_RELEASE); } +/* + * pcu_save_all_on_cpu: save all PCU state on current CPU + */ +void +pcu_save_all_on_cpu(void) +{ + + for (u_int id = 0; id < PCU_UNIT_COUNT; id++) { + pcu_cpu_op(pcu_ops_md_defs[id], PCU_SAVE | PCU_RELEASE); + } +} + /* * pcu_used: return true if PCU was used (pcu_load() case) by the LWP. */ @@ -427,7 +444,7 @@ pcu_used_p(const pcu_ops_t *pcu) const u_int id = pcu->pcu_id; lwp_t * const l = curlwp; - return l->l_pcu_used[0] & (1 << id); + return l->l_pcu_used[PCU_USER] & (1 << id); } void diff --git a/sys/sys/pcu.h b/sys/sys/pcu.h index cf0a2fa6df02..8d335511ea96 100644 --- a/sys/sys/pcu.h +++ b/sys/sys/pcu.h @@ -1,4 +1,4 @@ -/* $NetBSD: pcu.h,v 1.10 2012/12/26 18:30:22 matt Exp $ */ +/* $NetBSD: pcu.h,v 1.11 2013/08/22 19:50:55 drochner Exp $ */ /*- * Copyright (c) 2011 The NetBSD Foundation, Inc. @@ -82,7 +82,8 @@ void pcu_save_all(lwp_t *); void pcu_load(const pcu_ops_t *); void pcu_save(const pcu_ops_t *); -void pcu_discard(const pcu_ops_t *); +void pcu_save_all_on_cpu(void); +void pcu_discard(const pcu_ops_t *, bool); void pcu_kernel_acquire(const pcu_ops_t *); void pcu_kernel_release(const pcu_ops_t *); bool pcu_used_p(const pcu_ops_t *);