From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S966007AbcJYWbJ (ORCPT ); Tue, 25 Oct 2016 18:31:09 -0400 Received: from mail-db5eur01on0139.outbound.protection.outlook.com ([104.47.2.139]:20838 "EHLO EUR01-DB5-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S942120AbcJYWbF (ORCPT ); Tue, 25 Oct 2016 18:31:05 -0400 Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=dsafonov@virtuozzo.com; From: Dmitry Safonov To: CC: <0x7f454c46@gmail.com>, Dmitry Safonov , "Benjamin Herrenschmidt" , Paul Mackerras , Michael Ellerman , Andy Lutomirski , Oleg Nesterov , , Subject: [PATCH 3/7] powerpc/vdso: separate common code in vdso_common Date: Tue, 25 Oct 2016 18:51:02 +0300 Message-ID: <20161025155106.29946-4-dsafonov@virtuozzo.com> X-Mailer: git-send-email 2.10.0 In-Reply-To: <20161025155106.29946-1-dsafonov@virtuozzo.com> References: <20161025155106.29946-1-dsafonov@virtuozzo.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [195.214.232.10] X-ClientProxiedBy: DB5PR0301CA0040.eurprd03.prod.outlook.com (10.167.222.178) To DB6PR0801MB1734.eurprd08.prod.outlook.com (10.169.226.149) X-MS-Office365-Filtering-Correlation-Id: 41c0d9ec-eeb1-4285-b48b-08d3fcef072c X-Microsoft-Exchange-Diagnostics: 1;DB6PR0801MB1734;2:QDTGuROxCfIjjqBsfrAcJis+vK7ZPrer9voTpuHibyk1yBgE//e6yKfwBXIRZYhYqVNrrJho7Qb5GHK8/97/pEqsntZdj06hY+btOFaXCT/Hc2IBqM/UBEwMXGnZrfpiQuOPfhtKLqDjrkZW+pIX0BTKMeNWNk5diqt7Qq6eBr6yU6F4GW66ggOZJou+J1jL8c8s+s7FdwyBfjJZmxeQxg==;3:7A2OSLclvVtDdb7j38Oc13kF3pmtl3N3DqawPDJZ8Miz3VXCxcUdlGIUlnnFCJ2YoViJIHZeVkHdVjl2iBqLHQUcybt2gT6d+vXdH6cToeTBRvFQ9LMgaLn6lEhoEDTPmfBQIcNFTJ2aIvn0rHdcJQ==;25:29nlMEcLayQ5wmWQy2WidTnY0p+QMcOoVqZZk1BVCb6oOORDDJ7pJTqy7P9pDAYSi6zg9sxQhDSd+1SWwFOLgbpvGmBFFBXAXQSLy26KwdCiLt6wgez12FmH+BqQ3hNIbJDUJxIGOiUa7xWy2p1nDTYnPTyCI09mje1gV9e3E3Yd98RRSwkDU42knIOv1cP5NthOH5ala1upJv5OKyhiA7fPhsdCGfL6BbqVTR26wPc+g97MN+PTayP3/qihb12fJY2cTgGpNmUvpFduztoRNJFTaDSX/USb13+bQHHbh/DdpIZrb3O97kIwVdbJZMrf7CyMiwgMtYJn3ByJYsFPOiw+AjsrMvBrGhpfiocK8HXumvLtekXlVQqsm0aXxfwmFTJjzfC1LhNhevM6Wytm5dZlwmHlxx5BVBzY+E5XF0zUYw5tdKPU1QMqCWJ9q7wn X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:DB6PR0801MB1734; X-Microsoft-Exchange-Diagnostics: 1;DB6PR0801MB1734;31:ejRn3qSvIgueYdecCnAt0jt89qluYo6Ezbq+ir+v3reOeKHLfyYkBp5c2xLAsTf+zKgXs6T3bWceJ0aSf3HfO2B2sCvNLSKC70EeGjxA9v410rAQPrn+K2Ty1TQi5aPfMg/b3kk71zrqtP7Prr/EM7HquHXlizY4R8c5E9RwwYa/TeK8J2hDqNFASWSrFUFO+kleaInktdLDFtb0hWcJ8Ok2OWoPiBQFn2NYEs/2m4dDNRaaeU17q98fxdLfx3BW;4:yjUpXMPW5dvJysfWTWqYKpKZG/FYk3xUqtJNwO1vytdU+vN86RYGB7x//rMpW8DcGVlY6BlbVX9BoYP/J6g6P1wIrTO5bNupGKrl+GYQgGgaiKJ+h+7kOLXh2QjC8zn3Db2bKT52PhmSQD1n2d413VNkDdtHL10B237RV4dn/h7QyBjGcKRkL300AhMutbja2ZVokBrIkFvDvd5s0srFdhEGolPSnFoCi2H6gWm9RnBPZEC+Loha3KF1eFJFO40juuRqbBG1oS7o1KEVKCM3vCQp+dZzWVY5OMiEezSkqqlEJ55T01Q90cJX3PWckvmex94lpKE06vGje7GHOycVtmeAICCrc+d3fErQ5MSztf07xaIGpKAiAxY+BBijVGwRpKRPJC5O+2RTmqwZ0s1FfeAb1DKAKxm4eo1O1tUl1Hp6yH997DqdPL7qCGz60GNHsnBQt+Ws5/vxDnay/kORgqBwY143tBMsp+T90ylH9pE= X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(65623756079841); X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(6040176)(601004)(2401047)(8121501046)(5005006)(10201501046)(3002001)(6043046)(6042046);SRVR:DB6PR0801MB1734;BCL:0;PCL:0;RULEID:;SRVR:DB6PR0801MB1734; X-Forefront-PRVS: 01068D0A20 X-Forefront-Antispam-Report: SFV:NSPM;SFS:(10019020)(4630300001)(6009001)(7916002)(189002)(199003)(229853001)(2351001)(110136003)(2950100002)(105586002)(5660300001)(6916009)(19580395003)(5003940100001)(77096005)(305945005)(189998001)(586003)(97736004)(6666003)(69596002)(50226002)(50466002)(19580405001)(33646002)(48376002)(3846002)(4326007)(6116002)(36756003)(76176999)(50986999)(101416001)(575784001)(86362001)(92566002)(2906002)(53416004)(42186005)(8676002)(81166006)(81156014)(7846002)(68736007)(106356001)(47776003)(66066001)(7736002)(1076002);DIR:OUT;SFP:1102;SCL:1;SRVR:DB6PR0801MB1734;H:dsafonov.sw.ru;FPR:;SPF:None;PTR:InfoNoRecords;MX:1;A:1;LANG:en; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;DB6PR0801MB1734;23:ObvOMKFpdIsd0VTi+DjgOkP9mtQtaGlr5pocV79?= =?us-ascii?Q?4jq7ufYGYsNjuDHWx3TxS4VLyzsktlDe7spo+SehE48q2JMC3Ze9BRT9fvKI?= =?us-ascii?Q?UrFZF8Dx8KVPjBEHOgCCCfMPOJi61+XgICY5R7hHqlUSom8Lq+zEqu0sG5yG?= =?us-ascii?Q?RcrXX8QTlstrjLVWoHKH9JMTvKK2lKURUFxeU2pMpOtxHQEHo8kvTGdiI+Zh?= =?us-ascii?Q?83o9rw8NAGD7lur3O2PDZZ7mdSyL1LbYdkZvXnn0E8qRZlcnL3Pa9LKJj2B9?= =?us-ascii?Q?Kd581DUs/lDTiTwDMBpRrzADW2DyyHbCN2EwTD+Np5rQn43A/ScG9XDyQBQE?= =?us-ascii?Q?CcFUZaaMfbsk5EhhpWgoLdXxAtvwruhn6PUsVLAsfOAv2rHdvFHZeUpEydB+?= =?us-ascii?Q?wipl/fkqkFaaF12w/lbuwn6vTDxn2kz95ye8v2tn+yJB6wg/+qzpDzqlBhZi?= =?us-ascii?Q?MGvAo08Eo9AZ/RZ+QqegvRuRwFBZTyw8tf8DiN5BN8jnZYPqbn0IgisPvgcn?= =?us-ascii?Q?uRmcdgMIK6mr4KMcdIokP+zumuddjtpdwwWjrzr0rNhP83WRWe1uFYqTjURY?= =?us-ascii?Q?BOW8V4gpFWJ4EO2E1WiJCsS2OMrmObB1bG9uQhzyqp45ftaQcxANoeLacNvH?= =?us-ascii?Q?iOiO3SsWVx0PbwdjFVeNdZFq0bS8HDAzsAM629TVRpQfwSc9WEvu/++NCXQs?= =?us-ascii?Q?GiQln6JTRa+sACIeEHGwCr87eG2lf5HMYWHbru8sjR5MiMS3Z06m2TuNktnd?= =?us-ascii?Q?q0h+qGTiLXP3joLYAVSYp9CKK5e6AU1/fb3lIny5S2zCocJgZMLlQ5rtyfGs?= =?us-ascii?Q?zpDDBX4VWoe0yDrWMhL3nEPvGZMfuy/8WyEUY9sHgrNKkMKPK0ZJYMPL3JBz?= =?us-ascii?Q?iGVZ0v2Mxs4H2LYAe0eBFpO2898yEKD8E80hBT0ZGmL/GQouyHBxrrOs5Nvr?= =?us-ascii?Q?3+atoV1QYwOtSKehU8OZiVwPn3a6wjedfkxbqJppw+veWVblSBp5S3ZZj834?= =?us-ascii?Q?H0P+GrrWRcH2kLPejnZrKsc/pzpaeZ8xnghPt+9ZuFUotAACDCkrmNIMNReP?= =?us-ascii?Q?yhK72rL4t5uKlUTH9Pk+ycN2y8zFbZl5FCYzWNRUoj3avFc1XK9y7PaKyk6n?= =?us-ascii?Q?SuagcIc2O05SqU1kNjua1NHMl503eSiZnmJPBwc+myE16Rej9fiuibjMYKEe?= =?us-ascii?Q?k5mzy/pOLKhH/NrrzBTWyVj+XNmvrhFwP77B39pHX0HXsrIYCjQVCNam/1w?= =?us-ascii?Q?=3D=3D?= X-Microsoft-Exchange-Diagnostics: 1;DB6PR0801MB1734;6:lBFKdfM8gxyqu9dVNGwtZFA+fglZnYIlQ33tckUlb6j98atyh+9YEugqF+VlHsNXvBwSjRyPQdRsmdcfyC2j69PXjL+Emptl+5oVPZ1IhiByEte0CYvHTv9RnxCy+lPo53DjzHpeX8vKEPgcBm0Lhy2h3PVerIhG8MvOWaf2DBC9olXV+VG7i9h5oMyU4sSrxu2LRzwcCtXjW5Xga+ickB6DmyfiX4BjB0vLIxkHkwAFV1IYMpgpcryStB4LJDpoV+K+sikfp2HwLiJpQoyH8x1bwR05mSr25ivnhLX+xFwxuWPuZkXT+WbkDX/IUc15mTjDf+EVfcq+0Bf119rwIA==;5:Qyir50HRnqRmRUtatsRnDbuHv8ODugHreUdFE6Op88zDA8q7NuHT/lAgp3fsaJ3hRbNbVOunO1gvebQiV6anpHeGhEvU7FaPK/tFypEIZB95CM4EkCadzYunwCCdYIXhga/zf+aRz2EezY71JmHS3IkszMM57MK01n9tAsITsxs=;24:Tm1pr4jkpUuPxppr3MZTkl5ctL2Kri3JEB2wwHiU7DCmnrXpjKXo8oCOVWUNR/DEfF2TnmkItpvKhaiPg5OiTyi+TJ6zXMxTgoWl4Yf4TFQ= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1;DB6PR0801MB1734;7:AXDT8K7oFPfInSsI/Uneewv4adHy++y1ymnxAE0j07r5vzkJ9fczN53eclosSP0Y9oNMQyj/DQdAJydoNFYYghI3oU4wbtpuzLdOpCIXf6l3cnVi++2gMfUaNsufiFljE1LrxbvlXB0JR42I1hDuOk3nO+OTLnKJGs+Bq7Ze8x9EBv3nXLRlElWhkdau1A2Ze8DlHktIAOUn5uor9sSmea8dN+Rccy8YTQN615U3iGBvaOMIVaEnKN+t2Y/G/drDqZ/Lk3OFTURQ1oyP4Y1lxWIqNBpTdRSRd3ktPi/RQrDXI1ptI1MMJMFC44soNl7mltWjbNISpH6JHZS5DApoDQqQ2uMyrx2BXtRE1VFwRvM=;20:9zUuW0PPZsDiPmc99Qnh4ec5X735cLXKfcEDxfLKQnNh5TO55x2DVyJdGohAfy8UJKNi5NVHOLxqczNXk+QVgHPNHJUSVPK4zR4cs64gtKf0LdcUj9HYr12/PBsK2KnmDVgla5S8KZisDWH041/D2sCdek8aUqfgT9v/dT2JYvQ= X-OriginatorOrg: virtuozzo.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 25 Oct 2016 15:53:12.8498 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB6PR0801MB1734 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Impact: cleanup I also switched usage of printk(KERNEL_,...) on pr_(...) and used pr_fmt() macro for "vDSO{32,64}: " prefix. Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Cc: Andy Lutomirski Cc: Oleg Nesterov Cc: linuxppc-dev@lists.ozlabs.org Cc: linux-mm@kvack.org Signed-off-by: Dmitry Safonov --- arch/powerpc/kernel/vdso.c | 352 ++------------------------------------ arch/powerpc/kernel/vdso_common.c | 221 ++++++++++++++++++++++++ 2 files changed, 234 insertions(+), 339 deletions(-) create mode 100644 arch/powerpc/kernel/vdso_common.c diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c index 278b9aa25a1c..8010a0d82049 100644 --- a/arch/powerpc/kernel/vdso.c +++ b/arch/powerpc/kernel/vdso.c @@ -51,13 +51,13 @@ #define VDSO_ALIGNMENT (1 << 16) static unsigned int vdso32_pages; -static void *vdso32_kbase; static struct page **vdso32_pagelist; unsigned long vdso32_sigtramp; unsigned long vdso32_rt_sigtramp; #ifdef CONFIG_VDSO32 extern char vdso32_start, vdso32_end; +static void *vdso32_kbase; #endif #ifdef CONFIG_PPC64 @@ -246,250 +246,16 @@ const char *arch_vma_name(struct vm_area_struct *vma) return NULL; } - - #ifdef CONFIG_VDSO32 -static void * __init find_section32(Elf32_Ehdr *ehdr, const char *secname, - unsigned long *size) -{ - Elf32_Shdr *sechdrs; - unsigned int i; - char *secnames; - - /* Grab section headers and strings so we can tell who is who */ - sechdrs = (void *)ehdr + ehdr->e_shoff; - secnames = (void *)ehdr + sechdrs[ehdr->e_shstrndx].sh_offset; - - /* Find the section they want */ - for (i = 1; i < ehdr->e_shnum; i++) { - if (strcmp(secnames+sechdrs[i].sh_name, secname) == 0) { - if (size) - *size = sechdrs[i].sh_size; - return (void *)ehdr + sechdrs[i].sh_offset; - } - } - *size = 0; - return NULL; -} - -static Elf32_Sym * __init find_symbol32(struct lib32_elfinfo *lib, - const char *symname) -{ - unsigned int i; - char name[MAX_SYMNAME], *c; - - for (i = 0; i < (lib->dynsymsize / sizeof(Elf32_Sym)); i++) { - if (lib->dynsym[i].st_name == 0) - continue; - strlcpy(name, lib->dynstr + lib->dynsym[i].st_name, - MAX_SYMNAME); - c = strchr(name, '@'); - if (c) - *c = 0; - if (strcmp(symname, name) == 0) - return &lib->dynsym[i]; - } - return NULL; -} - -/* Note that we assume the section is .text and the symbol is relative to - * the library base - */ -static unsigned long __init find_function32(struct lib32_elfinfo *lib, - const char *symname) -{ - Elf32_Sym *sym = find_symbol32(lib, symname); - - if (sym == NULL) { - printk(KERN_WARNING "vDSO32: function %s not found !\n", - symname); - return 0; - } - return sym->st_value - VDSO32_LBASE; -} - -static int __init vdso_do_func_patch32(struct lib32_elfinfo *v32, - const char *orig, const char *fix) -{ - Elf32_Sym *sym32_gen, *sym32_fix; - - sym32_gen = find_symbol32(v32, orig); - if (sym32_gen == NULL) { - printk(KERN_ERR "vDSO32: Can't find symbol %s !\n", orig); - return -1; - } - if (fix == NULL) { - sym32_gen->st_name = 0; - return 0; - } - sym32_fix = find_symbol32(v32, fix); - if (sym32_fix == NULL) { - printk(KERN_ERR "vDSO32: Can't find symbol %s !\n", fix); - return -1; - } - sym32_gen->st_value = sym32_fix->st_value; - sym32_gen->st_size = sym32_fix->st_size; - sym32_gen->st_info = sym32_fix->st_info; - sym32_gen->st_other = sym32_fix->st_other; - sym32_gen->st_shndx = sym32_fix->st_shndx; - - return 0; -} -#else /* !CONFIG_VDSO32 */ -static unsigned long __init find_function32(struct lib32_elfinfo *lib, - const char *symname) -{ - return 0; -} - -static int __init vdso_do_func_patch32(struct lib32_elfinfo *v32, - const char *orig, const char *fix) -{ - return 0; -} +#include "vdso_common.c" #endif /* CONFIG_VDSO32 */ - #ifdef CONFIG_PPC64 - -static void * __init find_section64(Elf64_Ehdr *ehdr, const char *secname, - unsigned long *size) -{ - Elf64_Shdr *sechdrs; - unsigned int i; - char *secnames; - - /* Grab section headers and strings so we can tell who is who */ - sechdrs = (void *)ehdr + ehdr->e_shoff; - secnames = (void *)ehdr + sechdrs[ehdr->e_shstrndx].sh_offset; - - /* Find the section they want */ - for (i = 1; i < ehdr->e_shnum; i++) { - if (strcmp(secnames+sechdrs[i].sh_name, secname) == 0) { - if (size) - *size = sechdrs[i].sh_size; - return (void *)ehdr + sechdrs[i].sh_offset; - } - } - if (size) - *size = 0; - return NULL; -} - -static Elf64_Sym * __init find_symbol64(struct lib64_elfinfo *lib, - const char *symname) -{ - unsigned int i; - char name[MAX_SYMNAME], *c; - - for (i = 0; i < (lib->dynsymsize / sizeof(Elf64_Sym)); i++) { - if (lib->dynsym[i].st_name == 0) - continue; - strlcpy(name, lib->dynstr + lib->dynsym[i].st_name, - MAX_SYMNAME); - c = strchr(name, '@'); - if (c) - *c = 0; - if (strcmp(symname, name) == 0) - return &lib->dynsym[i]; - } - return NULL; -} - -/* Note that we assume the section is .text and the symbol is relative to - * the library base - */ -static unsigned long __init find_function64(struct lib64_elfinfo *lib, - const char *symname) -{ - Elf64_Sym *sym = find_symbol64(lib, symname); - - if (sym == NULL) { - printk(KERN_WARNING "vDSO64: function %s not found !\n", - symname); - return 0; - } -#ifdef VDS64_HAS_DESCRIPTORS - return *((u64 *)(vdso64_kbase + sym->st_value - VDSO64_LBASE)) - - VDSO64_LBASE; -#else - return sym->st_value - VDSO64_LBASE; -#endif -} - -static int __init vdso_do_func_patch64(struct lib64_elfinfo *v64, - const char *orig, const char *fix) -{ - Elf64_Sym *sym64_gen, *sym64_fix; - - sym64_gen = find_symbol64(v64, orig); - if (sym64_gen == NULL) { - printk(KERN_ERR "vDSO64: Can't find symbol %s !\n", orig); - return -1; - } - if (fix == NULL) { - sym64_gen->st_name = 0; - return 0; - } - sym64_fix = find_symbol64(v64, fix); - if (sym64_fix == NULL) { - printk(KERN_ERR "vDSO64: Can't find symbol %s !\n", fix); - return -1; - } - sym64_gen->st_value = sym64_fix->st_value; - sym64_gen->st_size = sym64_fix->st_size; - sym64_gen->st_info = sym64_fix->st_info; - sym64_gen->st_other = sym64_fix->st_other; - sym64_gen->st_shndx = sym64_fix->st_shndx; - - return 0; -} - +#define BITS 64 +#include "vdso_common.c" #endif /* CONFIG_PPC64 */ -static __init int vdso_do_find_sections(struct lib32_elfinfo *v32, - struct lib64_elfinfo *v64) -{ - void *sect; - - /* - * Locate symbol tables & text section - */ - -#ifdef CONFIG_VDSO32 - v32->dynsym = find_section32(v32->hdr, ".dynsym", &v32->dynsymsize); - v32->dynstr = find_section32(v32->hdr, ".dynstr", NULL); - if (v32->dynsym == NULL || v32->dynstr == NULL) { - printk(KERN_ERR "vDSO32: required symbol section not found\n"); - return -1; - } - sect = find_section32(v32->hdr, ".text", NULL); - if (sect == NULL) { - printk(KERN_ERR "vDSO32: the .text section was not found\n"); - return -1; - } - v32->text = sect - vdso32_kbase; -#endif - -#ifdef CONFIG_PPC64 - v64->dynsym = find_section64(v64->hdr, ".dynsym", &v64->dynsymsize); - v64->dynstr = find_section64(v64->hdr, ".dynstr", NULL); - if (v64->dynsym == NULL || v64->dynstr == NULL) { - printk(KERN_ERR "vDSO64: required symbol section not found\n"); - return -1; - } - sect = find_section64(v64->hdr, ".text", NULL); - if (sect == NULL) { - printk(KERN_ERR "vDSO64: the .text section was not found\n"); - return -1; - } - v64->text = sect - vdso64_kbase; -#endif /* CONFIG_PPC64 */ - - return 0; -} - static __init void vdso_setup_trampolines(struct lib32_elfinfo *v32, struct lib64_elfinfo *v64) { @@ -500,99 +266,10 @@ static __init void vdso_setup_trampolines(struct lib32_elfinfo *v32, #ifdef CONFIG_PPC64 vdso64_rt_sigtramp = find_function64(v64, "__kernel_sigtramp_rt64"); #endif +#ifdef CONFIG_VDSO32 vdso32_sigtramp = find_function32(v32, "__kernel_sigtramp32"); vdso32_rt_sigtramp = find_function32(v32, "__kernel_sigtramp_rt32"); -} - -static __init int vdso_fixup_datapage(struct lib32_elfinfo *v32, - struct lib64_elfinfo *v64) -{ -#ifdef CONFIG_VDSO32 - Elf32_Sym *sym32; -#endif -#ifdef CONFIG_PPC64 - Elf64_Sym *sym64; - - sym64 = find_symbol64(v64, "__kernel_datapage_offset"); - if (sym64 == NULL) { - printk(KERN_ERR "vDSO64: Can't find symbol " - "__kernel_datapage_offset !\n"); - return -1; - } - *((int *)(vdso64_kbase + sym64->st_value - VDSO64_LBASE)) = - (vdso64_pages << PAGE_SHIFT) - - (sym64->st_value - VDSO64_LBASE); -#endif /* CONFIG_PPC64 */ - -#ifdef CONFIG_VDSO32 - sym32 = find_symbol32(v32, "__kernel_datapage_offset"); - if (sym32 == NULL) { - printk(KERN_ERR "vDSO32: Can't find symbol " - "__kernel_datapage_offset !\n"); - return -1; - } - *((int *)(vdso32_kbase + (sym32->st_value - VDSO32_LBASE))) = - (vdso32_pages << PAGE_SHIFT) - - (sym32->st_value - VDSO32_LBASE); #endif - - return 0; -} - - -static __init int vdso_fixup_features(struct lib32_elfinfo *v32, - struct lib64_elfinfo *v64) -{ - unsigned long size; - void *start; - -#ifdef CONFIG_PPC64 - start = find_section64(v64->hdr, "__ftr_fixup", &size); - if (start) - do_feature_fixups(cur_cpu_spec->cpu_features, - start, start + size); - - start = find_section64(v64->hdr, "__mmu_ftr_fixup", &size); - if (start) - do_feature_fixups(cur_cpu_spec->mmu_features, - start, start + size); - - start = find_section64(v64->hdr, "__fw_ftr_fixup", &size); - if (start) - do_feature_fixups(powerpc_firmware_features, - start, start + size); - - start = find_section64(v64->hdr, "__lwsync_fixup", &size); - if (start) - do_lwsync_fixups(cur_cpu_spec->cpu_features, - start, start + size); -#endif /* CONFIG_PPC64 */ - -#ifdef CONFIG_VDSO32 - start = find_section32(v32->hdr, "__ftr_fixup", &size); - if (start) - do_feature_fixups(cur_cpu_spec->cpu_features, - start, start + size); - - start = find_section32(v32->hdr, "__mmu_ftr_fixup", &size); - if (start) - do_feature_fixups(cur_cpu_spec->mmu_features, - start, start + size); - -#ifdef CONFIG_PPC64 - start = find_section32(v32->hdr, "__fw_ftr_fixup", &size); - if (start) - do_feature_fixups(powerpc_firmware_features, - start, start + size); -#endif /* CONFIG_PPC64 */ - - start = find_section32(v32->hdr, "__lwsync_fixup", &size); - if (start) - do_lwsync_fixups(cur_cpu_spec->cpu_features, - start, start + size); -#endif - - return 0; } static __init int vdso_fixup_alt_funcs(struct lib32_elfinfo *v32, @@ -616,7 +293,9 @@ static __init int vdso_fixup_alt_funcs(struct lib32_elfinfo *v32, * It would be easy to do, but doesn't seem to be necessary, * patching the OPD symbol is enough. */ +#ifdef CONFIG_VDSO32 vdso_do_func_patch32(v32, patch->gen_name, patch->fix_name); +#endif #ifdef CONFIG_PPC64 vdso_do_func_patch64(v64, patch->gen_name, patch->fix_name); #endif /* CONFIG_PPC64 */ @@ -625,24 +304,19 @@ static __init int vdso_fixup_alt_funcs(struct lib32_elfinfo *v32, return 0; } - static __init int vdso_setup(void) { struct lib32_elfinfo v32; struct lib64_elfinfo v64; - v32.hdr = vdso32_kbase; -#ifdef CONFIG_PPC64 - v64.hdr = vdso64_kbase; -#endif - if (vdso_do_find_sections(&v32, &v64)) - return -1; - - if (vdso_fixup_datapage(&v32, &v64)) +#ifdef CONFIG_VDSO32 + if (vdso_setup32(&v32)) return -1; - - if (vdso_fixup_features(&v32, &v64)) +#endif +#ifdef CONFIG_PPC64 + if (vdso_setup64(&v64)) return -1; +#endif if (vdso_fixup_alt_funcs(&v32, &v64)) return -1; diff --git a/arch/powerpc/kernel/vdso_common.c b/arch/powerpc/kernel/vdso_common.c new file mode 100644 index 000000000000..ac25d66134fb --- /dev/null +++ b/arch/powerpc/kernel/vdso_common.c @@ -0,0 +1,221 @@ +#ifndef BITS +#define BITS 32 +#endif + +#undef Elf_Ehdr +#undef Elf_Sym +#undef Elf_Shdr + +#define _CONCAT3(a, b, c) a ## b ## c +#define CONCAT3(a, b, c) _CONCAT3(a, b, c) +#define Elf_Ehdr CONCAT3(Elf, BITS, _Ehdr) +#define Elf_Sym CONCAT3(Elf, BITS, _Sym) +#define Elf_Shdr CONCAT3(Elf, BITS, _Shdr) +#define VDSO_LBASE CONCAT3(VDSO, BITS, _LBASE) +#define vdso_kbase CONCAT3(vdso, BITS, _kbase) +#define vdso_pages CONCAT3(vdso, BITS, _pages) + +#undef pr_fmt +#define pr_fmt(fmt) "vDSO" __stringify(BITS) ": " fmt + +#define lib_elfinfo CONCAT3(lib, BITS, _elfinfo) + +#define find_section CONCAT3(find_section, BITS,) +static void * __init find_section(Elf_Ehdr *ehdr, const char *secname, + unsigned long *size) +{ + Elf_Shdr *sechdrs; + unsigned int i; + char *secnames; + + /* Grab section headers and strings so we can tell who is who */ + sechdrs = (void *)ehdr + ehdr->e_shoff; + secnames = (void *)ehdr + sechdrs[ehdr->e_shstrndx].sh_offset; + + /* Find the section they want */ + for (i = 1; i < ehdr->e_shnum; i++) { + if (strcmp(secnames+sechdrs[i].sh_name, secname) == 0) { + if (size) + *size = sechdrs[i].sh_size; + return (void *)ehdr + sechdrs[i].sh_offset; + } + } + if (size) + *size = 0; + return NULL; +} + +#define find_symbol CONCAT3(find_symbol, BITS,) +static Elf_Sym * __init find_symbol(struct lib_elfinfo *lib, + const char *symname) +{ + unsigned int i; + char name[MAX_SYMNAME], *c; + + for (i = 0; i < (lib->dynsymsize / sizeof(Elf_Sym)); i++) { + if (lib->dynsym[i].st_name == 0) + continue; + strlcpy(name, lib->dynstr + lib->dynsym[i].st_name, + MAX_SYMNAME); + c = strchr(name, '@'); + if (c) + *c = 0; + if (strcmp(symname, name) == 0) + return &lib->dynsym[i]; + } + return NULL; +} + +/* + * Note that we assume the section is .text and the symbol is relative to + * the library base. + */ +#define find_function CONCAT3(find_function, BITS,) +static unsigned long __init find_function(struct lib_elfinfo *lib, + const char *symname) +{ + Elf_Sym *sym = find_symbol(lib, symname); + + if (sym == NULL) { + pr_warn("function %s not found !\n", symname); + return 0; + } +#if defined(VDS64_HAS_DESCRIPTORS) && (BITS == 64) + return *((u64 *)(vdso64_kbase + sym->st_value - VDSO64_LBASE)) - + VDSO64_LBASE; +#else + return sym->st_value - VDSO_LBASE; +#endif +} + +#define vdso_do_func_patch CONCAT3(vdso_do_func_patch, BITS,) +static int __init vdso_do_func_patch(struct lib_elfinfo *v, + const char *orig, const char *fix) +{ + Elf_Sym *sym_gen, *sym_fix; + + sym_gen = find_symbol(v, orig); + if (sym_gen == NULL) { + pr_err("Can't find symbol %s !\n", orig); + return -1; + } + if (fix == NULL) { + sym_gen->st_name = 0; + return 0; + } + sym_fix = find_symbol(v, fix); + if (sym_fix == NULL) { + pr_err("Can't find symbol %s !\n", fix); + return -1; + } + sym_gen->st_value = sym_fix->st_value; + sym_gen->st_size = sym_fix->st_size; + sym_gen->st_info = sym_fix->st_info; + sym_gen->st_other = sym_fix->st_other; + sym_gen->st_shndx = sym_fix->st_shndx; + + return 0; +} + +#define vdso_do_find_sections CONCAT3(vdso_do_find_sections, BITS,) +static __init int vdso_do_find_sections(struct lib_elfinfo *v) +{ + void *sect; + + /* + * Locate symbol tables & text section + */ + v->dynsym = find_section(v->hdr, ".dynsym", &v->dynsymsize); + v->dynstr = find_section(v->hdr, ".dynstr", NULL); + if (v->dynsym == NULL || v->dynstr == NULL) { + pr_err("required symbol section not found\n"); + return -1; + } + + sect = find_section(v->hdr, ".text", NULL); + if (sect == NULL) { + pr_err("the .text section was not found\n"); + return -1; + } + v->text = sect - vdso_kbase; + + return 0; +} + +#define vdso_fixup_datapage CONCAT3(vdso_fixup_datapage, BITS,) +static __init int vdso_fixup_datapage(struct lib_elfinfo *v) +{ + Elf_Sym *sym = find_symbol(v, "__kernel_datapage_offset"); + + if (sym == NULL) { + pr_err("Can't find symbol __kernel_datapage_offset !\n"); + return -1; + } + *((int *)(vdso_kbase + sym->st_value - VDSO_LBASE)) = + (vdso_pages << PAGE_SHIFT) - (sym->st_value - VDSO_LBASE); + + return 0; +} + +#define vdso_fixup_features CONCAT3(vdso_fixup_features, BITS,) +static __init int vdso_fixup_features(struct lib_elfinfo *v) +{ + unsigned long size; + void *start; + + start = find_section(v->hdr, "__ftr_fixup", &size); + if (start) + do_feature_fixups(cur_cpu_spec->cpu_features, + start, start + size); + + start = find_section(v->hdr, "__mmu_ftr_fixup", &size); + if (start) + do_feature_fixups(cur_cpu_spec->mmu_features, + start, start + size); + +#ifdef CONFIG_PPC64 + start = find_section(v->hdr, "__fw_ftr_fixup", &size); + if (start) + do_feature_fixups(powerpc_firmware_features, + start, start + size); +#endif /* CONFIG_PPC64 */ + + start = find_section(v->hdr, "__lwsync_fixup", &size); + if (start) + do_lwsync_fixups(cur_cpu_spec->cpu_features, + start, start + size); + + return 0; +} + +#define vdso_setup CONCAT3(vdso_setup, BITS,) +static __init int vdso_setup(struct lib_elfinfo *v) +{ + v->hdr = vdso_kbase; + + if (vdso_do_find_sections(v)) + return -1; + if (vdso_fixup_datapage(v)) + return -1; + if (vdso_fixup_features(v)) + return -1; + return 0; +} + + +#undef find_section +#undef find_symbol +#undef find_function +#undef vdso_do_func_patch +#undef vdso_do_find_sections +#undef vdso_fixup_datapage +#undef vdso_fixup_features +#undef vdso_setup + +#undef VDSO_LBASE +#undef vdso_kbase +#undef vdso_pages +#undef lib_elfinfo +#undef BITS +#undef _CONCAT3 +#undef CONCAT3 -- 2.10.0 From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pf0-f198.google.com (mail-pf0-f198.google.com [209.85.192.198]) by kanga.kvack.org (Postfix) with ESMTP id BDC296B0276 for ; Tue, 25 Oct 2016 11:53:16 -0400 (EDT) Received: by mail-pf0-f198.google.com with SMTP id n85so3496085pfi.4 for ; Tue, 25 Oct 2016 08:53:16 -0700 (PDT) Received: from EUR02-VE1-obe.outbound.protection.outlook.com (mail-eopbgr20122.outbound.protection.outlook.com. [40.107.2.122]) by mx.google.com with ESMTPS id nw5si17771895pab.314.2016.10.25.08.53.15 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 25 Oct 2016 08:53:15 -0700 (PDT) From: Dmitry Safonov Subject: [PATCH 3/7] powerpc/vdso: separate common code in vdso_common Date: Tue, 25 Oct 2016 18:51:02 +0300 Message-ID: <20161025155106.29946-4-dsafonov@virtuozzo.com> In-Reply-To: <20161025155106.29946-1-dsafonov@virtuozzo.com> References: <20161025155106.29946-1-dsafonov@virtuozzo.com> MIME-Version: 1.0 Content-Type: text/plain Sender: owner-linux-mm@kvack.org List-ID: To: linux-kernel@vger.kernel.org Cc: 0x7f454c46@gmail.com, Dmitry Safonov , Benjamin Herrenschmidt , Paul Mackerras , Michael Ellerman , Andy Lutomirski , Oleg Nesterov , linuxppc-dev@lists.ozlabs.org, linux-mm@kvack.org Impact: cleanup I also switched usage of printk(KERNEL_,...) on pr_(...) and used pr_fmt() macro for "vDSO{32,64}: " prefix. Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Cc: Andy Lutomirski Cc: Oleg Nesterov Cc: linuxppc-dev@lists.ozlabs.org Cc: linux-mm@kvack.org Signed-off-by: Dmitry Safonov --- arch/powerpc/kernel/vdso.c | 352 ++------------------------------------ arch/powerpc/kernel/vdso_common.c | 221 ++++++++++++++++++++++++ 2 files changed, 234 insertions(+), 339 deletions(-) create mode 100644 arch/powerpc/kernel/vdso_common.c diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c index 278b9aa25a1c..8010a0d82049 100644 --- a/arch/powerpc/kernel/vdso.c +++ b/arch/powerpc/kernel/vdso.c @@ -51,13 +51,13 @@ #define VDSO_ALIGNMENT (1 << 16) static unsigned int vdso32_pages; -static void *vdso32_kbase; static struct page **vdso32_pagelist; unsigned long vdso32_sigtramp; unsigned long vdso32_rt_sigtramp; #ifdef CONFIG_VDSO32 extern char vdso32_start, vdso32_end; +static void *vdso32_kbase; #endif #ifdef CONFIG_PPC64 @@ -246,250 +246,16 @@ const char *arch_vma_name(struct vm_area_struct *vma) return NULL; } - - #ifdef CONFIG_VDSO32 -static void * __init find_section32(Elf32_Ehdr *ehdr, const char *secname, - unsigned long *size) -{ - Elf32_Shdr *sechdrs; - unsigned int i; - char *secnames; - - /* Grab section headers and strings so we can tell who is who */ - sechdrs = (void *)ehdr + ehdr->e_shoff; - secnames = (void *)ehdr + sechdrs[ehdr->e_shstrndx].sh_offset; - - /* Find the section they want */ - for (i = 1; i < ehdr->e_shnum; i++) { - if (strcmp(secnames+sechdrs[i].sh_name, secname) == 0) { - if (size) - *size = sechdrs[i].sh_size; - return (void *)ehdr + sechdrs[i].sh_offset; - } - } - *size = 0; - return NULL; -} - -static Elf32_Sym * __init find_symbol32(struct lib32_elfinfo *lib, - const char *symname) -{ - unsigned int i; - char name[MAX_SYMNAME], *c; - - for (i = 0; i < (lib->dynsymsize / sizeof(Elf32_Sym)); i++) { - if (lib->dynsym[i].st_name == 0) - continue; - strlcpy(name, lib->dynstr + lib->dynsym[i].st_name, - MAX_SYMNAME); - c = strchr(name, '@'); - if (c) - *c = 0; - if (strcmp(symname, name) == 0) - return &lib->dynsym[i]; - } - return NULL; -} - -/* Note that we assume the section is .text and the symbol is relative to - * the library base - */ -static unsigned long __init find_function32(struct lib32_elfinfo *lib, - const char *symname) -{ - Elf32_Sym *sym = find_symbol32(lib, symname); - - if (sym == NULL) { - printk(KERN_WARNING "vDSO32: function %s not found !\n", - symname); - return 0; - } - return sym->st_value - VDSO32_LBASE; -} - -static int __init vdso_do_func_patch32(struct lib32_elfinfo *v32, - const char *orig, const char *fix) -{ - Elf32_Sym *sym32_gen, *sym32_fix; - - sym32_gen = find_symbol32(v32, orig); - if (sym32_gen == NULL) { - printk(KERN_ERR "vDSO32: Can't find symbol %s !\n", orig); - return -1; - } - if (fix == NULL) { - sym32_gen->st_name = 0; - return 0; - } - sym32_fix = find_symbol32(v32, fix); - if (sym32_fix == NULL) { - printk(KERN_ERR "vDSO32: Can't find symbol %s !\n", fix); - return -1; - } - sym32_gen->st_value = sym32_fix->st_value; - sym32_gen->st_size = sym32_fix->st_size; - sym32_gen->st_info = sym32_fix->st_info; - sym32_gen->st_other = sym32_fix->st_other; - sym32_gen->st_shndx = sym32_fix->st_shndx; - - return 0; -} -#else /* !CONFIG_VDSO32 */ -static unsigned long __init find_function32(struct lib32_elfinfo *lib, - const char *symname) -{ - return 0; -} - -static int __init vdso_do_func_patch32(struct lib32_elfinfo *v32, - const char *orig, const char *fix) -{ - return 0; -} +#include "vdso_common.c" #endif /* CONFIG_VDSO32 */ - #ifdef CONFIG_PPC64 - -static void * __init find_section64(Elf64_Ehdr *ehdr, const char *secname, - unsigned long *size) -{ - Elf64_Shdr *sechdrs; - unsigned int i; - char *secnames; - - /* Grab section headers and strings so we can tell who is who */ - sechdrs = (void *)ehdr + ehdr->e_shoff; - secnames = (void *)ehdr + sechdrs[ehdr->e_shstrndx].sh_offset; - - /* Find the section they want */ - for (i = 1; i < ehdr->e_shnum; i++) { - if (strcmp(secnames+sechdrs[i].sh_name, secname) == 0) { - if (size) - *size = sechdrs[i].sh_size; - return (void *)ehdr + sechdrs[i].sh_offset; - } - } - if (size) - *size = 0; - return NULL; -} - -static Elf64_Sym * __init find_symbol64(struct lib64_elfinfo *lib, - const char *symname) -{ - unsigned int i; - char name[MAX_SYMNAME], *c; - - for (i = 0; i < (lib->dynsymsize / sizeof(Elf64_Sym)); i++) { - if (lib->dynsym[i].st_name == 0) - continue; - strlcpy(name, lib->dynstr + lib->dynsym[i].st_name, - MAX_SYMNAME); - c = strchr(name, '@'); - if (c) - *c = 0; - if (strcmp(symname, name) == 0) - return &lib->dynsym[i]; - } - return NULL; -} - -/* Note that we assume the section is .text and the symbol is relative to - * the library base - */ -static unsigned long __init find_function64(struct lib64_elfinfo *lib, - const char *symname) -{ - Elf64_Sym *sym = find_symbol64(lib, symname); - - if (sym == NULL) { - printk(KERN_WARNING "vDSO64: function %s not found !\n", - symname); - return 0; - } -#ifdef VDS64_HAS_DESCRIPTORS - return *((u64 *)(vdso64_kbase + sym->st_value - VDSO64_LBASE)) - - VDSO64_LBASE; -#else - return sym->st_value - VDSO64_LBASE; -#endif -} - -static int __init vdso_do_func_patch64(struct lib64_elfinfo *v64, - const char *orig, const char *fix) -{ - Elf64_Sym *sym64_gen, *sym64_fix; - - sym64_gen = find_symbol64(v64, orig); - if (sym64_gen == NULL) { - printk(KERN_ERR "vDSO64: Can't find symbol %s !\n", orig); - return -1; - } - if (fix == NULL) { - sym64_gen->st_name = 0; - return 0; - } - sym64_fix = find_symbol64(v64, fix); - if (sym64_fix == NULL) { - printk(KERN_ERR "vDSO64: Can't find symbol %s !\n", fix); - return -1; - } - sym64_gen->st_value = sym64_fix->st_value; - sym64_gen->st_size = sym64_fix->st_size; - sym64_gen->st_info = sym64_fix->st_info; - sym64_gen->st_other = sym64_fix->st_other; - sym64_gen->st_shndx = sym64_fix->st_shndx; - - return 0; -} - +#define BITS 64 +#include "vdso_common.c" #endif /* CONFIG_PPC64 */ -static __init int vdso_do_find_sections(struct lib32_elfinfo *v32, - struct lib64_elfinfo *v64) -{ - void *sect; - - /* - * Locate symbol tables & text section - */ - -#ifdef CONFIG_VDSO32 - v32->dynsym = find_section32(v32->hdr, ".dynsym", &v32->dynsymsize); - v32->dynstr = find_section32(v32->hdr, ".dynstr", NULL); - if (v32->dynsym == NULL || v32->dynstr == NULL) { - printk(KERN_ERR "vDSO32: required symbol section not found\n"); - return -1; - } - sect = find_section32(v32->hdr, ".text", NULL); - if (sect == NULL) { - printk(KERN_ERR "vDSO32: the .text section was not found\n"); - return -1; - } - v32->text = sect - vdso32_kbase; -#endif - -#ifdef CONFIG_PPC64 - v64->dynsym = find_section64(v64->hdr, ".dynsym", &v64->dynsymsize); - v64->dynstr = find_section64(v64->hdr, ".dynstr", NULL); - if (v64->dynsym == NULL || v64->dynstr == NULL) { - printk(KERN_ERR "vDSO64: required symbol section not found\n"); - return -1; - } - sect = find_section64(v64->hdr, ".text", NULL); - if (sect == NULL) { - printk(KERN_ERR "vDSO64: the .text section was not found\n"); - return -1; - } - v64->text = sect - vdso64_kbase; -#endif /* CONFIG_PPC64 */ - - return 0; -} - static __init void vdso_setup_trampolines(struct lib32_elfinfo *v32, struct lib64_elfinfo *v64) { @@ -500,99 +266,10 @@ static __init void vdso_setup_trampolines(struct lib32_elfinfo *v32, #ifdef CONFIG_PPC64 vdso64_rt_sigtramp = find_function64(v64, "__kernel_sigtramp_rt64"); #endif +#ifdef CONFIG_VDSO32 vdso32_sigtramp = find_function32(v32, "__kernel_sigtramp32"); vdso32_rt_sigtramp = find_function32(v32, "__kernel_sigtramp_rt32"); -} - -static __init int vdso_fixup_datapage(struct lib32_elfinfo *v32, - struct lib64_elfinfo *v64) -{ -#ifdef CONFIG_VDSO32 - Elf32_Sym *sym32; -#endif -#ifdef CONFIG_PPC64 - Elf64_Sym *sym64; - - sym64 = find_symbol64(v64, "__kernel_datapage_offset"); - if (sym64 == NULL) { - printk(KERN_ERR "vDSO64: Can't find symbol " - "__kernel_datapage_offset !\n"); - return -1; - } - *((int *)(vdso64_kbase + sym64->st_value - VDSO64_LBASE)) = - (vdso64_pages << PAGE_SHIFT) - - (sym64->st_value - VDSO64_LBASE); -#endif /* CONFIG_PPC64 */ - -#ifdef CONFIG_VDSO32 - sym32 = find_symbol32(v32, "__kernel_datapage_offset"); - if (sym32 == NULL) { - printk(KERN_ERR "vDSO32: Can't find symbol " - "__kernel_datapage_offset !\n"); - return -1; - } - *((int *)(vdso32_kbase + (sym32->st_value - VDSO32_LBASE))) = - (vdso32_pages << PAGE_SHIFT) - - (sym32->st_value - VDSO32_LBASE); #endif - - return 0; -} - - -static __init int vdso_fixup_features(struct lib32_elfinfo *v32, - struct lib64_elfinfo *v64) -{ - unsigned long size; - void *start; - -#ifdef CONFIG_PPC64 - start = find_section64(v64->hdr, "__ftr_fixup", &size); - if (start) - do_feature_fixups(cur_cpu_spec->cpu_features, - start, start + size); - - start = find_section64(v64->hdr, "__mmu_ftr_fixup", &size); - if (start) - do_feature_fixups(cur_cpu_spec->mmu_features, - start, start + size); - - start = find_section64(v64->hdr, "__fw_ftr_fixup", &size); - if (start) - do_feature_fixups(powerpc_firmware_features, - start, start + size); - - start = find_section64(v64->hdr, "__lwsync_fixup", &size); - if (start) - do_lwsync_fixups(cur_cpu_spec->cpu_features, - start, start + size); -#endif /* CONFIG_PPC64 */ - -#ifdef CONFIG_VDSO32 - start = find_section32(v32->hdr, "__ftr_fixup", &size); - if (start) - do_feature_fixups(cur_cpu_spec->cpu_features, - start, start + size); - - start = find_section32(v32->hdr, "__mmu_ftr_fixup", &size); - if (start) - do_feature_fixups(cur_cpu_spec->mmu_features, - start, start + size); - -#ifdef CONFIG_PPC64 - start = find_section32(v32->hdr, "__fw_ftr_fixup", &size); - if (start) - do_feature_fixups(powerpc_firmware_features, - start, start + size); -#endif /* CONFIG_PPC64 */ - - start = find_section32(v32->hdr, "__lwsync_fixup", &size); - if (start) - do_lwsync_fixups(cur_cpu_spec->cpu_features, - start, start + size); -#endif - - return 0; } static __init int vdso_fixup_alt_funcs(struct lib32_elfinfo *v32, @@ -616,7 +293,9 @@ static __init int vdso_fixup_alt_funcs(struct lib32_elfinfo *v32, * It would be easy to do, but doesn't seem to be necessary, * patching the OPD symbol is enough. */ +#ifdef CONFIG_VDSO32 vdso_do_func_patch32(v32, patch->gen_name, patch->fix_name); +#endif #ifdef CONFIG_PPC64 vdso_do_func_patch64(v64, patch->gen_name, patch->fix_name); #endif /* CONFIG_PPC64 */ @@ -625,24 +304,19 @@ static __init int vdso_fixup_alt_funcs(struct lib32_elfinfo *v32, return 0; } - static __init int vdso_setup(void) { struct lib32_elfinfo v32; struct lib64_elfinfo v64; - v32.hdr = vdso32_kbase; -#ifdef CONFIG_PPC64 - v64.hdr = vdso64_kbase; -#endif - if (vdso_do_find_sections(&v32, &v64)) - return -1; - - if (vdso_fixup_datapage(&v32, &v64)) +#ifdef CONFIG_VDSO32 + if (vdso_setup32(&v32)) return -1; - - if (vdso_fixup_features(&v32, &v64)) +#endif +#ifdef CONFIG_PPC64 + if (vdso_setup64(&v64)) return -1; +#endif if (vdso_fixup_alt_funcs(&v32, &v64)) return -1; diff --git a/arch/powerpc/kernel/vdso_common.c b/arch/powerpc/kernel/vdso_common.c new file mode 100644 index 000000000000..ac25d66134fb --- /dev/null +++ b/arch/powerpc/kernel/vdso_common.c @@ -0,0 +1,221 @@ +#ifndef BITS +#define BITS 32 +#endif + +#undef Elf_Ehdr +#undef Elf_Sym +#undef Elf_Shdr + +#define _CONCAT3(a, b, c) a ## b ## c +#define CONCAT3(a, b, c) _CONCAT3(a, b, c) +#define Elf_Ehdr CONCAT3(Elf, BITS, _Ehdr) +#define Elf_Sym CONCAT3(Elf, BITS, _Sym) +#define Elf_Shdr CONCAT3(Elf, BITS, _Shdr) +#define VDSO_LBASE CONCAT3(VDSO, BITS, _LBASE) +#define vdso_kbase CONCAT3(vdso, BITS, _kbase) +#define vdso_pages CONCAT3(vdso, BITS, _pages) + +#undef pr_fmt +#define pr_fmt(fmt) "vDSO" __stringify(BITS) ": " fmt + +#define lib_elfinfo CONCAT3(lib, BITS, _elfinfo) + +#define find_section CONCAT3(find_section, BITS,) +static void * __init find_section(Elf_Ehdr *ehdr, const char *secname, + unsigned long *size) +{ + Elf_Shdr *sechdrs; + unsigned int i; + char *secnames; + + /* Grab section headers and strings so we can tell who is who */ + sechdrs = (void *)ehdr + ehdr->e_shoff; + secnames = (void *)ehdr + sechdrs[ehdr->e_shstrndx].sh_offset; + + /* Find the section they want */ + for (i = 1; i < ehdr->e_shnum; i++) { + if (strcmp(secnames+sechdrs[i].sh_name, secname) == 0) { + if (size) + *size = sechdrs[i].sh_size; + return (void *)ehdr + sechdrs[i].sh_offset; + } + } + if (size) + *size = 0; + return NULL; +} + +#define find_symbol CONCAT3(find_symbol, BITS,) +static Elf_Sym * __init find_symbol(struct lib_elfinfo *lib, + const char *symname) +{ + unsigned int i; + char name[MAX_SYMNAME], *c; + + for (i = 0; i < (lib->dynsymsize / sizeof(Elf_Sym)); i++) { + if (lib->dynsym[i].st_name == 0) + continue; + strlcpy(name, lib->dynstr + lib->dynsym[i].st_name, + MAX_SYMNAME); + c = strchr(name, '@'); + if (c) + *c = 0; + if (strcmp(symname, name) == 0) + return &lib->dynsym[i]; + } + return NULL; +} + +/* + * Note that we assume the section is .text and the symbol is relative to + * the library base. + */ +#define find_function CONCAT3(find_function, BITS,) +static unsigned long __init find_function(struct lib_elfinfo *lib, + const char *symname) +{ + Elf_Sym *sym = find_symbol(lib, symname); + + if (sym == NULL) { + pr_warn("function %s not found !\n", symname); + return 0; + } +#if defined(VDS64_HAS_DESCRIPTORS) && (BITS == 64) + return *((u64 *)(vdso64_kbase + sym->st_value - VDSO64_LBASE)) - + VDSO64_LBASE; +#else + return sym->st_value - VDSO_LBASE; +#endif +} + +#define vdso_do_func_patch CONCAT3(vdso_do_func_patch, BITS,) +static int __init vdso_do_func_patch(struct lib_elfinfo *v, + const char *orig, const char *fix) +{ + Elf_Sym *sym_gen, *sym_fix; + + sym_gen = find_symbol(v, orig); + if (sym_gen == NULL) { + pr_err("Can't find symbol %s !\n", orig); + return -1; + } + if (fix == NULL) { + sym_gen->st_name = 0; + return 0; + } + sym_fix = find_symbol(v, fix); + if (sym_fix == NULL) { + pr_err("Can't find symbol %s !\n", fix); + return -1; + } + sym_gen->st_value = sym_fix->st_value; + sym_gen->st_size = sym_fix->st_size; + sym_gen->st_info = sym_fix->st_info; + sym_gen->st_other = sym_fix->st_other; + sym_gen->st_shndx = sym_fix->st_shndx; + + return 0; +} + +#define vdso_do_find_sections CONCAT3(vdso_do_find_sections, BITS,) +static __init int vdso_do_find_sections(struct lib_elfinfo *v) +{ + void *sect; + + /* + * Locate symbol tables & text section + */ + v->dynsym = find_section(v->hdr, ".dynsym", &v->dynsymsize); + v->dynstr = find_section(v->hdr, ".dynstr", NULL); + if (v->dynsym == NULL || v->dynstr == NULL) { + pr_err("required symbol section not found\n"); + return -1; + } + + sect = find_section(v->hdr, ".text", NULL); + if (sect == NULL) { + pr_err("the .text section was not found\n"); + return -1; + } + v->text = sect - vdso_kbase; + + return 0; +} + +#define vdso_fixup_datapage CONCAT3(vdso_fixup_datapage, BITS,) +static __init int vdso_fixup_datapage(struct lib_elfinfo *v) +{ + Elf_Sym *sym = find_symbol(v, "__kernel_datapage_offset"); + + if (sym == NULL) { + pr_err("Can't find symbol __kernel_datapage_offset !\n"); + return -1; + } + *((int *)(vdso_kbase + sym->st_value - VDSO_LBASE)) = + (vdso_pages << PAGE_SHIFT) - (sym->st_value - VDSO_LBASE); + + return 0; +} + +#define vdso_fixup_features CONCAT3(vdso_fixup_features, BITS,) +static __init int vdso_fixup_features(struct lib_elfinfo *v) +{ + unsigned long size; + void *start; + + start = find_section(v->hdr, "__ftr_fixup", &size); + if (start) + do_feature_fixups(cur_cpu_spec->cpu_features, + start, start + size); + + start = find_section(v->hdr, "__mmu_ftr_fixup", &size); + if (start) + do_feature_fixups(cur_cpu_spec->mmu_features, + start, start + size); + +#ifdef CONFIG_PPC64 + start = find_section(v->hdr, "__fw_ftr_fixup", &size); + if (start) + do_feature_fixups(powerpc_firmware_features, + start, start + size); +#endif /* CONFIG_PPC64 */ + + start = find_section(v->hdr, "__lwsync_fixup", &size); + if (start) + do_lwsync_fixups(cur_cpu_spec->cpu_features, + start, start + size); + + return 0; +} + +#define vdso_setup CONCAT3(vdso_setup, BITS,) +static __init int vdso_setup(struct lib_elfinfo *v) +{ + v->hdr = vdso_kbase; + + if (vdso_do_find_sections(v)) + return -1; + if (vdso_fixup_datapage(v)) + return -1; + if (vdso_fixup_features(v)) + return -1; + return 0; +} + + +#undef find_section +#undef find_symbol +#undef find_function +#undef vdso_do_func_patch +#undef vdso_do_find_sections +#undef vdso_fixup_datapage +#undef vdso_fixup_features +#undef vdso_setup + +#undef VDSO_LBASE +#undef vdso_kbase +#undef vdso_pages +#undef lib_elfinfo +#undef BITS +#undef _CONCAT3 +#undef CONCAT3 -- 2.10.0 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@kvack.org. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: email@kvack.org