Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S936602AbcJ0Rq2 (ORCPT ); Thu, 27 Oct 2016 13:46:28 -0400 Received: from mail-he1eur01on0122.outbound.protection.outlook.com ([104.47.0.122]:51405 "EHLO EUR01-HE1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S934200AbcJ0RqZ (ORCPT ); Thu, 27 Oct 2016 13:46:25 -0400 Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=dsafonov@virtuozzo.com; From: Dmitry Safonov To: CC: Dmitry Safonov , Benjamin Herrenschmidt , Paul Mackerras , "Michael Ellerman" , Andy Lutomirski , "Oleg Nesterov" , , Subject: [PATCHv3 3/8] powerpc/vdso: separate common code in vdso_common Date: Thu, 27 Oct 2016 20:09:43 +0300 Message-ID: <20161027170948.8279-4-dsafonov@virtuozzo.com> X-Mailer: git-send-email 2.10.1 In-Reply-To: <20161027170948.8279-1-dsafonov@virtuozzo.com> References: <20161027170948.8279-1-dsafonov@virtuozzo.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [195.214.232.10] X-ClientProxiedBy: AM5PR0601CA0041.eurprd06.prod.outlook.com (10.173.86.155) To DB6PR0801MB1735.eurprd08.prod.outlook.com (10.169.226.150) X-MS-Office365-Filtering-Correlation-Id: 6954caf0-1419-4413-a3ee-08d3fe8c5703 X-Microsoft-Exchange-Diagnostics: 1;DB6PR0801MB1735;2:0ZSOufWcrjQ8DL3bUr0C81uVzFF6dxN3BOGtznGPcikYh0nkVclhMs9D6GBtwts9t9ThnvW4Y3JvibS5JQg9/qPzr4cXXy2wWQP74Q6FsAt4kQBGCrtaSXSyPXjcHbSBRrR0V51kGe0njk1PUF5lHjXu+ab1rWzY8WqEz8aYluVFNhmC3vGXQs2eyD5Npv8ddbjCv9ybvHYGHfcMooZz5w==;3:A8sUdRdwztFt9zNNgiFKRuU8YRQpPFPGErXEeY9J+8h6CHyZVcbVDAIKy2G3HInmO4SVTzZ6X6GR8YALqulxUugvVGnMwMD3DyMQnRsBeLdWmFcP7yqD+mn0TMfkdDrTGLNwNSmmJH4Awli46Jb9Gg== X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:DB6PR0801MB1735; X-Microsoft-Exchange-Diagnostics: 1;DB6PR0801MB1735;25:xCGyfeSXI6WNuk/MDLoPoZgsfupClRUeyvLMqMc4ZR5AxFm8SotULGcFpRPTi87uSTDtzi6wk8VKTT/8QPyRej/aqJUTS0NFKm0dlOBKJhMD6goHMsQWPJgXaCGguOUfzU8fQ/LYq/SV6AgLqXpyMQdpVVDk/a7cMYqjHlUboynLOhvIyJYtNyRqt60KDzaZjk/UIsZH4UHTOoHZ5LLgVU1+PmFpehPs0lN3QMpHW6AVsFtJR9Owudu1pRBYkzCzKitmEC99o2avZKdZXPcDqgitAmQJYKjXnjnuaEtTbX36O28x0Gm2nttRB27FmlVF+rRviwdsLoyHZU+vLAZMiU7d/w4VWA/e+0QsYIHTkVIMb4az3JbNW7AzrHNzyjq05aLNUCSW5tmBGpumv2CATUxTcCsmJzneXAe0pS38h5b6oIrgF49c2Zaga12q1maGj9WwLbNPpXNkJH/2cgYN4kkiGxF2BC3g/34ZhY/8pM8lFaHIqa235cyE6ZuqU1eN65AAILKhxo/pB3LtIhMjds5KmUIl6XNZFaq/gB32FesUU5+LX/jbBCZCAQ21wwriauarkFmr33NyZ8CGOTa9gJB5TWJINxgxNN8Z8PEQGyOcZucE2iQCLeWZKIZNaBwBVw9lAR3T899JsmAwAcs2qIbamIDFWhAq4Qf82awyCfUEK9K29hwb1Xf8ygbqbQuhQIGJhtH/IbzEz8o8U/454w== X-Microsoft-Exchange-Diagnostics: 1;DB6PR0801MB1735;31:U3zgJ0kaxSPeGwOXNoHKYGhPbyG11X1SxGrYxAzwuRowxvl77dNdMcTRIprOI5xTBGFsgMHvE2ydsxj3c9lc57NSz3ed4idA42PyRAJdBtGDKnPZWeNraKUyQtEfLhL/ovMu+ItbIzes3CYRa/MO9JuMVuzLVm1lJ+9Nv7moy9zLtR0hcvQIGXotz0ehYDykZduIm3maJqGFMyzgxvnuElNiGAiF2TPgAnuWVweq39ALjaIOeiLMVFI9yN6so1Rg;4:aBrM25iQdKmLX9u3t+fo8VA74DMfnQEYgFinrA1wjfAo1a4xLBTJTyFrut20YFyPMLHDvq3qObedoXLVZt+TceY62Ql8mSDOjI6ztbpI5eTCqag3aQdi1LWawJjTSIqUjAsLG3koNB2mGXUtkvagQitTljv7aDW5KPOeZ9y3HoRvTSsmtMG8MXQSf5SgoFPxs4jWOcQlEfEYHKPPB/s6GwOs4r2gAMu+el2qdIwyr4iFWmBrP14UKywL/09z6VnMcxqmLIsP/88LvniRf2NK8E7wAo04Ewiaq6wUOJKrIL+25XKfVkoNX/+GCNlJDRx83R13/YkiUqqmDyQkCY70G2+hjZEHvNkDdj1hn2t5ku/E9qvp96n/meJAcW/zRNjPoEhSB9bBTNZ7TEpHmWSMz9y3inQPb9SuuDJvmYgT5mnS0FObN+xPC7g2c//hXfZgmAe+1wzLoUiJWFfDxeiMvro3dvXvGOudB5Ek1F+/740= 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)(6042046)(6043046);SRVR:DB6PR0801MB1735;BCL:0;PCL:0;RULEID:;SRVR:DB6PR0801MB1735; X-Forefront-PRVS: 0108A997B2 X-Forefront-Antispam-Report: SFV:NSPM;SFS:(10019020)(4630300001)(6009001)(7916002)(199003)(189002)(7846002)(81156014)(97736004)(5003940100001)(305945005)(7736002)(6666003)(81166006)(66066001)(8676002)(92566002)(101416001)(110136003)(2950100002)(69596002)(68736007)(48376002)(5660300001)(77096005)(50466002)(6916009)(47776003)(50986999)(76176999)(586003)(189998001)(2906002)(3846002)(1076002)(6116002)(106356001)(33646002)(105586002)(36756003)(19580395003)(42186005)(229853001)(50226002)(53416004)(19580405001)(2351001)(86362001)(575784001)(4326007)(341764005);DIR:OUT;SFP:1102;SCL:1;SRVR:DB6PR0801MB1735;H:dsafonov.sw.ru;FPR:;SPF:None;PTR:InfoNoRecords;A:1;MX:1;LANG:en; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;DB6PR0801MB1735;23:t/Hj6K/Y8zaAAn9CR/8oI/9GcqKJtXG3flg2WNT?= =?us-ascii?Q?/JD3rsoC6yUq3kfHOWUshP2zVMANBzrPBXgu+EsJxqkbcSTSJZXhkuFuc6Vl?= =?us-ascii?Q?ZmOzuxrW9Pv7LnpfWlszWdA+0TPwnXkOW7dZvCOxh0u6sUaZy4Fc1D0eAJ/B?= =?us-ascii?Q?AE2cPS4z1ps+Cp3j6MN8xUbnMkTRl/S+ZzBNn/ZjIEiktKpLDjcAQSUf/eB5?= =?us-ascii?Q?93cnNmwE88VZSrDVcJTq5RuuPtnJuxnkxvImwceNKaktrHuMVzKcBpt2nuA8?= =?us-ascii?Q?8eO90DLSmoUIySA3BfFzBle6sMwsV+NZpzLGDx4jYD+25ala9bP9mAYfZGfR?= =?us-ascii?Q?Ezw+yvTntnGhwKqk3ME1V1UDYXa/NSV81MdADwQ/k5n9/baxkmUcUzJ7UkHS?= =?us-ascii?Q?bmTiIQflyUm2Eeg5sNLTGZ9jjOOSN5fdup3dZ2CAhpOy3nU5yQ9F7GSRCKSJ?= =?us-ascii?Q?BwZYO68I17+4nlPTDIOcD6RCBSPU4AYYMAkk1RcbZNBFqCQ7aZejPVpafCcv?= =?us-ascii?Q?kf4G2UMbpag179JlBOfinavGfI/iqoHKZ8PbFeP7YPXatwIXneJ6TzgYhMyB?= =?us-ascii?Q?QTxRhefiFqBP75Qh2CYORcvBAbWoZI9qcMNASR14qSXqVLGiDB0d08MqRsvu?= =?us-ascii?Q?h/hxTfCrK/Ua2GrOqNjl/YjSGIKPcE2zVKzEJ5qnVdJWcASmsoVr6sEhrBjq?= =?us-ascii?Q?G5z0cD7joXbydR+/Ygc0zb3iw5A//8b4R+Uo4zk0BbOI+QkT+zn9JXTt94tg?= =?us-ascii?Q?TBNl0+aLswWS3BdM3qBcU0lLZPU1oU+62843tV50qA3UKQ0zGeoK9fwTeXLi?= =?us-ascii?Q?kp5FdAFQqcYi1v5zzdX6nidUoSOvUa4x9LNgJhNvzRNnO7Vrrd/mzLt2/pqo?= =?us-ascii?Q?R5hMIs2TzVQ1/W6ejMB72ilPONhhTkP7puRIGa+ej8W4QYyBXX55nSqToaie?= =?us-ascii?Q?xObdM+4cM4noCv1ir+CS7AmxIGb4OYlJVrSvoZffcEcJRLeQgFk2hQHkfC2w?= =?us-ascii?Q?9TjUfk7BIG3uKXzhLHaRlSYbZYONDdk7vJmsBbxsk3qag/LMjBOWYY3QIRFk?= =?us-ascii?Q?/GiwLlToWqiOVTR+JSgqdIGphZS3a6NnzMk/8r5vOmlNgacqsbwKg1XWLfDx?= =?us-ascii?Q?Aa3L2TolJMnWsYx5aeHqrz+AMVCypcbBEtnrFVB2psEksGt9zLTTmrLdG7KZ?= =?us-ascii?Q?4XxGTGQHdoYzesWbGgKwcC3T0gJ4VSKkYOqIB1e03hSgpZBm1RkA/gP68enV?= =?us-ascii?Q?g29kCXOM25CIrJnuyqFc=3D?= X-Microsoft-Exchange-Diagnostics: 1;DB6PR0801MB1735;6:9OMCWNreurzx6yGw+iuq+2LqaAmLffCxQ5CjqYoEsWMHr99MaWXpQs/jEnSe+fpG0HamjBOrVHLRtarRA0d6Z9sRU07zfHy+jD3rdQSDOcBzijwDtzvyWnFaoWAtQxGwXB89Ytb8N6+7mULOyy28mporzGdzld2iCaV1W/Hd39M71Z6JaDZRGkSkywhZlv4RvdJicK2L1G4g/5KzE2EaJG9sJZUvH6r9ePLT0Wp2T0jpZI2izD6RF8Qn1wYYILonUrXrfJkIp2NAWZrUHs2Njm8CDSksQVMdj6R0J4Rq4+ZhHgUmkuPzvVDKzhX7NnDWLQ3HLwzZZhGEZyhWKg9MGw==;5:KALHWODrpV/62tonH1p0ZIoOUdBIxj+TPAVZ4OVqaAVrPMM1z6na9QE0ZTe14igDq8n++tZX3fIY22ZTKn5Yy57ZgqaiIWlodoIvhQblVR7mlB3vkEC6O24wNea+5B3OBCtdBzQmSyQtcmqcuCfh2A==;24:ksysfkPJ2nB+LsjvF2mGSYdQivWIYaJwfY93uZZtuXWE05AOirAt4ksDtp/cdac+m7+zdW3jJT+wfrzD2s51OYY5O2pC7yhM+wStLYppbpM= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1;DB6PR0801MB1735;7:i7mzngSgcsmhdIxC0EH5Udi/qqLz5vCdMypw+kBNGoY8F68I4CgXBSwDz8hPwS0jST5M3qy9C2r+lK1Ph760GoiP2Kch/vuFZgxmMpWSGLinZs4pvBpZ9btISZ8QBhZhKteKW/AxiD4O7ufjt6Yr/Ubgdu1YbaJUgqY4LZMwgibzQXWv8voorGUhDBjUd52Fllw8+WicgYPHbYso/FCneDvxDFLjMvaNSyqr/dYeuRxgeu0RW77zAOpAaBdqzmh6St1jW3UJDkXjtkuLKbrzjDHN8g8d080ZGh/0QC5hU/DgJ5BTwcsnFDPWtFGnVsT0XoW969YSt3Z6SkAotXa7BDzSEywvad/cqXr/a3UX0Bk=;20:LbRiBkenfL4KFSgi9/eOd6hoE3V6p8/UPhXk/OprZ1oJW12VTyUj8se2UjVMIYH9/wmIXddlTwq2briQptf+d/ysVdDgt7GA87AlSs6FEhOZb67MbnyQZNnN40T+1vamAeo8jexQnDY9fVAw0giknBfR4AGYkODQ6PCIcqb9Yuc= X-OriginatorOrg: virtuozzo.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 27 Oct 2016 17:11:49.0118 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB6PR0801MB1735 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 17854 Lines: 672 Impact: cleanup There are common functions for handeling 32-bit and 64-bit vDSO ELF files: find_section{32,64}, find_symbol{32,64}, find_function{32,64}, vdso_do_func_patch{32,64}, vdso_do_find_sections{32,64}, vdso_fixup_datapag{32,64}, vdso_fixup_features{32,64}, vdso_setup{32,64} which all do the same work with the only difference is using structures for 32 or 64 bit ELF. Let's combine them into common code, reducing copy'n'paste code. Small changes: 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.1