From patchwork Mon Mar 30 14:45:33 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hajime Tazaki X-Patchwork-Id: 1263977 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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=VOf3yU0w; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=Xg7FkvV8; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (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 48rZzT1DfTz9sP7 for ; Tue, 31 Mar 2020 01:46:45 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.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=yTAd1AVVDfiJxV8jShqVb+6l32c8JPu2Fp4oYyVaEEM=; b=VOf3yU0wde3gfq T0p9C0JKVtiVntj1O6YKEBWk/nx5FKTZM1CuFKd5wAgG61zaeDmdmYcndkXOy8irE0xkBEd7VKOyG f8KaRWmyj5Exp4J9GHi9QHuCRCUVy//KDAnUNbQciBNmpwSfYXNKHfSvVjFntrtatCzhufk6nJlD9 Q5U+in9ch5yLlVySpcr4SxOinIS6BVJDT8X1Vplgh9bndJVaqKboLDAMRW9pE9pbyA+Bu0KTdlINp QNFg9YGbz8SHr7r6U1vo9IrmAdtoWNPF4ewbl74R+ZoeNLjnlMvhIS0amPh/EHbiMEgu+05B7VcVc PsYmV/LhpWjIxVWMHmtQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvgT-0004S8-Im; Mon, 30 Mar 2020 14:46:37 +0000 Received: from mail-pj1-x1043.google.com ([2607:f8b0:4864:20::1043]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvgQ-0004RM-8K for linux-um@lists.infradead.org; Mon, 30 Mar 2020 14:46:35 +0000 Received: by mail-pj1-x1043.google.com with SMTP id kx8so7412707pjb.5 for ; Mon, 30 Mar 2020 07:46:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=BBNV7mCHl8ARll4ecc1sVG2Qhvtdfex91jBAy7FeD5E=; b=Xg7FkvV8uCD5UbuTMsSG7MouNqxGXREwGo2CzFyIyiHdAtB7sXqI3tOWVghjtUEYh0 aXs+eWoOseSRSsH8JiqitZJK8BWXHmUUiLOCkuDb98VU3Phrph1MBzuTmTuW6DQsnW+E GruUp/0qfCRyDEsZ7tNIhn5CwEzk3RhKUl4sSSZYIOmzXcvrQcnlQMp78LfHMoJgypw1 823cbowoiSUn/YmTyfTQhqIUOUMM03B9YXiNZb/Y8kJply0edBKDKPirKYjqlSFI24q1 Z63y+/vmE+nTUoUwxQJKEeO9u7H/Mg3U6ITyXYlSHKvFhld8eynK6CJ9z8eW2eAEV1T7 dlnw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=BBNV7mCHl8ARll4ecc1sVG2Qhvtdfex91jBAy7FeD5E=; b=UZDfv3JKCMaxWzQKdk5NOfxb0caz+MV9cwl3KvjswnOadTz7bzbF0sLdsQ3b1P/2Rt sxJIUzFgbwmvNDXKk9TDcYn+E0JQrmIk5aItL9tg3QA2Ug6k4etWCnIOThON1aLxbK/G l4CcuDaVUa3iXyc0AwH7vBmC3sy5vsVS0fswYWiYgDRK5g1zPORqBaokPZBi2tW4uCRl yuXZwqesKwiC7tRUtqnww8QlWa5i3D9XOMxxJ+uIxGnBSgezV+pe4inAnzNbNWn+/BOt nXW1Nd7gpAM3a8CrK9smRpkLeb40nLrbhu5tjSYFqReI3wFEkulugyJ8xnwPBPHCkksv FW8Q== X-Gm-Message-State: ANhLgQ1/T5+CHshtJFisqYmBmpVLOvPdDGjBBhWCMOwWGS5k8otkRbKv s/9ZqxCsycisf4LzR6Ms1iM= X-Google-Smtp-Source: ADFU+vuzOLitTeL+ZQiw6hgGpxorkO+zvB0TOdLFdQtE28ZuSntUjkSNVSQ9+B/KwzIkHl+Y7e0+XA== X-Received: by 2002:a17:90a:f98d:: with SMTP id cq13mr16273240pjb.105.1585579593306; Mon, 30 Mar 2020 07:46:33 -0700 (PDT) Received: from earth-mac.local (219x123x138x129.ap219.ftth.ucom.ne.jp. [219.123.138.129]) by smtp.gmail.com with ESMTPSA id h198sm10333214pfe.76.2020.03.30.07.46.32 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 30 Mar 2020 07:46:32 -0700 (PDT) Received: by earth-mac.local (Postfix, from userid 501) id 2A534202804C0F; Mon, 30 Mar 2020 23:46:31 +0900 (JST) From: Hajime Tazaki To: linux-um@lists.infradead.org Subject: [RFC v4 01/25] arch: add __SYSCALL_DEFINE_ARCH Date: Mon, 30 Mar 2020 23:45:33 +0900 Message-Id: <9b9d47a8be1c38561d0fc3e4478628e4bb6056ef.1585579244.git.thehajime@gmail.com> X-Mailer: git-send-email 2.20.1 (Apple Git-117) In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200330_074634_301524_054A2022 X-CRM114-Status: UNSURE ( 8.26 ) X-CRM114-Notice: Please train this message. X-Spam-Score: -0.2 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:1043 listed in] [list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [thehajime[at]gmail.com] -0.0 SPF_PASS SPF: sender matches SPF record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 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: Octavian Purdila , linux-kernel-library@freelists.org, linux-arch@vger.kernel.org, linux-api@vger.kernel.org, Akira Moroo Sender: "linux-um" Errors-To: linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Octavian Purdila This allows the architecture code to process the system call definitions. It is used by LKL to create strong typed function definitions for system calls. Signed-off-by: Octavian Purdila Cc: linux-api@vger.kernel.org --- include/linux/syscalls.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 1815065d52f3..e45815a3ee10 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -203,9 +203,14 @@ static inline int is_syscall_trace_event(struct trace_event_call *tp_event) } #endif +#ifndef __SYSCALL_DEFINE_ARCH +#define __SYSCALL_DEFINE_ARCH(x, sname, ...) +#endif + #ifndef SYSCALL_DEFINE0 #define SYSCALL_DEFINE0(sname) \ SYSCALL_METADATA(_##sname, 0); \ + __SYSCALL_DEFINE_ARCH(0, _##sname); \ asmlinkage long sys_##sname(void); \ ALLOW_ERROR_INJECTION(sys_##sname, ERRNO); \ asmlinkage long sys_##sname(void) @@ -222,6 +227,7 @@ static inline int is_syscall_trace_event(struct trace_event_call *tp_event) #define SYSCALL_DEFINEx(x, sname, ...) \ SYSCALL_METADATA(sname, x, __VA_ARGS__) \ + __SYSCALL_DEFINE_ARCH(x, sname, __VA_ARGS__) \ __SYSCALL_DEFINEx(x, sname, __VA_ARGS__) #define __PROTECT(...) asmlinkage_protect(__VA_ARGS__) From patchwork Mon Mar 30 14:45:34 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hajime Tazaki X-Patchwork-Id: 1263979 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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=lmv2KEQ6; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=qTHVTJoO; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (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 48rZzq57hcz9sP7 for ; Tue, 31 Mar 2020 01:47:03 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.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=FyKinxCDInNzgo+KS/qqE4ZzhSoxyJL4IZhlg6m3AFs=; b=lmv2KEQ6MG1dG1 Nf5solnsfpJRCEnNPN0jtyNDwxWrA2a3NG1wstEM6btu3yYoro98zXx7GOz2mrPGjxSM72Gmj4xqO JcbCkHy9IVmdDYs34Bh2Fed9mGma4uv98Oi5xc7hbBBmrIcHWb8Oou1kbGJ3XwrEh7MFdTamVqV52 0SB94zRPSvdFfqhHqL8VQwab6pT/yXgsUnu5Rhtc8Vr14AiRuAt/i2JpJstxFfG9DTG+p+cd6JLUh 1qrZJtAzDiVA17cbOEGyBY8NFbj3zHL5w8rsAqd//8NWpOeUIWsocZuiUAyvhh1kPfJQcVOKIEb4c cZCI/EuxymwolhrEfinw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvgg-0004Ty-W7; Mon, 30 Mar 2020 14:46:51 +0000 Received: from mail-pg1-x542.google.com ([2607:f8b0:4864:20::542]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvgb-0004TL-Cm for linux-um@lists.infradead.org; Mon, 30 Mar 2020 14:46:49 +0000 Received: by mail-pg1-x542.google.com with SMTP id x7so8756726pgh.5 for ; Mon, 30 Mar 2020 07:46:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Tasqe+KHkch3NqicbWnxAtiVrmw5OI+ygzHxuJEijeQ=; b=qTHVTJoOynjlSzfdjtOgPYjXe3f0XdHQIvBDJWvqTFXdwMZI+M4wlwPNvwR3RZPH36 NSHdG+rqoDpG/4UE07NzGjzVw8m/97MwUWlSdV9sSsgMedOYuvTA7qeT8Qo1mMk6HGt8 kxaCw4P5IXDT8S80nP+BtAOkePhmX/Tve8TYNaxrTznlm6OBIQK+gjaYiEhNZuc5RYsc 5CochCuwdMOZXaJK/MOW/fE/xccvwhIZCyVCAfhPJkYe1eIbSLWBJfDoD/KZR95VUm1h EFkxlOwjCGajef+482UcyYUKC0WdsPSmNxyPkswnGNcW+IyWhrEI+hzpldTl2/1j+oFX LXQQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Tasqe+KHkch3NqicbWnxAtiVrmw5OI+ygzHxuJEijeQ=; b=I+0+2/KOpOwO4wi5GykWFvA/HMlDtx3Iorjc6eGDNEhhJFPnsHUCsa59K3C9LtoI0c Z9Kv6Bcz9Cj47r622Y/NJzHRDf6Ka4y6UL7OT35r3P/zYOoZDIA73zx1qWOzGilPzeUm OfrV3icl6hDaAGDeBower9eGVA7K7DDEDUTh9YKEUTX2pvaE+fwsZvAYwaqoWdEzwVkA wfhhxffVak28o6T5ow+E5G0LalpcvmfwdjWvMcasgT/igJB5m9AX0Ps/8BR+NyQkEbGt zhtu3fKTgMOH801NvSzHNOj4crGwMGGrYCSYASRhO7VPqJ4AGn6eQM7fbEQLIRvOVbVy z1fQ== X-Gm-Message-State: ANhLgQ1trF5XNs7iv3fG8ORknYfNELHMuv3eEagQ9uAmnLrQF1U6vHLp bsA7MrEGDYv7ZYg8L711t+c= X-Google-Smtp-Source: ADFU+vvkdjoGTVmjbK0mFs8EpXU3FOTtZTgETdyW9cMJnu2ec20rwaIE7bJWwLsUdXXUQfHPDJ9w/A== X-Received: by 2002:aa7:870b:: with SMTP id b11mr13417428pfo.134.1585579604389; Mon, 30 Mar 2020 07:46:44 -0700 (PDT) Received: from earth-mac.local (219x123x138x129.ap219.ftth.ucom.ne.jp. [219.123.138.129]) by smtp.gmail.com with ESMTPSA id g2sm10429351pfh.193.2020.03.30.07.46.42 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 30 Mar 2020 07:46:43 -0700 (PDT) Received: by earth-mac.local (Postfix, from userid 501) id 692A3202804C3F; Mon, 30 Mar 2020 23:46:41 +0900 (JST) From: Hajime Tazaki To: linux-um@lists.infradead.org Subject: [RFC v4 02/25] um lkl: architecture skeleton for Linux kernel library Date: Mon, 30 Mar 2020 23:45:34 +0900 Message-Id: X-Mailer: git-send-email 2.20.1 (Apple Git-117) In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200330_074645_547664_91C64443 X-CRM114-Status: GOOD ( 14.42 ) X-Spam-Score: 0.6 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (0.6 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:542 listed in] [list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [thehajime[at]gmail.com] -0.0 SPF_PASS SPF: sender matches SPF record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.8 UPPERCASE_50_75 message body is 50-75% uppercase 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: linux-arch@vger.kernel.org, Levente Kurusa , Matthieu Coudron , Hajime Tazaki , Conrad Meyer , Octavian Purdila , Jens Staal , Motomu Utsumi , Lai Jiangshan , Akira Moroo , Petros Angelatos , Yuan Liu , Xiao Jia , Mark Stillwell , Patrick Collins , linux-kernel-library@freelists.org, Pierre-Hugues Husson , Michael Zimmermann , Luca Dariz , "Edison M . Castro" Sender: "linux-um" Errors-To: linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Octavian Purdila Adds the LKL Kconfig, vmlinux linker script, basic architecture headers and miscellaneous basic functions or stubs such as dump_stack(), show_regs() and cpuinfo proc ops. The headers we introduce in this patch are simple wrappers to the asm-generic headers or stubs for things we don't support, such as ptrace, DMA, signals, ELF handling and low level processor operations. The kernel configuration is automatically updated to reflect the endianness of the host, 64bit support or the output format for vmlinux's linker script. We do this by looking at the ld's default output format. Cc: Andreas Abel Cc: Conrad Meyer Cc: Edison M. Castro Cc: H.K. Jerry Chu Cc: Jens Staal Cc: Lai Jiangshan Cc: Levente Kurusa Cc: Luca Dariz Cc: Mark Stillwell Cc: Matthieu Coudron Cc: Michael Zimmermann Cc: Motomu Utsumi Cc: Patrick Collins Cc: Petros Angelatos Cc: Pierre-Hugues Husson Cc: Xiao Jia Cc: Yuan Liu Signed-off-by: Hajime Tazaki Signed-off-by: Octavian Purdila --- MAINTAINERS | 8 + arch/um/lkl/.gitignore | 2 + arch/um/lkl/Kconfig | 56 ++ arch/um/lkl/Kconfig.debug | 0 arch/um/lkl/configs/lkl_defconfig | 1052 ++++++++++++++++++++ arch/um/lkl/include/asm/Kbuild | 79 ++ arch/um/lkl/include/asm/atomic.h | 11 + arch/um/lkl/include/asm/atomic64.h | 114 +++ arch/um/lkl/include/asm/bitsperlong.h | 11 + arch/um/lkl/include/asm/byteorder.h | 7 + arch/um/lkl/include/asm/cpu.h | 14 + arch/um/lkl/include/asm/elf.h | 15 + arch/um/lkl/include/asm/processor.h | 60 ++ arch/um/lkl/include/asm/ptrace.h | 25 + arch/um/lkl/include/asm/sched.h | 23 + arch/um/lkl/include/asm/syscalls.h | 18 + arch/um/lkl/include/asm/syscalls_32.h | 43 + arch/um/lkl/include/asm/tlb.h | 12 + arch/um/lkl/include/asm/uaccess.h | 64 ++ arch/um/lkl/include/asm/unistd_32.h | 31 + arch/um/lkl/include/asm/vmalloc.h | 5 + arch/um/lkl/include/asm/vmlinux.lds.h | 14 + arch/um/lkl/include/asm/xor.h | 9 + arch/um/lkl/include/uapi/asm/Kbuild | 11 + arch/um/lkl/include/uapi/asm/bitsperlong.h | 13 + arch/um/lkl/include/uapi/asm/byteorder.h | 11 + arch/um/lkl/include/uapi/asm/syscalls.h | 348 +++++++ arch/um/lkl/kernel/asm-offsets.c | 2 + arch/um/lkl/kernel/misc.c | 60 ++ arch/um/lkl/kernel/vmlinux.lds.S | 51 + 30 files changed, 2169 insertions(+) create mode 100644 arch/um/lkl/.gitignore create mode 100644 arch/um/lkl/Kconfig create mode 100644 arch/um/lkl/Kconfig.debug create mode 100644 arch/um/lkl/configs/lkl_defconfig create mode 100644 arch/um/lkl/include/asm/Kbuild create mode 100644 arch/um/lkl/include/asm/atomic.h create mode 100644 arch/um/lkl/include/asm/atomic64.h create mode 100644 arch/um/lkl/include/asm/bitsperlong.h create mode 100644 arch/um/lkl/include/asm/byteorder.h create mode 100644 arch/um/lkl/include/asm/cpu.h create mode 100644 arch/um/lkl/include/asm/elf.h create mode 100644 arch/um/lkl/include/asm/processor.h create mode 100644 arch/um/lkl/include/asm/ptrace.h create mode 100644 arch/um/lkl/include/asm/sched.h create mode 100644 arch/um/lkl/include/asm/syscalls.h create mode 100644 arch/um/lkl/include/asm/syscalls_32.h create mode 100644 arch/um/lkl/include/asm/tlb.h create mode 100644 arch/um/lkl/include/asm/uaccess.h create mode 100644 arch/um/lkl/include/asm/unistd_32.h create mode 100644 arch/um/lkl/include/asm/vmalloc.h create mode 100644 arch/um/lkl/include/asm/vmlinux.lds.h create mode 100644 arch/um/lkl/include/asm/xor.h create mode 100644 arch/um/lkl/include/uapi/asm/Kbuild create mode 100644 arch/um/lkl/include/uapi/asm/bitsperlong.h create mode 100644 arch/um/lkl/include/uapi/asm/byteorder.h create mode 100644 arch/um/lkl/include/uapi/asm/syscalls.h create mode 100644 arch/um/lkl/kernel/asm-offsets.c create mode 100644 arch/um/lkl/kernel/misc.c create mode 100644 arch/um/lkl/kernel/vmlinux.lds.S diff --git a/MAINTAINERS b/MAINTAINERS index cc1d18cb5d18..f3913964eabe 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9710,6 +9710,14 @@ F: Documentation/core-api/atomic_ops.rst F: Documentation/core-api/refcount-vs-atomic.rst F: Documentation/memory-barriers.txt +LINUX KERNEL LIBRARY +M: Octavian Purdila +M: Hajime Tazaki +L: linux-kernel-library@freelists.org +S: Maintained +F: arch/um/lkl/ +F: tools/lkl/ + LIS3LV02D ACCELEROMETER DRIVER M: Eric Piel S: Maintained diff --git a/arch/um/lkl/.gitignore b/arch/um/lkl/.gitignore new file mode 100644 index 000000000000..ced1c60d8235 --- /dev/null +++ b/arch/um/lkl/.gitignore @@ -0,0 +1,2 @@ +kernel/vmlinux.lds +include/generated diff --git a/arch/um/lkl/Kconfig b/arch/um/lkl/Kconfig new file mode 100644 index 000000000000..f7e8d707a12b --- /dev/null +++ b/arch/um/lkl/Kconfig @@ -0,0 +1,56 @@ +# SPDX-License-Identifier: GPL-2.0 + +config UML_LKL + def_bool y + depends on !SMP && !MMU && !COREDUMP && !SECCOMP && !UPROBES && !COMPAT && !USER_RETURN_NOTIFIER + select ARCH_THREAD_STACK_ALLOCATOR + select RWSEM_GENERIC_SPINLOCK + select GENERIC_ATOMIC64 if !64BIT + select GENERIC_HWEIGHT + select FLATMEM + select FLAT_NODE_MEM_MAP + select GENERIC_CLOCKEVENTS + select GENERIC_CPU_DEVICES + select NO_HZ_IDLE + select NO_PREEMPT + select ARCH_WANT_FRAME_POINTERS + select HAS_DMA + select DMA_DIRECT_OPS + select PHYS_ADDR_T_64BIT if 64BIT + select 64BIT if "$(OUTPUT_FORMAT)" = "elf64-x86-64" + select 64BIT if "$(OUTPUT_FORMAT)" = "elf64-x86-64-freebsd" + select NET + select MULTIUSER + +config OUTPUT_FORMAT + string "Output format" + default "$(OUTPUT_FORMAT)" + +config ARCH_DMA_ADDR_T_64BIT + def_bool 64BIT + +config 64BIT + def_bool n + +config COREDUMP + def_bool n + +config BIG_ENDIAN + def_bool n + +config GENERIC_CSUM + def_bool y + +config GENERIC_HWEIGHT + def_bool y + +config NO_IOPORT_MAP + def_bool y + +config RWSEM_GENERIC_SPINLOCK + bool + default y + +config HZ + int + default 100 diff --git a/arch/um/lkl/Kconfig.debug b/arch/um/lkl/Kconfig.debug new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/arch/um/lkl/configs/lkl_defconfig b/arch/um/lkl/configs/lkl_defconfig new file mode 100644 index 000000000000..7050c233a17e --- /dev/null +++ b/arch/um/lkl/configs/lkl_defconfig @@ -0,0 +1,1052 @@ +CONFIG_CC_IS_GCC=y +CONFIG_GCC_VERSION=80301 +CONFIG_CLANG_VERSION=0 +CONFIG_CC_CAN_LINK=y +CONFIG_CC_HAS_ASM_GOTO=y +CONFIG_CC_HAS_ASM_INLINE=y +CONFIG_CC_HAS_WARN_MAYBE_UNINITIALIZED=y +CONFIG_IRQ_WORK=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +# CONFIG_COMPILE_TEST is not set +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_BUILD_SALT="" +CONFIG_DEFAULT_HOSTNAME="(none)" +# CONFIG_SYSVIPC is not set +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_USELIB is not set +# CONFIG_AUDIT is not set +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ_COMMON=y +# CONFIG_HZ_PERIODIC is not set +CONFIG_NO_HZ_IDLE=y +# CONFIG_NO_HZ is not set +CONFIG_HIGH_RES_TIMERS=y +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_TICK_CPU_ACCOUNTING=y +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_PSI is not set +CONFIG_TINY_RCU=y +# CONFIG_RCU_EXPERT is not set +CONFIG_SRCU=y +CONFIG_TINY_SRCU=y +# CONFIG_IKCONFIG is not set +# CONFIG_IKHEADERS is not set +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=13 +CONFIG_CC_HAS_INT128=y +# CONFIG_CGROUPS is not set +# CONFIG_NAMESPACES is not set +# CONFIG_CHECKPOINT_RESTORE is not set +# CONFIG_SCHED_AUTOGROUP is not set +# CONFIG_SYSFS_DEPRECATED is not set +# CONFIG_RELAY is not set +# CONFIG_BLK_DEV_INITRD is not set +CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_BPF=y +CONFIG_EXPERT=y +CONFIG_MULTIUSER=y +# CONFIG_SGETMASK_SYSCALL is not set +# CONFIG_SYSFS_SYSCALL is not set +CONFIG_FHANDLE=y +CONFIG_POSIX_TIMERS=y +# CONFIG_KALLSYMS_USE_DATA_SECTION is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +# CONFIG_BASE_FULL is not set +# CONFIG_FUTEX is not set +CONFIG_EPOLL=y +# CONFIG_SIGNALFD is not set +# CONFIG_TIMERFD is not set +CONFIG_EVENTFD=y +# CONFIG_AIO is not set +CONFIG_IO_URING=y +# CONFIG_ADVISE_SYSCALLS is not set +CONFIG_MEMBARRIER=y +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +CONFIG_KALLSYMS_BASE_RELATIVE=y +# CONFIG_BPF_SYSCALL is not set +CONFIG_EMBEDDED=y +# CONFIG_PC104 is not set +# CONFIG_VM_EVENT_COUNTERS is not set +CONFIG_SLUB_DEBUG=y +# CONFIG_COMPAT_BRK is not set +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +CONFIG_SLAB_MERGE_DEFAULT=y +# CONFIG_SLAB_FREELIST_RANDOM is not set +# CONFIG_SLAB_FREELIST_HARDENED is not set +# CONFIG_SHUFFLE_PAGE_ALLOCATOR is not set +# CONFIG_MMAP_ALLOW_UNINITIALIZED is not set +# CONFIG_PROFILING is not set +CONFIG_LKL=y +# CONFIG_COREDUMP is not set +CONFIG_GENERIC_CSUM=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_NO_IOPORT_MAP=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HZ=100 +# CONFIG_STDERR_CONSOLE is not set +# CONFIG_SSL is not set +# CONFIG_NULL_CHAN is not set +# CONFIG_PORT_CHAN is not set +# CONFIG_PTY_CHAN is not set +# CONFIG_TTY_CHAN is not set +# CONFIG_XTERM_CHAN is not set +CONFIG_NOCONFIG_CHAN=y +CONFIG_CON_ZERO_CHAN="fd:0,fd:1" +CONFIG_CON_CHAN="xterm" +CONFIG_SSL_CHAN="pty" +# CONFIG_UML_SOUND is not set +# CONFIG_SOUND is not set +CONFIG_UML_NET=y +# CONFIG_UML_NET_ETHERTAP is not set +CONFIG_UML_NET_TUNTAP=y +# CONFIG_UML_NET_SLIP is not set +# CONFIG_UML_NET_DAEMON is not set +# CONFIG_UML_NET_VECTOR is not set +# CONFIG_UML_NET_VDE is not set +# CONFIG_UML_NET_MCAST is not set +# CONFIG_UML_NET_PCAP is not set +CONFIG_UML_NET_SLIRP=y +# CONFIG_VIRTIO_UML is not set +CONFIG_ARCH_THREAD_STACK_ALLOCATOR=y +CONFIG_CC_HAS_STACKPROTECTOR_NONE=y +CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y +CONFIG_PGTABLE_LEVELS=2 +CONFIG_PLUGIN_HOSTCC="" +CONFIG_BASE_SMALL=1 +# CONFIG_MODULES is not set +CONFIG_BLOCK=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_BSGLIB is not set +# CONFIG_BLK_DEV_INTEGRITY is not set +# CONFIG_BLK_DEV_ZONED is not set +# CONFIG_BLK_CMDLINE_PARSER is not set +# CONFIG_BLK_WBT is not set +# CONFIG_BLK_SED_OPAL is not set +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +CONFIG_EFI_PARTITION=y +CONFIG_MQ_IOSCHED_DEADLINE=y +CONFIG_MQ_IOSCHED_KYBER=y +# CONFIG_IOSCHED_BFQ is not set +CONFIG_INLINE_SPIN_UNLOCK_IRQ=y +CONFIG_INLINE_READ_UNLOCK=y +CONFIG_INLINE_READ_UNLOCK_IRQ=y +CONFIG_INLINE_WRITE_UNLOCK=y +CONFIG_INLINE_WRITE_UNLOCK_IRQ=y +CONFIG_BINFMT_SCRIPT=y +# CONFIG_BINFMT_MISC is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_SPLIT_PTLOCK_CPUS=999999 +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_NOMMU_INITIAL_TRIM_EXCESS=1 +CONFIG_NEED_PER_CPU_KM=y +# CONFIG_CLEANCACHE is not set +# CONFIG_ZPOOL is not set +# CONFIG_ZBUD is not set +# CONFIG_PERCPU_STATS is not set +# CONFIG_GUP_BENCHMARK is not set +CONFIG_NET=y +# CONFIG_PACKET is not set +# CONFIG_UNIX is not set +# CONFIG_TLS is not set +# CONFIG_XFRM_USER is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +# CONFIG_IP_FIB_TRIE_STATS is not set +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +# CONFIG_IP_ROUTE_VERBOSE is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE_DEMUX is not set +CONFIG_NET_IP_TUNNEL=y +# CONFIG_IP_MROUTE is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_NET_IPVTI is not set +# CONFIG_NET_FOU is not set +# CONFIG_NET_FOU_IP_TUNNELS is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +CONFIG_INET_TUNNEL=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_INET_UDP_DIAG is not set +# CONFIG_INET_RAW_DIAG is not set +# CONFIG_INET_DIAG_DESTROY is not set +CONFIG_TCP_CONG_ADVANCED=y +CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_CUBIC=y +CONFIG_TCP_CONG_WESTWOOD=y +CONFIG_TCP_CONG_HTCP=y +# CONFIG_TCP_CONG_HSTCP is not set +# CONFIG_TCP_CONG_HYBLA is not set +# CONFIG_TCP_CONG_VEGAS is not set +# CONFIG_TCP_CONG_NV is not set +# CONFIG_TCP_CONG_SCALABLE is not set +# CONFIG_TCP_CONG_LP is not set +# CONFIG_TCP_CONG_VENO is not set +# CONFIG_TCP_CONG_YEAH is not set +# CONFIG_TCP_CONG_ILLINOIS is not set +# CONFIG_TCP_CONG_DCTCP is not set +# CONFIG_TCP_CONG_CDG is not set +CONFIG_TCP_CONG_BBR=y +# CONFIG_DEFAULT_BIC is not set +CONFIG_DEFAULT_CUBIC=y +# CONFIG_DEFAULT_HTCP is not set +# CONFIG_DEFAULT_WESTWOOD is not set +# CONFIG_DEFAULT_BBR is not set +# CONFIG_DEFAULT_RENO is not set +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +CONFIG_IPV6=y +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_IPV6_MIP6 is not set +# CONFIG_IPV6_VTI is not set +CONFIG_IPV6_SIT=y +# CONFIG_IPV6_SIT_6RD is not set +CONFIG_IPV6_NDISC_NODETYPE=y +# CONFIG_IPV6_TUNNEL is not set +CONFIG_IPV6_MULTIPLE_TABLES=y +# CONFIG_IPV6_SUBTREES is not set +# CONFIG_IPV6_MROUTE is not set +# CONFIG_IPV6_SEG6_LWTUNNEL is not set +# CONFIG_IPV6_SEG6_HMAC is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +# CONFIG_NETFILTER is not set +# CONFIG_BPFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_L2TP is not set +# CONFIG_BRIDGE is not set +CONFIG_HAVE_NET_DSA=y +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_PHONET is not set +# CONFIG_6LOWPAN is not set +# CONFIG_IEEE802154 is not set +CONFIG_NET_SCHED=y +# CONFIG_NET_SCH_CBQ is not set +# CONFIG_NET_SCH_HTB is not set +# CONFIG_NET_SCH_HFSC is not set +# CONFIG_NET_SCH_PRIO is not set +# CONFIG_NET_SCH_MULTIQ is not set +# CONFIG_NET_SCH_RED is not set +# CONFIG_NET_SCH_SFB is not set +# CONFIG_NET_SCH_SFQ is not set +# CONFIG_NET_SCH_TEQL is not set +# CONFIG_NET_SCH_TBF is not set +# CONFIG_NET_SCH_CBS is not set +# CONFIG_NET_SCH_ETF is not set +# CONFIG_NET_SCH_TAPRIO is not set +# CONFIG_NET_SCH_GRED is not set +# CONFIG_NET_SCH_DSMARK is not set +# CONFIG_NET_SCH_NETEM is not set +# CONFIG_NET_SCH_DRR is not set +# CONFIG_NET_SCH_MQPRIO is not set +# CONFIG_NET_SCH_SKBPRIO is not set +# CONFIG_NET_SCH_CHOKE is not set +# CONFIG_NET_SCH_QFQ is not set +# CONFIG_NET_SCH_CODEL is not set +# CONFIG_NET_SCH_FQ_CODEL is not set +# CONFIG_NET_SCH_CAKE is not set +CONFIG_NET_SCH_FQ=y +# CONFIG_NET_SCH_HHF is not set +# CONFIG_NET_SCH_PIE is not set +# CONFIG_NET_SCH_PLUG is not set +# CONFIG_NET_SCH_DEFAULT is not set +# CONFIG_NET_CLS_BASIC is not set +# CONFIG_NET_CLS_TCINDEX is not set +# CONFIG_NET_CLS_ROUTE4 is not set +# CONFIG_NET_CLS_FW is not set +# CONFIG_NET_CLS_U32 is not set +# CONFIG_NET_CLS_RSVP is not set +# CONFIG_NET_CLS_RSVP6 is not set +# CONFIG_NET_CLS_FLOW is not set +# CONFIG_NET_CLS_BPF is not set +# CONFIG_NET_CLS_FLOWER is not set +# CONFIG_NET_CLS_MATCHALL is not set +# CONFIG_NET_EMATCH is not set +# CONFIG_NET_CLS_ACT is not set +CONFIG_NET_SCH_FIFO=y +# CONFIG_DCB is not set +# CONFIG_BATMAN_ADV is not set +# CONFIG_OPENVSWITCH is not set +# CONFIG_VSOCKETS is not set +# CONFIG_NETLINK_DIAG is not set +# CONFIG_MPLS is not set +# CONFIG_NET_NSH is not set +# CONFIG_HSR is not set +# CONFIG_NET_SWITCHDEV is not set +# CONFIG_NET_L3_MASTER_DEV is not set +# CONFIG_NET_NCSI is not set +CONFIG_NET_RX_BUSY_POLL=y +CONFIG_BQL=y +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +# CONFIG_AF_KCM is not set +CONFIG_FIB_RULES=y +# CONFIG_WIRELESS is not set +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set +# CONFIG_CEPH_LIB is not set +# CONFIG_NFC is not set +# CONFIG_PSAMPLE is not set +# CONFIG_NET_IFE is not set +# CONFIG_LWTUNNEL is not set +CONFIG_DST_CACHE=y +CONFIG_GRO_CELLS=y +CONFIG_FAILOVER=y +# CONFIG_PCCARD is not set +# CONFIG_UEVENT_HELPER is not set +# CONFIG_DEVTMPFS is not set +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +CONFIG_ALLOW_DEV_COREDUMP=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set +CONFIG_GENERIC_CPU_DEVICES=y +# CONFIG_CONNECTOR is not set +# CONFIG_GNSS is not set +# CONFIG_MTD is not set +# CONFIG_OF is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_NULL_BLK is not set +# CONFIG_BLK_DEV_UBD_SYNC is not set +CONFIG_BLK_DEV_COW_COMMON=y +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_DRBD is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_BLK_DEV_RBD is not set +# CONFIG_NVME_FC is not set +# CONFIG_DUMMY_IRQ is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_SRAM is not set +# CONFIG_XILINX_SDFEC is not set +# CONFIG_C2PORT is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_VOP_BUS is not set +# CONFIG_ECHO is not set +CONFIG_SCSI_MOD=y +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +# CONFIG_TARGET_CORE is not set +CONFIG_NETDEVICES=y +CONFIG_NET_CORE=y +# CONFIG_BONDING is not set +# CONFIG_DUMMY is not set +# CONFIG_EQUALIZER is not set +# CONFIG_NET_TEAM is not set +# CONFIG_MACVLAN is not set +# CONFIG_IPVLAN is not set +# CONFIG_VXLAN is not set +# CONFIG_GENEVE is not set +# CONFIG_GTP is not set +# CONFIG_MACSEC is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_TUN is not set +# CONFIG_TUN_VNET_CROSS_LE is not set +# CONFIG_VETH is not set +# CONFIG_NLMON is not set +# CONFIG_ETHERNET is not set +# CONFIG_MDIO_DEVICE is not set +# CONFIG_PHYLIB is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_WLAN is not set +# CONFIG_WAN is not set +CONFIG_NET_FAILOVER=y +# CONFIG_ISDN is not set +# CONFIG_NVM is not set +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set +# CONFIG_INPUT_SPARSEKMAP is not set +# CONFIG_INPUT_MATRIXKMAP is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_BYD=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_CYPRESS=y +CONFIG_MOUSE_PS2_TRACKPOINT=y +# CONFIG_MOUSE_PS2_ELANTECH is not set +# CONFIG_MOUSE_PS2_SENTELIC is not set +# CONFIG_MOUSE_PS2_TOUCHKIT is not set +CONFIG_MOUSE_PS2_FOCALTECH=y +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MOUSE_SYNAPTICS_USB is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set +# CONFIG_RMI4_CORE is not set +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO_ALTERA_PS2 is not set +# CONFIG_SERIO_PS2MULT is not set +# CONFIG_SERIO_ARC_PS2 is not set +# CONFIG_USERIO is not set +# CONFIG_GAMEPORT is not set +CONFIG_TTY=y +# CONFIG_VT is not set +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_N_GSM is not set +# CONFIG_TRACE_SINK is not set +# CONFIG_NULL_TTY is not set +CONFIG_LDISC_AUTOLOAD=y +CONFIG_DEVMEM=y +# CONFIG_DEVKMEM is not set +# CONFIG_SERIAL_8250 is not set +# CONFIG_SERIAL_UARTLITE is not set +# CONFIG_SERIAL_SCCNXP is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_ARC is not set +# CONFIG_SERIAL_FSL_LPUART is not set +# CONFIG_SERIAL_FSL_LINFLEXUART is not set +# CONFIG_SERIAL_DEV_BUS is not set +# CONFIG_TTY_PRINTK is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_HW_RANDOM_TIMERIOMEM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_RANDOM_TRUST_BOOTLOADER is not set +# CONFIG_I2C is not set +# CONFIG_I3C is not set +# CONFIG_SPI is not set +# CONFIG_SPMI is not set +# CONFIG_HSI is not set +# CONFIG_PPS is not set +# CONFIG_PTP_1588_CLOCK is not set +# CONFIG_PINCTRL is not set +# CONFIG_GPIOLIB is not set +# CONFIG_W1 is not set +# CONFIG_POWER_AVS is not set +# CONFIG_POWER_RESET is not set +# CONFIG_POWER_SUPPLY is not set +CONFIG_HWMON=y +# CONFIG_HWMON_DEBUG_CHIP is not set +# CONFIG_SENSORS_AS370 is not set +# CONFIG_SENSORS_ASPEED is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_MAX197 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_NTC_THERMISTOR is not set +# CONFIG_SENSORS_NCT6683 is not set +# CONFIG_SENSORS_NCT6775 is not set +# CONFIG_SENSORS_NPCM7XX is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_THERMAL is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set +CONFIG_BCMA_POSSIBLE=y +# CONFIG_BCMA is not set +# CONFIG_MFD_MADERA is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_KEMPLD is not set +# CONFIG_MFD_MT6397 is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_SYSCON is not set +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_MFD_TQMX86 is not set +# CONFIG_REGULATOR is not set +# CONFIG_RC_CORE is not set +# CONFIG_MEDIA_SUPPORT is not set +# CONFIG_DRM is not set +# CONFIG_DRM_DP_CEC is not set +# CONFIG_FB is not set +# CONFIG_LCD_CLASS_DEVICE is not set +# CONFIG_BACKLIGHT_CLASS_DEVICE is not set +CONFIG_HID=y +# CONFIG_HID_BATTERY_STRENGTH is not set +# CONFIG_HIDRAW is not set +# CONFIG_UHID is not set +CONFIG_HID_GENERIC=y +# CONFIG_HID_A4TECH is not set +# CONFIG_HID_ACRUX is not set +# CONFIG_HID_APPLE is not set +# CONFIG_HID_AUREAL is not set +# CONFIG_HID_BELKIN is not set +# CONFIG_HID_CHERRY is not set +# CONFIG_HID_CHICONY is not set +# CONFIG_HID_COUGAR is not set +# CONFIG_HID_MACALLY is not set +# CONFIG_HID_CMEDIA is not set +# CONFIG_HID_CYPRESS is not set +# CONFIG_HID_DRAGONRISE is not set +# CONFIG_HID_EMS_FF is not set +# CONFIG_HID_ELECOM is not set +# CONFIG_HID_EZKEY is not set +# CONFIG_HID_GEMBIRD is not set +# CONFIG_HID_GFRM is not set +# CONFIG_HID_KEYTOUCH is not set +# CONFIG_HID_KYE is not set +# CONFIG_HID_WALTOP is not set +# CONFIG_HID_VIEWSONIC is not set +# CONFIG_HID_GYRATION is not set +# CONFIG_HID_ICADE is not set +# CONFIG_HID_ITE is not set +# CONFIG_HID_JABRA is not set +# CONFIG_HID_TWINHAN is not set +# CONFIG_HID_KENSINGTON is not set +# CONFIG_HID_LCPOWER is not set +# CONFIG_HID_LENOVO is not set +# CONFIG_HID_MAGICMOUSE is not set +# CONFIG_HID_MALTRON is not set +# CONFIG_HID_MAYFLASH is not set +# CONFIG_HID_REDRAGON is not set +# CONFIG_HID_MICROSOFT is not set +# CONFIG_HID_MONTEREY is not set +# CONFIG_HID_MULTITOUCH is not set +# CONFIG_HID_NTI is not set +# CONFIG_HID_ORTEK is not set +# CONFIG_HID_PANTHERLORD is not set +# CONFIG_HID_PETALYNX is not set +# CONFIG_HID_PICOLCD is not set +# CONFIG_HID_PLANTRONICS is not set +# CONFIG_HID_PRIMAX is not set +# CONFIG_HID_SAITEK is not set +# CONFIG_HID_SAMSUNG is not set +# CONFIG_HID_SPEEDLINK is not set +# CONFIG_HID_STEAM is not set +# CONFIG_HID_STEELSERIES is not set +# CONFIG_HID_SUNPLUS is not set +# CONFIG_HID_RMI is not set +# CONFIG_HID_GREENASIA is not set +# CONFIG_HID_SMARTJOYPLUS is not set +# CONFIG_HID_TIVO is not set +# CONFIG_HID_TOPSEED is not set +# CONFIG_HID_THRUSTMASTER is not set +# CONFIG_HID_UDRAW_PS3 is not set +# CONFIG_HID_XINMO is not set +# CONFIG_HID_ZEROPLUS is not set +# CONFIG_HID_ZYDACRON is not set +# CONFIG_HID_SENSOR_HUB is not set +# CONFIG_HID_ALPS is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_SUPPORT=y +# CONFIG_USB_ULPI_BUS is not set +CONFIG_USB_ARCH_HAS_HCD=y +# CONFIG_USB is not set +# CONFIG_NOP_USB_XCEIV is not set +# CONFIG_USB_GADGET is not set +# CONFIG_TYPEC is not set +# CONFIG_USB_ROLE_SWITCH is not set +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_INFINIBAND is not set +# CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set +# CONFIG_SYNC_FILE is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_VIRT_DRIVERS is not set +CONFIG_VIRTIO_MENU=y +# CONFIG_VIRTIO_MMIO is not set +# CONFIG_GREYBUS is not set +# CONFIG_STAGING is not set +# CONFIG_GOLDFISH is not set +# CONFIG_HWSPINLOCK is not set +# CONFIG_MAILBOX is not set +# CONFIG_REMOTEPROC is not set +# CONFIG_RPMSG_VIRTIO is not set +# CONFIG_SOC_TI is not set +# CONFIG_XILINX_VCU is not set +# CONFIG_PM_DEVFREQ is not set +# CONFIG_EXTCON is not set +# CONFIG_MEMORY is not set +# CONFIG_IIO is not set +# CONFIG_PWM is not set +# CONFIG_IPACK_BUS is not set +# CONFIG_RESET_CONTROLLER is not set +# CONFIG_GENERIC_PHY is not set +# CONFIG_BCM_KONA_USB2_PHY is not set +# CONFIG_PHY_PXA_28NM_HSIC is not set +# CONFIG_PHY_PXA_28NM_USB2 is not set +# CONFIG_POWERCAP is not set +# CONFIG_MCB is not set +# CONFIG_RAS is not set +# CONFIG_ANDROID is not set +# CONFIG_LIBNVDIMM is not set +# CONFIG_DAX is not set +# CONFIG_NVMEM is not set +# CONFIG_STM is not set +# CONFIG_INTEL_TH is not set +# CONFIG_FPGA is not set +# CONFIG_SIOX is not set +# CONFIG_SLIMBUS is not set +# CONFIG_INTERCONNECT is not set +# CONFIG_COUNTER is not set +# CONFIG_VALIDATE_FS_PARSER is not set +CONFIG_FS_IOMAP=y +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_USE_FOR_EXT2=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +# CONFIG_EXT4_DEBUG is not set +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +CONFIG_BTRFS_FS=y +# CONFIG_BTRFS_FS_POSIX_ACL is not set +# CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set +# CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set +# CONFIG_BTRFS_DEBUG is not set +# CONFIG_BTRFS_ASSERT is not set +# CONFIG_BTRFS_FS_REF_VERIFY is not set +# CONFIG_NILFS2_FS is not set +# CONFIG_F2FS_FS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_EXPORTFS=y +# CONFIG_EXPORTFS_BLOCK_OPS is not set +# CONFIG_FILE_LOCKING is not set +# CONFIG_FS_ENCRYPTION is not set +# CONFIG_FS_VERITY is not set +# CONFIG_DNOTIFY is not set +# CONFIG_INOTIFY_USER is not set +# CONFIG_FANOTIFY is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_FUSE_FS is not set +# CONFIG_OVERLAY_FS is not set +# CONFIG_FSCACHE is not set +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set +CONFIG_FAT_FS=y +# CONFIG_MSDOS_FS is not set +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_FAT_DEFAULT_UTF8 is not set +# CONFIG_NTFS_FS is not set +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +# CONFIG_PROC_CHILDREN is not set +CONFIG_KERNFS=y +CONFIG_SYSFS=y +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ORANGEFS_FS is not set +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX6FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_PSTORE is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +# CONFIG_EROFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +# CONFIG_CEPH_FS is not set +# CONFIG_CIFS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=y +CONFIG_NLS_CODEPAGE_775=y +CONFIG_NLS_CODEPAGE_850=y +CONFIG_NLS_CODEPAGE_852=y +CONFIG_NLS_CODEPAGE_855=y +CONFIG_NLS_CODEPAGE_857=y +CONFIG_NLS_CODEPAGE_860=y +CONFIG_NLS_CODEPAGE_861=y +CONFIG_NLS_CODEPAGE_862=y +CONFIG_NLS_CODEPAGE_863=y +CONFIG_NLS_CODEPAGE_864=y +CONFIG_NLS_CODEPAGE_865=y +CONFIG_NLS_CODEPAGE_866=y +CONFIG_NLS_CODEPAGE_869=y +CONFIG_NLS_CODEPAGE_936=y +CONFIG_NLS_CODEPAGE_950=y +CONFIG_NLS_CODEPAGE_932=y +CONFIG_NLS_CODEPAGE_949=y +CONFIG_NLS_CODEPAGE_874=y +CONFIG_NLS_ISO8859_8=y +CONFIG_NLS_CODEPAGE_1250=y +CONFIG_NLS_CODEPAGE_1251=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_ISO8859_2=y +CONFIG_NLS_ISO8859_3=y +CONFIG_NLS_ISO8859_4=y +CONFIG_NLS_ISO8859_5=y +CONFIG_NLS_ISO8859_6=y +CONFIG_NLS_ISO8859_7=y +CONFIG_NLS_ISO8859_9=y +CONFIG_NLS_ISO8859_13=y +CONFIG_NLS_ISO8859_14=y +CONFIG_NLS_ISO8859_15=y +CONFIG_NLS_KOI8_R=y +CONFIG_NLS_KOI8_U=y +CONFIG_NLS_MAC_ROMAN=y +CONFIG_NLS_MAC_CELTIC=y +CONFIG_NLS_MAC_CENTEURO=y +CONFIG_NLS_MAC_CROATIAN=y +CONFIG_NLS_MAC_CYRILLIC=y +CONFIG_NLS_MAC_GAELIC=y +CONFIG_NLS_MAC_GREEK=y +CONFIG_NLS_MAC_ICELAND=y +CONFIG_NLS_MAC_INUIT=y +CONFIG_NLS_MAC_ROMANIAN=y +CONFIG_NLS_MAC_TURKISH=y +CONFIG_NLS_UTF8=y +# CONFIG_UNICODE is not set +CONFIG_IO_WQ=y +# CONFIG_KEYS is not set +# CONFIG_SECURITY_DMESG_RESTRICT is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y +# CONFIG_HARDENED_USERCOPY is not set +# CONFIG_STATIC_USERMODEHELPER is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_LSM="lockdown,yama,loadpin,safesetid,integrity" +CONFIG_INIT_STACK_NONE=y +# CONFIG_INIT_ON_ALLOC_DEFAULT_ON is not set +# CONFIG_INIT_ON_FREE_DEFAULT_ON is not set +CONFIG_XOR_BLOCKS=y +CONFIG_CRYPTO=y +# CONFIG_CRYPTO_FIPS is not set +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +# CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_USER is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_RSA is not set +# CONFIG_CRYPTO_DH is not set +# CONFIG_CRYPTO_ECDH is not set +# CONFIG_CRYPTO_ECRDSA is not set +# CONFIG_CRYPTO_CURVE25519 is not set +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_CHACHA20POLY1305 is not set +# CONFIG_CRYPTO_AEGIS128 is not set +# CONFIG_CRYPTO_SEQIV is not set +# CONFIG_CRYPTO_ECHAINIV is not set +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CFB is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_OFB is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set +# CONFIG_CRYPTO_KEYWRAP is not set +# CONFIG_CRYPTO_ADIANTUM is not set +# CONFIG_CRYPTO_ESSIV is not set +# CONFIG_CRYPTO_CMAC is not set +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set +CONFIG_CRYPTO_CRC32C=y +# CONFIG_CRYPTO_CRC32 is not set +CONFIG_CRYPTO_XXHASH=y +CONFIG_CRYPTO_BLAKE2B=y +# CONFIG_CRYPTO_BLAKE2S is not set +# CONFIG_CRYPTO_CRCT10DIF is not set +# CONFIG_CRYPTO_GHASH is not set +# CONFIG_CRYPTO_POLY1305 is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +CONFIG_CRYPTO_SHA256=y +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_SHA3 is not set +# CONFIG_CRYPTO_SM3 is not set +# CONFIG_CRYPTO_STREEBOG is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_AES_TI is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_CHACHA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_SM4 is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_LZO is not set +# CONFIG_CRYPTO_842 is not set +# CONFIG_CRYPTO_LZ4 is not set +# CONFIG_CRYPTO_LZ4HC is not set +# CONFIG_CRYPTO_ZSTD is not set +CONFIG_CRYPTO_ANSI_CPRNG=y +# CONFIG_CRYPTO_DRBG_MENU is not set +# CONFIG_CRYPTO_JITTERENTROPY is not set +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +# CONFIG_CRYPTO_USER_API_RNG is not set +# CONFIG_CRYPTO_USER_API_AEAD is not set +CONFIG_CRYPTO_LIB_AES=y +# CONFIG_CRYPTO_LIB_BLAKE2S is not set +# CONFIG_CRYPTO_LIB_CHACHA is not set +# CONFIG_CRYPTO_LIB_CURVE25519 is not set +CONFIG_CRYPTO_LIB_POLY1305_RSIZE=1 +# CONFIG_CRYPTO_LIB_POLY1305 is not set +# CONFIG_CRYPTO_LIB_CHACHA20POLY1305 is not set +CONFIG_CRYPTO_LIB_SHA256=y +CONFIG_CRYPTO_HW=y +# CONFIG_CRYPTO_DEV_AMLOGIC_GXL is not set +CONFIG_RAID6_PQ=y +# CONFIG_RAID6_PQ_BENCHMARK is not set +# CONFIG_PACKING is not set +CONFIG_BITREVERSE=y +CONFIG_GENERIC_NET_UTILS=y +# CONFIG_CORDIC is not set +# CONFIG_CRC_CCITT is not set +CONFIG_CRC16=y +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC32_SELFTEST is not set +CONFIG_CRC32_SLICEBY8=y +# CONFIG_CRC32_SLICEBY4 is not set +# CONFIG_CRC32_SARWATE is not set +# CONFIG_CRC32_BIT is not set +# CONFIG_CRC64 is not set +# CONFIG_CRC4 is not set +# CONFIG_CRC7 is not set +CONFIG_LIBCRC32C=y +# CONFIG_CRC8 is not set +CONFIG_XXHASH=y +# CONFIG_RANDOM32_SELFTEST is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_ZSTD_COMPRESS=y +CONFIG_ZSTD_DECOMPRESS=y +# CONFIG_XZ_DEC is not set +CONFIG_HAS_IOMEM=y +CONFIG_HAS_DMA=y +# CONFIG_DMA_API_DEBUG is not set +CONFIG_DQL=y +CONFIG_NLATTR=y +CONFIG_GENERIC_ATOMIC64=y +# CONFIG_IRQ_POLL is not set +CONFIG_SBITMAP=y +# CONFIG_STRING_SELFTEST is not set +CONFIG_PRINTK_TIME=y +# CONFIG_PRINTK_CALLER is not set +CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7 +CONFIG_CONSOLE_LOGLEVEL_QUIET=4 +CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 +CONFIG_SYMBOLIC_ERRNAME=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_INFO_REDUCED=y +# CONFIG_DEBUG_INFO_SPLIT is not set +# CONFIG_DEBUG_INFO_DWARF4 is not set +# CONFIG_DEBUG_INFO_BTF is not set +# CONFIG_GDB_SCRIPTS is not set +# CONFIG_ENABLE_MUST_CHECK is not set +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_READABLE_ASM is not set +# CONFIG_HEADERS_INSTALL is not set +CONFIG_OPTIMIZE_INLINING=y +# CONFIG_DEBUG_SECTION_MISMATCH is not set +CONFIG_SECTION_MISMATCH_WARN_ONLY=y +CONFIG_ARCH_WANT_FRAME_POINTERS=y +CONFIG_FRAME_POINTER=y +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_UBSAN is not set +CONFIG_UBSAN_ALIGNMENT=y +CONFIG_DEBUG_KERNEL=y +CONFIG_DEBUG_MISC=y +# CONFIG_PAGE_EXTENSION is not set +# CONFIG_DEBUG_PAGEALLOC is not set +# CONFIG_PAGE_POISONING is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_SCHED_STACK_END_CHECK is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_NOMMU_REGIONS is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +CONFIG_CC_HAS_KASAN_GENERIC=y +CONFIG_KASAN_STACK=1 +# CONFIG_DEBUG_SHIRQ is not set +# CONFIG_PANIC_ON_OOPS is not set +CONFIG_PANIC_ON_OOPS_VALUE=0 +CONFIG_PANIC_TIMEOUT=0 +# CONFIG_SOFTLOCKUP_DETECTOR is not set +# CONFIG_DETECT_HUNG_TASK is not set +# CONFIG_WQ_WATCHDOG is not set +CONFIG_SCHED_DEBUG=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_TIMEKEEPING is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RWSEMS is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_LOCK_TORTURE_TEST is not set +# CONFIG_WW_MUTEX_SELFTEST is not set +# CONFIG_WARN_ALL_UNSEEDED_RANDOM is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_PLIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_BUG_ON_DATA_CORRUPTION is not set +# CONFIG_DEBUG_CREDENTIALS is not set +# CONFIG_RCU_PERF_TEST is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_TRACE is not set +# CONFIG_RCU_EQS_DEBUG is not set +# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_SAMPLES is not set +# CONFIG_KUNIT is not set +# CONFIG_NOTIFIER_ERROR_INJECTION is not set +# CONFIG_FAULT_INJECTION is not set +CONFIG_CC_HAS_SANCOV_TRACE_PC=y +CONFIG_RUNTIME_TESTING_MENU=y +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_TEST_SORT is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_RBTREE_TEST is not set +# CONFIG_REED_SOLOMON_TEST is not set +# CONFIG_INTERVAL_TREE_TEST is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_TEST_HEXDUMP is not set +# CONFIG_TEST_STRING_HELPERS is not set +# CONFIG_TEST_STRSCPY is not set +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_TEST_PRINTF is not set +# CONFIG_TEST_BITMAP is not set +# CONFIG_TEST_BITFIELD is not set +# CONFIG_TEST_UUID is not set +# CONFIG_TEST_XARRAY is not set +# CONFIG_TEST_OVERFLOW is not set +# CONFIG_TEST_RHASHTABLE is not set +# CONFIG_TEST_HASH is not set +# CONFIG_TEST_IDA is not set +# CONFIG_FIND_BIT_BENCHMARK is not set +# CONFIG_TEST_SYSCTL is not set +# CONFIG_TEST_UDELAY is not set +# CONFIG_TEST_MEMCAT_P is not set +# CONFIG_TEST_STACKINIT is not set +# CONFIG_TEST_MEMINIT is not set +# CONFIG_MEMTEST is not set diff --git a/arch/um/lkl/include/asm/Kbuild b/arch/um/lkl/include/asm/Kbuild new file mode 100644 index 000000000000..6ae3104fa285 --- /dev/null +++ b/arch/um/lkl/include/asm/Kbuild @@ -0,0 +1,79 @@ +generic-y += barrier.h +generic-y += bitops.h +generic-y += bug.h +generic-y += bugs.h +generic-y += cache.h +generic-y += cacheflush.h +generic-y += checksum.h +generic-y += cmpxchg-local.h +generic-y += cmpxchg.h +generic-y += compat.h +generic-y += cputime.h +generic-y += current.h +generic-y += delay.h +generic-y += device.h +generic-y += div64.h +generic-y += dma.h +generic-y += dma-mapping.h +generic-y += emergency-restart.h +generic-y += errno.h +generic-y += extable.h +generic-y += exec.h +generic-y += ftrace.h +generic-y += futex.h +generic-y += hardirq.h +generic-y += hw_irq.h +generic-y += io.h +generic-y += ioctl.h +generic-y += ipcbuf.h +generic-y += irq_regs.h +generic-y += irqflags.h +generic-y += irq_work.h +generic-y += kdebug.h +generic-y += kmap_types.h +generic-y += linkage.h +generic-y += local.h +generic-y += local64.h +generic-y += mcs_spinlock.h +generic-y += mmiowb.h +generic-y += mmu.h +generic-y += mmu_context.h +generic-y += module.h +generic-y += msgbuf.h +generic-y += param.h +generic-y += parport.h +generic-y += pci.h +generic-y += percpu.h +generic-y += pgalloc.h +generic-y += poll.h +generic-y += preempt.h +generic-y += resource.h +generic-y += rwsem.h +generic-y += scatterlist.h +generic-y += seccomp.h +generic-y += sections.h +generic-y += segment.h +generic-y += sembuf.h +generic-y += serial.h +generic-y += shmbuf.h +generic-y += signal.h +generic-y += sizes.h +generic-y += socket.h +generic-y += sockios.h +generic-y += stat.h +generic-y += statfs.h +generic-y += string.h +generic-y += swab.h +generic-y += switch_to.h +generic-y += syscall.h +generic-y += termbits.h +generic-y += termios.h +generic-y += time.h +generic-y += timex.h +generic-y += tlbflush.h +generic-y += topology.h +generic-y += trace_clock.h +generic-y += unaligned.h +generic-y += user.h +generic-y += word-at-a-time.h +generic-y += kprobes.h diff --git a/arch/um/lkl/include/asm/atomic.h b/arch/um/lkl/include/asm/atomic.h new file mode 100644 index 000000000000..0c5f9f8e4b30 --- /dev/null +++ b/arch/um/lkl/include/asm/atomic.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __LKL_ATOMIC_H +#define __LKL_ATOMIC_H + +#include + +#ifndef CONFIG_GENERIC_ATOMIC64 +#include "atomic64.h" +#endif /* CONFIG_GENERIC_ATOMIC64 */ + +#endif diff --git a/arch/um/lkl/include/asm/atomic64.h b/arch/um/lkl/include/asm/atomic64.h new file mode 100644 index 000000000000..87d7956c29eb --- /dev/null +++ b/arch/um/lkl/include/asm/atomic64.h @@ -0,0 +1,114 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __LKL_ATOMIC64_H +#define __LKL_ATOMIC64_H + +#include + +#ifdef CONFIG_SMP +#error "SMP is not supported on this platform" +#else +#define ATOMIC64_OP(op, c_op) \ +static inline void atomic64_##op(s64 i, atomic64_t *v) \ +{ \ + unsigned long flags; \ + \ + raw_local_irq_save(flags); \ + v->counter = v->counter c_op i; \ + raw_local_irq_restore(flags); \ +} + +#define ATOMIC64_OP_RETURN(op, c_op) \ +static inline s64 atomic64_##op##_return(s64 i, atomic64_t *v) \ +{ \ + unsigned long flags; \ + s64 ret; \ + \ + raw_local_irq_save(flags); \ + ret = (v->counter = v->counter c_op i); \ + raw_local_irq_restore(flags); \ + \ + return ret; \ +} + +#define ATOMIC64_FETCH_OP(op, c_op) \ +static inline s64 atomic64_fetch_##op(s64 i, atomic64_t *v) \ +{ \ + unsigned long flags; \ + s64 ret; \ + \ + raw_local_irq_save(flags); \ + ret = v->counter; \ + v->counter = v->counter c_op i; \ + raw_local_irq_restore(flags); \ + \ + return ret; \ +} +#endif /* CONFIG_SMP */ + +#ifndef atomic64_add_return +ATOMIC64_OP_RETURN(add, +) +#endif + +#ifndef atomic64_sub_return +ATOMIC64_OP_RETURN(sub, -) +#endif + +#ifndef atomic64_fetch_add +ATOMIC64_FETCH_OP(add, +) +#endif + +#ifndef atomic64_fetch_sub +ATOMIC64_FETCH_OP(sub, -) +#endif + +#ifndef atomic64_fetch_and +ATOMIC64_FETCH_OP(and, &) +#endif + +#ifndef atomic64_fetch_or +ATOMIC64_FETCH_OP(or, |) +#endif + +#ifndef atomic64_fetch_xor +ATOMIC64_FETCH_OP(xor, ^) +#endif + +#ifndef atomic64_and +ATOMIC64_OP(and, &) +#endif + +#ifndef atomic64_or +ATOMIC64_OP(or, |) +#endif + +#ifndef atomic64_xor +ATOMIC64_OP(xor, ^) +#endif + +#undef ATOMIC64_FETCH_OP +#undef ATOMIC64_OP_RETURN +#undef ATOMIC64_OP + + +#define ATOMIC64_INIT(i) { (i) } + +static inline void atomic64_add(s64 i, atomic64_t *v) +{ + atomic64_add_return(i, v); +} + +static inline void atomic64_sub(s64 i, atomic64_t *v) +{ + atomic64_sub_return(i, v); +} + +#ifndef atomic64_read +#define atomic64_read(v) READ_ONCE((v)->counter) +#endif + +#define atomic64_set(v, i) WRITE_ONCE(((v)->counter), (i)) + +#define atomic64_xchg(ptr, v) (xchg(&(ptr)->counter, (v))) +#define atomic64_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), (old), (new))) + +#endif /* __LKL_ATOMIC64_H */ diff --git a/arch/um/lkl/include/asm/bitsperlong.h b/arch/um/lkl/include/asm/bitsperlong.h new file mode 100644 index 000000000000..5745d5e51274 --- /dev/null +++ b/arch/um/lkl/include/asm/bitsperlong.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __LKL_BITSPERLONG_H +#define __LKL_BITSPERLONG_H + +#include + +#define BITS_PER_LONG __BITS_PER_LONG + +#define BITS_PER_LONG_LONG 64 + +#endif diff --git a/arch/um/lkl/include/asm/byteorder.h b/arch/um/lkl/include/asm/byteorder.h new file mode 100644 index 000000000000..5d0c4efaa44b --- /dev/null +++ b/arch/um/lkl/include/asm/byteorder.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_LKL_BYTEORDER_H +#define _ASM_LKL_BYTEORDER_H + +#include + +#endif /* _ASM_LKL_BYTEORDER_H */ diff --git a/arch/um/lkl/include/asm/cpu.h b/arch/um/lkl/include/asm/cpu.h new file mode 100644 index 000000000000..d2b8c501c7b1 --- /dev/null +++ b/arch/um/lkl/include/asm/cpu.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_LKL_CPU_H +#define _ASM_LKL_CPU_H + +int lkl_cpu_get(void); +void lkl_cpu_put(void); +int lkl_cpu_try_run_irq(int irq); +int lkl_cpu_init(void); +void lkl_cpu_shutdown(void); +void lkl_cpu_wait_shutdown(void); +void lkl_cpu_change_owner(lkl_thread_t owner); +void lkl_cpu_set_irqs_pending(void); + +#endif /* _ASM_LKL_CPU_H */ diff --git a/arch/um/lkl/include/asm/elf.h b/arch/um/lkl/include/asm/elf.h new file mode 100644 index 000000000000..bb2456d638f4 --- /dev/null +++ b/arch/um/lkl/include/asm/elf.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_LKL_ELF_H +#define _ASM_LKL_ELF_H + +#define elf_check_arch(x) 0 + +#ifdef CONFIG_64BIT +#define ELF_CLASS ELFCLASS64 +#else +#define ELF_CLASS ELFCLASS32 +#endif + +#define elf_gregset_t long +#define elf_fpregset_t double +#endif diff --git a/arch/um/lkl/include/asm/processor.h b/arch/um/lkl/include/asm/processor.h new file mode 100644 index 000000000000..c1aa8b3a266e --- /dev/null +++ b/arch/um/lkl/include/asm/processor.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_LKL_PROCESSOR_H +#define _ASM_LKL_PROCESSOR_H + +struct task_struct; + +static inline void cpu_relax(void) +{ + unsigned long flags; + + /* since this is usually called in a tight loop waiting for some + * external condition (e.g. jiffies) lets run interrupts now to allow + * the external condition to propagate + */ + local_irq_save(flags); + local_irq_restore(flags); +} + +#define current_text_addr() ({ __label__ _l; _l: &&_l; }) + +static inline unsigned long thread_saved_pc(struct task_struct *tsk) +{ + return 0; +} + +static inline void release_thread(struct task_struct *dead_task) +{ +} + +static inline void prepare_to_copy(struct task_struct *tsk) +{ +} + +static inline unsigned long get_wchan(struct task_struct *p) +{ + return 0; +} + +static inline void flush_thread(void) +{ +} + +static inline void trap_init(void) +{ +} + +struct thread_struct { }; + +#define INIT_THREAD { } + +#define task_pt_regs(tsk) (struct pt_regs *)(NULL) + +/* We don't have strict user/kernel spaces */ +#define TASK_SIZE ((unsigned long)-1) +#define TASK_UNMAPPED_BASE 0 + +#define KSTK_EIP(tsk) (0) +#define KSTK_ESP(tsk) (0) + +#endif diff --git a/arch/um/lkl/include/asm/ptrace.h b/arch/um/lkl/include/asm/ptrace.h new file mode 100644 index 000000000000..28199be26dc0 --- /dev/null +++ b/arch/um/lkl/include/asm/ptrace.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_LKL_PTRACE_H +#define _ASM_LKL_PTRACE_H + +#include + +struct task_struct; + +#define user_mode(regs) 0 +#define kernel_mode(regs) 1 +#define profile_pc(regs) 0 +#define instruction_pointer(regs) 0 +#define user_stack_pointer(regs) 0 + +static inline long arch_ptrace(struct task_struct *child, long request, + unsigned long addr, unsigned long data) +{ + return -EINVAL; +} + +static inline void ptrace_disable(struct task_struct *child) +{ +} + +#endif diff --git a/arch/um/lkl/include/asm/sched.h b/arch/um/lkl/include/asm/sched.h new file mode 100644 index 000000000000..4c2635921ec8 --- /dev/null +++ b/arch/um/lkl/include/asm/sched.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_LKL_SCHED_H +#define _ASM_LKL_SCHED_H + +#include +#include + +static inline void thread_sched_jb(void) +{ + if (test_ti_thread_flag(current_thread_info(), TIF_HOST_THREAD)) { + set_ti_thread_flag(current_thread_info(), TIF_SCHED_JB); + set_current_state(TASK_UNINTERRUPTIBLE); + lkl_ops->jmp_buf_set(¤t_thread_info()->sched_jb, + schedule); + } else { + lkl_bug("%s() can be used only for host task\n", __func__); + } +} + +void switch_to_host_task(struct task_struct *); +int host_task_stub(void *unused); + +#endif /* _ASM_LKL_SCHED_H */ diff --git a/arch/um/lkl/include/asm/syscalls.h b/arch/um/lkl/include/asm/syscalls.h new file mode 100644 index 000000000000..2eaa870a9020 --- /dev/null +++ b/arch/um/lkl/include/asm/syscalls.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_LKL_SYSCALLS_H +#define _ASM_LKL_SYSCALLS_H + +int syscalls_init(void); +void syscalls_cleanup(void); +long lkl_syscall(long no, long *params); +void wakeup_idle_host_task(void); + +#define sys_mmap sys_mmap_pgoff +#define sys_mmap2 sys_mmap_pgoff +#define sys_clone sys_ni_syscall +#define sys_vfork sys_ni_syscall +#define sys_rt_sigreturn sys_ni_syscall + +#include + +#endif /* _ASM_LKL_SYSCALLS_H */ diff --git a/arch/um/lkl/include/asm/syscalls_32.h b/arch/um/lkl/include/asm/syscalls_32.h new file mode 100644 index 000000000000..0e1a7649c81b --- /dev/null +++ b/arch/um/lkl/include/asm/syscalls_32.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_SYSCALLS_32_H +#define _ASM_SYSCALLS_32_H + +#include +#include +#include +#include + +#if __BITS_PER_LONG == 32 + +/* kernel/syscalls_32.c */ +asmlinkage long sys32_truncate64(const char __user *, unsigned long, + unsigned long); +asmlinkage long sys32_ftruncate64(unsigned int, unsigned long, unsigned long); + +#ifdef CONFIG_MMU +struct mmap_arg_struct32; +asmlinkage long sys32_mmap(struct mmap_arg_struct32 __user *); +#endif + +asmlinkage long sys32_wait4(pid_t, unsigned int __user *, int, + struct rusage __user *); + +asmlinkage long sys32_pread64(unsigned int, char __user *, u32, u32, u32); +asmlinkage long sys32_pwrite64(unsigned int, const char __user *, u32, u32, + u32); + +long sys32_fadvise64_64(int a, __u32 b, __u32 c, __u32 d, __u32 e, int f); + +asmlinkage ssize_t sys32_readahead(int, unsigned int, unsigned int, size_t); +asmlinkage long sys32_sync_file_range(int, unsigned int, unsigned int, + unsigned int, unsigned int, unsigned int); +asmlinkage long sys32_sync_file_range2(int, unsigned int, unsigned int, + unsigned int, unsigned int, + unsigned int); +asmlinkage long sys32_fadvise64(int, unsigned int, unsigned int, size_t, int); +asmlinkage long sys32_fallocate(int, int, unsigned int, unsigned int, + unsigned int, unsigned int); + +#endif /* __BITS_PER_LONG */ + +#endif /* _ASM_SYSCALLS_32_H */ diff --git a/arch/um/lkl/include/asm/tlb.h b/arch/um/lkl/include/asm/tlb.h new file mode 100644 index 000000000000..d474890d317d --- /dev/null +++ b/arch/um/lkl/include/asm/tlb.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_LKL_TLB_H +#define _ASM_LKL_TLB_H + +#define tlb_start_vma(tlb, vma) do { } while (0) +#define tlb_end_vma(tlb, vma) do { } while (0) +#define __tlb_remove_tlb_entry(tlb, pte, address) do { } while (0) +#define tlb_flush(tlb) do { } while (0) + +#include + +#endif /* _ASM_LKL_TLB_H */ diff --git a/arch/um/lkl/include/asm/uaccess.h b/arch/um/lkl/include/asm/uaccess.h new file mode 100644 index 000000000000..f267ac3be8b3 --- /dev/null +++ b/arch/um/lkl/include/asm/uaccess.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_LKL_UACCESS_H +#define _ASM_LKL_UACCESS_H + +/* copied from old include/asm-generic/uaccess.h */ +static inline __must_check long +raw_copy_from_user(void *to, const void __user *from, unsigned long n) +{ + if (__builtin_constant_p(n)) { + switch (n) { + case 1: + *(u8 *)to = *(u8 __force *)from; + return 0; + case 2: + *(u16 *)to = *(u16 __force *)from; + return 0; + case 4: + *(u32 *)to = *(u32 __force *)from; + return 0; +#ifdef CONFIG_64BIT + case 8: + *(u64 *)to = *(u64 __force *)from; + return 0; +#endif + default: + break; + } + } + + memcpy(to, (const void __force *)from, n); + return 0; +} + +static inline __must_check long +raw_copy_to_user(void __user *to, const void *from, unsigned long n) +{ + if (__builtin_constant_p(n)) { + switch (n) { + case 1: + *(u8 __force *)to = *(u8 *)from; + return 0; + case 2: + *(u16 __force *)to = *(u16 *)from; + return 0; + case 4: + *(u32 __force *)to = *(u32 *)from; + return 0; +#ifdef CONFIG_64BIT + case 8: + *(u64 __force *)to = *(u64 *)from; + return 0; +#endif + default: + break; + } + } + + memcpy((void __force *)to, from, n); + return 0; +} + +#include + +#endif diff --git a/arch/um/lkl/include/asm/unistd_32.h b/arch/um/lkl/include/asm/unistd_32.h new file mode 100644 index 000000000000..8582a55e61e2 --- /dev/null +++ b/arch/um/lkl/include/asm/unistd_32.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#include + +#ifndef __SYSCALL +#define __SYSCALL(x, y) +#endif + +#if __BITS_PER_LONG == 32 +__SYSCALL(__NR3264_truncate, sys32_truncate64) +__SYSCALL(__NR3264_ftruncate, sys32_ftruncate64) + +#ifdef CONFIG_MMU +__SYSCALL(__NR3264_mmap, sys32_mmap) +#endif + +__SYSCALL(__NR_wait4, sys32_wait4) + +__SYSCALL(__NR_pread64, sys32_pread64) +__SYSCALL(__NR_pwrite64, sys32_pwrite64) + +__SYSCALL(__NR_readahead, sys32_readahead) +#ifdef __ARCH_WANT_SYNC_FILE_RANGE2 +__SYSCALL(__NR_sync_file_range2, sys32_sync_file_range2) +#else +__SYSCALL(__NR_sync_file_range, sys32_sync_file_range) +#endif +/* mm/fadvise.c */ +__SYSCALL(__NR3264_fadvise64, sys32_fadvise64_64) +__SYSCALL(__NR_fallocate, sys32_fallocate) + +#endif diff --git a/arch/um/lkl/include/asm/vmalloc.h b/arch/um/lkl/include/asm/vmalloc.h new file mode 100644 index 000000000000..46de2e4f03c7 --- /dev/null +++ b/arch/um/lkl/include/asm/vmalloc.h @@ -0,0 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LKL_VMALLOC_H +#define _LKL_VMALLOC_H + +#endif /* _LKL_VMALLOC_H */ diff --git a/arch/um/lkl/include/asm/vmlinux.lds.h b/arch/um/lkl/include/asm/vmlinux.lds.h new file mode 100644 index 000000000000..a3c285882dc4 --- /dev/null +++ b/arch/um/lkl/include/asm/vmlinux.lds.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LKL_VMLINUX_LDS_H +#define _LKL_VMLINUX_LDS_H + +/* we encode our own __ro_after_init section */ +#define RO_AFTER_INIT_DATA + +#ifdef __MINGW32__ +#define RODATA_SECTION .rdata +#endif + +#include + +#endif diff --git a/arch/um/lkl/include/asm/xor.h b/arch/um/lkl/include/asm/xor.h new file mode 100644 index 000000000000..286ce75b5d9d --- /dev/null +++ b/arch/um/lkl/include/asm/xor.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_LKL_XOR_H +#define _ASM_LKL_XOR_H + +#include + +#define XOR_SELECT_TEMPLATE(x) (&xor_block_8regs) + +#endif /* _ASM_LKL_XOR_H */ diff --git a/arch/um/lkl/include/uapi/asm/Kbuild b/arch/um/lkl/include/uapi/asm/Kbuild new file mode 100644 index 000000000000..e1f554364a56 --- /dev/null +++ b/arch/um/lkl/include/uapi/asm/Kbuild @@ -0,0 +1,11 @@ +# UAPI Header export list + +generic-y += elf.h +generic-y += kvm_para.h +generic-y += shmparam.h +generic-y += siginfo.h +generic-y += swab.h +generic-y += timex.h + +# no header-y since we need special user headers handling +# see arch/lkl/script/headers.py diff --git a/arch/um/lkl/include/uapi/asm/bitsperlong.h b/arch/um/lkl/include/uapi/asm/bitsperlong.h new file mode 100644 index 000000000000..8b4ebf2b0264 --- /dev/null +++ b/arch/um/lkl/include/uapi/asm/bitsperlong.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _ASM_UAPI_LKL_BITSPERLONG_H +#define _ASM_UAPI_LKL_BITSPERLONG_H + +#ifdef CONFIG_64BIT +#define __BITS_PER_LONG 64 +#else +#define __BITS_PER_LONG 32 +#endif + +#define __ARCH_WANT_STAT64 + +#endif /* _ASM_UAPI_LKL_BITSPERLONG_H */ diff --git a/arch/um/lkl/include/uapi/asm/byteorder.h b/arch/um/lkl/include/uapi/asm/byteorder.h new file mode 100644 index 000000000000..3c4a58d2062f --- /dev/null +++ b/arch/um/lkl/include/uapi/asm/byteorder.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _ASM_UAPI_LKL_BYTEORDER_H +#define _ASM_UAPI_LKL_BYTEORDER_H + +#if defined(CONFIG_BIG_ENDIAN) +#include +#else +#include +#endif + +#endif /* _ASM_UAPI_LKL_BYTEORDER_H */ diff --git a/arch/um/lkl/include/uapi/asm/syscalls.h b/arch/um/lkl/include/uapi/asm/syscalls.h new file mode 100644 index 000000000000..a81534ffccb7 --- /dev/null +++ b/arch/um/lkl/include/uapi/asm/syscalls.h @@ -0,0 +1,348 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _ASM_UAPI_LKL_SYSCALLS_H +#define _ASM_UAPI_LKL_SYSCALLS_H + +#include +#include + +typedef __kernel_uid32_t qid_t; +typedef __kernel_fd_set fd_set; +typedef __kernel_mode_t mode_t; +typedef unsigned short umode_t; +typedef __u32 nlink_t; +typedef __kernel_off_t off_t; +typedef __kernel_pid_t pid_t; +typedef __kernel_key_t key_t; +typedef __kernel_suseconds_t suseconds_t; +typedef __kernel_timer_t timer_t; +typedef __kernel_clockid_t clockid_t; +typedef __kernel_mqd_t mqd_t; +typedef __kernel_uid32_t uid_t; +typedef __kernel_gid32_t gid_t; +typedef __kernel_uid16_t uid16_t; +typedef __kernel_gid16_t gid16_t; +typedef unsigned long uintptr_t; +#ifdef CONFIG_UID16 +typedef __kernel_old_uid_t old_uid_t; +typedef __kernel_old_gid_t old_gid_t; +#endif +typedef __kernel_loff_t loff_t; +typedef __kernel_size_t size_t; +typedef __kernel_ssize_t ssize_t; +typedef __kernel_time_t time_t; +typedef __kernel_clock_t clock_t; +typedef __u32 u32; +typedef __s32 s32; +typedef __u64 u64; +typedef __s64 s64; + +#define __user + +#include +/* Temporary undefine system calls that don't have data types defined in UAPI + * headers + */ +#undef __NR_kexec_load +#undef __NR_getcpu +#undef __NR_sched_getattr +#undef __NR_sched_setattr +#undef __NR_sched_setparam +#undef __NR_sched_getparam +#undef __NR_sched_setscheduler +#undef __NR_name_to_handle_at +#undef __NR_open_by_handle_at + +/* deprecated system calls */ +#undef __NR_epoll_create +#undef __NR_epoll_wait +#undef __NR_access +#undef __NR_chmod +#undef __NR_chown +#undef __NR_lchown +#undef __NR_open +#undef __NR_creat +#undef __NR_readlink +#undef __NR_pipe +#undef __NR_mknod +#undef __NR_mkdir +#undef __NR_rmdir +#undef __NR_unlink +#undef __NR_symlink +#undef __NR_link +#undef __NR_rename +#undef __NR_getdents +#undef __NR_select +#undef __NR_poll +#undef __NR_dup2 +#undef __NR_futimesat +#undef __NR_utimes +#undef __NR_ustat +#undef __NR_eventfd +#undef __NR_bdflush +#undef __NR_send +#undef __NR_recv + +#undef __NR_umount +#define __NR_umount __NR_umount2 + +#ifdef CONFIG_64BIT +#define __NR_newfstat __NR3264_fstat +#define __NR_newfstatat __NR3264_fstatat +#endif + +#define __NR_mmap_pgoff __NR3264_mmap + +#include +#include +#include +#include +#define __KERNEL__ /* to pull in S_ definitions */ +#include +#undef __KERNEL__ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Define data structures used in system calls that are not defined in UAPI + * headers + */ +struct sockaddr { + unsigned short int sa_family; + char sa_data[14]; +}; + +#define __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO 1 +#define __UAPI_DEF_IF_IFNAMSIZ 1 +#define __UAPI_DEF_IF_NET_DEVICE_FLAGS 1 +#define __UAPI_DEF_IF_IFREQ 1 +#define __UAPI_DEF_IF_IFMAP 1 +#include +#define __UAPI_DEF_IN_IPPROTO 1 +#define __UAPI_DEF_IN_ADDR 1 +#define __UAPI_DEF_IN6_ADDR 1 +#define __UAPI_DEF_IP_MREQ 1 +#define __UAPI_DEF_IN_PKTINFO 1 +#define __UAPI_DEF_SOCKADDR_IN 1 +#define __UAPI_DEF_IN_CLASS 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +struct user_msghdr { + void __user *msg_name; + int msg_namelen; + struct iovec __user *msg_iov; + __kernel_size_t msg_iovlen; + void __user *msg_control; + __kernel_size_t msg_controllen; + unsigned int msg_flags; +}; + +typedef __u32 key_serial_t; + +struct mmsghdr { + struct user_msghdr msg_hdr; + unsigned int msg_len; +}; + +struct linux_dirent64 { + u64 d_ino; + s64 d_off; + unsigned short d_reclen; + unsigned char d_type; + char d_name[0]; +}; + +struct linux_dirent { + unsigned long d_ino; + unsigned long d_off; + unsigned short d_reclen; + char d_name[1]; +}; + +struct ustat { + __kernel_daddr_t f_tfree; + __kernel_ino_t f_tinode; + char f_fname[6]; + char f_fpack[6]; +}; + +typedef __kernel_rwf_t rwf_t; + +#define AF_UNSPEC 0 +#define AF_UNIX 1 +#define AF_LOCAL 1 +#define AF_INET 2 +#define AF_AX25 3 +#define AF_IPX 4 +#define AF_APPLETALK 5 +#define AF_NETROM 6 +#define AF_BRIDGE 7 +#define AF_ATMPVC 8 +#define AF_X25 9 +#define AF_INET6 10 +#define AF_ROSE 11 +#define AF_DECnet 12 +#define AF_NETBEUI 13 +#define AF_SECURITY 14 +#define AF_KEY 15 +#define AF_NETLINK 16 +#define AF_ROUTE AF_NETLINK +#define AF_PACKET 17 +#define AF_ASH 18 +#define AF_ECONET 19 +#define AF_ATMSVC 20 +#define AF_RDS 21 +#define AF_SNA 22 +#define AF_IRDA 23 +#define AF_PPPOX 24 +#define AF_WANPIPE 25 +#define AF_LLC 26 +#define AF_IB 27 +#define AF_MPLS 28 +#define AF_CAN 29 +#define AF_TIPC 30 +#define AF_BLUETOOTH 31 +#define AF_IUCV 32 +#define AF_RXRPC 33 +#define AF_ISDN 34 +#define AF_PHONET 35 +#define AF_IEEE802154 36 +#define AF_CAIF 37 +#define AF_ALG 38 +#define AF_NFC 39 +#define AF_VSOCK 40 + +#define SOCK_STREAM 1 +#define SOCK_DGRAM 2 +#define SOCK_RAW 3 +#define SOCK_RDM 4 +#define SOCK_SEQPACKET 5 +#define SOCK_DCCP 6 +#define SOCK_PACKET 10 + +#define MSG_TRUNC 0x20 +#define MSG_DONTWAIT 0x40 + +/* avoid colision with system headers defines */ +#define sa_handler sa_handler +#define st_atime st_atime +#define st_mtime st_mtime +#define st_ctime st_ctime +#define s_addr s_addr + +long lkl_syscall(long no, long *params); +long lkl_sys_halt(void); + +#define __MAP0(m, ...) +#define __MAP1(m, t, a) m(t, a) +#define __MAP2(m, t, a, ...) m(t, a), __MAP1(m, __VA_ARGS__) +#define __MAP3(m, t, a, ...) m(t, a), __MAP2(m, __VA_ARGS__) +#define __MAP4(m, t, a, ...) m(t, a), __MAP3(m, __VA_ARGS__) +#define __MAP5(m, t, a, ...) m(t, a), __MAP4(m, __VA_ARGS__) +#define __MAP6(m, t, a, ...) m(t, a), __MAP5(m, __VA_ARGS__) +#define __MAP(n, ...) __MAP##n(__VA_ARGS__) + +#define __SC_LONG(t, a) (long)a +#define __SC_TABLE(t, a) {sizeof(t), (long long)(a)} +#define __SC_DECL(t, a) t a + +#define LKL_SYSCALL0(name) \ + static inline long lkl_sys##name(void) \ + { \ + long params[6]; \ + return lkl_syscall(__lkl__NR##name, params); \ + } + +#if __BITS_PER_LONG == 32 +#define LKL_SYSCALLx(x, name, ...) \ + static inline \ + long lkl_sys##name(__MAP(x, __SC_DECL, __VA_ARGS__)) \ + { \ + struct { \ + unsigned int size; \ + long long value; \ + } lkl_params[x] = { __MAP(x, __SC_TABLE, __VA_ARGS__) }; \ + long sys_params[6], i, k; \ + for (i = k = 0; i < x && k < 6; i++, k++) { \ + if (lkl_params[i].size > sizeof(long) && \ + k + 1 < 6) { \ + sys_params[k] = \ + (long)(lkl_params[i].value & (-1UL)); \ + k++; \ + sys_params[k] = \ + (long)(lkl_params[i].value >> \ + __BITS_PER_LONG); \ + } else { \ + sys_params[k] = (long)(lkl_params[i].value); \ + } \ + } \ + return lkl_syscall(__lkl__NR##name, sys_params); \ + } +#else +#define LKL_SYSCALLx(x, name, ...) \ + static inline \ + long lkl_sys##name(__MAP(x, __SC_DECL, __VA_ARGS__)) \ + { \ + long lkl_params[6] = { __MAP(x, __SC_LONG, __VA_ARGS__) }; \ + return lkl_syscall(__lkl__NR##name, lkl_params); \ + } +#endif + +#define SYSCALL_DEFINE0(name, ...) LKL_SYSCALL0(name) +#define SYSCALL_DEFINE1(name, ...) LKL_SYSCALLx(1, name, __VA_ARGS__) +#define SYSCALL_DEFINE2(name, ...) LKL_SYSCALLx(2, name, __VA_ARGS__) +#define SYSCALL_DEFINE3(name, ...) LKL_SYSCALLx(3, name, __VA_ARGS__) +#define SYSCALL_DEFINE4(name, ...) LKL_SYSCALLx(4, name, __VA_ARGS__) +#define SYSCALL_DEFINE5(name, ...) LKL_SYSCALLx(5, name, __VA_ARGS__) +#define SYSCALL_DEFINE6(name, ...) LKL_SYSCALLx(6, name, __VA_ARGS__) + +#if __BITS_PER_LONG == 32 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpointer-to-int-cast" +#endif + +#include + +#if __BITS_PER_LONG == 32 +#pragma GCC diagnostic pop +#endif + +#endif diff --git a/arch/um/lkl/kernel/asm-offsets.c b/arch/um/lkl/kernel/asm-offsets.c new file mode 100644 index 000000000000..6be0763698dc --- /dev/null +++ b/arch/um/lkl/kernel/asm-offsets.c @@ -0,0 +1,2 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Dummy asm-offsets.c file. Required by kbuild and ready to be used - hint! */ diff --git a/arch/um/lkl/kernel/misc.c b/arch/um/lkl/kernel/misc.c new file mode 100644 index 000000000000..60f048f02ae6 --- /dev/null +++ b/arch/um/lkl/kernel/misc.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_PRINTK +void dump_stack(void) +{ + unsigned long dummy; + unsigned long *stack = &dummy; + unsigned long addr; + + pr_info("Call Trace:\n"); + while (((long)stack & (THREAD_SIZE - 1)) != 0) { + addr = *stack; + if (__kernel_text_address(addr)) { + pr_info("%p: [<%08lx>] %pS", stack, addr, + (void *)addr); + pr_cont("\n"); + } + stack++; + } + pr_info("\n"); +} +#endif + +void show_regs(struct pt_regs *regs) +{ +} + +#ifdef CONFIG_PROC_FS +static void *cpuinfo_start(struct seq_file *m, loff_t *pos) +{ + return NULL; +} + +static void *cpuinfo_next(struct seq_file *m, void *v, loff_t *pos) +{ + return NULL; +} + +static void cpuinfo_stop(struct seq_file *m, void *v) +{ +} + +static int show_cpuinfo(struct seq_file *m, void *v) +{ + return 0; +} + +const struct seq_operations cpuinfo_op = { + .start = cpuinfo_start, + .next = cpuinfo_next, + .stop = cpuinfo_stop, + .show = show_cpuinfo, +}; +#endif diff --git a/arch/um/lkl/kernel/vmlinux.lds.S b/arch/um/lkl/kernel/vmlinux.lds.S new file mode 100644 index 000000000000..f57c563522cb --- /dev/null +++ b/arch/um/lkl/kernel/vmlinux.lds.S @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#include +#include +#include +#include +#include + +OUTPUT_FORMAT(CONFIG_OUTPUT_FORMAT) + +jiffies = jiffies_64; + +SECTIONS +{ + __init_begin = .; + HEAD_TEXT_SECTION + INIT_TEXT_SECTION(PAGE_SIZE) + INIT_DATA_SECTION(16) + PERCPU_SECTION(L1_CACHE_BYTES) + __init_end = .; + + _stext = .; + _text = . ; + text = . ; + .text : + { + TEXT_TEXT + SCHED_TEXT + LOCK_TEXT + CPUIDLE_TEXT + } + _etext = .; + + _sdata = .; + RO_DATA(PAGE_SIZE) + RW_DATA(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE) + _edata = .; + + __start_ro_after_init = .; + .data..ro_after_init : { *(.data..ro_after_init)} + EXCEPTION_TABLE(16) + __end_ro_after_init = .; + NOTES + + BSS_SECTION(0, 0, 0) + _end = .; + + STABS_DEBUG + DWARF_DEBUG + + DISCARDS +} From patchwork Mon Mar 30 14:45:35 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hajime Tazaki X-Patchwork-Id: 1263978 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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=fKn2kNjL; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=sA8XzZhH; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (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 48rZzm3rTnz9sP7 for ; Tue, 31 Mar 2020 01:47:00 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.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=Pq5fOG0XdxNceUgDYIgXcah9vAg2X/1QJKzLY0OLFq0=; b=fKn2kNjLvizVe7 eB6OpQogMqOFNNyNWb69Z+Ps7I9JJp1igg2+QnD2y+fcIcsEFPFWcfMnPg+t9xx31FtZ8wISX+00B 663QLL9/4MjzpkYIMwbuqSNJmyCT2I9oCYDpOEg5XSE5b8eDQA/PAqsaf/J4byy33pq8g/oFpdnef 9AeT6Z69r0YRXac8UlIZTsSVuHMFLeO6S0ajNzD0D6Zrqbv3vChr8lqo7rIZpKFLQ5+nUtTN+e0NV Y8lrvjR7/JKaAyeuwONyig2VZSKyW3MDsDxwxhgRu6BC4RUK0urp9cQsBXoEypK+ez/WixLWSptQ1 8f0seosPlAwxZ5L3MlBA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvgj-0004Un-Ea; Mon, 30 Mar 2020 14:46:53 +0000 Received: from mail-pj1-x1043.google.com ([2607:f8b0:4864:20::1043]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvgg-0004Tk-CT for linux-um@lists.infradead.org; Mon, 30 Mar 2020 14:46:51 +0000 Received: by mail-pj1-x1043.google.com with SMTP id w9so7680389pjh.1 for ; Mon, 30 Mar 2020 07:46:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=RKef0Si42OEfpiKCb0RBwsAXF8ojY8UauQkTHAz5Bio=; b=sA8XzZhH5GUZt+NtMsglSqJvWTyDg098LTWUZd40WhrgZa8/Nej6Tg5l4XbwTaMZ00 PGHYQwd6AgFgdonzdYiJMca3LHSeGgQrVhByo+4xWAdAlehp/Edj8IXvyeRipJfD5ifb RO1KP5GPY/E7i1ZO10xL56obwpz1AUedc02sRn/TzIIegtzqnXGU85ed4qz0iYMTKhxD LJvBgFa8ghE7aPslNuN7CQMniCVtbLYWkVj8MUCiEm4Fgwo74dfGyDknL7SzikZCQl9h 52u2/QZ8BwXIb/0BsAg4f/L575+Kr/pPsbOkp64ZD84zSBx4IWHCxEJQtOGAw+azAbjp L+tg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=RKef0Si42OEfpiKCb0RBwsAXF8ojY8UauQkTHAz5Bio=; b=C0ZzAfTJ9oo55VLsj8zm3WATBAps/RV3aPtWWME1+Yukwy22/Cakka6Jr6LZFzU6VW qVcvfb933aCcG13woeXVhypMJrHCU0IRsnDC8IMXlN3FBmpSOOIHtvsYYqnwJYVGdFz2 cWPcqbsRLgKl+0yG8xhWuDISBqgRWAn3HZcl93vQBM2s82nfdRPfwUmFZOKQHF4B/L5H aoTMSnmven2PswMIYMlPC3x48bom1+AprHGvTS3CO4btbvDsv6IEwyosznsM8ug1cKMb nElHFeU7wCD3PzwR6Eh+XKkj3houxVQk13oPCG8rp+88gbBGb5JYM8xkzWTJQw8z4YvB uK+A== X-Gm-Message-State: ANhLgQ0oqKj8mhP0fOS5p8rHIkcilbstrlUcgwdSNbN1xi6BBa4LGeLI QrpqbYEVVPIk6GzwJ1KVo54= X-Google-Smtp-Source: ADFU+vv4YV0OjN6LnpWbIA1NvMK/gKAb+8rbdMBw87SqbxIJYjLkoiiG7T6WKuQleqjWaoJCM10z8Q== X-Received: by 2002:a17:902:d705:: with SMTP id w5mr13143925ply.68.1585579609858; Mon, 30 Mar 2020 07:46:49 -0700 (PDT) Received: from earth-mac.local (219x123x138x129.ap219.ftth.ucom.ne.jp. [219.123.138.129]) by smtp.gmail.com with ESMTPSA id 67sm10289633pfe.168.2020.03.30.07.46.48 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 30 Mar 2020 07:46:49 -0700 (PDT) Received: by earth-mac.local (Postfix, from userid 501) id 7A418202804C59; Mon, 30 Mar 2020 23:46:47 +0900 (JST) From: Hajime Tazaki To: linux-um@lists.infradead.org Subject: [RFC v4 03/25] um lkl: host interface Date: Mon, 30 Mar 2020 23:45:35 +0900 Message-Id: X-Mailer: git-send-email 2.20.1 (Apple Git-117) In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200330_074650_452821_8306008E X-CRM114-Status: GOOD ( 11.44 ) X-Spam-Score: -0.2 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:1043 listed in] [list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [thehajime[at]gmail.com] -0.0 SPF_PASS SPF: sender matches SPF record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 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: linux-arch@vger.kernel.org, Hajime Tazaki , Octavian Purdila , Akira Moroo , Patrick Collins , linux-kernel-library@freelists.org, Pierre-Hugues Husson , Michael Zimmermann , Yuan Liu Sender: "linux-um" Errors-To: linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Octavian Purdila This patch introduces the host operations that define the interface between the LKL and the host. These operations must be provided either by a host library or by the application itself. Cc: Michael Zimmermann Cc: Patrick Collins Cc: Pierre-Hugues Husson Cc: Yuan Liu Signed-off-by: Hajime Tazaki Signed-off-by: Octavian Purdila --- arch/um/lkl/include/asm/host_ops.h | 10 ++++++++++ arch/um/lkl/include/uapi/asm/host_ops.h | 26 +++++++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 arch/um/lkl/include/asm/host_ops.h create mode 100644 arch/um/lkl/include/uapi/asm/host_ops.h diff --git a/arch/um/lkl/include/asm/host_ops.h b/arch/um/lkl/include/asm/host_ops.h new file mode 100644 index 000000000000..65850f394b79 --- /dev/null +++ b/arch/um/lkl/include/asm/host_ops.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_LKL_HOST_OPS_H +#define _ASM_LKL_HOST_OPS_H + +#include "irq.h" +#include + +extern struct lkl_host_operations *lkl_ops; + +#endif diff --git a/arch/um/lkl/include/uapi/asm/host_ops.h b/arch/um/lkl/include/uapi/asm/host_ops.h new file mode 100644 index 000000000000..7cfb0a93e6a6 --- /dev/null +++ b/arch/um/lkl/include/uapi/asm/host_ops.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _ASM_UAPI_LKL_HOST_OPS_H +#define _ASM_UAPI_LKL_HOST_OPS_H + +/* Defined in {posix,nt}-host.c */ +struct lkl_mutex; +struct lkl_sem; +struct lkl_tls_key; +typedef unsigned long lkl_thread_t; +struct lkl_jmp_buf { + unsigned long buf[32]; +}; + +/** + * lkl_host_operations - host operations used by the Linux kernel + * + * These operations must be provided by a host library or by the application + * itself. + * + */ +struct lkl_host_operations { +}; + +void lkl_bug(const char *fmt, ...); + +#endif From patchwork Mon Mar 30 14:45:36 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hajime Tazaki X-Patchwork-Id: 1263982 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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=pQ0/lKqK; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=a4gUu1gU; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (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 48rb0M0cV5z9sP7 for ; Tue, 31 Mar 2020 01:47:31 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.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=XohKWZ4wnJhZpL3/y73XkJ77PYEijeu3v16rt9/Ui34=; b=pQ0/lKqKyPsuiC 0hMdRznR2GvZfZ2dugNk2rvzHV4pAlngzJPlvb8eC248Zia4fMSGi/FdjW8bfzUt+o8rR9e6fgkjU ji/ourcwKHSkgB9uxKYc+NaUhaFP7qxW61C82eec2B6dJHbmX4mylczTuYMajaBToSR/Ik7ERhCI0 lmj+Me0uLbEo0LNDhzVOzII2YKHp6KjWADHIpRguW5+UEgZbpp44pbaKtruRp4Srn9GGL+/P3G1og 1Fa39o4G3G5vrQq4FxnrZtR24CzZ4WDsuyIL0lIxR2m1h809OZ1V1e5CrEckKSneIDfju+xicNlyh oF+vEJ1fLY5MaJoLgN3A==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvhD-0004lL-HE; Mon, 30 Mar 2020 14:47:23 +0000 Received: from mail-pj1-x1044.google.com ([2607:f8b0:4864:20::1044]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvh9-0004kL-RA for linux-um@lists.infradead.org; Mon, 30 Mar 2020 14:47:21 +0000 Received: by mail-pj1-x1044.google.com with SMTP id kx8so7414092pjb.5 for ; Mon, 30 Mar 2020 07:47:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=7r3Fmz9uH6eUoLXG/+dpk0ne5HgRyoo2jAEaQ9QR82s=; b=a4gUu1gUohM+F52DQpF7CFon5gdqlI3P3kQjoKLNnC4dS1fe5tpUYXn7IguFIDPS1B YlGjN1CBE9zP1y1ttzi4GYUZedpR/hxZAo8hyKx+3bTisywKI2XvvGvO5nKlo1qXT4Nb Hz7jjOFH/PI2yx8FaZ/USQL4GkA8r+K5UYmuYm81Hy/vOIP4+ZS2SgY+9cuWBW4gbQZV ftPGJzVpUV/G3KEU+SFqjCJ8yQhL1Jye9MLJNl1lknjrVu6ngbnbjjN7FlUOpdeW2npw iGRNFRmyq+0Ua54IE33SG87ifcxXnlBbRtAhlEYRKsqbxuQFxyQxtdoGxu1a0MyrV/s7 +8kQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=7r3Fmz9uH6eUoLXG/+dpk0ne5HgRyoo2jAEaQ9QR82s=; b=C19E/QOSW/wG0YINW84enDvm92dYb/16KzHyEfbI9FywHHd8Knw0+MeZzfapRKtko6 71xXG2JnEF5MIO+TS33KSIZAR9U2MHV2IZHohLBuFYTCJGCatxONESfFdit9idwFS5tj EEkRFiptizMGVpOG3VRymVzICml4t3SaAVMBxKF/N9NTQ/5SzO42ZlKxPLE3CA5/XOUY yQqrbfrFnZBh+rMJCuUzwX80i3V3DrIEDR9tNUNpCNMywCpyMPm3tYN6cntrR8azHhyQ tRg4d9MdkeUt+WGA7bdmZKk+YxS3jbbzlptZvTVy9mx7sQxvlo2zPuK5FvjniRGzSdwv AlJg== X-Gm-Message-State: ANhLgQ3sYUZtSK+ZhJ/wnmLeF+k9pWJWHyeHcZD9KQ9fJ0ypdcptFGd/ y3Xz8BlLN3FsYDD9QEe5g9o7gPk8WsUU4A== X-Google-Smtp-Source: ADFU+vv3iQ3v4ML1iraGxXMdzlVLAaGwCsSDDCNxDAQ1j9lia+x5we67kUVvbrLwNbaAKnQyKywoTw== X-Received: by 2002:a17:90a:228c:: with SMTP id s12mr16345022pjc.68.1585579639174; Mon, 30 Mar 2020 07:47:19 -0700 (PDT) Received: from earth-mac.local (219x123x138x129.ap219.ftth.ucom.ne.jp. [219.123.138.129]) by smtp.gmail.com with ESMTPSA id l7sm10547776pfl.171.2020.03.30.07.47.18 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 30 Mar 2020 07:47:18 -0700 (PDT) Received: by earth-mac.local (Postfix, from userid 501) id B0D59202804C8A; Mon, 30 Mar 2020 23:47:01 +0900 (JST) From: Hajime Tazaki To: linux-um@lists.infradead.org Subject: [RFC v4 04/25] um lkl: memory handling Date: Mon, 30 Mar 2020 23:45:36 +0900 Message-Id: <39950bf12f6b4380f95e227c9373102ac76acc18.1585579244.git.thehajime@gmail.com> X-Mailer: git-send-email 2.20.1 (Apple Git-117) In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200330_074719_902027_F13DF77C X-CRM114-Status: GOOD ( 16.57 ) X-Spam-Score: -0.2 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:1044 listed in] [list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [thehajime[at]gmail.com] -0.0 SPF_PASS SPF: sender matches SPF record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 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: linux-arch@vger.kernel.org, Levente Kurusa , Octavian Purdila , Akira Moroo , Hajime Tazaki , linux-kernel-library@freelists.org, Yuan Liu Sender: "linux-um" Errors-To: linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Octavian Purdila LKL is a non MMU architecture and hence there is not much work left to do other than initializing the boot allocator and providing the page and page table definitions. The backstore memory is allocated via a host operation and the memory size to be used is specified when the kernel is started, in the lkl_start_kernel call. Cc: H.K. Jerry Chu Cc: Levente Kurusa Cc: Yuan Liu Signed-off-by: Hajime Tazaki Signed-off-by: Octavian Purdila --- arch/um/lkl/include/asm/page.h | 14 ++++++ arch/um/lkl/include/asm/pgtable.h | 57 +++++++++++++++++++++ arch/um/lkl/include/uapi/asm/host_ops.h | 5 ++ arch/um/lkl/mm/bootmem.c | 66 +++++++++++++++++++++++++ 4 files changed, 142 insertions(+) create mode 100644 arch/um/lkl/include/asm/page.h create mode 100644 arch/um/lkl/include/asm/pgtable.h create mode 100644 arch/um/lkl/mm/bootmem.c diff --git a/arch/um/lkl/include/asm/page.h b/arch/um/lkl/include/asm/page.h new file mode 100644 index 000000000000..e77f3da22031 --- /dev/null +++ b/arch/um/lkl/include/asm/page.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_LKL_PAGE_H +#define _ASM_LKL_PAGE_H + +#define CONFIG_KERNEL_RAM_BASE_ADDRESS memory_start + +#ifndef __ASSEMBLY__ +void free_mem(void); +void bootmem_init(unsigned long mem_size); +#endif + +#include + +#endif /* _ASM_LKL_PAGE_H */ diff --git a/arch/um/lkl/include/asm/pgtable.h b/arch/um/lkl/include/asm/pgtable.h new file mode 100644 index 000000000000..733beb6d53f6 --- /dev/null +++ b/arch/um/lkl/include/asm/pgtable.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LKL_PGTABLE_H +#define _LKL_PGTABLE_H + +#include + +/* + * (C) Copyright 2000-2002, Greg Ungerer + */ + +#include +#include +#include + +#define pgd_present(pgd) (1) +#define pgd_none(pgd) (0) +#define pgd_bad(pgd) (0) +#define pgd_clear(pgdp) +#define kern_addr_valid(addr) (1) +#define pmd_offset(a, b) ((void *)0) + +#define PAGE_NONE __pgprot(0) +#define PAGE_SHARED __pgprot(0) +#define PAGE_COPY __pgprot(0) +#define PAGE_READONLY __pgprot(0) +#define PAGE_KERNEL __pgprot(0) + +void paging_init(void); +#define swapper_pg_dir ((pgd_t *)0) + +#define __swp_type(x) (0) +#define __swp_offset(x) (0) +#define __swp_entry(typ, off) ((swp_entry_t) { ((typ) | ((off) << 7)) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) + +/* + * ZERO_PAGE is a global shared page that is always zero: used + * for zero-mapped memory areas etc.. + */ +extern void *empty_zero_page; +#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page)) + +/* + * All 32bit addresses are effectively valid for vmalloc... + * Sort of meaningless for non-VM targets. + */ +#define VMALLOC_START 0 +#define VMALLOC_END 0xffffffff +#define KMAP_START 0 +#define KMAP_END 0xffffffff + +#include + +#define check_pgt_cache() do { } while (0) + +#endif diff --git a/arch/um/lkl/include/uapi/asm/host_ops.h b/arch/um/lkl/include/uapi/asm/host_ops.h index 7cfb0a93e6a6..6bbc94c120be 100644 --- a/arch/um/lkl/include/uapi/asm/host_ops.h +++ b/arch/um/lkl/include/uapi/asm/host_ops.h @@ -17,8 +17,13 @@ struct lkl_jmp_buf { * These operations must be provided by a host library or by the application * itself. * + * @mem_alloc - allocate memory + * @mem_free - free memory + * */ struct lkl_host_operations { + void *(*mem_alloc)(unsigned long mem); + void (*mem_free)(void *mem); }; void lkl_bug(const char *fmt, ...); diff --git a/arch/um/lkl/mm/bootmem.c b/arch/um/lkl/mm/bootmem.c new file mode 100644 index 000000000000..39dd0d22b44e --- /dev/null +++ b/arch/um/lkl/mm/bootmem.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include + +unsigned long memory_start, memory_end; +static unsigned long _memory_start, mem_size; + +void *empty_zero_page; + +void __init bootmem_init(unsigned long mem_sz) +{ + mem_size = mem_sz; + + _memory_start = (unsigned long)lkl_ops->mem_alloc(mem_size); + memory_start = _memory_start; + WARN_ON(!memory_start); + memory_end = memory_start + mem_size; + + if (PAGE_ALIGN(memory_start) != memory_start) { + mem_size -= PAGE_ALIGN(memory_start) - memory_start; + memory_start = PAGE_ALIGN(memory_start); + mem_size = (mem_size / PAGE_SIZE) * PAGE_SIZE; + } + pr_info("memblock address range: 0x%lx - 0x%lx\n", memory_start, + memory_start + mem_size); + /* + * Give all the memory to the bootmap allocator, tell it to put the + * boot mem_map at the start of memory. + */ + max_low_pfn = virt_to_pfn(memory_end); + min_low_pfn = virt_to_pfn(memory_start); + memblock_add(memory_start, mem_size); + + empty_zero_page = memblock_alloc(PAGE_SIZE, PAGE_SIZE); + memset((void *)empty_zero_page, 0, PAGE_SIZE); + + { + unsigned long zones_size[MAX_NR_ZONES] = {0, }; + + zones_size[ZONE_NORMAL] = (mem_size) >> PAGE_SHIFT; + free_area_init(zones_size); + } +} + +void __init mem_init(void) +{ + max_mapnr = (((unsigned long)high_memory) - PAGE_OFFSET) >> PAGE_SHIFT; + /* this will put all memory onto the freelists */ + totalram_pages_add(memblock_free_all()); + pr_info("Memory available: %luk/%luk RAM\n", + (nr_free_pages() << PAGE_SHIFT) >> 10, mem_size >> 10); +} + +/* + * In our case __init memory is not part of the page allocator so there is + * nothing to free. + */ +void free_initmem(void) +{ +} + +void free_mem(void) +{ + lkl_ops->mem_free((void *)_memory_start); +} From patchwork Mon Mar 30 14:45:37 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hajime Tazaki X-Patchwork-Id: 1263980 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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=LPlNls+i; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=FftiiuEB; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (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 48rb0D2kGwz9sRf for ; Tue, 31 Mar 2020 01:47:24 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.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=33LzZ9F82KoWOYfCwKnKA06Lb58n1CVzn9lNhVHC3rY=; b=LPlNls+iWkzjvY EeaIfnWkNQpWPGupAVa6AhAaeJW9RCXeSVh/2EG0WdNvUNTGOc5+JkbcMTtaXoRDEpajuaou9RaET NgLj9TSd4re6JsTnLBCRrJuEWYWnYvd8oRJLUNwpCd+AeUzFaSI+QSsYUYdZoSFVs+5XP5jNuyoT1 pAIZkrwV8OrW68nM1fbzWv2K88SZDyFqZO2BRwsm2lYDfijbaiFCmaq1oI9GWrQasoIqnIZxSmS3l sKZ6vpDGn87K7i2E6GfnkgIjCy71G5lygPPtcYeTDMLCyw13G+rgL7rwNIQ5QYUDKOnzHCMemHOXb C8dz8u1izEJUgqCwRdKQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvh4-0004ig-T4; Mon, 30 Mar 2020 14:47:14 +0000 Received: from mail-pj1-x1042.google.com ([2607:f8b0:4864:20::1042]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvh1-0004gi-Is for linux-um@lists.infradead.org; Mon, 30 Mar 2020 14:47:14 +0000 Received: by mail-pj1-x1042.google.com with SMTP id w9so7681112pjh.1 for ; Mon, 30 Mar 2020 07:47:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=GIQcIQ+25C2PbtdQpPQLdEstHve27+lEeoM4U2juW8w=; b=FftiiuEBgA3DDQuUsCCf3NJeUWTFpoRPneMiQVikSulDp0nTSbH40jrTJ2bxaryQHN ClzHcVhQuX2QEm0HcIQxCN+eZMprJEFkhAitSv1bbUhcvPH/dujYP1v7npuYlAWPumcP uapnVqMc79n0KIHhZ8Ljz/QU+rGCSjAxNRIddPGdLNvRrxJN5TggbUPnAEpiFIm+uHBF yd3ZxEHSG27Aw/8sdHQ5KxoKouzTsitJAdQpy25CdSAlm1U+y8upWaEDnwWnBpelJeYg lmDZWVkp8nAAXZYkUfbbS9MrbQJCE7psUkqiRs2NC4mn7nLSJEzth8LmES/k15H6X0OA WPNw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=GIQcIQ+25C2PbtdQpPQLdEstHve27+lEeoM4U2juW8w=; b=RgsEJtEW5sSGg29xEViOdfewtEa8rsXn5bX3x7um9ncgkt/n377wOP61+ek3Q8RQFi HID1G4J9mCnGLMjhVna1cJ7aSHzofX8yvkgRw/h1A/BczC6p5+74Qpvdk8MwDtalUKMa MzLPIPyU5rKfjV1TXOI6RDdn00G9fbiP2nJ+lzMc1SiOlJ7wRWijcAE0bUz+tm2UYZOC rlEt0hCdGh9dIvhODzbpWHhjDWxXFaSMQzENfabu8nHScEt4H4mmSHrerC8lkvwKRKtJ f3MrPI4Vo6bg8TO94xWaLIRfteIX0utocqxtQ1iFw4thKJJiBGeLfV64dDinQCR6uqjd pq5w== X-Gm-Message-State: ANhLgQ0N1z58ihd5W3aYRasChHhnSRg+MZY1lse4B3xI5hbDp1pw4lxk FAgVHZpx1SCMGGKbq3ouUb68N3YpqMK1MA== X-Google-Smtp-Source: ADFU+vsDY3SsExL75nhCaOpAhCfsPdvYwz+MhPoWKeA+Z8ldE4387z5/nDCZEILYyyfpcY/IEa4W4w== X-Received: by 2002:a17:902:347:: with SMTP id 65mr12919646pld.21.1585579630853; Mon, 30 Mar 2020 07:47:10 -0700 (PDT) Received: from earth-mac.local (219x123x138x129.ap219.ftth.ucom.ne.jp. [219.123.138.129]) by smtp.gmail.com with ESMTPSA id q185sm10293812pfb.154.2020.03.30.07.47.09 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 30 Mar 2020 07:47:10 -0700 (PDT) Received: by earth-mac.local (Postfix, from userid 501) id 7A55A202804CBE; Mon, 30 Mar 2020 23:47:07 +0900 (JST) From: Hajime Tazaki To: linux-um@lists.infradead.org Subject: [RFC v4 05/25] um lkl: kernel threads support Date: Mon, 30 Mar 2020 23:45:37 +0900 Message-Id: X-Mailer: git-send-email 2.20.1 (Apple Git-117) In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200330_074711_669764_611559FD X-CRM114-Status: GOOD ( 27.05 ) X-Spam-Score: -0.2 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:1042 listed in] [list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [thehajime[at]gmail.com] -0.0 SPF_PASS SPF: sender matches SPF record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 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: linux-arch@vger.kernel.org, Hajime Tazaki , Octavian Purdila , Lai Jiangshan , Akira Moroo , Patrick Collins , linux-kernel-library@freelists.org, Yuan Liu Sender: "linux-um" Errors-To: linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Octavian Purdila LKL does not support user processes but it must support kernel threads as part as the normal kernel work-flow. It uses host operations to create and terminate host threads that are going to run the kernel threads. It also uses semaphores to synchronize those threads and to allow the Linux kernel scheduler to control how the kernel threads run. Each kernel thread runs in a host threads and has a host semaphore associated with it - the thread's scheduling semaphore. The semaphore counter is initialized to 0. The first thing a kernel thread does after getting spawned, before running any kernel code, is to perform a down operation to block the thread. The kernel controls host threads scheduling by performing up and down operations on the scheduling semaphore. In __switch_context an up operation on the next thread is performed to wake up a blocked thread, and a down operation is performed on the prev thread to block it. A thread is terminated by marking it in free_thread_info and performing an up operation on the scheduling semaphore at which point the marked thread will terminate itself. Cc: Lai Jiangshan Cc: Patrick Collins Cc: Yuan Liu Signed-off-by: Hajime Tazaki Signed-off-by: Octavian Purdila --- arch/um/lkl/include/asm/thread_info.h | 70 ++++++++ arch/um/lkl/include/uapi/asm/host_ops.h | 55 ++++++ arch/um/lkl/kernel/cpu.c | 223 +++++++++++++++++++++++ arch/um/lkl/kernel/threads.c | 227 ++++++++++++++++++++++++ 4 files changed, 575 insertions(+) create mode 100644 arch/um/lkl/include/asm/thread_info.h create mode 100644 arch/um/lkl/kernel/cpu.c create mode 100644 arch/um/lkl/kernel/threads.c diff --git a/arch/um/lkl/include/asm/thread_info.h b/arch/um/lkl/include/asm/thread_info.h new file mode 100644 index 000000000000..da4e75fc7b10 --- /dev/null +++ b/arch/um/lkl/include/asm/thread_info.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_LKL_THREAD_INFO_H +#define _ASM_LKL_THREAD_INFO_H + +#define THREAD_SIZE (4096) + +#ifndef __ASSEMBLY__ +#include +#include +#include + +typedef struct { + unsigned long seg; +} mm_segment_t; + +struct thread_info { + struct task_struct *task; + unsigned long flags; + int preempt_count; + mm_segment_t addr_limit; + struct lkl_sem *sched_sem; + struct lkl_jmp_buf sched_jb; + bool dead; + lkl_thread_t tid; + struct task_struct *prev_sched; + unsigned long stackend; +}; + +#define INIT_THREAD_INFO(tsk) \ +{ \ + .task = &tsk, \ + .preempt_count = INIT_PREEMPT_COUNT, \ + .flags = 0, \ + .addr_limit = KERNEL_DS, \ +} + +/* how to get the thread information struct from C */ +extern struct thread_info *_current_thread_info; +static inline struct thread_info *current_thread_info(void) +{ + return _current_thread_info; +} + +/* thread information allocation */ +unsigned long *alloc_thread_stack_node(struct task_struct *, int node); +void free_thread_stack(struct task_struct *tsk); + +void threads_init(void); +void threads_cleanup(void); + +#define TIF_SYSCALL_TRACE 0 +#define TIF_NOTIFY_RESUME 1 +#define TIF_SIGPENDING 2 +#define TIF_NEED_RESCHED 3 +#define TIF_RESTORE_SIGMASK 4 +#define TIF_MEMDIE 5 +#define TIF_NOHZ 6 +#define TIF_SCHED_JB 7 +#define TIF_HOST_THREAD 8 + +#define __HAVE_THREAD_FUNCTIONS + +#define task_thread_info(task) ((struct thread_info *)(task)->stack) +#define task_stack_page(task) ((task)->stack) +void setup_thread_stack(struct task_struct *p, struct task_struct *org); +#define end_of_stack(p) (&task_thread_info(p)->stackend) + +#endif /* __ASSEMBLY__ */ + +#endif diff --git a/arch/um/lkl/include/uapi/asm/host_ops.h b/arch/um/lkl/include/uapi/asm/host_ops.h index 6bbc94c120be..19924fc7c718 100644 --- a/arch/um/lkl/include/uapi/asm/host_ops.h +++ b/arch/um/lkl/include/uapi/asm/host_ops.h @@ -17,15 +17,70 @@ struct lkl_jmp_buf { * These operations must be provided by a host library or by the application * itself. * + * @sem_alloc - allocate a host semaphore an initialize it to count + * @sem_free - free a host semaphore + * @sem_up - perform an up operation on the semaphore + * @sem_down - perform a down operation on the semaphore + * + * @mutex_alloc - allocate and initialize a host mutex; the recursive parameter + * determines if the mutex is recursive or not + * @mutex_free - free a host mutex + * @mutex_lock - acquire the mutex + * @mutex_unlock - release the mutex + * + * @thread_create - create a new thread and run f(arg) in its context; returns a + * thread handle or 0 if the thread could not be created + * @thread_detach - on POSIX systems, free up resources held by + * pthreads. Noop on Win32. + * @thread_exit - terminates the current thread + * @thread_join - wait for the given thread to terminate. Returns 0 + * for success, -1 otherwise + * * @mem_alloc - allocate memory * @mem_free - free memory * + * @gettid - returns the host thread id of the caller, which need not + * be the same as the handle returned by thread_create + * + * @jmp_buf_set - runs the give function and setups a jump back point by saving + * the context in the jump buffer; jmp_buf_longjmp can be called from the give + * function or any callee in that function to return back to the jump back + * point + * + * NOTE: we can't return from jmp_buf_set before calling jmp_buf_longjmp or + * otherwise the saved context (stack) is not going to be valid, so we must pass + * the function that will eventually call longjmp here + * + * @jmp_buf_longjmp - perform a jump back to the saved jump buffer */ struct lkl_host_operations { + struct lkl_sem *(*sem_alloc)(int count); + void (*sem_free)(struct lkl_sem *sem); + void (*sem_up)(struct lkl_sem *sem); + void (*sem_down)(struct lkl_sem *sem); + + struct lkl_mutex *(*mutex_alloc)(int recursive); + void (*mutex_free)(struct lkl_mutex *mutex); + void (*mutex_lock)(struct lkl_mutex *mutex); + void (*mutex_unlock)(struct lkl_mutex *mutex); + + lkl_thread_t (*thread_create)(void (*f)(void *), void *arg); + void (*thread_detach)(void); + void (*thread_exit)(void); + int (*thread_join)(lkl_thread_t tid); + lkl_thread_t (*thread_self)(void); + int (*thread_equal)(lkl_thread_t a, lkl_thread_t b); + void *(*mem_alloc)(unsigned long mem); void (*mem_free)(void *mem); + + long (*gettid)(void); + + void (*jmp_buf_set)(struct lkl_jmp_buf *jmpb, void (*f)(void)); + void (*jmp_buf_longjmp)(struct lkl_jmp_buf *jmpb, int val); }; +int lkl_printf(const char *fmt, ...); void lkl_bug(const char *fmt, ...); #endif diff --git a/arch/um/lkl/kernel/cpu.c b/arch/um/lkl/kernel/cpu.c new file mode 100644 index 000000000000..125af3b2d5dd --- /dev/null +++ b/arch/um/lkl/kernel/cpu.c @@ -0,0 +1,223 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * This structure is used to get access to the "LKL CPU" that allows us to run + * Linux code. Because we have to deal with various synchronization requirements + * between idle thread, system calls, interrupts, "reentrancy", CPU shutdown, + * imbalance wake up (i.e. acquire the CPU from one thread and release it from + * another), we can't use a simple synchronization mechanism such as (recursive) + * mutex or semaphore. Instead, we use a mutex and a bunch of status data plus a + * semaphore. + */ +static struct lkl_cpu { + /* lock that protects the CPU status data */ + struct lkl_mutex *lock; + /* + * Since we must free the cpu lock during shutdown we need a + * synchronization algorithm between lkl_cpu_shutdown() and the CPU + * access functions since lkl_cpu_get() gets called from thread + * destructor callback functions which may be scheduled after + * lkl_cpu_shutdown() has freed the cpu lock. + * + * An atomic counter is used to keep track of the number of running + * CPU access functions and allow the shutdown function to wait for + * them. + * + * The shutdown functions adds MAX_THREADS to this counter which allows + * the CPU access functions to check if the shutdown process has + * started. + * + * This algorithm assumes that we never have more the MAX_THREADS + * requesting CPU access. + */ + #define MAX_THREADS 1000000 + unsigned int shutdown_gate; + bool irqs_pending; + /* no of threads waiting the CPU */ + unsigned int sleepers; + /* no of times the current thread got the CPU */ + unsigned int count; + /* current thread that owns the CPU */ + lkl_thread_t owner; + /* semaphore for threads waiting the CPU */ + struct lkl_sem *sem; + /* semaphore used for shutdown */ + struct lkl_sem *shutdown_sem; +} cpu; + +static int __cpu_try_get_lock(int n) +{ + lkl_thread_t self; + + if (__sync_fetch_and_add(&cpu.shutdown_gate, n) >= MAX_THREADS) + return -2; + + lkl_ops->mutex_lock(cpu.lock); + + if (cpu.shutdown_gate >= MAX_THREADS) + return -1; + + self = lkl_ops->thread_self(); + + if (cpu.owner && !lkl_ops->thread_equal(cpu.owner, self)) + return 0; + + cpu.owner = self; + cpu.count++; + + return 1; +} + +static void __cpu_try_get_unlock(int lock_ret, int n) +{ + if (lock_ret >= -1) + lkl_ops->mutex_unlock(cpu.lock); + __sync_fetch_and_sub(&cpu.shutdown_gate, n); +} + +void lkl_cpu_change_owner(lkl_thread_t owner) +{ + lkl_ops->mutex_lock(cpu.lock); + if (cpu.count > 1) + lkl_bug("bad count while changing owner\n"); + cpu.owner = owner; + lkl_ops->mutex_unlock(cpu.lock); +} + +int lkl_cpu_get(void) +{ + int ret; + + ret = __cpu_try_get_lock(1); + + while (ret == 0) { + cpu.sleepers++; + __cpu_try_get_unlock(ret, 0); + lkl_ops->sem_down(cpu.sem); + ret = __cpu_try_get_lock(0); + } + + __cpu_try_get_unlock(ret, 1); + + return ret; +} + +void lkl_cpu_put(void) +{ + lkl_ops->mutex_lock(cpu.lock); + + if (!cpu.count || !cpu.owner || + !lkl_ops->thread_equal(cpu.owner, lkl_ops->thread_self())) + lkl_bug("%s: unbalanced put\n", __func__); + + while (cpu.irqs_pending && !irqs_disabled()) { + cpu.irqs_pending = false; + lkl_ops->mutex_unlock(cpu.lock); + run_irqs(); + lkl_ops->mutex_lock(cpu.lock); + } + + if (test_ti_thread_flag(current_thread_info(), TIF_HOST_THREAD) && + !single_task_running() && cpu.count == 1) { + if (in_interrupt()) + lkl_bug("%s: in interrupt\n", __func__); + lkl_ops->mutex_unlock(cpu.lock); + thread_sched_jb(); + return; + } + + if (--cpu.count > 0) { + lkl_ops->mutex_unlock(cpu.lock); + return; + } + + if (cpu.sleepers) { + cpu.sleepers--; + lkl_ops->sem_up(cpu.sem); + } + + cpu.owner = 0; + + lkl_ops->mutex_unlock(cpu.lock); +} + +int lkl_cpu_try_run_irq(int irq) +{ + int ret; + + ret = __cpu_try_get_lock(1); + if (!ret) { + set_irq_pending(irq); + cpu.irqs_pending = true; + } + __cpu_try_get_unlock(ret, 1); + + return ret; +} + +void lkl_cpu_shutdown(void) +{ + __sync_fetch_and_add(&cpu.shutdown_gate, MAX_THREADS); +} + +void lkl_cpu_wait_shutdown(void) +{ + lkl_ops->sem_down(cpu.shutdown_sem); + lkl_ops->sem_free(cpu.shutdown_sem); +} + +static void lkl_cpu_cleanup(bool shutdown) +{ + while (__sync_fetch_and_add(&cpu.shutdown_gate, 0) > MAX_THREADS) + ; + + if (shutdown) + lkl_ops->sem_up(cpu.shutdown_sem); + else if (cpu.shutdown_sem) + lkl_ops->sem_free(cpu.shutdown_sem); + if (cpu.sem) + lkl_ops->sem_free(cpu.sem); + if (cpu.lock) + lkl_ops->mutex_free(cpu.lock); +} + +void arch_cpu_idle(void) +{ + if (cpu.shutdown_gate >= MAX_THREADS) { + lkl_ops->mutex_lock(cpu.lock); + while (cpu.sleepers--) + lkl_ops->sem_up(cpu.sem); + lkl_ops->mutex_unlock(cpu.lock); + + lkl_cpu_cleanup(true); + + lkl_ops->thread_exit(); + } + /* enable irqs now to allow direct irqs to run */ + local_irq_enable(); + + /* switch to idle_host_task */ + wakeup_idle_host_task(); +} + +int lkl_cpu_init(void) +{ + cpu.lock = lkl_ops->mutex_alloc(0); + cpu.sem = lkl_ops->sem_alloc(0); + cpu.shutdown_sem = lkl_ops->sem_alloc(0); + + if (!cpu.lock || !cpu.sem || !cpu.shutdown_sem) { + lkl_cpu_cleanup(false); + return -ENOMEM; + } + + return 0; +} diff --git a/arch/um/lkl/kernel/threads.c b/arch/um/lkl/kernel/threads.c new file mode 100644 index 000000000000..4fe8c56ae5e0 --- /dev/null +++ b/arch/um/lkl/kernel/threads.c @@ -0,0 +1,227 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include +#include + +static int init_ti(struct thread_info *ti) +{ + ti->sched_sem = lkl_ops->sem_alloc(0); + if (!ti->sched_sem) + return -ENOMEM; + + ti->dead = false; + ti->prev_sched = NULL; + ti->tid = 0; + + return 0; +} + +unsigned long *alloc_thread_stack_node(struct task_struct *task, int node) +{ + struct thread_info *ti; + + ti = kmalloc(sizeof(*ti), GFP_KERNEL); + if (!ti) + return NULL; + + if (init_ti(ti)) { + kfree(ti); + return NULL; + } + ti->task = task; + + return (unsigned long *)ti; +} + +/* + * The only new tasks created are kernel threads that have a predefined starting + * point thus no stack copy is required. + */ +void setup_thread_stack(struct task_struct *p, struct task_struct *org) +{ + struct thread_info *ti = task_thread_info(p); + struct thread_info *org_ti = task_thread_info(org); + + ti->flags = org_ti->flags; + ti->preempt_count = org_ti->preempt_count; + ti->addr_limit = org_ti->addr_limit; +} + +static void kill_thread(struct thread_info *ti) +{ + if (!test_ti_thread_flag(ti, TIF_HOST_THREAD)) { + ti->dead = true; + lkl_ops->sem_up(ti->sched_sem); + lkl_ops->thread_join(ti->tid); + } + lkl_ops->sem_free(ti->sched_sem); +} + +void free_thread_stack(struct task_struct *tsk) +{ + struct thread_info *ti = task_thread_info(tsk); + + kill_thread(ti); + kfree(ti); +} + +struct thread_info *_current_thread_info = &init_thread_union.thread_info; + +/* + * schedule() expects the return of this function to be the task that we + * switched away from. Returning prev is not going to work because we are + * actually going to return the previous taks that was scheduled before the + * task we are going to wake up, and not the current task, e.g.: + * + * swapper -> init: saved prev on swapper stack is swapper + * init -> ksoftirqd0: saved prev on init stack is init + * ksoftirqd0 -> swapper: returned prev is swapper + */ +static struct task_struct *abs_prev = &init_task; + +struct task_struct *__switch_to(struct task_struct *prev, + struct task_struct *next) +{ + struct thread_info *_prev = task_thread_info(prev); + struct thread_info *_next = task_thread_info(next); + unsigned long _prev_flags = _prev->flags; + struct lkl_jmp_buf _prev_jb; + + _current_thread_info = task_thread_info(next); + _next->prev_sched = prev; + abs_prev = prev; + + BUG_ON(!_next->tid); + lkl_cpu_change_owner(_next->tid); + + if (test_bit(TIF_SCHED_JB, &_prev_flags)) { + /* Atomic. Must be done before wakeup next */ + clear_ti_thread_flag(_prev, TIF_SCHED_JB); + _prev_jb = _prev->sched_jb; + } + + lkl_ops->sem_up(_next->sched_sem); + if (test_bit(TIF_SCHED_JB, &_prev_flags)) + lkl_ops->jmp_buf_longjmp(&_prev_jb, 1); + else + lkl_ops->sem_down(_prev->sched_sem); + + if (_prev->dead) + lkl_ops->thread_exit(); + + return abs_prev; +} + +int host_task_stub(void *unused) +{ + return 0; +} + +void switch_to_host_task(struct task_struct *task) +{ + if (WARN_ON(!test_tsk_thread_flag(task, TIF_HOST_THREAD))) + return; + + task_thread_info(task)->tid = lkl_ops->thread_self(); + + if (current == task) + return; + + wake_up_process(task); + thread_sched_jb(); + lkl_ops->sem_down(task_thread_info(task)->sched_sem); + schedule_tail(abs_prev); +} + +struct thread_bootstrap_arg { + struct thread_info *ti; + int (*f)(void *arg); + void *arg; +}; + +static void thread_bootstrap(void *_tba) +{ + struct thread_bootstrap_arg *tba = (struct thread_bootstrap_arg *)_tba; + struct thread_info *ti = tba->ti; + int (*f)(void *) = tba->f; + void *arg = tba->arg; + + lkl_ops->sem_down(ti->sched_sem); + kfree(tba); + if (ti->prev_sched) + schedule_tail(ti->prev_sched); + + f(arg); + do_exit(0); +} + +int copy_thread(unsigned long clone_flags, unsigned long esp, + unsigned long unused, struct task_struct *p) +{ + struct thread_info *ti = task_thread_info(p); + struct thread_bootstrap_arg *tba; + + if ((int (*)(void *))esp == host_task_stub) { + set_ti_thread_flag(ti, TIF_HOST_THREAD); + return 0; + } + + tba = kmalloc(sizeof(*tba), GFP_KERNEL); + if (!tba) + return -ENOMEM; + + tba->f = (int (*)(void *))esp; + tba->arg = (void *)unused; + tba->ti = ti; + + ti->tid = lkl_ops->thread_create(thread_bootstrap, tba); + if (!ti->tid) { + kfree(tba); + return -ENOMEM; + } + + return 0; +} + +void show_stack(struct task_struct *task, unsigned long *esp) +{ +} + +/** + * This is called before the kernel initializes, so no kernel calls (including + * printk) can't be made yet. + */ +void threads_init(void) +{ + int ret; + struct thread_info *ti = &init_thread_union.thread_info; + + ret = init_ti(ti); + if (ret < 0) + lkl_printf("lkl: failed to allocate init schedule semaphore\n"); + + ti->tid = lkl_ops->thread_self(); +} + +void threads_cleanup(void) +{ + struct task_struct *p, *t; + + for_each_process_thread(p, t) { + struct thread_info *ti = task_thread_info(t); + + if (t->pid != 1 && !test_ti_thread_flag(ti, TIF_HOST_THREAD)) + WARN(!(t->flags & PF_KTHREAD), + "non kernel thread task %s\n", t->comm); + WARN(t->state == TASK_RUNNING, + "thread %s still running while halting\n", t->comm); + + kill_thread(ti); + } + + lkl_ops->sem_free(init_thread_union.thread_info.sched_sem); +} From patchwork Mon Mar 30 14:45:38 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hajime Tazaki X-Patchwork-Id: 1263981 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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=mD0tApU4; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=OEmP8KBi; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (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 48rb0H02tXz9sQt for ; Tue, 31 Mar 2020 01:47:27 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.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=23K14R5iuZmZCa/xDczvth6pcsb/S+HSJfwc6FqQc4M=; b=mD0tApU4RDHM1n tgDsxNiuQnsAftuVoW75FgXtYOlHUDLuQHIurfFaGswvnfOp+51bIdiBBE9LC6u4FyENVzZj3CQrW Yr6QnCJxMdufpQj7t2H51NYv0NppXKuOT+PRJ7FIG1WBX7Uy9is5/RYJ0+NPbTURgFsi9Dnwk0qRq wiGADF4hrE+gwVvplitOSOiVnZ6D8i8tKUdsLVURlxfHYfPy8S7thtA//pKBEk1jwL+x210zLemvg N5vf4l9ap+q3+Bj8ukJnsprQN1kdWyTUncqUHnW7cHceiszoEGX/Z0N9jq7JDr8K72ehxof0FWAo4 K5AuoOuXLCM+8zuLoxVw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvh9-0004k3-4s; Mon, 30 Mar 2020 14:47:19 +0000 Received: from mail-pg1-x543.google.com ([2607:f8b0:4864:20::543]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvh5-0004iy-OE for linux-um@lists.infradead.org; Mon, 30 Mar 2020 14:47:17 +0000 Received: by mail-pg1-x543.google.com with SMTP id a32so8755604pga.4 for ; Mon, 30 Mar 2020 07:47:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=J9G/kWXWjhk5wlU2qddt8RP0B1h9r/gLTCrz8limKXo=; b=OEmP8KBi4AlyBE1lJnVZjGPGgKXqfOr7Q+zAH/VSyw/ye7QNIQFHHN2mtZy4eTmktv ZbLfi/AWrphAPV5wbA/Vdw44C8YCFMEaUckMsY5x1dnK9lII02jEGgtnQBdZ0rDHtCD2 1UM4F/5LhV8qiDtys+wLzPq7W+SkwQudA03LdufSU35n89S1YdfIOLdEOnv4CjtQlYsA gJSyx+dOsIE2p9vI4AgJ7BHDIaRFmoaDqfedg+Hs6th2Xjx19Fh5RovMb1Q4FgehkY7k QEIY2THJlM2B/Zn0l4xmTePN+ii8SW338aIpOZeyJdbgRjahfyl3jTBRXj1oMbi6BcfE oRfg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=J9G/kWXWjhk5wlU2qddt8RP0B1h9r/gLTCrz8limKXo=; b=hLVTY8RIM40UV9b3KAunhM+La9i9Cj1rX0Gu130BYQTJ9VagHkB8EdOh69Az6ErKaM WY1fmOVBszZw1ZC/kbSxmNVpm1CHDx0VZMdDIw64dj7gZ7g2HcY8pPrviWbsWjyHTqIe YyESWrPjFcNEdZdQ0EpWkQyAqUBk8gQDaR2M6vsi41LDSxCGrMyFCzqgZeUQKj8Zw5Ym TM2hekfgqUGeKHoUMxAtiewO/6EKG6eOsSJ1aAHDhYVUdyrdUM1/EIOsNAw2FICn5Zh3 J3q+6jgXCq4k0s8GvWRk7HW1fGqKLrra1sHt7mr9eulZW6msBDGz2XVhWcopGS/wFXk/ 3ezA== X-Gm-Message-State: ANhLgQ3dZsmjS8kqJ/5j1qVdwjBXc+m7gW8W8uGj/sKMM6w+0V/JQva+ xWBXl5f0ztVf+X/JHGR7z7A= X-Google-Smtp-Source: ADFU+vtV6RwWvAIo11TszHeCQN1wNWVsN8GOw4SWnypNwQizc8eMmDIik7XCRffPqF2CmWv9YaJxiQ== X-Received: by 2002:aa7:9481:: with SMTP id z1mr12811358pfk.185.1585579635092; Mon, 30 Mar 2020 07:47:15 -0700 (PDT) Received: from earth-mac.local (219x123x138x129.ap219.ftth.ucom.ne.jp. [219.123.138.129]) by smtp.gmail.com with ESMTPSA id p22sm9818866pgn.73.2020.03.30.07.47.13 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 30 Mar 2020 07:47:14 -0700 (PDT) Received: by earth-mac.local (Postfix, from userid 501) id 8125A202804CD6; Mon, 30 Mar 2020 23:47:12 +0900 (JST) From: Hajime Tazaki To: linux-um@lists.infradead.org Subject: [RFC v4 06/25] um lkl: interrupt support Date: Mon, 30 Mar 2020 23:45:38 +0900 Message-Id: X-Mailer: git-send-email 2.20.1 (Apple Git-117) In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200330_074715_827173_7D38B7C8 X-CRM114-Status: GOOD ( 23.10 ) X-Spam-Score: -0.2 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:543 listed in] [list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [thehajime[at]gmail.com] -0.0 SPF_PASS SPF: sender matches SPF record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 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: linux-arch@vger.kernel.org, Octavian Purdila , Akira Moroo , linux-kernel-library@freelists.org, Michael Zimmermann , Hajime Tazaki Sender: "linux-um" Errors-To: linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Octavian Purdila Add APIs that allows the host to reserve and free and interrupt number and also to trigger an interrupt. The trigger operation will simply store the interrupt data in queue. The interrupt handler is run later, at the first opportunity it has to avoid races with any kernel threads. Currently, interrupts are run on the first interrupt enable operation if interrupts are disabled and if we are not already in interrupt context. When triggering an interrupt, it uses GCC's built-in functions for atomic memory access to synchronize and simple boolean flags. Cc: Michael Zimmermann Signed-off-by: Hajime Tazaki Signed-off-by: Octavian Purdila --- arch/um/lkl/include/asm/irq.h | 13 ++ arch/um/lkl/include/uapi/asm/irq.h | 36 ++++ arch/um/lkl/include/uapi/asm/sigcontext.h | 16 ++ arch/um/lkl/kernel/irq.c | 190 ++++++++++++++++++++++ 4 files changed, 255 insertions(+) create mode 100644 arch/um/lkl/include/asm/irq.h create mode 100644 arch/um/lkl/include/uapi/asm/irq.h create mode 100644 arch/um/lkl/include/uapi/asm/sigcontext.h create mode 100644 arch/um/lkl/kernel/irq.c diff --git a/arch/um/lkl/include/asm/irq.h b/arch/um/lkl/include/asm/irq.h new file mode 100644 index 000000000000..948fc54cb76c --- /dev/null +++ b/arch/um/lkl/include/asm/irq.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_LKL_IRQ_H +#define _ASM_LKL_IRQ_H + +#define IRQ_STATUS_BITS (sizeof(long) * 8) +#define NR_IRQS ((int)(IRQ_STATUS_BITS * IRQ_STATUS_BITS)) + +void run_irqs(void); +void set_irq_pending(int irq); + +#include + +#endif diff --git a/arch/um/lkl/include/uapi/asm/irq.h b/arch/um/lkl/include/uapi/asm/irq.h new file mode 100644 index 000000000000..666628b233eb --- /dev/null +++ b/arch/um/lkl/include/uapi/asm/irq.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _ASM_UAPI_LKL_IRQ_H +#define _ASM_UAPI_LKL_IRQ_H + +/** + * lkl_trigger_irq - generate an interrupt + * + * This function is used by the device host side to signal its Linux counterpart + * that some event happened. + * + * @irq - the irq number to signal + */ +int lkl_trigger_irq(int irq); + +/** + * lkl_get_free_irq - find and reserve a free IRQ number + * + * This function is called by the host device code to find an unused IRQ number + * and reserved it for its own use. + * + * @user - a string to identify the user + * @returns - and irq number that can be used by request_irq or an negative + * value in case of an error + */ +int lkl_get_free_irq(const char *user); + +/** + * lkl_put_irq - release an IRQ number previously obtained with lkl_get_free_irq + * + * @irq - irq number to release + * @user - string identifying the user; should be the same as the one passed to + * lkl_get_free_irq when the irq number was obtained + */ +void lkl_put_irq(int irq, const char *name); + +#endif diff --git a/arch/um/lkl/include/uapi/asm/sigcontext.h b/arch/um/lkl/include/uapi/asm/sigcontext.h new file mode 100644 index 000000000000..2f4848843d1d --- /dev/null +++ b/arch/um/lkl/include/uapi/asm/sigcontext.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _ASM_UAPI_LKL_SIGCONTEXT_H +#define _ASM_UAPI_LKL_SIGCONTEXT_H + +#include + +struct pt_regs { + void *irq_data; +}; + +struct sigcontext { + struct pt_regs regs; + unsigned long oldmask; +}; + +#endif diff --git a/arch/um/lkl/kernel/irq.c b/arch/um/lkl/kernel/irq.c new file mode 100644 index 000000000000..c794412f85d9 --- /dev/null +++ b/arch/um/lkl/kernel/irq.c @@ -0,0 +1,190 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * To avoid much overhead we use an indirect approach: the irqs are marked using + * a bitmap (array of longs) and a summary of the modified bits is kept in a + * separate "index" long - one bit for each sizeof(long). Thus we can support + * 4096 irqs on 64bit platforms and 1024 irqs on 32bit platforms. + * + * Whenever an irq is trigger both the array and the index is updated. To find + * which irqs were triggered we first search the index and then the + * corresponding part of the arrary. + */ +static unsigned long irq_status[NR_IRQS / IRQ_STATUS_BITS]; +static unsigned long irq_index_status; + +static inline unsigned long test_and_clear_irq_index_status(void) +{ + if (!irq_index_status) + return 0; + return __sync_fetch_and_and(&irq_index_status, 0); +} + +static inline unsigned long test_and_clear_irq_status(int index) +{ + if (!&irq_status[index]) + return 0; + return __sync_fetch_and_and(&irq_status[index], 0); +} + +void set_irq_pending(int irq) +{ + int index = irq / IRQ_STATUS_BITS; + int bit = irq % IRQ_STATUS_BITS; + + __sync_fetch_and_or(&irq_status[index], BIT(bit)); + __sync_fetch_and_or(&irq_index_status, BIT(index)); +} + +static struct irq_info { + const char *user; +} irqs[NR_IRQS]; + +static bool irqs_enabled; + +static struct pt_regs dummy; + +static void run_irq(int irq) +{ + unsigned long flags; + struct pt_regs *old_regs = set_irq_regs((struct pt_regs *)&dummy); + + /* interrupt handlers need to run with interrupts disabled */ + local_irq_save(flags); + irq_enter(); + generic_handle_irq(irq); + irq_exit(); + set_irq_regs(old_regs); + local_irq_restore(flags); +} + +/** + * This function can be called from arbitrary host threads, so do not + * issue any Linux calls (e.g. prink) if lkl_cpu_get() was not issued + * before. + */ +int lkl_trigger_irq(int irq) +{ + int ret; + + if (!irq || irq > NR_IRQS) + return -EINVAL; + + ret = lkl_cpu_try_run_irq(irq); + if (ret <= 0) + return ret; + + /* + * Since this can be called from Linux context (e.g. lkl_trigger_irq -> + * IRQ -> softirq -> lkl_trigger_irq) make sure we are actually allowed + * to run irqs at this point + */ + if (!irqs_enabled) + set_irq_pending(irq); + else + run_irq(irq); + + lkl_cpu_put(); + + return 0; +} + +static inline void for_each_bit(unsigned long word, void (*f)(int, int), int j) +{ + int i = 0; + + while (word) { + if (word & 1) + f(i, j); + word >>= 1; + i++; + } +} + +static inline void deliver_irq(int bit, int index) +{ + run_irq(index * IRQ_STATUS_BITS + bit); +} + +static inline void check_irq_status(int i, int unused) +{ + for_each_bit(test_and_clear_irq_status(i), deliver_irq, i); +} + +void run_irqs(void) +{ + for_each_bit(test_and_clear_irq_index_status(), check_irq_status, 0); +} + +int show_interrupts(struct seq_file *p, void *v) +{ + return 0; +} + +int lkl_get_free_irq(const char *user) +{ + int i; + int ret = -EBUSY; + + /* 0 is not a valid IRQ */ + for (i = 1; i < NR_IRQS; i++) { + if (!irqs[i].user) { + irqs[i].user = user; + irq_set_chip_and_handler(i, &dummy_irq_chip, + handle_simple_irq); + ret = i; + break; + } + } + + return ret; +} + +void lkl_put_irq(int i, const char *user) +{ + if (!irqs[i].user || strcmp(irqs[i].user, user) != 0) { + WARN("%s tried to release %s's irq %d", user, irqs[i].user, i); + return; + } + + irqs[i].user = NULL; +} + +unsigned long arch_local_save_flags(void) +{ + return irqs_enabled; +} + +void arch_local_irq_restore(unsigned long flags) +{ + if (flags == ARCH_IRQ_ENABLED && irqs_enabled == ARCH_IRQ_DISABLED && + !in_interrupt()) + run_irqs(); + irqs_enabled = flags; +} + +void init_IRQ(void) +{ + int i; + + for (i = 0; i < NR_IRQS; i++) + irq_set_chip_and_handler(i, &dummy_irq_chip, handle_simple_irq); + + pr_info("lkl: irqs initialized\n"); +} + +void cpu_yield_to_irqs(void) +{ + cpu_relax(); +} From patchwork Mon Mar 30 14:45:39 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hajime Tazaki X-Patchwork-Id: 1263983 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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=ctJvlMfy; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=gFZ3aqJ7; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (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 48rb0v1XRRz9sQt for ; Tue, 31 Mar 2020 01:47:59 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.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=k3UW5tXKR1t1zzr63fZ0d+onojnc4Elb6MJkq76ZwXM=; b=ctJvlMfyhJNRSD vda2n62ucYvMJ69tMMHi8Ck31Y1OY6bOeGlbp+KMkn00Ek7kFa9hhI5J3K0mmoCXdjEDrHA+0T78A tmB/BYa4wLwi4V//uHmn0j37sZanu0PbJ3Uy8CL8Vk5rDV2iEHVNoPw7VNu8h4LAkbfHhMDP8+AeY oF4iq4M4XTKIHvASaTER0qCaJgO9x0M16Dl6sJ7WnHRZEBhaKAIxhwF4LQz2pFzXQOzwV0AcEFjde WFhWj+d0nGfvsPg9e+2PWHog/UAQr5K2LmuzaTg2fXRX36jalqNtwE0vpfWaQgk8pgQ+XXdYZ8JEV p2hScTBuc0EpoLVWliqA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvhe-0004nY-0n; Mon, 30 Mar 2020 14:47:50 +0000 Received: from mail-pl1-x643.google.com ([2607:f8b0:4864:20::643]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvhY-0004n3-QL for linux-um@lists.infradead.org; Mon, 30 Mar 2020 14:47:49 +0000 Received: by mail-pl1-x643.google.com with SMTP id g2so6816465plo.3 for ; Mon, 30 Mar 2020 07:47:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=+Uk5+ZHIYNQeKzs+4Zpbn9bAOvJrAa05qxICMyJH0aU=; b=gFZ3aqJ7UOKbUv2cqj3+T2Ews4PZ84nSDUrwy6VC4g6lFetnp9SH9gYz2vZcKrZoL6 zYBpgIdUYgH4ixZUK9WioYVoYyfQbuGvMYzTgulQjNCTllNxHG6qhCBaHlohF4iZBftg ngWArs38mxRTbl5lYm1sNL7JkJ4BZcZ7IZFNQJnvXBD0Le2x8nf4U7HhHwTib39nO70+ 8GECcRIc80qMttK0zEzl2G9sJryYLL/3nQJnEVOl6KrM7E4bK9O5asCFyOUwLFlRc34H nFmcM65I3ehVtM/EypxPdWVMpNLLjpicEw5JDI6vR1G57uZv3QHqP8+BOlbtB8uBYubo swAQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=+Uk5+ZHIYNQeKzs+4Zpbn9bAOvJrAa05qxICMyJH0aU=; b=Ht5SuMyuivVV046uLGTCvocx+UqsDrHSZO6RrwgZ9nlgy1tzu99f8m7PiozV1tUi8X plV4Vba8x1Nr7I3xAt+gocqN04O2BSzk7hdgQ07IZhA0gBFoGEZwE50PdnIz2w56+qMt HTfGgG5nEFxeEYyoQa9Ca2EwkLmvbmCul4UpDWQWDcIqTl2znSwsq5hggI3pn+FMfMNy SFfTx0fNVSUIk7j7NOKqjzwbPHCnM0P++m7mh1i617/6fg38Wp97bfxfgSNzRQ9/6ina hFrcyPiKF+2IA0N+PsctUvdoAzKLis8uT1HodcP7Hf/19CXs0Uephmc0WiWtLmzaaHFy jYdA== X-Gm-Message-State: ANhLgQ1gt1AO7xGAtiZRNMzOLbmDVVomrbqaRPDX2EiocF6JKRoD/bFd RNfZ9OfOhm/3hcOBOp+Jxgo= X-Google-Smtp-Source: ADFU+vsypHzUCrD8Ejkt3s7QhF8M0XjFOv8J/J++2qeD6qaykcog9S522lNaqDnTkY86lSVExEqudQ== X-Received: by 2002:a17:90a:fd90:: with SMTP id cx16mr16405639pjb.41.1585579664069; Mon, 30 Mar 2020 07:47:44 -0700 (PDT) Received: from earth-mac.local (219x123x138x129.ap219.ftth.ucom.ne.jp. [219.123.138.129]) by smtp.gmail.com with ESMTPSA id a13sm9743667pgi.77.2020.03.30.07.47.43 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 30 Mar 2020 07:47:43 -0700 (PDT) Received: by earth-mac.local (Postfix, from userid 501) id A56A3202804D08; Mon, 30 Mar 2020 23:47:26 +0900 (JST) From: Hajime Tazaki To: linux-um@lists.infradead.org Subject: [RFC v4 07/25] um lkl: system call interface and application API Date: Mon, 30 Mar 2020 23:45:39 +0900 Message-Id: <2cdbea16972f67259c5b19d1933fdfa5513f0f45.1585579244.git.thehajime@gmail.com> X-Mailer: git-send-email 2.20.1 (Apple Git-117) In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200330_074746_925561_AB248EF9 X-CRM114-Status: GOOD ( 22.79 ) X-Spam-Score: -0.2 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:643 listed in] [list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [thehajime[at]gmail.com] -0.0 SPF_PASS SPF: sender matches SPF record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 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: linux-arch@vger.kernel.org, Hajime Tazaki , Conrad Meyer , Octavian Purdila , Jens Staal , Lai Jiangshan , Akira Moroo , Patrick Collins , linux-kernel-library@freelists.org, Pierre-Hugues Husson , Michael Zimmermann , Luca Dariz , Yuan Liu Sender: "linux-um" Errors-To: linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Octavian Purdila The LKL application API is based on the kernel system call interface in order to offer a stable API to applications. Note that we can't offer the full Linux system call interface due to LKL limitations such as lack of virtual memory, signal, user processes, etc. The host is using the LKL interrupt mechanism (lkl_trigger_irq) to initiate a system call. The system call is executed in the context of the init process. To avoid collisions between the Linux API and the LKL API (e.g. struct stat, MKNOD, etc.) we use a python script to modify the user headers and to prefix all of the global symbols (structures, typedefs, defines) with LKL, lkl, _LKL, _lkl, __LKL or __lkl. Cc: Conrad Meyer Cc: Jens Staal Cc: Lai Jiangshan Cc: Luca Dariz Cc: Michael Zimmermann Cc: Patrick Collins Cc: Pierre-Hugues Husson Cc: Yuan Liu Signed-off-by: Hajime Tazaki Signed-off-by: Octavian Purdila --- arch/um/lkl/include/asm/unistd.h | 27 ++++ arch/um/lkl/include/uapi/asm/host_ops.h | 14 ++ arch/um/lkl/include/uapi/asm/unistd.h | 13 ++ arch/um/lkl/kernel/syscalls.c | 192 +++++++++++++++++++++++ arch/um/lkl/kernel/syscalls_32.c | 159 +++++++++++++++++++ arch/um/lkl/scripts/headers_install.py | 196 ++++++++++++++++++++++++ 6 files changed, 601 insertions(+) create mode 100644 arch/um/lkl/include/asm/unistd.h create mode 100644 arch/um/lkl/include/uapi/asm/unistd.h create mode 100644 arch/um/lkl/kernel/syscalls.c create mode 100644 arch/um/lkl/kernel/syscalls_32.c create mode 100755 arch/um/lkl/scripts/headers_install.py diff --git a/arch/um/lkl/include/asm/unistd.h b/arch/um/lkl/include/asm/unistd.h new file mode 100644 index 000000000000..ca0eac0f2827 --- /dev/null +++ b/arch/um/lkl/include/asm/unistd.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#include + +#define __SC_ASCII(t, a) #t "," #a + +#define __ASCII_MAP0(m, ...) +#define __ASCII_MAP1(m, t, a) m(t, a) +#define __ASCII_MAP2(m, t, a, ...) m(t, a) "," __ASCII_MAP1(m, __VA_ARGS__) +#define __ASCII_MAP3(m, t, a, ...) m(t, a) "," __ASCII_MAP2(m, __VA_ARGS__) +#define __ASCII_MAP4(m, t, a, ...) m(t, a) "," __ASCII_MAP3(m, __VA_ARGS__) +#define __ASCII_MAP5(m, t, a, ...) m(t, a) "," __ASCII_MAP4(m, __VA_ARGS__) +#define __ASCII_MAP6(m, t, a, ...) m(t, a) "," __ASCII_MAP5(m, __VA_ARGS__) +#define __ASCII_MAP(n, ...) __ASCII_MAP##n(__VA_ARGS__) + +#ifdef __MINGW32__ +#define SECTION_ATTRS "n0" +#else +#define SECTION_ATTRS "a" +#endif + +#define __SYSCALL_DEFINE_ARCH(x, name, ...) \ + asm(".section .syscall_defs,\"" SECTION_ATTRS "\"\n" \ + ".ascii \"#ifdef __NR" #name "\\n\"\n" \ + ".ascii \"SYSCALL_DEFINE" #x "(" #name "," \ + __ASCII_MAP(x, __SC_ASCII, __VA_ARGS__) ")\\n\"\n" \ + ".ascii \"#endif\\n\"\n" \ + ".section .text\n"); diff --git a/arch/um/lkl/include/uapi/asm/host_ops.h b/arch/um/lkl/include/uapi/asm/host_ops.h index 19924fc7c718..1c839d7139f8 100644 --- a/arch/um/lkl/include/uapi/asm/host_ops.h +++ b/arch/um/lkl/include/uapi/asm/host_ops.h @@ -36,6 +36,15 @@ struct lkl_jmp_buf { * @thread_join - wait for the given thread to terminate. Returns 0 * for success, -1 otherwise * + * @tls_alloc - allocate a thread local storage key; returns 0 if successful; if + * destructor is not NULL it will be called when a thread terminates with its + * argument set to the current thread local storage value + * @tls_free - frees a thread local storage key; returns 0 if successful + * @tls_set - associate data to the thread local storage key; returns 0 if + * successful + * @tls_get - return data associated with the thread local storage key or NULL + * on error + * * @mem_alloc - allocate memory * @mem_free - free memory * @@ -71,6 +80,11 @@ struct lkl_host_operations { lkl_thread_t (*thread_self)(void); int (*thread_equal)(lkl_thread_t a, lkl_thread_t b); + struct lkl_tls_key *(*tls_alloc)(void (*destructor)(void *)); + void (*tls_free)(struct lkl_tls_key *key); + int (*tls_set)(struct lkl_tls_key *key, void *data); + void *(*tls_get)(struct lkl_tls_key *key); + void *(*mem_alloc)(unsigned long mem); void (*mem_free)(void *mem); diff --git a/arch/um/lkl/include/uapi/asm/unistd.h b/arch/um/lkl/include/uapi/asm/unistd.h new file mode 100644 index 000000000000..7670e93f0152 --- /dev/null +++ b/arch/um/lkl/include/uapi/asm/unistd.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#define __ARCH_WANT_RENAMEAT +#define __ARCH_WANT_NEW_STAT +#define __ARCH_WANT_SET_GET_RLIMIT +#define __ARCH_WANT_TIME32_SYSCALLS + +#include + +#if __BITS_PER_LONG == 64 +#define __ARCH_WANT_SYS_NEWFSTATAT +#endif + +#include diff --git a/arch/um/lkl/kernel/syscalls.c b/arch/um/lkl/kernel/syscalls.c new file mode 100644 index 000000000000..3ab1d776ca4b --- /dev/null +++ b/arch/um/lkl/kernel/syscalls.c @@ -0,0 +1,192 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef long (*syscall_handler_t)(long arg1, ...); + +#undef __SYSCALL +#define __SYSCALL(nr, sym)[nr] = (syscall_handler_t)sym, + +static syscall_handler_t syscall_table[__NR_syscalls] = { + [0 ... __NR_syscalls - 1] = (syscall_handler_t)sys_ni_syscall, +#include + +#if __BITS_PER_LONG == 32 +#include +#endif +}; + +static long run_syscall(long no, long *params) +{ + long ret; + + if (no < 0 || no >= __NR_syscalls) + return -ENOSYS; + + ret = syscall_table[no](params[0], params[1], params[2], params[3], + params[4], params[5]); + + task_work_run(); + + return ret; +} + + +#define CLONE_FLAGS (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_THREAD | \ + CLONE_SIGHAND | SIGCHLD) + +static int host_task_id; +static struct task_struct *host0; + +static int new_host_task(struct task_struct **task) +{ + pid_t pid; + + switch_to_host_task(host0); + + pid = kernel_thread(host_task_stub, NULL, CLONE_FLAGS); + if (pid < 0) + return pid; + + rcu_read_lock(); + *task = find_task_by_pid_ns(pid, &init_pid_ns); + rcu_read_unlock(); + + host_task_id++; + + snprintf((*task)->comm, sizeof((*task)->comm), "host%d", host_task_id); + + return 0; +} +static void exit_task(void) +{ + do_exit(0); +} + +static void del_host_task(void *arg) +{ + struct task_struct *task = (struct task_struct *)arg; + struct thread_info *ti = task_thread_info(task); + + if (lkl_cpu_get() < 0) + return; + + switch_to_host_task(task); + host_task_id--; + set_ti_thread_flag(ti, TIF_SCHED_JB); + lkl_ops->jmp_buf_set(&ti->sched_jb, exit_task); +} + +static struct lkl_tls_key *task_key; + +long lkl_syscall(long no, long *params) +{ + struct task_struct *task = host0; + long ret; + + ret = lkl_cpu_get(); + if (ret < 0) + return ret; + + if (lkl_ops->tls_get) { + task = lkl_ops->tls_get(task_key); + if (!task) { + ret = new_host_task(&task); + if (ret) + goto out; + lkl_ops->tls_set(task_key, task); + } + } + + switch_to_host_task(task); + + ret = run_syscall(no, params); + + if (no == __NR_reboot) { + thread_sched_jb(); + return ret; + } + +out: + lkl_cpu_put(); + + return ret; +} + +static struct task_struct *idle_host_task; + +/* called from idle, don't failed, don't block */ +void wakeup_idle_host_task(void) +{ + if (!need_resched() && idle_host_task) + wake_up_process(idle_host_task); +} + +static int idle_host_task_loop(void *unused) +{ + struct thread_info *ti = task_thread_info(current); + + snprintf(current->comm, sizeof(current->comm), "idle_host_task"); + set_thread_flag(TIF_HOST_THREAD); + idle_host_task = current; + + for (;;) { + lkl_cpu_put(); + lkl_ops->sem_down(ti->sched_sem); + if (idle_host_task == NULL) { + lkl_ops->thread_exit(); + return 0; + } + schedule_tail(ti->prev_sched); + } +} + +int syscalls_init(void) +{ + snprintf(current->comm, sizeof(current->comm), "host0"); + set_thread_flag(TIF_HOST_THREAD); + host0 = current; + + if (lkl_ops->tls_alloc) { + task_key = lkl_ops->tls_alloc(del_host_task); + if (!task_key) + return -1; + } + + if (kernel_thread(idle_host_task_loop, NULL, CLONE_FLAGS) < 0) { + if (lkl_ops->tls_free) + lkl_ops->tls_free(task_key); + return -1; + } + + return 0; +} + +void syscalls_cleanup(void) +{ + if (idle_host_task) { + struct thread_info *ti = task_thread_info(idle_host_task); + + idle_host_task = NULL; + lkl_ops->sem_up(ti->sched_sem); + lkl_ops->thread_join(ti->tid); + } + + if (lkl_ops->tls_free) + lkl_ops->tls_free(task_key); +} diff --git a/arch/um/lkl/kernel/syscalls_32.c b/arch/um/lkl/kernel/syscalls_32.c new file mode 100644 index 000000000000..a4271593c338 --- /dev/null +++ b/arch/um/lkl/kernel/syscalls_32.c @@ -0,0 +1,159 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * sys_ia32.c: Conversion between 32bit and 64bit native syscalls. Based on + * sys_sparc32 + * + * Copyright (C) 2000 VA Linux Co + * Copyright (C) 2000 Don Dugger + * Copyright (C) 1999 Arun Sharma + * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) + * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 2000 Hewlett-Packard Co. + * Copyright (C) 2000 David Mosberger-Tang + * Copyright (C) 2000,2001,2002 Andi Kleen, SuSE Labs (x86-64 port) + * + * These routines maintain argument size conversion between 32bit and 64bit + * environment. In 2.5 most of this should be moved to a generic directory. + * + * This file assumes that there is a hole at the end of user address space. + * + * Some of the functions are LE specific currently. These are + * hopefully all marked. This should be fixed. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define AA(__x) ((unsigned long)(__x)) + +#if __BITS_PER_LONG == 32 + +asmlinkage long sys32_truncate64(const char __user *filename, + unsigned long offset_low, + unsigned long offset_high) +{ + return sys_truncate64(filename, + ((loff_t)offset_high << 32) | offset_low); +} + +asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long offset_low, + unsigned long offset_high) +{ + return sys_ftruncate64(fd, ((loff_t)offset_high << 32) | offset_low); +} + +#ifdef CONFIG_MMU +/* + * Linux/i386 didn't use to be able to handle more than + * 4 system call parameters, so these system calls used a memory + * block for parameter passing.. + */ + +struct mmap_arg_struct32 { + unsigned int addr; + unsigned int len; + unsigned int prot; + unsigned int flags; + unsigned int fd; + unsigned int offset; +}; + +asmlinkage long sys32_mmap(struct mmap_arg_struct32 __user *arg) +{ + struct mmap_arg_struct32 a; + + if (copy_from_user(&a, arg, sizeof(a))) + return -EFAULT; + + if (a.offset & ~PAGE_MASK) + return -EINVAL; + + return sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, + a.offset >> PAGE_SHIFT); +} +#endif + +asmlinkage long sys32_wait4(pid_t pid, unsigned int __user *stat_addr, + int options, struct rusage __user *ru) +{ + return sys_wait4(pid, stat_addr, options, ru); +} + +asmlinkage long sys32_pread64(unsigned int fd, char __user *ubuf, u32 count, + u32 poslo, u32 poshi) +{ + return sys_pread64(fd, ubuf, count, + ((loff_t)AA(poshi) << 32) | AA(poslo)); +} + +asmlinkage long sys32_pwrite64(unsigned int fd, const char __user *ubuf, + u32 count, u32 poslo, u32 poshi) +{ + return sys_pwrite64(fd, ubuf, count, + ((loff_t)AA(poshi) << 32) | AA(poslo)); +} + +/* + * Some system calls that need sign extended arguments. This could be + * done by a generic wrapper. + */ +long sys32_fadvise64_64(int fd, __u32 offset_low, __u32 offset_high, + __u32 len_low, __u32 len_high, int advice) +{ + return sys_fadvise64_64(fd, (((u64)offset_high) << 32) | offset_low, + (((u64)len_high) << 32) | len_low, advice); +} + +asmlinkage ssize_t sys32_readahead(int fd, unsigned int off_lo, + unsigned int off_hi, size_t count) +{ + return sys_readahead(fd, ((u64)off_hi << 32) | off_lo, count); +} + +asmlinkage long sys32_sync_file_range(int fd, unsigned int off_low, + unsigned int off_hi, unsigned int n_low, + unsigned int n_hi, unsigned int flags) +{ + return sys_sync_file_range(fd, ((u64)off_hi << 32) | off_low, + ((u64)n_hi << 32) | n_low, flags); +} + +asmlinkage long sys32_sync_file_range2(int fd, unsigned int flags, + unsigned int off_low, + unsigned int off_hi, unsigned int n_low, + unsigned int n_hi) +{ + return sys_sync_file_range(fd, ((u64)off_hi << 32) | off_low, + ((u64)n_hi << 32) | n_low, flags); +} + +asmlinkage long sys32_fallocate(int fd, int mode, unsigned int offset_lo, + unsigned int offset_hi, unsigned int len_lo, + unsigned int len_hi) +{ + return sys_fallocate(fd, mode, ((u64)offset_hi << 32) | offset_lo, + ((u64)len_hi << 32) | len_lo); +} + +#endif diff --git a/arch/um/lkl/scripts/headers_install.py b/arch/um/lkl/scripts/headers_install.py new file mode 100755 index 000000000000..30101bd1d4bf --- /dev/null +++ b/arch/um/lkl/scripts/headers_install.py @@ -0,0 +1,196 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: GPL-2.0 +import re, os, sys, argparse, multiprocessing, fnmatch + +srctree = os.environ["srctree"] +objtree = os.environ["objtree"] +install_hdr_path = os.environ["INSTALL_HDR_PATH"] +header_paths = [ install_hdr_path + "/include/", + "arch/um/lkl/include/generated/uapi/", "include/generated/" ] + +headers = set() +includes = set() + +def relpath2abspath(relpath): + if "generated" in relpath: + return objtree + "/" + relpath + else: + return objtree + "/" + relpath + +def find_headers(path): + headers.add(path) + f = open(relpath2abspath(path)) + for l in f.readlines(): + m = re.search("#include <(.*)>", l) + try: + i = m.group(1) + for p in header_paths: + if os.access(relpath2abspath(p + i), os.R_OK): + if p + i not in headers: + includes.add(i) + headers.add(p + i) + find_headers(p + i) + except: + pass + f.close() + +def has_lkl_prefix(w): + return w.startswith("lkl") or w.startswith("_lkl") or w.startswith("__lkl") \ + or w.startswith("LKL") or w.startswith("_LKL") or w.startswith("__LKL") + +def find_symbols(regexp, store): + for h in headers: + f = open(h) + for l in f.readlines(): + m = regexp.search(l) + if not m: + continue + for e in reversed(m.groups()): + if e: + if not has_lkl_prefix(e): + store.add(e) + break + f.close() + +def find_ml_symbols(regexp, store): + for h in headers: + for i in regexp.finditer(open(h).read()): + for j in reversed(i.groups()): + if j: + if not has_lkl_prefix(j): + store.add(j) + break + +def find_enums(block_regexp, symbol_regexp, store): + for h in headers: + # remove comments + content = re.sub(re.compile("(\/\*(\*(?!\/)|[^*])*\*\/)", re.S|re.M), " ", open(h).read()) + # remove preprocesor lines + clean_content = "" + for l in content.split("\n"): + if re.match("\s*#", l): + continue + clean_content += l + "\n" + for i in block_regexp.finditer(clean_content): + for j in reversed(i.groups()): + if j: + for k in symbol_regexp.finditer(j): + for l in k.groups(): + if l: + if not has_lkl_prefix(l): + store.add(l) + break + +def lkl_prefix(w): + r = "" + + if w.startswith("__"): + r = "__" + elif w.startswith("_"): + r = "_" + + if w.isupper(): + r += "LKL" + else: + r += "lkl" + + if not w.startswith("_"): + r += "_" + + r += w + + return r + +def replace(h): + content = open(h).read() + for i in includes: + search_str = "(#[ \t]*include[ \t]*[<\"][ \t]*)" + i + "([ \t]*[>\"])" + replace_str = "\\1" + "lkl/" + i + "\\2" + content = re.sub(search_str, replace_str, content) + tmp = "" + for w in re.split("(\W+)", content): + if w in defines: + w = lkl_prefix(w) + tmp += w + content = tmp + for s in structs: + search_str = "(\W?struct\s+)" + s + "(\W)" + replace_str = "\\1" + lkl_prefix(s) + "\\2" + content = re.sub(search_str, replace_str, content, flags = re.MULTILINE) + for s in unions: + search_str = "(\W?union\s+)" + s + "(\W)" + replace_str = "\\1" + lkl_prefix(s) + "\\2" + content = re.sub(search_str, replace_str, content, flags = re.MULTILINE) + open(h, 'w').write(content) + +parser = argparse.ArgumentParser(description='install lkl headers') +parser.add_argument('path', help='path to install to', ) +parser.add_argument('-j', '--jobs', help='number of parallel jobs', default=1, type=int) +args = parser.parse_args() + +find_headers(install_hdr_path + "/include/asm/syscalls.h") +headers.add(install_hdr_path + "/include/asm/host_ops.h") + +if 'LKL_INSTALL_ADDITIONAL_HEADERS' in os.environ: + with open(os.environ['LKL_INSTALL_ADDITIONAL_HEADERS'], 'rU') as f: + for line in f.readlines(): + line = line.split('#', 1)[0].strip() + if line != '': + headers.add(line) + +new_headers = set() + +for h in headers: + dir = os.path.dirname(h) + out_dir = args.path + "/" + re.sub("(arch/um/lkl/include/generated/uapi/|include/generated/uapi/|include/generated|" + install_hdr_path + "/include/)(.*)", "lkl/\\2", dir) + try: + os.makedirs(out_dir) + except: + pass + print(" INSTALL\t%s" % (out_dir + "/" + os.path.basename(h))) + os.system(srctree+"/scripts/headers_install.sh %s %s" % (os.path.abspath(h), + out_dir + "/" + os.path.basename(h))) + new_headers.add(out_dir + "/" + os.path.basename(h)) + +headers = new_headers + +defines = set() +structs = set() +unions = set() + +p = re.compile("#[ \t]*define[ \t]*(\w+)") +find_symbols(p, defines) +p = re.compile("typedef.*(\(\*(\w+)\)\(.*\)\s*|\W+(\w+)\s*|\s+(\w+)\(.*\)\s*);") +find_symbols(p, defines) +p = re.compile("typedef\s+(struct|union)\s+\w*\s*{[^\\{\}]*}\W*(\w+)\s*;", re.M|re.S) +find_ml_symbols(p, defines) +defines.add("siginfo_t") +defines.add("sigevent_t") +p = re.compile("struct\s+(\w+)\s*\{") +find_symbols(p, structs) +structs.add("iovec") +p = re.compile("union\s+(\w+)\s*\{") +find_symbols(p, unions) +p = re.compile("static\s+__inline__(\s+\w+)+\s+(\w+)\([^)]*\)\s") +find_symbols(p, defines) +p = re.compile("static\s+__always_inline(\s+\w+)+\s+(\w+)\([^)]*\)\s") +find_symbols(p, defines) +p = re.compile("enum\s+(\w*)\s*{([^}]*)}", re.M|re.S) +q = re.compile("(\w+)\s*(,|=[^,]*|$)", re.M|re.S) +find_enums(p, q, defines) + +# needed for i386 +defines.add("__NR_stime") + +def process_header(h): + print(" REPLACE\t%s" % (out_dir + "/" + os.path.basename(h))) + replace(h) + +p = multiprocessing.Pool(args.jobs) +try: + p.map_async(process_header, headers).wait(999999) + p.close() +except: + p.terminate() +finally: + p.join() From patchwork Mon Mar 30 14:45:40 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hajime Tazaki X-Patchwork-Id: 1263987 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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=AJREl8wy; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=K/0l0mxE; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (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 48rb186zQmz9sP7 for ; Tue, 31 Mar 2020 01:48:12 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.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=AdTYm2d8+Enw+x6cuS8Urbds2xE9odf7kG/G7Tp23+4=; b=AJREl8wyQ1Xmze lSmTY3gNvdQ43MWkMfKBPB/xG/+gYBVGf6iEgt9jYPP+Mck2C+vCV5LV2MBCeY+pCMD5f3awBKK1h VwMrUzritLj3RVFF9nAKyesbry5nHhJPkUO1G0aiPHh8h3X5pn6zhalGXbOae5p9CmkLNjUrEnq1p dv5/G+s6vy0E4g+NDpTut5VaOakIVZc4WIawQ1V/8ULkiuAONkGzgg/4TeKyFyhif4l0TrgrEBepN 16X/y2UNpKI+Uk0JGRXcgRZ/4ynShpdfIznjbCp+ktisJlHuUdRVN/59ccIRh9U8rUAMucdW6Rmeh igrIa4cyQ4bUpgcNP2Qw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvht-0004sz-1y; Mon, 30 Mar 2020 14:48:05 +0000 Received: from mail-pj1-x1041.google.com ([2607:f8b0:4864:20::1041]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvhp-0004rp-U7 for linux-um@lists.infradead.org; Mon, 30 Mar 2020 14:48:03 +0000 Received: by mail-pj1-x1041.google.com with SMTP id w9so7682833pjh.1 for ; Mon, 30 Mar 2020 07:48:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=NN5VM2LTBubLn/61axczwTNSQEgLs/aawxghBqEu7kA=; b=K/0l0mxEe2fP3w+iz6CMzAOntePtgxksP+Jdt/VmyG2y1J6e+RNgA/j2Ry1knZ0qsX TA4bi7LRth6GwHT9E3M9kwNT3WbWKNk4SidPocVvxssS9RxNpHrQl0307+vw+kgtTpPo hCTM84fxK+g+yjFcZR1rtsxVy+gq40Lw8CxHdpmBeCuhNoGP/gwinfCanc6CiHy3JBH7 WDLhSW1KfxbFjOFqbEL2gzrh5lShZZc4p+6pnjcL7JP5x7+GNcRR+Kn2ZHYf+yHtF6Im ytJQV2qQqVrHwikasqetL4HrVKA42XwLwgaAj+U+21SqQmNCN7HriS6xfMt71Bql4KYd kPwg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=NN5VM2LTBubLn/61axczwTNSQEgLs/aawxghBqEu7kA=; b=TD72KQGfmhQLe1tlYixTjVZaoElm1jiSSU7pVaAb7dZuK3hOOpSKpw2eXe5GvFG3qY Am7ASkjao9t5XXhdIAiTTLk5GRz0q4/tT39VpVqBbBBqjv4ggPTtHw5FWtbugGiLYtSY ls14leQy7femXC6FabRfXEbYVoK84syOk51eYkDg0udantIKLaHpWlGsRpKk9spZVPyr 0T2+77TA/3IWTCKUugCS+bErj8rYzvXpFUc5s8cZiMN9zM6zX2uKe8BnmV3wQLPy4Dp4 gqpNyDIRq5cdTw0f+YYNwql6ukio084yraDML8XFdSWq+7HUhOReSYDrFs1YEmIdA8ka SOzA== X-Gm-Message-State: ANhLgQ1tJy2dlFeXpOOSUqpxrJ3ZFp0E2OysejnCpHpuyYixXfjAJpHU Pw6TxKuy4ZSKrRZf1Nfxlkg= X-Google-Smtp-Source: ADFU+vvnQ8/ZQJTlonQDs+Y2Cnbr95SFqdP16huG+QNyy8b2/2ERROvPj+XDtM5toaUYxWzt4Hsywg== X-Received: by 2002:a17:902:8c88:: with SMTP id t8mr12709656plo.176.1585579681122; Mon, 30 Mar 2020 07:48:01 -0700 (PDT) Received: from earth-mac.local (219x123x138x129.ap219.ftth.ucom.ne.jp. [219.123.138.129]) by smtp.gmail.com with ESMTPSA id 6sm7077146pgm.51.2020.03.30.07.48.00 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 30 Mar 2020 07:48:00 -0700 (PDT) Received: by earth-mac.local (Postfix, from userid 501) id C758D202804D3F; Mon, 30 Mar 2020 23:47:43 +0900 (JST) From: Hajime Tazaki To: linux-um@lists.infradead.org Subject: [RFC v4 08/25] um lkl: timers, time and delay support Date: Mon, 30 Mar 2020 23:45:40 +0900 Message-Id: X-Mailer: git-send-email 2.20.1 (Apple Git-117) In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200330_074801_976869_254B7261 X-CRM114-Status: GOOD ( 15.56 ) X-Spam-Score: -0.2 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:1041 listed in] [list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [thehajime[at]gmail.com] -0.0 SPF_PASS SPF: sender matches SPF record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 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: linux-arch@vger.kernel.org, Octavian Purdila , Akira Moroo , linux-kernel-library@freelists.org, Michael Zimmermann , Hajime Tazaki Sender: "linux-um" Errors-To: linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Octavian Purdila Clockevent driver based on host timer operations and clocksource driver and udelay support based on host time operations. Cc: Michael Zimmermann Signed-off-by: Hajime Tazaki Signed-off-by: Octavian Purdila --- arch/um/lkl/include/uapi/asm/host_ops.h | 13 +++ arch/um/lkl/kernel/time.c | 145 ++++++++++++++++++++++++ 2 files changed, 158 insertions(+) create mode 100644 arch/um/lkl/kernel/time.c diff --git a/arch/um/lkl/include/uapi/asm/host_ops.h b/arch/um/lkl/include/uapi/asm/host_ops.h index 1c839d7139f8..c9f77dd7fbe7 100644 --- a/arch/um/lkl/include/uapi/asm/host_ops.h +++ b/arch/um/lkl/include/uapi/asm/host_ops.h @@ -48,6 +48,13 @@ struct lkl_jmp_buf { * @mem_alloc - allocate memory * @mem_free - free memory * + * @timer_create - allocate a host timer that runs fn(arg) when the timer + * fires. + * @timer_free - disarms and free the timer + * @timer_set_oneshot - arm the timer to fire once, after delta ns. + * @timer_set_periodic - arm the timer to fire periodically, with a period of + * delta ns. + * * @gettid - returns the host thread id of the caller, which need not * be the same as the handle returned by thread_create * @@ -88,6 +95,12 @@ struct lkl_host_operations { void *(*mem_alloc)(unsigned long mem); void (*mem_free)(void *mem); + unsigned long long (*time)(void); + + void *(*timer_alloc)(void (*fn)(void *), void *arg); + int (*timer_set_oneshot)(void *timer, unsigned long delta); + void (*timer_free)(void *timer); + long (*gettid)(void); void (*jmp_buf_set)(struct lkl_jmp_buf *jmpb, void (*f)(void)); diff --git a/arch/um/lkl/kernel/time.c b/arch/um/lkl/kernel/time.c new file mode 100644 index 000000000000..dade9717a986 --- /dev/null +++ b/arch/um/lkl/kernel/time.c @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include +#include +#include + +static unsigned long long boot_time; + +void __ndelay(unsigned long nsecs) +{ + unsigned long long start = lkl_ops->time(); + + while (lkl_ops->time() < start + nsecs) + ; +} + +void __udelay(unsigned long usecs) +{ + __ndelay(usecs * NSEC_PER_USEC); +} + +void __const_udelay(unsigned long xloops) +{ + __udelay(xloops / 0x10c7ul); +} + +void calibrate_delay(void) +{ +} + +void read_persistent_clock(struct timespec64 *ts) +{ + *ts = ns_to_timespec64(lkl_ops->time()); +} + +/* + * Scheduler clock - returns current time in nanosec units. + * + */ +unsigned long long sched_clock(void) +{ + if (!boot_time) + return 0; + + return lkl_ops->time() - boot_time; +} + +static u64 clock_read(struct clocksource *cs) +{ + return lkl_ops->time(); +} + +static struct clocksource clocksource = { + .name = "lkl", + .rating = 499, + .read = clock_read, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, + .mask = CLOCKSOURCE_MASK(64), +}; + +static void *timer; + +static int timer_irq; + +static void timer_fn(void *arg) +{ + lkl_trigger_irq(timer_irq); +} + +static int clockevent_set_state_shutdown(struct clock_event_device *evt) +{ + if (timer) { + lkl_ops->timer_free(timer); + timer = NULL; + } + + return 0; +} + +static int clockevent_set_state_oneshot(struct clock_event_device *evt) +{ + timer = lkl_ops->timer_alloc(timer_fn, NULL); + if (!timer) + return -ENOMEM; + + return 0; +} + +static irqreturn_t timer_irq_handler(int irq, void *dev_id) +{ + struct clock_event_device *dev = (struct clock_event_device *)dev_id; + + dev->event_handler(dev); + + return IRQ_HANDLED; +} + +static int clockevent_next_event(unsigned long ns, + struct clock_event_device *evt) +{ + return lkl_ops->timer_set_oneshot(timer, ns); +} + +static struct clock_event_device clockevent = { + .name = "lkl", + .features = CLOCK_EVT_FEAT_ONESHOT, + .set_state_oneshot = clockevent_set_state_oneshot, + .set_next_event = clockevent_next_event, + .set_state_shutdown = clockevent_set_state_shutdown, +}; + +static struct irqaction irq0 = { + .handler = timer_irq_handler, + .flags = IRQF_NOBALANCING | IRQF_TIMER, + .dev_id = &clockevent, + .name = "timer" +}; + +void __init time_init(void) +{ + int ret; + + if (!lkl_ops->timer_alloc || !lkl_ops->timer_free || + !lkl_ops->timer_set_oneshot || !lkl_ops->time) { + pr_err("lkl: no time or timer support provided by host\n"); + return; + } + + timer_irq = lkl_get_free_irq("timer"); + setup_irq(timer_irq, &irq0); + + ret = clocksource_register_khz(&clocksource, 1000000); + if (ret) + pr_err("lkl: unable to register clocksource\n"); + + clockevents_config_and_register(&clockevent, NSEC_PER_SEC, 1, + ULONG_MAX); + + boot_time = lkl_ops->time(); + pr_info("lkl: time and timers initialized (irq%d)\n", timer_irq); +} From patchwork Mon Mar 30 14:45:41 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hajime Tazaki X-Patchwork-Id: 1263984 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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=CcYPn9HD; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=iCIVxfyX; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (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 48rb0x0xVZz9sPk for ; Tue, 31 Mar 2020 01:48:01 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.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=eyJrkbzwqaj+uMFyb9iVFVa24KTEO/bObttwVrlX+cs=; b=CcYPn9HDnRPKol mBObLXDsp+SncSaAqO4qTb34gRXqUHf3NGgrOIMeqYjiFygsVuR5Yq0c38+1Zk0kKoYGs28VyGfN5 1D/jMolyHgYxwcBslLZ+JIb9PO6l6VJG+zHzyjMAXQODZRcuP3pPJwUkfRNB4b6/Es1WQFAu/TUep Q5oFyMOcrnxG+2234WXkkeh/pDv9bemMydvkf5zaNCPI/S/sXPgF/YUBygZOPdDJduyfiigf38Pq7 sXEgieJbF3C6pM09kKk+FC29F2HXTnbfRC//f8w/qv2gOIG4US5r0Fv3H4hf1/ytu81VZ+FWKtlvJ UxEv5MiXoIvngfw3Q7pw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvhh-0004od-GK; Mon, 30 Mar 2020 14:47:53 +0000 Received: from mail-pl1-x642.google.com ([2607:f8b0:4864:20::642]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvhe-0004nw-Po for linux-um@lists.infradead.org; Mon, 30 Mar 2020 14:47:52 +0000 Received: by mail-pl1-x642.google.com with SMTP id x1so6813080plm.4 for ; Mon, 30 Mar 2020 07:47:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=6WJWXIBn2EeJafNFgCrfWBYhVUMwRu8tn6FcwGDWnVA=; b=iCIVxfyXhJPCtvZuxxdFOqNact2m60anKnxGvMI61GdQufDa7q6HrC0pdRxy2q4JjM dPMq/ALeRzrtRtP/2v8gAmFh+eTkY4l6+nGt9Qqla1FxCHsO/vJtMosdTZNp/FucHhqI baTDDPeLrJk5zhCdDR7HpCS+8Cwd1OkeiFQFDEj8y4UK8J8Yo/e3GFMts/Tv8y349mAv SWzhJdzqUFk0HkcOjHLFzLitVhc1/iD/snxNT7aCz4R3dbUD2iMWa0lm+nLWDOFsD84N jSens+lIpebRccng5lB17RkAHD+tFZk+Uot1PYTsuXq7FIuOYqx60ktHhBeYceQRDc+g eA5g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=6WJWXIBn2EeJafNFgCrfWBYhVUMwRu8tn6FcwGDWnVA=; b=Mbvm0TK+GKHKbwyv3mUOznmE8rV4UaQF0f93bi4YCpN1UtQkoq1cZhpvPF5HwCkn9n fwSXUMPPJAFKnRqMyOzBjRmeSuDyK9qor2BaDsq3ep6omgOJeqRpMEcmeAG4e/1cJqzK Ga5cVTd9bwIjXpOP129O5/IdNMW/t4rhbaLkYcBENYI6UCexlqgQb6nXDZhorfIs/w8m OPBuswN7pg11mVK2hcjyfCZubJ4bs0nkUPE6uj+UZxd9V9Dbtu31j58g+YxZWJUrCMc8 D8Pb0nYc0NIBOGuo9VzopmKvHrP7M0vhjB1a0wK9dLBQ+acfyuQLkexggqkfa+bTFu6t 1QDQ== X-Gm-Message-State: ANhLgQ0HzespXofArW9uyIHqQQ3Ta8w9mUeEAtEEXp3MKSgJJHW6jGwI hbcrbzvJsvlLXArGlogxqdg= X-Google-Smtp-Source: ADFU+vtbM7bFviKqNSqDo3jcri4/ukynuq+Ny5bXej7qJt6EyG+HCzRvd34bWJoUeQU1ImCjs9pnbg== X-Received: by 2002:a17:902:b692:: with SMTP id c18mr13081155pls.7.1585579670147; Mon, 30 Mar 2020 07:47:50 -0700 (PDT) Received: from earth-mac.local (219x123x138x129.ap219.ftth.ucom.ne.jp. [219.123.138.129]) by smtp.gmail.com with ESMTPSA id r4sm9744680pgp.53.2020.03.30.07.47.49 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 30 Mar 2020 07:47:49 -0700 (PDT) Received: by earth-mac.local (Postfix, from userid 501) id BA31D202804D55; Mon, 30 Mar 2020 23:47:47 +0900 (JST) From: Hajime Tazaki To: linux-um@lists.infradead.org Subject: [RFC v4 09/25] um lkl: basic kernel console support Date: Mon, 30 Mar 2020 23:45:41 +0900 Message-Id: <0c8b9f122563372acea307b738f833a211ef28c5.1585579244.git.thehajime@gmail.com> X-Mailer: git-send-email 2.20.1 (Apple Git-117) In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200330_074750_878135_1B088F46 X-CRM114-Status: GOOD ( 12.65 ) X-Spam-Score: -0.2 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:642 listed in] [list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [thehajime[at]gmail.com] -0.0 SPF_PASS SPF: sender matches SPF record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 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: Octavian Purdila , linux-kernel-library@freelists.org, linux-arch@vger.kernel.org, Akira Moroo Sender: "linux-um" Errors-To: linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Octavian Purdila This patch adds a basic structure of console support in kernel. Write operations are deferred to the host print operation. Signed-off-by: Octavian Purdila --- arch/um/lkl/include/uapi/asm/host_ops.h | 4 +++ arch/um/lkl/kernel/console.c | 42 +++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 arch/um/lkl/kernel/console.c diff --git a/arch/um/lkl/include/uapi/asm/host_ops.h b/arch/um/lkl/include/uapi/asm/host_ops.h index c9f77dd7fbe7..986340ba9d8d 100644 --- a/arch/um/lkl/include/uapi/asm/host_ops.h +++ b/arch/um/lkl/include/uapi/asm/host_ops.h @@ -17,6 +17,8 @@ struct lkl_jmp_buf { * These operations must be provided by a host library or by the application * itself. * + * @print - optional operation that receives console messages + * * @sem_alloc - allocate a host semaphore an initialize it to count * @sem_free - free a host semaphore * @sem_up - perform an up operation on the semaphore @@ -70,6 +72,8 @@ struct lkl_jmp_buf { * @jmp_buf_longjmp - perform a jump back to the saved jump buffer */ struct lkl_host_operations { + void (*print)(const char *str, int len); + struct lkl_sem *(*sem_alloc)(int count); void (*sem_free)(struct lkl_sem *sem); void (*sem_up)(struct lkl_sem *sem); diff --git a/arch/um/lkl/kernel/console.c b/arch/um/lkl/kernel/console.c new file mode 100644 index 000000000000..54d7f756c6da --- /dev/null +++ b/arch/um/lkl/kernel/console.c @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include + +static void console_write(struct console *con, const char *str, + unsigned int len) +{ + if (lkl_ops->print) + lkl_ops->print(str, len); +} + +#ifdef CONFIG_LKL_EARLY_CONSOLE +static struct console lkl_boot_console = { + .name = "lkl_boot_console", + .write = console_write, + .flags = CON_PRINTBUFFER | CON_BOOT, + .index = -1, +}; + +int __init lkl_boot_console_init(void) +{ + register_console(&lkl_boot_console); + return 0; +} +early_initcall(lkl_boot_console_init); +#endif + +static struct console lkl_console = { + .name = "lkl_console", + .write = console_write, + .flags = CON_PRINTBUFFER, + .index = -1, +}; + +static int __init lkl_console_init(void) +{ + register_console(&lkl_console); + return 0; +} +core_initcall(lkl_console_init); From patchwork Mon Mar 30 14:45:42 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hajime Tazaki X-Patchwork-Id: 1263985 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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=pn5qQ7Vz; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=WVoyx8TH; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (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 48rb123knnz9sP7 for ; Tue, 31 Mar 2020 01:48:06 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.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=UpXAyhmuydltaeaTsFNqEgQd7ten1zOy1+TdOGgVtPw=; b=pn5qQ7VzfVz+Zr PlrRAZ0UW6vfs29WBpVG+wfcADz3+jqXIp3qtyqwLSYCSBi27peh/G4XFDispNApI98pDZUSO3G7B bFPRIqMlxu6DmPW2OKfZYh8kCZrvxwvo11k1gDAkXgvrvDZHi8jT18GRefuNnTzRJurKJdajU4pc9 DAqBtc5oFcppHh8h99G/I3NpaC1wMlM2cL4h10CwRFohw9oaTFn5fzratgrZdnDhnbRAc8yXvHipm pP6b/OyU4ejV1wr4BMApJZPb3QGi76JbHuE78gCmVW2tOwwk72G6eKhBcqXDIJtLQ7xxU9t6uzlic 3vagZwc7lB5WhsodWEPQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvhk-0004ps-QH; Mon, 30 Mar 2020 14:47:56 +0000 Received: from mail-pf1-x444.google.com ([2607:f8b0:4864:20::444]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvhh-0004oX-F3 for linux-um@lists.infradead.org; Mon, 30 Mar 2020 14:47:55 +0000 Received: by mail-pf1-x444.google.com with SMTP id r14so6200738pfl.12 for ; Mon, 30 Mar 2020 07:47:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=7KZd4yDF7feHHZHrU3H4VRHPCqEnKtFHBAt9igrYvhk=; b=WVoyx8TH2XlaQRHhqVUx83S8LF7eJhU/mqDKQgS9kCk4i8X6AzhbW5gmcSGo5k5lld zuvqPxMJb4THF+23hTd3PIkwqVJFjmuU+7LYYun1Ik6Zf6WR/HkfK92NpQDekQIoX6tl YZZ59os2lwVjHnW7oXaoqnIdMXXVA9oa6hCup3XQZvd/TYWicpHvLeoUWd2geDXywFvQ tf41IdxYjj3iWx5RIsuPpQ8eOeJJii96VV+ZEDxUOJp04BVcwXx6j6rN76t+ZEUa37Ab mSJe4VTsKSeIz7CloVlJqmdfzAeWCwT9S4nfblBWcBsaZSwAfJfd/0AUQqv86Bx19LFL QrjQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=7KZd4yDF7feHHZHrU3H4VRHPCqEnKtFHBAt9igrYvhk=; b=EagC31rolkqxF/lm5EtaOj2VR85QXqeL25ylk22fA5S1DKBfZZnJX0sSeo5PTeoPkd /y2N+d70jkv8+3lWrjxs/FJhywKWqxfYW9TzZgPKn29kPa1G/TnBMuOsGiQcAGO1hy5g nhDQjU06G3dPnHicx5R9g0CsAbY4498vFp9Wd2ZTFsnJC3LxbzYJQQhE+fg6XB4NCfzx RVl+ojJuo8AE0vuBYWxTxGm80sjPR6ZPbkSQhBd2Firp3nJc5Pc+CGScXu1AyRTAWtNi 9hEDffi9COlg5SHzMpyYPGCqxPohInc/C2Al/ye7cIGDUOIAjEZHW914Kwrel7WjGKfE 3tGQ== X-Gm-Message-State: ANhLgQ3LvyNkCBllCqDJhFxDNiaoJQGSTgUrdCZbq9htHNxO7GD4FyTO qoynUQMLoOCVlju0dCfOb2k= X-Google-Smtp-Source: ADFU+vsSyLBd8fgvj0Ffq71gXXhfKC29Uup9MA2sA5FnZ2lsodn/GEjZPGj/seNzID2PmHrgf2dn5g== X-Received: by 2002:aa7:953b:: with SMTP id c27mr13522756pfp.201.1585579672692; Mon, 30 Mar 2020 07:47:52 -0700 (PDT) Received: from earth-mac.local (219x123x138x129.ap219.ftth.ucom.ne.jp. [219.123.138.129]) by smtp.gmail.com with ESMTPSA id g18sm9824519pgh.42.2020.03.30.07.47.51 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 30 Mar 2020 07:47:52 -0700 (PDT) Received: by earth-mac.local (Postfix, from userid 501) id 3CB0C202804D57; Mon, 30 Mar 2020 23:47:50 +0900 (JST) From: Hajime Tazaki To: linux-um@lists.infradead.org Subject: [RFC v4 10/25] um lkl: initialization and cleanup Date: Mon, 30 Mar 2020 23:45:42 +0900 Message-Id: <7c79d701ea499276e1d68ba9eb61e784c456746a.1585579244.git.thehajime@gmail.com> X-Mailer: git-send-email 2.20.1 (Apple Git-117) In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200330_074753_556476_F7B8ABE4 X-CRM114-Status: GOOD ( 21.21 ) X-Spam-Score: -0.2 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:444 listed in] [list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [thehajime[at]gmail.com] -0.0 SPF_PASS SPF: sender matches SPF record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 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: linux-arch@vger.kernel.org, Hajime Tazaki , Octavian Purdila , Akira Moroo , Patrick Collins , linux-kernel-library@freelists.org, Michael Zimmermann , Yuan Liu Sender: "linux-um" Errors-To: linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Octavian Purdila Add the lkl_start_kernel and lkl_sys_halt APIs that start and respectively stops the Linux kernel. lkl_start_kernel creates a separate threads that will run the initial and idle kernel thread. It waits for the kernel to complete initialization before returning, to avoid races with system calls issues by the host application. During the setup phase, we create "/init" in initial ramfs root filesystem to avoid mounting the "real" rootfs since ramfs is good enough for now. lkl_sys_halt will shutdown the kernel, terminate all threads and free all host resources used by the kernel before returning. This patch also introduces idle CPU handling since it is closely related to the shutdown process. A host semaphore is used to wait for new interrupts when the kernel switches the CPU to idle to avoid wasting host CPU cycles. When the kernel is shutdown we terminate the idle thread at the first CPU idle event. Cc: Michael Zimmermann Cc: Patrick Collins Cc: Yuan Liu Signed-off-by: Hajime Tazaki Signed-off-by: Octavian Purdila --- arch/um/lkl/include/asm/setup.h | 7 + arch/um/lkl/include/uapi/asm/host_ops.h | 20 +++ arch/um/lkl/kernel/setup.c | 189 ++++++++++++++++++++++++ 3 files changed, 216 insertions(+) create mode 100644 arch/um/lkl/include/asm/setup.h create mode 100644 arch/um/lkl/kernel/setup.c diff --git a/arch/um/lkl/include/asm/setup.h b/arch/um/lkl/include/asm/setup.h new file mode 100644 index 000000000000..b40955208cc6 --- /dev/null +++ b/arch/um/lkl/include/asm/setup.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_LKL_SETUP_H +#define _ASM_LKL_SETUP_H + +#define COMMAND_LINE_SIZE 4096 + +#endif diff --git a/arch/um/lkl/include/uapi/asm/host_ops.h b/arch/um/lkl/include/uapi/asm/host_ops.h index 986340ba9d8d..fe4382c3050a 100644 --- a/arch/um/lkl/include/uapi/asm/host_ops.h +++ b/arch/um/lkl/include/uapi/asm/host_ops.h @@ -19,6 +19,8 @@ struct lkl_jmp_buf { * * @print - optional operation that receives console messages * + * @panic - called during a kernel panic + * * @sem_alloc - allocate a host semaphore an initialize it to count * @sem_free - free a host semaphore * @sem_up - perform an up operation on the semaphore @@ -73,6 +75,7 @@ struct lkl_jmp_buf { */ struct lkl_host_operations { void (*print)(const char *str, int len); + void (*panic)(void); struct lkl_sem *(*sem_alloc)(int count); void (*sem_free)(struct lkl_sem *sem); @@ -111,6 +114,23 @@ struct lkl_host_operations { void (*jmp_buf_longjmp)(struct lkl_jmp_buf *jmpb, int val); }; +/** + * lkl_start_kernel - registers the host operations and starts the kernel + * + * The function returns only after the kernel is shutdown with lkl_sys_halt. + * + * @lkl_ops - pointer to host operations + * @cmd_line - format for command line string that is going to be used to + * generate the Linux kernel command line + */ +int lkl_start_kernel(struct lkl_host_operations *lkl_ops, const char *cmd_line, + ...); + +/** + * lkl_is_running - returns 1 if the kernel is currently running + */ +int lkl_is_running(void); + int lkl_printf(const char *fmt, ...); void lkl_bug(const char *fmt, ...); diff --git a/arch/um/lkl/kernel/setup.c b/arch/um/lkl/kernel/setup.c new file mode 100644 index 000000000000..36c199d3aa22 --- /dev/null +++ b/arch/um/lkl/kernel/setup.c @@ -0,0 +1,189 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct lkl_host_operations *lkl_ops; +static char cmd_line[COMMAND_LINE_SIZE]; +static void *init_sem; +static int is_running; +void (*pm_power_off)(void) = NULL; +static unsigned long mem_size = 64 * 1024 * 1024; + +static long lkl_panic_blink(int state) +{ + lkl_ops->panic(); + return 0; +} + +static int __init setup_mem_size(char *str) +{ + mem_size = memparse(str, NULL); + return 0; +} +early_param("mem", setup_mem_size); + +void __init setup_arch(char **cl) +{ + *cl = cmd_line; + panic_blink = lkl_panic_blink; + parse_early_param(); + bootmem_init(mem_size); +} + +static void __init lkl_run_kernel(void *arg) +{ + threads_init(); + lkl_cpu_get(); + start_kernel(); +} + +int __init lkl_start_kernel(struct lkl_host_operations *ops, const char *fmt, + ...) +{ + va_list ap; + int ret; + + lkl_ops = ops; + + va_start(ap, fmt); + ret = vsnprintf(boot_command_line, COMMAND_LINE_SIZE, fmt, ap); + va_end(ap); + + memcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE); + + init_sem = lkl_ops->sem_alloc(0); + if (!init_sem) + return -ENOMEM; + + ret = lkl_cpu_init(); + if (ret) + goto out_free_init_sem; + + ret = lkl_ops->thread_create(lkl_run_kernel, NULL); + if (!ret) { + ret = -ENOMEM; + goto out_free_init_sem; + } + + lkl_ops->sem_down(init_sem); + lkl_ops->sem_free(init_sem); + current_thread_info()->tid = lkl_ops->thread_self(); + lkl_cpu_change_owner(current_thread_info()->tid); + + lkl_cpu_put(); + is_running = 1; + + return 0; + +out_free_init_sem: + lkl_ops->sem_free(init_sem); + + return ret; +} + +int lkl_is_running(void) +{ + return is_running; +} + +void machine_halt(void) +{ + lkl_cpu_shutdown(); +} + +void machine_power_off(void) +{ + machine_halt(); +} + +void machine_restart(char *unused) +{ + machine_halt(); +} + +long lkl_sys_halt(void) +{ + long err; + long params[6] = { + LINUX_REBOOT_MAGIC1, + LINUX_REBOOT_MAGIC2, + LINUX_REBOOT_CMD_RESTART, + }; + + err = lkl_syscall(__NR_reboot, params); + if (err < 0) + return err; + + is_running = false; + + lkl_cpu_wait_shutdown(); + + syscalls_cleanup(); + threads_cleanup(); + /* Shutdown the clockevents source. */ + tick_suspend_local(); + free_mem(); + lkl_ops->thread_join(current_thread_info()->tid); + + return 0; +} + +static int lkl_run_init(struct linux_binprm *bprm); + +static struct linux_binfmt lkl_run_init_binfmt = { + .module = THIS_MODULE, + .load_binary = lkl_run_init, +}; + +static int lkl_run_init(struct linux_binprm *bprm) +{ + int ret; + + if (strcmp("/init", bprm->filename) != 0) + return -EINVAL; + + ret = flush_old_exec(bprm); + if (ret) + return ret; + set_personality(PER_LINUX); + setup_new_exec(bprm); + install_exec_creds(bprm); + + set_binfmt(&lkl_run_init_binfmt); + + init_pid_ns.child_reaper = NULL; + + syscalls_init(); + + lkl_ops->sem_up(init_sem); + lkl_ops->thread_exit(); + + return 0; +} + +/* skip mounting the "real" rootfs. ramfs is good enough. */ +static int __init fs_setup(void) +{ + int fd; + + fd = sys_open("/init", O_CREAT, 0700); + WARN_ON(fd < 0); + sys_close(fd); + + register_binfmt(&lkl_run_init_binfmt); + + return 0; +} +late_initcall(fs_setup); From patchwork Mon Mar 30 14:45:43 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hajime Tazaki X-Patchwork-Id: 1263986 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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=mi3+h1fs; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=czXjoOWF; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (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 48rb142BVQz9sP7 for ; Tue, 31 Mar 2020 01:48:08 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.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=GZHgTUl6hi9A10JA3mvCTEAZwwaqfASnVptdtlErIkk=; b=mi3+h1fsWuG93g DbqcuLR/hjsaL45zFPRpUEO2mNpb9n9Ucfgu6j10HXm+CWs5f6+8zRK8nGnNdQxkGl1ePDMsWyQGi R8LfbU6ONJqE70fIlzh6hG5ySIP0f8MKMSV1bHSGkKGekwb0mUHtj5chRWc7CoMMfhAp9FavSUKEM RbIn9wZMmJpeWfct3/i5re9K9Xg2Kbm5WrhmQMzXo73YyAuLI3+ZeuIWb7OG6bana1VVEIAraAyXI puIeErSoTfGyUUXzoD4TCIemYmIeh0BJtIDItjOLResb26SdKKWWbJUw60B6f+lMjWx5qhtd1rlsi 6/+8ZFzC4YNrErSKx80A==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvhn-0004qr-FR; Mon, 30 Mar 2020 14:47:59 +0000 Received: from mail-pl1-x643.google.com ([2607:f8b0:4864:20::643]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvhk-0004pa-Hq for linux-um@lists.infradead.org; Mon, 30 Mar 2020 14:47:58 +0000 Received: by mail-pl1-x643.google.com with SMTP id a23so6819403plm.1 for ; Mon, 30 Mar 2020 07:47:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=crxY0P9Cw/36E1OJdjjcbQJMYcLGDWiv6136clh8l9U=; b=czXjoOWFPBtTtkQvPysXcb0DCDUQVaHz3OtP4zjah1iBNMLwcICDUenm2ux2n5dLAh sjgfl1rDa0/iXIxzqOGC/Zvr7/W1Vi8TfrlXBQbluU0qO/0BkIPIrAikKazj4ajetuWN Vo5ZVN+oICB8IYuGIwGQcVr7j+XSnMS0dhxhRILrmMO2bf38KhI9/YObNgM/06OScLcq H5i7LjzWva1pRF3fWvZNFaKZQg8PuJbQEYEj6cNtk9YJwgt+d/Thum9CfXcDeWnplg+m Xaqc/jNSQRVbXO4MBG/+5HUlDNN3JooxR+Qxv8+Vpo/cNrFgT0DqQS+gxAnzupaildbW X4Cg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=crxY0P9Cw/36E1OJdjjcbQJMYcLGDWiv6136clh8l9U=; b=o7zRxXpcxapehUEngMfbY0jdHFNmedkycBV7n8bx4MoZyS2WYsA+7HCNkBVqQYCseM 5ntVsZyXy5Lm6WZr+TaZmJDqnFgKvaRqPnoVcWCnDe9CDn3etvkmXsXHG8V5/Qyxd9kS 8UzKTmjyJKsMPAYlovgg19U1RbfTbBD9OaSXkz7M1cRsprWW7Jfqmx95mhOLoKzanP5M BJYIwhYpuoO3Tj4cyG045XtADrAjglR/rySU7Hm6Ch+v1S8X/uZyDDq0XD7BP+OItfcd 49TH+Dkr17zlDR7AyI/TKS9BJCRThJgiPjVbhtrxHYEgdMJDETyzBxprJoEiEJGXVhH0 fylQ== X-Gm-Message-State: ANhLgQ2OVuPBnfqt4ai1CL89ErMDzqMH+SePcKdmU3WxnZFXdI+k+oES tCD8m6Jlm5yuDSYrLqop6aE= X-Google-Smtp-Source: ADFU+vsSZ21zZYhlGeXEbFW7k8n8Gggry75EDOXpm7jg9uCeexs2G2gidB1e0D4ykJVheNYs25jpzA== X-Received: by 2002:a17:90a:30cf:: with SMTP id h73mr16978054pjb.189.1585579675815; Mon, 30 Mar 2020 07:47:55 -0700 (PDT) Received: from earth-mac.local (219x123x138x129.ap219.ftth.ucom.ne.jp. [219.123.138.129]) by smtp.gmail.com with ESMTPSA id 66sm10507703pfb.150.2020.03.30.07.47.54 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 30 Mar 2020 07:47:55 -0700 (PDT) Received: by earth-mac.local (Postfix, from userid 501) id 3D9EA202804D6E; Mon, 30 Mar 2020 23:47:53 +0900 (JST) From: Hajime Tazaki To: linux-um@lists.infradead.org Subject: [RFC v4 11/25] um lkl: plug in the build system Date: Mon, 30 Mar 2020 23:45:43 +0900 Message-Id: X-Mailer: git-send-email 2.20.1 (Apple Git-117) In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200330_074756_601922_D04051C5 X-CRM114-Status: GOOD ( 16.32 ) X-Spam-Score: -0.2 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:643 listed in] [list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [thehajime[at]gmail.com] -0.0 SPF_PASS SPF: sender matches SPF record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 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: Octavian Purdila , linux-kernel-library@freelists.org, linux-arch@vger.kernel.org, Hajime Tazaki , Akira Moroo Sender: "linux-um" Errors-To: linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Octavian Purdila Basic Makefiles for building LKL. Add a new architecture specific target for installing the resulting library files and headers. To make LKL binaries build, UML introduced an additional option, UMMODE variable, to switch the output file of build: kernel (default), or library (LKL). Those modes are not able to be ON at the same time. To build on library mode, users do the following: make defconfig ARCH=um UMMODE=library make ARCH=um UMMODE=library Signed-off-by: Octavian Purdila Signed-off-by: Akira Moroo Signed-off-by: Hajime Tazaki --- arch/um/Kconfig | 13 +++++++ arch/um/Makefile | 19 ++++++++++- arch/um/Makefile.um | 10 ++++++ arch/um/lkl/Kconfig | 31 +++++++++++++++-- arch/um/lkl/Makefile | 67 +++++++++++++++++++++++++++++++++++++ arch/um/lkl/auto.conf | 1 + arch/um/lkl/kernel/Makefile | 4 +++ arch/um/lkl/mm/Makefile | 1 + 8 files changed, 143 insertions(+), 3 deletions(-) create mode 100644 arch/um/Makefile.um create mode 100644 arch/um/lkl/Makefile create mode 100644 arch/um/lkl/auto.conf create mode 100644 arch/um/lkl/kernel/Makefile create mode 100644 arch/um/lkl/mm/Makefile diff --git a/arch/um/Kconfig b/arch/um/Kconfig index 96ab7026b037..17a6bc25b615 100644 --- a/arch/um/Kconfig +++ b/arch/um/Kconfig @@ -5,6 +5,10 @@ menu "UML-specific options" config UML bool default y + +config UMMODE_KERN + bool "UML mode: kernel mode" + default y if "$(UMMODE)" = "kernel" select ARCH_HAS_KCOV select ARCH_NO_PREEMPT select HAVE_ARCH_AUDITSYSCALL @@ -20,7 +24,12 @@ config UML select GENERIC_CLOCKEVENTS select HAVE_GCC_PLUGINS select TTY # Needed for line.c + help + This mode switches a mode to build a regular kernel executable + of UML. + +if UMMODE_KERN config MMU bool default y @@ -207,6 +216,10 @@ config UML_TIME_TRAVEL_SUPPORT It is safe to say Y, but you probably don't need this. +endif #UMMODE_KERN + endmenu source "arch/um/drivers/Kconfig" + +source "arch/um/lkl/Kconfig" diff --git a/arch/um/Makefile b/arch/um/Makefile index d2daa206872d..f2a537f700c2 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # This file is included by the global makefile so that you can add your own # architecture-specific flags and dependencies. @@ -44,7 +45,7 @@ HOST_DIR := arch/$(HEADER_ARCH) include $(ARCH_DIR)/Makefile-skas include $(HOST_DIR)/Makefile.um -core-y += $(HOST_DIR)/um/ + SHARED_HEADERS := $(ARCH_DIR)/include/shared ARCH_INCLUDE := -I$(srctree)/$(SHARED_HEADERS) @@ -144,5 +145,21 @@ CLEAN_FILES += linux x.i gmon.out archclean: @find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \ -o -name '*.gcov' \) -type f -print | xargs rm -f + $(Q)rm -rf $(srctree)/$(LKL_DIR)/include/generated export HEADER_ARCH SUBARCH USER_CFLAGS CFLAGS_NO_HARDENING OS DEV_NULL_PATH + + + +# SPDX-License-Identifier: GPL-2.0 +# select mode of UML build +UMMODE ?= kernel +LKL_DIR := $(ARCH_DIR)/lkl + +ifeq ($(UMMODE),kernel) + include $(ARCH_DIR)/Makefile.um +else ifeq ($(UMMODE),library) + include $(ARCH_DIR)/lkl/Makefile +endif + +export UMMODE LKL_DIR diff --git a/arch/um/Makefile.um b/arch/um/Makefile.um new file mode 100644 index 000000000000..be7ee4d1adde --- /dev/null +++ b/arch/um/Makefile.um @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# This file is included by the global makefile so that you can add your own +# architecture-specific flags and dependencies. +# +# Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) +# Licensed under the GPL +# + +core-y += $(HOST_DIR)/um/ diff --git a/arch/um/lkl/Kconfig b/arch/um/lkl/Kconfig index f7e8d707a12b..c72c40226509 100644 --- a/arch/um/lkl/Kconfig +++ b/arch/um/lkl/Kconfig @@ -1,6 +1,25 @@ # SPDX-License-Identifier: GPL-2.0 -config UML_LKL +menu "LKL-specific options" + +config UML + bool + default y + +config UMMODE_LIB + bool "UML mode: library mode" + depends on !UMMODE_KERN + select LKL + default y if "$(UMMODE)" = "library" + help + This mode switches a mode to build a library of UML (Linux + Kernel Library/LKL). This switch is exclusive to "kernel mode" + of UML, which is traditional mode of UML. + + For more detail about LKL, see + . + +config LKL def_bool y depends on !SMP && !MMU && !COREDUMP && !SECCOMP && !UPROBES && !COMPAT && !USER_RETURN_NOTIFIER select ARCH_THREAD_STACK_ALLOCATOR @@ -29,6 +48,12 @@ config OUTPUT_FORMAT config ARCH_DMA_ADDR_T_64BIT def_bool 64BIT +config X86_64 + def_bool y if "$(OUTPUT_FORMAT)" = "elf64-x86-64" + +config X86_32 + def_bool y if "$(OUTPUT_FORMAT)" = "elf32-i386" + config 64BIT def_bool n @@ -39,7 +64,7 @@ config BIG_ENDIAN def_bool n config GENERIC_CSUM - def_bool y + def_bool LKL config GENERIC_HWEIGHT def_bool y @@ -54,3 +79,5 @@ config RWSEM_GENERIC_SPINLOCK config HZ int default 100 + +endmenu diff --git a/arch/um/lkl/Makefile b/arch/um/lkl/Makefile new file mode 100644 index 000000000000..e1161fa3fb63 --- /dev/null +++ b/arch/um/lkl/Makefile @@ -0,0 +1,67 @@ +# SPDX-License-Identifier: GPL-2.0 + +include $(LKL_DIR)/auto.conf + +# fixup CFLAGS of um build +KBUILD_CFLAGS := $(subst $(CFLAGS),,$(KBUILD_CFLAGS)) + +SRCARCH := um/lkl +ARCH_INCLUDE += -I$(srctree)/$(LKL_DIR)/um/include +LINUXINCLUDE := $(subst $(ARCH_DIR),$(LKL_DIR),$(LINUXINCLUDE)) $(ARCH_INCLUDE) +KBUILD_CFLAGS += -fno-builtin +KBUILD_DEFCONFIG := lkl_defconfig + +ifneq (,$(filter $(OUTPUT_FORMAT),elf64-x86-64 elf32-i386 elf64-x86-64-freebsd elf32-littlearm elf64-littleaarch64)) +KBUILD_CFLAGS += -fPIC +else ifneq (,$(filter $(OUTPUT_FORMAT),pe-i386 pe-x86-64 )) +ifneq ($(OUTPUT_FORMAT),pe-x86-64) +prefix=_ +endif +# workaround for #include_next errors +LINUXINCLUDE := -isystem $(LKL_DIR)/include/system $(LINUXINCLUDE) +# workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52991 +KBUILD_CFLAGS += -mno-ms-bitfields +else +$(error Unrecognized platform: $(OUTPUT_FORMAT)) +endif + +ifeq ($(shell uname -s), Linux) +NPROC=$(shell nproc) +else # e.g., FreeBSD +NPROC=$(shell sysctl -n hw.ncpu) +endif + +LDFLAGS_vmlinux += -r +LKL_ENTRY_POINTS := lkl_start_kernel lkl_sys_halt lkl_syscall lkl_trigger_irq \ + lkl_get_free_irq lkl_put_irq lkl_is_running lkl_bug lkl_printf + +ifeq ($(OUTPUT_FORMAT),elf32-i386) +LKL_ENTRY_POINTS += \ + __x86.get_pc_thunk.bx __x86.get_pc_thunk.dx __x86.get_pc_thunk.ax \ + __x86.get_pc_thunk.cx __x86.get_pc_thunk.si __x86.get_pc_thunk.di +endif + +core-y += $(LKL_DIR)/kernel/ +core-y += $(LKL_DIR)/mm/ + +all: lkl.o + +lkl.o: vmlinux + $(OBJCOPY) -R .eh_frame -R .syscall_defs $(foreach sym,$(LKL_ENTRY_POINTS),-G$(prefix)$(sym)) vmlinux lkl.o + +$(LKL_DIR)/include/generated/uapi/asm/syscall_defs.h: vmlinux + $(OBJCOPY) -j .syscall_defs -O binary --set-section-flags .syscall_defs=alloc $< $@ + $(Q) export tmpfile=$(shell mktemp); \ + sed 's/\x0//g' $@ > $$tmpfile; mv $$tmpfile $@ ; rm -f $$tmpfile + +install: lkl.o headers $(LKL_DIR)/include/generated/uapi/asm/syscall_defs.h + @echo " INSTALL $(INSTALL_PATH)/lib/lkl.o" + @mkdir -p $(INSTALL_PATH)/lib/ + @cp lkl.o $(INSTALL_PATH)/lib/ + $(Q)$(srctree)/$(LKL_DIR)/scripts/headers_install.py \ + $(subst -j,-j$(NPROC),$(findstring -j,$(MAKEFLAGS))) \ + $(INSTALL_PATH)/include + +define archhelp + echo ' install - Install library and headers to INSTALL_PATH/{lib,include}' +endef diff --git a/arch/um/lkl/auto.conf b/arch/um/lkl/auto.conf new file mode 100644 index 000000000000..4bfd65a02d73 --- /dev/null +++ b/arch/um/lkl/auto.conf @@ -0,0 +1 @@ +export OUTPUT_FORMAT=$(shell $(LD) -r -print-output-format) diff --git a/arch/um/lkl/kernel/Makefile b/arch/um/lkl/kernel/Makefile new file mode 100644 index 000000000000..ef489f2f7176 --- /dev/null +++ b/arch/um/lkl/kernel/Makefile @@ -0,0 +1,4 @@ +extra-y := vmlinux.lds + +obj-y = setup.o threads.o irq.o time.o syscalls.o misc.o console.o \ + syscalls_32.o cpu.o diff --git a/arch/um/lkl/mm/Makefile b/arch/um/lkl/mm/Makefile new file mode 100644 index 000000000000..2af6e3051897 --- /dev/null +++ b/arch/um/lkl/mm/Makefile @@ -0,0 +1 @@ +obj-y = bootmem.o From patchwork Mon Mar 30 14:45:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hajime Tazaki X-Patchwork-Id: 1263988 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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=bIRPTcvV; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=m7Eo7wtA; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (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 48rb1R51ymz9sP7 for ; Tue, 31 Mar 2020 01:48:27 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.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=5FWc73ojP6CYtHPNj9u/PlLS65Dypd7BNiMtg4u2Y6w=; b=bIRPTcvVWAyMTh Iq2vme9C/ocdTXfm2Vcs+ATtL0T7ggVOeFl9sNN8fM3+qnsKSCa+exWCsCugnRjFTHb9Jd8a5FQYL xOTw9vi/ugsO+7rjNJQQD+zkap2B8Wo9AwWVtNqWJed5Ji0Eg0j3S06UKZYrccR9A4TEAFNuAAR/J uVp+WR7+Tl42voU2JKLBKTr5aI1SjMGIUmDAVVqMTeD9Lt3a8OjN47ntGBw44pIFVqAlCs2/oufb7 qSPE3w6/qp644pDWW02Pu+Z6MmtwWrCwJZOTihXpxJjYPEPNlxtySmyctGk3F+/zvNoRTW/fUot1t hwtTfyb2OBwu6xOl+TZg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvi6-0004vL-Fa; Mon, 30 Mar 2020 14:48:18 +0000 Received: from mail-pj1-x1043.google.com ([2607:f8b0:4864:20::1043]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvi2-0004ua-FZ for linux-um@lists.infradead.org; Mon, 30 Mar 2020 14:48:17 +0000 Received: by mail-pj1-x1043.google.com with SMTP id jz1so6430193pjb.0 for ; Mon, 30 Mar 2020 07:48:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=zGYBhmvgID5eSC7rh+weNwge7uhFpNpVvXZwFggk8dg=; b=m7Eo7wtAE1p6N+oDcIdgjRKzH4EEFAw1Xd6iHhDCBEJ+itVTn+XOKWzMScgBiEoIT4 lsePQeIegYwuD/m0dz3zzRCtCZvGB2FyhrP0/wIurta/JKDWsEWnVGfBpcQVNm0OzKAW B+BHD5PU61cz2sMKkcAdVjUawY1djk+CcHHoDOcdN9/iNJeTlXJqtTMF7tgWXsQ+wprd SuY/B7plNyxHQMR1KyeY7m4mFa5L1N5hT72DiVFrs7UDqtkT3l6Od/qB2TH04frfgW3p rjKixIRIghw1liB1GPBdEgFSV8LBI6SX9JGMTHkYu2aBZ4b+RJvvof53z2ThAF4OKtRw nuAg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=zGYBhmvgID5eSC7rh+weNwge7uhFpNpVvXZwFggk8dg=; b=AbmQHZI0yrger7VBVwumxfVDpUq04j8h9otcDM4h7he7oYeBa58o9VqZiRxLk50LNC YzPaO7cfxvQePXDPiYKxSrul4jdvQLOrli+ehqjXjLkmjXs1XnKuH/jSsWDb3/eXhYMT kyplkpLE6t+qso6vi/f24GnHUreSGp5ohaorEKcY1HGEk7OzpQNB7KZgQnX4S6DVodXV lUDXWHPkIwrtL7i6qo+vUceJtV8k4AsF4g1COEXukudU5k267kwoIKBcUnrB9pMbil+W +qxfk3VH4vcyfSh1Bc8LFHgn7J4AcnJpdtool7DrNJ4BGdT9ZyOaqJk30ZJhFZ8u/EtV 7grg== X-Gm-Message-State: ANhLgQ125GhUYeTAoc6l61YJP60EDHWrgdfo2YGHAxKy5/ESVWL8yYLL pVokrbtX/drce5TPFNoI5KkWtkx9N4E8CA== X-Google-Smtp-Source: ADFU+vvPwYdGJGXdeoLCxx0Vp/QsQahYF1JlklOniLEW8B2ZV1ZoIJd7cNoA/vGALC6zgxZmGmc7VA== X-Received: by 2002:a17:902:b004:: with SMTP id o4mr11997739plr.54.1585579693729; Mon, 30 Mar 2020 07:48:13 -0700 (PDT) Received: from earth-mac.local (219x123x138x129.ap219.ftth.ucom.ne.jp. [219.123.138.129]) by smtp.gmail.com with ESMTPSA id h4sm9893359pgk.72.2020.03.30.07.48.12 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 30 Mar 2020 07:48:12 -0700 (PDT) Received: by earth-mac.local (Postfix, from userid 501) id E99F2202804DC1; Mon, 30 Mar 2020 23:48:10 +0900 (JST) From: Hajime Tazaki To: linux-um@lists.infradead.org Subject: [RFC v4 12/25] lkl tools: skeleton for host side library Date: Mon, 30 Mar 2020 23:45:44 +0900 Message-Id: <901a5e531f9fcff3f9c0b165fde3bfcad98a19ee.1585579244.git.thehajime@gmail.com> X-Mailer: git-send-email 2.20.1 (Apple Git-117) In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200330_074814_538035_AD0AE119 X-CRM114-Status: GOOD ( 14.86 ) X-Spam-Score: -0.2 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:1043 listed in] [list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [thehajime[at]gmail.com] -0.0 SPF_PASS SPF: sender matches SPF record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 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: linux-arch@vger.kernel.org, Patrick Collins , Xiao Jia , Hajime Tazaki , Conrad Meyer , Octavian Purdila , Motomu Utsumi , Akira Moroo , Petros Angelatos , Thomas Liebetraut , Mark Stillwell , Ben Wolsieffer , linux-kernel-library@freelists.org, Michael Zimmermann , Luca Dariz , Yuan Liu Sender: "linux-um" Errors-To: linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Octavian Purdila This patch adds the skeleton for the host library. The host library is implementing the host operations needed by LKL and is split into host dependent (depends on a specific host, e.g. POSIX hosts) and host independent parts (will work on all supported hosts). Cc: Ben Wolsieffer Cc: Conrad Meyer Cc: H.K. Jerry Chu Cc: Luca Dariz Cc: Mark Stillwell Cc: Michael Zimmermann Cc: Motomu Utsumi Cc: Patrick Collins Cc: Petros Angelatos Cc: Thomas Liebetraut Cc: Xiao Jia Cc: Yuan Liu Signed-off-by: Hajime Tazaki Signed-off-by: Octavian Purdila --- tools/lkl/.gitignore | 4 + tools/lkl/Build | 0 tools/lkl/Makefile | 125 ++++++++++++ tools/lkl/Makefile.autoconf | 65 +++++++ tools/lkl/Targets | 3 + tools/lkl/include/.gitignore | 1 + tools/lkl/include/lkl.h | 358 +++++++++++++++++++++++++++++++++++ tools/lkl/include/lkl_host.h | 19 ++ tools/lkl/lib/.gitignore | 3 + tools/lkl/lib/Build | 1 + 10 files changed, 579 insertions(+) create mode 100644 tools/lkl/.gitignore create mode 100644 tools/lkl/Build create mode 100644 tools/lkl/Makefile create mode 100644 tools/lkl/Makefile.autoconf create mode 100644 tools/lkl/Targets create mode 100644 tools/lkl/include/.gitignore create mode 100644 tools/lkl/include/lkl.h create mode 100644 tools/lkl/include/lkl_host.h create mode 100644 tools/lkl/lib/.gitignore create mode 100644 tools/lkl/lib/Build diff --git a/tools/lkl/.gitignore b/tools/lkl/.gitignore new file mode 100644 index 000000000000..1aed58bfe171 --- /dev/null +++ b/tools/lkl/.gitignore @@ -0,0 +1,4 @@ +Makefile.conf +include/lkl_autoconf.h +tests/autoconf.sh +bin/stat diff --git a/tools/lkl/Build b/tools/lkl/Build new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tools/lkl/Makefile b/tools/lkl/Makefile new file mode 100644 index 000000000000..11ea7e9095bb --- /dev/null +++ b/tools/lkl/Makefile @@ -0,0 +1,125 @@ +# Do not use make's built-in rules +# (this improves performance and avoids hard-to-debug behaviour); +# also do not print "Entering directory..." messages from make +.SUFFIXES: +MAKEFLAGS += -r --no-print-directory + +KCONFIG?=defconfig + +ifneq ($(silent),1) + ifneq ($(V),1) + QUIET_AUTOCONF = @echo ' AUTOCONF '$@; + Q = @ + endif +endif + +PREFIX := /usr + +ifeq (,$(srctree)) + srctree := $(patsubst %/,%,$(dir $(shell pwd))) + srctree := $(patsubst %/,%,$(dir $(srctree))) +endif +export srctree + +-include $(srctree)/tools/scripts/Makefile.include + +# OUTPUT fixup should be *after* include ../scripts/Makefile.include +ifneq ($(OUTPUT),) + OUTPUT := $(OUTPUT)/tools/lkl/ +else + OUTPUT := $(CURDIR)/ +endif +export OUTPUT + + +all: + +conf: $(OUTPUT)Makefile.conf + +$(OUTPUT)Makefile.conf: Makefile.autoconf + $(call QUIET_AUTOCONF, headers)$(MAKE) -f Makefile.autoconf -s + +-include $(OUTPUT)Makefile.conf + +export CFLAGS += -I$(OUTPUT)/include -Iinclude -Wall -g -O2 -Wextra \ + -Wno-unused-parameter \ + -Wno-missing-field-initializers -fno-strict-aliasing + +-include Targets + +TARGETS := $(progs-y:%=$(OUTPUT)%$(EXESUF)) +TARGETS += $(libs-y:%=$(OUTPUT)%$(SOSUF)) +all: $(TARGETS) + +# this workaround is for FreeBSD +bin/stat: + $(Q)mkdir -p bin/ +ifeq ($(LKL_HOST_CONFIG_BSD),y) + $(Q)ln -sf `which gnustat` bin/stat + $(Q)ln -sf `which gsed` bin/sed +else + $(Q)touch bin/stat +endif + +# rule to build lkl.o +$(OUTPUT)lib/lkl.o: bin/stat + $(Q)$(MAKE) -C $(srctree) ARCH=um UMMODE=library $(KOPT) $(KCONFIG) +# this workaround is for arm32 linker (ld.gold) + $(Q)export PATH=$(shell pwd)/bin/:${PATH} ;\ + $(MAKE) -C $(srctree) ARCH=um UMMODE=library $(KOPT) install INSTALL_PATH=$(OUTPUT) + +# rules to link libs +$(OUTPUT)%$(SOSUF): LDFLAGS += -shared +$(OUTPUT)%$(SOSUF): $(OUTPUT)%-in.o $(OUTPUT)liblkl.a + $(QUIET_LINK)$(CC) $(LDFLAGS) $(LDFLAGS_$*-y) -o $@ $^ $(LDLIBS) $(LDLIBS_$*-y) + +# liblkl is special +$(OUTPUT)liblkl$(SOSUF): $(OUTPUT)%-in.o $(OUTPUT)lib/lkl.o +$(OUTPUT)liblkl.a: $(OUTPUT)lib/liblkl-in.o $(OUTPUT)lib/lkl.o + $(QUIET_AR)$(AR) -rc $@ $^ + +# rule to link programs +$(OUTPUT)%$(EXESUF): $(OUTPUT)%-in.o $(OUTPUT)liblkl.a + $(QUIET_LINK)$(CC) $(LDFLAGS) $(LDFLAGS_$*-y) -o $@ $^ $(LDLIBS) $(LDLIBS_$*-y) + +# rule to build objects +$(OUTPUT)%-in.o: $(OUTPUT)lib/lkl.o FORCE + $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(patsubst %/,%,$(dir $*)) obj=$(notdir $*) + + +clean: + $(call QUIET_CLEAN, objects)find $(OUTPUT) -name '*.o' -delete -o -name '\.*.cmd'\ + -delete -o -name '\.*.d' -delete + $(call QUIET_CLEAN, headers)$(RM) -r $(OUTPUT)/include/lkl/ + $(call QUIET_CLEAN, liblkl.a)$(RM) $(OUTPUT)/liblkl.a + $(call QUIET_CLEAN, targets)$(RM) $(TARGETS) bin/stat + +clean-conf: clean + $(call QUIET_CLEAN, Makefile.conf)$(RM) $(OUTPUT)/Makefile.conf + +headers_install: $(TARGETS) + $(call QUIET_INSTALL, headers) \ + install -d $(DESTDIR)$(PREFIX)/include ; \ + install -m 644 include/lkl.h include/lkl_host.h $(OUTPUT)include/lkl_autoconf.h \ + include/lkl_config.h $(DESTDIR)$(PREFIX)/include ; \ + cp -r $(OUTPUT)include/lkl $(DESTDIR)$(PREFIX)/include + +libraries_install: $(libs-y:%=$(OUTPUT)%$(SOSUF)) $(OUTPUT)liblkl.a + $(call QUIET_INSTALL, libraries) \ + install -d $(DESTDIR)$(PREFIX)/lib ; \ + install -m 644 $^ $(DESTDIR)$(PREFIX)/lib + +programs_install: $(progs-y:%=$(OUTPUT)%$(EXESUF)) + $(call QUIET_INSTALL, programs) \ + install -d $(DESTDIR)$(PREFIX)/bin ; \ + install -m 755 $^ $(DESTDIR)$(PREFIX)/bin + +install: headers_install libraries_install programs_install + + +FORCE: ; +.PHONY: all clean FORCE +.PHONY: headers_install libraries_install programs_install install +.NOTPARALLEL : lib/lkl.o +.SECONDARY: + diff --git a/tools/lkl/Makefile.autoconf b/tools/lkl/Makefile.autoconf new file mode 100644 index 000000000000..268c367d9962 --- /dev/null +++ b/tools/lkl/Makefile.autoconf @@ -0,0 +1,65 @@ +POSIX_HOSTS=elf64-x86-64 elf32-i386 elf64-x86-64-freebsd + +define set_autoconf_var + $(shell echo "#define LKL_HOST_CONFIG_$(1) $(2)" \ + >> $(OUTPUT)/include/lkl_autoconf.h) + $(shell echo "LKL_HOST_CONFIG_$(1)=$(2)" >> $(OUTPUT)/tests/autoconf.sh) + export LKL_HOST_CONFIG_$(1)=$(2) +endef + +define find_include + $(eval include_paths=$(shell $(CC) -E -Wp,-v -xc /dev/null 2>&1 | grep '^ ')) + $(foreach f, $(include_paths), $(wildcard $(f)/$(1))) +endef + +define is_defined +$(shell $(CC) -dM -E - $(OUTPUT)/include/lkl_autoconf.h) + $(shell echo -n "" > $(OUTPUT)/tests/autoconf.sh) + @echo "$$do_autoconf" > $(OUTPUT)/Makefile.conf diff --git a/tools/lkl/Targets b/tools/lkl/Targets new file mode 100644 index 000000000000..24c985e64638 --- /dev/null +++ b/tools/lkl/Targets @@ -0,0 +1,3 @@ +libs-y += lib/liblkl + + diff --git a/tools/lkl/include/.gitignore b/tools/lkl/include/.gitignore new file mode 100644 index 000000000000..c41a463c898d --- /dev/null +++ b/tools/lkl/include/.gitignore @@ -0,0 +1 @@ +lkl/ \ No newline at end of file diff --git a/tools/lkl/include/lkl.h b/tools/lkl/include/lkl.h new file mode 100644 index 000000000000..4b95d0ef8e5b --- /dev/null +++ b/tools/lkl/include/lkl.h @@ -0,0 +1,358 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LKL_H +#define _LKL_H + +#include "lkl_autoconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define _LKL_LIBC_COMPAT_H + +#ifdef __cplusplus +#define class __lkl__class +#endif + +/* + * Avoid collisions between Android which defines __unused and + * linux/icmp.h which uses __unused as a structure field. + */ +#pragma push_macro("__unused") +#undef __unused + +#include + +#pragma pop_macro("__unused") + +#ifdef __cplusplus +#undef class +#endif + +#if defined(__MINGW32__) +#define strtok_r strtok_s +#define inet_pton lkl_inet_pton + +int inet_pton(int af, const char *src, void *dst); +#endif + +#if __LKL__BITS_PER_LONG == 64 +#define lkl_sys_fstatat lkl_sys_newfstatat +#define lkl_sys_fstat lkl_sys_newfstat + +#else +#define __lkl__NR_fcntl __lkl__NR_fcntl64 + +#define lkl_stat lkl_stat64 +#define lkl_sys_stat lkl_sys_stat64 +#define lkl_sys_lstat lkl_sys_lstat64 +#define lkl_sys_truncate lkl_sys_truncate64 +#define lkl_sys_ftruncate lkl_sys_ftruncate64 +#define lkl_sys_sendfile lkl_sys_sendfile64 +#define lkl_sys_fstatat lkl_sys_fstatat64 +#define lkl_sys_fstat lkl_sys_fstat64 +#define lkl_sys_fcntl lkl_sys_fcntl64 + +#define lkl_statfs lkl_statfs64 + +static inline int lkl_sys_statfs(const char *path, struct lkl_statfs *buf) +{ + return lkl_sys_statfs64(path, sizeof(*buf), buf); +} + +static inline int lkl_sys_fstatfs(unsigned int fd, struct lkl_statfs *buf) +{ + return lkl_sys_fstatfs64(fd, sizeof(*buf), buf); +} + +#define lkl_sys_nanosleep lkl_sys_nanosleep_time32 +static inline int lkl_sys_nanosleep_time32(struct __lkl__kernel_timespec *rqtp, + struct __lkl__kernel_timespec *rmtp) +{ + long p[6] = {(long)rqtp, (long)rmtp, 0, 0, 0, 0}; + + return lkl_syscall(__lkl__NR_nanosleep, p); +} + +#endif + +static inline int lkl_sys_stat(const char *path, struct lkl_stat *buf) +{ + return lkl_sys_fstatat(LKL_AT_FDCWD, path, buf, 0); +} + +static inline int lkl_sys_lstat(const char *path, struct lkl_stat *buf) +{ + return lkl_sys_fstatat(LKL_AT_FDCWD, path, buf, + LKL_AT_SYMLINK_NOFOLLOW); +} + +#ifdef __lkl__NR_llseek +/** + * lkl_sys_lseek - wrapper for lkl_sys_llseek + */ +static inline long long lkl_sys_lseek(unsigned int fd, __lkl__kernel_loff_t off, + unsigned int whence) +{ + long long res; + long ret = lkl_sys_llseek(fd, off >> 32, off & 0xffffffff, &res, + whence); + + return ret < 0 ? ret : res; +} +#endif + +static inline void *lkl_sys_mmap(void *addr, size_t length, int prot, int flags, + int fd, off_t offset) +{ + return (void *)lkl_sys_mmap_pgoff((long)addr, length, prot, flags, fd, + offset >> 12); +} + +#define lkl_sys_mmap2 lkl_sys_mmap_pgoff + +#ifdef __lkl__NR_openat +/** + * lkl_sys_open - wrapper for lkl_sys_openat + */ +static inline long lkl_sys_open(const char *file, int flags, int mode) +{ + return lkl_sys_openat(LKL_AT_FDCWD, file, flags, mode); +} + +/** + * lkl_sys_creat - wrapper for lkl_sys_openat + */ +static inline long lkl_sys_creat(const char *file, int mode) +{ + return lkl_sys_openat(LKL_AT_FDCWD, file, + LKL_O_CREAT|LKL_O_WRONLY|LKL_O_TRUNC, mode); +} +#endif + + +#ifdef __lkl__NR_faccessat +/** + * lkl_sys_access - wrapper for lkl_sys_faccessat + */ +static inline long lkl_sys_access(const char *file, int mode) +{ + return lkl_sys_faccessat(LKL_AT_FDCWD, file, mode); +} +#endif + +#ifdef __lkl__NR_fchownat +/** + * lkl_sys_chown - wrapper for lkl_sys_fchownat + */ +static inline long lkl_sys_chown(const char *path, lkl_uid_t uid, lkl_gid_t gid) +{ + return lkl_sys_fchownat(LKL_AT_FDCWD, path, uid, gid, 0); +} +#endif + +#ifdef __lkl__NR_fchmodat +/** + * lkl_sys_chmod - wrapper for lkl_sys_fchmodat + */ +static inline long lkl_sys_chmod(const char *path, mode_t mode) +{ + return lkl_sys_fchmodat(LKL_AT_FDCWD, path, mode); +} +#endif + +#ifdef __lkl__NR_linkat +/** + * lkl_sys_link - wrapper for lkl_sys_linkat + */ +static inline long lkl_sys_link(const char *existing, const char *new) +{ + return lkl_sys_linkat(LKL_AT_FDCWD, existing, LKL_AT_FDCWD, new, 0); +} +#endif + +#ifdef __lkl__NR_unlinkat +/** + * lkl_sys_unlink - wrapper for lkl_sys_unlinkat + */ +static inline long lkl_sys_unlink(const char *path) +{ + return lkl_sys_unlinkat(LKL_AT_FDCWD, path, 0); +} +#endif + +#ifdef __lkl__NR_symlinkat +/** + * lkl_sys_symlink - wrapper for lkl_sys_symlinkat + */ +static inline long lkl_sys_symlink(const char *existing, const char *new) +{ + return lkl_sys_symlinkat(existing, LKL_AT_FDCWD, new); +} +#endif + +#ifdef __lkl__NR_readlinkat +/** + * lkl_sys_readlink - wrapper for lkl_sys_readlinkat + */ +static inline long lkl_sys_readlink(const char *path, char *buf, size_t bufsize) +{ + return lkl_sys_readlinkat(LKL_AT_FDCWD, path, buf, bufsize); +} +#endif + +#ifdef __lkl__NR_renameat +/** + * lkl_sys_rename - wrapper for lkl_sys_renameat + */ +static inline long lkl_sys_rename(const char *old, const char *new) +{ + return lkl_sys_renameat(LKL_AT_FDCWD, old, LKL_AT_FDCWD, new); +} +#endif + +#ifdef __lkl__NR_mkdirat +/** + * lkl_sys_mkdir - wrapper for lkl_sys_mkdirat + */ +static inline long lkl_sys_mkdir(const char *path, mode_t mode) +{ + return lkl_sys_mkdirat(LKL_AT_FDCWD, path, mode); +} +#endif + +#ifdef __lkl__NR_unlinkat +/** + * lkl_sys_rmdir - wrapper for lkl_sys_unlinkrat + */ +static inline long lkl_sys_rmdir(const char *path) +{ + return lkl_sys_unlinkat(LKL_AT_FDCWD, path, LKL_AT_REMOVEDIR); +} +#endif + +#ifdef __lkl__NR_mknodat +/** + * lkl_sys_mknod - wrapper for lkl_sys_mknodat + */ +static inline long lkl_sys_mknod(const char *path, mode_t mode, dev_t dev) +{ + return lkl_sys_mknodat(LKL_AT_FDCWD, path, mode, dev); +} +#endif + +#ifdef __lkl__NR_pipe2 +/** + * lkl_sys_pipe - wrapper for lkl_sys_pipe2 + */ +static inline long lkl_sys_pipe(int fd[2]) +{ + return lkl_sys_pipe2(fd, 0); +} +#endif + +#ifdef __lkl__NR_sendto +/** + * lkl_sys_send - wrapper for lkl_sys_sendto + */ +static inline long lkl_sys_send(int fd, void *buf, size_t len, int flags) +{ + return lkl_sys_sendto(fd, buf, len, flags, 0, 0); +} +#endif + +#ifdef __lkl__NR_recvfrom +/** + * lkl_sys_recv - wrapper for lkl_sys_recvfrom + */ +static inline long lkl_sys_recv(int fd, void *buf, size_t len, int flags) +{ + return lkl_sys_recvfrom(fd, buf, len, flags, 0, 0); +} +#endif + +#ifdef __lkl__NR_pselect6 +/** + * lkl_sys_select - wrapper for lkl_sys_pselect + */ +static inline long lkl_sys_select(int n, lkl_fd_set *rfds, lkl_fd_set *wfds, + lkl_fd_set *efds, struct lkl_timeval *tv) +{ + long data[2] = { 0, _LKL_NSIG/8 }; + struct lkl_timespec ts; + lkl_time_t extra_secs; + const lkl_time_t max_time = ((1ULL<<8)*sizeof(time_t)-1)-1; + + if (tv) { + if (tv->tv_sec < 0 || tv->tv_usec < 0) + return -LKL_EINVAL; + + extra_secs = tv->tv_usec / 1000000; + ts.tv_nsec = tv->tv_usec % 1000000 * 1000; + ts.tv_sec = extra_secs > max_time - tv->tv_sec ? + max_time : tv->tv_sec + extra_secs; + } + return lkl_sys_pselect6(n, rfds, wfds, efds, tv ? + (struct __lkl__kernel_timespec *)&ts : 0, data); +} +#endif + +#ifdef __lkl__NR_ppoll +/** + * lkl_sys_poll - wrapper for lkl_sys_ppoll + */ +static inline long lkl_sys_poll(struct lkl_pollfd *fds, int n, int timeout) +{ + return lkl_sys_ppoll(fds, n, timeout >= 0 ? + (struct __lkl__kernel_timespec *) + &((struct lkl_timespec){ .tv_sec = timeout/1000, + .tv_nsec = timeout%1000*1000000 }) : 0, + 0, _LKL_NSIG/8); +} +#endif + +#ifdef __lkl__NR_epoll_create1 +/** + * lkl_sys_epoll_create - wrapper for lkl_sys_epoll_create1 + */ +static inline long lkl_sys_epoll_create(int size) +{ + return lkl_sys_epoll_create1(0); +} +#endif + +#ifdef __lkl__NR_epoll_pwait +/** + * lkl_sys_epoll_wait - wrapper for lkl_sys_epoll_pwait + */ +static inline long lkl_sys_epoll_wait(int fd, struct lkl_epoll_event *ev, + int cnt, int to) +{ + return lkl_sys_epoll_pwait(fd, ev, cnt, to, 0, _LKL_NSIG/8); +} +#endif + + + +/** + * lkl_strerror - returns a string describing the given error code + * + * @err - error code + * @returns - string for the given error code + */ +const char *lkl_strerror(int err); + +/** + * lkl_perror - prints a string describing the given error code + * + * @msg - prefix for the error message + * @err - error code + */ +void lkl_perror(char *msg, int err); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/tools/lkl/include/lkl_host.h b/tools/lkl/include/lkl_host.h new file mode 100644 index 000000000000..b5f96096fe69 --- /dev/null +++ b/tools/lkl/include/lkl_host.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LKL_HOST_H +#define _LKL_HOST_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +extern struct lkl_host_operations lkl_host_ops; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/tools/lkl/lib/.gitignore b/tools/lkl/lib/.gitignore new file mode 100644 index 000000000000..427ae0273fdd --- /dev/null +++ b/tools/lkl/lib/.gitignore @@ -0,0 +1,3 @@ +lkl.o +liblkl.a + diff --git a/tools/lkl/lib/Build b/tools/lkl/lib/Build new file mode 100644 index 000000000000..8b137891791f --- /dev/null +++ b/tools/lkl/lib/Build @@ -0,0 +1 @@ + From patchwork Mon Mar 30 14:45:45 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hajime Tazaki X-Patchwork-Id: 1263989 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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=eKpN0POq; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=uYMVovbM; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (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 48rb1W0ClGz9sP7 for ; Tue, 31 Mar 2020 01:48:31 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.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=5sXeYG7H+JATlbCU1Gx56dfSZnUCzZ5zz3SKsvUo5n0=; b=eKpN0POqxVTr3w JOAwSsStdQZnk6RvM465y2tSMFGTy7uUr+XRq+gETprbccBO5Ax+vcB52oJ3ZA1fqeYO16ZFg3rvV UWbafrpwipN1EWrG4pA3nH3yBc3AczA1JjGJvKsfdDc/b2C2TnKUzGqGbczi215rYMqqwyBeILkwU 853GlXoI0I5HNk0dHfT07F3YdBb/UGxKWxBkhNUhLDYTCgXswc/zlsWoYLJpoUlDcCwvgGLp1SXkc BvTYSvkEfuSTDKvQGO+3KOzWhNY+uH+22fYvP7m2Wz0ux+lepO3F1gTIlR13cn8wzv6WQ92jCrSNM wXnyc3H92Q1cC0c+wGZQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvi9-0004wU-RD; Mon, 30 Mar 2020 14:48:21 +0000 Received: from mail-pj1-x1042.google.com ([2607:f8b0:4864:20::1042]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvi4-0004us-MP for linux-um@lists.infradead.org; Mon, 30 Mar 2020 14:48:20 +0000 Received: by mail-pj1-x1042.google.com with SMTP id np9so7679926pjb.4 for ; Mon, 30 Mar 2020 07:48:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=n+mIb8Ex+oi99qKsW1zNkHrEBQF7LZ6jP0LcinC7qeg=; b=uYMVovbMODtzSDZZ/oHkCUHFkgQAKIgZifpSioJepflkPtn/r/fbYU0UlH+tIY7laR tcedAhg3jlApS3s+coV5Gd/UKoUPk/b1Kbz4r58S0tMYD55jowZ3VfgB2FSBEvkiFAf0 Nw5PgHAWiZmTRrPXr6NoapGAvICbwuPiOKXxIhQR645LiEut06cjjarydJVzsPrhDKr0 TX1yO5Mo8Ng9HuWUme86csYSPXz73GThAits0rGy5V6hYLrCMpmq0msnsEQZVARFHGd9 MBXIIquWfou1CjwLKSSVjGYxoEte+1zny9EvxaIamHkSxS4ZasznwPRN2n0ZhQodQyiU qO7Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=n+mIb8Ex+oi99qKsW1zNkHrEBQF7LZ6jP0LcinC7qeg=; b=N2qQL/IV5ewanig8+FZRDezkDLFrbm+xLVfFsb/f0aA9wdNVZcwSyn3HzwtRn1RPgw 9DEvDwmE06L3eyYgt2SkYRWo63OdfIiDtl9KI5pv6dJVhlErpew7OpGDZQBAOwc570eD dDwo/6tRfe8VTEhkrkAeIYYTY8M13y85bK8rvmPw8vHXHGNcKM87Gx5/87+D4Z6/rATQ NTst5nxOA2LAojK7hQPDGShi2iRGCjgunn6DORgWwqNfe/83py3YqfkX5NNranCFtsbz gCKN4jF9wJdtBgwRRs/gJkET9RFA89jaXZ+t+BgWx82aj4VXcDMAMiBHOpezR0ckFIk7 g11w== X-Gm-Message-State: ANhLgQ1CpPMvkvyHE83T82/Do0QDoH/9UjpgErNAHqoAf3s9UCUEWhp2 s8uSNgWEYqMReF+EQltcYtg= X-Google-Smtp-Source: ADFU+vvFZd1p1DkpecjEVCMr+RNcU/o5i2vkKaJ8JD30ThrmrY897vS5R8ozWnUcgOD4+2VE8K9HFw== X-Received: by 2002:a17:902:32b:: with SMTP id 40mr12507815pld.22.1585579695792; Mon, 30 Mar 2020 07:48:15 -0700 (PDT) Received: from earth-mac.local (219x123x138x129.ap219.ftth.ucom.ne.jp. [219.123.138.129]) by smtp.gmail.com with ESMTPSA id m68sm10836017pjb.0.2020.03.30.07.48.14 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 30 Mar 2020 07:48:15 -0700 (PDT) Received: by earth-mac.local (Postfix, from userid 501) id 2A80B202804DD9; Mon, 30 Mar 2020 23:48:13 +0900 (JST) From: Hajime Tazaki To: linux-um@lists.infradead.org Subject: [RFC v4 13/25] lkl tools: host lib: add utilities functions Date: Mon, 30 Mar 2020 23:45:45 +0900 Message-Id: <7c750f53b2f272239d6626895dc6de22a4fa2ab0.1585579244.git.thehajime@gmail.com> X-Mailer: git-send-email 2.20.1 (Apple Git-117) In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200330_074816_782124_D7EF0362 X-CRM114-Status: GOOD ( 19.20 ) X-Spam-Score: -0.2 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:1042 listed in] [list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [thehajime[at]gmail.com] -0.0 SPF_PASS SPF: sender matches SPF record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 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: linux-arch@vger.kernel.org, Hajime Tazaki , Conrad Meyer , Octavian Purdila , Motomu Utsumi , Akira Moroo , Patrick Collins , linux-kernel-library@freelists.org, Yuan Liu Sender: "linux-um" Errors-To: linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Octavian Purdila Add basic utility functions for getting a string from a kernel error code and a fprintf like function that uses the host print operation. The latter is useful for informing the user about errors that occur in the host library. Other configuration and debug utilities are also added. Cc: Conrad Meyer Cc: Patrick Collins Cc: Yuan Liu Cc: Motomu Utsumi Signed-off-by: Hajime Tazaki Signed-off-by: Octavian Purdila --- tools/lkl/include/lkl_config.h | 61 +++ tools/lkl/include/lkl_host.h | 7 + tools/lkl/lib/Build | 7 + tools/lkl/lib/config.c | 744 +++++++++++++++++++++++++++++++++ tools/lkl/lib/dbg.c | 300 +++++++++++++ tools/lkl/lib/dbg_handler.c | 44 ++ tools/lkl/lib/endian.h | 31 ++ tools/lkl/lib/jmp_buf.c | 14 + tools/lkl/lib/jmp_buf.h | 8 + tools/lkl/lib/utils.c | 266 ++++++++++++ 10 files changed, 1482 insertions(+) create mode 100644 tools/lkl/include/lkl_config.h create mode 100644 tools/lkl/lib/config.c create mode 100644 tools/lkl/lib/dbg.c create mode 100644 tools/lkl/lib/dbg_handler.c create mode 100644 tools/lkl/lib/endian.h create mode 100644 tools/lkl/lib/jmp_buf.c create mode 100644 tools/lkl/lib/jmp_buf.h create mode 100644 tools/lkl/lib/utils.c diff --git a/tools/lkl/include/lkl_config.h b/tools/lkl/include/lkl_config.h new file mode 100644 index 000000000000..d3edf8b414cf --- /dev/null +++ b/tools/lkl/include/lkl_config.h @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LKL_LIB_CONFIG_H +#define _LKL_LIB_CONFIG_H + +#define LKL_CONFIG_JSON_TOKEN_MAX 300 + +struct lkl_config_iface { + struct lkl_config_iface *next; + struct lkl_netdev *nd; + + /* OBSOLETE: should use IFTYPE and IFPARAMS */ + char *iftap; + char *iftype; + char *ifparams; + char *ifmtu_str; + char *ifip; + char *ifipv6; + char *ifgateway; + char *ifgateway6; + char *ifmac_str; + char *ifnetmask_len; + char *ifnetmask6_len; + char *ifoffload_str; + char *ifneigh_entries; + char *ifqdisc_entries; +}; + +struct lkl_config { + int ifnum; + struct lkl_config_iface *ifaces; + + char *gateway; + char *gateway6; + char *debug; + char *mount; + /* single_cpu mode: + * 0: Don't pin to single CPU (default). + * 1: Pin only LKL kernel threads to single CPU. + * 2: Pin all LKL threads to single CPU including all LKL kernel threads + * and device polling threads. Avoid this mode if having busy polling + * threads. + * + * mode 2 can achieve better TCP_RR but worse TCP_STREAM than mode 1. + * You should choose the best for your application and virtio device + * type. + */ + char *single_cpu; + char *sysctls; + char *boot_cmdline; + char *dump; + char *delay_main; +}; + +int lkl_load_config_json(struct lkl_config *cfg, char *jstr); +int lkl_load_config_env(struct lkl_config *cfg); +void lkl_show_config(struct lkl_config *cfg); +int lkl_load_config_pre(struct lkl_config *cfg); +int lkl_load_config_post(struct lkl_config *cfg); +int lkl_unload_config(struct lkl_config *cfg); + +#endif /* _LKL_LIB_CONFIG_H */ diff --git a/tools/lkl/include/lkl_host.h b/tools/lkl/include/lkl_host.h index b5f96096fe69..85e80eb4ad0d 100644 --- a/tools/lkl/include/lkl_host.h +++ b/tools/lkl/include/lkl_host.h @@ -11,6 +11,13 @@ extern "C" { extern struct lkl_host_operations lkl_host_ops; +/** + * lkl_printf - print a message via the host print operation + * + * @fmt: printf like format string + */ +int lkl_printf(const char *fmt, ...); + #ifdef __cplusplus } diff --git a/tools/lkl/lib/Build b/tools/lkl/lib/Build index 8b137891791f..658bfa865b9c 100644 --- a/tools/lkl/lib/Build +++ b/tools/lkl/lib/Build @@ -1 +1,8 @@ +CFLAGS_config.o += -I$(srctree)/tools/perf/pmu-events +liblkl-y += jmp_buf.o +liblkl-y += utils.o +liblkl-y += dbg.o +liblkl-y += dbg_handler.o +liblkl-y += ../../perf/pmu-events/jsmn.o +liblkl-y += config.o diff --git a/tools/lkl/lib/config.c b/tools/lkl/lib/config.c new file mode 100644 index 000000000000..37f8ac4d942a --- /dev/null +++ b/tools/lkl/lib/config.c @@ -0,0 +1,744 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#define _HAVE_STRING_ARCH_strtok_r +#include +#ifndef __MINGW32__ +#include +#endif +#include +#include + +#include "jsmn.h" + +static int jsoneq(const char *json, jsmntok_t *tok, const char *s) +{ + if (tok->type == JSMN_STRING && + (int) strlen(s) == tok->end - tok->start && + strncmp(json + tok->start, s, tok->end - tok->start) == 0) { + return 0; + } + return -1; +} + +static int cfgcpy(char **to, char *from) +{ + if (!from) + return 0; + if (*to) + free(*to); + *to = (char *)malloc((strlen(from) + 1) * sizeof(char)); + if (*to == NULL) { + lkl_printf("malloc failed\n"); + return -1; + } + strcpy(*to, from); + return 0; +} + +static int cfgncpy(char **to, char *from, int len) +{ + if (!from) + return 0; + if (*to) + free(*to); + *to = (char *)malloc((len + 1) * sizeof(char)); + if (*to == NULL) { + lkl_printf("malloc failed\n"); + return -1; + } + strncpy(*to, from, len + 1); + (*to)[len] = '\0'; + return 0; +} + +static int parse_ifarr(struct lkl_config *cfg, + jsmntok_t *toks, char *jstr, int startpos) +{ + int ifidx, pos, posend, ret; + char **cfgptr; + struct lkl_config_iface *iface, *prev = NULL; + + if (!cfg || !toks || !jstr) + return -1; + pos = startpos; + pos++; + if (toks[pos].type != JSMN_ARRAY) { + lkl_printf("unexpected json type, json array expected\n"); + return -1; + } + + cfg->ifnum = toks[pos].size; + pos++; + iface = cfg->ifaces; + + for (ifidx = 0; ifidx < cfg->ifnum; ifidx++) { + if (toks[pos].type != JSMN_OBJECT) { + lkl_printf("object json type expected\n"); + return -1; + } + + posend = pos + toks[pos].size; + pos++; + iface = malloc(sizeof(struct lkl_config_iface)); + memset(iface, 0, sizeof(struct lkl_config_iface)); + + if (prev) + prev->next = iface; + else + cfg->ifaces = iface; + prev = iface; + + for (; pos < posend; pos += 2) { + if (toks[pos].type != JSMN_STRING) { + lkl_printf("object json type expected\n"); + return -1; + } + if (jsoneq(jstr, &toks[pos], "type") == 0) { + cfgptr = &iface->iftype; + } else if (jsoneq(jstr, &toks[pos], "param") == 0) { + cfgptr = &iface->ifparams; + } else if (jsoneq(jstr, &toks[pos], "mtu") == 0) { + cfgptr = &iface->ifmtu_str; + } else if (jsoneq(jstr, &toks[pos], "ip") == 0) { + cfgptr = &iface->ifip; + } else if (jsoneq(jstr, &toks[pos], "ipv6") == 0) { + cfgptr = &iface->ifipv6; + } else if (jsoneq(jstr, &toks[pos], "ifgateway") == 0) { + cfgptr = &iface->ifgateway; + } else if (jsoneq(jstr, &toks[pos], + "ifgateway6") == 0) { + cfgptr = &iface->ifgateway6; + } else if (jsoneq(jstr, &toks[pos], "mac") == 0) { + cfgptr = &iface->ifmac_str; + } else if (jsoneq(jstr, &toks[pos], "masklen") == 0) { + cfgptr = &iface->ifnetmask_len; + } else if (jsoneq(jstr, &toks[pos], "masklen6") == 0) { + cfgptr = &iface->ifnetmask6_len; + } else if (jsoneq(jstr, &toks[pos], "neigh") == 0) { + cfgptr = &iface->ifneigh_entries; + } else if (jsoneq(jstr, &toks[pos], "qdisc") == 0) { + cfgptr = &iface->ifqdisc_entries; + } else if (jsoneq(jstr, &toks[pos], "offload") == 0) { + cfgptr = &iface->ifoffload_str; + } else { + lkl_printf("unexpected key: %.*s\n", + toks[pos].end-toks[pos].start, + jstr + toks[pos].start); + return -1; + } + ret = cfgncpy(cfgptr, jstr + toks[pos+1].start, + toks[pos+1].end-toks[pos+1].start); + if (ret < 0) + return ret; + } + } + return pos - startpos; +} + +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) + +int lkl_load_config_json(struct lkl_config *cfg, char *jstr) +{ + int pos, ret; + char **cfgptr; + jsmn_parser jp; + jsmntok_t toks[LKL_CONFIG_JSON_TOKEN_MAX]; + + if (!cfg || !jstr) + return -1; + jsmn_init(&jp); + ret = jsmn_parse(&jp, jstr, strlen(jstr), toks, ARRAY_SIZE(toks)); + if (ret != JSMN_SUCCESS) { + lkl_printf("failed to parse json\n"); + return -1; + } + if (toks[0].type != JSMN_OBJECT) { + lkl_printf("object json type expected\n"); + return -1; + } + for (pos = 1; pos < jp.toknext; pos++) { + if (toks[pos].type != JSMN_STRING) { + lkl_printf("string json type expected\n"); + return -1; + } + if (jsoneq(jstr, &toks[pos], "interfaces") == 0) { + ret = parse_ifarr(cfg, toks, jstr, pos); + if (ret < 0) + return ret; + pos += ret; + pos--; + continue; + } + if (jsoneq(jstr, &toks[pos], "gateway") == 0) { + cfgptr = &cfg->gateway; + } else if (jsoneq(jstr, &toks[pos], "gateway6") == 0) { + cfgptr = &cfg->gateway6; + } else if (jsoneq(jstr, &toks[pos], "debug") == 0) { + cfgptr = &cfg->debug; + } else if (jsoneq(jstr, &toks[pos], "mount") == 0) { + cfgptr = &cfg->mount; + } else if (jsoneq(jstr, &toks[pos], "singlecpu") == 0) { + cfgptr = &cfg->single_cpu; + } else if (jsoneq(jstr, &toks[pos], "sysctl") == 0) { + cfgptr = &cfg->sysctls; + } else if (jsoneq(jstr, &toks[pos], "boot_cmdline") == 0) { + cfgptr = &cfg->boot_cmdline; + } else if (jsoneq(jstr, &toks[pos], "dump") == 0) { + cfgptr = &cfg->dump; + } else if (jsoneq(jstr, &toks[pos], "delay_main") == 0) { + cfgptr = &cfg->delay_main; + } else { + lkl_printf("unexpected key in json %.*s\n", + toks[pos].end-toks[pos].start, + jstr + toks[pos].start); + return -1; + } + pos++; + ret = cfgncpy(cfgptr, jstr + toks[pos].start, + toks[pos].end-toks[pos].start); + if (ret < 0) + return ret; + } + return 0; +} + +void lkl_show_config(struct lkl_config *cfg) +{ + struct lkl_config_iface *iface; + int i = 0; + + if (!cfg) + return; + lkl_printf("gateway: %s\n", cfg->gateway); + lkl_printf("gateway6: %s\n", cfg->gateway6); + lkl_printf("debug: %s\n", cfg->debug); + lkl_printf("mount: %s\n", cfg->mount); + lkl_printf("singlecpu: %s\n", cfg->single_cpu); + lkl_printf("sysctl: %s\n", cfg->sysctls); + lkl_printf("cmdline: %s\n", cfg->boot_cmdline); + lkl_printf("dump: %s\n", cfg->dump); + lkl_printf("delay: %s\n", cfg->delay_main); + + for (iface = cfg->ifaces; iface; iface = iface->next, i++) { + lkl_printf("ifmac[%d] = %s\n", i, iface->ifmac_str); + lkl_printf("ifmtu[%d] = %s\n", i, iface->ifmtu_str); + lkl_printf("iftype[%d] = %s\n", i, iface->iftype); + lkl_printf("ifparam[%d] = %s\n", i, iface->ifparams); + lkl_printf("ifip[%d] = %s\n", i, iface->ifip); + lkl_printf("ifmasklen[%d] = %s\n", i, iface->ifnetmask_len); + lkl_printf("ifgateway[%d] = %s\n", i, iface->ifgateway); + lkl_printf("ifip6[%d] = %s\n", i, iface->ifipv6); + lkl_printf("ifmasklen6[%d] = %s\n", i, iface->ifnetmask6_len); + lkl_printf("ifgateway6[%d] = %s\n", i, iface->ifgateway6); + lkl_printf("ifoffload[%d] = %s\n", i, iface->ifoffload_str); + lkl_printf("ifneigh[%d] = %s\n", i, iface->ifneigh_entries); + lkl_printf("ifqdisk[%d] = %s\n", i, iface->ifqdisc_entries); + } +} + +int lkl_load_config_env(struct lkl_config *cfg) +{ + int ret; + char *enviftype = getenv("LKL_HIJACK_NET_IFTYPE"); + char *envifparams = getenv("LKL_HIJACK_NET_IFPARAMS"); + char *envmtu_str = getenv("LKL_HIJACK_NET_MTU"); + char *envip = getenv("LKL_HIJACK_NET_IP"); + char *envipv6 = getenv("LKL_HIJACK_NET_IPV6"); + char *envifgateway = getenv("LKL_HIJACK_NET_IFGATEWAY"); + char *envifgateway6 = getenv("LKL_HIJACK_NET_IFGATEWAY6"); + char *envmac_str = getenv("LKL_HIJACK_NET_MAC"); + char *envnetmask_len = getenv("LKL_HIJACK_NET_NETMASK_LEN"); + char *envnetmask6_len = getenv("LKL_HIJACK_NET_NETMASK6_LEN"); + char *envgateway = getenv("LKL_HIJACK_NET_GATEWAY"); + char *envgateway6 = getenv("LKL_HIJACK_NET_GATEWAY6"); + char *envdebug = getenv("LKL_HIJACK_DEBUG"); + char *envmount = getenv("LKL_HIJACK_MOUNT"); + char *envneigh_entries = getenv("LKL_HIJACK_NET_NEIGHBOR"); + char *envqdisc_entries = getenv("LKL_HIJACK_NET_QDISC"); + char *envsingle_cpu = getenv("LKL_HIJACK_SINGLE_CPU"); + char *envoffload_str = getenv("LKL_HIJACK_OFFLOAD"); + char *envsysctls = getenv("LKL_HIJACK_SYSCTL"); + char *envboot_cmdline = getenv("LKL_HIJACK_BOOT_CMDLINE") ? : ""; + char *envdump = getenv("LKL_HIJACK_DUMP"); + struct lkl_config_iface *iface; + + if (!cfg) + return -1; + if (enviftype) + cfg->ifnum = 1; + + iface = malloc(sizeof(struct lkl_config_iface)); + memset(iface, 0, sizeof(struct lkl_config_iface)); + + ret = cfgcpy(&iface->iftype, enviftype); + if (ret < 0) + return ret; + ret = cfgcpy(&iface->ifparams, envifparams); + if (ret < 0) + return ret; + ret = cfgcpy(&iface->ifmtu_str, envmtu_str); + if (ret < 0) + return ret; + ret = cfgcpy(&iface->ifip, envip); + if (ret < 0) + return ret; + ret = cfgcpy(&iface->ifipv6, envipv6); + if (ret < 0) + return ret; + ret = cfgcpy(&iface->ifgateway, envifgateway); + if (ret < 0) + return ret; + ret = cfgcpy(&iface->ifgateway6, envifgateway6); + if (ret < 0) + return ret; + ret = cfgcpy(&iface->ifmac_str, envmac_str); + if (ret < 0) + return ret; + ret = cfgcpy(&iface->ifnetmask_len, envnetmask_len); + if (ret < 0) + return ret; + ret = cfgcpy(&iface->ifnetmask6_len, envnetmask6_len); + if (ret < 0) + return ret; + ret = cfgcpy(&iface->ifoffload_str, envoffload_str); + if (ret < 0) + return ret; + ret = cfgcpy(&iface->ifneigh_entries, envneigh_entries); + if (ret < 0) + return ret; + ret = cfgcpy(&iface->ifqdisc_entries, envqdisc_entries); + if (ret < 0) + return ret; + ret = cfgcpy(&cfg->gateway, envgateway); + if (ret < 0) + return ret; + ret = cfgcpy(&cfg->gateway6, envgateway6); + if (ret < 0) + return ret; + ret = cfgcpy(&cfg->debug, envdebug); + if (ret < 0) + return ret; + ret = cfgcpy(&cfg->mount, envmount); + if (ret < 0) + return ret; + ret = cfgcpy(&cfg->single_cpu, envsingle_cpu); + if (ret < 0) + return ret; + ret = cfgcpy(&cfg->sysctls, envsysctls); + if (ret < 0) + return ret; + ret = cfgcpy(&cfg->boot_cmdline, envboot_cmdline); + if (ret < 0) + return ret; + ret = cfgcpy(&cfg->dump, envdump); + if (ret < 0) + return ret; + return 0; +} + +static int parse_mac_str(char *mac_str, __lkl__u8 mac[LKL_ETH_ALEN]) +{ + char delim[] = ":"; + char *saveptr = NULL, *token = NULL; + int i = 0; + + if (!mac_str) + return 0; + + for (token = strtok_r(mac_str, delim, &saveptr); + i < LKL_ETH_ALEN; i++) { + if (!token) { + /* The address is too short */ + return -1; + } + + mac[i] = (__lkl__u8) strtol(token, NULL, 16); + token = strtok_r(NULL, delim, &saveptr); + } + + if (strtok_r(NULL, delim, &saveptr)) { + /* The address is too long */ + return -1; + } + + return 1; +} + +/* Add permanent neighbor entries in the form of "ip|mac;ip|mac;..." */ +static void add_neighbor(int ifindex, char *entries) +{ + char *saveptr = NULL, *token = NULL; + char *ip = NULL, *mac_str = NULL; + int ret = 0; + __lkl__u8 mac[LKL_ETH_ALEN]; + char ip_addr[16]; + int af; + + for (token = strtok_r(entries, ";", &saveptr); token; + token = strtok_r(NULL, ";", &saveptr)) { + ip = strtok(token, "|"); + mac_str = strtok(NULL, "|"); + if (ip == NULL || mac_str == NULL || strtok(NULL, "|") != NULL) + return; + + af = LKL_AF_INET; + ret = inet_pton(LKL_AF_INET, ip, ip_addr); + if (ret == 0) { + ret = inet_pton(LKL_AF_INET6, ip, ip_addr); + af = LKL_AF_INET6; + } + if (ret != 1) { + lkl_printf("Bad ip address: %s\n", ip); + return; + } + + ret = parse_mac_str(mac_str, mac); + if (ret != 1) { + lkl_printf("Failed to parse mac: %s\n", mac_str); + return; + } + ret = lkl_add_neighbor(ifindex, af, ip_addr, mac); + if (ret) { + lkl_printf("Failed to add neighbor entry: %s\n", + lkl_strerror(ret)); + return; + } + } +} + +/* We don't have an easy way to make FILE*s out of our fds, so we + * can't use e.g. fgets + */ +static int dump_file(char *path) +{ + int ret = -1, bytes_read = 0; + char str[1024] = { 0 }; + int fd; + + fd = lkl_sys_open(path, LKL_O_RDONLY, 0); + + if (fd < 0) { + lkl_printf("%s lkl_sys_open %s: %s\n", + __func__, path, lkl_strerror(fd)); + return -1; + } + + /* Need to print this out in order to make sense of the output */ + lkl_printf("Reading from %s:\n==========\n", path); + while ((ret = lkl_sys_read(fd, str, sizeof(str) - 1)) > 0) + bytes_read += lkl_printf("%s", str); + lkl_printf("==========\n"); + + if (ret) { + lkl_printf("%s lkl_sys_read %s: %s\n", + __func__, path, lkl_strerror(ret)); + return -1; + } + + return 0; +} + +static void mount_cmds_exec(char *_cmds, int (*callback)(char *)) +{ + char *saveptr = NULL, *token; + int ret = 0; + char *cmds = strdup(_cmds); + + token = strtok_r(cmds, ",", &saveptr); + + while (token && ret >= 0) { + ret = callback(token); + token = strtok_r(NULL, ",", &saveptr); + } + + if (ret < 0) + lkl_printf("%s: failed parsing %s\n", __func__, _cmds); + + free(cmds); +} + +static int lkl_config_netdev_create(struct lkl_config *cfg, + struct lkl_config_iface *iface) +{ + int ret, offload = 0; + struct lkl_netdev_args nd_args; + __lkl__u8 mac[LKL_ETH_ALEN] = {0}; + struct lkl_netdev *nd = NULL; + + if (iface->ifoffload_str) + offload = strtol(iface->ifoffload_str, NULL, 0); + memset(&nd_args, 0, sizeof(struct lkl_netdev_args)); + + if (!nd && iface->iftype && iface->ifparams) { + } + + if (nd) { + if ((mac[0] != 0) || (mac[1] != 0) || + (mac[2] != 0) || (mac[3] != 0) || + (mac[4] != 0) || (mac[5] != 0)) { + nd_args.mac = mac; + } else { + ret = parse_mac_str(iface->ifmac_str, mac); + + if (ret < 0) { + lkl_printf("failed to parse mac\n"); + return -1; + } else if (ret > 0) { + nd_args.mac = mac; + } else { + nd_args.mac = NULL; + } + } + + nd_args.offload = offload; + iface->nd = nd; + } + return 0; +} + +static int lkl_config_netdev_configure(struct lkl_config *cfg, + struct lkl_config_iface *iface) +{ + int ret, nd_ifindex = -1; + struct lkl_netdev *nd = iface->nd; + + if (!nd) { + lkl_printf("no netdev available %s\n", iface ? iface->ifparams + : "(null)"); + return -1; + } + + if (nd->id >= 0) { + nd_ifindex = lkl_netdev_get_ifindex(nd->id); + if (nd_ifindex > 0) + lkl_if_up(nd_ifindex); + else + lkl_printf( + "failed to get ifindex for netdev id %d: %s\n", + nd->id, lkl_strerror(nd_ifindex)); + } + + if (nd_ifindex >= 0 && iface->ifmtu_str) { + int mtu = atoi(iface->ifmtu_str); + + ret = lkl_if_set_mtu(nd_ifindex, mtu); + if (ret < 0) + lkl_printf("failed to set MTU: %s\n", + lkl_strerror(ret)); + } + + if (nd_ifindex >= 0 && iface->ifip && iface->ifnetmask_len) { + unsigned int addr; + + if (inet_pton(LKL_AF_INET, iface->ifip, + (struct lkl_in_addr *)&addr) != 1) + lkl_printf("Invalid ipv4 address: %s\n", iface->ifip); + + int nmlen = atoi(iface->ifnetmask_len); + + if (addr != LKL_INADDR_NONE && nmlen > 0 && nmlen < 32) { + ret = lkl_if_set_ipv4(nd_ifindex, addr, nmlen); + if (ret < 0) + lkl_printf("failed to set IPv4 address: %s\n", + lkl_strerror(ret)); + } + if (iface->ifgateway) { + unsigned int gwaddr; + + if (inet_pton(LKL_AF_INET, iface->ifgateway, + (struct lkl_in_addr *)&gwaddr) != 1) + lkl_printf("Invalid ipv4 gateway: %s\n", + iface->ifgateway); + + if (gwaddr != LKL_INADDR_NONE) { + ret = lkl_if_set_ipv4_gateway(nd_ifindex, + addr, nmlen, gwaddr); + if (ret < 0) + lkl_printf( + "failed to set v4 if gw: %s\n", + lkl_strerror(ret)); + } + } + } + + if (nd_ifindex >= 0 && iface->ifipv6 && + iface->ifnetmask6_len) { + struct lkl_in6_addr addr; + unsigned int pflen = atoi(iface->ifnetmask6_len); + + if (inet_pton(LKL_AF_INET6, iface->ifipv6, + (struct lkl_in6_addr *)&addr) != 1) { + lkl_printf("Invalid ipv6 addr: %s\n", + iface->ifipv6); + } else { + ret = lkl_if_set_ipv6(nd_ifindex, &addr, pflen); + if (ret < 0) + lkl_printf("failed to set IPv6 address: %s\n", + lkl_strerror(ret)); + } + if (iface->ifgateway6) { + char gwaddr[16]; + + if (inet_pton(LKL_AF_INET6, iface->ifgateway6, + gwaddr) != 1) { + lkl_printf("Invalid ipv6 gateway: %s\n", + iface->ifgateway6); + } else { + ret = lkl_if_set_ipv6_gateway(nd_ifindex, + &addr, pflen, gwaddr); + if (ret < 0) + lkl_printf( + "failed to set v6 if gw: %s\n", + lkl_strerror(ret)); + } + } + } + + if (nd_ifindex >= 0 && iface->ifneigh_entries) + add_neighbor(nd_ifindex, iface->ifneigh_entries); + + if (nd_ifindex >= 0 && iface->ifqdisc_entries) + lkl_qdisc_parse_add(nd_ifindex, iface->ifqdisc_entries); + + return 0; +} + +static void free_cfgparam(char *cfgparam) +{ + if (cfgparam) + free(cfgparam); +} + +static int lkl_clean_config(struct lkl_config *cfg) +{ + struct lkl_config_iface *iface; + + if (!cfg) + return -1; + + for (iface = cfg->ifaces; iface; iface = iface->next) { + free_cfgparam(iface->iftype); + free_cfgparam(iface->ifparams); + free_cfgparam(iface->ifmtu_str); + free_cfgparam(iface->ifip); + free_cfgparam(iface->ifipv6); + free_cfgparam(iface->ifgateway); + free_cfgparam(iface->ifgateway6); + free_cfgparam(iface->ifmac_str); + free_cfgparam(iface->ifnetmask_len); + free_cfgparam(iface->ifnetmask6_len); + free_cfgparam(iface->ifoffload_str); + free_cfgparam(iface->ifneigh_entries); + free_cfgparam(iface->ifqdisc_entries); + } + free_cfgparam(cfg->gateway); + free_cfgparam(cfg->gateway6); + free_cfgparam(cfg->debug); + free_cfgparam(cfg->mount); + free_cfgparam(cfg->single_cpu); + free_cfgparam(cfg->sysctls); + free_cfgparam(cfg->boot_cmdline); + free_cfgparam(cfg->dump); + free_cfgparam(cfg->delay_main); + return 0; +} + + +int lkl_load_config_pre(struct lkl_config *cfg) +{ + int lkl_debug, ret; + struct lkl_config_iface *iface; + + if (!cfg) + return 0; + + if (cfg->debug) + lkl_debug = strtol(cfg->debug, NULL, 0); + + if (!cfg->debug || (lkl_debug == 0)) + lkl_host_ops.print = NULL; + + for (iface = cfg->ifaces; iface; iface = iface->next) { + ret = lkl_config_netdev_create(cfg, iface); + if (ret < 0) + return -1; + } + + return 0; +} + +int lkl_load_config_post(struct lkl_config *cfg) +{ + int ret; + struct lkl_config_iface *iface; + + if (!cfg) + return 0; + + if (cfg->mount) + mount_cmds_exec(cfg->mount, lkl_mount_fs); + + for (iface = cfg->ifaces; iface; iface = iface->next) { + ret = lkl_config_netdev_configure(cfg, iface); + if (ret < 0) + break; + } + + if (cfg->gateway) { + unsigned int gwaddr; + + if (inet_pton(LKL_AF_INET, cfg->gateway, + (struct lkl_in_addr *)&gwaddr) != 1) + lkl_printf("Invalid ipv4 gateway: %s\n", cfg->gateway); + + if (gwaddr != LKL_INADDR_NONE) { + ret = lkl_set_ipv4_gateway(gwaddr); + if (ret < 0) + lkl_printf("failed to set IPv4 gateway: %s\n", + lkl_strerror(ret)); + } + } + + if (cfg->gateway6) { + char gw[16]; + + if (inet_pton(LKL_AF_INET6, cfg->gateway6, gw) != 1) { + lkl_printf("Invalid ipv6 gateway: %s\n", cfg->gateway6); + } else { + ret = lkl_set_ipv6_gateway(gw); + if (ret < 0) + lkl_printf("failed to set IPv6 gateway: %s\n", + lkl_strerror(ret)); + } + } + + if (cfg->sysctls) + lkl_sysctl_parse_write(cfg->sysctls); + + /* put a delay before calling main() */ + if (cfg->delay_main) { + unsigned long delay = strtoul(cfg->delay_main, NULL, 10); + + if (delay == ~0UL) + lkl_printf("got invalid delay_main value (%s)\n", + cfg->delay_main); + else { + lkl_printf("sleeping %lu usec\n", delay); + usleep(delay); + } + } + + return 0; +} + +int lkl_unload_config(struct lkl_config *cfg) +{ + if (cfg) { + if (cfg->dump) + mount_cmds_exec(cfg->dump, dump_file); + + lkl_clean_config(cfg); + } + + return 0; +} diff --git a/tools/lkl/lib/dbg.c b/tools/lkl/lib/dbg.c new file mode 100644 index 000000000000..b613353bce5c --- /dev/null +++ b/tools/lkl/lib/dbg.c @@ -0,0 +1,300 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include + +static const char *PROMOTE = "$"; +#define str(x) #x +#define xstr(s) str(s) +#define MAX_BUF 100 +static char cmd[MAX_BUF]; +static char argv[10][MAX_BUF]; +static int argc; +static char cur_dir[MAX_BUF] = "/"; + +static char *normalize_path(const char *src, size_t src_len) +{ + char *res; + unsigned int res_len; + const char *ptr = src; + const char *end = &src[src_len]; + const char *next; + + res = malloc((src_len > 0 ? src_len : 1) + 1); + res_len = 0; + + for (ptr = src; ptr < end; ptr = next+1) { + size_t len; + + next = memchr(ptr, '/', end-ptr); + if (next == NULL) + next = end; + + len = next-ptr; + switch (len) { + case 2: + if (ptr[0] == '.' && ptr[1] == '.') { + const char *slash = strrchr(res, '/'); + + if (slash != NULL) + res_len = slash - res; + continue; + } + break; + case 1: + if (ptr[0] == '.') + continue; + break; + case 0: + continue; + } + res[res_len++] = '/'; + memcpy(&res[res_len], ptr, len); + res_len += len; + } + if (res_len == 0) + res[res_len++] = '/'; + res[res_len] = '\0'; + return res; +} + +static void build_path(char *path) +{ + char *npath; + + strcpy(path, cur_dir); + if (argc >= 1) { + if (argv[0][0] == '/') + strncpy(path, argv[0], LKL_PATH_MAX); + else { + strncat(path, "/", LKL_PATH_MAX - strlen(path) - 1); + strncat(path, argv[0], LKL_PATH_MAX - strlen(path) - 1); + } + } + npath = normalize_path(path, strlen(path)); + strcpy(path, npath); + free(npath); +} + +static void help(void) +{ + const char *msg = + "cat FILE\n" + "\tShow content of FILE\n" + "cd [DIR]\n" + "\tChange directory to DIR\n" + "exit\n" + "\tExit the debug session\n" + "help\n" + "\tShow this message\n" + "ls [DIR]\n" + "\tList files in DIR\n" + "mount FSTYPE\n" + "\tMount FSTYPE as /FSTYPE\n" + "overwrite FILE\n" + "\tOverwrite content of FILE from stdin\n" + "pwd\n" + "\tShow current directory\n" + ; + printf("%s", msg); +} + +static void ls(void) +{ + char path[LKL_PATH_MAX]; + struct lkl_dir *dir; + struct lkl_linux_dirent64 *de; + int err; + + build_path(path); + dir = lkl_opendir(path, &err); + if (dir) { + do { + de = lkl_readdir(dir); + if (de) { + printf("%s\n", de->d_name); + } else { + err = lkl_errdir(dir); + if (err != 0) { + fprintf(stderr, "%s\n", + lkl_strerror(err)); + } + break; + } + } while (1); + lkl_closedir(dir); + } else { + fprintf(stderr, "%s: %s\n", path, lkl_strerror(err)); + } +} + +static void cd(void) +{ + char path[LKL_PATH_MAX]; + struct lkl_dir *dir; + int err; + + build_path(path); + dir = lkl_opendir(path, &err); + if (dir) { + strcpy(cur_dir, path); + lkl_closedir(dir); + } else { + fprintf(stderr, "%s: %s\n", path, lkl_strerror(err)); + } +} + +static void mount(void) +{ + char *fstype; + int ret = 0; + + if (argc != 1) { + fprintf(stderr, "%s\n", "One argument is needed."); + return; + } + + fstype = argv[0]; + ret = lkl_mount_fs(fstype); + if (ret == 1) + fprintf(stderr, "%s is already mounted.\n", fstype); +} + +static void cat(void) +{ + char path[LKL_PATH_MAX]; + int ret; + char buf[1024]; + int fd; + + if (argc != 1) { + fprintf(stderr, "%s\n", "One argument is needed."); + return; + } + + build_path(path); + fd = lkl_sys_open(path, LKL_O_RDONLY, 0); + + if (fd < 0) { + fprintf(stderr, "lkl_sys_open %s: %s\n", + path, lkl_strerror(fd)); + return; + } + + while ((ret = lkl_sys_read(fd, buf, sizeof(buf) - 1)) > 0) { + buf[ret] = '\0'; + printf("%s", buf); + } + + if (ret) { + fprintf(stderr, "lkl_sys_read %s: %s\n", + path, lkl_strerror(ret)); + } + lkl_sys_close(fd); +} + +static void overwrite(void) +{ + char path[LKL_PATH_MAX]; + int ret; + int fd; + char buf[1024]; + + build_path(path); + fd = lkl_sys_open(path, LKL_O_WRONLY | LKL_O_CREAT, 0); + if (fd < 0) { + fprintf(stderr, "lkl_sys_open %s: %s\n", + path, lkl_strerror(fd)); + return; + } + printf("Input the content and stop by hitting Ctrl-D:\n"); + while (fgets(buf, 1023, stdin)) { + ret = lkl_sys_write(fd, buf, strlen(buf)); + if (ret < 0) { + fprintf(stderr, "lkl_sys_write %s: %s\n", + path, lkl_strerror(fd)); + } + } + lkl_sys_close(fd); +} + +static void pwd(void) +{ + printf("%s\n", cur_dir); +} + +static int parse_cmd(char *input) +{ + char *token; + + token = strtok(input, " "); + if (token) + strcpy(cmd, token); + else + return -1; + + argc = 0; + token = strtok(NULL, " "); + while (token) { + if (argc >= 10) { + fprintf(stderr, "To many args > 10\n"); + return -1; + } + strcpy(argv[argc++], token); + token = strtok(NULL, " "); + } + return 0; +} + +static void run_cmd(void) +{ + if (strcmp(cmd, "cat") == 0) + cat(); + else if (strcmp(cmd, "cd") == 0) + cd(); + else if (strcmp(cmd, "help") == 0) + help(); + else if (strcmp(cmd, "ls") == 0) + ls(); + else if (strcmp(cmd, "mount") == 0) + mount(); + else if (strcmp(cmd, "overwrite") == 0) + overwrite(); + else if (strcmp(cmd, "pwd") == 0) + pwd(); + else + fprintf(stderr, "Unknown command: %s\n", cmd); +} + +void dbg_entrance(void) +{ + char input[MAX_BUF + 1]; + int ret; + int c; + + printf("Type help to see a list of commands\n"); + do { + printf("%s ", PROMOTE); + ret = scanf("%" xstr(MAX_BUF) "[^\n]s", input); + while ((c = getchar()) != '\n' && c != EOF) + ; + if (ret == 0) + continue; + if (ret != 1 && errno != EINTR) { + perror("scanf"); + continue; + } + if (strlen(input) == MAX_BUF) { + fprintf(stderr, "Too long input > %d\n", MAX_BUF - 1); + continue; + } + if (parse_cmd(input)) + continue; + if (strcmp(cmd, "exit") == 0) + break; + run_cmd(); + } while (1); +} diff --git a/tools/lkl/lib/dbg_handler.c b/tools/lkl/lib/dbg_handler.c new file mode 100644 index 000000000000..01d165a5fc1e --- /dev/null +++ b/tools/lkl/lib/dbg_handler.c @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include + +extern void dbg_entrance(void); +static int dbg_running; + +static void dbg_thread(void *arg) +{ + lkl_host_ops.thread_detach(); + printf("======Enter Debug======\n"); + dbg_entrance(); + printf("======Exit Debug======\n"); + dbg_running = 0; +} + +void dbg_handler(int signum) +{ + /* We don't care about the possible race on dbg_running. */ + if (dbg_running) { + fprintf(stderr, "A debug lib is running\n"); + return; + } + dbg_running = 1; + lkl_host_ops.thread_create(&dbg_thread, NULL); +} + +#ifndef __MINGW32__ +#include +void lkl_register_dbg_handler(void) +{ + struct sigaction sa; + + sigemptyset(&sa.sa_mask); + sa.sa_handler = dbg_handler; + if (sigaction(SIGTSTP, &sa, NULL) == -1) + perror("sigaction"); +} +#else +void lkl_register_dbg_handler(void) +{ + fprintf(stderr, "%s is not implemented.\n", __func__); +} +#endif diff --git a/tools/lkl/lib/endian.h b/tools/lkl/lib/endian.h new file mode 100644 index 000000000000..aaccfa0edb65 --- /dev/null +++ b/tools/lkl/lib/endian.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LKL_LIB_ENDIAN_H +#define _LKL_LIB_ENDIAN_H + +#if defined(__FreeBSD__) +#include +#elif defined(__ANDROID__) +#include +#elif defined(__MINGW32__) +#include +#define le32toh(x) (x) +#define le16toh(x) (x) +#define htole32(x) (x) +#define htole16(x) (x) +#define le64toh(x) (x) +#define htobe32(x) htonl(x) +#define htobe16(x) htons(x) +#define be32toh(x) ntohl(x) +#define be16toh(x) ntohs(x) +#else +#include +#endif + +#ifndef htonl +#define htonl(x) htobe32(x) +#define htons(x) htobe16(x) +#define ntohl(x) be32toh(x) +#define ntohs(x) be16toh(x) +#endif + +#endif /* _LKL_LIB_ENDIAN_H */ diff --git a/tools/lkl/lib/jmp_buf.c b/tools/lkl/lib/jmp_buf.c new file mode 100644 index 000000000000..f6bdd7e4bd83 --- /dev/null +++ b/tools/lkl/lib/jmp_buf.c @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include + +void jmp_buf_set(struct lkl_jmp_buf *jmpb, void (*f)(void)) +{ + if (!setjmp(*((jmp_buf *)jmpb->buf))) + f(); +} + +void jmp_buf_longjmp(struct lkl_jmp_buf *jmpb, int val) +{ + longjmp(*((jmp_buf *)jmpb->buf), val); +} diff --git a/tools/lkl/lib/jmp_buf.h b/tools/lkl/lib/jmp_buf.h new file mode 100644 index 000000000000..8782cbaaf51f --- /dev/null +++ b/tools/lkl/lib/jmp_buf.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LKL_LIB_JMP_BUF_H +#define _LKL_LIB_JMP_BUF_H + +void jmp_buf_set(struct lkl_jmp_buf *jmpb, void (*f)(void)); +void jmp_buf_longjmp(struct lkl_jmp_buf *jmpb, int val); + +#endif diff --git a/tools/lkl/lib/utils.c b/tools/lkl/lib/utils.c new file mode 100644 index 000000000000..7de92bbe5475 --- /dev/null +++ b/tools/lkl/lib/utils.c @@ -0,0 +1,266 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include + +static const char * const lkl_err_strings[] = { + "Success", + "Operation not permitted", + "No such file or directory", + "No such process", + "Interrupted system call", + "I/O error", + "No such device or address", + "Argument list too long", + "Exec format error", + "Bad file number", + "No child processes", + "Try again", + "Out of memory", + "Permission denied", + "Bad address", + "Block device required", + "Device or resource busy", + "File exists", + "Cross-device link", + "No such device", + "Not a directory", + "Is a directory", + "Invalid argument", + "File table overflow", + "Too many open files", + "Not a typewriter", + "Text file busy", + "File too large", + "No space left on device", + "Illegal seek", + "Read-only file system", + "Too many links", + "Broken pipe", + "Math argument out of domain of func", + "Math result not representable", + "Resource deadlock would occur", + "File name too long", + "No record locks available", + "Invalid system call number", + "Directory not empty", + "Too many symbolic links encountered", + "Bad error code", /* EWOULDBLOCK is EAGAIN */ + "No message of desired type", + "Identifier removed", + "Channel number out of range", + "Level 2 not synchronized", + "Level 3 halted", + "Level 3 reset", + "Link number out of range", + "Protocol driver not attached", + "No CSI structure available", + "Level 2 halted", + "Invalid exchange", + "Invalid request descriptor", + "Exchange full", + "No anode", + "Invalid request code", + "Invalid slot", + "Bad error code", /* EDEADLOCK is EDEADLK */ + "Bad font file format", + "Device not a stream", + "No data available", + "Timer expired", + "Out of streams resources", + "Machine is not on the network", + "Package not installed", + "Object is remote", + "Link has been severed", + "Advertise error", + "Srmount error", + "Communication error on send", + "Protocol error", + "Multihop attempted", + "RFS specific error", + "Not a data message", + "Value too large for defined data type", + "Name not unique on network", + "File descriptor in bad state", + "Remote address changed", + "Can not access a needed shared library", + "Accessing a corrupted shared library", + ".lib section in a.out corrupted", + "Attempting to link in too many shared libraries", + "Cannot exec a shared library directly", + "Illegal byte sequence", + "Interrupted system call should be restarted", + "Streams pipe error", + "Too many users", + "Socket operation on non-socket", + "Destination address required", + "Message too long", + "Protocol wrong type for socket", + "Protocol not available", + "Protocol not supported", + "Socket type not supported", + "Operation not supported on transport endpoint", + "Protocol family not supported", + "Address family not supported by protocol", + "Address already in use", + "Cannot assign requested address", + "Network is down", + "Network is unreachable", + "Network dropped connection because of reset", + "Software caused connection abort", + "Connection reset by peer", + "No buffer space available", + "Transport endpoint is already connected", + "Transport endpoint is not connected", + "Cannot send after transport endpoint shutdown", + "Too many references: cannot splice", + "Connection timed out", + "Connection refused", + "Host is down", + "No route to host", + "Operation already in progress", + "Operation now in progress", + "Stale file handle", + "Structure needs cleaning", + "Not a XENIX named type file", + "No XENIX semaphores available", + "Is a named type file", + "Remote I/O error", + "Quota exceeded", + "No medium found", + "Wrong medium type", + "Operation Canceled", + "Required key not available", + "Key has expired", + "Key has been revoked", + "Key was rejected by service", + "Owner died", + "State not recoverable", + "Operation not possible due to RF-kill", + "Memory page has hardware error", +}; + +const char *lkl_strerror(int err) +{ + if (err < 0) + err = -err; + + if ((size_t)err >= sizeof(lkl_err_strings) / sizeof(const char *)) + return "Bad error code"; + + return lkl_err_strings[err]; +} + +void lkl_perror(char *msg, int err) +{ + const char *err_msg = lkl_strerror(err); + /* We need to use 'real' printf because lkl_host_ops.print can + * be turned off when debugging is off. + */ + lkl_printf("%s: %s\n", msg, err_msg); +} + +static int lkl_vprintf(const char *fmt, va_list args) +{ + int n; + char *buffer; + va_list copy; + + if (!lkl_host_ops.print) + return 0; + + va_copy(copy, args); + n = vsnprintf(NULL, 0, fmt, copy); + va_end(copy); + + buffer = lkl_host_ops.mem_alloc(n + 1); + if (!buffer) + return -1; + + vsnprintf(buffer, n + 1, fmt, args); + + lkl_host_ops.print(buffer, n); + lkl_host_ops.mem_free(buffer); + + return n; +} + +int lkl_printf(const char *fmt, ...) +{ + int n; + va_list args; + + va_start(args, fmt); + n = lkl_vprintf(fmt, args); + va_end(args); + + return n; +} + +void lkl_bug(const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + lkl_vprintf(fmt, args); + va_end(args); + + lkl_host_ops.panic(); +} +#ifndef __arch_um__ +int lkl_sysctl(const char *path, const char *value) +{ + int ret; + int fd; + char *delim, *p; + char full_path[256]; + + lkl_mount_fs("proc"); + + snprintf(full_path, sizeof(full_path), "/proc/sys/%s", path); + p = full_path; + while ((delim = strstr(p, "."))) { + *delim = '/'; + p = delim + 1; + } + + fd = lkl_sys_open(full_path, LKL_O_WRONLY | LKL_O_CREAT, 0); + if (fd < 0) { + lkl_printf("lkl_sys_open %s: %s\n", + full_path, lkl_strerror(fd)); + return -1; + } + ret = lkl_sys_write(fd, value, strlen(value)); + if (ret < 0) { + lkl_printf("lkl_sys_write %s: %s\n", + full_path, lkl_strerror(fd)); + } + + lkl_sys_close(fd); + + return 0; +} + +/* Configure sysctl parameters as the form of "key=value;key=value;..." */ +void lkl_sysctl_parse_write(const char *sysctls) +{ + char *saveptr = NULL, *token = NULL; + char *key = NULL, *value = NULL; + char strings[256]; + int ret = 0; + + strcpy(strings, sysctls); + for (token = strtok_r(strings, ";", &saveptr); token; + token = strtok_r(NULL, ";", &saveptr)) { + key = strtok(token, "="); + value = strtok(NULL, "="); + ret = lkl_sysctl(key, value); + if (ret) { + lkl_printf("Failed to configure sysctl entries: %s\n", + lkl_strerror(ret)); + return; + } + } +} +#endif From patchwork Mon Mar 30 14:45:46 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hajime Tazaki X-Patchwork-Id: 1263990 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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=s9oV0yqF; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=DYzV0EUl; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (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 48rb1Z36G3z9sP7 for ; Tue, 31 Mar 2020 01:48:34 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.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=B42R7SMD0fwrlRY+gYR5x4VLb3Vs7W6fTFU42Z5OAC0=; b=s9oV0yqFad7k/O lhJxbHFEpOCd4MCZse/7xMYcPRLWxH4PbMwdyK4jmZwIdlF+u60aHlTKu9xiicjAg+DdT45f1z9yQ xpd2q4sININTS/Z2L8roAZBsJXa34ivmTbwyyLlJWjeWj4SpcNwJemSnrGLD3DC1rxQeUE6Lh7AoD M7K4TXJYpPXw1uumCGCq7y25HnUra3RDl0JXGmapMG0i+3hyUJgrKmfCwSvVDPvrUZuaL79znJCRT P4SVUOBfFmRAjAknqqvyf+zr6OBLIFipJefym75hocVTO2/nCsh+mOglLtwmY+gHPUlJ/TH7v9gF6 zxB6I0KqbhGRfeHozX1Q==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIviF-0004yK-AW; Mon, 30 Mar 2020 14:48:27 +0000 Received: from mail-pg1-x532.google.com ([2607:f8b0:4864:20::532]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIviA-0004w1-Hg for linux-um@lists.infradead.org; Mon, 30 Mar 2020 14:48:25 +0000 Received: by mail-pg1-x532.google.com with SMTP id b1so8748239pgm.8 for ; Mon, 30 Mar 2020 07:48:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=XNACQsOzFYlxcZi20fAeRmb2vLMaf+w0ke2mZUmN0Nw=; b=DYzV0EUlq0SHIYI3+P0vipHKLeNhS4wj+WrPqldtqGTjrU7VkkKTj/JKD/Mk+4eLGZ jmPmyKxkOb8KaV9EDRNdKa3xlkYttonQK96fGZyVMsLSLIJ4xZrAGN/9EngosJh8F4Y0 bhG7hyEaowK3ohZW91fiZvL5DeAmdldBXkAwR9ZymyFThsQZlZPfUBvV+2zzu2SomCSB o9whzXAAEycSsmm2CyRp9dmIYUuN509LkqQHT2vgWYRgH8yrvLwzQLnCqaNuxEusev7p mYBWIv+BnWZKiEG4PT0Np2mTsV95ynYuR6+tanA/xT8jW/Bc3BV0okACOA0A4TsxRXm7 ni5w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=XNACQsOzFYlxcZi20fAeRmb2vLMaf+w0ke2mZUmN0Nw=; b=UlBnR5vs9uc+uDAcbbMeljWCx1S/2ul5y6cdBUo9n5N2swXVLT0BgHXOJ9/uVBOo+X 4n5vG2myIXkPTIiwMu+IvJ+B/zQWY02lkKwnvDw6//+HslUkdH4MUUHcotrqbUSdgEQt HCn3T60MFPbU+5Pgylwg8olWC60WDCsqemJ/0ceqCvL43NopMql7ILT+qihyD7Q7WieT V9s2B5+bnBnf7hGq1IIo/AEBJhe+pyGnAlVfmrbZ0zOnWEBm7XBeMeeyXszwHnwCPRpv NTdjFH+2y5gSYv1cdESQMAwJZeML8DXUmMzWEKh2Nwx+Ulw/Plr+A8SqTlYO7MdXvrHn TNiQ== X-Gm-Message-State: ANhLgQ3Uo8r5e2Txdv/itv50YLVN5BBkxJr8MiNXz1Y/uKexYoOotYK2 Mfcb3djBf0Br70CXF8Ifu00= X-Google-Smtp-Source: ADFU+vu4Q169vTMpGK41O70ni1RaxM2+ppoiF4176xomnUSF3bnDfNZwnxebTkncLLTgoRtn9gpO3A== X-Received: by 2002:a63:e607:: with SMTP id g7mr12905205pgh.303.1585579699282; Mon, 30 Mar 2020 07:48:19 -0700 (PDT) Received: from earth-mac.local (219x123x138x129.ap219.ftth.ucom.ne.jp. [219.123.138.129]) by smtp.gmail.com with ESMTPSA id c21sm4056215pgn.84.2020.03.30.07.48.18 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 30 Mar 2020 07:48:18 -0700 (PDT) Received: by earth-mac.local (Postfix, from userid 501) id 5CA08202804DDB; Mon, 30 Mar 2020 23:48:16 +0900 (JST) From: Hajime Tazaki To: linux-um@lists.infradead.org Subject: [RFC v4 14/25] lkl tools: host lib: filesystem helpers Date: Mon, 30 Mar 2020 23:45:46 +0900 Message-Id: <403e9ca733a581621945eca015884572d91d7410.1585579244.git.thehajime@gmail.com> X-Mailer: git-send-email 2.20.1 (Apple Git-117) In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200330_074822_664796_E84877ED X-CRM114-Status: GOOD ( 26.29 ) X-Spam-Score: -0.2 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:532 listed in] [list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [thehajime[at]gmail.com] -0.0 SPF_PASS SPF: sender matches SPF record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 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: linux-arch@vger.kernel.org, Conrad Meyer , Octavian Purdila , Akira Moroo , Yuan Liu , linux-kernel-library@freelists.org, Michael Zimmermann , Hajime Tazaki Sender: "linux-um" Errors-To: linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org Add LKL applications APIs to mount and unmount a filesystem from a disk added via lkl_disk_add(). Also add open/close/read directory wrappers on top of lkl_sys_getdents64. Cc: Conrad Meyer Cc: Michael Zimmermann Cc: Yuan Liu Signed-off-by: Hajime Tazaki Signed-off-by: Octavian Purdila --- tools/lkl/include/lkl.h | 165 ++++++++++++++ tools/lkl/lib/Build | 1 + tools/lkl/lib/fs.c | 471 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 637 insertions(+) create mode 100644 tools/lkl/lib/fs.c diff --git a/tools/lkl/include/lkl.h b/tools/lkl/include/lkl.h index 4b95d0ef8e5b..cdae92300320 100644 --- a/tools/lkl/include/lkl.h +++ b/tools/lkl/include/lkl.h @@ -350,6 +350,171 @@ const char *lkl_strerror(int err); */ void lkl_perror(char *msg, int err); +/** + * struct lkl_dev_blk_ops - block device host operations, defined in lkl_host.h. + */ +struct lkl_dev_blk_ops; + +/** + * lkl_disk - host disk handle + * + * @dev - a pointer to private information for this disk backend + * @fd - a POSIX file descriptor that can be used by preadv/pwritev + * @handle - an NT file handle that can be used by ReadFile/WriteFile + */ +struct lkl_disk { + void *dev; + union { + int fd; + void *handle; + }; + struct lkl_dev_blk_ops *ops; +}; + +/** + * lkl_disk_add - add a new disk + * + * @disk - the host disk handle + * @returns a disk id (0 is valid) or a strictly negative value in case of error + */ +int lkl_disk_add(struct lkl_disk *disk); + +/** + * lkl_disk_remove - remove a disk + * + * This function makes a cleanup of the @disk's private information + * that was initialized by lkl_disk_add before. + * + * @disk - the host disk handle + */ +int lkl_disk_remove(struct lkl_disk disk); + +/** + * lkl_encode_dev_from_sysfs_blkdev - extract device id from sysfs + * + * This function returns the device id for the given sysfs dev node. + * The content of the node has to be in the form 'MAJOR:MINOR'. + * Also, this function expects an absolute path which means that sysfs + * already has to be mounted at the given path + * + * @sysfs_path - absolute path to the sysfs dev node + * @pdevid - pointer to memory where dev id will be returned + * @returns - 0 on success, a negative value on error + */ +int lkl_encode_dev_from_sysfs(const char *sysfs_path, uint32_t *pdevid); + +/** + * lkl_mount_dev - mount a disk + * + * This functions creates a device file for the given disk, creates a mount + * point and mounts the device over the mount point. + * + * @disk_id - the disk id identifying the disk to be mounted + * @part - disk partition or zero for full disk + * @fs_type - filesystem type + * @flags - mount flags + * @opts - additional filesystem specific mount options + * @mnt_str - a string that will be filled by this function with the path where + * the filesystem has been mounted + * @mnt_str_len - size of mnt_str + * @returns - 0 on success, a negative value on error + */ +long lkl_mount_dev(unsigned int disk_id, unsigned int part, const char *fs_type, + int flags, const char *opts, + char *mnt_str, unsigned int mnt_str_len); + +/** + * lkl_umount_dev - umount a disk + * + * This functions umounts the given disks and removes the device file and the + * mount point. + * + * @disk_id - the disk id identifying the disk to be mounted + * @part - disk partition or zero for full disk + * @flags - umount flags + * @timeout_ms - timeout to wait for the kernel to flush closed files so that + * umount can succeed + * @returns - 0 on success, a negative value on error + */ +long lkl_umount_dev(unsigned int disk_id, unsigned int part, int flags, + long timeout_ms); + +/** + * lkl_umount_timeout - umount filesystem with timeout + * + * @path - the path to unmount + * @flags - umount flags + * @timeout_ms - timeout to wait for the kernel to flush closed files so that + * umount can succeed + * @returns - 0 on success, a negative value on error + */ +long lkl_umount_timeout(char *path, int flags, long timeout_ms); + +/** + * lkl_opendir - open a directory + * + * @path - directory path + * @err - pointer to store the error in case of failure + * @returns - a handle to be used when calling lkl_readdir + */ +struct lkl_dir *lkl_opendir(const char *path, int *err); + +/** + * lkl_fdopendir - open a directory + * + * @fd - file descriptor + * @err - pointer to store the error in case of failure + * @returns - a handle to be used when calling lkl_readdir + */ +struct lkl_dir *lkl_fdopendir(int fd, int *err); + +/** + * lkl_rewinddir - reset directory stream + * + * @dir - the directory handler as returned by lkl_opendir + */ +void lkl_rewinddir(struct lkl_dir *dir); + +/** + * lkl_closedir - close the directory + * + * @dir - the directory handler as returned by lkl_opendir + */ +int lkl_closedir(struct lkl_dir *dir); + +/** + * lkl_readdir - get the next available entry of the directory + * + * @dir - the directory handler as returned by lkl_opendir + * @returns - a lkl_dirent64 entry or NULL if the end of the directory stream is + * reached or if an error occurred; check lkl_errdir() to distinguish between + * errors or end of the directory stream + */ +struct lkl_linux_dirent64 *lkl_readdir(struct lkl_dir *dir); + +/** + * lkl_errdir - checks if an error occurred during the last lkl_readdir call + * + * @dir - the directory handler as returned by lkl_opendir + * @returns - 0 if no error occurred, or a negative value otherwise + */ +int lkl_errdir(struct lkl_dir *dir); + +/** + * lkl_dirfd - gets the file descriptor associated with the directory handle + * + * @dir - the directory handle as returned by lkl_opendir + * @returns - a positive value,which is the LKL file descriptor associated with + * the directory handle, or a negative value otherwise + */ +int lkl_dirfd(struct lkl_dir *dir); + +/** + * lkl_mount_fs - mount a file system type like proc, sys + * @fstype - file system type. e.g. proc, sys + * @returns - 0 on success. 1 if it's already mounted. negative on failure. + */ +int lkl_mount_fs(char *fstype); #ifdef __cplusplus } diff --git a/tools/lkl/lib/Build b/tools/lkl/lib/Build index 658bfa865b9c..4a444337b0e7 100644 --- a/tools/lkl/lib/Build +++ b/tools/lkl/lib/Build @@ -1,5 +1,6 @@ CFLAGS_config.o += -I$(srctree)/tools/perf/pmu-events +liblkl-y += fs.o liblkl-y += jmp_buf.o liblkl-y += utils.o liblkl-y += dbg.o diff --git a/tools/lkl/lib/fs.c b/tools/lkl/lib/fs.c new file mode 100644 index 000000000000..d51d928c14b6 --- /dev/null +++ b/tools/lkl/lib/fs.c @@ -0,0 +1,471 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include + +#define MAX_FSTYPE_LEN 50 + +static struct lkl_disk *lkl_disks[16]; + +int lkl_disk_add(struct lkl_disk *disk) +{ + int ret = -1; + + switch (disk->backend) { + case BLK_BACKEND_UM: + ret = lkl_disk_um_add(disk, disk->dev); + break; + default: + break; + } + + lkl_disks[ret] = disk; + + return ret; +} + +int lkl_disk_remove(struct lkl_disk disk) +{ + switch (disk.backend) { + case BLK_BACKEND_UM: + default: + break; + } + + return 0; +} + +int lkl_mount_fs(char *fstype) +{ + char dir[MAX_FSTYPE_LEN+2] = "/"; + int flags = 0, ret = 0; + + strncat(dir, fstype, MAX_FSTYPE_LEN); + + /* Create with regular umask */ + ret = lkl_sys_mkdir(dir, 0xff); + if (ret && ret != -LKL_EEXIST) { + lkl_perror("mount_fs mkdir", ret); + return ret; + } + + /* We have no use for nonzero flags right now */ + ret = lkl_sys_mount("none", dir, fstype, flags, NULL); + if (ret && ret != -LKL_EBUSY) { + lkl_sys_rmdir(dir); + return ret; + } + + if (ret == -LKL_EBUSY) + return 1; + return 0; +} + +static uint32_t new_encode_dev(unsigned int major, unsigned int minor) +{ + return (minor & 0xff) | (major << 8) | ((minor & ~0xff) << 12); +} + +static int startswith(const char *str, const char *pre) +{ + return strncmp(pre, str, strlen(pre)) == 0; +} + +static int get_node_with_prefix(const char *path, const char *prefix, + char *result, unsigned int result_len) +{ + struct lkl_dir *dir = NULL; + struct lkl_linux_dirent64 *dirent; + int ret; + + dir = lkl_opendir(path, &ret); + if (!dir) + return ret; + + ret = -LKL_ENOENT; + + while ((dirent = lkl_readdir(dir))) { + if (startswith(dirent->d_name, prefix)) { + if (strlen(dirent->d_name) + 1 > result_len) { + ret = -LKL_ENOMEM; + break; + } + memcpy(result, dirent->d_name, strlen(dirent->d_name)); + result[strlen(dirent->d_name)] = '\0'; + ret = 0; + break; + } + } + + lkl_closedir(dir); + + return ret; +} + +int lkl_encode_dev_from_sysfs(const char *sysfs_path, uint32_t *pdevid) +{ + int ret; + long fd; + int major, minor; + char buf[16] = { 0, }; + char *bufptr; + + fd = lkl_sys_open(sysfs_path, LKL_O_RDONLY, 0); + if (fd < 0) + return fd; + + ret = lkl_sys_read(fd, buf, sizeof(buf)); + if (ret < 0) + goto out_close; + + if (ret == sizeof(buf)) { + ret = -LKL_ENOBUFS; + goto out_close; + } + + bufptr = strchr(buf, ':'); + if (bufptr == NULL) { + ret = -LKL_EINVAL; + goto out_close; + } + bufptr[0] = '\0'; + bufptr++; + + major = atoi(buf); + minor = atoi(bufptr); + + *pdevid = new_encode_dev(major, minor); + ret = 0; + +out_close: + lkl_sys_close(fd); + + return ret; +} + +#define SYSFS_DEV_UMBLK_CMDLINE_PATH \ + "/sysfs/devices/platform/uml-blkdev.%d" + +struct abuf { + char *mem, *ptr; + unsigned int len; +}; + +static int snprintf_append(struct abuf *buf, const char *fmt, ...) +{ + int ret; + va_list args; + + if (!buf->ptr) + buf->ptr = buf->mem; + + va_start(args, fmt); + ret = vsnprintf(buf->ptr, buf->len - (buf->ptr - buf->mem), fmt, args); + va_end(args); + + if (ret < 0 || (ret >= (int)(buf->len - (buf->ptr - buf->mem)))) + return -LKL_ENOMEM; + + buf->ptr += ret; + + return 0; +} + +static int __lkl_get_blkdev(int disk_id, unsigned int part, uint32_t *pdevid, + const char *sysfs_path_fmt, const char *drv_prefix, + const char *disk_prefix) +{ + char sysfs_path[LKL_PATH_MAX]; + char drv_name[LKL_PATH_MAX]; + char disk_name[LKL_PATH_MAX]; + struct abuf sysfs_path_buf = { + .mem = sysfs_path, + .len = sizeof(sysfs_path), + }; + int ret; + + if (disk_id < 0) + return -LKL_EINVAL; + + ret = lkl_mount_fs("sysfs"); + if (ret < 0) + return ret; + + ret = snprintf_append(&sysfs_path_buf, sysfs_path_fmt, disk_id); + if (ret) + return ret; + + ret = get_node_with_prefix(sysfs_path, drv_prefix, drv_name, + sizeof(drv_name)); + if (ret) + return ret; + + ret = snprintf_append(&sysfs_path_buf, "/%s/block", drv_name); + if (ret) + return ret; + + ret = get_node_with_prefix(sysfs_path, disk_prefix, disk_name, + sizeof(disk_name)); + if (ret) + return ret; + + if (!part) + ret = snprintf_append(&sysfs_path_buf, "/%s/dev", disk_name); + else + ret = snprintf_append(&sysfs_path_buf, "/%s/%s%d/dev", + disk_name, disk_name, part); + if (ret) + return ret; + + return lkl_encode_dev_from_sysfs(sysfs_path, pdevid); +} + +int lkl_get_blkdev(int disk_id, unsigned int part, uint32_t *pdevid) +{ + char *fmt; + struct lkl_disk *disk = lkl_disks[disk_id]; + + switch (disk->backend) { + case BLK_BACKEND_UM: + fmt = SYSFS_DEV_UMBLK_CMDLINE_PATH; + return __lkl_get_blkdev(disk_id, part, pdevid, fmt, + "", "ubd"); + default: + break; + } + + return -1; +} + +long lkl_mount_dev(unsigned int disk_id, unsigned int part, + const char *fs_type, int flags, + const char *data, char *mnt_str, unsigned int mnt_str_len) +{ + char dev_str[] = { "/dev/xxxxxxxx" }; + unsigned int dev; + int err; + char _data[4096]; /* FIXME: PAGE_SIZE is not exported by LKL */ + + if (mnt_str_len < sizeof(dev_str)) + return -LKL_ENOMEM; + + err = lkl_get_blkdev(disk_id, part, &dev); + if (err < 0) + return err; + + snprintf(dev_str, sizeof(dev_str), "/dev/%08x", dev); + snprintf(mnt_str, mnt_str_len, "/mnt/%08x", dev); + + err = lkl_sys_access("/dev", LKL_S_IRWXO); + if (err < 0) { + if (err == -LKL_ENOENT) + err = lkl_sys_mkdir("/dev", 0700); + if (err < 0) + return err; + } + + err = lkl_sys_mknod(dev_str, LKL_S_IFBLK | 0600, dev); + if (err < 0) + return err; + + err = lkl_sys_access("/mnt", LKL_S_IRWXO); + if (err < 0) { + if (err == -LKL_ENOENT) + err = lkl_sys_mkdir("/mnt", 0700); + if (err < 0) + return err; + } + + err = lkl_sys_mkdir(mnt_str, 0700); + if (err < 0) { + lkl_sys_unlink(dev_str); + return err; + } + + /* kernel always copies a full page */ + if (data) { + strncpy(_data, data, sizeof(_data)); + _data[sizeof(_data) - 1] = 0; + } else { + _data[0] = 0; + } + + err = lkl_sys_mount(dev_str, mnt_str, (char *)fs_type, flags, _data); + if (err < 0) { + lkl_sys_unlink(dev_str); + lkl_sys_rmdir(mnt_str); + return err; + } + + return 0; +} + +long lkl_umount_timeout(char *path, int flags, long timeout_ms) +{ + long incr = 10000000; /* 10 ms */ + struct lkl_timespec ts = { + .tv_sec = 0, + .tv_nsec = incr, + }; + long err; + + do { + err = lkl_sys_umount(path, flags); + if (err == -LKL_EBUSY) { + lkl_sys_nanosleep((struct __lkl__kernel_timespec *)&ts, + NULL); + timeout_ms -= incr / 1000000; + } + } while (err == -LKL_EBUSY && timeout_ms > 0); + + return err; +} + +long lkl_umount_dev(unsigned int disk_id, unsigned int part, int flags, + long timeout_ms) +{ + char dev_str[] = { "/dev/xxxxxxxx" }; + char mnt_str[] = { "/mnt/xxxxxxxx" }; + unsigned int dev; + int err; + + err = lkl_get_blkdev(disk_id, part, &dev); + if (err < 0) + return err; + + snprintf(dev_str, sizeof(dev_str), "/dev/%08x", dev); + snprintf(mnt_str, sizeof(mnt_str), "/mnt/%08x", dev); + + err = lkl_umount_timeout(mnt_str, flags, timeout_ms); + if (err) + return err; + + err = lkl_sys_unlink(dev_str); + if (err) + return err; + + return lkl_sys_rmdir(mnt_str); +} + +struct lkl_dir { + int fd; + char buf[1024]; + char *pos; + int len; +}; + +static struct lkl_dir *lkl_dir_alloc(int *err) +{ + struct lkl_dir *dir = lkl_host_ops.mem_alloc(sizeof(struct lkl_dir)); + + if (!dir) { + *err = -LKL_ENOMEM; + return NULL; + } + + dir->len = 0; + dir->pos = NULL; + + return dir; +} + +struct lkl_dir *lkl_opendir(const char *path, int *err) +{ + struct lkl_dir *dir = lkl_dir_alloc(err); + + if (!dir) { + *err = -LKL_ENOMEM; + return NULL; + } + + dir->fd = lkl_sys_open(path, LKL_O_RDONLY | LKL_O_DIRECTORY, 0); + if (dir->fd < 0) { + *err = dir->fd; + lkl_host_ops.mem_free(dir); + return NULL; + } + + *err = 0; + + return dir; +} + +struct lkl_dir *lkl_fdopendir(int fd, int *err) +{ + struct lkl_dir *dir = lkl_dir_alloc(err); + + if (!dir) + return NULL; + + dir->fd = fd; + + return dir; +} + +void lkl_rewinddir(struct lkl_dir *dir) +{ + lkl_sys_lseek(dir->fd, 0, LKL_SEEK_SET); + dir->len = 0; + dir->pos = NULL; +} + +int lkl_closedir(struct lkl_dir *dir) +{ + int ret; + + ret = lkl_sys_close(dir->fd); + lkl_host_ops.mem_free(dir); + + return ret; +} + +struct lkl_linux_dirent64 *lkl_readdir(struct lkl_dir *dir) +{ + struct lkl_linux_dirent64 *de; + + if (dir->len < 0) + return NULL; + + if (!dir->pos || dir->pos - dir->buf >= dir->len) + goto read_buf; + +return_de: + de = (struct lkl_linux_dirent64 *)dir->pos; + dir->pos += de->d_reclen; + + return de; + +read_buf: + dir->pos = NULL; + de = (struct lkl_linux_dirent64 *)dir->buf; + dir->len = lkl_sys_getdents64(dir->fd, de, sizeof(dir->buf)); + if (dir->len <= 0) + return NULL; + + dir->pos = dir->buf; + goto return_de; +} + +int lkl_errdir(struct lkl_dir *dir) +{ + if (dir->len >= 0) + return 0; + + return dir->len; +} + +int lkl_dirfd(struct lkl_dir *dir) +{ + return dir->fd; +} + +int lkl_set_fd_limit(unsigned int fd_limit) +{ + struct lkl_rlimit rlim = { + .rlim_cur = fd_limit, + .rlim_max = fd_limit, + }; + return lkl_sys_setrlimit(LKL_RLIMIT_NOFILE, &rlim); +} From patchwork Mon Mar 30 14:45:47 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hajime Tazaki X-Patchwork-Id: 1263991 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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=uMQ9Hp1U; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=GrDwNAH0; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (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 48rb1k3lHnz9sP7 for ; Tue, 31 Mar 2020 01:48:42 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.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=4lKoLcieHHN3KSnz6e5v8m3ZMhDLRblqendoU0NFP4Q=; b=uMQ9Hp1Uwa0AUv Bvvhp6fCcgv+y2v0yI1rNDmVSttyyEZG+P8FK/1jAOYbgkQZ/kIPk5VB3ILhtq8D/BxA/QINQdTC9 VYYF3MiSwuo6xBK2wr7Rzjf9+EDNTEtsRfkM3NRKVc1ccY7AMjnbOOBTxGb3forHj2VQ0AzysTPDZ 10kCBFCbcsLdofmemTdUMVSpRZjWVVuHkKylDqNLN13+SAVqZVLA3vyzm+YRe4sXAvflsfuzwBF6b bIxHdLCQrMEZdrIqsO/R8smOpqB7OGWkPrBtdt0sIaI9hX25PpOIl4TZtaG32eUDyY33EsDpADI3a ng9SQ8eMbzHY15EI31nA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIviJ-0004z4-Ok; Mon, 30 Mar 2020 14:48:31 +0000 Received: from mail-pj1-x1035.google.com ([2607:f8b0:4864:20::1035]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIviB-0004xK-T3 for linux-um@lists.infradead.org; Mon, 30 Mar 2020 14:48:30 +0000 Received: by mail-pj1-x1035.google.com with SMTP id z3so6909473pjr.4 for ; Mon, 30 Mar 2020 07:48:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=8RkGkzvpEn2gE6ufEUfTmXKju5Dp210suWhMm1w9oYg=; b=GrDwNAH0WCdAruDR2vlb2GixUp32KNVjA1xdPTaaHzg5AV3HFQbP4VYSLu39FUFAVv DF0OahuEKkewaaH8KCwsyV8s6CbTQqVUbVyLZUcglIPixX0uxWNvLEuO+U0BE+i8hICH ziwHQLlAXt8HqM28dxKO1afmb0PenOaKLbwJ5maEYOAQZdZCl4C1nvgVwEmTGWgpBDd0 MF1a2714AAkTot534vMU6agA/NMqGmIny1re9TEVaCyzHXkLx/D4Xk6BIPgEmiHKzfgE 6LIealkrfViOg8qQdPejBEQSGl9GLhdLoY4XwhoCzOK2mIWSQJMbDbPpsybm4S6pFUkz wpfg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=8RkGkzvpEn2gE6ufEUfTmXKju5Dp210suWhMm1w9oYg=; b=C9QdtVdz/vgdp5KOPxdigWRTsAtewTlpywcVFe9JrDt8arRobt71+m7wGuNnvf6wgG kTX/hiDScHNu850aqFuPAgxKLNQLZ0j/JmLz1AujYgpuaT/9hNWsfTY7MWfnPC+QTHcN LPzlhaZcXmU9eBcr54H6JOndK/UQcgzs52abjiLFGml/ILbwvSPQQsS7GAieix76hwOY 5eK749J+BGSRsDASZg0PT/u021tJfWVphF5+r+OGkhPC7+S5QJwdY2+jVIzF3C5qwyOv 812O2r5Pbcn6jx9HFyFK0H3CwF997kYlca86h7s3dNGVnViclqE6RDI47cTuV1Fvu3yx eXFQ== X-Gm-Message-State: ANhLgQ3+hjKQRpsZzOVT1qLpQIwkHXjsUO/EV2CGl3zYsW6uqtoqgGf9 3kG9lcdTEqfIm07xiWQ8oEs= X-Google-Smtp-Source: ADFU+vvKD6fi6KeNUEa083IDPVpmuJ3GOegOTD/XqHjp4Mu6L8kt8KoR8dnHBg9SiYntKJ3XmsZx8w== X-Received: by 2002:a17:902:8c94:: with SMTP id t20mr12792932plo.170.1585579702376; Mon, 30 Mar 2020 07:48:22 -0700 (PDT) Received: from earth-mac.local (219x123x138x129.ap219.ftth.ucom.ne.jp. [219.123.138.129]) by smtp.gmail.com with ESMTPSA id o11sm9703435pgh.78.2020.03.30.07.48.21 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 30 Mar 2020 07:48:21 -0700 (PDT) Received: by earth-mac.local (Postfix, from userid 501) id BCBF0202804DF2; Mon, 30 Mar 2020 23:48:19 +0900 (JST) From: Hajime Tazaki To: linux-um@lists.infradead.org Subject: [RFC v4 15/25] lkl tools: host lib: networking helpers Date: Mon, 30 Mar 2020 23:45:47 +0900 Message-Id: <94b12a3395df2184c2faa9a95393166fc7fca46a.1585579244.git.thehajime@gmail.com> X-Mailer: git-send-email 2.20.1 (Apple Git-117) In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200330_074824_027363_A4C70257 X-CRM114-Status: GOOD ( 21.71 ) X-Spam-Score: -0.2 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:1035 listed in] [list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [thehajime[at]gmail.com] -0.0 SPF_PASS SPF: sender matches SPF record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 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: Octavian Purdila , linux-kernel-library@freelists.org, linux-arch@vger.kernel.org, Hajime Tazaki , Akira Moroo Sender: "linux-um" Errors-To: linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org This commit adds LKL application APIs to control network related resources of kernel via LKL syscall, ioctl, and via netlink messages. Signed-off-by: Hajime Tazaki --- tools/lkl/include/lkl.h | 241 ++++++++++ tools/lkl/include/lkl_host.h | 85 ++++ tools/lkl/lib/Build | 1 + tools/lkl/lib/net.c | 826 +++++++++++++++++++++++++++++++++++ 4 files changed, 1153 insertions(+) create mode 100644 tools/lkl/lib/net.c diff --git a/tools/lkl/include/lkl.h b/tools/lkl/include/lkl.h index cdae92300320..1f4291ad9455 100644 --- a/tools/lkl/include/lkl.h +++ b/tools/lkl/include/lkl.h @@ -516,6 +516,247 @@ int lkl_dirfd(struct lkl_dir *dir); */ int lkl_mount_fs(char *fstype); +/** + * lkl_if_up - activate network interface + * + * @ifindex - the ifindex of the interface + * @returns - return 0 if no error: otherwise negative value returns + */ +int lkl_if_up(int ifindex); + +/** + * lkl_if_down - deactivate network interface + * + * @ifindex - the ifindex of the interface + * @returns - return 0 if no error: otherwise negative value returns + */ +int lkl_if_down(int ifindex); + +/** + * lkl_if_set_mtu - set MTU on interface + * + * @ifindex - the ifindex of the interface + * @mtu - the requested MTU size + * @returns - return 0 if no error: otherwise negative value returns + */ +int lkl_if_set_mtu(int ifindex, int mtu); + +/** + * lkl_if_set_ipv4 - set IPv4 address on interface + * + * @ifindex - the ifindex of the interface + * @addr - 4-byte IP address (i.e., struct in_addr) + * @netmask_len - prefix length of the @addr + * @returns - return 0 if no error: otherwise negative value returns + */ +int lkl_if_set_ipv4(int ifindex, unsigned int addr, unsigned int netmask_len); + +/** + * lkl_set_ipv4_gateway - add an IPv4 default route + * + * @addr - 4-byte IP address of the gateway (i.e., struct in_addr) + * @returns - return 0 if no error: otherwise negative value returns + */ +int lkl_set_ipv4_gateway(unsigned int addr); + +/** + * lkl_if_set_ipv4_gateway - add an IPv4 default route in rule table + * + * @ifindex - the ifindex of the interface, used for tableid calculation + * @addr - 4-byte IP address of the interface + * @netmask_len - prefix length of the @addr + * @gw_addr - 4-byte IP address of the gateway + * @returns - return 0 if no error: otherwise negative value returns + */ +int lkl_if_set_ipv4_gateway(int ifindex, unsigned int addr, + unsigned int netmask_len, unsigned int gw_addr); + +/** + * lkl_if_set_ipv6 - set IPv6 address on interface + * must be called after interface is up. + * + * @ifindex - the ifindex of the interface + * @addr - 16-byte IPv6 address (i.e., struct in6_addr) + * @netprefix_len - prefix length of the @addr + * @returns - return 0 if no error: otherwise negative value returns + */ +int lkl_if_set_ipv6(int ifindex, void *addr, unsigned int netprefix_len); + +/** + * lkl_set_ipv6_gateway - add an IPv6 default route + * + * @addr - 16-byte IPv6 address of the gateway (i.e., struct in6_addr) + * @returns - return 0 if no error: otherwise negative value returns + */ +int lkl_set_ipv6_gateway(void *addr); + +/** + * lkl_if_set_ipv6_gateway - add an IPv6 default route in rule table + * + * @ifindex - the ifindex of the interface, used for tableid calculation + * @addr - 16-byte IP address of the interface + * @netmask_len - prefix length of the @addr + * @gw_addr - 16-byte IP address of the gateway (i.e., struct in_addr) + * @returns - return 0 if no error: otherwise negative value returns + */ +int lkl_if_set_ipv6_gateway(int ifindex, void *addr, + unsigned int netmask_len, void *gw_addr); + +/** + * lkl_ifname_to_ifindex - obtain ifindex of an interface by name + * + * @name - string of an interface + * @returns - return an integer of ifindex if no error + */ +int lkl_ifname_to_ifindex(const char *name); + +/** + * lkl_netdev_get_ifindex - retrieve the interface index for a given network + * device id + * + * @id - the network device id + * @returns the interface index or a stricly negative value in case of error + */ +int lkl_netdev_get_ifindex(int id); + +/** + * lkl_add_neighbor - add a permanent arp entry + * @ifindex - the ifindex of the interface + * @af - address family of the ip address. Must be LKL_AF_INET or LKL_AF_INET6 + * @ip - ip address of the entry in network byte order + * @mac - mac address of the entry + */ +int lkl_add_neighbor(int ifindex, int af, void *addr, void *mac); + +/** + * lkl_if_add_ip - add an ip address + * @ifindex - the ifindex of the interface + * @af - address family of the ip address. Must be LKL_AF_INET or LKL_AF_INET6 + * @addr - ip address of the entry in network byte order + * @netprefix_len - prefix length of the @addr + */ +int lkl_if_add_ip(int ifindex, int af, void *addr, unsigned int netprefix_len); + +/** + * lkl_if_del_ip - add an ip address + * @ifindex - the ifindex of the interface + * @af - address family of the ip address. Must be LKL_AF_INET or LKL_AF_INET6 + * @addr - ip address of the entry in network byte order + * @netprefix_len - prefix length of the @addr + */ +int lkl_if_del_ip(int ifindex, int af, void *addr, unsigned int netprefix_len); + +/** + * lkl_add_gateway - add a gateway + * @af - address family of the ip address. Must be LKL_AF_INET or LKL_AF_INET6 + * @gwaddr - 4-byte IP address of the gateway (i.e., struct in_addr) + */ +int lkl_add_gateway(int af, void *gwaddr); + +/** + * XXX Should I use OIF selector? + * temporary table idx = ifindex * 2 + 0 <- ipv4 + * temporary table idx = ifindex * 2 + 1 <- ipv6 + */ +/** + * lkl_if_add_rule_from_addr - create an ip rule table with "from" selector + * @ifindex - the ifindex of the interface, used for table id calculation + * @af - address family of the ip address. Must be LKL_AF_INET or LKL_AF_INET6 + * @saddr - network byte order ip address, "from" selector address of this rule + */ +int lkl_if_add_rule_from_saddr(int ifindex, int af, void *saddr); + +/** + * lkl_if_add_gateway - add gateway to rule table + * @ifindex - the ifindex of the interface, used for table id calculation + * @af - address family of the ip address. Must be LKL_AF_INET or LKL_AF_INET6 + * @gwaddr - 4-byte IP address of the gateway (i.e., struct in_addr) + */ +int lkl_if_add_gateway(int ifindex, int af, void *gwaddr); + +/** + * lkl_if_add_linklocal - add linklocal route to rule table + * @ifindex - the ifindex of the interface, used for table id calculation + * @af - address family of the ip address. Must be LKL_AF_INET or LKL_AF_INET6 + * @addr - ip address of the entry in network byte order + * @netprefix_len - prefix length of the @addr + */ +int lkl_if_add_linklocal(int ifindex, int af, void *addr, int netprefix_len); + +/** + * lkl_if_wait_ipv6_dad - wait for DAD to be done for a ipv6 address + * must be called after interface is up + * + * @ifindex - the ifindex of the interface + * @addr - ip address of the entry in network byte order + */ +int lkl_if_wait_ipv6_dad(int ifindex, void *addr); + +/** + * lkl_set_fd_limit - set the maximum number of file descriptors allowed + * @fd_limit - fd max limit + */ +int lkl_set_fd_limit(unsigned int fd_limit); + +/** + * lkl_qdisc_add - set qdisc rule onto an interface + * + * @ifindex - the ifindex of the interface + * @root - the name of root class (e.g., "root"); + * @type - the type of qdisc (e.g., "fq") + */ +int lkl_qdisc_add(int ifindex, const char *root, const char *type); + +/** + * lkl_qdisc_parse_add - Add a qdisc entry for an interface with strings + * + * @ifindex - the ifindex of the interface + * @entries - strings of qdisc configurations in the form of + * "root|type;root|type;..." + */ +void lkl_qdisc_parse_add(int ifindex, const char *entries); + +/** + * lkl_netdev - host network device handle, defined in lkl_host.h. + */ +struct lkl_netdev; + +/** + * lkl_netdev_args - arguments to lkl_netdev_add + * @mac - optional MAC address for the device + * @offload - offload bits for the device + */ +struct lkl_netdev_args { + void *mac; + unsigned int offload; +}; + +/* + * lkl_register_dbg_handler- register a signal handler that loads a debug lib. + * + * The signal handler is triggered by Ctrl-Z. It creates a new pthread which + * call dbg_entrance(). + * + * If you run the program from shell script, make sure you ignore SIGTSTP by + * "trap '' TSTP" in the shell script. + */ +void lkl_register_dbg_handler(void); + +/** + * lkl_sysctl - write a sysctl value + * + * @path - the path to an sysctl entry (e.g., "net.ipv4.tcp_wmem"); + * @value - the value of the sysctl (e.g., "4096 87380 2147483647") + */ +int lkl_sysctl(const char *path, const char *value); + +/** + * lkl_sysctl_parse_write - Configure sysctl parameters with strings + * + * @sysctls - Configure sysctl parameters as the form of "key=value;..." + */ +void lkl_sysctl_parse_write(const char *sysctls); + #ifdef __cplusplus } #endif diff --git a/tools/lkl/include/lkl_host.h b/tools/lkl/include/lkl_host.h index 85e80eb4ad0d..4e6d6e031498 100644 --- a/tools/lkl/include/lkl_host.h +++ b/tools/lkl/include/lkl_host.h @@ -18,6 +18,91 @@ extern struct lkl_host_operations lkl_host_ops; */ int lkl_printf(const char *fmt, ...); +#ifdef LKL_HOST_CONFIG_POSIX +#include +#else +struct iovec { + void *iov_base; + size_t iov_len; +}; +#endif + +struct lkl_netdev { + struct lkl_dev_net_ops *ops; + int id; + uint8_t has_vnet_hdr: 1; +}; + +/** + * struct lkl_dev_net_ops - network device host operations + */ +struct lkl_dev_net_ops { + /** + * @tx: writes a L2 packet into the net device + * + * The data buffer can only hold 0 or 1 complete packets. + * + * @nd - pointer to the network device; + * @iov - pointer to the buffer vector; + * @cnt - # of vectors in iov. + * + * @returns number of bytes transmitted + */ + int (*tx)(struct lkl_netdev *nd, struct iovec *iov, int cnt); + + /** + * @rx: reads a packet from the net device. + * + * It must only read one complete packet if present. + * + * If the buffer is too small for the packet, the implementation may + * decide to drop it or trim it. + * + * @nd - pointer to the network device + * @iov - pointer to the buffer vector to store the packet + * @cnt - # of vectors in iov. + * + * @returns number of bytes read for success or < 0 if error + */ + int (*rx)(struct lkl_netdev *nd, struct iovec *iov, int cnt); + +#define LKL_DEV_NET_POLL_RX 1 +#define LKL_DEV_NET_POLL_TX 2 +#define LKL_DEV_NET_POLL_HUP 4 + + /** + * @poll: polls a net device + * + * Supports the following events: LKL_DEV_NET_POLL_RX + * (readable), LKL_DEV_NET_POLL_TX (writable) or + * LKL_DEV_NET_POLL_HUP (the close operations has been issued + * and we need to clean up). Blocks until one event is + * available. + * + * @nd - pointer to the network device + * + * @returns - LKL_DEV_NET_POLL_RX, LKL_DEV_NET_POLL_TX, + * LKL_DEV_NET_POLL_HUP or a negative value for errors + */ + int (*poll)(struct lkl_netdev *nd); + + /** + * @poll_hup: make poll wakeup and return LKL_DEV_NET_POLL_HUP + * + * @nd - pointer to the network device + */ + void (*poll_hup)(struct lkl_netdev *nd); + + /** + * @free: frees a network device + * + * Implementation must release its resources and free the network device + * structure. + * + * @nd - pointer to the network device + */ + void (*free)(struct lkl_netdev *nd); +}; #ifdef __cplusplus } diff --git a/tools/lkl/lib/Build b/tools/lkl/lib/Build index 4a444337b0e7..dba530424e4a 100644 --- a/tools/lkl/lib/Build +++ b/tools/lkl/lib/Build @@ -1,6 +1,7 @@ CFLAGS_config.o += -I$(srctree)/tools/perf/pmu-events liblkl-y += fs.o +liblkl-y += net.o liblkl-y += jmp_buf.o liblkl-y += utils.o liblkl-y += dbg.o diff --git a/tools/lkl/lib/net.c b/tools/lkl/lib/net.c new file mode 100644 index 000000000000..cf6894c35e46 --- /dev/null +++ b/tools/lkl/lib/net.c @@ -0,0 +1,826 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include "endian.h" +#include + +#ifdef __MINGW32__ +#include + +int lkl_inet_pton(int af, const char *src, void *dst) +{ + struct addrinfo hint, *res = NULL; + int err; + + memset(&hint, 0, sizeof(struct addrinfo)); + + hint.ai_family = af; + hint.ai_flags = AI_NUMERICHOST; + + err = getaddrinfo(src, NULL, &hint, &res); + if (err) + return 0; + + switch (af) { + case AF_INET: + *(struct in_addr *)dst = + ((struct sockaddr_in *)&res->ai_addr)->sin_addr; + break; + case AF_INET6: + *(struct in6_addr *)dst = + ((struct sockaddr_in6 *)&res->ai_addr)->sin6_addr; + break; + default: + freeaddrinfo(res); + return 0; + } + + freeaddrinfo(res); + return 1; +} +#endif + +static inline void set_sockaddr(struct lkl_sockaddr_in *sin, unsigned int addr, + unsigned short port) +{ + sin->sin_family = LKL_AF_INET; + sin->sin_addr.lkl_s_addr = addr; + sin->sin_port = port; +} + +static inline int ifindex_to_name(int sock, struct lkl_ifreq *ifr, int ifindex) +{ + ifr->lkl_ifr_ifindex = ifindex; + return lkl_sys_ioctl(sock, LKL_SIOCGIFNAME, (long)ifr); +} + +int lkl_ifname_to_ifindex(const char *name) +{ + struct lkl_ifreq ifr; + int fd, ret; + + fd = lkl_sys_socket(LKL_AF_INET, LKL_SOCK_DGRAM, 0); + if (fd < 0) + return fd; + + if (strlen(name) >= LKL_IFNAMSIZ) + return -LKL_ENAMETOOLONG; + + strcpy(ifr.lkl_ifr_name, name); + + ret = lkl_sys_ioctl(fd, LKL_SIOCGIFINDEX, (long)&ifr); + if (ret < 0) + return ret; + + return ifr.lkl_ifr_ifindex; +} + +int lkl_if_up(int ifindex) +{ + struct lkl_ifreq ifr; + int err, sock = lkl_sys_socket(LKL_AF_INET, LKL_SOCK_DGRAM, 0); + + if (sock < 0) + return sock; + err = ifindex_to_name(sock, &ifr, ifindex); + if (err < 0) + return err; + + err = lkl_sys_ioctl(sock, LKL_SIOCGIFFLAGS, (long)&ifr); + if (!err) { + ifr.lkl_ifr_flags |= LKL_IFF_UP; + err = lkl_sys_ioctl(sock, LKL_SIOCSIFFLAGS, (long)&ifr); + } + + lkl_sys_close(sock); + + return err; +} + +int lkl_if_down(int ifindex) +{ + struct lkl_ifreq ifr; + int err, sock; + + sock = lkl_sys_socket(LKL_AF_INET, LKL_SOCK_DGRAM, 0); + if (sock < 0) + return sock; + + err = ifindex_to_name(sock, &ifr, ifindex); + if (err < 0) + return err; + + err = lkl_sys_ioctl(sock, LKL_SIOCGIFFLAGS, (long)&ifr); + if (!err) { + ifr.lkl_ifr_flags &= ~LKL_IFF_UP; + err = lkl_sys_ioctl(sock, LKL_SIOCSIFFLAGS, (long)&ifr); + } + + lkl_sys_close(sock); + + return err; +} + +int lkl_if_set_mtu(int ifindex, int mtu) +{ + struct lkl_ifreq ifr; + int err, sock; + + sock = lkl_sys_socket(LKL_AF_INET, LKL_SOCK_DGRAM, 0); + if (sock < 0) + return sock; + + err = ifindex_to_name(sock, &ifr, ifindex); + if (err < 0) + return err; + + ifr.lkl_ifr_mtu = mtu; + + err = lkl_sys_ioctl(sock, LKL_SIOCSIFMTU, (long)&ifr); + + lkl_sys_close(sock); + + return err; +} + +int lkl_if_set_ipv4(int ifindex, unsigned int addr, unsigned int netmask_len) +{ + return lkl_if_add_ip(ifindex, LKL_AF_INET, &addr, netmask_len); +} + +int lkl_if_set_ipv4_gateway(int ifindex, unsigned int src_addr, + unsigned int src_masklen, unsigned int via_addr) +{ + int err; + + err = lkl_if_add_rule_from_saddr(ifindex, LKL_AF_INET, &src_addr); + if (err) + return err; + err = lkl_if_add_linklocal(ifindex, LKL_AF_INET, + &src_addr, src_masklen); + if (err) + return err; + return lkl_if_add_gateway(ifindex, LKL_AF_INET, &via_addr); +} + +int lkl_set_ipv4_gateway(unsigned int addr) +{ + return lkl_add_gateway(LKL_AF_INET, &addr); +} + +int lkl_netdev_get_ifindex(int id) +{ + struct lkl_ifreq ifr; + int sock, ret; + + sock = lkl_sys_socket(LKL_AF_INET, LKL_SOCK_DGRAM, 0); + if (sock < 0) + return sock; + + snprintf(ifr.lkl_ifr_name, sizeof(ifr.lkl_ifr_name), "eth%d", id); + ret = lkl_sys_ioctl(sock, LKL_SIOCGIFINDEX, (long)&ifr); + lkl_sys_close(sock); + + return ret < 0 ? ret : ifr.lkl_ifr_ifindex; +} + +static int netlink_sock(unsigned int groups) +{ + struct lkl_sockaddr_nl la; + int fd, err; + + fd = lkl_sys_socket(LKL_AF_NETLINK, LKL_SOCK_DGRAM, LKL_NETLINK_ROUTE); + if (fd < 0) + return fd; + + memset(&la, 0, sizeof(la)); + la.nl_family = LKL_AF_NETLINK; + la.nl_groups = groups; + err = lkl_sys_bind(fd, (struct lkl_sockaddr *)&la, sizeof(la)); + if (err < 0) + return err; + + return fd; +} + +static int parse_rtattr(struct lkl_rtattr *tb[], int max, + struct lkl_rtattr *rta, int len) +{ + unsigned short type; + + memset(tb, 0, sizeof(struct lkl_rtattr *) * (max + 1)); + while (LKL_RTA_OK(rta, len)) { + type = rta->rta_type; + if ((type <= max) && (!tb[type])) + tb[type] = rta; + rta = LKL_RTA_NEXT(rta, len); + } + if (len) + lkl_printf("!!!Deficit %d, rta_len=%d\n", len, + rta->rta_len); + return 0; +} + +struct addr_filter { + unsigned int ifindex; + void *addr; +}; + +static unsigned int get_ifa_flags(struct lkl_ifaddrmsg *ifa, + struct lkl_rtattr *ifa_flags_attr) +{ + return ifa_flags_attr ? *(unsigned int *)LKL_RTA_DATA(ifa_flags_attr) : + ifa->ifa_flags; +} + +/* returns: + * 0 - dad succeed. + * -1 - dad failed or other error. + * 1 - should wait for new msg. + */ +static int check_ipv6_dad(struct lkl_sockaddr_nl *nladdr, + struct lkl_nlmsghdr *n, void *arg) +{ + struct addr_filter *filter = arg; + struct lkl_ifaddrmsg *ifa = LKL_NLMSG_DATA(n); + struct lkl_rtattr *rta_tb[LKL_IFA_MAX+1]; + unsigned int ifa_flags; + int len = n->nlmsg_len; + + if (n->nlmsg_type != LKL_RTM_NEWADDR) + return 1; + + len -= LKL_NLMSG_LENGTH(sizeof(*ifa)); + if (len < 0) { + lkl_printf("BUG: wrong nlmsg len %d\n", len); + return -1; + } + + parse_rtattr(rta_tb, LKL_IFA_MAX, LKL_IFA_RTA(ifa), + n->nlmsg_len - LKL_NLMSG_LENGTH(sizeof(*ifa))); + + ifa_flags = get_ifa_flags(ifa, rta_tb[LKL_IFA_FLAGS]); + + if (ifa->ifa_index != filter->ifindex) + return 1; + if (ifa->ifa_family != LKL_AF_INET6) + return 1; + + if (!rta_tb[LKL_IFA_LOCAL]) + rta_tb[LKL_IFA_LOCAL] = rta_tb[LKL_IFA_ADDRESS]; + + if (!rta_tb[LKL_IFA_LOCAL] || + (filter->addr && memcmp(LKL_RTA_DATA(rta_tb[LKL_IFA_LOCAL]), + filter->addr, 16))) { + return 1; + } + if (ifa_flags & LKL_IFA_F_DADFAILED) { + lkl_printf("IPV6 DAD failed.\n"); + return -1; + } + if (!(ifa_flags & LKL_IFA_F_TENTATIVE)) + return 0; + return 1; +} + +/* Copied from iproute2/lib/ */ +static int rtnl_listen(int fd, int (*handler)(struct lkl_sockaddr_nl *nladdr, + struct lkl_nlmsghdr *, void *), + void *arg) +{ + int status; + struct lkl_nlmsghdr *h; + struct lkl_sockaddr_nl nladdr = { .nl_family = LKL_AF_NETLINK }; + struct lkl_iovec iov; + struct lkl_user_msghdr msg = { + .msg_name = &nladdr, + .msg_namelen = sizeof(nladdr), + .msg_iov = &iov, + .msg_iovlen = 1, + }; + char buf[16384]; + + iov.iov_base = buf; + while (1) { + iov.iov_len = sizeof(buf); + status = lkl_sys_recvmsg(fd, &msg, 0); + + if (status < 0) { + if (status == -LKL_EINTR || status == -LKL_EAGAIN) + continue; + lkl_printf("netlink receive error %s (%d)\n", + lkl_strerror(status), status); + if (status == -LKL_ENOBUFS) + continue; + return status; + } + if (status == 0) { + lkl_printf("EOF on netlink\n"); + return -1; + } + if (msg.msg_namelen != sizeof(nladdr)) { + lkl_printf("Sender address length == %d\n", + msg.msg_namelen); + return -1; + } + + for (h = (struct lkl_nlmsghdr *)buf; + (unsigned int)status >= sizeof(*h);) { + int err; + int len = h->nlmsg_len; + int l = len - sizeof(*h); + + if (l < 0 || len > status) { + if (msg.msg_flags & LKL_MSG_TRUNC) { + lkl_printf("Truncated message\n"); + return -1; + } + lkl_printf("!!!malformed message: len=%d\n", + len); + return -1; + } + + err = handler(&nladdr, h, arg); + if (err <= 0) + return err; + + status -= LKL_NLMSG_ALIGN(len); + h = (struct lkl_nlmsghdr *)((char *)h + + LKL_NLMSG_ALIGN(len)); + } + if (msg.msg_flags & LKL_MSG_TRUNC) { + lkl_printf("Message truncated\n"); + continue; + } + if (status) { + lkl_printf("!!!Remnant of size %d\n", status); + return -1; + } + } +} + +int lkl_if_wait_ipv6_dad(int ifindex, void *addr) +{ + struct addr_filter filter = {.ifindex = ifindex, .addr = addr}; + int fd, ret; + struct { + struct lkl_nlmsghdr nlmsg_info; + struct lkl_ifaddrmsg ifaddrmsg_info; + } req; + + fd = netlink_sock(1 << (LKL_RTNLGRP_IPV6_IFADDR - 1)); + if (fd < 0) + return fd; + + memset(&req, 0, sizeof(req)); + req.nlmsg_info.nlmsg_len = + LKL_NLMSG_LENGTH(sizeof(struct lkl_ifaddrmsg)); + req.nlmsg_info.nlmsg_flags = LKL_NLM_F_REQUEST | LKL_NLM_F_DUMP; + req.nlmsg_info.nlmsg_type = LKL_RTM_GETADDR; + req.ifaddrmsg_info.ifa_family = LKL_AF_INET6; + req.ifaddrmsg_info.ifa_index = ifindex; + ret = lkl_sys_send(fd, &req, req.nlmsg_info.nlmsg_len, 0); + if (ret < 0) { + lkl_perror("lkl_sys_send", ret); + return ret; + } + ret = rtnl_listen(fd, check_ipv6_dad, (void *)&filter); + lkl_sys_close(fd); + return ret; +} + +int lkl_if_set_ipv6(int ifindex, void *addr, unsigned int netprefix_len) +{ + int err = lkl_if_add_ip(ifindex, LKL_AF_INET6, addr, netprefix_len); + + if (err) + return err; + return lkl_if_wait_ipv6_dad(ifindex, addr); +} + +int lkl_if_set_ipv6_gateway(int ifindex, void *src_addr, + unsigned int src_masklen, void *via_addr) +{ + int err; + + err = lkl_if_add_rule_from_saddr(ifindex, LKL_AF_INET6, src_addr); + if (err) + return err; + err = lkl_if_add_linklocal(ifindex, LKL_AF_INET6, + src_addr, src_masklen); + if (err) + return err; + return lkl_if_add_gateway(ifindex, LKL_AF_INET6, via_addr); +} + +int lkl_set_ipv6_gateway(void *addr) +{ + return lkl_add_gateway(LKL_AF_INET6, addr); +} + +/* returns: + * 0 - succeed. + * < 0 - error number. + * 1 - should wait for new msg. + */ +static int check_error(struct lkl_sockaddr_nl *nladdr, struct lkl_nlmsghdr *n, + void *arg) +{ + unsigned int s = *(unsigned int *)arg; + + if (nladdr->nl_pid != 0 || n->nlmsg_seq != s) { + /* Don't forget to skip that message. */ + return 1; + } + + if (n->nlmsg_type == LKL_NLMSG_ERROR) { + struct lkl_nlmsgerr *err = + (struct lkl_nlmsgerr *)LKL_NLMSG_DATA(n); + int l = n->nlmsg_len - sizeof(*n); + + if (l < (int)sizeof(struct lkl_nlmsgerr)) + lkl_printf("ERROR truncated\n"); + else if (!err->error) + return 0; + + lkl_printf("RTNETLINK answers: %s\n", + lkl_strerror(-err->error)); + return err->error; + } + lkl_printf("Unexpected reply!!!\n"); + return -1; +} + +static unsigned int seq; +static int rtnl_talk(int fd, struct lkl_nlmsghdr *n) +{ + int status; + struct lkl_sockaddr_nl nladdr = {.nl_family = LKL_AF_NETLINK}; + struct lkl_iovec iov = {.iov_base = (void *)n, .iov_len = n->nlmsg_len}; + struct lkl_user_msghdr msg = { + .msg_name = &nladdr, + .msg_namelen = sizeof(nladdr), + .msg_iov = &iov, + .msg_iovlen = 1, + }; + + n->nlmsg_seq = seq; + n->nlmsg_flags |= LKL_NLM_F_ACK; + + status = lkl_sys_sendmsg(fd, &msg, 0); + if (status < 0) { + lkl_perror("Cannot talk to rtnetlink", status); + return status; + } + + status = rtnl_listen(fd, check_error, (void *)&seq); + seq++; + return status; +} + +static int addattr_l(struct lkl_nlmsghdr *n, unsigned int maxlen, + int type, const void *data, int alen) +{ + int len = LKL_RTA_LENGTH(alen); + struct lkl_rtattr *rta; + + if (LKL_NLMSG_ALIGN(n->nlmsg_len) + LKL_RTA_ALIGN(len) > maxlen) { + lkl_printf("%s ERROR: message exceeded bound of %d\n", __func__, + maxlen); + return -1; + } + rta = ((struct lkl_rtattr *) (((void *) (n)) + + LKL_NLMSG_ALIGN(n->nlmsg_len))); + rta->rta_type = type; + rta->rta_len = len; + memcpy(LKL_RTA_DATA(rta), data, alen); + n->nlmsg_len = LKL_NLMSG_ALIGN(n->nlmsg_len) + LKL_RTA_ALIGN(len); + return 0; +} + +int lkl_add_neighbor(int ifindex, int af, void *ip, void *mac) +{ + struct { + struct lkl_nlmsghdr n; + struct lkl_ndmsg r; + char buf[1024]; + } req = { + .n.nlmsg_len = LKL_NLMSG_LENGTH(sizeof(struct lkl_ndmsg)), + .n.nlmsg_type = LKL_RTM_NEWNEIGH, + .n.nlmsg_flags = LKL_NLM_F_REQUEST | + LKL_NLM_F_CREATE | LKL_NLM_F_REPLACE, + .r.ndm_family = af, + .r.ndm_ifindex = ifindex, + .r.ndm_state = LKL_NUD_PERMANENT, + + }; + int err, addr_sz; + int fd; + + if (af == LKL_AF_INET) + addr_sz = 4; + else if (af == LKL_AF_INET6) + addr_sz = 16; + else { + lkl_printf("Bad address family: %d\n", af); + return -1; + } + + fd = netlink_sock(0); + if (fd < 0) + return fd; + + // create the IP attribute + addattr_l(&req.n, sizeof(req), LKL_NDA_DST, ip, addr_sz); + + // create the MAC attribute + addattr_l(&req.n, sizeof(req), LKL_NDA_LLADDR, mac, 6); + + err = rtnl_talk(fd, &req.n); + lkl_sys_close(fd); + return err; +} + +static int ipaddr_modify(int cmd, int flags, int ifindex, int af, void *addr, + unsigned int netprefix_len) +{ + struct { + struct lkl_nlmsghdr n; + struct lkl_ifaddrmsg ifa; + char buf[256]; + } req = { + .n.nlmsg_len = LKL_NLMSG_LENGTH(sizeof(struct lkl_ifaddrmsg)), + .n.nlmsg_flags = LKL_NLM_F_REQUEST | flags, + .n.nlmsg_type = cmd, + .ifa.ifa_family = af, + .ifa.ifa_prefixlen = netprefix_len, + .ifa.ifa_index = ifindex, + }; + int err, addr_sz; + int fd; + + if (af == LKL_AF_INET) + addr_sz = 4; + else if (af == LKL_AF_INET6) + addr_sz = 16; + else { + lkl_printf("Bad address family: %d\n", af); + return -1; + } + + fd = netlink_sock(0); + if (fd < 0) + return fd; + + // create the IP attribute + addattr_l(&req.n, sizeof(req), LKL_IFA_LOCAL, addr, addr_sz); + + err = rtnl_talk(fd, &req.n); + + lkl_sys_close(fd); + return err; +} + +int lkl_if_add_ip(int ifindex, int af, void *addr, unsigned int netprefix_len) +{ + return ipaddr_modify(LKL_RTM_NEWADDR, LKL_NLM_F_CREATE | LKL_NLM_F_EXCL, + ifindex, af, addr, netprefix_len); +} + +int lkl_if_del_ip(int ifindex, int af, void *addr, unsigned int netprefix_len) +{ + return ipaddr_modify(LKL_RTM_DELADDR, 0, ifindex, af, + addr, netprefix_len); +} + +static int iproute_modify(int cmd, unsigned int flags, int ifindex, int af, + void *route_addr, int route_masklen, void *gwaddr) +{ + struct { + struct lkl_nlmsghdr n; + struct lkl_rtmsg r; + char buf[1024]; + } req = { + .n.nlmsg_len = LKL_NLMSG_LENGTH(sizeof(struct lkl_rtmsg)), + .n.nlmsg_flags = LKL_NLM_F_REQUEST | flags, + .n.nlmsg_type = cmd, + .r.rtm_family = af, + .r.rtm_table = LKL_RT_TABLE_MAIN, + .r.rtm_scope = LKL_RT_SCOPE_UNIVERSE, + }; + int err, addr_sz; + int i, fd; + + fd = netlink_sock(0); + if (fd < 0) { + lkl_printf("netlink_sock error: %d\n", fd); + return fd; + } + + if (af == LKL_AF_INET) + addr_sz = 4; + else if (af == LKL_AF_INET6) + addr_sz = 16; + else { + lkl_printf("Bad address family: %d\n", af); + return -1; + } + + if (cmd != LKL_RTM_DELROUTE) { + req.r.rtm_protocol = LKL_RTPROT_BOOT; + req.r.rtm_scope = LKL_RT_SCOPE_UNIVERSE; + req.r.rtm_type = LKL_RTN_UNICAST; + } + + if (gwaddr) + addattr_l(&req.n, sizeof(req), + LKL_RTA_GATEWAY, gwaddr, addr_sz); + + if (af == LKL_AF_INET && route_addr) { + unsigned int netaddr = *(unsigned int *)route_addr; + + netaddr = ntohl(netaddr); + netaddr = (netaddr >> (32 - route_masklen)); + netaddr = (netaddr << (32 - route_masklen)); + netaddr = htonl(netaddr); + *(unsigned int *)route_addr = netaddr; + req.r.rtm_dst_len = route_masklen; + addattr_l(&req.n, sizeof(req), LKL_RTA_DST, + route_addr, addr_sz); + } + + if (af == LKL_AF_INET6 && route_addr) { + struct lkl_in6_addr netaddr = + *(struct lkl_in6_addr *)route_addr; + int rmbyte = route_masklen/8; + int rmbit = route_masklen%8; + + for (i = 0; i < rmbyte; i++) + netaddr.in6_u.u6_addr8[15-i] = 0; + netaddr.in6_u.u6_addr8[15-rmbyte] = + (netaddr.in6_u.u6_addr8[15-rmbyte] >> rmbit); + netaddr.in6_u.u6_addr8[15-rmbyte] = + (netaddr.in6_u.u6_addr8[15-rmbyte] << rmbit); + *(struct lkl_in6_addr *)route_addr = netaddr; + req.r.rtm_dst_len = route_masklen; + addattr_l(&req.n, sizeof(req), LKL_RTA_DST, + route_addr, addr_sz); + } + + if (ifindex != LKL_RT_TABLE_MAIN) { + if (af == LKL_AF_INET) + req.r.rtm_table = ifindex * 2; + else if (af == LKL_AF_INET6) + req.r.rtm_table = ifindex * 2 + 1; + addattr_l(&req.n, sizeof(req), LKL_RTA_OIF, &ifindex, addr_sz); + } + err = rtnl_talk(fd, &req.n); + lkl_sys_close(fd); + return err; +} + +int lkl_if_add_linklocal(int ifindex, int af, void *addr, int netprefix_len) +{ + return iproute_modify(LKL_RTM_NEWROUTE, LKL_NLM_F_CREATE|LKL_NLM_F_EXCL, + ifindex, af, addr, netprefix_len, NULL); +} + +int lkl_if_add_gateway(int ifindex, int af, void *gwaddr) +{ + return iproute_modify(LKL_RTM_NEWROUTE, LKL_NLM_F_CREATE|LKL_NLM_F_EXCL, + ifindex, af, NULL, 0, gwaddr); +} + +int lkl_add_gateway(int af, void *gwaddr) +{ + return iproute_modify(LKL_RTM_NEWROUTE, LKL_NLM_F_CREATE|LKL_NLM_F_EXCL, + LKL_RT_TABLE_MAIN, af, NULL, 0, gwaddr); +} + +static int iprule_modify(int cmd, int ifindex, int af, void *saddr) +{ + struct { + struct lkl_nlmsghdr n; + struct lkl_rtmsg r; + char buf[1024]; + } req = { + .n.nlmsg_type = cmd, + .n.nlmsg_len = LKL_NLMSG_LENGTH(sizeof(struct lkl_rtmsg)), + .n.nlmsg_flags = LKL_NLM_F_REQUEST, + .r.rtm_protocol = LKL_RTPROT_BOOT, + .r.rtm_scope = LKL_RT_SCOPE_UNIVERSE, + .r.rtm_family = af, + .r.rtm_type = LKL_RTN_UNSPEC, + }; + int fd, err; + int addr_sz; + + if (af == LKL_AF_INET) + addr_sz = 4; + else if (af == LKL_AF_INET6) + addr_sz = 16; + else { + lkl_printf("Bad address family: %d\n", af); + return -1; + } + + fd = netlink_sock(0); + if (fd < 0) + return fd; + + if (cmd == LKL_RTM_NEWRULE) { + req.n.nlmsg_flags |= LKL_NLM_F_CREATE|LKL_NLM_F_EXCL; + req.r.rtm_type = LKL_RTN_UNICAST; + } + + //set from address + req.r.rtm_src_len = 8 * addr_sz; + addattr_l(&req.n, sizeof(req), LKL_FRA_SRC, saddr, addr_sz); + + //use ifindex as table id + if (af == LKL_AF_INET) + req.r.rtm_table = ifindex * 2; + else if (af == LKL_AF_INET6) + req.r.rtm_table = ifindex * 2 + 1; + err = rtnl_talk(fd, &req.n); + + lkl_sys_close(fd); + return err; +} + +int lkl_if_add_rule_from_saddr(int ifindex, int af, void *saddr) +{ + return iprule_modify(LKL_RTM_NEWRULE, ifindex, af, saddr); +} + +static int qdisc_add(int cmd, int flags, int ifindex, + const char *root, const char *type) +{ + struct { + struct lkl_nlmsghdr n; + struct lkl_tcmsg tc; + char buf[2*1024]; + } req = { + .n.nlmsg_len = LKL_NLMSG_LENGTH(sizeof(struct lkl_tcmsg)), + .n.nlmsg_flags = LKL_NLM_F_REQUEST|flags, + .n.nlmsg_type = cmd, + .tc.tcm_family = LKL_AF_UNSPEC, + }; + int err, fd; + + if (!root || !type) { + lkl_printf("root and type arguments\n"); + return -1; + } + + if (strcmp(root, "root") == 0) + req.tc.tcm_parent = LKL_TC_H_ROOT; + req.tc.tcm_ifindex = ifindex; + + fd = netlink_sock(0); + if (fd < 0) + return fd; + + // create the qdisc attribute + addattr_l(&req.n, sizeof(req), LKL_TCA_KIND, type, strlen(type)+1); + + err = rtnl_talk(fd, &req.n); + lkl_sys_close(fd); + return err; +} + +int lkl_qdisc_add(int ifindex, const char *root, const char *type) +{ + return qdisc_add(LKL_RTM_NEWQDISC, LKL_NLM_F_CREATE | LKL_NLM_F_EXCL, + ifindex, root, type); +} + +/* Add a qdisc entry for an interface in the form of + * "root|type;root|type;..." + */ +void lkl_qdisc_parse_add(int ifindex, const char *entries) +{ + char *saveptr = NULL, *token = NULL; + char *root = NULL, *type = NULL; + char strings[256]; + int ret = 0; + + if (strlen(entries) >= sizeof(strings)) { + lkl_printf("Error: long strings of input: %s\n", entries); + return; + } + + strcpy(strings, entries); + + for (token = strtok_r(strings, ";", &saveptr); token; + token = strtok_r(NULL, ";", &saveptr)) { + root = strtok(token, "|"); + type = strtok(NULL, "|"); + ret = lkl_qdisc_add(ifindex, root, type); + if (ret) { + lkl_printf("Failed to add qdisc entry: %s\n", + lkl_strerror(ret)); + return; + } + } +} From patchwork Mon Mar 30 14:45:48 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hajime Tazaki X-Patchwork-Id: 1263992 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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=kwViokRY; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=aSyzzFkt; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (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 48rb214fbDz9sP7 for ; Tue, 31 Mar 2020 01:48:57 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.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=vMx7ZJu1nxKPx5O9ZUVupBSqzI48w3eDFSahYRfcEog=; b=kwViokRYys+Bte lr35VymG7r0KC3ZFnMttz/FMm+IOfYsVe1XWclQfAdwcQpFgIMOb2pySmlXQp60wAs243hoGno7JG sWD5D7Ko7FxZuAHQrMLY3cfASTTlLFh34xhNJ1roqAc9iP2Tj2FHkyfmyfMhf/yTQkQBGXsGHOyfu YFirgILIHOYAV8JpIBS10AB7uRX5PVPVpK5ayzEQ9tXnVZJUiNfTzlBoQJvdgDw/R9Fc5lAjX2z0+ Txk4GiraxKrnwJNyZC/XMMRAiQyI+VAPj7zv1znU9r+VJOlKkB3tqJs8reZbWNBb6GuwZ1SUiyOJf NZp8K2/EL2YSNp0XQvYg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIviY-00051L-6u; Mon, 30 Mar 2020 14:48:46 +0000 Received: from mail-pl1-x641.google.com ([2607:f8b0:4864:20::641]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIviU-00050e-I9 for linux-um@lists.infradead.org; Mon, 30 Mar 2020 14:48:44 +0000 Received: by mail-pl1-x641.google.com with SMTP id t4so852679plq.12 for ; Mon, 30 Mar 2020 07:48:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=P9RNoEzbbgw1c3biOrP2WMrvjOX1CmcwEAo3VDKIBII=; b=aSyzzFktASEqcZhmB14e5xHTl92y/72UvBBsaaRCAyWnWpmvbzGIjKCJdLPgee4I5X rOUfWVK6SavrVoysy9IwPaHWJZfnqzx9moJe0rUklBt7+DsCJBhW8tGaTUjzboAafJim xyeV9AiAc/YoUyc1uwRISMv8q/VDE8TkrAVJ7L2RnIM7Q7LFrb7chdsw+LKImkmltE4v sFGMnhLui+FWD3Uf33DFXUhdyYaQrzMElFKqPZHKp153XxzwvxcbS/yIX9TjcAl/lzBG WbZZIjfA/fYkmupRenjZWg9V5ymG10ie5ioXP2xEaJTstRDHG6OHLI6GngNWwHScVXzK y2Fg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=P9RNoEzbbgw1c3biOrP2WMrvjOX1CmcwEAo3VDKIBII=; b=uRD5Y4e5qey4gwpU4W/BF07FdCGcC+L8E+NXhT2Ax40DvfhPSKTN+ZQIauILxtYKu4 2MWpSJZEdyCxjj7uPhNCDrOmSSVMGdIMBDmSjX5nA/tZHbeWWfuLg0mg4kof8GVBu542 t5T3Ynd3/6rlFPYG2X5FIKDEGDUCvyrxXUCfwvpUnmWxFJVPDnCcoxCY+mFoeBSb6pZ6 x3WYVZLvz4R+LdGm7dAzzGy3+ZNwc1Dg4PJy1nQYxGllLUkxBMLvryuTfKc16Uax2rGL xGdQO4r0EyjRfeBm4hDFk1uMDBnTIvv4o02t378qrn6tR5H/7kYv7G/JzC/2NJT/5SfZ 4bhg== X-Gm-Message-State: ANhLgQ2vfkyxmTdUwn33SCkArYhWlJOP9rN48chrBv+XDHlLrXdLPDpS UjvdNAAuFRwRnwW1Qb0oQt4= X-Google-Smtp-Source: ADFU+vvpiSFpS8RMWEin6rlzj/fguPJ1G741G/jqPjqHtucmPq88Qv8j6MmaYJJ+0UKvbolgIlkLTA== X-Received: by 2002:a17:90a:240e:: with SMTP id h14mr13737086pje.5.1585579721277; Mon, 30 Mar 2020 07:48:41 -0700 (PDT) Received: from earth-mac.local (219x123x138x129.ap219.ftth.ucom.ne.jp. [219.123.138.129]) by smtp.gmail.com with ESMTPSA id c19sm10394552pfo.205.2020.03.30.07.48.40 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 30 Mar 2020 07:48:40 -0700 (PDT) Received: by earth-mac.local (Postfix, from userid 501) id 0EFC4202804E3F; Mon, 30 Mar 2020 23:48:39 +0900 (JST) From: Hajime Tazaki To: linux-um@lists.infradead.org Subject: [RFC v4 16/25] lkl tools: host lib: posix host operations Date: Mon, 30 Mar 2020 23:45:48 +0900 Message-Id: <3fabf7fce74f62cfdace9dbdc26d6e787ba618b8.1585579244.git.thehajime@gmail.com> X-Mailer: git-send-email 2.20.1 (Apple Git-117) In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200330_074842_723875_501D5A63 X-CRM114-Status: GOOD ( 15.78 ) X-Spam-Score: -0.2 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:641 listed in] [list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [thehajime[at]gmail.com] -0.0 SPF_PASS SPF: sender matches SPF record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 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: linux-arch@vger.kernel.org, Hajime Tazaki , Conrad Meyer , Octavian Purdila , Akira Moroo , Thomas Liebetraut , Mark Stillwell , Patrick Collins , linux-kernel-library@freelists.org, Pierre-Hugues Husson , Yuan Liu Sender: "linux-um" Errors-To: linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Octavian Purdila This commit implements LKL host operations for POSIX hosts. The operations are implemented to be portable in various POSIX OSs. Cc: Conrad Meyer Cc: Mark Stillwell Cc: Patrick Collins Cc: Pierre-Hugues Husson Cc: Thomas Liebetraut Cc: Yuan Liu Signed-off-by: Hajime Tazaki Signed-off-by: Octavian Purdila --- tools/lkl/lib/Build | 2 + tools/lkl/lib/posix-host.c | 353 +++++++++++++++++++++++++++++++++++++ 2 files changed, 355 insertions(+) create mode 100644 tools/lkl/lib/posix-host.c diff --git a/tools/lkl/lib/Build b/tools/lkl/lib/Build index dba530424e4a..0e711e260a3a 100644 --- a/tools/lkl/lib/Build +++ b/tools/lkl/lib/Build @@ -1,8 +1,10 @@ CFLAGS_config.o += -I$(srctree)/tools/perf/pmu-events +CFLAGS_posix-host.o += -D_FILE_OFFSET_BITS=64 liblkl-y += fs.o liblkl-y += net.o liblkl-y += jmp_buf.o +liblkl-$(LKL_HOST_CONFIG_POSIX) += posix-host.o liblkl-y += utils.o liblkl-y += dbg.o liblkl-y += dbg_handler.o diff --git a/tools/lkl/lib/posix-host.c b/tools/lkl/lib/posix-host.c new file mode 100644 index 000000000000..4be1611a8942 --- /dev/null +++ b/tools/lkl/lib/posix-host.c @@ -0,0 +1,353 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "jmp_buf.h" + +/* Let's see if the host has semaphore.h */ +#include + +#ifdef _POSIX_SEMAPHORES +#include +/* TODO(pscollins): We don't support fork() for now, but maybe one day + * we will? + */ +#define SHARE_SEM 0 +#endif /* _POSIX_SEMAPHORES */ + +static void print(const char *str, int len) +{ + int ret __attribute__((unused)); + + ret = write(STDOUT_FILENO, str, len); +} + +struct lkl_mutex { + pthread_mutex_t mutex; +}; + +struct lkl_sem { +#ifdef _POSIX_SEMAPHORES + sem_t sem; +#else + pthread_mutex_t lock; + int count; + pthread_cond_t cond; +#endif /* _POSIX_SEMAPHORES */ +}; + +struct lkl_tls_key { + pthread_key_t key; +}; + +#define WARN_UNLESS(exp) do { \ + if (exp < 0) \ + lkl_printf("%s: %s\n", #exp, strerror(errno)); \ + } while (0) + +static int _warn_pthread(int ret, char *str_exp) +{ + if (ret > 0) + lkl_printf("%s: %s\n", str_exp, strerror(ret)); + + return ret; +} + + +/* pthread_* functions use the reverse convention */ +#define WARN_PTHREAD(exp) _warn_pthread(exp, #exp) + +static struct lkl_sem *sem_alloc(int count) +{ + struct lkl_sem *sem; + + sem = malloc(sizeof(*sem)); + if (!sem) + return NULL; + +#ifdef _POSIX_SEMAPHORES + if (sem_init(&sem->sem, SHARE_SEM, count) < 0) { + lkl_printf("sem_init: %s\n", strerror(errno)); + free(sem); + return NULL; + } +#else + pthread_mutex_init(&sem->lock, NULL); + sem->count = count; + WARN_PTHREAD(pthread_cond_init(&sem->cond, NULL)); +#endif /* _POSIX_SEMAPHORES */ + + return sem; +} + +static void sem_free(struct lkl_sem *sem) +{ +#ifdef _POSIX_SEMAPHORES + WARN_UNLESS(sem_destroy(&sem->sem)); +#else + WARN_PTHREAD(pthread_cond_destroy(&sem->cond)); + WARN_PTHREAD(pthread_mutex_destroy(&sem->lock)); +#endif /* _POSIX_SEMAPHORES */ + free(sem); +} + +static void sem_up(struct lkl_sem *sem) +{ +#ifdef _POSIX_SEMAPHORES + WARN_UNLESS(sem_post(&sem->sem)); +#else + WARN_PTHREAD(pthread_mutex_lock(&sem->lock)); + sem->count++; + if (sem->count > 0) + WARN_PTHREAD(pthread_cond_signal(&sem->cond)); + WARN_PTHREAD(pthread_mutex_unlock(&sem->lock)); +#endif /* _POSIX_SEMAPHORES */ + +} + +static void sem_down(struct lkl_sem *sem) +{ +#ifdef _POSIX_SEMAPHORES + int err; + + do { + err = sem_wait(&sem->sem); + } while (err < 0 && errno == EINTR); + if (err < 0 && errno != EINTR) + lkl_printf("sem_wait: %s\n", strerror(errno)); +#else + WARN_PTHREAD(pthread_mutex_lock(&sem->lock)); + while (sem->count <= 0) + WARN_PTHREAD(pthread_cond_wait(&sem->cond, &sem->lock)); + sem->count--; + WARN_PTHREAD(pthread_mutex_unlock(&sem->lock)); +#endif /* _POSIX_SEMAPHORES */ +} + +static struct lkl_mutex *mutex_alloc(int recursive) +{ + struct lkl_mutex *_mutex = malloc(sizeof(struct lkl_mutex)); + pthread_mutex_t *mutex = NULL; + pthread_mutexattr_t attr; + + if (!_mutex) + return NULL; + + mutex = &_mutex->mutex; + WARN_PTHREAD(pthread_mutexattr_init(&attr)); + + /* PTHREAD_MUTEX_ERRORCHECK is *very* useful for debugging, + * but has some overhead, so we provide an option to turn it + * off. + */ +#ifdef DEBUG + if (!recursive) + WARN_PTHREAD(pthread_mutexattr_settype( + &attr, PTHREAD_MUTEX_ERRORCHECK)); +#endif /* DEBUG */ + + if (recursive) + WARN_PTHREAD(pthread_mutexattr_settype( + &attr, PTHREAD_MUTEX_RECURSIVE)); + + WARN_PTHREAD(pthread_mutex_init(mutex, &attr)); + + return _mutex; +} + +static void mutex_lock(struct lkl_mutex *mutex) +{ + WARN_PTHREAD(pthread_mutex_lock(&mutex->mutex)); +} + +static void mutex_unlock(struct lkl_mutex *_mutex) +{ + pthread_mutex_t *mutex = &_mutex->mutex; + + WARN_PTHREAD(pthread_mutex_unlock(mutex)); +} + +static void mutex_free(struct lkl_mutex *_mutex) +{ + pthread_mutex_t *mutex = &_mutex->mutex; + + WARN_PTHREAD(pthread_mutex_destroy(mutex)); + free(_mutex); +} + +static lkl_thread_t thread_create(void (*fn)(void *), void *arg) +{ + pthread_t thread; + + if (WARN_PTHREAD(pthread_create(&thread, NULL, (void *)fn, + arg))) + return 0; + else + return (lkl_thread_t) thread; +} + +static void thread_detach(void) +{ + WARN_PTHREAD(pthread_detach(pthread_self())); +} + +static void thread_exit(void) +{ + pthread_exit(NULL); +} + +static int thread_join(lkl_thread_t tid) +{ + if (WARN_PTHREAD(pthread_join((pthread_t)tid, NULL))) + return (-1); + else + return 0; +} + +static lkl_thread_t thread_self(void) +{ + return (lkl_thread_t)pthread_self(); +} + +static int thread_equal(lkl_thread_t a, lkl_thread_t b) +{ + return pthread_equal((pthread_t)a, (pthread_t)b); +} + +static struct lkl_tls_key *tls_alloc(void (*destructor)(void *)) +{ + struct lkl_tls_key *ret = malloc(sizeof(struct lkl_tls_key)); + + if (WARN_PTHREAD(pthread_key_create(&ret->key, destructor))) { + free(ret); + return NULL; + } + return ret; +} + +static void tls_free(struct lkl_tls_key *key) +{ + WARN_PTHREAD(pthread_key_delete(key->key)); + free(key); +} + +static int tls_set(struct lkl_tls_key *key, void *data) +{ + if (WARN_PTHREAD(pthread_setspecific(key->key, data))) + return (-1); + return 0; +} + +static void *tls_get(struct lkl_tls_key *key) +{ + return pthread_getspecific(key->key); +} + +static unsigned long long time_ns(void) +{ + struct timespec ts; + + clock_gettime(CLOCK_MONOTONIC, &ts); + + return 1e9*ts.tv_sec + ts.tv_nsec; +} + +static void *timer_alloc(void (*fn)(void *), void *arg) +{ + int err; + timer_t timer; + struct sigevent se = { + .sigev_notify = SIGEV_THREAD, + .sigev_value = { + .sival_ptr = arg, + }, + .sigev_notify_function = (void *)fn, + }; + + err = timer_create(CLOCK_REALTIME, &se, &timer); + if (err) + return NULL; + + return (void *)(long)timer; +} + +static int timer_set_oneshot(void *_timer, unsigned long ns) +{ + timer_t timer = (timer_t)(long)_timer; + struct itimerspec ts = { + .it_value = { + .tv_sec = ns / 1000000000, + .tv_nsec = ns % 1000000000, + }, + }; + + return timer_settime(timer, 0, &ts, NULL); +} + +static void timer_free(void *_timer) +{ + timer_t timer = (timer_t)(long)_timer; + + timer_delete(timer); +} + +static void panic(void) +{ + assert(0); +} + +static long _gettid(void) +{ +#ifdef __FreeBSD__ + return (long)pthread_self(); +#else + return syscall(SYS_gettid); +#endif +} + +struct lkl_host_operations lkl_host_ops = { + .panic = panic, + .thread_create = thread_create, + .thread_detach = thread_detach, + .thread_exit = thread_exit, + .thread_join = thread_join, + .thread_self = thread_self, + .thread_equal = thread_equal, + .sem_alloc = sem_alloc, + .sem_free = sem_free, + .sem_up = sem_up, + .sem_down = sem_down, + .mutex_alloc = mutex_alloc, + .mutex_free = mutex_free, + .mutex_lock = mutex_lock, + .mutex_unlock = mutex_unlock, + .tls_alloc = tls_alloc, + .tls_free = tls_free, + .tls_set = tls_set, + .tls_get = tls_get, + .time = time_ns, + .timer_alloc = timer_alloc, + .timer_set_oneshot = timer_set_oneshot, + .timer_free = timer_free, + .print = print, + .mem_alloc = (void *)malloc, + .mem_free = free, + .gettid = _gettid, + .jmp_buf_set = jmp_buf_set, + .jmp_buf_longjmp = jmp_buf_longjmp, +}; + From patchwork Mon Mar 30 14:45:49 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hajime Tazaki X-Patchwork-Id: 1263993 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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=QIsovisD; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=Fa+WRSqU; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (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 48rb274pYJz9sP7 for ; Tue, 31 Mar 2020 01:49:03 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.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=R0fF/F/MoK+hrxP65mN9+wtGEQc4fKOnWP1EJyfzs5Y=; b=QIsovisDIzVj37 7/tNbJubMK5UDfQqxw8+nc2apPbX+ZAOueWiU0wVFRTVA1t+fp3vdE63Jxz05saB5OKLoHQcRLSek eUxOQ9EATC+PdeAmfLS7m3ITXQ9nbONL4ZHSUcJNjIPMvj7A3stcFfjnkLt9q7ZlI+Wl9mE0pZMb7 Y5LyOB47V73tIIAkrJ/OOXWs1N3+7aEDbZCSJM/rrPO+JCin0xMx3VJRRAkWpBBTwqYNzT2bi48x/ PdirjZdyQXorZNfMHMYp9R3+NKdykyr9TkTsbvl0s7bt5LnEu/cmmFscMF88+PTua31v/7/Kz9t/8 jKYyA77ucHxcjZLD0KjQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvie-00052h-G5; Mon, 30 Mar 2020 14:48:52 +0000 Received: from mail-pl1-x643.google.com ([2607:f8b0:4864:20::643]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIviX-000513-HH for linux-um@lists.infradead.org; Mon, 30 Mar 2020 14:48:50 +0000 Received: by mail-pl1-x643.google.com with SMTP id e1so6803788plt.9 for ; Mon, 30 Mar 2020 07:48:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=dY0Cs2GLN9B5IOjRYUJ63n4TqEafLZsrxeHrY3G99Jc=; b=Fa+WRSqUiIltRWhKht/wQOiSiU2lqQdv8mYt9Fu47t+LC8OPm+tfdbUFAjerghbRXV +VwBniwyaW131Icf3CEdGXmI9pdiVj9k0ROJHa5EOpPaIycqHuLHV0ja/R1KJDYluenN XciPsgcbHEspb04WkOX7bRlyqzfEcnsbY5eBsdFiMD6Sv/J3pj9b8Gdzhk+hC9mA5jv/ IQcnGfv8wSdW8CqZLZYtBYXcF/yyXqtRKFfTjnf2oFNf1JPr/uS2jZI53rVFBQo/Nxds YJgZgflPHBZA70pdxE0/p0P+FJ4X8oJdsG9lVVkG8tyW9kjaEfIBQUvlqH6tvNk/z3xd CEnA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=dY0Cs2GLN9B5IOjRYUJ63n4TqEafLZsrxeHrY3G99Jc=; b=nV43A0BkZwllTFf6TyZE8D021gm8e+Ns9MebUSe2otQaGs0e4fSokDaEFbsQnCuxYN sXbGycrscCqHaYIW7TYfLmcORdTdCytRqQ/PPGslm7Xyfw9L6/b5BNI1rljJMdKmfVgq ou3/GurzLVASS7KgLpRV3DwQ16Q1RE1Yx0+ugPwnIr8zgaJgXdYSiOQBcPr5vEe3l9l8 J/JJ/IFCIyRkggbWboVidyqss4NziyybDjJU7b4wL/7Xo3iJezs5tcah5kxcS94qIYOA Qp+9lCjZPw2Mh7wiTh85N/T5/z1Na2WrtiC6Ff4W/5O3dZtyjvcgwWVJX401ilaNYKQD vVFg== X-Gm-Message-State: ANhLgQ0FivNH68+QCyeHLuZBKOGVFk6uBBbzjE/6Bkd/o/rS/uP1xS1S lMLLnSTIO7CuArjnjzLoxaM= X-Google-Smtp-Source: ADFU+vu+ZrY4qted6aEfyuACjZirAg7C8VoKDRdxpZCXlaer3jY1lDFnBQ51/8bhwwH+i+I+JEOE+g== X-Received: by 2002:a17:90a:fb94:: with SMTP id cp20mr16699074pjb.117.1585579724444; Mon, 30 Mar 2020 07:48:44 -0700 (PDT) Received: from earth-mac.local (219x123x138x129.ap219.ftth.ucom.ne.jp. [219.123.138.129]) by smtp.gmail.com with ESMTPSA id c9sm10277862pjr.47.2020.03.30.07.48.42 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 30 Mar 2020 07:48:43 -0700 (PDT) Received: by earth-mac.local (Postfix, from userid 501) id 85A12202804E43; Mon, 30 Mar 2020 23:48:41 +0900 (JST) From: Hajime Tazaki To: linux-um@lists.infradead.org Subject: [RFC v4 17/25] lkl tools: add test programs Date: Mon, 30 Mar 2020 23:45:49 +0900 Message-Id: X-Mailer: git-send-email 2.20.1 (Apple Git-117) In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200330_074845_703787_70CC6166 X-CRM114-Status: GOOD ( 20.26 ) X-Spam-Score: -0.2 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:643 listed in] [list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [thehajime[at]gmail.com] -0.0 SPF_PASS SPF: sender matches SPF record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 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: linux-arch@vger.kernel.org, Patrick Collins , Hajime Tazaki , Conrad Meyer , Octavian Purdila , Motomu Utsumi , Lai Jiangshan , Akira Moroo , Petros Angelatos , Thomas Liebetraut , Mark Stillwell , David Disseldorp , linux-kernel-library@freelists.org, Luca Dariz , Yuan Liu Sender: "linux-um" Errors-To: linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Octavian Purdila Add a simple LKL test application (boot) that starts the kernel and performs simple tests that minimally exercise the LKL API. Networking and block device tests are also added which are useful to detect regressions. Cc: Conrad Meyer Cc: David Disseldorp Cc: H.K. Jerry Chu Cc: Lai Jiangshan Cc: Luca Dariz Cc: Mark Stillwell Cc: Motomu Utsumi Cc: Patrick Collins Cc: Petros Angelatos Cc: Thomas Liebetraut Cc: Yuan Liu Signed-off-by: Hajime Tazaki Signed-off-by: Octavian Purdila --- tools/lkl/.gitignore | 5 + tools/lkl/Makefile | 5 +- tools/lkl/Targets | 3 + tools/lkl/tests/Build | 3 + tools/lkl/tests/boot.c | 562 ++++++++++++++++++++++++++++++ tools/lkl/tests/boot.sh | 9 + tools/lkl/tests/cla.c | 159 +++++++++ tools/lkl/tests/cla.h | 33 ++ tools/lkl/tests/disk.c | 189 ++++++++++ tools/lkl/tests/disk.sh | 61 ++++ tools/lkl/tests/net-setup.sh | 73 ++++ tools/lkl/tests/net-test.c | 299 ++++++++++++++++ tools/lkl/tests/net.sh | 90 +++++ tools/lkl/tests/run.py | 179 ++++++++++ tools/lkl/tests/tap13.py | 209 +++++++++++ tools/lkl/tests/test.c | 126 +++++++ tools/lkl/tests/test.h | 72 ++++ tools/lkl/tests/test.sh | 182 ++++++++++ tools/lkl/tests/valgrind.supp | 105 ++++++ tools/lkl/tests/valgrind2xunit.py | 69 ++++ 20 files changed, 2432 insertions(+), 1 deletion(-) create mode 100644 tools/lkl/tests/Build create mode 100644 tools/lkl/tests/boot.c create mode 100755 tools/lkl/tests/boot.sh create mode 100644 tools/lkl/tests/cla.c create mode 100644 tools/lkl/tests/cla.h create mode 100644 tools/lkl/tests/disk.c create mode 100755 tools/lkl/tests/disk.sh create mode 100644 tools/lkl/tests/net-setup.sh create mode 100644 tools/lkl/tests/net-test.c create mode 100755 tools/lkl/tests/net.sh create mode 100755 tools/lkl/tests/run.py create mode 100644 tools/lkl/tests/tap13.py create mode 100644 tools/lkl/tests/test.c create mode 100644 tools/lkl/tests/test.h create mode 100644 tools/lkl/tests/test.sh create mode 100644 tools/lkl/tests/valgrind.supp create mode 100755 tools/lkl/tests/valgrind2xunit.py diff --git a/tools/lkl/.gitignore b/tools/lkl/.gitignore index 1aed58bfe171..4e08254dbd46 100644 --- a/tools/lkl/.gitignore +++ b/tools/lkl/.gitignore @@ -2,3 +2,8 @@ Makefile.conf include/lkl_autoconf.h tests/autoconf.sh bin/stat +tests/net-test +tests/disk +tests/boot +tests/valgrind*.xml +*.pyc diff --git a/tools/lkl/Makefile b/tools/lkl/Makefile index 11ea7e9095bb..0abccb9d86b6 100644 --- a/tools/lkl/Makefile +++ b/tools/lkl/Makefile @@ -117,8 +117,11 @@ programs_install: $(progs-y:%=$(OUTPUT)%$(EXESUF)) install: headers_install libraries_install programs_install +run-tests: + ./tests/run.py $(tests) + FORCE: ; -.PHONY: all clean FORCE +.PHONY: all clean FORCE run-tests .PHONY: headers_install libraries_install programs_install install .NOTPARALLEL : lib/lkl.o .SECONDARY: diff --git a/tools/lkl/Targets b/tools/lkl/Targets index 24c985e64638..a9f74c3cc8fb 100644 --- a/tools/lkl/Targets +++ b/tools/lkl/Targets @@ -1,3 +1,6 @@ libs-y += lib/liblkl +progs-y += tests/boot +progs-y += tests/disk +progs-y += tests/net-test diff --git a/tools/lkl/tests/Build b/tools/lkl/tests/Build new file mode 100644 index 000000000000..ace86a3d3438 --- /dev/null +++ b/tools/lkl/tests/Build @@ -0,0 +1,3 @@ +boot-y += boot.o test.o +disk-y += disk.o cla.o test.o +net-test-y += net-test.o cla.o test.o diff --git a/tools/lkl/tests/boot.c b/tools/lkl/tests/boot.c new file mode 100644 index 000000000000..b021e9540147 --- /dev/null +++ b/tools/lkl/tests/boot.c @@ -0,0 +1,562 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#if defined(__FreeBSD__) +#include +#include +#elif __linux +#include +#include +#elif __MINGW32__ +#include +#endif + +#include "test.h" + +#ifndef __MINGW32__ +#define sleep_ns 87654321 +int lkl_test_nanosleep(void) +{ + struct lkl_timespec ts = { + .tv_sec = 0, + .tv_nsec = sleep_ns, + }; + struct timespec start, stop; + long delta; + long ret; + + clock_gettime(CLOCK_MONOTONIC, &start); + ret = lkl_sys_nanosleep((struct __lkl__kernel_timespec *)&ts, NULL); + clock_gettime(CLOCK_MONOTONIC, &stop); + + delta = 1e9*(stop.tv_sec - start.tv_sec) + + (stop.tv_nsec - start.tv_nsec); + + lkl_test_logf("sleep %ld, expected sleep %d\n", delta, sleep_ns); + + if (ret == 0 && delta > sleep_ns * 0.9) + return TEST_SUCCESS; + + return TEST_FAILURE; +} +#endif + +LKL_TEST_CALL(getpid, lkl_sys_getpid, 1) + +void check_latency(long (*f)(void), long *min, long *max, long *avg) +{ + int i; + unsigned long long start, stop, sum = 0; + static const int count = 1000; + long delta; + + *min = 1000000000; + *max = -1; + + for (i = 0; i < count; i++) { + start = lkl_host_ops.time(); + f(); + stop = lkl_host_ops.time(); + delta = stop - start; + if (*min > delta) + *min = delta; + if (*max < delta) + *max = delta; + sum += delta; + } + *avg = sum / count; +} + +static long native_getpid(void) +{ +#ifdef __MINGW32__ + GetCurrentProcessId(); +#else + getpid(); +#endif + return 0; +} + +int lkl_test_syscall_latency(void) +{ + long min, max, avg; + + lkl_test_logf("avg/min/max: "); + + check_latency(lkl_sys_getpid, &min, &max, &avg); + + lkl_test_logf("lkl:%ld/%ld/%ld ", avg, min, max); + + check_latency(native_getpid, &min, &max, &avg); + + lkl_test_logf("native:%ld/%ld/%ld\n", avg, min, max); + + return TEST_SUCCESS; +} + +#define access_rights 0721 + +LKL_TEST_CALL(creat, lkl_sys_creat, 0, "/file", access_rights) +LKL_TEST_CALL(close, lkl_sys_close, 0, 0); +LKL_TEST_CALL(failopen, lkl_sys_open, -LKL_ENOENT, "/file2", 0, 0); +LKL_TEST_CALL(umask, lkl_sys_umask, 022, 0777); +LKL_TEST_CALL(umask2, lkl_sys_umask, 0777, 0); +LKL_TEST_CALL(open, lkl_sys_open, 0, "/file", LKL_O_RDWR, 0); +static const char wrbuf[] = "test"; +LKL_TEST_CALL(write, lkl_sys_write, sizeof(wrbuf), 0, wrbuf, sizeof(wrbuf)); +LKL_TEST_CALL(lseek_cur, lkl_sys_lseek, sizeof(wrbuf), 0, 0, LKL_SEEK_CUR); +LKL_TEST_CALL(lseek_end, lkl_sys_lseek, sizeof(wrbuf), 0, 0, LKL_SEEK_END); +LKL_TEST_CALL(lseek_set, lkl_sys_lseek, 0, 0, 0, LKL_SEEK_SET); + +int lkl_test_read(void) +{ + char buf[10] = { 0, }; + long ret; + + ret = lkl_sys_read(0, buf, sizeof(buf)); + + lkl_test_logf("lkl_sys_read=%ld buf=%s\n", ret, buf); + + if (ret == sizeof(wrbuf) && !strcmp(wrbuf, buf)) + return TEST_SUCCESS; + + return TEST_FAILURE; +} + +int lkl_test_fstat(void) +{ + struct lkl_stat stat; + long ret; + + ret = lkl_sys_fstat(0, &stat); + + lkl_test_logf("lkl_sys_fstat=%ld mode=%o size=%zd\n", ret, stat.st_mode, + stat.st_size); + + if (ret == 0 && stat.st_size == sizeof(wrbuf) && + stat.st_mode == (access_rights | LKL_S_IFREG)) + return TEST_SUCCESS; + + return TEST_FAILURE; +} + +LKL_TEST_CALL(mkdir, lkl_sys_mkdir, 0, "/mnt", access_rights) + +int lkl_test_stat(void) +{ + struct lkl_stat stat; + long ret; + + ret = lkl_sys_stat("/mnt", &stat); + + lkl_test_logf("lkl_sys_stat(\"/mnt\")=%ld mode=%o\n", ret, + stat.st_mode); + + if (ret == 0 && stat.st_mode == (access_rights | LKL_S_IFDIR)) + return TEST_SUCCESS; + + return TEST_FAILURE; +} + +static int lkl_test_pipe2(void) +{ + int pipe_fds[2]; + int READ_IDX = 0, WRITE_IDX = 1; + static const char msg[] = "Hello world!"; + char str[20]; + int msg_len_bytes = strlen(msg) + 1; + int cmp_res; + long ret; + + ret = lkl_sys_pipe2(pipe_fds, LKL_O_NONBLOCK); + if (ret) { + lkl_test_logf("pipe2: %s\n", lkl_strerror(ret)); + return TEST_FAILURE; + } + + ret = lkl_sys_write(pipe_fds[WRITE_IDX], msg, msg_len_bytes); + if (ret != msg_len_bytes) { + if (ret < 0) + lkl_test_logf("write error: %s\n", lkl_strerror(ret)); + else + lkl_test_logf("short write: %ld\n", ret); + return TEST_FAILURE; + } + + ret = lkl_sys_read(pipe_fds[READ_IDX], str, msg_len_bytes); + if (ret != msg_len_bytes) { + if (ret < 0) + lkl_test_logf("read error: %s\n", lkl_strerror(ret)); + else + lkl_test_logf("short read: %ld\n", ret); + return TEST_FAILURE; + } + + cmp_res = memcmp(msg, str, msg_len_bytes); + if (cmp_res) { + lkl_test_logf("memcmp failed: %d\n", cmp_res); + return TEST_FAILURE; + } + + ret = lkl_sys_close(pipe_fds[0]); + if (ret) { + lkl_test_logf("close error: %s\n", lkl_strerror(ret)); + return TEST_FAILURE; + } + + ret = lkl_sys_close(pipe_fds[1]); + if (ret) { + lkl_test_logf("close error: %s\n", lkl_strerror(ret)); + return TEST_FAILURE; + } + + return TEST_SUCCESS; +} + +static int lkl_test_epoll(void) +{ + int epoll_fd, pipe_fds[2]; + int READ_IDX = 0, WRITE_IDX = 1; + struct lkl_epoll_event wait_on, read_result; + static const char msg[] = "Hello world!"; + long ret; + + memset(&wait_on, 0, sizeof(wait_on)); + memset(&read_result, 0, sizeof(read_result)); + + ret = lkl_sys_pipe2(pipe_fds, LKL_O_NONBLOCK); + if (ret) { + lkl_test_logf("pipe2 error: %s\n", lkl_strerror(ret)); + return TEST_FAILURE; + } + + epoll_fd = lkl_sys_epoll_create(1); + if (epoll_fd < 0) { + lkl_test_logf("epoll_create error: %s\n", lkl_strerror(ret)); + return TEST_FAILURE; + } + + wait_on.events = LKL_POLLIN | LKL_POLLOUT; + wait_on.data = pipe_fds[READ_IDX]; + + ret = lkl_sys_epoll_ctl(epoll_fd, LKL_EPOLL_CTL_ADD, pipe_fds[READ_IDX], + &wait_on); + if (ret < 0) { + lkl_test_logf("epoll_ctl error: %s\n", lkl_strerror(ret)); + return TEST_FAILURE; + } + + /* Shouldn't be ready before we have written something */ + ret = lkl_sys_epoll_wait(epoll_fd, &read_result, 1, 0); + if (ret != 0) { + if (ret < 0) + lkl_test_logf("epoll_wait error: %s\n", + lkl_strerror(ret)); + else + lkl_test_logf("epoll_wait: bad event: 0x%lx\n", ret); + return TEST_FAILURE; + } + + ret = lkl_sys_write(pipe_fds[WRITE_IDX], msg, strlen(msg) + 1); + if (ret < 0) { + lkl_test_logf("write error: %s\n", lkl_strerror(ret)); + return TEST_FAILURE; + } + + /* We expect exactly 1 fd to be ready immediately */ + ret = lkl_sys_epoll_wait(epoll_fd, &read_result, 1, 0); + if (ret != 1) { + if (ret < 0) + lkl_test_logf("epoll_wait error: %s\n", + lkl_strerror(ret)); + else + lkl_test_logf("epoll_wait: bad ev no %ld\n", ret); + return TEST_FAILURE; + } + + /* Already tested reading from pipe2 so no need to do it + * here + */ + + return TEST_SUCCESS; +} + +LKL_TEST_CALL(chdir_proc, lkl_sys_chdir, 0, "proc"); + +static int dir_fd; + +static int lkl_test_open_cwd(void) +{ + dir_fd = lkl_sys_open(".", LKL_O_RDONLY | LKL_O_DIRECTORY, 0); + if (dir_fd < 0) { + lkl_test_logf("failed to open current directory: %s\n", + lkl_strerror(dir_fd)); + return TEST_FAILURE; + } + + return TEST_SUCCESS; +} + +/* column where to insert a line break for the list file tests below. */ +#define COL_LINE_BREAK 70 + +static int lkl_test_getdents64(void) +{ + long ret; + char buf[1024], *pos; + struct lkl_linux_dirent64 *de; + int wr; + + de = (struct lkl_linux_dirent64 *)buf; + ret = lkl_sys_getdents64(dir_fd, de, sizeof(buf)); + + wr = lkl_test_logf("%d ", dir_fd); + + if (ret < 0) + return TEST_FAILURE; + + for (pos = buf; pos - buf < ret; pos += de->d_reclen) { + de = (struct lkl_linux_dirent64 *)pos; + + wr += lkl_test_logf("%s ", de->d_name); + if (wr >= COL_LINE_BREAK) { + lkl_test_logf("\n"); + wr = 0; + } + } + + return TEST_SUCCESS; +} + +LKL_TEST_CALL(close_dir_fd, lkl_sys_close, 0, dir_fd); +LKL_TEST_CALL(chdir_root, lkl_sys_chdir, 0, "/"); +LKL_TEST_CALL(mount_fs_proc, lkl_mount_fs, 0, "proc"); +LKL_TEST_CALL(umount_fs_proc, lkl_umount_timeout, 0, "proc", 0, 1000); +LKL_TEST_CALL(lo_ifup, lkl_if_up, 0, 1); + +static int lkl_test_mutex(void) +{ + long ret = TEST_SUCCESS; + /* + * Can't do much to verify that this works, so we'll just let Valgrind + * warn us on CI if we've made bad memory accesses. + */ + + struct lkl_mutex *mutex; + + mutex = lkl_host_ops.mutex_alloc(0); + lkl_host_ops.mutex_lock(mutex); + lkl_host_ops.mutex_unlock(mutex); + lkl_host_ops.mutex_free(mutex); + + mutex = lkl_host_ops.mutex_alloc(1); + lkl_host_ops.mutex_lock(mutex); + lkl_host_ops.mutex_lock(mutex); + lkl_host_ops.mutex_unlock(mutex); + lkl_host_ops.mutex_unlock(mutex); + lkl_host_ops.mutex_free(mutex); + + return ret; +} + +static int lkl_test_semaphore(void) +{ + long ret = TEST_SUCCESS; + /* + * Can't do much to verify that this works, so we'll just let Valgrind + * warn us on CI if we've made bad memory accesses. + */ + + struct lkl_sem *sem = lkl_host_ops.sem_alloc(1); + + lkl_host_ops.sem_down(sem); + lkl_host_ops.sem_up(sem); + lkl_host_ops.sem_free(sem); + + return ret; +} + +static int lkl_test_gettid(void) +{ + long tid = lkl_host_ops.gettid(); + + lkl_test_logf("%ld", tid); + + /* As far as I know, thread IDs are non-zero on all reasonable + * systems. + */ + if (tid) + return TEST_SUCCESS; + else + return TEST_FAILURE; +} + +static void test_thread(void *data) +{ + int *pipe_fds = (int *) data; + char tmp[LKL_PIPE_BUF+1]; + int ret; + + ret = lkl_sys_read(pipe_fds[0], tmp, sizeof(tmp)); + if (ret < 0) + lkl_test_logf("%s: %s\n", __func__, lkl_strerror(ret)); +} + +static int lkl_test_syscall_thread(void) +{ + int pipe_fds[2]; + char tmp[LKL_PIPE_BUF+1]; + long ret; + lkl_thread_t tid; + + ret = lkl_sys_pipe2(pipe_fds, 0); + if (ret) { + lkl_test_logf("pipe2: %s\n", lkl_strerror(ret)); + return TEST_FAILURE; + } + + ret = lkl_sys_fcntl(pipe_fds[0], LKL_F_SETPIPE_SZ, 1); + if (ret < 0) { + lkl_test_logf("fcntl setpipe_sz: %s\n", lkl_strerror(ret)); + return TEST_FAILURE; + } + + tid = lkl_host_ops.thread_create(test_thread, pipe_fds); + if (!tid) { + lkl_test_logf("failed to create thread\n"); + return TEST_FAILURE; + } + + ret = lkl_sys_write(pipe_fds[1], tmp, sizeof(tmp)); + if (ret != sizeof(tmp)) { + if (ret < 0) + lkl_test_logf("write error: %s\n", lkl_strerror(ret)); + else + lkl_test_logf("short write: %ld\n", ret); + return TEST_FAILURE; + } + + ret = lkl_host_ops.thread_join(tid); + if (ret) { + lkl_test_logf("failed to join thread\n"); + return TEST_FAILURE; + } + + return TEST_SUCCESS; +} + +#ifndef __MINGW32__ +static void thread_get_pid(void *unused) +{ + lkl_sys_getpid(); +} + +static int lkl_test_many_syscall_threads(void) +{ + lkl_thread_t tid; + int count = 65, ret; + + while (--count > 0) { + tid = lkl_host_ops.thread_create(thread_get_pid, NULL); + if (!tid) { + lkl_test_logf("failed to create thread\n"); + return TEST_FAILURE; + } + + ret = lkl_host_ops.thread_join(tid); + if (ret) { + lkl_test_logf("failed to join thread\n"); + return TEST_FAILURE; + } + } + + return TEST_SUCCESS; +} +#endif + +static void thread_quit_immediately(void *unused) +{ +} + +static int lkl_test_join(void) +{ + lkl_thread_t tid = lkl_host_ops.thread_create(thread_quit_immediately, + NULL); + int ret = lkl_host_ops.thread_join(tid); + + if (ret == 0) { + lkl_test_logf("joined %ld\n", tid); + return TEST_SUCCESS; + } + + lkl_test_logf("failed joining %ld\n", tid); + return TEST_FAILURE; +} + +LKL_TEST_CALL(start_kernel, lkl_start_kernel, 0, &lkl_host_ops, + "mem=16M loglevel=8"); +LKL_TEST_CALL(stop_kernel, lkl_sys_halt, 0); + +struct lkl_test tests[] = { + LKL_TEST(mutex), + LKL_TEST(semaphore), + LKL_TEST(join), + LKL_TEST(start_kernel), + LKL_TEST(getpid), + LKL_TEST(syscall_latency), + LKL_TEST(umask), + LKL_TEST(umask2), + LKL_TEST(creat), + LKL_TEST(close), + LKL_TEST(failopen), + LKL_TEST(open), + LKL_TEST(write), + LKL_TEST(lseek_cur), + LKL_TEST(lseek_end), + LKL_TEST(lseek_set), + LKL_TEST(read), + LKL_TEST(fstat), + LKL_TEST(mkdir), + LKL_TEST(stat), +#ifndef __MINGW32__ + LKL_TEST(nanosleep), +#endif + LKL_TEST(pipe2), + LKL_TEST(epoll), + LKL_TEST(mount_fs_proc), + LKL_TEST(chdir_proc), + LKL_TEST(open_cwd), + LKL_TEST(getdents64), + LKL_TEST(close_dir_fd), + LKL_TEST(chdir_root), + LKL_TEST(umount_fs_proc), + LKL_TEST(lo_ifup), + LKL_TEST(gettid), + LKL_TEST(syscall_thread), + /* + * Wine has an issue where the FlsCallback is not called when + * the thread terminates which makes testing the automatic + * syscall threads cleanup impossible under wine. + */ +#ifndef __MINGW32__ + LKL_TEST(many_syscall_threads), +#endif + LKL_TEST(stop_kernel), +}; + +int main(int argc, const char **argv) +{ + lkl_host_ops.print = lkl_test_log; + + return lkl_test_run(tests, sizeof(tests)/sizeof(struct lkl_test), + "boot"); +} diff --git a/tools/lkl/tests/boot.sh b/tools/lkl/tests/boot.sh new file mode 100755 index 000000000000..d985c04b0ac1 --- /dev/null +++ b/tools/lkl/tests/boot.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: GPL-2.0 + +script_dir=$(cd $(dirname ${BASH_SOURCE:-$0}); pwd) +source $script_dir/test.sh + +lkl_test_plan 1 "boot" +lkl_test_run 1 +lkl_test_exec $script_dir/boot diff --git a/tools/lkl/tests/cla.c b/tools/lkl/tests/cla.c new file mode 100644 index 000000000000..a34badeb5f06 --- /dev/null +++ b/tools/lkl/tests/cla.c @@ -0,0 +1,159 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#ifdef __MINGW32__ +#include +#else +#include +#include +#include +#endif + +#include "cla.h" + +static int cl_arg_parse_bool(struct cl_arg *arg, const char *value) +{ + *((int *)arg->store) = 1; + return 0; +} + +static int cl_arg_parse_str(struct cl_arg *arg, const char *value) +{ + *((const char **)arg->store) = value; + return 0; +} + +static int cl_arg_parse_int(struct cl_arg *arg, const char *value) +{ + errno = 0; + *((int *)arg->store) = strtol(value, NULL, 0); + return errno == 0; +} + +static int cl_arg_parse_str_set(struct cl_arg *arg, const char *value) +{ + const char **set = arg->set; + int i; + + for (i = 0; set[i] != NULL; i++) { + if (strcmp(set[i], value) == 0) { + *((int *)arg->store) = i; + return 0; + } + } + + return -1; +} + +static int cl_arg_parse_ipv4(struct cl_arg *arg, const char *value) +{ + unsigned int addr; + + if (!value) + return -1; + + addr = inet_addr(value); + if (addr == INADDR_NONE) + return -1; + *((unsigned int *)arg->store) = addr; + return 0; +} + +static cl_arg_parser_t parsers[] = { + [CL_ARG_BOOL] = cl_arg_parse_bool, + [CL_ARG_INT] = cl_arg_parse_int, + [CL_ARG_STR] = cl_arg_parse_str, + [CL_ARG_STR_SET] = cl_arg_parse_str_set, + [CL_ARG_IPV4] = cl_arg_parse_ipv4, +}; + +static struct cl_arg *find_short_arg(char name, struct cl_arg *args) +{ + struct cl_arg *arg; + + for (arg = args; arg->short_name != 0; arg++) { + if (arg->short_name == name) + return arg; + } + + return NULL; +} + +static struct cl_arg *find_long_arg(const char *name, struct cl_arg *args) +{ + struct cl_arg *arg; + + for (arg = args; arg->long_name; arg++) { + if (strcmp(arg->long_name, name) == 0) + return arg; + } + + return NULL; +} + +static void print_help(struct cl_arg *args) +{ + struct cl_arg *arg; + + fprintf(stderr, "usage:\n"); + for (arg = args; arg->long_name; arg++) { + fprintf(stderr, "-%c, --%-20s %s", arg->short_name, + arg->long_name, arg->help); + if (arg->type == CL_ARG_STR_SET) { + const char **set = arg->set; + + fprintf(stderr, " [ "); + while (*set != NULL) + fprintf(stderr, "%s ", *(set++)); + fprintf(stderr, "]"); + } + fprintf(stderr, "\n"); + } +} + +int parse_args(int argc, const char **argv, struct cl_arg *args) +{ + int i; + + for (i = 1; i < argc; i++) { + struct cl_arg *arg = NULL; + cl_arg_parser_t parser; + + if (argv[i][0] == '-') { + if (argv[i][1] != '-') + arg = find_short_arg(argv[i][1], args); + else + arg = find_long_arg(&argv[i][2], args); + } + + if (!arg) { + fprintf(stderr, "unknown option '%s'\n", argv[i]); + print_help(args); + return -1; + } + + if (arg->type == CL_ARG_USER || arg->type >= CL_ARG_END) + parser = arg->parser; + else + parser = parsers[arg->type]; + + if (!parser) { + fprintf(stderr, "can't parse --'%s'/-'%c'\n", + arg->long_name, args->short_name); + return -1; + } + + if (parser(arg, argv[i + 1]) < 0) { + fprintf(stderr, "can't parse '%s'\n", argv[i]); + print_help(args); + return -1; + } + + if (arg->has_arg) + i++; + } + + return 0; +} diff --git a/tools/lkl/tests/cla.h b/tools/lkl/tests/cla.h new file mode 100644 index 000000000000..f8369be02e5a --- /dev/null +++ b/tools/lkl/tests/cla.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LKL_TEST_CLA_H +#define _LKL_TEST_CLA_H + +enum cl_arg_type { + CL_ARG_USER = 0, + CL_ARG_BOOL, + CL_ARG_INT, + CL_ARG_STR, + CL_ARG_STR_SET, + CL_ARG_IPV4, + CL_ARG_END, +}; + +struct cl_arg; + +typedef int (*cl_arg_parser_t)(struct cl_arg *arg, const char *value); + +struct cl_arg { + const char *long_name; + char short_name; + const char *help; + int has_arg; + enum cl_arg_type type; + void *store; + void *set; + cl_arg_parser_t parser; +}; + +int parse_args(int argc, const char **argv, struct cl_arg *args); + + +#endif /* _LKL_TEST_CLA_H */ diff --git a/tools/lkl/tests/disk.c b/tools/lkl/tests/disk.c new file mode 100644 index 000000000000..0aa039876b54 --- /dev/null +++ b/tools/lkl/tests/disk.c @@ -0,0 +1,189 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef __MINGW32__ +#include +#include +#include +#else +#include +#endif + +#include "test.h" +#include "cla.h" + +static struct { + int printk; + const char *disk; + const char *fstype; + int partition; +} cla; + +struct cl_arg args[] = { + {"disk", 'd', "disk file to use", 1, CL_ARG_STR, &cla.disk}, + {"partition", 'P', "partition to mount", 1, CL_ARG_INT, &cla.partition}, + {"type", 't', "filesystem type", 1, CL_ARG_STR, &cla.fstype}, + {0}, +}; + + +static struct lkl_disk disk; +static int disk_id = -1; + +int lkl_test_disk_add(void) +{ +#ifdef __MINGW32__ + disk.handle = CreateFile(cla.disk, GENERIC_READ | GENERIC_WRITE, + 0, NULL, OPEN_EXISTING, 0, NULL); + if (!disk.handle) +#else + disk.fd = open(cla.disk, O_RDWR); + if (disk.fd < 0) +#endif + goto out_unlink; + + disk.ops = NULL; + + disk_id = lkl_disk_add(&disk); + if (disk_id < 0) + goto out_close; + + goto out; + +out_close: +#ifdef __MINGW32__ + CloseHandle(disk.handle); +#else + close(disk.fd); +#endif + +out_unlink: +#ifdef __MINGW32__ + DeleteFile(cla.disk); +#else + unlink(cla.disk); +#endif + +out: + lkl_test_logf("disk fd/handle %x disk_id %d", disk.fd, disk_id); + + if (disk_id >= 0) + return TEST_SUCCESS; + + return TEST_FAILURE; +} + +int lkl_test_disk_remove(void) +{ + int ret; + + ret = lkl_disk_remove(disk); + +#ifdef __MINGW32__ + CloseHandle(disk.handle); +#else + close(disk.fd); +#endif + + if (ret == 0) + return TEST_SUCCESS; + + return TEST_FAILURE; +} + + +static char mnt_point[32]; + +LKL_TEST_CALL(mount_dev, lkl_mount_dev, 0, disk_id, cla.partition, cla.fstype, + 0, NULL, mnt_point, sizeof(mnt_point)) + +static int lkl_test_umount_dev(void) +{ + long ret, ret2; + + ret = lkl_sys_chdir("/"); + + ret2 = lkl_umount_dev(disk_id, cla.partition, 0, 1000); + + lkl_test_logf("%ld %ld", ret, ret2); + + if (!ret && !ret2) + return TEST_SUCCESS; + + return TEST_FAILURE; +} + +struct lkl_dir *dir; + +static int lkl_test_opendir(void) +{ + int err; + + dir = lkl_opendir(mnt_point, &err); + + lkl_test_logf("lkl_opedir(%s) = %d %s\n", mnt_point, err, + lkl_strerror(err)); + + if (err == 0) + return TEST_SUCCESS; + + return TEST_FAILURE; +} + +static int lkl_test_readdir(void) +{ + struct lkl_linux_dirent64 *de = lkl_readdir(dir); + int wr = 0; + + while (de) { + wr += lkl_test_logf("%s ", de->d_name); + if (wr >= 70) { + lkl_test_logf("\n"); + wr = 0; + break; + } + de = lkl_readdir(dir); + } + + if (lkl_errdir(dir) == 0) + return TEST_SUCCESS; + + return TEST_FAILURE; +} + +LKL_TEST_CALL(closedir, lkl_closedir, 0, dir); +LKL_TEST_CALL(chdir_mnt_point, lkl_sys_chdir, 0, mnt_point); +LKL_TEST_CALL(start_kernel, lkl_start_kernel, 0, &lkl_host_ops, + "mem=16M loglevel=8"); +LKL_TEST_CALL(stop_kernel, lkl_sys_halt, 0); + +struct lkl_test tests[] = { + LKL_TEST(disk_add), + LKL_TEST(start_kernel), + LKL_TEST(mount_dev), + LKL_TEST(chdir_mnt_point), + LKL_TEST(opendir), + LKL_TEST(readdir), + LKL_TEST(closedir), + LKL_TEST(umount_dev), + LKL_TEST(stop_kernel), + LKL_TEST(disk_remove), + +}; + +int main(int argc, const char **argv) +{ + if (parse_args(argc, argv, args) < 0) + return -1; + + lkl_host_ops.print = lkl_test_log; + + return lkl_test_run(tests, sizeof(tests)/sizeof(struct lkl_test), + "disk %s", cla.fstype); +} diff --git a/tools/lkl/tests/disk.sh b/tools/lkl/tests/disk.sh new file mode 100755 index 000000000000..9bdcb16f2d5c --- /dev/null +++ b/tools/lkl/tests/disk.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: GPL-2.0 + +script_dir=$(cd $(dirname ${BASH_SOURCE:-$0}); pwd) + +source $script_dir/test.sh + +function prepfs() +{ + set -e + + file=`mktemp` + + dd if=/dev/zero of=$file bs=1024 count=204800 + + yes | mkfs.$1 $file + + if ! [ -z $BSD_WDIR ]; then + $MYSSH mkdir -p $BSD_WDIR + ssh_copy $file $BSD_WDIR + rm $file + file=$BSD_WDIR/$(basename $file) + fi + + export_vars file +} + +function cleanfs() +{ + set -e + + if ! [ -z $BSD_WDIR ]; then + $MYSSH rm $1 + $MYSSH rm $BSD_WDIR/disk + else + rm $1 + fi +} + +if [ "$1" = "-t" ]; then + shift + fstype=$1 + shift +fi + +if [ -z "$fstype" ]; then + fstype="ext4" +fi + +if [ -z $(which mkfs.$fstype) ]; then + lkl_test_plan 0 "disk $fstype" + echo "no mkfs.$fstype command" + exit 0 +fi + +lkl_test_plan 1 "disk $fstype" +lkl_test_run 1 prepfs $fstype +lkl_test_exec $script_dir/disk -d $file -t $fstype $@ +lkl_test_plan 1 "disk $fstype" +lkl_test_run 1 cleanfs $file + diff --git a/tools/lkl/tests/net-setup.sh b/tools/lkl/tests/net-setup.sh new file mode 100644 index 000000000000..0cfc42a30a54 --- /dev/null +++ b/tools/lkl/tests/net-setup.sh @@ -0,0 +1,73 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: GPL-2.0 + +TEST_IP_NETWORK=192.168.113.0 +TEST_IP_NETMASK=24 +TEST_IP6_NETWORK=fc03::0 +TEST_IP6_NETMASK=64 +TEST_MAC0="aa:bb:cc:dd:ee:ff" +TEST_MAC1="aa:bb:cc:dd:ee:aa" +TEST_NETSERVER_PORT=11223 + +# $1 - count +# $2 - netcount +ip_add() +{ + IP_HEX=$(printf '%.2X%.2X%.2X%.2X\n' \ + `echo $TEST_IP_NETWORK | sed -e 's/\./ /g'`) + NET_COUNT=$(( 1 << (32 - $TEST_IP_NETMASK) )) + NEXT_IP_HEX=$(printf %.8X `echo $((0x$IP_HEX + $1 + ${2:-0} * $NET_COUNT))`) + NEXT_IP=$(printf '%d.%d.%d.%d\n' \ + `echo $NEXT_IP_HEX | sed -r 's/(..)/0x\1 /g'`) + echo -n "$NEXT_IP" +} + +# $1 - count +# $2 - netcount +ip6_add() +{ + IP6_PREFIX=${TEST_IP6_NETWORK%*::*} + IP6_HOST=${TEST_IP6_NETWORK#*::*} + echo -n "$(printf "%x" $((0x$IP6_PREFIX+${2:-0})))::$(($IP6_HOST+$1))" +} + +ip_host() +{ + + ip_add 1 $1 +} + +ip_lkl() +{ + ip_add 2 $1 +} + +ip_host_mask() +{ + echo -n "$(ip_host $1)/$TEST_IP_NETMASK" +} + +ip_net_mask() +{ + echo "$(ip_add 0 $1)/$TEST_IP_NETMASK" +} + +ip6_host() +{ + ip6_add 1 $1 +} + +ip6_lkl() +{ + ip6_add 2 $1 +} + +ip6_host_mask() +{ + echo -n "$(ip6_host $1)/$TEST_IP6_NETMASK" +} + +ip6_net_mask() +{ + echo "$(ip6_add 0 $1)/$TEST_IP6_NETMASK" +} diff --git a/tools/lkl/tests/net-test.c b/tools/lkl/tests/net-test.c new file mode 100644 index 000000000000..5a8e39a52417 --- /dev/null +++ b/tools/lkl/tests/net-test.c @@ -0,0 +1,299 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#ifdef __FreeBSD__ +#include +#endif +#ifdef __MINGW32__ +#include +#else +#include +#include +#include +#endif + +#include +#include + +#include "cla.h" +#include "test.h" + +enum { + BACKEND_NONE, +}; + +const char *backends[] = { "loopback", NULL }; +static struct { + int backend; + const char *ifname; + int dhcp, nmlen; + unsigned int ip, dst, gateway, sleep; +} cla = { + .backend = BACKEND_NONE, + .ip = INADDR_NONE, + .gateway = INADDR_NONE, + .dst = INADDR_NONE, + .sleep = 0, +}; + + +struct cl_arg args[] = { + {"backend", 'b', "network backend type", 1, CL_ARG_STR_SET, + &cla.backend, backends}, + {"ifname", 'i', "interface name", 1, CL_ARG_STR, &cla.ifname}, + {"dhcp", 'd', "use dhcp to configure LKL", 0, CL_ARG_BOOL, &cla.dhcp}, + {"ip", 'I', "IPv4 address to use", 1, CL_ARG_IPV4, &cla.ip}, + {"netmask-len", 'n', "IPv4 netmask length", 1, CL_ARG_INT, + &cla.nmlen}, + {"gateway", 'g', "IPv4 gateway to use", 1, CL_ARG_IPV4, &cla.gateway}, + {"dst", 'D', "IPv4 destination address", 1, CL_ARG_IPV4, &cla.dst}, + {"sleep", 's', "sleep", 1, CL_ARG_INT, &cla.sleep}, + {0}, +}; + +u_short +in_cksum(const u_short *addr, register int len, u_short csum) +{ + int nleft = len; + const u_short *w = addr; + u_short answer; + int sum = csum; + + while (nleft > 1) { + sum += *w++; + nleft -= 2; + } + + if (nleft == 1) + sum += htons(*(u_char *)w << 8); + + sum = (sum >> 16) + (sum & 0xffff); + sum += (sum >> 16); + answer = ~sum; + return answer; +} + +static int lkl_test_sleep(void) +{ + struct lkl_timespec ts = { + .tv_sec = cla.sleep, + }; + int ret; + + ret = lkl_sys_nanosleep((struct __lkl__kernel_timespec *)&ts, NULL); + if (ret < 0) { + lkl_test_logf("nanosleep error: %s\n", lkl_strerror(ret)); + return TEST_FAILURE; + } + + return TEST_SUCCESS; +} + +static int lkl_test_icmp(void) +{ + int sock, ret; + struct lkl_iphdr *iph; + struct lkl_icmphdr *icmp; + struct lkl_sockaddr_in saddr; + struct lkl_pollfd pfd; + char buf[32]; + + if (cla.dst == INADDR_NONE) + return TEST_SKIP; + + memset(&saddr, 0, sizeof(saddr)); + saddr.sin_family = AF_INET; + saddr.sin_addr.lkl_s_addr = cla.dst; + + lkl_test_logf("pinging %s\n", + inet_ntoa(*(struct in_addr *)&saddr.sin_addr)); + + sock = lkl_sys_socket(LKL_AF_INET, LKL_SOCK_RAW, LKL_IPPROTO_ICMP); + if (sock < 0) { + lkl_test_logf("socket error (%s)\n", lkl_strerror(sock)); + return TEST_FAILURE; + } + + icmp = malloc(sizeof(struct lkl_icmphdr)); + icmp->type = LKL_ICMP_ECHO; + icmp->code = 0; + icmp->checksum = 0; + icmp->un.echo.sequence = 0; + icmp->un.echo.id = 0; + icmp->checksum = in_cksum((u_short *)icmp, sizeof(*icmp), 0); + + ret = lkl_sys_sendto(sock, icmp, sizeof(*icmp), 0, + (struct lkl_sockaddr *)&saddr, + sizeof(saddr)); + if (ret < 0) { + lkl_test_logf("sendto error (%s)\n", lkl_strerror(ret)); + return TEST_FAILURE; + } + + free(icmp); + + pfd.fd = sock; + pfd.events = LKL_POLLIN; + pfd.revents = 0; + + ret = lkl_sys_poll(&pfd, 1, 1000); + if (ret < 0) { + lkl_test_logf("poll error (%s)\n", lkl_strerror(ret)); + return TEST_FAILURE; + } + + ret = lkl_sys_recv(sock, buf, sizeof(buf), LKL_MSG_DONTWAIT); + if (ret < 0) { + lkl_test_logf("recv error (%s)\n", lkl_strerror(ret)); + return TEST_FAILURE; + } + + if (ret < (int)sizeof(struct lkl_iphdr)) { + lkl_test_logf("short length of received ip packet (len=%d)\n", + ret); + return TEST_FAILURE; + } + iph = (struct lkl_iphdr *)buf; + + if (ret < (int)((iph->ihl * 4) + sizeof(struct lkl_icmphdr))) { + lkl_test_logf("short length of received icmp packet (len=%d)\n", + ret); + return TEST_FAILURE; + } + icmp = (struct lkl_icmphdr *)(buf + iph->ihl * 4); + + /* DHCP server may issue an ICMP echo request to a dhcp client */ + if ((icmp->type != LKL_ICMP_ECHOREPLY || icmp->code != 0) && + (icmp->type != LKL_ICMP_ECHO)) { + lkl_test_logf("no ICMP echo reply (type=%d, code=%d)\n", + icmp->type, icmp->code); + return TEST_FAILURE; + } + + return TEST_SUCCESS; +} + +static struct lkl_netdev *nd; + +static int lkl_test_nd_create(void) +{ + switch (cla.backend) { + case BACKEND_NONE: + return TEST_SKIP; + } + + if (!nd) { + lkl_test_logf("failed to create netdev\n"); + return TEST_BAILOUT; + } + + return TEST_SUCCESS; +} + +static int nd_id; + +static int lkl_test_nd_add(void) +{ + if (cla.backend == BACKEND_NONE) + return TEST_SKIP; + + return TEST_SUCCESS; +} + +static int lkl_test_nd_remove(void) +{ + if (cla.backend == BACKEND_NONE) + return TEST_SKIP; + + return TEST_SUCCESS; +} + +LKL_TEST_CALL(start_kernel, lkl_start_kernel, 0, &lkl_host_ops, + "mem=16M loglevel=8 %s", cla.dhcp ? "ip=dhcp" : ""); +LKL_TEST_CALL(stop_kernel, lkl_sys_halt, 0); + +static int nd_ifindex; + +static int lkl_test_nd_ifindex(void) +{ + if (cla.backend == BACKEND_NONE) + return TEST_SKIP; + + nd_ifindex = lkl_netdev_get_ifindex(nd_id); + if (nd_ifindex < 0) { + lkl_test_logf("failed to get ifindex for netdev id %d: %s\n", + nd_id, lkl_strerror(nd_ifindex)); + return TEST_BAILOUT; + } + + return TEST_SUCCESS; +} + +LKL_TEST_CALL(if_up, lkl_if_up, 0, + cla.backend == BACKEND_NONE ? 1 : nd_ifindex); + +static int lkl_test_set_ipv4(void) +{ + int ret; + + if (cla.backend == BACKEND_NONE || cla.ip == LKL_INADDR_NONE) + return TEST_SKIP; + + ret = lkl_if_set_ipv4(nd_ifindex, cla.ip, cla.nmlen); + if (ret < 0) { + lkl_test_logf("failed to set IPv4 address: %s\n", + lkl_strerror(ret)); + return TEST_BAILOUT; + } + + return TEST_SUCCESS; +} + +static int lkl_test_set_gateway(void) +{ + int ret; + + if (cla.backend == BACKEND_NONE || cla.gateway == LKL_INADDR_NONE) + return TEST_SKIP; + + ret = lkl_set_ipv4_gateway(cla.gateway); + if (ret < 0) { + lkl_test_logf("failed to set IPv4 gateway: %s\n", + lkl_strerror(ret)); + return TEST_BAILOUT; + } + + return TEST_SUCCESS; +} + +struct lkl_test tests[] = { + LKL_TEST(nd_create), + LKL_TEST(nd_add), + LKL_TEST(start_kernel), + LKL_TEST(nd_ifindex), + LKL_TEST(if_up), + LKL_TEST(set_ipv4), + LKL_TEST(set_gateway), + LKL_TEST(sleep), + LKL_TEST(icmp), + LKL_TEST(nd_remove), + LKL_TEST(stop_kernel), +}; + +int main(int argc, const char **argv) +{ + if (parse_args(argc, argv, args) < 0) + return -1; + + if (cla.ip != LKL_INADDR_NONE && (cla.nmlen < 0 || cla.nmlen > 32)) { + fprintf(stderr, "invalid netmask length %d\n", cla.nmlen); + return -1; + } + + lkl_host_ops.print = lkl_test_log; + + return lkl_test_run(tests, sizeof(tests)/sizeof(struct lkl_test), + "net %s", backends[cla.backend]); +} diff --git a/tools/lkl/tests/net.sh b/tools/lkl/tests/net.sh new file mode 100755 index 000000000000..32e8452b0406 --- /dev/null +++ b/tools/lkl/tests/net.sh @@ -0,0 +1,90 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: GPL-2.0 + +script_dir=$(cd $(dirname ${BASH_SOURCE:-$0}); pwd) + +source $script_dir/test.sh +source $script_dir/net-setup.sh + +cleanup_backend() +{ + set -e + + case "$1" in + "loopback") + ;; + esac +} + +get_test_ip() +{ + # DHCP test parameters + TEST_HOST=8.8.8.8 + HOST_IF=$(lkl_test_cmd ip route get $TEST_HOST | head -n1 |cut -d ' ' -f5) + HOST_GW=$(lkl_test_cmd ip route get $TEST_HOST | head -n1 | cut -d ' ' -f3) + if lkl_test_cmd ping -c1 -w1 $HOST_GW; then + TEST_IP_REMOTE=$HOST_GW + elif lkl_test_cmd ping -c1 -w1 $TEST_HOST; then + TEST_IP_REMOTE=$TEST_HOST + else + echo "could not find remote test ip" + return $TEST_SKIP + fi + + export_vars HOST_IF TEST_IP_REMOTE +} + +setup_backend() +{ + set -e + + if [ "$LKL_HOST_CONFIG_POSIX" != "y" ] && + [ "$1" != "loopback" ]; then + echo "not a posix environment" + return $TEST_SKIP + fi + + case "$1" in + "loopback") + ;; + *) + echo "don't know how to setup backend $1" + return $TEST_FAILED + ;; + esac +} + +run_tests() +{ + case "$1" in + "loopback") + lkl_test_exec $script_dir/net-test --dst 127.0.0.1 + ;; + esac +} + +if [ "$1" = "-b" ]; then + shift + backend=$1 + shift +fi + +if [ -z "$backend" ]; then + backend="loopback" +fi + +lkl_test_plan 1 "net $backend" +lkl_test_run 1 setup_backend $backend + +if [ $? = $TEST_SKIP ]; then + exit 0 +fi + +trap "cleanup_backend $backend" EXIT + +run_tests $backend + +trap : EXIT +lkl_test_plan 1 "net $backend" +lkl_test_run 1 cleanup_backend $backend + diff --git a/tools/lkl/tests/run.py b/tools/lkl/tests/run.py new file mode 100755 index 000000000000..b72299aaabee --- /dev/null +++ b/tools/lkl/tests/run.py @@ -0,0 +1,179 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: GPL-2.0 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License +# +# Author: Octavian Purdila +# + +from __future__ import print_function + +import argparse +import os +import subprocess +import sys +import tap13 +import xml.etree.ElementTree as ET + +from junit_xml import TestSuite, TestCase + + +class Reporter(tap13.Reporter): + def start(self, obj): + if type(obj) is tap13.Test: + if obj.result == "*": + end='\r' + else: + end='\n' + print(" TEST %-8s %.50s" % + (obj.result, obj.description + " " + obj.comment), end=end) + + elif type(obj) is tap13.Suite: + if obj.tests_planned == 0: + status = "skip" + else: + status = "" + print(" SUITE %-8s %s" % (status, obj.name)) + + def end(self, obj): + if type(obj) is tap13.Test: + if obj.result != "ok": + try: + print(obj.yaml["log"], end='') + except: + None + + +mydir=os.path.dirname(os.path.realpath(__file__)) + +tests = [ + 'boot.sh', + 'disk.sh -t ext4', + 'disk.sh -t vfat', + 'disk.sh -t btrfs', + 'net.sh -b loopback', + 'lklfuse.sh -t ext4', + 'lklfuse.sh -t vfat', + 'lklfuse.sh -t btrfs', +] + +parser = argparse.ArgumentParser(description='LKL test runner') +parser.add_argument('tests', nargs='?', action='append', + help='tests to run %s' % tests) +parser.add_argument('--junit-dir', + help='directory where to store the juni suites') +parser.add_argument('--gdb', action='store_true', default=False, + help='run simple tests under gdb; implies --pass-through') +parser.add_argument('--pass-through', action='store_true', default=False, + help='run the test without interpeting the test output') +parser.add_argument('--valgrind', action='store_true', default=False, + help='run simple tests under valgrind') + +args = parser.parse_args() +if args.tests == [None]: + args.tests = tests + +if args.gdb: + args.pass_through=True + os.environ['GDB']="yes" + +if args.valgrind: + os.environ['VALGRIND']="yes" + +tap = tap13.Parser(Reporter()) + +os.environ['PATH'] += ":" + mydir + +exit_code = 0 + +for t in args.tests: + if not t: + continue + if args.pass_through: + print(t) + if subprocess.call(t, shell=True) != 0: + exit_code = 1 + else: + p = subprocess.Popen(t, shell=True, stdout=subprocess.PIPE) + tap.parse(p.stdout) + +if args.pass_through: + sys.exit(exit_code) + +suites_count = 0 +tests_total = 0 +tests_not_ok = 0 +tests_ok = 0 +tests_skip = 0 +val_errs = 0 +val_fails = 0 +val_skips = 0 + +for s in tap.run.suites: + + junit_tests = [] + suites_count += 1 + + for t in s.tests: + try: + secs = t.yaml["time_us"] / 1000000.0 + except: + secs = 0 + try: + log = t.yaml['log'] + except: + log = "" + + jt = TestCase(t.description, elapsed_sec=secs, stdout=log) + if t.result == 'skip': + jt.add_skipped_info(output=log) + elif t.result == 'not ok': + jt.add_error_info(output=log) + + junit_tests.append(jt) + + tests_total += 1 + if t.result == "ok": + tests_ok += 1 + elif t.result == "not ok": + tests_not_ok += 1 + exit_code = 1 + elif t.result == "skip": + tests_skip += 1 + + if args.junit_dir: + js = TestSuite(s.name, junit_tests) + with open(os.path.join(args.junit_dir, os.path.basename(s.name) + '.xml'), 'w') as f: + js.to_file(f, [js]) + + if os.getenv('VALGRIND') is not None: + val_xml = 'valgrind-%s.xml' % os.path.basename(s.name).replace(' ','-') + # skipped tests don't generate xml file + if os.path.exists(val_xml) is False: + continue + + cmd = 'mv %s %s' % (val_xml, args.junit_dir) + subprocess.call(cmd, shell=True, ) + + cmd = mydir + '/valgrind2xunit.py ' + val_xml + subprocess.call(cmd, shell=True, cwd=args.junit_dir) + + # count valgrind results + doc = ET.parse(os.path.join(args.junit_dir, 'valgrind-%s_xunit.xml' \ + % (os.path.basename(s.name).replace(' ','-')))) + ts = doc.getroot() + val_errs += int(ts.get('errors')) + val_fails += int(ts.get('failures')) + val_skips += int(ts.get('skip')) + +print("Summary: %d suites run, %d tests, %d ok, %d not ok, %d skipped" % + (suites_count, tests_total, tests_ok, tests_not_ok, tests_skip)) + +if os.getenv('VALGRIND') is not None: + print(" valgrind (memcheck): %d failures, %d skipped" % (val_fails, val_skips)) + if val_errs or val_fails: + exit_code = 1 + +sys.exit(exit_code) diff --git a/tools/lkl/tests/tap13.py b/tools/lkl/tests/tap13.py new file mode 100644 index 000000000000..65c73cda7ca1 --- /dev/null +++ b/tools/lkl/tests/tap13.py @@ -0,0 +1,209 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: GPL-2.0 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License +# +# Author: Octavian Purdila +# +# Based on TAP13: +# +# Copyright 2013, Red Hat, Inc. +# Author: Josef Skladanka +# +from __future__ import print_function + +import re +import sys +import yamlish + + +class Reporter(object): + + def start(self, obj): + None + + def end(self, obj): + None + + +class Test(object): + def __init__(self, reporter, result, id, description=None, directive=None, + comment=None): + self.reporter = reporter + self.result = result + if directive: + self.result = directive.lower() + if id: + self.id = int(id) + else: + self.id = None + if description: + self.description = description + else: + self.description = "" + if comment: + self.comment = "# " + comment + else: + self.comment = "" + self.yaml = None + self._yaml_buffer = None + self.diagnostics = [] + + self.reporter.start(self) + + def end(self): + if not self.yaml: + self.yaml = yamlish.load(self._yaml_buffer) + self.reporter.end(self) + + +class Suite(object): + def __init__(self, reporter, start, end, explanation): + self.reporter = reporter + self.tests = [] + self.name = explanation + self.tests_planned = int(end) + + self.__tests_counter = 0 + self.__tests_base = 0 + + self.reporter.start(self) + + def newTest(self, args): + try: + self.tests[-1].end() + except IndexError: + None + + if 'id' not in args or not args['id']: + args['id'] = self.__tests_counter + else: + args['id'] = int(args['id']) + self.__tests_base + + if args['id'] < self.__tests_counter: + print("error: bad test id %d, fixing it" % (args['id'])) + args['id'] = self.__tests_counter + # according to TAP13 specs, missing tests must be handled as 'not ok' + # here we add the missing tests in sequence + while args['id'] > (self.__tests_counter + 1): + comment = 'test %d not present' % self.__tests_counter + self.tests.append(Test(self.reporter, 'not ok', + self.__tests_counter, comment=comment)) + self.__tests_counter += 1 + + if args['id'] == self.__tests_counter: + if args['directive']: + self.test().result = args['directive'].lower() + else: + self.test().result = args['result'] + self.reporter.start(self.test()) + else: + self.tests.append(Test(self.reporter, **args)) + self.__tests_counter += 1 + + def test(self): + return self.tests[-1] + + def end(self, name, planned): + if name == self.name: + self.tests_planned += int(planned) + self.__tests_base = self.__tests_counter + return False + try: + self.test().end() + except IndexError: + None + if len(self.tests) != self.tests_planned: + for i in range(len(self.tests), self.tests_planned): + self.tests.append(Test(self.reporter, 'not ok', i+1, + comment='test not present')) + return True + + +class Run(object): + + def __init__(self, reporter): + self.reporter = reporter + self.suites = [] + + def suite(self): + return self.suites[-1] + + def test(self): + return self.suites[-1].tests[-1] + + def newSuite(self, args): + new = False + try: + if self.suite().end(args['explanation'], args['end']): + new = True + except IndexError: + new = True + if new: + self.suites.append(Suite(self.reporter, **args)) + + def newTest(self, args): + self.suite().newTest(args) + + +class Parser(object): + RE_PLAN = re.compile(r"^\s*(?P\d+)\.\.(?P\d+)\s*(#\s*(?P.*))?\s*$") + RE_TEST_LINE = re.compile(r"^\s*(?P(not\s+)?ok|[*]+)\s*(?P\d+)?\s*(?P[^#]+)?\s*(#\s*(?PTODO|SKIP)?\s*(?P.+)?)?\s*$", re.IGNORECASE) + RE_EXPLANATION = re.compile(r"^\s*#\s*(?P.+)?\s*$") + RE_YAMLISH_START = re.compile(r"^\s*---.*$") + RE_YAMLISH_END = re.compile(r"^\s*\.\.\.\s*$") + + def __init__(self, reporter): + self.seek_test = False + self.in_test = False + self.in_yaml = False + self.run = Run(reporter) + + def parse(self, source): + # to avoid input buffering + while True: + line = source.readline() + if not line: + break + + if self.in_yaml: + if Parser.RE_YAMLISH_END.match(line): + self.run.test()._yaml_buffer.append(line.strip()) + self.in_yaml = False + else: + self.run.test()._yaml_buffer.append(line.rstrip()) + continue + + line = line.strip() + + if self.in_test: + if Parser.RE_EXPLANATION.match(line): + self.run.test().diagnostics.append(line) + continue + if Parser.RE_YAMLISH_START.match(line): + self.run.test()._yaml_buffer = [line.strip()] + self.in_yaml = True + continue + + m = Parser.RE_PLAN.match(line) + if m: + self.seek_test = True + args = m.groupdict() + self.run.newSuite(args) + continue + + if self.seek_test: + m = Parser.RE_TEST_LINE.match(line) + if m: + args = m.groupdict() + self.run.newTest(args) + self.in_test = True + continue + + print(line) + try: + self.run.suite().end(None, 0) + except IndexError: + None diff --git a/tools/lkl/tests/test.c b/tools/lkl/tests/test.c new file mode 100644 index 000000000000..3e334d106c48 --- /dev/null +++ b/tools/lkl/tests/test.c @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include + +#include "test.h" + +/* circular log buffer */ + +static char log_buf[0x10000]; +static char *head = log_buf, *tail = log_buf; + +static inline void advance(char **ptr) +{ + if ((unsigned int)(*ptr - log_buf) >= sizeof(log_buf)) + *ptr = log_buf; + else + *ptr = *ptr + 1; +} + +static void log_char(char c) +{ + *tail = c; + advance(&tail); + if (tail == head) + advance(&head); +} + +static void print_log(void) +{ + char last; + + printf(" log: |\n"); + last = '\n'; + while (head != tail) { + if (last == '\n') + printf(" "); + last = *head; + putchar(last); + advance(&head); + } + if (last != '\n') + putchar('\n'); +} + +int lkl_test_run(const struct lkl_test *tests, int nr, const char *fmt, ...) +{ + int i, ret, status = TEST_SUCCESS; + clock_t start, stop; + char name[1024]; + va_list args; + + va_start(args, fmt); + vsnprintf(name, sizeof(name), fmt, args); + va_end(args); + + printf("1..%d # %s\n", nr, name); + for (i = 1; i <= nr; i++) { + const struct lkl_test *t = &tests[i-1]; + unsigned long delta_us; + + printf("* %d %s\n", i, t->name); + fflush(stdout); + + start = clock(); + + ret = t->fn(t->arg1, t->arg2, t->arg3); + + stop = clock(); + + switch (ret) { + case TEST_SUCCESS: + printf("ok %d %s\n", i, t->name); + break; + case TEST_SKIP: + printf("ok %d %s # SKIP\n", i, t->name); + break; + case TEST_BAILOUT: + status = TEST_BAILOUT; + /* fall through */ + case TEST_FAILURE: + default: + if (status != TEST_BAILOUT) + status = TEST_FAILURE; + printf("not ok %d %s\n", i, t->name); + } + + printf(" ---\n"); + delta_us = (stop - start) * 1000000 / CLOCKS_PER_SEC; + printf(" time_us: %ld\n", delta_us); + print_log(); + printf(" ...\n"); + + if (status == TEST_BAILOUT) { + printf("Bail out!\n"); + return TEST_FAILURE; + } + + fflush(stdout); + } + + return status; +} + + +void lkl_test_log(const char *str, int len) +{ + while (len--) + log_char(*(str++)); +} + +int lkl_test_logf(const char *fmt, ...) +{ + char tmp[1024], *c; + va_list args; + unsigned int n; + + va_start(args, fmt); + n = vsnprintf(tmp, sizeof(tmp), fmt, args); + va_end(args); + + for (c = tmp; *c != 0; c++) + log_char(*c); + + return n > sizeof(tmp) ? sizeof(tmp) : n; +} diff --git a/tools/lkl/tests/test.h b/tools/lkl/tests/test.h new file mode 100644 index 000000000000..f63ad6d419cb --- /dev/null +++ b/tools/lkl/tests/test.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LKL_TEST_H +#define _LKL_TEST_H + +#define TEST_SUCCESS 0 +#define TEST_FAILURE 1 +#define TEST_SKIP 2 +#define TEST_TODO 3 +#define TEST_BAILOUT 4 + +struct lkl_test { + const char *name; + int (*fn)(); + void *arg1, *arg2, *arg3; +}; + +/** + * Simple wrapper to initialize a test entry. + * @name - test name, it assume test function is named test_@name + * @vargs - arguments to be passed to the function + */ +#define LKL_TEST(name, ...) { #name, lkl_test_##name, __VA_ARGS__ } + +/** + * lkl_test_run - run a test suite + * + * @tests - the list of tests to run + * @nr - number of tests + * @fmt - format string to be used for suite name + */ +int lkl_test_run(const struct lkl_test *tests, int nr, const char *fmt, ...); + +/** + * lkl_test_log - store a string in the test log buffer + * @str - the string to log (can be non-NULL terminated) + * @len - the string length + */ +void lkl_test_log(const char *str, int len); + +/** + * lkl_test_logf - printf like function to store into the test log buffer + * @fmt - printf format string + * @vargs - arguments to the format string + */ +int lkl_test_logf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); + +/** + * LKL_TEST_CALL - create a test function as for a LKL call + * + * The test function will be named lkl_test_@name and will return + * TEST_SUCCESS if the called functions returns @expect. Otherwise + * will return TEST_FAILUIRE. + * + * @name - test name; must be unique because it is part of the the + * test function; the test function will be named + * @call - function to call + * @expect - expected return value for success + * @args - arguments to pass to the LKL call + */ +#define LKL_TEST_CALL(name, call, expect, ...) \ + static int lkl_test_##name(void) \ + { \ + long ret; \ + \ + ret = call(__VA_ARGS__); \ + lkl_test_logf("%s(%s) = %ld %s\n", #call, #__VA_ARGS__, \ + ret, ret < 0 ? lkl_strerror(ret) : ""); \ + return (ret == expect) ? TEST_SUCCESS : TEST_FAILURE; \ + } + + +#endif /* _LKL_TEST_H */ diff --git a/tools/lkl/tests/test.sh b/tools/lkl/tests/test.sh new file mode 100644 index 000000000000..f4d652b9fbe8 --- /dev/null +++ b/tools/lkl/tests/test.sh @@ -0,0 +1,182 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: GPL-2.0 + +script_dir=$(cd $(dirname ${BASH_SOURCE:-$0}); pwd) +basedir=$(cd $script_dir/..; pwd) +base_objdir=$(cd ${OUTPUT}/; pwd) +source ${script_dir}/autoconf.sh + +TEST_SUCCESS=0 +TEST_FAILURE=1 +TEST_SKIP=113 +TEST_TODO=114 +TEST_BAILOUT=115 + +print_log() +{ + echo " log: |" + while read line; do + echo " $line" + done < $1 +} + +export_vars() +{ + if [ -z "$var_file" ]; then + return + fi + + for i in $@; do + echo "$i=${!i}" >> $var_file + done +} + +lkl_test_run() +{ + log_file=$(mktemp) + export var_file=$(mktemp) + + tid=$1 && shift && tname=$@ + + echo "* $tid $tname" + + start=$(date '+%s%9N') + # run in a separate shell to avoid -e terminating us + $@ 2>&1 | strings >$log_file + exit=${PIPESTATUS[0]} + stop=$(date '+%s%9N') + + case $exit in + $TEST_SUCCESS) + echo "ok $tid $tname" + ;; + $TEST_SKIP) + echo "ok $tid $tname # SKIP" + ;; + $TEST_BAILOUT) + echo "not ok $tid $tname" + echo "Bail out!" + ;; + $TEST_FAILURE|*) + echo "not ok $tid $tname" + ;; + esac + + delta=$(((stop-start)/1000)) + + echo " ---" + echo " time_us: $delta" + print_log $log_file + echo -e " ..." + + rm $log_file + . $var_file + rm $var_file + + return $exit +} + +lkl_test_plan() +{ + echo "1..$1 # $2" + export suite_name="${2// /\-}" +} + +lkl_test_exec() +{ + local SUDO="" + local WRAPPER="" + + if [ "$1" = "sudo" ]; then + SUDO=sudo + shift + fi + + local file=$1 + shift + + if [ -n "$LKL_HOST_CONFIG_NT" ]; then + file=$file.exe + fi + + file=${OUTPUT}/tests/$(basename $file) + + if file $file | grep ARM; then + WRAPPER="qemu-arm-static" + elif file $file | grep "FreeBSD" ; then + ssh_copy "$file" $BSD_WDIR + if [ -n "$SUDO" ]; then + SUDO="" + fi + WRAPPER="$MYSSH $SU" + # ssh will mess up with pipes ('|') so, escape the pipe char. + args="${@//\|/\\\|}" + set - $BSD_WDIR/$(basename $file) $args + file="" + elif [ -n "$GDB" ]; then + WRAPPER="gdb" + args="$@" + set - -ex "run $args" -ex quit $file + file="" + elif [ -n "$VALGRIND" ]; then + WRAPPER="valgrind --suppressions=$script_dir/valgrind.supp \ + --leak-check=full --show-leak-kinds=all --xml=yes \ + --xml-file=valgrind-$suite_name.xml" + fi + + $SUDO $WRAPPER $file "$@" +} + +lkl_test_cmd() +{ + local WRAPPER="" + + if [ -z "$QUIET" ]; then + SHOPTS="-x" + fi + + if [ -n "$LKL_HOST_CONFIG_BSD" ]; then + WRAPPER="$MYSSH $SU" + fi + + echo "$@" | $WRAPPER sh $SHOPTS +} + +# XXX: $MYSSH and $MYSCP are defined in a circleci docker image. +# see the definitions in lkl/lkl-docker:circleci/freebsd11/Dockerfile +ssh_push() +{ + while [ -n "$1" ]; do + if [[ "$1" = *.sh ]]; then + type="script" + else + type="file" + fi + + dir=$(dirname $1) + $MYSSH mkdir -p $BSD_WDIR/$dir + + $MYSCP -P 7722 -r $basedir/$1 root@localhost:$BSD_WDIR/$dir + if [ "$type" = "script" ]; then + $MYSSH chmod a+x $BSD_WDIR/$1 + fi + + shift + done +} + +ssh_copy() +{ + $MYSCP -P 7722 -r $1 root@localhost:$2 +} + +lkl_test_bsd_cleanup() +{ + $MYSSH rm -rf $BSD_WDIR +} + +if [ -n "$LKL_HOST_CONFIG_BSD" ]; then + trap lkl_test_bsd_cleanup EXIT + export BSD_WDIR=/root/lkl + $MYSSH mkdir -p $BSD_WDIR +fi diff --git a/tools/lkl/tests/valgrind.supp b/tools/lkl/tests/valgrind.supp new file mode 100644 index 000000000000..2a0e270f2292 --- /dev/null +++ b/tools/lkl/tests/valgrind.supp @@ -0,0 +1,105 @@ +{ + + Memcheck:Leak + match-leak-kinds: possible + ... + fun:pthread_create@@GLIBC_2.2.5 + fun:__start_helper_thread + fun:__pthread_once_slow + fun:timer_create@@GLIBC_2.3.3 + fun:timer_alloc + fun:clockevent_set_state_oneshot + ... + fun:__clockevents_switch_state + fun:clockevents_switch_state + fun:tick_setup_periodic + ... +} + +{ + + Memcheck:Leak + match-leak-kinds: possible + ... + fun:allocate_stack + fun:pthread_create@@GLIBC_2.2.5 + fun:timer_helper_thread + fun:start_thread + ... +} + +{ + + Memcheck:Leak + match-leak-kinds: possible + ... + fun:thread_create + fun:copy_thread + fun:copy_thread_tls + ... + fun:rest_init + ... + fun:start_kernel + ... +} + +{ + + Memcheck:Value8 + fun:crc32_body + fun:crc32_le_generic + fun:__crc32c_le + fun:chksum_update + fun:crypto_shash_update + fun:crc32c + fun:xlog_cksum +} + +{ + + Memcheck:Param + pwrite64(buf) + ... + fun:blk_request + fun:blk_enqueue + fun:virtio_process_one + fun:virtio_process_queue + fun:virtio_write + fun:__raw_writel + fun:writel + fun:vm_notify + fun:virtqueue_notify + fun:virtio_queue_rq + fun:blk_mq_dispatch_rq_list + fun:blk_mq_sched_dispatch_requests +} + +{ + + Memcheck:Param + writev(vector[...]) + ... + fun:fd_net_tx + fun:net_enqueue + fun:virtio_process_one + fun:virtio_process_queue + fun:virtio_write + fun:__raw_writel + fun:writel + fun:vm_notify + ... + fun:netdev_start_xmit + ... +} + +{ + + Memcheck:Param + read(buf) + ... + fun:read + fun:os_read_file + fun:bulk_req_safe_read.constprop.11 + fun:io_thread + ... +} diff --git a/tools/lkl/tests/valgrind2xunit.py b/tools/lkl/tests/valgrind2xunit.py new file mode 100755 index 000000000000..ab7c12b83377 --- /dev/null +++ b/tools/lkl/tests/valgrind2xunit.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: GPL-2.0 + +## +## Downloader from +## http://humdi.net/wiki/tips/valgrind-to-xunit-xml-converter +## + +import xml.etree.ElementTree as ET +import sys +import os + +fname = sys.argv[1] +if fname is None: + fname = 'valgrind.xml' + +doc = ET.parse(fname) +errors = doc.findall('.//error') + +out = open(os.path.splitext(os.path.basename(fname))[0]+'_xunit.xml',"w") +out.write('\n') +out.write('\n') +errorcount=0 +for error in errors: + errorcount=errorcount+1 + + kind = error.find('kind') + what = error.find('what') + if what == None: + what = error.find('xwhat/text') + + stack = error.find('stack') + frames = stack.findall('frame') + + for frame in frames: + fi = frame.find('file') + li = frame.find('line') + if fi != None and li != None: + break + + if fi != None and li != None: + out.write(' \n') + else: + out.write(' \n') + out.write(' \n') + out.write(' '+what.text+'\n\n') + + for frame in frames: + ip = frame.find('ip') + fn = frame.find('fn') + fi = frame.find('file') + li = frame.find('line') + + if fn is None: + bodytext = '(unresolved symbol)' + else: + bodytext = fn.text + bodytext = bodytext.replace("&","&") + bodytext = bodytext.replace("<","<") + bodytext = bodytext.replace(">",">") + if fi != None and li != None: + out.write(' '+ip.text+': '+bodytext+' ('+fi.text+':'+li.text+')\n') + else: + out.write(' '+ip.text+': '+bodytext+'\n') + + out.write(' \n') + out.write(' \n') +out.write('\n') +out.close() From patchwork Mon Mar 30 14:45:50 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hajime Tazaki X-Patchwork-Id: 1264001 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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=PwdSPHF9; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=GyWNoM4D; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (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 48rb8w2vcfz9sP7 for ; Tue, 31 Mar 2020 01:54:56 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.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=Pt5AWD15FnRN4ea/GamwtcTrcQs03Y+ViaG1FV5DbtI=; b=PwdSPHF9YWLB3n Mer9FrXtHIN414fXhYN08UPYFKu3Ex9k4CpFk2kMggK0Nbj48IOIQBsSlDFomScZqRhruSV2De3M7 6LRFVCiV8B0UQzZtO9FVIbH2I7MrBYqLvkaitfquKC/v7mM4sJU2SQLD/uuD2kn+c34bvfq3UCZu8 OvrjtLbo2dItSwPeqWcRS24SeBGBmhwIxX62h4SnZRKFo42hPJd04CN/cYHZmdxYvnBzBb85BFV4T Z4H0mNRF5WKb7eTokff584/j7SWeJKI5+1OwNwwUwyWOgLOG/EYbiF/zog0KhwEg/IXfH+hHUxEMJ Iqb4Njl3kJQfQyED459A==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvoN-0007AS-SD; Mon, 30 Mar 2020 14:54:47 +0000 Received: from mail-pj1-x1041.google.com ([2607:f8b0:4864:20::1041]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvoK-000793-1T for linux-um@lists.infradead.org; Mon, 30 Mar 2020 14:54:46 +0000 Received: by mail-pj1-x1041.google.com with SMTP id w9so7697435pjh.1 for ; Mon, 30 Mar 2020 07:54:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=FeGkYni7LJnQM11cC/ZJMS21tEqO7nFsGMOBX356P0E=; b=GyWNoM4DblDRbZlBkfMKWSXmQ9JG/u2Sln6ln9+BBQ5d6erERdjR6bmpEdzC97oBb3 3EWMcnfXW+hxq+pUo7bX0boyZ0xfDS+YG7eMN3EMYritO+4hT9SfvSsJovDxFaUOuVws +I4Fue6GSeUREExHmeAnb2WAT6wYBvkb8aUlzQgauJY3K+n/MqthAjXWjX20J+/puvKs pjvx0LUAGCA0WyaEF4OYSJOrUcIQu6ZanF3x37Xml2nMGucqJHy8SHklLL0Ss/wnqBKX 9vISil+RVo2zMb8mCMd4rOEwMiXdZp9vil4u4D96HVELajGAxrfqrLFl7ZCS/4cuH0zP W42Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=FeGkYni7LJnQM11cC/ZJMS21tEqO7nFsGMOBX356P0E=; b=grPBK78RQlM3FTqQLWTonRDwjY9l2IkO3zcsSDCYwZw2AIaleg+sRymCLBu7Lpm3O9 eWD2HDnkgGVKdW+ASzT8MefQR56BNb67eHdZOh0YL/3TJRtth9QOBcSGDNnGS3xl4qqE 7ux1nQRkI7CPHFA9zCtUeQq81svCwzpyJYTCi0PYwAuwjd4xrgh2WpGodrgbgrbLdXk1 2Jyp/jRHL9JqcO8p1Bx+vrhTx4jh2rkkXiEeSxj71kgXzsbjZg344mvFRk6vNMdAL/NG JA0sM/JkNEbEVRzpshK/Rb42P/H055fr2ME49MZ1062r7iQseoQhB6TrAp4OyqgTdEYZ nv4Q== X-Gm-Message-State: ANhLgQ31OrGXO+HUZYHfzqGu/b0cM4aGMPVaS+obfB5X5rI/EGq++MjN mKblI3QzCuBun67jjQN1DK3922FR7/Wj2Q== X-Google-Smtp-Source: APiQypIukTARaonWw1lDxXWk8Jnc+T9ZFuD7i6/LbsX3XF7cg2+l2t6DjoSnm/agnvgikM+BLNbS7A== X-Received: by 2002:a17:902:7c05:: with SMTP id x5mr9076620pll.166.1585579741183; Mon, 30 Mar 2020 07:49:01 -0700 (PDT) Received: from earth-mac.local (219x123x138x129.ap219.ftth.ucom.ne.jp. [219.123.138.129]) by smtp.gmail.com with ESMTPSA id t85sm9718917pgb.1.2020.03.30.07.49.00 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 30 Mar 2020 07:49:00 -0700 (PDT) Received: by earth-mac.local (Postfix, from userid 501) id 9D108202804E45; Mon, 30 Mar 2020 23:48:43 +0900 (JST) From: Hajime Tazaki To: linux-um@lists.infradead.org Subject: [RFC v4 18/25] lkl tools: cptofs that reads/writes to/from a filesystem image Date: Mon, 30 Mar 2020 23:45:50 +0900 Message-Id: X-Mailer: git-send-email 2.20.1 (Apple Git-117) In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200330_075444_116979_2F68E07C X-CRM114-Status: GOOD ( 18.69 ) X-Spam-Score: -0.2 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:1041 listed in] [list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [thehajime[at]gmail.com] -0.0 SPF_PASS SPF: sender matches SPF record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 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: linux-arch@vger.kernel.org, Conrad Meyer , Octavian Purdila , Akira Moroo , Petros Angelatos , Dan Peebles , linux-kernel-library@freelists.org, Yuriy Taraday , Tuomas Tynkkynen , Hajime Tazaki Sender: "linux-um" Errors-To: linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Octavian Purdila A tool to read/write to/from a filesystem image without mounting the file to host filesystem. Thus there is no root privilege to modify the contents. Cc: Conrad Meyer Cc: Dan Peebles Cc: Petros Angelatos Cc: Tuomas Tynkkynen Cc: Yuriy Taraday Signed-off-by: Hajime Tazaki Signed-off-by: Octavian Purdila --- tools/lkl/.gitignore | 2 + tools/lkl/Build | 2 + tools/lkl/Makefile | 3 + tools/lkl/Targets | 4 + tools/lkl/cptofs.c | 636 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 647 insertions(+) create mode 100644 tools/lkl/cptofs.c diff --git a/tools/lkl/.gitignore b/tools/lkl/.gitignore index 4e08254dbd46..1a8210f4d9c4 100644 --- a/tools/lkl/.gitignore +++ b/tools/lkl/.gitignore @@ -7,3 +7,5 @@ tests/disk tests/boot tests/valgrind*.xml *.pyc +cptofs +cpfromfs diff --git a/tools/lkl/Build b/tools/lkl/Build index e69de29bb2d1..a9d12c5ca260 100644 --- a/tools/lkl/Build +++ b/tools/lkl/Build @@ -0,0 +1,2 @@ +cptofs-$(LKL_HOST_CONFIG_ARCHIVE) += cptofs.o + diff --git a/tools/lkl/Makefile b/tools/lkl/Makefile index 0abccb9d86b6..03750aab98d8 100644 --- a/tools/lkl/Makefile +++ b/tools/lkl/Makefile @@ -86,6 +86,9 @@ $(OUTPUT)%$(EXESUF): $(OUTPUT)%-in.o $(OUTPUT)liblkl.a $(OUTPUT)%-in.o: $(OUTPUT)lib/lkl.o FORCE $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(patsubst %/,%,$(dir $*)) obj=$(notdir $*) +$(OUTPUT)cpfromfs$(EXESUF): $(OUTPUT)cptofs$(EXESUF) + $(Q)if ! [ -e $@ ]; then ln -s $< $@; fi + clean: $(call QUIET_CLEAN, objects)find $(OUTPUT) -name '*.o' -delete -o -name '\.*.cmd'\ diff --git a/tools/lkl/Targets b/tools/lkl/Targets index a9f74c3cc8fb..17de965f92b3 100644 --- a/tools/lkl/Targets +++ b/tools/lkl/Targets @@ -4,3 +4,7 @@ progs-y += tests/boot progs-y += tests/disk progs-y += tests/net-test +progs-$(LKL_HOST_CONFIG_ARCHIVE) += cptofs +progs-$(LKL_HOST_CONFIG_ARCHIVE) += cpfromfs +LDLIBS_cptofs-y := -larchive +LDLIBS_cptofs-$(LKL_HOST_CONFIG_NEEDS_LARGP) += -largp diff --git a/tools/lkl/cptofs.c b/tools/lkl/cptofs.c new file mode 100644 index 000000000000..fb34f570fa1e --- /dev/null +++ b/tools/lkl/cptofs.c @@ -0,0 +1,636 @@ +// SPDX-License-Identifier: GPL-2.0 +#ifdef __FreeBSD__ +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const char doc_cptofs[] = "Copy files to a filesystem image"; +static const char doc_cpfromfs[] = "Copy files from a filesystem image"; +static const char args_doc_cptofs[] = "-t fstype -i fsimage path... fs_path"; +static const char args_doc_cpfromfs[] = "-t fstype -i fsimage fs_path... path"; + +static struct argp_option options[] = { + {"enable-printk", 'p', 0, 0, "show Linux printks"}, + {"partition", 'P', "int", 0, "partition number"}, + {"filesystem-type", 't', "string", 0, + "select filesystem type - mandatory"}, + {"filesystem-image", 'i', "string", 0, + "path to the filesystem image - mandatory"}, + {"selinux", 's', "string", 0, "selinux attributes for destination"}, + {0}, +}; + +static struct cl_args { + int printk; + int part; + const char *fsimg_type; + const char *fsimg_path; + int npaths; + char **paths; + const char *selinux; +} cla; + +static int cptofs; + +static error_t parse_opt(int key, char *arg, struct argp_state *state) +{ + struct cl_args *cla = state->input; + + switch (key) { + case 'p': + cla->printk = 1; + break; + case 'P': + cla->part = atoi(arg); + break; + case 't': + cla->fsimg_type = arg; + break; + case 'i': + cla->fsimg_path = arg; + break; + case 's': + cla->selinux = arg; + break; + case ARGP_KEY_ARG: + // Capture all remaining arguments in our paths array and stop + // parsing here. We treat the last one as the destination and + // everything before it as sources, just like cp does. + cla->paths = &state->argv[state->next - 1]; + cla->npaths = state->argc - state->next + 1; + state->next = state->argc; + break; + default: + return ARGP_ERR_UNKNOWN; + } + + return 0; +} + +static struct argp argp_cptofs = { + .options = options, + .parser = parse_opt, + .args_doc = args_doc_cptofs, + .doc = doc_cptofs, +}; + +static struct argp argp_cpfromfs = { + .options = options, + .parser = parse_opt, + .args_doc = args_doc_cpfromfs, + .doc = doc_cpfromfs, +}; + +static int searchdir(const char *fs_path, const char *path, const char *match); + +static int open_src(const char *path) +{ + int fd; + + if (cptofs) + fd = open(path, O_RDONLY, 0); + else + fd = lkl_sys_open(path, LKL_O_RDONLY, 0); + + if (fd < 0) + fprintf(stderr, "unable to open file %s for reading: %s\n", + path, cptofs ? strerror(errno) : lkl_strerror(fd)); + + return fd; +} + +static int open_dst(const char *path, int mode) +{ + int fd; + + if (cptofs) + fd = lkl_sys_open(path, LKL_O_RDWR | LKL_O_TRUNC | LKL_O_CREAT, + mode); + else + fd = open(path, O_RDWR | O_TRUNC | O_CREAT, mode); + + if (fd < 0) + fprintf(stderr, "unable to open file %s for writing: %s\n", + path, cptofs ? lkl_strerror(fd) : strerror(errno)); + + if (cla.selinux && cptofs) { + int ret = lkl_sys_fsetxattr(fd, "security.selinux", cla.selinux, + strlen(cla.selinux), 0); + if (ret) + fprintf(stderr, + "unable to set selinux attribute on %s: %s\n", + path, lkl_strerror(ret)); + } + + return fd; +} + +static int read_src(int fd, char *buf, int len) +{ + int ret; + + if (cptofs) + ret = read(fd, buf, len); + else + ret = lkl_sys_read(fd, buf, len); + + if (ret < 0) + fprintf(stderr, "error reading file: %s\n", + cptofs ? strerror(errno) : lkl_strerror(ret)); + + return ret; +} + +static int write_dst(int fd, char *buf, int len) +{ + int ret; + + if (cptofs) + ret = lkl_sys_write(fd, buf, len); + else + ret = write(fd, buf, len); + + if (ret < 0) + fprintf(stderr, "error writing file: %s\n", + cptofs ? lkl_strerror(ret) : strerror(errno)); + + return ret; +} + +static void close_src(int fd) +{ + if (cptofs) + close(fd); + else + lkl_sys_close(fd); +} + +static void close_dst(int fd) +{ + if (cptofs) + lkl_sys_close(fd); + else + close(fd); +} + +static int copy_file(const char *src, const char *dst, int mode) +{ + long len, to_write, wrote; + char buf[4096], *ptr; + int ret = 0; + int fd_src, fd_dst; + + fd_src = open_src(src); + if (fd_src < 0) + return fd_src; + + fd_dst = open_dst(dst, mode); + if (fd_dst < 0) + return fd_dst; + + do { + len = read_src(fd_src, buf, sizeof(buf)); + + if (len > 0) { + ptr = buf; + to_write = len; + do { + wrote = write_dst(fd_dst, ptr, to_write); + + if (wrote < 0) { + ret = wrote; + goto out; + } + + to_write -= wrote; + ptr += len; + + } while (to_write > 0); + } + + if (len < 0) + ret = len; + + } while (len > 0); + +out: + close_src(fd_src); + close_dst(fd_dst); + + return ret; +} + +static int stat_src(const char *path, unsigned int *type, unsigned int *mode, + long long *size, struct lkl_timespec *mtime, + struct lkl_timespec *atime) +{ + struct stat stat; + struct lkl_stat lkl_stat; + int ret; + + if (cptofs) { + ret = lstat(path, &stat); + if (type) + *type = stat.st_mode & S_IFMT; + if (mode) + *mode = stat.st_mode & ~S_IFMT; + if (size) + *size = stat.st_size; + if (mtime) { + mtime->tv_sec = stat.st_mtim.tv_sec; + mtime->tv_nsec = stat.st_mtim.tv_nsec; + } + if (atime) { + atime->tv_sec = stat.st_atim.tv_sec; + atime->tv_nsec = stat.st_atim.tv_nsec; + } + } else { + ret = lkl_sys_lstat(path, &lkl_stat); + if (type) + *type = lkl_stat.st_mode & S_IFMT; + if (mode) + *mode = lkl_stat.st_mode & ~S_IFMT; + if (size) + *size = lkl_stat.st_size; + if (mtime) { + mtime->tv_sec = lkl_stat.lkl_st_mtime; + mtime->tv_nsec = lkl_stat.st_mtime_nsec; + } + if (atime) { + atime->tv_sec = lkl_stat.lkl_st_atime; + atime->tv_nsec = lkl_stat.st_atime_nsec; + } + } + + if (ret) + fprintf(stderr, "fsimg lstat(%s) error: %s\n", + path, cptofs ? strerror(errno) : lkl_strerror(ret)); + + return ret; +} + +static int mkdir_dst(const char *path, unsigned int mode) +{ + int ret; + + if (cptofs) { + ret = lkl_sys_mkdir(path, mode); + if (ret == -LKL_EEXIST) + ret = 0; + } else { + ret = mkdir(path, mode); + if (ret < 0 && errno == EEXIST) + ret = 0; + } + + if (ret) + fprintf(stderr, "unable to create directory %s: %s\n", + path, cptofs ? strerror(errno) : lkl_strerror(ret)); + + return ret; +} + +static int readlink_src(const char *src, char *out, int outsize) +{ + int ret; + + if (cptofs) + ret = readlink(src, out, outsize); + else + ret = lkl_sys_readlink(src, out, outsize); + + if (ret < 0) + fprintf(stderr, "unable to readlink '%s': %s\n", src, + cptofs ? strerror(errno) : lkl_strerror(ret)); + + return ret; +} + +static int symlink_dst(const char *path, const char *target) +{ + int ret; + + if (cptofs) + ret = lkl_sys_symlink(target, path); + else + ret = symlink(target, path); + + if (ret) + fprintf(stderr, "unable to symlink '%s' with target '%s': %s\n", + path, target, cptofs ? lkl_strerror(ret) : + strerror(errno)); + + return ret; +} + +static int copy_symlink(const char *src, const char *dst) +{ + int ret; + long long size, actual_size; + char *target = NULL; + + ret = stat_src(src, NULL, NULL, &size, NULL, NULL); + if (ret) { + ret = -1; + goto out; + } + + target = malloc(size + 1); + if (!target) { + fprintf(stderr, "Unable to allocate memory (%lld bytes)\n", + size + 1); + ret = -1; + goto out; + } + + actual_size = readlink_src(src, target, size); + if (actual_size != size) { + fprintf(stderr, + "readlink(%s) bad size: got %lld, expected %lld\n", + src, actual_size, size); + ret = -1; + goto out; + } + target[size] = 0; // readlink doesn't append the trailing null byte + + ret = symlink_dst(dst, target); + if (ret) + ret = -1; + +out: + if (target) + free(target); + + return ret; +} + +static int do_entry(const char *_src, const char *_dst, const char *name) +{ + char src[PATH_MAX], dst[PATH_MAX]; + struct lkl_timespec mtime, atime; + unsigned int type, mode; + int ret; + + snprintf(src, sizeof(src), "%s/%s", _src, name); + snprintf(dst, sizeof(dst), "%s/%s", _dst, name); + + ret = stat_src(src, &type, &mode, NULL, &mtime, &atime); + + switch (type) { + case S_IFREG: + { + ret = copy_file(src, dst, mode); + break; + } + case S_IFDIR: + ret = mkdir_dst(dst, mode); + if (ret) + break; + ret = searchdir(src, dst, NULL); + break; + case S_IFLNK: + ret = copy_symlink(src, dst); + break; + case S_IFSOCK: + case S_IFBLK: + case S_IFCHR: + case S_IFIFO: + default: + printf("skipping %s: unsupported entry type %d\n", src, type); + } + + if (!ret) { + if (cptofs) { + struct lkl_timespec lkl_ts[] = { atime, mtime }; + + ret = lkl_sys_utimensat(-1, dst, + (struct __lkl__kernel_timespec + *)lkl_ts, + LKL_AT_SYMLINK_NOFOLLOW); + } else { + struct timespec ts[] = { + { .tv_sec = atime.tv_sec, + .tv_nsec = atime.tv_nsec, }, + { .tv_sec = mtime.tv_sec, + .tv_nsec = mtime.tv_nsec, }, + }; + + ret = utimensat(-1, dst, ts, AT_SYMLINK_NOFOLLOW); + } + } + + if (ret) + printf("error processing entry %s, aborting\n", src); + + return ret; +} + +static DIR *open_dir(const char *path) +{ + DIR *dir; + int err; + + if (cptofs) + dir = opendir(path); + else + dir = (DIR *)lkl_opendir(path, &err); + + if (!dir) + fprintf(stderr, "unable to open directory %s: %s\n", + path, cptofs ? strerror(errno) : lkl_strerror(err)); + return dir; +} + +static const char *read_dir(DIR *dir, const char *path) +{ + struct lkl_dir *lkl_dir = (struct lkl_dir *)dir; + const char *name = NULL; + const char *err = NULL; + + if (cptofs) { + struct dirent *de = readdir(dir); + + if (de) + name = de->d_name; + } else { + struct lkl_linux_dirent64 *de = lkl_readdir(lkl_dir); + + if (de) + name = de->d_name; + } + + if (!name) { + if (cptofs) { + if (errno) + err = strerror(errno); + } else { + if (lkl_errdir(lkl_dir)) + err = lkl_strerror(lkl_errdir(lkl_dir)); + } + } + + if (err) + fprintf(stderr, "error while reading directory %s: %s\n", + path, err); + return name; +} + +static void close_dir(DIR *dir) +{ + if (cptofs) + closedir(dir); + else + lkl_closedir((struct lkl_dir *)dir); +} + +static int searchdir(const char *src, const char *dst, const char *match) +{ + DIR *dir; + const char *name; + int ret = 0; + + dir = open_dir(src); + if (!dir) + return -1; + + while ((name = read_dir(dir, src))) { + if (!strcmp(name, ".") || !strcmp(name, "..") || + (match && fnmatch(match, name, 0) != 0)) + continue; + + ret = do_entry(src, dst, name); + if (ret) + goto out; + } + +out: + close_dir(dir); + + return ret; +} + +static int match_root(const char *src) +{ + const char *c = src; + + while (*c) { + switch (*c) { + case '.': + if (c > src && c[-1] == '.') + return 0; + break; + case '/': + break; + default: + return 0; + } + c++; + } + + return 1; +} + +int copy_one(const char *src, const char *mpoint, const char *dst) +{ + char *src_path_dir, *src_path_base; + char src_path[PATH_MAX], dst_path[PATH_MAX]; + + if (cptofs) { + snprintf(src_path, sizeof(src_path), "%s", src); + snprintf(dst_path, sizeof(dst_path), "%s/%s", mpoint, dst); + } else { + snprintf(src_path, sizeof(src_path), "%s/%s", mpoint, src); + snprintf(dst_path, sizeof(dst_path), "%s", dst); + } + + if (match_root(src)) + return searchdir(src_path, dst, NULL); + + src_path_dir = dirname(strdup(src_path)); + src_path_base = basename(strdup(src_path)); + + return searchdir(src_path_dir, dst_path, src_path_base); +} + +int main(int argc, char **argv) +{ + struct lkl_disk disk; + long ret, umount_ret; + int i; + char mpoint[32]; + unsigned int disk_id; + + if (strstr(argv[0], "cptofs")) { + cptofs = 1; + ret = argp_parse(&argp_cptofs, argc, argv, 0, 0, &cla); + } else { + ret = argp_parse(&argp_cpfromfs, argc, argv, 0, 0, &cla); + } + + if (ret < 0) + return -1; + + if (!cla.printk) + lkl_host_ops.print = NULL; + + disk.fd = open(cla.fsimg_path, cptofs ? O_RDWR : O_RDONLY); + if (disk.fd < 0) { + fprintf(stderr, "can't open fsimg %s: %s\n", cla.fsimg_path, + strerror(errno)); + ret = 1; + goto out; + } + + disk.ops = NULL; + disk.dev = (char *)cla.fsimg_path; + + ret = lkl_disk_add(&disk); + if (ret < 0) { + fprintf(stderr, "can't add disk: %s\n", lkl_strerror(ret)); + goto out_close; + } + disk_id = ret; + + lkl_start_kernel(&lkl_host_ops, "mem=100M"); + + ret = lkl_mount_dev(disk_id, cla.part, cla.fsimg_type, + cptofs ? 0 : LKL_MS_RDONLY, + NULL, mpoint, sizeof(mpoint)); + if (ret) { + fprintf(stderr, "can't mount disk: %s\n", lkl_strerror(ret)); + goto out_close; + } + + lkl_sys_umask(0); + + for (i = 0; i < cla.npaths - 1; i++) { + ret = copy_one(cla.paths[i], mpoint, cla.paths[cla.npaths - 1]); + if (ret) + break; + } + + umount_ret = lkl_umount_dev(disk_id, cla.part, 0, 1000); + if (ret == 0) + ret = umount_ret; + +out_close: + close(disk.fd); + +out: + lkl_sys_halt(); + + return ret; +} From patchwork Mon Mar 30 14:45:51 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hajime Tazaki X-Patchwork-Id: 1263994 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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=ZpsGxYyc; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=MMiQ/y6X; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (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 48rb2849f0z9sPk for ; Tue, 31 Mar 2020 01:49:04 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.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=dRoGgcwVqq1Py/idy6pX2viWRJDa51nzmzFOIjixKQU=; b=ZpsGxYycT+343a 6bnioAzU2fEGTTHkNAas2mxzUAgEKgE04cLAgwiUPqlutWaFpZDRMx9mt19veEqEaZ3LCYtxb54C8 Brn2Y7sLBcXuA/hpl8EaeX7cGCxPYV3Fw232cwAQWWO7MJuCrvjZlzvuMgkfYyDnD00KMFnqyQof+ 6KpoKXUJjJUURHwcMrQY2B6oh11++lzy+fX8oqo82TdU+xlc/MPWLhs3KZMP7JzcP17LgDH1DOu4q AQKakNgac28l3XpbELwksqo/oynupUwaJbD4P/3V1cVQ7XntQk/VIXgpmyi9l7OCGa2WF1Cysjl/5 tEIq45P1JNBe7EPsnUdg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvie-000532-Qs; Mon, 30 Mar 2020 14:48:52 +0000 Received: from mail-pj1-x1042.google.com ([2607:f8b0:4864:20::1042]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvia-00051q-Ko for linux-um@lists.infradead.org; Mon, 30 Mar 2020 14:48:50 +0000 Received: by mail-pj1-x1042.google.com with SMTP id np9so7681049pjb.4 for ; Mon, 30 Mar 2020 07:48:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=imps6g8P7Pz4OGYnQVZikVA60FQoafCxwcYjnUyS3X0=; b=MMiQ/y6XRLdAtyd5l11TORYdX3WTkSH7lYXTfdhDGZZ9bLQV3J9OAOOcs1WAQkxZgm o7MetapaOq6Vwm/kzPSSqHvFUSMLet9/aO20OESfX9OY+7p8R1XhFdUfdGc/fe3zoxBs +XjhYgtvlXby5577yZ53Ys/+R0E/6lf4spdFCYgoX6sakok0SGob/fQQZphMqYdWB6PB s1LYrD6RDCm+pg4V/HTk/b20BPwGAMwjEYOyXPPZeFQucx4Xk/FpfSBvg8PS9pDeNfkc kPNPgGhqaHtLXT4zVZtBnUdxwC4qHL/qt31mCYijvKuy5x7AzdAEN3UV7uJicRWOPLtX dylg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=imps6g8P7Pz4OGYnQVZikVA60FQoafCxwcYjnUyS3X0=; b=n267j0q14ifdWcesiZy/VSmkQOa7fXL3aY7TQ/y6pNFCubutxPYKgw4SrkyomIpJFO pryTXTIbHVf6zieCMA8Zg9HGOLe9hMmlcTnSjmLUXVn3+eBt6rKka10H3FlCKvjUpSqi OwYpyApGyaPBq7mxaMB5EmMH1jC+eDkb0y/CivG9umoUQwZ4Ow+U0pPdHikNUCOQHC2P HGjZrd8AWRQgE+qUfUh2sUD79LZGYDJowmPZwqXpzrQbowc/GBiXTHsEvzE7ihijkmWw shPRyOVC5eLPJen/kzDcG1rkRkTIU1wgh/fuu3fAfSAEkUkeZrjVhk3YCX7WdyDQV8/6 7R1g== X-Gm-Message-State: ANhLgQ1UNyWBTEwG0PTFQLUJh43RsSwDqKhTV54y5qhzeb2yYE9S1R2Q 9wLzCxGIJ7lWB7arJ6dFRtQ= X-Google-Smtp-Source: ADFU+vtYUo1F2+DC9mFXfpI9aclCi5qirSVGdV2vmcpipbDqT3qrU61F8qfmF+pcrwhu1u0flQWWdw== X-Received: by 2002:a17:90a:e382:: with SMTP id b2mr15382207pjz.83.1585579727980; Mon, 30 Mar 2020 07:48:47 -0700 (PDT) Received: from earth-mac.local (219x123x138x129.ap219.ftth.ucom.ne.jp. [219.123.138.129]) by smtp.gmail.com with ESMTPSA id r7sm10334233pfg.38.2020.03.30.07.48.47 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 30 Mar 2020 07:48:47 -0700 (PDT) Received: by earth-mac.local (Postfix, from userid 501) id 848A6202804E5C; Mon, 30 Mar 2020 23:48:45 +0900 (JST) From: Hajime Tazaki To: linux-um@lists.infradead.org Subject: [RFC v4 19/25] lkl tools: fs2tar that converts a filesystem image to tar Date: Mon, 30 Mar 2020 23:45:51 +0900 Message-Id: <2f324a9e2aa88b994df169b34a0069e9c0525ace.1585579244.git.thehajime@gmail.com> X-Mailer: git-send-email 2.20.1 (Apple Git-117) In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200330_074848_724548_CCF82F1B X-CRM114-Status: GOOD ( 17.76 ) X-Spam-Score: -0.2 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:1042 listed in] [list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [thehajime[at]gmail.com] -0.0 SPF_PASS SPF: sender matches SPF record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 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: linux-arch@vger.kernel.org, Conrad Meyer , Octavian Purdila , Akira Moroo , Petros Angelatos , linux-kernel-library@freelists.org, Hajime Tazaki Sender: "linux-um" Errors-To: linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Octavian Purdila Simple utility that converts a filesystem image to a tar file, preserving file rights and extended attributes. Cc: Conrad Meyer Cc: Petros Angelatos Signed-off-by: Hajime Tazaki Signed-off-by: Octavian Purdila --- tools/lkl/.gitignore | 1 + tools/lkl/Build | 1 + tools/lkl/Targets | 4 + tools/lkl/fs2tar.c | 412 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 418 insertions(+) create mode 100644 tools/lkl/fs2tar.c diff --git a/tools/lkl/.gitignore b/tools/lkl/.gitignore index 1a8210f4d9c4..138e65efcad2 100644 --- a/tools/lkl/.gitignore +++ b/tools/lkl/.gitignore @@ -9,3 +9,4 @@ tests/valgrind*.xml *.pyc cptofs cpfromfs +fs2tar diff --git a/tools/lkl/Build b/tools/lkl/Build index a9d12c5ca260..73b37363a6de 100644 --- a/tools/lkl/Build +++ b/tools/lkl/Build @@ -1,2 +1,3 @@ cptofs-$(LKL_HOST_CONFIG_ARCHIVE) += cptofs.o +fs2tar-$(LKL_HOST_CONFIG_ARCHIVE) += fs2tar.o diff --git a/tools/lkl/Targets b/tools/lkl/Targets index 17de965f92b3..3451a1856955 100644 --- a/tools/lkl/Targets +++ b/tools/lkl/Targets @@ -8,3 +8,7 @@ progs-$(LKL_HOST_CONFIG_ARCHIVE) += cptofs progs-$(LKL_HOST_CONFIG_ARCHIVE) += cpfromfs LDLIBS_cptofs-y := -larchive LDLIBS_cptofs-$(LKL_HOST_CONFIG_NEEDS_LARGP) += -largp + +progs-$(LKL_HOST_CONFIG_ARCHIVE) += fs2tar +LDLIBS_fs2tar-y := -larchive +LDLIBS_fs2tar-$(LKL_HOST_CONFIG_NEEDS_LARGP) += -largp diff --git a/tools/lkl/fs2tar.c b/tools/lkl/fs2tar.c new file mode 100644 index 000000000000..b7dbcf2028a3 --- /dev/null +++ b/tools/lkl/fs2tar.c @@ -0,0 +1,412 @@ +// SPDX-License-Identifier: GPL-2.0 +#ifdef __FreeBSD__ +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +char doc[] = ""; +char args_doc[] = "-t fstype fsimage_path tar_path"; +static struct argp_option options[] = { + {"enable-printk", 'p', 0, 0, "show Linux printks"}, + {"partition", 'P', "int", 0, "partition number"}, + {"filesystem-type", 't', "string", 0, + "select filesystem type - mandatory"}, + {"selinux-contexts", 's', "file", 0, + "export selinux contexts to file"}, + {0}, +}; + +static struct cl_args { + int printk; + int part; + const char *fsimg_type; + const char *fsimg_path; + const char *tar_path; + FILE *selinux; +} cla; + +static error_t parse_opt(int key, char *arg, struct argp_state *state) +{ + struct cl_args *cla = state->input; + + switch (key) { + case 'p': + cla->printk = 1; + break; + case 'P': + cla->part = atoi(arg); + break; + case 't': + cla->fsimg_type = arg; + break; + case 's': + cla->selinux = fopen(arg, "w"); + if (!cla->selinux) { + fprintf(stderr, + "failed to open selinux contexts file: %s\n", + strerror(errno)); + return -1; + } + break; + case ARGP_KEY_ARG: + if (!cla->fsimg_path) + cla->fsimg_path = arg; + else if (!cla->tar_path) + cla->tar_path = arg; + else + return -1; + break; + case ARGP_KEY_END: + if (state->arg_num < 2 || !cla->fsimg_type) + argp_usage(state); + break; + default: + return ARGP_ERR_UNKNOWN; + } + + return 0; +} + +static struct argp argp = { options, parse_opt, args_doc, doc }; + +static struct archive *tar; + +static int searchdir(const char *fsimg_path, const char *path); + +static int copy_file(const char *fsimg_path, const char *path) +{ + long fsimg_fd; + char buff[4096]; + long len, wrote; + int ret = 0; + + fsimg_fd = lkl_sys_open(fsimg_path, LKL_O_RDONLY, 0); + if (fsimg_fd < 0) { + fprintf(stderr, "fsimg error opening %s: %s\n", fsimg_path, + lkl_strerror(fsimg_fd)); + return fsimg_fd; + } + + do { + len = lkl_sys_read(fsimg_fd, buff, sizeof(buff)); + if (len > 0) { + wrote = archive_write_data(tar, buff, len); + if (wrote != len) { + fprintf(stderr, + "error writing file %s to archive: %s [%d %ld]\n", + path, archive_error_string(tar), ret, + len); + ret = -archive_errno(tar); + break; + } + } + + if (len < 0) { + fprintf(stderr, "error reading fsimg file %s: %s\n", + fsimg_path, lkl_strerror(len)); + ret = len; + } + + } while (len > 0); + + lkl_sys_close(fsimg_fd); + + return ret; +} + +static int add_link(const char *fsimg_path, const char *path, + struct archive_entry *entry) +{ + char buf[4096] = { 0, }; + long len; + + len = lkl_sys_readlink(fsimg_path, buf, sizeof(buf)); + if (len < 0) { + fprintf(stderr, "fsimg readlink error %s: %s\n", + fsimg_path, lkl_strerror(len)); + return len; + } + + archive_entry_set_symlink(entry, buf); + + return 0; +} + +static inline void fsimg_copy_stat(struct stat *st, struct lkl_stat *fst) +{ + st->st_dev = fst->st_dev; + st->st_ino = fst->st_ino; + st->st_mode = fst->st_mode; + st->st_nlink = fst->st_nlink; + st->st_uid = fst->st_uid; + st->st_gid = fst->st_gid; + st->st_rdev = fst->st_rdev; + st->st_size = fst->st_size; + st->st_blksize = fst->st_blksize; + st->st_blocks = fst->st_blocks; + st->st_atim.tv_sec = fst->lkl_st_atime; + st->st_atim.tv_nsec = fst->st_atime_nsec; + st->st_mtim.tv_sec = fst->lkl_st_mtime; + st->st_mtim.tv_nsec = fst->st_mtime_nsec; + st->st_ctim.tv_sec = fst->lkl_st_ctime; + st->st_ctim.tv_nsec = fst->st_ctime_nsec; +} + +static int copy_xattr(const char *fsimg_path, const char *path, + struct archive_entry *entry) +{ + long ret; + char *xattr_list, *i; + long xattr_list_size; + + ret = lkl_sys_llistxattr(fsimg_path, NULL, 0); + if (ret < 0) { + fprintf(stderr, "fsimg llistxattr(%s) error: %s\n", + path, lkl_strerror(ret)); + return ret; + } + + if (!ret) + return 0; + + xattr_list = malloc(ret); + + ret = lkl_sys_llistxattr(fsimg_path, xattr_list, ret); + if (ret < 0) { + fprintf(stderr, "fsimg llistxattr(%s) error: %s\n", path, + lkl_strerror(ret)); + free(xattr_list); + return ret; + } + + xattr_list_size = ret; + + for (i = xattr_list; i - xattr_list < xattr_list_size; + i += strlen(i) + 1) { + void *xattr_buf; + + ret = lkl_sys_lgetxattr(fsimg_path, i, NULL, 0); + if (ret < 0) { + fprintf(stderr, "fsimg lgetxattr(%s) error: %s\n", path, + lkl_strerror(ret)); + free(xattr_list); + return ret; + } + + xattr_buf = malloc(ret); + + ret = lkl_sys_lgetxattr(fsimg_path, i, xattr_buf, ret); + if (ret < 0) { + fprintf(stderr, "fsimg lgetxattr2(%s) error: %s\n", + path, lkl_strerror(ret)); + free(xattr_list); + free(xattr_buf); + return ret; + } + + if (cla.selinux && strcmp(i, "security.selinux") == 0) + fprintf(cla.selinux, "%s %s\n", path, + (char *)xattr_buf); + + archive_entry_xattr_clear(entry); + archive_entry_xattr_add_entry(entry, i, xattr_buf, ret); + + free(xattr_buf); + } + + free(xattr_list); + + return 0; +} + +static int do_entry(const char *fsimg_path, const char *path, + const struct lkl_linux_dirent64 *de) +{ + char fsimg_new_path[PATH_MAX], new_path[PATH_MAX]; + struct lkl_stat fsimg_stat; + struct stat stat; + struct archive_entry *entry; + int ftype; + long ret; + + snprintf(new_path, sizeof(new_path), "%s/%s", path, de->d_name); + snprintf(fsimg_new_path, sizeof(fsimg_new_path), "%s/%s", fsimg_path, + de->d_name); + + ret = lkl_sys_lstat(fsimg_new_path, &fsimg_stat); + if (ret) { + fprintf(stderr, "fsimg lstat(%s) error: %s\n", + path, lkl_strerror(ret)); + return ret; + } + + entry = archive_entry_new(); + + archive_entry_set_pathname(entry, new_path); + fsimg_copy_stat(&stat, &fsimg_stat); + archive_entry_copy_stat(entry, &stat); + ret = copy_xattr(fsimg_new_path, new_path, entry); + if (ret) + return ret; + /* TODO: ACLs */ + + ftype = stat.st_mode & S_IFMT; + + switch (ftype) { + case S_IFREG: + archive_write_header(tar, entry); + ret = copy_file(fsimg_new_path, new_path); + break; + case S_IFDIR: + archive_write_header(tar, entry); + ret = searchdir(fsimg_new_path, new_path); + break; + case S_IFLNK: + ret = add_link(fsimg_new_path, new_path, entry); + /* fall through */ + case S_IFSOCK: + case S_IFBLK: + case S_IFCHR: + case S_IFIFO: + if (ret) + break; + archive_write_header(tar, entry); + break; + default: + printf("skipping %s: unsupported entry type %d\n", new_path, + ftype); + } + + archive_entry_free(entry); + + if (ret) + printf("error processing entry %s, aborting\n", new_path); + + return ret; +} + +static int searchdir(const char *fsimg_path, const char *path) +{ + long ret, fd; + char buf[1024], *pos; + long buf_len; + + fd = lkl_sys_open(fsimg_path, LKL_O_RDONLY | LKL_O_DIRECTORY, 0); + if (fd < 0) { + fprintf(stderr, "failed to open dir %s: %s", fsimg_path, + lkl_strerror(fd)); + return fd; + } + + do { + struct lkl_linux_dirent64 *de; + + de = (struct lkl_linux_dirent64 *) buf; + buf_len = lkl_sys_getdents64(fd, de, sizeof(buf)); + if (buf_len < 0) { + fprintf(stderr, "gentdents64 error: %s\n", + lkl_strerror(buf_len)); + break; + } + + for (pos = buf; pos - buf < buf_len; pos += de->d_reclen) { + de = (struct lkl_linux_dirent64 *)pos; + + if (!strcmp(de->d_name, ".") || + !strcmp(de->d_name, "..")) + continue; + + ret = do_entry(fsimg_path, path, de); + if (ret) + goto out; + } + + } while (buf_len > 0); + +out: + lkl_sys_close(fd); + return ret; +} + +int main(int argc, char **argv) +{ + struct lkl_disk disk; + long ret; + char mpoint[32]; + unsigned int disk_id; + + if (argp_parse(&argp, argc, argv, 0, 0, &cla) < 0) + return -1; + + if (!cla.printk) + lkl_host_ops.print = NULL; + + disk.fd = open(cla.fsimg_path, O_RDONLY); + if (disk.fd < 0) { + fprintf(stderr, "can't open fsimg %s: %s\n", cla.fsimg_path, + strerror(errno)); + ret = 1; + goto out; + } + + disk.ops = NULL; + disk.dev = (char *)cla.fsimg_path; + + ret = lkl_disk_add(&disk); + if (ret < 0) { + fprintf(stderr, "can't add disk: %s\n", lkl_strerror(ret)); + goto out_close; + } + disk_id = ret; + + lkl_start_kernel(&lkl_host_ops, "mem=10M"); + + ret = lkl_mount_dev(disk_id, cla.part, cla.fsimg_type, LKL_MS_RDONLY, + NULL, mpoint, sizeof(mpoint)); + if (ret) { + fprintf(stderr, "can't mount disk: %s\n", lkl_strerror(ret)); + goto out_close; + } + + ret = lkl_sys_chdir(mpoint); + if (ret) { + fprintf(stderr, "can't chdir to %s: %s\n", mpoint, + lkl_strerror(ret)); + goto out_umount; + } + + tar = archive_write_new(); + archive_write_set_format_pax_restricted(tar); + archive_write_open_filename(tar, cla.tar_path); + + ret = searchdir(mpoint, ""); + + archive_write_free(tar); + + if (cla.selinux) + fclose(cla.selinux); + +out_umount: + lkl_umount_dev(disk_id, cla.part, 0, 1000); + +out_close: + close(disk.fd); + +out: + lkl_sys_halt(); + + return ret; +} From patchwork Mon Mar 30 14:45:52 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hajime Tazaki X-Patchwork-Id: 1263995 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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=mn+Mvkc8; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=vYyS5efc; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (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 48rb2P17Tpz9sQt for ; Tue, 31 Mar 2020 01:49:17 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.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=ip4bp3WQTqxdLS/A+dJ2oEO0uj0sQn3pvra+ftp+PgA=; b=mn+Mvkc87DbqZF PB8qyeRBgiegu4yvwwC/Q9y9YZAJgCtG8JWTWvnZCnhzuJgf0vIOZXLmFzRJEmqn1qSXLYBBly2kd ErPIja7qaEWQj3Gsn/NRbOtu0pxaNwg+RxuhAjxkTJ5hu+dUT/rlilyuFzlT9nqYLyy29sY4A4Uu5 2ixqPxYtCX3ATMxQUCYTD0kvIMAqz/M4O60P/iLLtRWF8/WMCqa3VekxF4NmDEGNwUeUt59W/HrsU P+UQ7CTTs7PZRJsri1PcEd85e10MFmEGrBupscUJA81JwKA9Z1iDXj4Wln/OVSwfrTcxczDd3T1d0 TSpI0Zn5m+/rzHjvs2fg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvit-00055H-Ct; Mon, 30 Mar 2020 14:49:07 +0000 Received: from mail-pl1-x642.google.com ([2607:f8b0:4864:20::642]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvip-00054e-OO for linux-um@lists.infradead.org; Mon, 30 Mar 2020 14:49:06 +0000 Received: by mail-pl1-x642.google.com with SMTP id x1so6814521plm.4 for ; Mon, 30 Mar 2020 07:49:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=BEOokeSvnrY0DsD29hfNbeEvHK/HiFZdUeVRF/fRM4o=; b=vYyS5efcQYxCjE+6UZ37gMLHTRaxviJxJU2K4wABBulBvaSLdPvgYBr0Egh9f4QiH+ kSST2Vr7W1moyp3+AsjpIxi62xWShXF8XmsJqcObDMqmVdVzYydW45zrfSTg9/hrSaAs sqULkHBZb+ZZfvfQMDoWY9EJQwxmReg5+Nj9bw1lFcDGSGe0BMt8j+5N2fe3MjUr5Jf2 1J8tMZcng4GArwM5Wk4aBfbAd2ThGYI5qAWlQ2F317GzDgRzMYDnKCQ1imN7qK9sQtAL N4JSryX3OwdAKtQG2P5ZNnvJwRrOrEwPOEXnVcmij6sLUat8q2pv77BFFLc0ny9Co7wp QAww== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=BEOokeSvnrY0DsD29hfNbeEvHK/HiFZdUeVRF/fRM4o=; b=ilCYOzF41uBBMTddH1QvD9paxuwmELQ6jj9dXZzGVDsy6QuxoJnRLv2hGxU83g4dad qsdDBMseJpsSN6X1Qzw+PeV4YQ4vskAh+2jmDHqLKNJZ4jPmq79i6QtQ6J2jFPesuTV/ CO3Eq+rnuwHhp+o/79P6xzR3i6MF4AW+HCkFpo0mRQT1mQR8TwKSh5jeiXBG/lY6tnGh SE0qPHAnp8RDj9KRB0nfppEIi7vAb+drC4xzFVUocWenGr9xn9AYAwuvniaYU7r+8tRs ixDpydN9g9ub4a0e7x8B+KoYbpo9FS7KdKpQ2RoY39aql+m+pLA5Z2eTD/NlV9mfoiF3 48pA== X-Gm-Message-State: ANhLgQ3G85Wz/2mnQ9LXPPNHYy/vXMGO1hLKaPzskLuQs1rm263erx9Q tO+qcwhBszv6vhI7sDMweNk= X-Google-Smtp-Source: ADFU+vsRV5sOyYdmhY6lF+ep8RYYzNSCyCFOeINKelPok+3AGo6fagOzzY/Fiy6ySJpM1PKrlgREMA== X-Received: by 2002:a17:90a:240a:: with SMTP id h10mr15982674pje.123.1585579742920; Mon, 30 Mar 2020 07:49:02 -0700 (PDT) Received: from earth-mac.local (219x123x138x129.ap219.ftth.ucom.ne.jp. [219.123.138.129]) by smtp.gmail.com with ESMTPSA id u21sm10393596pjy.8.2020.03.30.07.49.01 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 30 Mar 2020 07:49:02 -0700 (PDT) Received: by earth-mac.local (Postfix, from userid 501) id A5CEF202804E93; Mon, 30 Mar 2020 23:49:00 +0900 (JST) From: Hajime Tazaki To: linux-um@lists.infradead.org Subject: [RFC v4 20/25] lkl tools: add lklfuse Date: Mon, 30 Mar 2020 23:45:52 +0900 Message-Id: <88fb75c4432a2a3ee8f2a1c98f057b25a50fc5b5.1585579244.git.thehajime@gmail.com> X-Mailer: git-send-email 2.20.1 (Apple Git-117) In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200330_074903_816273_192E5908 X-CRM114-Status: GOOD ( 19.12 ) X-Spam-Score: -0.2 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:642 listed in] [list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [thehajime[at]gmail.com] -0.0 SPF_PASS SPF: sender matches SPF record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 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: linux-arch@vger.kernel.org, Rafael Gieschke , Conrad Meyer , Octavian Purdila , Akira Moroo , Quentin Anglade , linux-kernel-library@freelists.org, Hajime Tazaki Sender: "linux-um" Errors-To: linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Octavian Purdila Add a simple fuse based program that can mount filesystem in userspace using LKL. Cc: Conrad Meyer Cc: Quentin Anglade Cc: Rafael Gieschke Signed-off-by: Hajime Tazaki Signed-off-by: Octavian Purdila --- tools/lkl/.gitignore | 1 + tools/lkl/Build | 3 + tools/lkl/Targets | 3 + tools/lkl/lklfuse.c | 659 +++++++++++++++++++++++++++++++++++++ tools/lkl/tests/lklfuse.sh | 110 +++++++ 5 files changed, 776 insertions(+) create mode 100644 tools/lkl/lklfuse.c create mode 100755 tools/lkl/tests/lklfuse.sh diff --git a/tools/lkl/.gitignore b/tools/lkl/.gitignore index 138e65efcad2..c78ec268e4b0 100644 --- a/tools/lkl/.gitignore +++ b/tools/lkl/.gitignore @@ -10,3 +10,4 @@ tests/valgrind*.xml cptofs cpfromfs fs2tar +lklfuse diff --git a/tools/lkl/Build b/tools/lkl/Build index 73b37363a6de..6048440d0e1b 100644 --- a/tools/lkl/Build +++ b/tools/lkl/Build @@ -1,3 +1,6 @@ +CFLAGS_lklfuse.o += -D_FILE_OFFSET_BITS=64 + cptofs-$(LKL_HOST_CONFIG_ARCHIVE) += cptofs.o fs2tar-$(LKL_HOST_CONFIG_ARCHIVE) += fs2tar.o +lklfuse-$(LKL_HOST_CONFIG_FUSE) += lklfuse.o diff --git a/tools/lkl/Targets b/tools/lkl/Targets index 3451a1856955..03d24362a195 100644 --- a/tools/lkl/Targets +++ b/tools/lkl/Targets @@ -12,3 +12,6 @@ LDLIBS_cptofs-$(LKL_HOST_CONFIG_NEEDS_LARGP) += -largp progs-$(LKL_HOST_CONFIG_ARCHIVE) += fs2tar LDLIBS_fs2tar-y := -larchive LDLIBS_fs2tar-$(LKL_HOST_CONFIG_NEEDS_LARGP) += -largp + +progs-$(LKL_HOST_CONFIG_FUSE) += lklfuse +LDLIBS_lklfuse-y := -lfuse diff --git a/tools/lkl/lklfuse.c b/tools/lkl/lklfuse.c new file mode 100644 index 000000000000..f6e14778e354 --- /dev/null +++ b/tools/lkl/lklfuse.c @@ -0,0 +1,659 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define FUSE_USE_VERSION 26 +#include +#include +#include +#include +#include + +#define LKLFUSE_VERSION "0.1" + +struct lklfuse { + const char *file; + const char *log; + const char *type; + const char *opts; + struct lkl_disk disk; + int disk_id; + int part; + int ro; + int mb; +} lklfuse = { + .mb = 64, +}; + +#define LKLFUSE_OPT(t, p, v) { t, offsetof(struct lklfuse, p), v } + +enum { + KEY_HELP, + KEY_VERSION, +}; + +static struct fuse_opt lklfuse_opts[] = { + LKLFUSE_OPT("log=%s", log, 0), + LKLFUSE_OPT("type=%s", type, 0), + LKLFUSE_OPT("mb=%d", mb, 0), + LKLFUSE_OPT("opts=%s", opts, 0), + LKLFUSE_OPT("part=%d", part, 0), + FUSE_OPT_KEY("-h", KEY_HELP), + FUSE_OPT_KEY("--help", KEY_HELP), + FUSE_OPT_KEY("-V", KEY_VERSION), + FUSE_OPT_KEY("--version", KEY_VERSION), + FUSE_OPT_END +}; + +static void usage(void) +{ + printf( +"usage: lklfuse file mountpoint [options]\n" +"\n" +"general options:\n" +" -o opt,[opt...] mount options\n" +" -h --help print help\n" +" -V --version print version\n" +"\n" +"lklfuse options:\n" +" -o log=FILE log file\n" +" -o type=fstype filesystem type\n" +" -o mb=memory in mb ammount of memory to allocate\n" +" -o part=parition partition to mount\n" +" -o ro open file read-only\n" +" -o opts=options mount options (use \\ to escape , and =)\n" +); +} + +static int lklfuse_opt_proc(void *data, const char *arg, int key, + struct fuse_args *args) +{ + switch (key) { + case FUSE_OPT_KEY_OPT: + if (strcmp(arg, "ro") == 0) + lklfuse.ro = 1; + return 1; + + case FUSE_OPT_KEY_NONOPT: + if (!lklfuse.file) { + lklfuse.file = strdup(arg); + return 0; + } + return 1; + + case KEY_HELP: + usage(); + fuse_opt_add_arg(args, "-ho"); + fuse_main(args->argc, args->argv, NULL, NULL); + exit(1); + + case KEY_VERSION: + printf("lklfuse version %s\n", LKLFUSE_VERSION); + fuse_opt_add_arg(args, "--version"); + fuse_main(args->argc, args->argv, NULL, NULL); + exit(0); + + default: + fprintf(stderr, "internal error\n"); + abort(); + } +} + +static void lklfuse_xlat_stat(const struct lkl_stat *in, struct stat *st) +{ + st->st_dev = in->st_dev; + st->st_ino = in->st_ino; + st->st_mode = in->st_mode; + st->st_nlink = in->st_nlink; + st->st_uid = in->st_uid; + st->st_gid = in->st_gid; + st->st_rdev = in->st_rdev; + st->st_size = in->st_size; + st->st_blksize = in->st_blksize; + st->st_blocks = in->st_blocks; + st->st_atim.tv_sec = in->lkl_st_atime; + st->st_atim.tv_nsec = in->st_atime_nsec; + st->st_mtim.tv_sec = in->lkl_st_mtime; + st->st_mtim.tv_nsec = in->st_mtime_nsec; + st->st_ctim.tv_sec = in->lkl_st_ctime; + st->st_ctim.tv_nsec = in->st_ctime_nsec; +} + +static int lklfuse_fgetattr(const char *path, struct stat *st, + struct fuse_file_info *fi) +{ + long ret; + struct lkl_stat lkl_stat; + + ret = lkl_sys_fstat(fi->fh, &lkl_stat); + if (ret) + return ret; + + lklfuse_xlat_stat(&lkl_stat, st); + return 0; +} + +static int lklfuse_getattr(const char *path, struct stat *st) +{ + long ret; + struct lkl_stat lkl_stat; + + ret = lkl_sys_lstat(path, &lkl_stat); + if (ret) + return ret; + + lklfuse_xlat_stat(&lkl_stat, st); + return 0; +} + +static int lklfuse_readlink(const char *path, char *buf, size_t len) +{ + long ret; + + ret = lkl_sys_readlink(path, buf, len); + if (ret < 0) + return ret; + + if ((size_t)ret == len) + ret = len - 1; + + buf[ret] = 0; + + return 0; +} + +static int lklfuse_mknod(const char *path, mode_t mode, dev_t dev) +{ + return lkl_sys_mknod(path, mode, dev); +} + +static int lklfuse_mkdir(const char *path, mode_t mode) +{ + return lkl_sys_mkdir(path, mode); +} + +static int lklfuse_unlink(const char *path) +{ + return lkl_sys_unlink(path); +} + +static int lklfuse_rmdir(const char *path) +{ + return lkl_sys_rmdir(path); +} + +static int lklfuse_symlink(const char *oldname, const char *newname) +{ + return lkl_sys_symlink(oldname, newname); +} + + +static int lklfuse_rename(const char *oldname, const char *newname) +{ + return lkl_sys_rename(oldname, newname); +} + +static int lklfuse_link(const char *oldname, const char *newname) +{ + return lkl_sys_link(oldname, newname); +} + +static int lklfuse_chmod(const char *path, mode_t mode) +{ + return lkl_sys_chmod(path, mode); +} + + +static int lklfuse_chown(const char *path, uid_t uid, gid_t gid) +{ + return lkl_sys_fchownat(LKL_AT_FDCWD, path, uid, gid, + LKL_AT_SYMLINK_NOFOLLOW); +} + +static int lklfuse_truncate(const char *path, off_t off) +{ + return lkl_sys_truncate(path, off); +} + +static int lklfuse_open3(const char *path, bool create, mode_t mode, + struct fuse_file_info *fi) +{ + long ret; + int flags; + + if ((fi->flags & O_ACCMODE) == O_RDONLY) + flags = LKL_O_RDONLY; + else if ((fi->flags & O_ACCMODE) == O_WRONLY) + flags = LKL_O_WRONLY; + else if ((fi->flags & O_ACCMODE) == O_RDWR) + flags = LKL_O_RDWR; + else + return -EINVAL; + + if (create) + flags |= LKL_O_CREAT; + + ret = lkl_sys_open(path, flags, mode); + if (ret < 0) + return ret; + + fi->fh = ret; + + return 0; +} + +static int lklfuse_create(const char *path, mode_t mode, + struct fuse_file_info *fi) +{ + return lklfuse_open3(path, true, mode, fi); +} + +static int lklfuse_open(const char *path, struct fuse_file_info *fi) +{ + return lklfuse_open3(path, false, 0, fi); +} + +static int lklfuse_read(const char *path, char *buf, size_t size, off_t offset, + struct fuse_file_info *fi) +{ + long ret; + ssize_t orig_size = size; + + do { + ret = lkl_sys_pread64(fi->fh, buf, size, offset); + if (ret <= 0) + break; + size -= ret; + offset += ret; + buf += ret; + } while (size > 0); + + return ret < 0 ? ret : orig_size - (ssize_t)size; + +} + +static int lklfuse_write(const char *path, const char *buf, size_t size, + off_t offset, struct fuse_file_info *fi) +{ + long ret; + ssize_t orig_size = size; + + do { + ret = lkl_sys_pwrite64(fi->fh, buf, size, offset); + if (ret <= 0) + break; + size -= ret; + offset += ret; + buf += ret; + } while (size > 0); + + return ret < 0 ? ret : orig_size - (ssize_t)size; +} + + +static int lklfuse_statfs(const char *path, struct statvfs *stat) +{ + long ret; + struct lkl_statfs lkl_statfs; + + ret = lkl_sys_statfs(path, &lkl_statfs); + if (ret < 0) + return ret; + + stat->f_bsize = lkl_statfs.f_bsize; + stat->f_frsize = lkl_statfs.f_frsize; + stat->f_blocks = lkl_statfs.f_blocks; + stat->f_bfree = lkl_statfs.f_bfree; + stat->f_bavail = lkl_statfs.f_bavail; + stat->f_files = lkl_statfs.f_files; + stat->f_ffree = lkl_statfs.f_ffree; + stat->f_favail = stat->f_ffree; + stat->f_fsid = *(unsigned long *)&lkl_statfs.f_fsid.val[0]; + stat->f_flag = lkl_statfs.f_flags; + stat->f_namemax = lkl_statfs.f_namelen; + + return 0; +} + +static int lklfuse_flush(const char *path, struct fuse_file_info *fi) +{ + return 0; +} + +static int lklfuse_release(const char *path, struct fuse_file_info *fi) +{ + return lkl_sys_close(fi->fh); +} + +static int lklfuse_fsync(const char *path, int datasync, + struct fuse_file_info *fi) +{ + if (datasync) + return lkl_sys_fdatasync(fi->fh); + else + return lkl_sys_fsync(fi->fh); +} + +static int lklfuse_setxattr(const char *path, const char *name, const char *val, + size_t size, int flags) +{ + return lkl_sys_setxattr(path, name, val, size, flags); +} + +static int lklfuse_getxattr(const char *path, const char *name, char *val, + size_t size) +{ + return lkl_sys_getxattr(path, name, val, size); +} + +static int lklfuse_listxattr(const char *path, char *list, size_t size) +{ + return lkl_sys_listxattr(path, list, size); +} + +static int lklfuse_removexattr(const char *path, const char *name) +{ + return lkl_sys_removexattr(path, name); +} + +static int lklfuse_opendir(const char *path, struct fuse_file_info *fi) +{ + struct lkl_dir *dir; + int err; + + dir = lkl_opendir(path, &err); + if (!dir) + return err; + + fi->fh = (uintptr_t)dir; + + return 0; +} + +/** Read directory + * + * This supersedes the old getdir() interface. New applications + * should use this. + * + * The filesystem may choose between two modes of operation: + * + * 1) The readdir implementation ignores the offset parameter, and + * passes zero to the filler function's offset. The filler + * function will not return '1' (unless an error happens), so the + * whole directory is read in a single readdir operation. This + * works just like the old getdir() method. + * + * 2) The readdir implementation keeps track of the offsets of the + * directory entries. It uses the offset parameter and always + * passes non-zero offset to the filler function. When the buffer + * is full (or an error happens) the filler function will return + * '1'. + * + * Introduced in version 2.3 + */ +static int lklfuse_readdir(const char *path, void *buf, fuse_fill_dir_t fill, + off_t off, struct fuse_file_info *fi) +{ + struct lkl_dir *dir = (struct lkl_dir *)(uintptr_t)fi->fh; + struct lkl_linux_dirent64 *de; + + while ((de = lkl_readdir(dir))) { + struct stat st = { 0, }; + + st.st_ino = de->d_ino; + st.st_mode = de->d_type << 12; + + if (fill(buf, de->d_name, &st, 0)) + break; + } + + if (!de) + return lkl_errdir(dir); + + return 0; +} + +static int lklfuse_releasedir(const char *path, struct fuse_file_info *fi) +{ + struct lkl_dir *dir = (struct lkl_dir *)(uintptr_t)fi->fh; + + return lkl_closedir(dir); +} + +static int lklfuse_fsyncdir(const char *path, int datasync, + struct fuse_file_info *fi) +{ + struct lkl_dir *dir = (struct lkl_dir *)(uintptr_t)fi->fh; + int fd = lkl_dirfd(dir); + + if (datasync) + return lkl_sys_fdatasync(fd); + else + return lkl_sys_fsync(fd); +} + +static int lklfuse_access(const char *path, int mode) +{ + return lkl_sys_access(path, mode); +} + +static int lklfuse_utimens(const char *path, const struct timespec tv[2]) +{ + struct lkl_timespec ts[2]; + + ts[0].tv_sec = tv[0].tv_sec; + ts[0].tv_nsec = tv[0].tv_nsec; + ts[1].tv_sec = tv[0].tv_sec; + ts[1].tv_nsec = tv[0].tv_nsec; + + return lkl_sys_utimensat(-1, path, (struct __lkl__kernel_timespec *)ts, + LKL_AT_SYMLINK_NOFOLLOW); +} + +static int lklfuse_fallocate(const char *path, int mode, off_t offset, + off_t len, struct fuse_file_info *fi) +{ + return lkl_sys_fallocate(fi->fh, mode, offset, len); +} + +const struct fuse_operations lklfuse_ops = { + .flag_nullpath_ok = 1, + .flag_nopath = 1, + .flag_utime_omit_ok = 1, + + .getattr = lklfuse_getattr, + .readlink = lklfuse_readlink, + .mknod = lklfuse_mknod, + .mkdir = lklfuse_mkdir, + .unlink = lklfuse_unlink, + .rmdir = lklfuse_rmdir, + .symlink = lklfuse_symlink, + .rename = lklfuse_rename, + .link = lklfuse_link, + .chmod = lklfuse_chmod, + .chown = lklfuse_chown, + .truncate = lklfuse_truncate, + .open = lklfuse_open, + .read = lklfuse_read, + .write = lklfuse_write, + .statfs = lklfuse_statfs, + .flush = lklfuse_flush, + .release = lklfuse_release, + .fsync = lklfuse_fsync, + .setxattr = lklfuse_setxattr, + .getxattr = lklfuse_getxattr, + .listxattr = lklfuse_listxattr, + .removexattr = lklfuse_removexattr, + .opendir = lklfuse_opendir, + .readdir = lklfuse_readdir, + .releasedir = lklfuse_releasedir, + .fsyncdir = lklfuse_fsyncdir, + .access = lklfuse_access, + .create = lklfuse_create, + .fgetattr = lklfuse_fgetattr, + /* .lock, */ + .utimens = lklfuse_utimens, + /* .bmap, */ + /* .ioctl, */ + /* .poll, */ + /* .write_buf, (SG io) */ + /* .read_buf, (SG io) */ + /* .flock, */ + .fallocate = lklfuse_fallocate, +}; + +static int start_lkl(void) +{ + long ret; + char mpoint[32], cmdline[16]; + + snprintf(cmdline, sizeof(cmdline), "mem=%dM", lklfuse.mb); + ret = lkl_start_kernel(&lkl_host_ops, cmdline); + if (ret) { + fprintf(stderr, "can't start kernel: %s\n", lkl_strerror(ret)); + goto out; + } + + ret = lkl_mount_dev(lklfuse.disk_id, lklfuse.part, lklfuse.type, + lklfuse.ro ? LKL_MS_RDONLY : 0, lklfuse.opts, + mpoint, sizeof(mpoint)); + + if (ret) { + fprintf(stderr, "can't mount disk: %s\n", lkl_strerror(ret)); + goto out_halt; + } + + ret = lkl_sys_chroot(mpoint); + if (ret) { + fprintf(stderr, "can't chdir to %s: %s\n", mpoint, + lkl_strerror(ret)); + goto out_umount; + } + + return 0; + +out_umount: + lkl_umount_dev(lklfuse.disk_id, lklfuse.part, 0, 1000); + +out_halt: + lkl_sys_halt(); + +out: + return ret; +} + +static void stop_lkl(void) +{ + int ret; + + ret = lkl_sys_chdir("/"); + if (ret) + fprintf(stderr, "can't chdir to /: %s\n", lkl_strerror(ret)); + ret = lkl_sys_umount("/", 0); + if (ret) + fprintf(stderr, "failed to umount disk: %d: %s\n", + lklfuse.disk_id, lkl_strerror(ret)); + lkl_sys_halt(); +} + +int main(int argc, char **argv) +{ + struct fuse_args args = FUSE_ARGS_INIT(argc, argv); + struct fuse_chan *ch; + struct fuse *fuse; + struct stat st; + char *mnt; + int fg, mt, ret; + + if (fuse_opt_parse(&args, &lklfuse, lklfuse_opts, lklfuse_opt_proc)) + return 1; + + if (!lklfuse.file || !lklfuse.type) { + fprintf(stderr, "no file or filesystem type specified\n"); + return 1; + } + + if (fuse_parse_cmdline(&args, &mnt, &mt, &fg)) + return 1; + + ret = stat(mnt, &st); + if (ret) { + perror(mnt); + goto out_free; + } + + ret = open(lklfuse.file, lklfuse.ro ? O_RDONLY : O_RDWR); + if (ret < 0) { + perror(lklfuse.file); + goto out_free; + } + + lklfuse.disk.fd = ret; + lklfuse.disk.dev = (char *)lklfuse.file; + + ret = lkl_disk_add(&lklfuse.disk); + if (ret < 0) { + fprintf(stderr, "can't add disk: %s\n", lkl_strerror(ret)); + goto out_close_disk; + } + + lklfuse.disk_id = ret; + + ch = fuse_mount(mnt, &args); + if (!ch) { + ret = -1; + goto out_close_disk; + } + + fuse = fuse_new(ch, &args, &lklfuse_ops, sizeof(lklfuse_ops), NULL); + if (!fuse) { + ret = -1; + goto out_fuse_unmount; + } + + fuse_opt_free_args(&args); + + if (fuse_daemonize(fg) || + fuse_set_signal_handlers(fuse_get_session(fuse))) { + ret = -1; + goto out_fuse_destroy; + } + + ret = start_lkl(); + if (ret) { + ret = -1; + goto out_remove_signals; + } + + if (mt) + fprintf(stderr, "warning: multithreaded mode not supported\n"); + + ret = fuse_loop(fuse); + + stop_lkl(); + +out_remove_signals: + fuse_remove_signal_handlers(fuse_get_session(fuse)); + +out_fuse_unmount: + if (ch) + fuse_unmount(mnt, ch); + +out_fuse_destroy: + if (fuse) + fuse_destroy(fuse); + +out_close_disk: + close(lklfuse.disk.fd); + +out_free: + free(mnt); + + return ret < 0 ? 1 : 0; +} diff --git a/tools/lkl/tests/lklfuse.sh b/tools/lkl/tests/lklfuse.sh new file mode 100755 index 000000000000..7f35dd53fc4e --- /dev/null +++ b/tools/lkl/tests/lklfuse.sh @@ -0,0 +1,110 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: GPL-2.0 + +script_dir=$(cd $(dirname ${BASH_SOURCE:-$0}); pwd) + +source $script_dir/test.sh + +cleanup() +{ + set -e + + sleep 1 + fusermount -u $dir + rm $file + rmdir $dir +} + + +# $1 - disk image +# $2 - fstype +function prepfs() +{ + set -e + + dd if=/dev/zero of=$1 bs=1024 count=102400 + + yes | mkfs.$2 $1 +} + +# $1 - disk image +# $2 - mount point +# $3 - filesystem type +lklfuse_mount() +{ + ${script_dir}/../lklfuse $1 $2 -o type=$3 +} + +# $1 - mount point +lklfuse_basic() +{ + set -e + + cd $1 + touch a + if ! [ -e ]; then exit 1; fi + rm a + mkdir a + if ! [ -d ]; then exit 1; fi + rmdir a +} + +# $1 - dir +# $2 - filesystem type +lklfuse_stressng() +{ + set -e + + if [ -z $(which stress-ng) ]; then + echo "missing stress-ng" + return $TEST_SKIP + fi + + cd $1 + + if [ "$2" = "vfat" ]; then + exclude="chmod,filename,link,mknod,symlink,xattr" + fi + + stress-ng --class filesystem --all 0 --timeout 10 \ + --exclude fiemap,$exclude --fallocate-bytes 10m \ + --sync-file-bytes 10m +} + +if [ "$1" = "-t" ]; then + shift + fstype=$1 + shift +fi + +if [ -z "$fstype" ]; then + fstype="ext4" +fi + +if ! [ -x $script_dir/../lklfuse ]; then + lkl_test_plan 0 "lklfuse.sh $fstype" + echo "lklfuse not available" + exit 0 +fi + +if ! [ -e /dev/fuse ]; then + lkl_test_plan 0 "lklfuse.sh $fstype" + echo "/dev/fuse not available" + exit 0 +fi + + +file=`mktemp` +dir=`mktemp -d` + +trap cleanup EXIT + +lkl_test_plan 4 "lklfuse $fstype" + +lkl_test_run 1 prepfs $file $fstype +lkl_test_run 2 lklfuse_mount $file $dir $fstype +lkl_test_run 3 lklfuse_basic $dir +# stress-ng returns 2 with no apparent failures so skip it for now +#lkl_test_run 4 lklfuse_stressng $dir $fstype +trap : EXIT +lkl_test_run 4 cleanup From patchwork Mon Mar 30 14:45:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hajime Tazaki X-Patchwork-Id: 1263996 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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=AU+bglRY; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=bf/0Y3ov; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (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 48rb2Y0xJVz9sP7 for ; Tue, 31 Mar 2020 01:49:25 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.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=FR/Qf1r/YXWm6VR0wq+hRwUoGTSEnwXeVszHxf8xyPQ=; b=AU+bglRYrQ6IXu bgPxpfnO/c/Z7VQqECM0U6HaMhklvxn4/j83509FpuXC1S6QARwDjew0qagN3R9c+aOPW0Nr2Zd6I O22dHI72PCy2FpSqelFBwijZx/zhMwOSW7kJMlwJMG4lcO2nGs987NQmfT6a8iHq0zSo95VWV3l1a uK75wV0PLkftHKO0Gm6eAEPZqu4azl5IaN9gdTbRkZBkjAlpOpJG8bvb86k6HpJLGAR2681+czeMB VYY6q/egEhXKkcNuHfVyHfOuFjaJSqgVKknAVNkmZ/dk3SUN2+eHbLfNdRimyenNqFA8GI2co1qfs muIDaYFUm8/mVMGXiw8A==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvj3-00056p-RD; Mon, 30 Mar 2020 14:49:17 +0000 Received: from mail-pj1-x1043.google.com ([2607:f8b0:4864:20::1043]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvj1-00056R-CK for linux-um@lists.infradead.org; Mon, 30 Mar 2020 14:49:16 +0000 Received: by mail-pj1-x1043.google.com with SMTP id jz1so6431062pjb.0 for ; Mon, 30 Mar 2020 07:49:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=WSuzOG+ewbWDKhDgxww0G95iKdrDh8WJzQDaiNNuPD0=; b=bf/0Y3ov/x7KJtJrtZkDbiz3v4S4/t1avT2BTMvBhVcGw2FuNnWOZF7yiVZBgOz4Kq qcdIfGwZjitOAJZhaSOEsudSnEf3kwVAaqE/ej+D1akVXyaulQ7wKOkd+OkfFsOWvMWV WkSrUFtejSIq8kASoA+Cz4/26ZHtDQM9DcgaDYf1SSHUKjWqshKLPQTxJN8wdD84mCR1 KdW/RF84TK0f5pArwhw4J1UkKZZ+6qKDtWe5Oj6YRQsU6CHRzihvcQsB1heuuQmqqF9K rRrZDlcSJFPDwMkeuIZhpoi2wz7XXVYhfWMlDguD/OJBpFCST2xESxZAX4ulxKNkDnRl H03g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=WSuzOG+ewbWDKhDgxww0G95iKdrDh8WJzQDaiNNuPD0=; b=U44Ex6BgXPMxm9mbEDeON+ucCSmBmFSxiUzAnijucyKi70bVEMNQ434F19XIEiPVlI 8bDre/UrdD7C/4zWbHKMn2K5QRL2NNh3tbhhz9bOYQu8bD0CM2mvh5J8aOxkyEzwUAdw 7rJwdA7EhivKkGNuTHA4G7yCy/9o6uskw4fwfhZTX4MqfQA+D+pjJVguj+qpSGre1R9K ouOIh7EJAOhidA2Q4DNITfnkeGb0vBlousOO0L//lLjZkLXZOnL1oVR0J9IwlavSYTCC boILT0BZxdy/Tp8dBiI1lSS1J0DTOETxrlIanYSzzKus/0pf+42o88f3pW9r1iH3CkA8 bZCw== X-Gm-Message-State: ANhLgQ2XX7spAQFn7w+Wl7v8osfvqUB6tMvKZU+2DzyqX056yp0gjlul SQ/bmjBdd74qv2k1mBLU2QI= X-Google-Smtp-Source: ADFU+vuSEPEP0URWHtgXEE0QX/kINogxQ4v2oPFoZEEXoG5aMvy+w0kPvgvOdLPWZYy4ioFrYEaNqA== X-Received: by 2002:a17:902:598e:: with SMTP id p14mr12051668pli.276.1585579754735; Mon, 30 Mar 2020 07:49:14 -0700 (PDT) Received: from earth-mac.local (219x123x138x129.ap219.ftth.ucom.ne.jp. [219.123.138.129]) by smtp.gmail.com with ESMTPSA id a127sm10401300pfa.111.2020.03.30.07.49.13 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 30 Mar 2020 07:49:14 -0700 (PDT) Received: by earth-mac.local (Postfix, from userid 501) id 4E8F1202804EDF; Mon, 30 Mar 2020 23:49:12 +0900 (JST) From: Hajime Tazaki To: linux-um@lists.infradead.org Subject: [RFC v4 21/25] um lkl: add documentation Date: Mon, 30 Mar 2020 23:45:53 +0900 Message-Id: X-Mailer: git-send-email 2.20.1 (Apple Git-117) In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200330_074915_431982_6C70A084 X-CRM114-Status: GOOD ( 14.67 ) X-Spam-Score: -0.2 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:1043 listed in] [list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [thehajime[at]gmail.com] -0.0 SPF_PASS SPF: sender matches SPF record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 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: linux-arch@vger.kernel.org, Conrad Meyer , Octavian Purdila , Motomu Utsumi , Akira Moroo , Thomas Liebetraut , Patrick Collins , linux-kernel-library@freelists.org, Chenyang Zhong , Yuan Liu , Gustavo Bittencourt Sender: "linux-um" Errors-To: linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Octavian Purdila A document describing brief introduction of LKL, why it is needed, and how it is used is added. The document is located under uml/ directory. Cc: Chenyang Zhong Cc: Conrad Meyer Cc: Gustavo Bittencourt Cc: H.K. Jerry Chu Cc: Motomu Utsumi Cc: Patrick Collins Cc: Thomas Liebetraut Cc: Yuan Liu Signed-off-by: Octavian Purdila --- Documentation/virt/uml/lkl.txt | 64 ++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 Documentation/virt/uml/lkl.txt diff --git a/Documentation/virt/uml/lkl.txt b/Documentation/virt/uml/lkl.txt new file mode 100644 index 000000000000..f6d581092331 --- /dev/null +++ b/Documentation/virt/uml/lkl.txt @@ -0,0 +1,64 @@ + +Introduction +============ + +LKL (Linux Kernel Library) is aiming to allow reusing the Linux kernel code as +extensively as possible with minimal effort and reduced maintenance overhead. + +Examples of how LKL can be used are: creating userspace applications (running on +Linux and other operating systems) that can read or write Linux filesystems or +can use the Linux networking stack, creating kernel drivers for other operating +systems that can read Linux filesystems, bootloaders support for reading/writing +Linux filesystems, etc. + +With LKL, the kernel code is compiled into an object file that can be directly +linked by applications. The API offered by LKL is based on the Linux system call +interface. + +LKL is implemented as one of the mode of UML (arch/um). It uses host operations +defined by the application or a host library (tools/lkl/lib). + + +Supported hosts +=============== + +The supported host for now is Linux (x86 architecture) userspace applications. + + +Building LKL the host library and LKL applications +================================================== + + $ make -C tools/lkl + +will build LKL as a object file, it will install it in tools/lkl/lib together +with the headers files in tools/lkl/include then will build the host library, +tests and a few of application examples: + +* tests/boot - a simple applications that uses LKL and exercises the basic LKL + APIs + +* tests/net-test - a simple applications that uses network feature of LKL and + exercises the basic network-related APIs + +* fs2tar - a tool that converts a filesystem image to a tar archive + +* cptofs/cpfromfs - a tool that copies files to/from a filesystem image + +* lklfuse - a tool that can mount a filesystem image in userspace, + without root privileges, using FUSE + + +Building LKL on Ubuntu +----------------------- + + $ sudo apt-get install libfuse-dev libarchive-dev xfsprogs + + # Optional, if you would like to be able to run tests + $ sudo apt-get install btrfs-tools + $ pip install yamlish junit_xml + + $ make -C tools/lkl + + # To check that everything works: + $ cd tools/lkl + $ make run-tests From patchwork Mon Mar 30 14:45:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hajime Tazaki X-Patchwork-Id: 1263997 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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=DyvH8sPg; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=ZmUVk8cm; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (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 48rb2d2T9lz9sRN for ; Tue, 31 Mar 2020 01:49:29 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.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=t+qqdb20e2OrvuF1oawJS1JKXysYUUbTci1MsJXtFxs=; b=DyvH8sPgzyPlb9 om3opluneVfb4QsKz7NiK0uQfJuJBoALdVaAdrjijQIyKI3JOjvtEP15Kq34+l5ksczZ6rksj8mC+ fUL8VTANBLHRavK7Z85L1shlO5SqcQC3+X2WV0Vfh2U22CTfbxaLjcPzDu+ykX7edkRn+MQeNqE4f /vJXbQdcJfyLRrpX5i71diAIh/+7jasKhGUCDa2BBmSBhEgcI54E1Xj9LaVAKxYCKV1Vc8R5E3mzN B4HPe5xD7BWEHYwwZPidn7XGo/Z2os4VUpT7xoa+vrJHZnOKONKRuHXNwmdZMCFjYC3a6Ym9BJSkj z8xQNy62FxlLePVgb49A==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvj7-00057p-0d; Mon, 30 Mar 2020 14:49:21 +0000 Received: from mail-pj1-x1042.google.com ([2607:f8b0:4864:20::1042]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvj4-000576-BY for linux-um@lists.infradead.org; Mon, 30 Mar 2020 14:49:20 +0000 Received: by mail-pj1-x1042.google.com with SMTP id ng8so7681047pjb.2 for ; Mon, 30 Mar 2020 07:49:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=VPfgMJ4whYlDNg51uPEu7Wqa2lUjKNAf/x39mbVIwkk=; b=ZmUVk8cm0o9cr+W4Af0MMA0v9cpaChWCpWT68gZX9HL1earyVTWijmMW5rORv3fAzW +VQvC3HMRVco5EFl2T8p5Mu3J2iA5rKw2tlpcsmgQMdZnIB3cnRxMjO3qSHxyR6zn6xJ sN5+crtBmOynKtoC9tOEz7BKapawhiO6oTQvO4uh0l84ruv7BqoAgBagLjl08o1vEfrf PGneaaaMj5fearO/kB7jQTB2bsZ1jLsdyXcIwynhPz6ep6lY79t4Xc+5N2I3GO2w6dXz TvM2Omcd7Lnnh4zTRGK31VY0Ola0+/fwNgWXKBz6FuNfN8yB9ixZKDKIYANmsa6s9V+p 8LYA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=VPfgMJ4whYlDNg51uPEu7Wqa2lUjKNAf/x39mbVIwkk=; b=K+OP8kwQi2ITUiSPwjUY8S8Q6ajJ2p2rB1d8NOkvZ9FuDfcQQdiqNnym6F1wmOTmDN VBSyG+Dwc4vzbqAqj70YuPnNv1BiPp0mhMcLqzucG6/YhElINuZuwCpIfteyY0PGzuyR jzI8S8GDZczzkbI7gyiNcGsm1Q1Hl5596HI+gyoPWpq/X8Ipv3L74Pm7K/zu7HUQ7v7o lUzu2yoZmInz4WJ0Jac9besrNmr0drxkjwzQ+jk5tPatUYDQ1WElIqg9iYHcoNuGDpS4 //O6idVv324ED/X9q4O/Uvz0QRVq2GfCvbDaKsTX9ovTbYiKmZvTZT81kNMVZl/9AUef Hs+w== X-Gm-Message-State: ANhLgQ1uWzZKcodb5bKxd1wan671X4ugHf1buId/z0Q/2vNg7JLRFW94 Ws/UVkSVzE3AlGtEkbr+QoQ= X-Google-Smtp-Source: ADFU+vsERiTjq1ijFCVWk+gxYMWmNlmjTC1Ml4fgRDaYTI071a98DI7/urLrnLMRH4iI0v1qyZ0zgA== X-Received: by 2002:a17:902:9a09:: with SMTP id v9mr12482069plp.341.1585579757659; Mon, 30 Mar 2020 07:49:17 -0700 (PDT) Received: from earth-mac.local (219x123x138x129.ap219.ftth.ucom.ne.jp. [219.123.138.129]) by smtp.gmail.com with ESMTPSA id k70sm9734177pga.91.2020.03.30.07.49.16 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 30 Mar 2020 07:49:17 -0700 (PDT) Received: by earth-mac.local (Postfix, from userid 501) id 64785202804EE2; Mon, 30 Mar 2020 23:49:15 +0900 (JST) From: Hajime Tazaki To: linux-um@lists.infradead.org Subject: [RFC v4 22/25] um lkl: add CI scripts to conduct regression tests Date: Mon, 30 Mar 2020 23:45:54 +0900 Message-Id: <49a31f01759ea22e9331afd22c48e22cf9ae24d4.1585579244.git.thehajime@gmail.com> X-Mailer: git-send-email 2.20.1 (Apple Git-117) In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200330_074918_417457_BE597A99 X-CRM114-Status: GOOD ( 12.36 ) X-Spam-Score: -0.2 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:1042 listed in] [list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [thehajime[at]gmail.com] -0.0 SPF_PASS SPF: sender matches SPF record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 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: Octavian Purdila , linux-kernel-library@freelists.org, linux-arch@vger.kernel.org, Hajime Tazaki , Akira Moroo Sender: "linux-um" Errors-To: linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org For the continuous integration (CI), we use CircleCI with multiple test targets triggered with a single commit. The test also conducts memory checks using valgrind in order to prevent enbug. Signed-off-by: Hajime Tazaki --- .circleci/config.yml | 196 +++++++++++++++++++++++++++++++ tools/lkl/scripts/checkpatch.sh | 60 ++++++++++ tools/lkl/scripts/lkl-jenkins.sh | 21 ++++ 3 files changed, 277 insertions(+) create mode 100644 .circleci/config.yml create mode 100755 tools/lkl/scripts/checkpatch.sh create mode 100755 tools/lkl/scripts/lkl-jenkins.sh diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 000000000000..5bdf059014c0 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,196 @@ +version: 2 +general: + artifacts: + +do_steps: &do_steps + steps: + - run: echo "$CROSS_COMPILE" > ~/_cross_compile + - restore_cache: + key: code-tree-shallow-{{ .Environment.CACHE_VERSION }} + - run: + name: checkout build tree + command: | + mkdir -p ~/.ssh/ + ssh-keyscan -H github.com >> ~/.ssh/known_hosts + if ! [ -d .git ]; then + git clone --depth=1 $CIRCLE_REPOSITORY_URL .; + fi + if [[ $CIRCLE_BRANCH == pull/* ]]; then + git fetch --depth=1 origin $CIRCLE_BRANCH/head; + else + git fetch --depth=1 origin $CIRCLE_BRANCH; + fi + git reset --hard $CIRCLE_SHA1 + - save_cache: + key: code-tree-shallow-{{ .Environment.CACHE_VERSION }}-{{ epoch }} + paths: + - /home/ubuntu/project/.git + - run: + name: clean + command: | + make mrproper + cd tools/lkl && make clean-conf + rm -rf ~/junit + - run: mkdir -p /home/ubuntu/.ccache + - restore_cache: + key: compiler-cache-{{ checksum "~/_cross_compile" }}-{{ .Environment.CACHE_VERSION }} + - run: cd tools/lkl && make -j8 ${MKARG} + - run: mkdir -p ~/destdir && cd tools/lkl && make DESTDIR=~/destdir + - save_cache: + paths: + - /home/ubuntu/.ccache + key: compiler-cache-{{ checksum "~/_cross_compile" }}-{{ .Environment.CACHE_VERSION }}-{{ epoch }} + - run: + name: run tests + command: | + mkdir -p ~/junit + make -C tools/lkl run-tests tests="--junit-dir ~/junit" + no_output_timeout: "90m" + - run: + name: collecting test results + command: | + find ./tools/lkl/ -type f -name "*.xml" -exec mv {} ~/junit/ \; + - store_test_results: + path: ~/junit + - store_artifacts: + path: ~/junit + + +do_uml_steps: &do_uml_steps + steps: + - run: echo "$CROSS_COMPILE" > ~/_cross_compile + - restore_cache: + key: code-tree-shallow-{{ .Environment.CACHE_VERSION }} + - run: + name: checkout build tree + command: | + mkdir -p ~/.ssh/ + ssh-keyscan -H github.com >> ~/.ssh/known_hosts + if ! [ -d .git ]; then + git clone --depth=1 $CIRCLE_REPOSITORY_URL .; + fi + if [[ $CIRCLE_BRANCH == pull/* ]]; then + git fetch --depth=1 origin $CIRCLE_BRANCH/head; + else + git fetch --depth=1 origin $CIRCLE_BRANCH; + fi + git reset --hard $CIRCLE_SHA1 + - save_cache: + key: code-tree-shallow-{{ .Environment.CACHE_VERSION }}-{{ epoch }} + paths: + - /home/ubuntu/project/.git + - run: mkdir -p /home/ubuntu/.ccache + - restore_cache: + key: compiler-cache-{{ checksum "~/_cross_compile" }}-{{ .Environment.CACHE_VERSION }} + - run: + name: build + command: | + sudo apt-get update + sudo apt-get install -y gcc-multilib g++-multilib + make defconfig ARCH=um SUBARCH=$SUBARCH + make ARCH=um SUBARCH=$SUBARCH + - save_cache: + paths: + - /home/ubuntu/.ccache + key: compiler-cache-{{ checksum "~/_cross_compile" }}-{{ .Environment.CACHE_VERSION }}-{{ epoch }} + - run: + name: test + command: | + # XXX: i386 build doesn't work with the test + if [ $CIRCLE_STAGE = "i386_uml" ] || [ $CIRCLE_STAGE = "i386_uml_on_x86_64" ]; then + exit 0 + fi + ./linux rootfstype=hostfs ro mem=1g loglevel=10 init="/bin/bash -c exit" || export RETVAL=$? + # SIGABRT=6 => 128+6 + if [ $RETVAL != "134" ]; then + exit 1 + fi + +## Customize the test machine +jobs: + x86_64: + docker: + - image: lkldocker/circleci-x86_64:0.7 + environment: + CROSS_COMPILE: "" + <<: *do_steps + + i386: + docker: + - image: lkldocker/circleci-i386:0.1 + environment: + CROSS_COMPILE: "" + <<: *do_steps + + x86_64_valgrind: + docker: + - image: lkldocker/circleci-x86_64:0.7 + environment: + CROSS_COMPILE: "" + VALGRIND: 1 + <<: *do_steps + + x86_64_uml: + docker: + - image: lkldocker/circleci-x86_64:0.7 + environment: + CROSS_COMPILE: "" + TMPDIR: "/tmp" # required for not using /dev/shm + SUBARCH: "x86_64" + <<: *do_uml_steps + + i386_uml: + docker: + - image: lkldocker/circleci-i386:0.1 + environment: + CROSS_COMPILE: "" + SUBARCH: "i386" + TMPDIR: "/tmp" # required for not using /dev/shm + <<: *do_uml_steps + + i386_uml_on_x86_64: + docker: + - image: lkldocker/circleci-x86_64:0.7 + environment: + CROSS_COMPILE: "" + TMPDIR: "/tmp" # required for not using /dev/shm + SUBARCH: "i386" + <<: *do_uml_steps + + checkpatch: + docker: + - image: lkldocker/circleci:0.5 + environment: + steps: + - restore_cache: + key: code-tree-full-history-{{ .Environment.CACHE_VERSION }} + - checkout + - run: sudo pip install ply + - run: tools/lkl/scripts/checkpatch.sh + - save_cache: + key: code-tree-full-history-{{ .Environment.CACHE_VERSION }}-{{ epoch }} + paths: + - /home/ubuntu/project/.git + when: always + +workflows: + version: 2 + build: + jobs: + - x86_64 + - x86_64_valgrind + - checkpatch + - i386 + - x86_64_uml + - i386_uml + - i386_uml_on_x86_64 + nightly: + triggers: + - schedule: + cron: "0 0 * * *" + filters: + branches: + only: + - master + jobs: + - x86_64_valgrind diff --git a/tools/lkl/scripts/checkpatch.sh b/tools/lkl/scripts/checkpatch.sh new file mode 100755 index 000000000000..0c02ca6b21a2 --- /dev/null +++ b/tools/lkl/scripts/checkpatch.sh @@ -0,0 +1,60 @@ +#!/bin/sh -ex +# SPDX-License-Identifier: GPL-2.0 + +if [ -z "$origin_master" ]; then + origin_master="origin/master" +fi + +UPSTREAM=git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git +LKL=github.com:lkl/linux.git + +upstream=`git remote -v | grep $UPSTREAM | cut -f1 | head -n1` +lkl=`git remote -v | grep $LKL | cut -f1 | head -n1` + +if [ -z "$upstream" ]; then + git fetch --tags --progress git://$UPSTREAM +else + git fetch --tags $upstream +fi + +if [ -z "$lkl" ]; then + git remote add lkl-upstream git@$LKL || true + lkl=`git remote -v | grep $LKL | cut -f1 | head -n1` +fi + +if [ -z "$lkl" ]; then + echo "can't find lkl remote, quiting" + exit 1 +fi + +git fetch $lkl +git fetch --tags $upstream + +# find the last upstream tag to avoid checking upstream commits during +# upstream merges +tag=`git tag --sort='-*authordate' | grep ^v | head -n1` +tmp=`mktemp -d` + +commits=$(git log --no-merges --pretty=format:%h HEAD ^$lkl/master ^$tag) +for c in $commits; do + git format-patch -1 -o $tmp $c +done + +if [ -z "$c" ]; then + echo "there are not commits/patches to check, quiting." + rmdir $tmp + exit 0 +fi + +./scripts/checkpatch.pl --ignore FILE_PATH_CHANGES $tmp/*.patch +rm $tmp/*.patch + +# checkpatch.pl does not know how to deal with 3 way diffs which would +# be useful to check the conflict resolutions during merges... +#for c in `git log --merges --pretty=format:%h HEAD ^$origin_master ^$tag`; do +# git log --pretty=email $c -1 > $tmp/$c.patch +# git diff $c $c^1 $c^2 >> $tmp/$c.patch +#done + +rmdir $tmp + diff --git a/tools/lkl/scripts/lkl-jenkins.sh b/tools/lkl/scripts/lkl-jenkins.sh new file mode 100755 index 000000000000..eaadc6e90143 --- /dev/null +++ b/tools/lkl/scripts/lkl-jenkins.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +set -e + +script_dir=$(cd $(dirname ${BASH_SOURCE:-$0}); pwd) +basedir=$(cd $script_dir/../../..; pwd) + +export PATH=$PATH:/sbin + +build_and_test() +{ + cd $basedir + make mrproper + cd tools/lkl + make clean-conf + make -j4 + make run-tests +} + +build_and_test From patchwork Mon Mar 30 14:45:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hajime Tazaki X-Patchwork-Id: 1263998 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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=bOdlO7L+; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=TxNVbqw8; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (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 48rb2r4GBfz9sP7 for ; Tue, 31 Mar 2020 01:49:40 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.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=nDh5p6cS7TblFbColUIs8bVEEv2dwZ92BeUK3rZ7xpc=; b=bOdlO7L+Qf+B8i rd59bs9/Q9THNXmTDREoJoKl4S90uBz1tJYUVg+glCzlAcK3nemKiuoFo97Txmw8yHvKrHxZpwlyn Ubnl/rHXJpGrl/CIriTyCHDBBPBr7Ik2AfaWIAkpMfG0yijf2dq0Q0XGfq1rJYlcmlDiB1gBwffvO sHyDO+cIWHfkis7wfQCbwIRqyVE+3BNgwcGms8fyfCscbzZIqrAfuuwLJkfUxi1J3TYZctvxtmFdq fiBzu7xlUHcdRjzKOQYADHAZTuaPLqpqgTCJH78GrrWCy3M1PCrLLRsn4vmibIna21jjRBHGPhKwR C0P7aF5gC2/20UmFmW8g==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvjG-00059P-AX; Mon, 30 Mar 2020 14:49:30 +0000 Received: from mail-pl1-x642.google.com ([2607:f8b0:4864:20::642]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvjA-00058d-Ic for linux-um@lists.infradead.org; Mon, 30 Mar 2020 14:49:28 +0000 Received: by mail-pl1-x642.google.com with SMTP id e1so6804632plt.9 for ; Mon, 30 Mar 2020 07:49:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=R8n8lvKR4QQt0TRszS55Rv0tamP2PJ4VtgSKPMdoabQ=; b=TxNVbqw8EOtH02z8PLY+6z4mq09IA7owgxehbLk3eSE6YTfj8H3ytNZzl8qGoZBYWV cSQ6JGiC4CxPDKbb/bEMMPgI+f4R0awnbBC1mSEE2B9DfdFtqzHDQHmVlLQE0bfj2qaj iP6xycVUj2sI4vrXX6IiLepAmuEocKUP25aK3nq/hvqgRIJefdZduIcOqMG6eKINYOl0 7qG+uazYTqEVrRaMmYx3M+21Ndr7iEqxlUdaBAAFOs3P//WawkacX80n28ESTbCS8iuC VoQ6YEM48opNqUlx+U/jJI1OWs2gvZSsCGJ0C4u8sWms/bQbOLv+piDH9k7fT8579wM7 s/dg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=R8n8lvKR4QQt0TRszS55Rv0tamP2PJ4VtgSKPMdoabQ=; b=gCcIX0/rUtSzwcgq+TCxU9rGlevno0vXNAblPzlWdBU7J0wkF1EqS1vFNwrdiyfFIV hF8ojNx90NwGtvOlSCFVZziGiV8nIyrBKvmDuzih8QLvVGab9I+Cc+aVPqpHYmfIZxCr x6dZlSck5/sZMyINShQqDqNWhUgu/7rfDDis3ZrSjRjf1r/etji8sQ3YqgPeNgsS2Qip 2iEBWlzDzxk4jDuCzjcvk09X59Ah93kpyjk+7kL2gQu+vMa8BhYV2irB8zTweNH9zPxN /Kl++pVX3rVb1wkG1kqcqtRtNbh+uV6TTO9DgBbrm1FICKzO9ci2BzHPkbsmVY1OnLFV +GZw== X-Gm-Message-State: ANhLgQ04GKykpqq5KaPQn/jqr1eElgshRJIpSLL5SVcCtcanHDxBnA+7 qpTxKMRQj6PvqNR2RXk5JMPt1R6Akr6iIw== X-Google-Smtp-Source: ADFU+vvTQuxJ6f0nV5vQ8as3bge5BcZJPL6aMc/jDZjmfJbl2Ysin74wdonRExLEwoWIqw1oenz94g== X-Received: by 2002:a17:90b:8c4:: with SMTP id ds4mr16706377pjb.44.1585579763687; Mon, 30 Mar 2020 07:49:23 -0700 (PDT) Received: from earth-mac.local (219x123x138x129.ap219.ftth.ucom.ne.jp. [219.123.138.129]) by smtp.gmail.com with ESMTPSA id j17sm10414951pfd.175.2020.03.30.07.49.22 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 30 Mar 2020 07:49:23 -0700 (PDT) Received: by earth-mac.local (Postfix, from userid 501) id 5C81E202804EF9; Mon, 30 Mar 2020 23:49:21 +0900 (JST) From: Hajime Tazaki To: linux-um@lists.infradead.org Subject: [RFC v4 23/25] um lkl: add UML network driver for lkl Date: Mon, 30 Mar 2020 23:45:55 +0900 Message-Id: <0f087b36ad579eeb8062b12e9e61566d9b5b18ac.1585579244.git.thehajime@gmail.com> X-Mailer: git-send-email 2.20.1 (Apple Git-117) In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200330_074924_629584_D1E90184 X-CRM114-Status: GOOD ( 21.98 ) X-Spam-Score: -0.2 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:642 listed in] [list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [thehajime[at]gmail.com] -0.0 SPF_PASS SPF: sender matches SPF record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 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: Octavian Purdila , linux-kernel-library@freelists.org, linux-arch@vger.kernel.org, Hajime Tazaki , Akira Moroo Sender: "linux-um" Errors-To: linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org This commit adds the use of the UML drivers of network interfaces which should be able to use any backend configured by boot command line parameters. Currently vector tap backend and (obsolte) slirp and tuntap backends are tested. Since the UML drivers use LKL irq infrastructure, the build system only picks required object files of UML, and LKL adds trivial glue code and ifdefs into UML code so that existing driver codes can be used for LKL as-is. Here is a benchmark number with netperf (TCP_STREAM/TCP_MAERTS in Mbps) over 10Gbps ethernet. |TCP_STREAM | TCP_MAERTS -------------------- -------------------------- UMMODE_LIB (um-tap) | 1932.71 | 8.58 UMMODE_LIB (vec-tap) | 7565.97 | 9216.49 UMMODE_LIB (virtio) | 8743.91 | 9310.35 UMMODE_KERN (um-tap) | 1819.09 | 0.84 UMMODE_KERN (vec-tap)| 5418.51 | 9412.07 - setup We varied client side (netperf) with different net drivers/devices. tso,tx/rx csum are enabled if possible. +--docker0--+ | | 10GbEth netperf +---tap0 eth0 +==========+ eth0 +---+ netserver (client) (ixgbe) (ixgbe) <-- Linux box (4.18.5) --> <-- Linux box (4.17.19) --> - summary With vector driver over tap backend, UMMODE_LIB can reach similar results with the one of virtio. And outperforming to UMMODE_KERN is the result of simplified user/kernel-space transision (just function calls rather than interposision by ptrace&co). Signed-off-by: Hajime Tazaki --- .circleci/config.yml | 2 + arch/um/drivers/Makefile | 2 + arch/um/include/asm/irq.h | 2 + arch/um/kernel/Makefile | 4 ++ arch/um/kernel/irq.c | 4 ++ arch/um/lkl/Kconfig | 2 + arch/um/lkl/configs/lkl_defconfig | 2 +- arch/um/lkl/include/asm/irq.h | 3 ++ arch/um/lkl/include/uapi/asm/host_ops.h | 6 +++ arch/um/lkl/kernel/asm-offsets.c | 1 + arch/um/lkl/kernel/irq.c | 33 +++++++++++++ arch/um/lkl/kernel/setup.c | 4 ++ arch/um/lkl/mm/bootmem.c | 33 +++++++++++++ arch/um/os-Linux/Makefile | 5 ++ tools/lkl/Makefile.autoconf | 2 + tools/lkl/include/lkl.h | 9 ++++ tools/lkl/include/lkl_host.h | 1 + tools/lkl/lib/Build | 1 + tools/lkl/lib/config.c | 6 +++ tools/lkl/lib/net.c | 8 ++++ tools/lkl/lib/posix-host.c | 3 ++ tools/lkl/lib/um/Build | 2 + tools/lkl/lib/um/um_glue.c | 39 +++++++++++++++ tools/lkl/lib/um/um_net.c | 30 ++++++++++++ tools/lkl/tests/net-setup.sh | 63 +++++++++++++++++++++++++ tools/lkl/tests/net-test.c | 18 +++++-- tools/lkl/tests/net.sh | 45 ++++++++++++++++++ tools/lkl/tests/run.py | 2 + 28 files changed, 326 insertions(+), 6 deletions(-) create mode 100644 tools/lkl/lib/um/Build create mode 100644 tools/lkl/lib/um/um_glue.c create mode 100644 tools/lkl/lib/um/um_net.c diff --git a/.circleci/config.yml b/.circleci/config.yml index 5bdf059014c0..df1554078a4b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -43,6 +43,8 @@ do_steps: &do_steps - run: name: run tests command: | + sudo apt-get update + sudo apt-get install -y slirp mkdir -p ~/junit make -C tools/lkl run-tests tests="--junit-dir ~/junit" no_output_timeout: "90m" diff --git a/arch/um/drivers/Makefile b/arch/um/drivers/Makefile index a290821e355c..3cce6c81079e 100644 --- a/arch/um/drivers/Makefile +++ b/arch/um/drivers/Makefile @@ -37,7 +37,9 @@ $(obj)/vde.o: $(obj)/vde_kern.o $(obj)/vde_user.o # When the above is fixed, don't forget to add this too! #targets += $(obj)/pcap.o +ifeq ($(UMMODE),kernel) obj-y := stdio_console.o fd.o chan_kern.o chan_user.o line.o +endif obj-$(CONFIG_SSL) += ssl.o obj-$(CONFIG_STDERR_CONSOLE) += stderr_console.o diff --git a/arch/um/include/asm/irq.h b/arch/um/include/asm/irq.h index 42c6205e2dc4..839b86f29b8a 100644 --- a/arch/um/include/asm/irq.h +++ b/arch/um/include/asm/irq.h @@ -32,6 +32,8 @@ #endif +#ifdef CONFIG_UMMODE_KERN #define NR_IRQS (LAST_IRQ + 1) +#endif /* CONFIG_UMMODE_KERN */ #endif diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile index 5aa882011e04..78b49eb9bf81 100644 --- a/arch/um/kernel/Makefile +++ b/arch/um/kernel/Makefile @@ -12,12 +12,16 @@ CPPFLAGS_vmlinux.lds := -DSTART=$(LDS_START) \ -DELF_ARCH=$(LDS_ELF_ARCH) \ -DELF_FORMAT=$(LDS_ELF_FORMAT) \ $(LDS_EXTRA) +ifeq ($(UMMODE),kernel) extra-y := vmlinux.lds obj-y = config.o exec.o exitcode.o irq.o ksyms.o mem.o \ physmem.o process.o ptrace.o reboot.o sigio.o \ signal.o syscall.o sysrq.o time.o tlb.o trap.o \ um_arch.o umid.o maccess.o kmsg_dump.o skas/ +else ifeq ($(UMMODE),library) +obj-y = irq.o +endif obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o obj-$(CONFIG_GPROF) += gprof_syms.o diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c index 3577118bb4a5..26e6bd804f99 100644 --- a/arch/um/kernel/irq.c +++ b/arch/um/kernel/irq.c @@ -406,6 +406,7 @@ int deactivate_all_fds(void) return 0; } +#ifdef CONFIG_UMMODE_KERN /* * do_IRQ handles all normal device IRQs (the special * SMP cross-CPU interrupts have their own specific @@ -420,6 +421,7 @@ unsigned int do_IRQ(int irq, struct uml_pt_regs *regs) set_irq_regs(old_regs); return 1; } +#endif /* CONFIG_UMMODE_KERN */ void um_free_irq(unsigned int irq, void *dev) { @@ -446,6 +448,7 @@ int um_request_irq(unsigned int irq, int fd, int type, EXPORT_SYMBOL(um_request_irq); +#ifdef CONFIG_UMMODE_KERN /* * irq_chip must define at least enable/disable and ack when * the edge handler is used. @@ -597,3 +600,4 @@ unsigned long from_irq_stack(int nested) return mask & ~1; } +#endif /* CONFIG_UMMODE_KERN */ diff --git a/arch/um/lkl/Kconfig b/arch/um/lkl/Kconfig index c72c40226509..2b6b4063045c 100644 --- a/arch/um/lkl/Kconfig +++ b/arch/um/lkl/Kconfig @@ -81,3 +81,5 @@ config HZ default 100 endmenu + +source "arch/um/drivers/Kconfig" diff --git a/arch/um/lkl/configs/lkl_defconfig b/arch/um/lkl/configs/lkl_defconfig index 7050c233a17e..f2f218a17185 100644 --- a/arch/um/lkl/configs/lkl_defconfig +++ b/arch/um/lkl/configs/lkl_defconfig @@ -113,7 +113,7 @@ CONFIG_UML_NET=y CONFIG_UML_NET_TUNTAP=y # CONFIG_UML_NET_SLIP is not set # CONFIG_UML_NET_DAEMON is not set -# CONFIG_UML_NET_VECTOR is not set +CONFIG_UML_NET_VECTOR=y # CONFIG_UML_NET_VDE is not set # CONFIG_UML_NET_MCAST is not set # CONFIG_UML_NET_PCAP is not set diff --git a/arch/um/lkl/include/asm/irq.h b/arch/um/lkl/include/asm/irq.h index 948fc54cb76c..2ee00ffde21c 100644 --- a/arch/um/lkl/include/asm/irq.h +++ b/arch/um/lkl/include/asm/irq.h @@ -2,6 +2,9 @@ #ifndef _ASM_LKL_IRQ_H #define _ASM_LKL_IRQ_H +/* pull UML's definitions */ +#include "../../../include/asm/irq.h" + #define IRQ_STATUS_BITS (sizeof(long) * 8) #define NR_IRQS ((int)(IRQ_STATUS_BITS * IRQ_STATUS_BITS)) diff --git a/arch/um/lkl/include/uapi/asm/host_ops.h b/arch/um/lkl/include/uapi/asm/host_ops.h index fe4382c3050a..0230885f4f64 100644 --- a/arch/um/lkl/include/uapi/asm/host_ops.h +++ b/arch/um/lkl/include/uapi/asm/host_ops.h @@ -17,6 +17,10 @@ struct lkl_jmp_buf { * These operations must be provided by a host library or by the application * itself. * + * @um_devices - string containg the list of UML devices in command line + * format. This string is appended to the kernel command line and + * is provided here for convenience to be implemented by the host library. + * * @print - optional operation that receives console messages * * @panic - called during a kernel panic @@ -74,6 +78,8 @@ struct lkl_jmp_buf { * @jmp_buf_longjmp - perform a jump back to the saved jump buffer */ struct lkl_host_operations { + const char *um_devices; + void (*print)(const char *str, int len); void (*panic)(void); diff --git a/arch/um/lkl/kernel/asm-offsets.c b/arch/um/lkl/kernel/asm-offsets.c index 6be0763698dc..6fdca6df21a2 100644 --- a/arch/um/lkl/kernel/asm-offsets.c +++ b/arch/um/lkl/kernel/asm-offsets.c @@ -1,2 +1,3 @@ // SPDX-License-Identifier: GPL-2.0 /* Dummy asm-offsets.c file. Required by kbuild and ready to be used - hint! */ +#include diff --git a/arch/um/lkl/kernel/irq.c b/arch/um/lkl/kernel/irq.c index c794412f85d9..59e8572862a2 100644 --- a/arch/um/lkl/kernel/irq.c +++ b/arch/um/lkl/kernel/irq.c @@ -11,6 +11,11 @@ #include #include +#if defined(__linux) && (defined(__i386) || defined(__x86_64)) +#include +#endif +void *um_os_signal(int signum, void *handler); + /* * To avoid much overhead we use an indirect approach: the irqs are marked using * a bitmap (array of longs) and a summary of the modified bits is kept in a @@ -174,6 +179,16 @@ void arch_local_irq_restore(unsigned long flags) irqs_enabled = flags; } +#if defined(__linux) && (defined(__i386) || defined(__x86_64)) +static void sig_handler(int sig) +{ + if (sig != SIGIO) + return; + + sigio_handler(sig, NULL, NULL); +} +#endif + void init_IRQ(void) { int i; @@ -181,6 +196,11 @@ void init_IRQ(void) for (i = 0; i < NR_IRQS; i++) irq_set_chip_and_handler(i, &dummy_irq_chip, handle_simple_irq); +#if defined(__linux) && (defined(__i386) || defined(__x86_64)) + /* Initialize EPOLL Loop */ + os_setup_epoll(); + um_os_signal(SIGIO, sig_handler); +#endif pr_info("lkl: irqs initialized\n"); } @@ -188,3 +208,16 @@ void cpu_yield_to_irqs(void) { cpu_relax(); } + +#if defined(__linux) && (defined(__i386) || defined(__x86_64)) +unsigned int do_IRQ(int irq, struct uml_pt_regs *regs) +{ + /* + * this might be called in signal handler, so dispatch to different + * thread to avoid race + */ + set_irq_pending(irq); + + return 1; +} +#endif diff --git a/arch/um/lkl/kernel/setup.c b/arch/um/lkl/kernel/setup.c index 36c199d3aa22..39b7b7c79581 100644 --- a/arch/um/lkl/kernel/setup.c +++ b/arch/um/lkl/kernel/setup.c @@ -61,6 +61,10 @@ int __init lkl_start_kernel(struct lkl_host_operations *ops, const char *fmt, ret = vsnprintf(boot_command_line, COMMAND_LINE_SIZE, fmt, ap); va_end(ap); + if (ops->um_devices) + strscpy(boot_command_line + ret, ops->um_devices, + COMMAND_LINE_SIZE - ret); + memcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE); init_sem = lkl_ops->sem_alloc(0); diff --git a/arch/um/lkl/mm/bootmem.c b/arch/um/lkl/mm/bootmem.c index 39dd0d22b44e..3175dadee13f 100644 --- a/arch/um/lkl/mm/bootmem.c +++ b/arch/um/lkl/mm/bootmem.c @@ -64,3 +64,36 @@ void free_mem(void) { lkl_ops->mem_free((void *)_memory_start); } + +void *uml_kmalloc(int size, int flags) +{ + return kmalloc(size, flags); +} + +char *uml_strdup(const char *string) +{ + return kstrdup(string, GFP_KERNEL); +} + +void free_stack(unsigned long stack, int order) +{ + free_pages(stack, order); +} + +unsigned long alloc_stack(int order, int atomic) +{ + unsigned long page; + gfp_t flags = GFP_KERNEL; + + if (atomic) + flags = GFP_ATOMIC; + page = __get_free_pages(flags, order); + + return page; +} + +int __cant_sleep(void) +{ + return in_atomic() || irqs_disabled() || in_interrupt(); + /* Is in_interrupt() really needed? */ +} diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile index 839915b8c31c..a74a2486e178 100644 --- a/arch/um/os-Linux/Makefile +++ b/arch/um/os-Linux/Makefile @@ -6,9 +6,14 @@ # Don't instrument UML-specific code KCOV_INSTRUMENT := n +ifeq ($(UMMODE),kernel) obj-y = execvp.o file.o helper.o irq.o main.o mem.o process.o \ registers.o sigio.o signal.o start_up.o time.o tty.o \ umid.o user_syms.o util.o drivers/ skas/ +else +obj-y = execvp.o file.o helper.o irq.o drivers/ +endif + obj-$(CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA) += elf_aux.o diff --git a/tools/lkl/Makefile.autoconf b/tools/lkl/Makefile.autoconf index 268c367d9962..d2dcaa3b85f2 100644 --- a/tools/lkl/Makefile.autoconf +++ b/tools/lkl/Makefile.autoconf @@ -41,6 +41,8 @@ define posix_host $(if $(strip $(call find_include,archive.h)),$(call set_autoconf_var,ARCHIVE,y)) $(if $(filter $(1),elf64-x86-64-freebsd),$(call set_autoconf_var,NEEDS_LARGP,y)) $(if $(filter $(1),elf32-i386),$(call set_autoconf_var,I386,y)) + $(if $(filter $(1),elf64-x86-64),$(call set_autoconf_var,UML_DEV,y)) + $(if $(filter $(1),elf32-i386),$(call set_autoconf_var,UML_DEV,y)) endef define do_autoconf diff --git a/tools/lkl/include/lkl.h b/tools/lkl/include/lkl.h index 1f4291ad9455..952d11e30868 100644 --- a/tools/lkl/include/lkl.h +++ b/tools/lkl/include/lkl.h @@ -731,6 +731,15 @@ struct lkl_netdev_args { unsigned int offload; }; +#ifdef LKL_HOST_CONFIG_UML_DEV +struct lkl_netdev *lkl_um_netdev_create(const char *ifparams); +#else +static inline struct lkl_netdev *lkl_um_netdev_create(const char *ifparams) +{ + return NULL; +} +#endif + /* * lkl_register_dbg_handler- register a signal handler that loads a debug lib. * diff --git a/tools/lkl/include/lkl_host.h b/tools/lkl/include/lkl_host.h index 4e6d6e031498..7ac30bdcaf0a 100644 --- a/tools/lkl/include/lkl_host.h +++ b/tools/lkl/include/lkl_host.h @@ -10,6 +10,7 @@ extern "C" { #include extern struct lkl_host_operations lkl_host_ops; +extern char lkl_um_devs[4096]; /** * lkl_printf - print a message via the host print operation diff --git a/tools/lkl/lib/Build b/tools/lkl/lib/Build index 0e711e260a3a..ad8a4b806375 100644 --- a/tools/lkl/lib/Build +++ b/tools/lkl/lib/Build @@ -10,3 +10,4 @@ liblkl-y += dbg.o liblkl-y += dbg_handler.o liblkl-y += ../../perf/pmu-events/jsmn.o liblkl-y += config.o +liblkl-$(LKL_HOST_CONFIG_UML_DEV) += um/ diff --git a/tools/lkl/lib/config.c b/tools/lkl/lib/config.c index 37f8ac4d942a..db3af68446d3 100644 --- a/tools/lkl/lib/config.c +++ b/tools/lkl/lib/config.c @@ -470,6 +470,12 @@ static int lkl_config_netdev_create(struct lkl_config *cfg, memset(&nd_args, 0, sizeof(struct lkl_netdev_args)); if (!nd && iface->iftype && iface->ifparams) { + if ((strcmp(iface->iftype, "um") == 0)) { + nd = lkl_um_netdev_create(iface->ifparams); + iface->nd = nd; + /* um_netdev doesn't use virtio device */ + return 0; + } } if (nd) { diff --git a/tools/lkl/lib/net.c b/tools/lkl/lib/net.c index cf6894c35e46..4d4cd2382b2a 100644 --- a/tools/lkl/lib/net.c +++ b/tools/lkl/lib/net.c @@ -179,6 +179,14 @@ int lkl_netdev_get_ifindex(int id) snprintf(ifr.lkl_ifr_name, sizeof(ifr.lkl_ifr_name), "eth%d", id); ret = lkl_sys_ioctl(sock, LKL_SIOCGIFINDEX, (long)&ifr); + + /* retry with vector device */ + if (ret < 0) { + snprintf(ifr.lkl_ifr_name, sizeof(ifr.lkl_ifr_name), + "vec%d",id); + ret = lkl_sys_ioctl(sock, LKL_SIOCGIFINDEX, (long)&ifr); + } + lkl_sys_close(sock); return ret < 0 ? ret : ifr.lkl_ifr_ifindex; diff --git a/tools/lkl/lib/posix-host.c b/tools/lkl/lib/posix-host.c index 4be1611a8942..d6394d41e125 100644 --- a/tools/lkl/lib/posix-host.c +++ b/tools/lkl/lib/posix-host.c @@ -346,6 +346,9 @@ struct lkl_host_operations lkl_host_ops = { .print = print, .mem_alloc = (void *)malloc, .mem_free = free, +#ifdef LKL_HOST_CONFIG_UML_DEV + .um_devices = lkl_um_devs, +#endif .gettid = _gettid, .jmp_buf_set = jmp_buf_set, .jmp_buf_longjmp = jmp_buf_longjmp, diff --git a/tools/lkl/lib/um/Build b/tools/lkl/lib/um/Build new file mode 100644 index 000000000000..09a60975ecd6 --- /dev/null +++ b/tools/lkl/lib/um/Build @@ -0,0 +1,2 @@ +liblkl-y += um_glue.o +liblkl-y += um_net.o diff --git a/tools/lkl/lib/um/um_glue.c b/tools/lkl/lib/um/um_glue.c new file mode 100644 index 000000000000..f59e31a706de --- /dev/null +++ b/tools/lkl/lib/um/um_glue.c @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include + + + +char lkl_um_devs[4096]; + +/* from sigio.c */ +void maybe_sigio_broken(int fd, int read) +{ +} + +/* from process.c */ +int os_getpid(void) +{ + return getpid(); +} + + +/* from chan_kern.c */ +void free_irqs(void) +{ +} + +/* from sigio.c */ +int ignore_sigio_fd(int fd) +{ + return 0; +} + +/* new functions */ +void *um_os_signal(int signum, void *handler) +{ + return signal(signum, handler); +} diff --git a/tools/lkl/lib/um/um_net.c b/tools/lkl/lib/um/um_net.c new file mode 100644 index 000000000000..eed2dcd9a91c --- /dev/null +++ b/tools/lkl/lib/um/um_net.c @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include + +static int registered_net_dev_idx; + +struct lkl_netdev *lkl_um_netdev_create(const char *ifparams) +{ + struct lkl_netdev *nd; + + nd = lkl_host_ops.mem_alloc(sizeof(struct lkl_netdev)); + if (!nd) + return NULL; + + memset(nd, 0, sizeof(struct lkl_netdev)); + + nd->id = registered_net_dev_idx++; + /* concat strings */ + /* XXX: better vector device detection ? */ + if (strncmp(ifparams, "trans", 5) == 0) + snprintf(lkl_um_devs + strlen(lkl_um_devs), sizeof(lkl_um_devs), + " vec%d:%s", nd->id, ifparams); + else + snprintf(lkl_um_devs + strlen(lkl_um_devs), sizeof(lkl_um_devs), + " eth%d=%s", nd->id, ifparams); + + return nd; +} diff --git a/tools/lkl/tests/net-setup.sh b/tools/lkl/tests/net-setup.sh index 0cfc42a30a54..7aef0afc2df9 100644 --- a/tools/lkl/tests/net-setup.sh +++ b/tools/lkl/tests/net-setup.sh @@ -1,6 +1,11 @@ #!/usr/bin/env bash # SPDX-License-Identifier: GPL-2.0 +if [ -n "$LKL_HOST_CONFIG_BSD" ]; then +TEST_TAP_IFNAME=tap +else +TEST_TAP_IFNAME=lkl_test_tap +fi TEST_IP_NETWORK=192.168.113.0 TEST_IP_NETMASK=24 TEST_IP6_NETWORK=fc03::0 @@ -8,6 +13,8 @@ TEST_IP6_NETMASK=64 TEST_MAC0="aa:bb:cc:dd:ee:ff" TEST_MAC1="aa:bb:cc:dd:ee:aa" TEST_NETSERVER_PORT=11223 +TEST_UM_SLIRP_PARMS="slirp,,`which slirp`" +TEST_UM_VECTOR_TAP_PARMS="transport=tap,ifname=${TEST_TAP_IFNAME}0" # $1 - count # $2 - netcount @@ -71,3 +78,59 @@ ip6_net_mask() { echo "$(ip6_add 0 $1)/$TEST_IP6_NETMASK" } + +tap_ifname() +{ + echo -n "$TEST_TAP_IFNAME${1:-0}" +} + +tap_prepare() +{ + if [ -n "$LKL_HOST_CONFIG_ANDROID" ]; then + if ! lkl_test_cmd test -d /dev/net &>/dev/null; then + lkl_test_cmd sudo mkdir /dev/net + lkl_test_cmd sudo ln -s /dev/tun /dev/net/tun + fi + TAP_USER="vpn" + ANDROID_USER="vpn,vpn,net_admin,inet" + export_vars ANDROID_USER + else + TAP_USER=$USER + fi +} + +tap_setup() +{ + if [ -n "$LKL_HOST_CONFIG_BSD" ]; then + lkl_test_cmd sudo ifconfig tap create + lkl_test_cmd sudo sysctl net.link.tap.up_on_open=1 + lkl_test_cmd sudo sysctl net.link.tap.user_open=1 + lkl_test_cmd sudo ifconfig $(tap_ifname) $(ip_host) + lkl_test_cmd sudo ifconfig $(tap_ifname) inet6 $(ip6_host) + return + fi + + lkl_test_cmd sudo ip tuntap add dev $(tap_ifname $1) mode tap user $TAP_USER + lkl_test_cmd sudo ip link set dev $(tap_ifname $1) up + lkl_test_cmd sudo ip addr add dev $(tap_ifname $1) $(ip_host_mask $1) + lkl_test_cmd sudo ip -6 addr add dev $(tap_ifname $1) $(ip6_host_mask $1) + + if [ -n "$LKL_HOST_CONFIG_ANDROID" ]; then + lkl_test_cmd sudo ip route add $(ip_net_mask $1) \ + dev $(tap_ifname $1) proto kernel scope link \ + src $(ip_host $1) table local + lkl_test_cmd sudo ip -6 route add $(ip6_net_mask $1) \ + dev $(tap_ifname $1) table local + fi +} + +tap_cleanup() +{ + if [ -n "$LKL_HOST_CONFIG_BSD" ]; then + lkl_test_cmd sudo ifconfig $(tap_ifname) destroy + return + fi + + lkl_test_cmd sudo ip link set dev $(tap_ifname $1) down + lkl_test_cmd sudo ip tuntap del dev $(tap_ifname $1) mode tap +} diff --git a/tools/lkl/tests/net-test.c b/tools/lkl/tests/net-test.c index 5a8e39a52417..1050b0df3134 100644 --- a/tools/lkl/tests/net-test.c +++ b/tools/lkl/tests/net-test.c @@ -22,9 +22,11 @@ enum { BACKEND_NONE, + BACKEND_UM, + BACKEND_UM_VECTOR_TAP, }; -const char *backends[] = { "loopback", NULL }; +const char *backends[] = { "loopback", "um", "um-vector-tap", NULL }; static struct { int backend; const char *ifname; @@ -176,12 +178,18 @@ static int lkl_test_icmp(void) } static struct lkl_netdev *nd; +static int nd_id; static int lkl_test_nd_create(void) { switch (cla.backend) { case BACKEND_NONE: return TEST_SKIP; + case BACKEND_UM: + case BACKEND_UM_VECTOR_TAP: + nd = lkl_um_netdev_create(cla.ifname); + nd_id = nd->id; + break; } if (!nd) { @@ -192,11 +200,10 @@ static int lkl_test_nd_create(void) return TEST_SUCCESS; } -static int nd_id; - static int lkl_test_nd_add(void) { - if (cla.backend == BACKEND_NONE) + if (cla.backend == BACKEND_NONE || cla.backend == BACKEND_UM + || cla.backend == BACKEND_UM_VECTOR_TAP) return TEST_SKIP; return TEST_SUCCESS; @@ -204,7 +211,8 @@ static int lkl_test_nd_add(void) static int lkl_test_nd_remove(void) { - if (cla.backend == BACKEND_NONE) + if (cla.backend == BACKEND_NONE || cla.backend == BACKEND_UM + || cla.backend == BACKEND_UM_VECTOR_TAP) return TEST_SKIP; return TEST_SUCCESS; diff --git a/tools/lkl/tests/net.sh b/tools/lkl/tests/net.sh index 32e8452b0406..d964c6a2321d 100755 --- a/tools/lkl/tests/net.sh +++ b/tools/lkl/tests/net.sh @@ -11,8 +11,17 @@ cleanup_backend() set -e case "$1" in + "um-vector-tap") + # only intel arch is capable with um-net backent + if [ -z "$LKL_HOST_CONFIG_UML_DEV" ]; then + return $TEST_SKIP + fi + tap_cleanup + ;; "loopback") ;; + "um") + ;; esac } @@ -47,6 +56,30 @@ setup_backend() case "$1" in "loopback") ;; + "um") + # only intel arch is capable with um-net backent + if [ -z "$LKL_HOST_CONFIG_UML_DEV" ]; then + return $TEST_SKIP + fi + # slirp's helper process doesn't work with valgrind + if [ -n "$VALGRIND" ]; then + return $TEST_SKIP + fi + ;; + "um-vector-tap") + # only intel arch is capable with um-net backent + if [ -z "$LKL_HOST_CONFIG_UML_DEV" ]; then + return $TEST_SKIP + fi + tap_prepare + if ! lkl_test_cmd test -c /dev/net/tun; then + if [ -z "$LKL_HOST_CONFIG_BSD" ]; then + echo "missing /dev/net/tun" + return $TEST_SKIP + fi + fi + tap_setup + ;; *) echo "don't know how to setup backend $1" return $TEST_FAILED @@ -60,6 +93,18 @@ run_tests() "loopback") lkl_test_exec $script_dir/net-test --dst 127.0.0.1 ;; + "um") + lkl_test_exec $script_dir/net-test --backend um \ + --ifname $TEST_UM_SLIRP_PARMS \ + --ip 10.0.2.15 --netmask-len 8 \ + --dst 10.0.2.2 + ;; + "um-vector-tap") + lkl_test_exec $script_dir/net-test --backend um-vector-tap \ + --ifname $TEST_UM_VECTOR_TAP_PARMS \ + --ip $(ip_lkl) --netmask-len $TEST_IP_NETMASK \ + --dst $(ip_host) + ;; esac } diff --git a/tools/lkl/tests/run.py b/tools/lkl/tests/run.py index b72299aaabee..2cc918a6e11a 100755 --- a/tools/lkl/tests/run.py +++ b/tools/lkl/tests/run.py @@ -54,6 +54,8 @@ tests = [ 'disk.sh -t vfat', 'disk.sh -t btrfs', 'net.sh -b loopback', + 'net.sh -b um', + 'net.sh -b um-vector-tap', 'lklfuse.sh -t ext4', 'lklfuse.sh -t vfat', 'lklfuse.sh -t btrfs', From patchwork Mon Mar 30 14:45:56 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hajime Tazaki X-Patchwork-Id: 1263999 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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=h2YrO7xl; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=Xkt8ht0f; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (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 48rb374gy1z9sQt for ; Tue, 31 Mar 2020 01:49:55 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.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=1r0L23Oe91RbJrXQh2vHhoicpoCJhWtetQHurucHoUU=; b=h2YrO7xl5PNQjL m3r2o6JP14t81FNlizR/vckDnKkd+L4LeEASunRriShhRQ3ko10a2W0lV6XzSvi3C68+GbeBksbAm ShE4/fpuiI6VPx1c0NgqvbeApRPFu/Icgj2VbdTo6VnHNdM8ci1r2H3gkS8kArN+X93dfnyftDKyg d4r3bCjFwU35HJTwDta4emVZU/fIch7rGGBRuQxOuzgsT0j/g2bG4k/H3QQ+74nUY4FTOtsDXORBp KNpI+4k4wxqoBILC9q8pdIWNzDjisCZTiQlkGPTYCQiNt3tW3qzNVnmCHvQfGGzFha5cSPOkyjhR3 pTRgtNrXQr5TeMK51Obg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvjW-0005BF-OT; Mon, 30 Mar 2020 14:49:46 +0000 Received: from mail-pg1-x541.google.com ([2607:f8b0:4864:20::541]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvjT-0005AZ-HW for linux-um@lists.infradead.org; Mon, 30 Mar 2020 14:49:45 +0000 Received: by mail-pg1-x541.google.com with SMTP id b1so8750287pgm.8 for ; Mon, 30 Mar 2020 07:49:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Ra2KUflXUydcEuVymN0GQqY7t7CCQJkQXwhxGSQKhhs=; b=Xkt8ht0fWQ26dgElhYxdPCEvCtA29qhaCnXZU5ySH47H+Ind/LcWckairGU4cQ0UZj WX4K7Lkxi2+mDJKPJLFux6CpJwcejCO/O8yigaaZFi/nZDue/sKSHGH96GpS0IjmO2lo doGn0DYAIScQmjXPqfImFeGMpRO6Dtwv6jDKTaTSrULYi3LO8UxxWOodSAAsxQMoz54J DExOhrtE3+bHklyNxkp3aLQnHVg7Jpi31tnaukftODCLKFiwG8A26vF+nYNfQk4+eVLh lViIDIocJvuYjNLs+oTxBCXxkiF/X3KChZ1WMLWgf1UAf1OCSFeyjKUpfdB/JjFS+rze giWw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Ra2KUflXUydcEuVymN0GQqY7t7CCQJkQXwhxGSQKhhs=; b=mb3xWjUtDu6+cEUxenxx9gQrnMOSM0xvoKwfw7iY88nToInEWlOgedg/yZDnsjDz9R ccmDxy4XkcsxM964NBb0U22d3pzDyXgfa5jfawAq8SH3j7UQFf4NxUAOGrJiHvsmpq4r w0Tq+s23d4ukVmEBZAb+5bmgfQu9crcVeo9Exiz2e8Y9MSBtk9Dx+LLNe0oZwrKa844/ pJkEg4ZKHUz+66gIaDJWg+eXA+7t3i0qx1SDP0fJUmAMiXbqu5iBjkxTa1fLG/21XFxX 9GO7Lhw2V9NogkgdO2CVb7GgnyE+C5VQXdoUHm3cavmZ2qOrAUV2AXpWbeB8bPBHtHSu +eAg== X-Gm-Message-State: ANhLgQ3oLPu2PKCCfLleectmcjWUgvzxnjxeCT0Hp4o1g7TMDrRTZxnI P5Mr1TJSR3bKx9AAM2SCOte1EF+x7/CSMQ== X-Google-Smtp-Source: ADFU+vuzo9vQHNmIsDDgZNkjlTVkZC0N9kEz1ejEOn/8zrsDMnTY7HzO9KigTdf9D2rsfQbZj7UUpg== X-Received: by 2002:a63:d351:: with SMTP id u17mr12905753pgi.396.1585579782681; Mon, 30 Mar 2020 07:49:42 -0700 (PDT) Received: from earth-mac.local (219x123x138x129.ap219.ftth.ucom.ne.jp. [219.123.138.129]) by smtp.gmail.com with ESMTPSA id i4sm10373226pjg.4.2020.03.30.07.49.41 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 30 Mar 2020 07:49:42 -0700 (PDT) Received: by earth-mac.local (Postfix, from userid 501) id 744D4202804F40; Mon, 30 Mar 2020 23:49:40 +0900 (JST) From: Hajime Tazaki To: linux-um@lists.infradead.org Subject: [RFC v4 24/25] um lkl: add UML block device driver (ubd) for lkl Date: Mon, 30 Mar 2020 23:45:56 +0900 Message-Id: <5f1d48e40c4daf4ef3ddca3ca3207f11ef29739f.1585579244.git.thehajime@gmail.com> X-Mailer: git-send-email 2.20.1 (Apple Git-117) In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200330_074943_606008_E0E529FF X-CRM114-Status: GOOD ( 18.41 ) X-Spam-Score: -0.2 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:541 listed in] [list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [thehajime[at]gmail.com] -0.0 SPF_PASS SPF: sender matches SPF record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 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: Octavian Purdila , linux-kernel-library@freelists.org, linux-arch@vger.kernel.org, Hajime Tazaki , Akira Moroo Sender: "linux-um" Errors-To: linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org This commit adds a support to utilize exising UML drivers of block devices for LKL. The goal is similar to networking drivers, add minimum amount of code and use drivers code as-is. This commit also adds a test code with several filesystems (ext4, vfat, btrfs at the moment) to exercise the basic operations of disk. Signed-off-by: Hajime Tazaki --- arch/um/drivers/ubd_kern.c | 6 +++++- arch/um/lkl/Kconfig | 3 +++ arch/um/lkl/include/uapi/asm/syscalls.h | 1 + arch/um/lkl/kernel/setup.c | 5 +++++ tools/lkl/include/lkl.h | 15 +++++++++++++++ tools/lkl/lib/um/Build | 1 + tools/lkl/lib/um/um_block.c | 17 +++++++++++++++++ tools/lkl/lib/um/um_glue.c | 24 +++++++++++++++++++++++- tools/lkl/tests/disk.c | 14 ++++++++++++++ 9 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 tools/lkl/lib/um/um_block.c diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index eae8c83364f7..248bac8e36b8 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -545,7 +545,7 @@ static irqreturn_t ubd_intr(int irq, void *dev) /* Only changed by ubd_init, which is an initcall. */ static int io_pid = -1; -static void kill_io_thread(void) +void kill_io_thread(void) { if(io_pid != -1) os_kill_process(io_pid, 1); @@ -819,6 +819,7 @@ static int ubd_open_dev(struct ubd *ubd_dev) } ubd_dev->fd = fd; +#ifdef CONFIG_UMMODE_KERN if(ubd_dev->cow.file != NULL){ blk_queue_max_hw_sectors(ubd_dev->queue, 8 * sizeof(long)); @@ -843,6 +844,7 @@ static int ubd_open_dev(struct ubd *ubd_dev) if(err < 0) goto error; ubd_dev->cow.fd = err; } +#endif /* CONFIG_UMMODE_KERN */ if (ubd_dev->no_trim == 0) { ubd_dev->queue->limits.discard_granularity = SECTOR_SIZE; ubd_dev->queue->limits.discard_alignment = SECTOR_SIZE; @@ -852,9 +854,11 @@ static int ubd_open_dev(struct ubd *ubd_dev) } blk_queue_flag_set(QUEUE_FLAG_NONROT, ubd_dev->queue); return 0; +#ifdef CONFIG_UMMODE_KERN error: os_close_file(ubd_dev->fd); return err; +#endif } static void ubd_device_release(struct device *dev) diff --git a/arch/um/lkl/Kconfig b/arch/um/lkl/Kconfig index 2b6b4063045c..8e4e0a465fc8 100644 --- a/arch/um/lkl/Kconfig +++ b/arch/um/lkl/Kconfig @@ -48,6 +48,9 @@ config OUTPUT_FORMAT config ARCH_DMA_ADDR_T_64BIT def_bool 64BIT +config BLK_DEV_UBD + def_bool y if "$(OUTPUT_FORMAT)" = "elf32-i386" || "$(OUTPUT_FORMAT)" = "elf64-x86-64" + config X86_64 def_bool y if "$(OUTPUT_FORMAT)" = "elf64-x86-64" diff --git a/arch/um/lkl/include/uapi/asm/syscalls.h b/arch/um/lkl/include/uapi/asm/syscalls.h index a81534ffccb7..1384c34137d6 100644 --- a/arch/um/lkl/include/uapi/asm/syscalls.h +++ b/arch/um/lkl/include/uapi/asm/syscalls.h @@ -164,6 +164,7 @@ struct sockaddr { #include #include #include +#include struct user_msghdr { void __user *msg_name; diff --git a/arch/um/lkl/kernel/setup.c b/arch/um/lkl/kernel/setup.c index 39b7b7c79581..daf55c216db9 100644 --- a/arch/um/lkl/kernel/setup.c +++ b/arch/um/lkl/kernel/setup.c @@ -126,6 +126,11 @@ long lkl_sys_halt(void) LINUX_REBOOT_CMD_RESTART, }; +#ifdef CONFIG_BLK_DEV_UBD +void kill_io_thread(void); + kill_io_thread(); +#endif + err = lkl_syscall(__NR_reboot, params); if (err < 0) return err; diff --git a/tools/lkl/include/lkl.h b/tools/lkl/include/lkl.h index 952d11e30868..7d164e4dcad1 100644 --- a/tools/lkl/include/lkl.h +++ b/tools/lkl/include/lkl.h @@ -355,6 +355,10 @@ void lkl_perror(char *msg, int err); */ struct lkl_dev_blk_ops; +enum { + BLK_BACKEND_UM, +}; + /** * lkl_disk - host disk handle * @@ -368,6 +372,7 @@ struct lkl_disk { int fd; void *handle; }; + int backend; struct lkl_dev_blk_ops *ops; }; @@ -403,6 +408,16 @@ int lkl_disk_remove(struct lkl_disk disk); */ int lkl_encode_dev_from_sysfs(const char *sysfs_path, uint32_t *pdevid); + +#ifdef LKL_HOST_CONFIG_UML_DEV +int lkl_disk_um_add(struct lkl_disk *disk, const char *blkparams); +#else +static inline int lkl_disk_um_add(struct lkl_disk *disk, const char *blkparams) +{ + return -LKL_ENOSYS; +} +#endif + /** * lkl_mount_dev - mount a disk * diff --git a/tools/lkl/lib/um/Build b/tools/lkl/lib/um/Build index 09a60975ecd6..52573c05a797 100644 --- a/tools/lkl/lib/um/Build +++ b/tools/lkl/lib/um/Build @@ -1,2 +1,3 @@ liblkl-y += um_glue.o liblkl-y += um_net.o +liblkl-y += um_block.o diff --git a/tools/lkl/lib/um/um_block.c b/tools/lkl/lib/um/um_block.c new file mode 100644 index 000000000000..70dc624ec43c --- /dev/null +++ b/tools/lkl/lib/um/um_block.c @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include + + +static int registered_blk_dev_idx; + +int lkl_disk_um_add(struct lkl_disk *disk, const char *blkparams) +{ + /* concat strings */ + snprintf(lkl_um_devs + strlen(lkl_um_devs), sizeof(lkl_um_devs), + " ubd%d=%s", registered_blk_dev_idx, blkparams); + + return registered_blk_dev_idx++; +} diff --git a/tools/lkl/lib/um/um_glue.c b/tools/lkl/lib/um/um_glue.c index f59e31a706de..fd5a338bcb9f 100644 --- a/tools/lkl/lib/um/um_glue.c +++ b/tools/lkl/lib/um/um_glue.c @@ -2,9 +2,10 @@ #include #include #include +#include #include #include - +#include char lkl_um_devs[4096]; @@ -37,3 +38,24 @@ void *um_os_signal(int signum, void *handler) { return signal(signum, handler); } + +/* from util.c */ +/* + * UML helper threads must not handle SIGWINCH/INT/TERM + */ +void os_fix_helper_signals(void) +{ + signal(SIGWINCH, SIG_IGN); + signal(SIGINT, SIG_DFL); + signal(SIGTERM, SIG_DFL); +} + +void os_kill_process(int pid, int reap_child) +{ + kill(pid, SIGKILL); + if (reap_child) { + while ((errno = 0, ((waitpid(pid, NULL, __WALL)) < 0)) + && (errno == EINTR)) + ; + } +} diff --git a/tools/lkl/tests/disk.c b/tools/lkl/tests/disk.c index 0aa039876b54..f7801014d054 100644 --- a/tools/lkl/tests/disk.c +++ b/tools/lkl/tests/disk.c @@ -23,12 +23,17 @@ static struct { const char *disk; const char *fstype; int partition; + int backend; } cla; +const char *backends[] = { "um", NULL }; + struct cl_arg args[] = { {"disk", 'd', "disk file to use", 1, CL_ARG_STR, &cla.disk}, {"partition", 'P', "partition to mount", 1, CL_ARG_INT, &cla.partition}, {"type", 't', "filesystem type", 1, CL_ARG_STR, &cla.fstype}, + {"backend", 'b', "blockd evice backend type", 1, CL_ARG_STR_SET, + &cla.backend, backends}, {0}, }; @@ -50,6 +55,15 @@ int lkl_test_disk_add(void) disk.ops = NULL; + disk.backend = cla.backend; + + switch (disk.backend) { + case BLK_BACKEND_UM: + disk.dev = (char *)cla.disk; + default: + break; + } + disk_id = lkl_disk_add(&disk); if (disk_id < 0) goto out_close; From patchwork Mon Mar 30 14:45:57 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hajime Tazaki X-Patchwork-Id: 1264000 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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=Gxn0dmV4; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=fM5YmBSU; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (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 48rb3857klz9sSG for ; Tue, 31 Mar 2020 01:49:56 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.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=e1UXK2AUhcuC+ta1ltwfLubRtRnJ5z0HLkeWYXoa6Jw=; b=Gxn0dmV4qCA0TF gJfMDBg/rQ2LjoNXo51RyEqOZFYj5azbAAUqAn2XUWYY/EeSgug2WNMl1nNe3KxdwbhaOuWeBDBNV /aL8ZfbO16hMQMykQCCFO7s747A30D9TG4AyHPmNge5kauKvtYZU0ragSw/esnODxe2VJ+/zwjtDA wpKMDUEBm0qIiIinDQlGNpm7b7oMt8223chJNItGR+hDtUfeybw3LAtda9k7bra5tii4ji1FwpwL+ aRtBR4bmYJWntMQvu0eJpcodXQ0TW5i/wRJe8PrA5dFlsvGOtvQFUQiVpYdB7RMnBF2mdOpYCRKO/ l6MQ4oR1w2QxhQTLcFqg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvjX-0005Bm-V9; Mon, 30 Mar 2020 14:49:47 +0000 Received: from mail-pj1-x1044.google.com ([2607:f8b0:4864:20::1044]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jIvjV-0005B2-Sw for linux-um@lists.infradead.org; Mon, 30 Mar 2020 14:49:47 +0000 Received: by mail-pj1-x1044.google.com with SMTP id fh8so2570152pjb.5 for ; Mon, 30 Mar 2020 07:49:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=BE2CIeYLuvmQLbPTA0A8Oy0mfYI7Ki1Lsyf1Q2IfEvE=; b=fM5YmBSUpVhk2D3kZFLo43ShLvBtqFZuD9H6HiI7nyNSnDfqHq24n18WHy7NSezkAK mYdmPYDizB1X85i83HT5JqBOZFJNSa/I6tdyGvzXgqescPXlj4qNZHLORdpg9x6rGy/V P9XyFO0hv5gCGVxeeFe/YslE0TNYh92panQ2II13Q+atUdCZ3K8ppsh0F3dCFxgCKtHn Tmc5BdmaPeizdvg3UScNGCFspqY+9uMJ+jmhc8GQQN2rHo306MAdlbHjMgVjIPU4Zg24 k/qjYfBNGjyyYKrC/fMf0HStp2k+6T3gpkeInrsRzclCfvsN5XuGpmtKBH/p2rBvrVGS KdKg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=BE2CIeYLuvmQLbPTA0A8Oy0mfYI7Ki1Lsyf1Q2IfEvE=; b=iDe2MNxjvieCOQVzKdw2iJqeOpC1E7SB58Z8xuxLlxGEkPn+QFm4L/8JaYE0o2G7Ld divEFSZ1AEHLDAZXTfvU+5KTeTRpfKa4M4223lemD6kiAHCmuoOf0cLqsQjgu8bRYLzo MNV3zDsqEc7daEHF50wYQZ4WCsieQeEGPa/eEHLXiGundBIq7u/oD56bgNdxAYiaImxj 2PM7Dw21xThZb6mdtTtl65YQgZf1xNznCqv80qmpGc7HFlXXJK+cw5X4usg1MiIi3MXe nU7sNcsSvGgA8DAgq3VbKeteULUiVNFLYRz+GjNcCATxAe1ok1UsMjzW3TvTkI5GNyV3 6pdA== X-Gm-Message-State: ANhLgQ188BNKqNTWoUaFOuPu/Yk0v0lygCX1353DzfqNR9v4fbNNZwgN YVfuJEiyAUwsUDlt+3p4VlI= X-Google-Smtp-Source: ADFU+vtByNg2KagPD0ozfZL5ly8dh5icC2xyEJ7dF1U47aZpMsjWzNupjMsttHEKhTzqbd3vMkVfAQ== X-Received: by 2002:a17:90b:1b05:: with SMTP id nu5mr16258384pjb.110.1585579785301; Mon, 30 Mar 2020 07:49:45 -0700 (PDT) Received: from earth-mac.local (219x123x138x129.ap219.ftth.ucom.ne.jp. [219.123.138.129]) by smtp.gmail.com with ESMTPSA id k189sm9755377pgc.24.2020.03.30.07.49.44 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 30 Mar 2020 07:49:44 -0700 (PDT) Received: by earth-mac.local (Postfix, from userid 501) id 3141B202804F59; Mon, 30 Mar 2020 23:49:43 +0900 (JST) From: Hajime Tazaki To: linux-um@lists.infradead.org Subject: [RFC v4 25/25] um: fix clone flags to be familiar with valgrind Date: Mon, 30 Mar 2020 23:45:57 +0900 Message-Id: <59ed4e23efa7abc9c7d52e6b5fb31fb8ce795c5c.1585579244.git.thehajime@gmail.com> X-Mailer: git-send-email 2.20.1 (Apple Git-117) In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200330_074945_933888_FE41778C X-CRM114-Status: UNSURE ( 9.54 ) X-CRM114-Notice: Please train this message. X-Spam-Score: -0.2 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:1044 listed in] [list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [thehajime[at]gmail.com] -0.0 SPF_PASS SPF: sender matches SPF record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 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: Octavian Purdila , linux-kernel-library@freelists.org, linux-arch@vger.kernel.org, Hajime Tazaki , Akira Moroo Sender: "linux-um" Errors-To: linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org Valgrind reports the following error with UML when ubd driver is compiled in. ==29588== Unsupported clone() flags: 0x500 ==29588== ==29588== The only supported clone() uses are: ==29588== - via a threads library (LinuxThreads or NPTL) ==29588== - via the implementation of fork or vfork Adding CLONE_FS flags silences this issue. Signed-off-by: Hajime Tazaki --- arch/um/drivers/ubd_user.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c index a1afe414ce48..fabb50e91c37 100644 --- a/arch/um/drivers/ubd_user.c +++ b/arch/um/drivers/ubd_user.c @@ -47,7 +47,8 @@ int start_io_thread(unsigned long sp, int *fd_out) goto out_close; } - pid = clone(io_thread, (void *) sp, CLONE_FILES | CLONE_VM, NULL); + pid = clone(io_thread, (void *) sp, + CLONE_FILES | CLONE_VM | CLONE_FS, NULL); if(pid < 0){ err = -errno; printk("start_io_thread - clone failed : errno = %d\n", errno);