From patchwork Tue Dec 15 09:44:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Ivanov X-Patchwork-Id: 1416365 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.infradead.org (client-ip=2001:8b0:10b:1231::1; helo=merlin.infradead.org; envelope-from=linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=cambridgegreys.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; secure) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=merlin.20170209 header.b=XHnt8lVq; dkim-atps=neutral Received: from merlin.infradead.org (merlin.infradead.org [IPv6:2001:8b0:10b:1231::1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4CwCz95YCJz9s0b for ; Tue, 15 Dec 2020 20:44:53 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=sRpjcYO2KWCsG2RjZZag5tvVROUWOgx6J0GzPPEO/CU=; b=XHnt8lVqC393j6juh7bFbLEcz f4t3wdk2x8MVL5HkmXc5RoOmKA7sYQm9IfhyZxnYd/YDmiLSNlT5Yqtb9jVLlPMpusRyy3+HdUD6M 0P9smR9d+16iOTLUhoLDO0b/ADuyHs7HH5Ku2+PaZWM9KXn5p5nMo43trOSTOBbNWV7qSFEJm1HAu IGr3k4MEI++xd08QExxcCr1d+pr/0csHloUFy5qh5GYG0MEcAVtnGK//kmeuSu+APr0h8RK48CTTE a5XDBXP1+htZ/gH93TaudU7CXHV3JVvDmwp73vA3dxrXvdc4qT/JUU9KEwoHLFXaYG+D7boHNO+3T Ejqm6MXUQ==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kp6sq-0004bd-OU; Tue, 15 Dec 2020 09:44:40 +0000 Received: from ivanoab7.miniserver.com ([37.128.132.42] helo=www.kot-begemot.co.uk) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kp6sn-0004aR-RD for linux-um@lists.infradead.org; Tue, 15 Dec 2020 09:44:39 +0000 Received: from tun252.jain.kot-begemot.co.uk ([192.168.18.6] helo=jain.kot-begemot.co.uk) by www.kot-begemot.co.uk with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1kp6sm-0001Mr-VE; Tue, 15 Dec 2020 09:44:37 +0000 Received: from jain.kot-begemot.co.uk ([192.168.3.3]) by jain.kot-begemot.co.uk with esmtp (Exim 4.92) (envelope-from ) id 1kp6sk-0000J4-3k; Tue, 15 Dec 2020 09:44:35 +0000 From: anton.ivanov@cambridgegreys.com To: linux-um@lists.infradead.org Subject: [PATCH v6 4/4] um: allow the use of glibc functions instead of builtins Date: Tue, 15 Dec 2020 09:44:26 +0000 Message-Id: <20201215094426.1117-4-anton.ivanov@cambridgegreys.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20201215094426.1117-1-anton.ivanov@cambridgegreys.com> References: <20201215094426.1117-1-anton.ivanov@cambridgegreys.com> MIME-Version: 1.0 X-Spam-Score: -1.0 X-Spam-Score: -1.0 X-Clacks-Overhead: GNU Terry Pratchett X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201215_044437_944443_2736868B X-CRM114-Status: GOOD ( 17.97 ) X-Spam-Score: 0.4 (/) X-Spam-Report: SpamAssassin version 3.4.4 on merlin.infradead.org summary: Content analysis details: (0.4 points) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 SPF_NONE SPF: sender does not publish an SPF Record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.4 KHOP_HELO_FCRDNS Relay HELO differs from its IP's reverse DNS X-BeenThere: linux-um@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: richard@nod.at, Anton Ivanov Sender: "linux-um" Errors-To: linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Anton Ivanov The UML kernel runs as a normal userspace process and can use most of glibc string.h functionality instead of built-ins. At present, when using built-ins, it is also limited to their unoptimized versions, because it does not have the runtime code patching present on x86 via apply_alternatives() Allowing the use of glibc for memcpy, memmove, etc provides 1-5% boost on common file io as measured by cat and dd. The size of the linux executable is also reduced by ~10KBytes. It is possible to turn this on/off via the kernel configuration. Signed-off-by: Anton Ivanov --- arch/um/Kconfig | 10 ++++++ arch/um/include/asm/string.h | 70 ++++++++++++++++++++++++++++++++++++ arch/um/os-Linux/user_syms.c | 29 ++++++++++++--- arch/x86/um/Makefile | 6 ++-- 4 files changed, 109 insertions(+), 6 deletions(-) create mode 100644 arch/um/include/asm/string.h diff --git a/arch/um/Kconfig b/arch/um/Kconfig index 6d707122e8d8..9e4503066552 100644 --- a/arch/um/Kconfig +++ b/arch/um/Kconfig @@ -192,6 +192,16 @@ config UML_TIME_TRAVEL_SUPPORT It is safe to say Y, but you probably don't need this. +config UML_USE_BUILT_IN_STRINGS + bool + default N + prompt "Use kernel memcpy, memmove, etc" + help + UML can use the kernel built in memcpy, memmove, etc functions + or use the glibc equivalents instead. + The glibc equivalents are slightly faster and will result in a + slightly smaller executable when linking UML dynamically. + endmenu source "arch/um/drivers/Kconfig" diff --git a/arch/um/include/asm/string.h b/arch/um/include/asm/string.h new file mode 100644 index 000000000000..a65bbbe83083 --- /dev/null +++ b/arch/um/include/asm/string.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * Copyright (C) 2020 Cambridge Greys Ltd. + * Copyright (C) 2020 Red Hat Inc. + */ + +#ifndef __ASM_UM_STRING_H +#define __ASM_UM_STRING_H + +#ifndef CONFIG_UML_USE_BUILT_IN_STRINGS + +#include + +#define __HAVE_ARCH_STRCPY +extern char *strcpy(char *dest, const char *src); +#define __HAVE_ARCH_STRNCPY +extern char *strncpy(char *dest, const char *src, size_t n); +#define __HAVE_ARCH_STRCAT +extern char *strcat(char *dest, const char *src); +#define __HAVE_ARCH_STRNCAT +extern char *strncat(char *dest, const char *src, size_t n); +#define __HAVE_ARCH_STRCMP +extern int strcmp(const char *s1, const char *s2); +#define __HAVE_ARCH_STRNCMP +extern int strncmp(const char *s1, const char *s2, size_t n); +#define __HAVE_ARCH_STRCHR +extern char *strchr(const char *s, int c); +#define __HAVE_ARCH_STRLEN +extern size_t strlen(const char *s); +#define __HAVE_ARCH_MEMCPY +extern void *memcpy(void *dest, const void *src, size_t n); +#define __HAVE_ARCH_MEMMOVE +extern void *memmove(void *dest, const void *src, size_t n); +#define __HAVE_ARCH_MEMCHR +extern void *memchr(const void *s, int c, size_t n); +#define __HAVE_ARCH_STRNLEN +extern size_t strnlen(const char *s, size_t maxlen); +#define __HAVE_ARCH_STRSTR +extern char *strstr(const char *haystack, const char *needle); +#define __HAVE_ARCH_MEMSET +extern void *memset(void *s, int c, size_t n); +#define __HAVE_ARCH_STRNCASECMP +extern int strncasecmp(const char *s1, const char *s2, size_t n); +#define __HAVE_ARCH_STRCASECMP +extern int strcasecmp(const char *s1, const char *s2); +#define __HAVE_ARCH_STRCHRNUL +extern char *strchrnul(const char *s, int c); +#define __HAVE_ARCH_STRRCH +extern char *strchrnul(const char *s, int c); +#define __HAVE_ARCH_STRSPN +extern size_t strspn(const char *s, const char *accept); +#define __HAVE_ARCH_STRCSPN +extern size_t strcspn(const char *s, const char *reject); +#define __HAVE_ARCH_STRPBRK +extern char *strpbrk(const char *s, const char *accept); +#define __HAVE_ARCH_STRSEP +extern char *strsep(char **stringp, const char *delim); +#define __HAVE_ARCH_MEMCMP +extern int memcmp(const void *s1, const void *s2, size_t n); +#define __HAVE_ARCH_BCMP +extern int bcmp(const void *s1, const void *s2, size_t n); + +#else + +#include <../../x86/include/asm/string.h> + +#endif + +#endif /* __ASM_UM_STRING_H */ diff --git a/arch/um/os-Linux/user_syms.c b/arch/um/os-Linux/user_syms.c index 715594fe5719..2e24c9000316 100644 --- a/arch/um/os-Linux/user_syms.c +++ b/arch/um/os-Linux/user_syms.c @@ -9,6 +9,7 @@ * add an EXPORT for the glibc one. */ +#ifdef CONFIG_UML_USE_BUILT_IN_STRINGS #undef strlen #undef strstr #undef memcpy @@ -17,6 +18,7 @@ extern size_t strlen(const char *); extern void *memmove(void *, const void *, size_t); extern void *memset(void *, int, size_t); +#endif extern int printf(const char *, ...); /* If it's not defined, the export is included in lib/string.c.*/ @@ -24,14 +26,33 @@ extern int printf(const char *, ...); EXPORT_SYMBOL(strstr); #endif -#ifndef __x86_64__ -extern void *memcpy(void *, const void *, size_t); -EXPORT_SYMBOL(memcpy); +#ifndef CONFIG_UML_USE_BUILT_IN_STRINGS +/* These all come from glibc */ +EXPORT_SYMBOL(printf); +EXPORT_SYMBOL(strcpy); +EXPORT_SYMBOL(strncpy); +EXPORT_SYMBOL(strcat); +EXPORT_SYMBOL(strncat); +EXPORT_SYMBOL(strcmp); +EXPORT_SYMBOL(strncmp); +EXPORT_SYMBOL(strchr); +EXPORT_SYMBOL(strlen); +EXPORT_SYMBOL(memchr); +EXPORT_SYMBOL(strnlen); +EXPORT_SYMBOL(strncasecmp); +EXPORT_SYMBOL(strcasecmp); +EXPORT_SYMBOL(strchrnul); +EXPORT_SYMBOL(strcspn); +EXPORT_SYMBOL(strpbrk); +EXPORT_SYMBOL(strsep); +EXPORT_SYMBOL(memcmp); +EXPORT_SYMBOL(bcmp); + #endif +EXPORT_SYMBOL(memcpy); EXPORT_SYMBOL(memmove); EXPORT_SYMBOL(memset); -EXPORT_SYMBOL(printf); /* Here, instead, I can provide a fake prototype. Yes, someone cares: genksyms. * However, the modules will use the CRC defined *here*, no matter if it is diff --git a/arch/x86/um/Makefile b/arch/x86/um/Makefile index 77f70b969d14..453ea23a9770 100644 --- a/arch/x86/um/Makefile +++ b/arch/x86/um/Makefile @@ -20,14 +20,16 @@ ifeq ($(CONFIG_X86_32),y) obj-y += checksum_32.o syscalls_32.o obj-$(CONFIG_ELF_CORE) += elfcore.o -subarch-y = ../lib/string_32.o ../lib/atomic64_32.o ../lib/atomic64_cx8_32.o +subarch-y = ../lib/atomic64_32.o ../lib/atomic64_cx8_32.o subarch-y += ../kernel/sys_ia32.o +subarch-$(CONFIG_UML_USE_BUILT_IN_STRINGS) += ../lib/string_32.o else obj-y += syscalls_64.o vdso/ -subarch-y = ../lib/csum-partial_64.o ../lib/memcpy_64.o ../entry/thunk_64.o +subarch-y = ../lib/csum-partial_64.o ../entry/thunk_64.o +subarch-$(CONFIG_UML_USE_BUILT_IN_STRINGS) += ../lib/memcpy_64.o endif