From patchwork Thu Nov 12 10:12:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Ivanov X-Patchwork-Id: 1398814 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=2UODQTCJ; 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 4CWy8r6tm2z9s1l for ; Thu, 12 Nov 2020 21:13:00 +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: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:In-Reply-To:References:List-Owner; bh=xhKzNS3A0gnWs/2eVQLZ6Fxzob3lTqw/uzbbRW/QK6I=; b=2UODQTCJUCWdGx0IwxFQneGYFb RtyrwoN2KZ5/A2lT96Y/MLB7XtSsKe5/Zyo4mdY8x9LHqey77vYmKqAmGmdzdJYbVwXqybyp5r0Ob Bnq9o5gXwoE0jrjitGwHbg8QZv704AAPqXftYcyFh+Zct8I1+E0O9ne+xJIkhGZIBAJivOeQHmVao fx+r0VjQsvClSrQzamfQklx4AwJU9ji6P1oBOSJ6cmXqnGsqB/bnSuz/Q2KFH03UxlsdLc3gkpiFp ahUB5vuMi3whdrgVCp/GdCNTvVo5Tb2gLet+F8TZyL0THuHF7eVdl4up1EPKvn8VmVpTvlcIXTnoz oiNANIpg==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kd9b6-0001Iq-9w; Thu, 12 Nov 2020 10:12:56 +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 1kd9b3-0001IK-EC for linux-um@lists.infradead.org; Thu, 12 Nov 2020 10:12:54 +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 1kd9b0-0007N5-Nz; Thu, 12 Nov 2020 10:12:51 +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 1kd9ax-0000Zt-MF; Thu, 12 Nov 2020 10:12:49 +0000 From: anton.ivanov@cambridgegreys.com To: linux-um@lists.infradead.org Subject: [PATCH v2] um: allow the use of glibc functions instead of builtins Date: Thu, 12 Nov 2020 10:12:44 +0000 Message-Id: <20201112101244.2148-1-anton.ivanov@cambridgegreys.com> X-Mailer: git-send-email 2.20.1 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-20201112_051253_585565_92171974 X-CRM114-Status: GOOD ( 18.29 ) 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_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 SPF_NONE SPF: sender 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 | 27 +++++++++++++- arch/x86/um/Makefile | 6 ++-- 4 files changed, 110 insertions(+), 3 deletions(-) create mode 100644 arch/um/include/asm/string.h diff --git a/arch/um/Kconfig b/arch/um/Kconfig index 4b799fad8b48..ec2802ded9d1 100644 --- a/arch/um/Kconfig +++ b/arch/um/Kconfig @@ -189,6 +189,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..ac16890e0867 --- /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 + +#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..9da980a89a9f 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,7 +26,7 @@ extern int printf(const char *, ...); EXPORT_SYMBOL(strstr); #endif -#ifndef __x86_64__ +#if !defined(__x86_64__) || !defined(CONFIG_UML_USE_BUILT_IN_STRINGS) extern void *memcpy(void *, const void *, size_t); EXPORT_SYMBOL(memcpy); #endif @@ -33,6 +35,29 @@ EXPORT_SYMBOL(memmove); EXPORT_SYMBOL(memset); EXPORT_SYMBOL(printf); +#ifndef CONFIG_UML_USE_BUILT_IN_STRINGS +/* These all come from glibc */ +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 + /* 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 * good; so the versions of these symbols will always match 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