From patchwork Wed Oct 23 04:37:54 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hajime Tazaki X-Patchwork-Id: 1181818 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.b="p/Z5vMwI"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="vMBbgrFI"; 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 46ydVL3QPyz9sNw for ; Wed, 23 Oct 2019 16:00:26 +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=PNwch9pVqiaqNnXSJMmxULH+HotVBTJF/ThAhE3/Eho=; b=p/Z5vMwIZkZttF K2CrHzuv6uGt/jpaQXeSjwOANUsfElQ9ch6Wnq5ei8LWJB9IoGs48XfP7aw9YadCDPNmgOZD3m2mX ZAwMWXyAUGkTK2RwccQoM8AkT7VigUE3ptdJlf7FzVQJ1Cm1R0RvKc0i2zlv99zXjmzFICdXPZyPb Ofd/e1b1uzUXslq0JnnrBNyHIcTAE0wkRcSy2yeypj5fvQraAL0UYNQ761UNMaNW5WBX1520GtYLg 9G9sCH+OVigCiaQN4pfLupckIhQQGA8rkAUJcHYMjNwMYANNU07nSRux7p/nQbHJsEO3rwPKmPYgk Uy574bbANXFbHF25QDzQ==; 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 1iN8ks-0002EK-Ei; Wed, 23 Oct 2019 05:00:18 +0000 Received: from mail-pg1-x544.google.com ([2607:f8b0:4864:20::544]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1iN8kk-0001uR-4j for linux-um@lists.infradead.org; Wed, 23 Oct 2019 05:00:15 +0000 Received: by mail-pg1-x544.google.com with SMTP id w3so11378167pgt.5 for ; Tue, 22 Oct 2019 22:00:09 -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=dJROnqvih2/w+buQ5/pIJu9kUje19yoLs553NK0JwW4=; b=vMBbgrFIJB7j2ZB4v6LuF6gC/VN2g7RcudczPPebJxHJ82Qp8RWXpeNeFmyEqeYad4 medybmOGcHpzx9YIWcKHWmjW7uspk7cy1VLDreZeIB2Gnpi1W/Alsi+VS4vhbWTeXLru unSQUklvuMZmUTQX/3e4mXz6VmN/ifRVDQVE+BkuvoPHCLKjg0pCDkpGs4fO/oeyUC/7 Iqig+AezZkTq1t1f2FOBBhVTCP9x0tFQ77l6667HmwCszrLZfGkoI9V/JrU9iaGg1YZR WUXxQXOtQjfMNaFElyqYL0hdspFIoJDYn6Q8sVrykCh/YFJMFHHde64iMT2DpphPPF4S h2KQ== 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=dJROnqvih2/w+buQ5/pIJu9kUje19yoLs553NK0JwW4=; b=p9SUK0hKRvkv9BrvgmlHIRjEaZMFhs5ZpcJ4MWWqIdlVy8NMX6+N7IOFosh3sPrJWA dh6MiF6oZblYXSlQ5PE+e+7lYIAuvOLwQz6etJLbDbrhJxG8qzyg6dCtP46myQUELC3N ZJiYlNe93pGu1cIEPFWd1b3hSPfWcWPh/FvMvI8hIpaeNVf+i/mboEGNQUmhx2W2Qsl2 2ueBKvwi/abp7QI5bhJitbBR1yXbtCAxM6E3UZxTxDjhZBcuNfusmCaWxTgq1FIOcHVV drE3e7qfA8uJWXY2i4CB/hp5vBazLrGZc2V9yu+79CH6TEyQTFWfMGbVJgUKJF4iDskc /GmA== X-Gm-Message-State: APjAAAWOZP2YWcoNkiImefJHqfxUTO66f149ESl2ODodQRLNVGZIMA1S E5m0I7XdEt66r6YHrvYHB5M= X-Google-Smtp-Source: APXvYqyTOy/xvtOjDVaLkE+BJ8Jur2Uu2uY9xQcPRb1JNFFHOKpL4ELJijfcZB4UMR/sUnBHvXwoXQ== X-Received: by 2002:a63:4b06:: with SMTP id y6mr7575358pga.409.1571806809324; Tue, 22 Oct 2019 22:00:09 -0700 (PDT) Received: from earth-mac.local ([202.214.86.179]) by smtp.gmail.com with ESMTPSA id y20sm19055092pge.48.2019.10.22.22.00.06 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 22 Oct 2019 22:00:09 -0700 (PDT) Received: by earth-mac.local (Postfix, from userid 501) id C608420199581A; Wed, 23 Oct 2019 13:38:53 +0900 (JST) From: Hajime Tazaki To: linux-um@lists.infradead.org Subject: [RFC PATCH 20/47] lkl tools: host lib: posix host operations Date: Wed, 23 Oct 2019 13:37:54 +0900 Message-Id: <1f14dd7627ee7898659831a4a0a46643b296c330.1571798507.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-20191022_220010_225463_A646703A X-CRM114-Status: GOOD ( 17.61 ) X-Spam-Score: -0.2 (/) X-Spam-Report: SpamAssassin version 3.4.2 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:544 listed in] [list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (thehajime[at]gmail.com) -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid 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: Conrad Meyer , Octavian Purdila , Akira Moroo , Yuan Liu , Thomas Liebetraut , Mark Stillwell , Patrick Collins , Pierre-Hugues Husson , Hajime Tazaki Sender: "linux-um" Errors-To: linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Octavian Purdila Implement LKL host operations for POSIX hosts. Signed-off-by: Conrad Meyer Signed-off-by: Hajime Tazaki Signed-off-by: Mark Stillwell Signed-off-by: Patrick Collins Signed-off-by: Pierre-Hugues Husson Signed-off-by: Thomas Liebetraut Signed-off-by: Yuan Liu Signed-off-by: Octavian Purdila --- Makefile | 2 + tools/lkl/lib/posix-host.c | 439 +++++++++++++++++++++++++++++++++++++ 2 files changed, 441 insertions(+) create mode 100644 tools/lkl/lib/posix-host.c diff --git a/Makefile b/Makefile index 8c1f7422d0bc..cf88c66fba2e 100644 --- a/Makefile +++ b/Makefile @@ -1124,7 +1124,9 @@ archprepare: archheaders archscripts scripts prepare3 outputmakefile \ asm-generic $(version_h) $(autoksyms_h) include/generated/utsrelease.h prepare0: archprepare +ifeq ($(findstring elf,$(if $(CONFIG_OUTPUT_FORMAT),$(CONFIG_OUTPUT_FORMAT),elf)),elf) $(Q)$(MAKE) $(build)=scripts/mod +endif $(Q)$(MAKE) $(build)=. # All the preparing.. diff --git a/tools/lkl/lib/posix-host.c b/tools/lkl/lib/posix-host.c new file mode 100644 index 000000000000..4d52b06c9944 --- /dev/null +++ b/tools/lkl/lib/posix-host.c @@ -0,0 +1,439 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "iomem.h" +#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* (*)(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 (*)(union sigval))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); +} + +#ifndef __arch_um__ +static void panic(void) +{ + assert(0); +} +#endif + +static long _gettid(void) +{ +#ifdef __FreeBSD__ + return (long)pthread_self(); +#else + return syscall(SYS_gettid); +#endif +} + +struct lkl_host_operations lkl_host_ops = { +#ifndef __arch_um__ + .panic = panic, +#endif + .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 = malloc, + .mem_free = free, + .ioremap = lkl_ioremap, + .iomem_access = lkl_iomem_access, + .virtio_devices = lkl_virtio_devs, + .gettid = _gettid, + .jmp_buf_set = jmp_buf_set, + .jmp_buf_longjmp = jmp_buf_longjmp, +}; + +static int fd_get_capacity(struct lkl_disk disk, unsigned long long *res) +{ + off_t off; + + off = lseek(disk.fd, 0, SEEK_END); + if (off < 0) + return (-1); + + *res = off; + return 0; +} + +static int do_rw(ssize_t (*fn)(), struct lkl_disk disk, struct lkl_blk_req *req) +{ + off_t off = req->sector * 512; + void *addr; + int len; + int i; + int ret = 0; + + for (i = 0; i < req->count; i++) { + + addr = req->buf[i].iov_base; + len = req->buf[i].iov_len; + + do { + ret = fn(disk.fd, addr, len, off); + + if (ret <= 0) { + ret = -1; + goto out; + } + + addr += ret; + len -= ret; + off += ret; + + } while (len); + } + +out: + return ret; +} + +static int blk_request(struct lkl_disk disk, struct lkl_blk_req *req) +{ + int err = 0; + + switch (req->type) { + case LKL_DEV_BLK_TYPE_READ: + err = do_rw(pread, disk, req); + break; + case LKL_DEV_BLK_TYPE_WRITE: + err = do_rw(pwrite, disk, req); + break; + case LKL_DEV_BLK_TYPE_FLUSH: + case LKL_DEV_BLK_TYPE_FLUSH_OUT: +#ifdef __linux__ + err = fdatasync(disk.fd); +#else + err = fsync(disk.fd); +#endif + break; + default: + return LKL_DEV_BLK_STATUS_UNSUP; + } + + if (err < 0) + return LKL_DEV_BLK_STATUS_IOERR; + + return LKL_DEV_BLK_STATUS_OK; +} + +struct lkl_dev_blk_ops lkl_dev_blk_ops = { + .get_capacity = fd_get_capacity, + .request = blk_request, +}; +