From patchwork Mon Apr 24 22:58:49 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Lewis X-Patchwork-Id: 13222655 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 06C5BC77B61 for ; Mon, 24 Apr 2023 22:59:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232569AbjDXW7D (ORCPT ); Mon, 24 Apr 2023 18:59:03 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59278 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232384AbjDXW7B (ORCPT ); Mon, 24 Apr 2023 18:59:01 -0400 Received: from mail-pj1-x1049.google.com (mail-pj1-x1049.google.com [IPv6:2607:f8b0:4864:20::1049]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A3BB36E82 for ; Mon, 24 Apr 2023 15:59:00 -0700 (PDT) Received: by mail-pj1-x1049.google.com with SMTP id 98e67ed59e1d1-2470e26b570so2854595a91.3 for ; Mon, 24 Apr 2023 15:59:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1682377140; x=1684969140; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=KTxwJNyDzO4UQd4QGSqMyj1j0pyih/Zhsb1jsC7qgpI=; b=NEkf0cAW8ZSrwtJ2y/ot+bzX0ZgQzh1kxJ7vhFkZdPyeNXQtN+WE2BsBlPqOdtz/QB Mc3mWAevT8lh0G1+2SLnG94Kj2R0Mqd8V4dMO9gmfx6YotS6FCHwmyvxqMnbcVhuc13P h8kjt7vUvrhMgSI8kWVhw7p8y+4PEtvHQm7oUQiEr1XowfrVgn9HAbwK7lKOIU9l38Fl 7tUsc6fEE4QTNsBSQcXAdAzQpZDzSopWy2KA9eNOFwcpN7GrM+xOTpooLsWnUD9cP/5p W+pvK2Zj9mXqEdvJpZKKrpzTHASFUbGAZRBfNacfkmZT3WFrBfeyJIDrRYWrMERQ5LyI bX/g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1682377140; x=1684969140; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=KTxwJNyDzO4UQd4QGSqMyj1j0pyih/Zhsb1jsC7qgpI=; b=dwFzkiGGyMa+HLBgDFpl85q40iS9RoiGbVE9widDYalAq89/s92BN2OXxjRqmDVa9d eA80rya3Z+yDTfqNL/xcNOqXJfU4sJkkPJspFbUYMjwYbkpwuxY0X+wfIfaBrMaWdkms LuGeRTM/on1J9BuIo2AMLQ/z+M4arsWPosfZ1CxhkQcid2WQl5Fmv2QZxeAlLmVA1ViZ /J2reD69dW2U7w1gbIuvIGsEnaixiijxMkguBdIDD6timgGkiRqRc5zx+LkuBc4cErEx TKcGpmidEzfnxYR8JllA96JQ1f4Lk99yGY9RfU9T6hi994FLRlO1cg/GaNPVUiJCIS/1 OvgQ== X-Gm-Message-State: AAQBX9enqZ/ANJ/FaCtrHXyeEnO1fxds/cdqBKpjuvddzRkZZAgebDcI 2uS2gNiIpBjXLkZP59tY5V1ZfTkFjh4KE0ECdjPxEUC3/lL0VA+M9SQWa+7AYDgKCdwA+P47k09 bs84wAxYYW8F4purH/wBqkeccAazOZyiAig4AENP9k0A+HqsS31TNAMG803j2F5f954Aa X-Google-Smtp-Source: AKy350ZdbJvnQ7+JhyxGMnWDNU/wJRH+qY+szhq5fh73l4sATab+S3fbjerdGg/dMPzc2LDL/qVUEWYvj/2H+2RA X-Received: from aaronlewis-2.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:519c]) (user=aaronlewis job=sendgmr) by 2002:a17:90a:9c5:b0:247:96d9:eb40 with SMTP id 63-20020a17090a09c500b0024796d9eb40mr3545056pjo.3.1682377140043; Mon, 24 Apr 2023 15:59:00 -0700 (PDT) Date: Mon, 24 Apr 2023 22:58:49 +0000 In-Reply-To: <20230424225854.4023978-1-aaronlewis@google.com> Mime-Version: 1.0 References: <20230424225854.4023978-1-aaronlewis@google.com> X-Mailer: git-send-email 2.40.0.634.g4ca3ef3211-goog Message-ID: <20230424225854.4023978-2-aaronlewis@google.com> Subject: [PATCH v2 1/6] KVM: selftests: Add strnlen() to the string overrides From: Aaron Lewis To: kvm@vger.kernel.org Cc: pbonzini@redhat.com, jmattson@google.com, seanjc@google.com, Aaron Lewis Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Add strnlen() to the string overrides to allow it to be called in the guest. The implementation for strnlen() was taken from the kernel's generic version, lib/string.c. This will be needed when printf() is introduced. Signed-off-by: Aaron Lewis --- tools/testing/selftests/kvm/Makefile | 1 + tools/testing/selftests/kvm/lib/string_override.c | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index 18cadc669798..d93bee00c72a 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -198,6 +198,7 @@ endif CFLAGS += -Wall -Wstrict-prototypes -Wuninitialized -O2 -g -std=gnu99 \ -Wno-gnu-variable-sized-type-not-at-end \ -fno-builtin-memcmp -fno-builtin-memcpy -fno-builtin-memset \ + -fno-builtin-strnlen \ -fno-stack-protector -fno-PIE -I$(LINUX_TOOL_INCLUDE) \ -I$(LINUX_TOOL_ARCH_INCLUDE) -I$(LINUX_HDR_PATH) -Iinclude \ -I$( X-Patchwork-Id: 13222656 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A60C3C77B61 for ; Mon, 24 Apr 2023 22:59:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232757AbjDXW7F (ORCPT ); Mon, 24 Apr 2023 18:59:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59318 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232384AbjDXW7E (ORCPT ); Mon, 24 Apr 2023 18:59:04 -0400 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 897716E82 for ; Mon, 24 Apr 2023 15:59:02 -0700 (PDT) Received: by mail-yb1-xb4a.google.com with SMTP id 3f1490d57ef6-b8f606184a3so9578603276.2 for ; Mon, 24 Apr 2023 15:59:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1682377142; x=1684969142; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=bhYTpUUdtdZNxIvvO/N9vL9exgBimvdMaOOsqthAZDk=; b=EbAovieHBKnK2BEvcP3O1w0NK2wQerFqCjj1dL5FCmm8T/fbUdX4mRVrqO+amT8WuQ Z0H/YC2FQY42IakAWHTr0nn63RLqSTziE9quCZhkh2+UOfdKj3+ZiaYOPACT0U9YeBPc Xf2uOqfXLT3T3CS0eH2OR1LU3NNTMTK684ChZPdKitW2bwe7bsz9yhHUAo2oUdAj+eUg HZ6CfNjHpyyMn4GNs2mmVtpkFWHpDo+MbiSHx5dxvj0CKPcIi9T7nf0wOxjqSxt+5xpb 8lR20BDBMkBE9Z3rrSj0TdYjC7hndvQ5UWMW3UH2GCKNVIevFqIkqJe1GFHd9z8muSYa yTsQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1682377142; x=1684969142; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=bhYTpUUdtdZNxIvvO/N9vL9exgBimvdMaOOsqthAZDk=; b=WOJWCnxTFjbjOk2hADVQI24PwMNFaqnHuVIfaZ7103CWV7pvfkvgregwK8VsIl1hHp OKtryJW06w16LBQQj17Xtep1eUl2IEorNf5zup8TNY/oF9qvmbTU2inmus4dATieGLP3 YgJ8SrmPDNk6YKYyiqF3inJW7NQHGu2oPYz/7iD6D8LD84Wo2bGajlc5FwvOznhCUy9B 4+Yq5b8UB3ee8MTbIDiLXGJ1flXe8JY9WgR63AOpu6oFCZTO8l+8RCisug7W0YSFSusE m0X798illm5wSgXg7k5aucJw7aEfKuLg40pwKgd22whuGHCoAjbqDsDlO5/4zGgoD1Qx Ky+g== X-Gm-Message-State: AAQBX9eqpMLBGHIPXpzScep+sD9Q/V0yo8lLt8AcuodmA0JKOhSz+xGi nfUsQug/fXW8vYoKoC9aQ7SCKXqW4cOOvXtsAG3Qzo5Olv0lBZUlvnEnKcbhTIO3JndUcZ5mpDi aCW2xicXpJfZNSGJ0fgOBpCabwSBiKGO4Ffj6D0KSgdLdln22gKoYDllXnw7xOs4ai25j X-Google-Smtp-Source: AKy350ZA9Ze/2wJ/1XV+vcp5mjv261Da5+tAaQjSCHW9sphOmLSpgQKvxK6K01KSTvdFfkryzbjG7JWH5kycqniS X-Received: from aaronlewis-2.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:519c]) (user=aaronlewis job=sendgmr) by 2002:a25:c905:0:b0:b8f:6b3b:8a0a with SMTP id z5-20020a25c905000000b00b8f6b3b8a0amr8268951ybf.6.1682377141796; Mon, 24 Apr 2023 15:59:01 -0700 (PDT) Date: Mon, 24 Apr 2023 22:58:50 +0000 In-Reply-To: <20230424225854.4023978-1-aaronlewis@google.com> Mime-Version: 1.0 References: <20230424225854.4023978-1-aaronlewis@google.com> X-Mailer: git-send-email 2.40.0.634.g4ca3ef3211-goog Message-ID: <20230424225854.4023978-3-aaronlewis@google.com> Subject: [PATCH v2 2/6] KVM: selftests: Add kvm_snprintf() to KVM selftests From: Aaron Lewis To: kvm@vger.kernel.org Cc: pbonzini@redhat.com, jmattson@google.com, seanjc@google.com, Aaron Lewis Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Add a local version of kvm_snprintf() for use in the guest. Having a local copy allows the guest access to string formatting options without dependencies on LIBC. LIBC is problematic because it heavily relies on both AVX-512 instructions and a TLS, neither of which are guaranteed to be set up in the guest. The file kvm_sprintf.c was lifted from arch/x86/boot/printf.c and adapted to work in the guest, including the addition of buffer length. I.e. s/sprintf/snprintf/ The functions where prefixed with "kvm_" to allow guests to explicitly call them. Signed-off-by: Aaron Lewis --- tools/testing/selftests/kvm/Makefile | 1 + .../testing/selftests/kvm/include/test_util.h | 3 + tools/testing/selftests/kvm/lib/kvm_sprintf.c | 313 ++++++++++++++++++ 3 files changed, 317 insertions(+) create mode 100644 tools/testing/selftests/kvm/lib/kvm_sprintf.c diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index d93bee00c72a..84b126398729 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -23,6 +23,7 @@ LIBKVM += lib/guest_modes.c LIBKVM += lib/io.c LIBKVM += lib/kvm_util.c LIBKVM += lib/memstress.c +LIBKVM += lib/kvm_sprintf.c LIBKVM += lib/rbtree.c LIBKVM += lib/sparsebit.c LIBKVM += lib/test_util.c diff --git a/tools/testing/selftests/kvm/include/test_util.h b/tools/testing/selftests/kvm/include/test_util.h index a6e9f215ce70..45cb0dd41412 100644 --- a/tools/testing/selftests/kvm/include/test_util.h +++ b/tools/testing/selftests/kvm/include/test_util.h @@ -186,4 +186,7 @@ static inline uint32_t atoi_non_negative(const char *name, const char *num_str) return num; } +int kvm_vsnprintf(char *buf, int n, const char *fmt, va_list args); +int kvm_snprintf(char *buf, int n, const char *fmt, ...); + #endif /* SELFTEST_KVM_TEST_UTIL_H */ diff --git a/tools/testing/selftests/kvm/lib/kvm_sprintf.c b/tools/testing/selftests/kvm/lib/kvm_sprintf.c new file mode 100644 index 000000000000..db369e00a6fc --- /dev/null +++ b/tools/testing/selftests/kvm/lib/kvm_sprintf.c @@ -0,0 +1,313 @@ +// SPDX-License-Identifier: GPL-2.0-only +#include "test_util.h" + +#define ASSIGN_AND_INC_SAFE(str, end, v) \ +({ \ + if (str < end) \ + *str = (v); \ + str++; \ +}) + +static int isdigit(int ch) +{ + return (ch >= '0') && (ch <= '9'); +} + +static int skip_atoi(const char **s) +{ + int i = 0; + + while (isdigit(**s)) + i = i * 10 + *((*s)++) - '0'; + return i; +} + +#define ZEROPAD 1 /* pad with zero */ +#define SIGN 2 /* unsigned/signed long */ +#define PLUS 4 /* show plus */ +#define SPACE 8 /* space if plus */ +#define LEFT 16 /* left justified */ +#define SMALL 32 /* Must be 32 == 0x20 */ +#define SPECIAL 64 /* 0x */ + +#define __do_div(n, base) \ +({ \ + int __res; \ + \ + __res = ((uint64_t) n) % (uint32_t) base; \ + n = ((uint64_t) n) / (uint32_t) base; \ + __res; \ +}) + +static char *number(char *str, const char *end, long num, int base, int size, + int precision, int type) +{ + /* we are called with base 8, 10 or 16, only, thus don't need "G..." */ + static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */ + + char tmp[66]; + char c, sign, locase; + int i; + + /* + * locase = 0 or 0x20. ORing digits or letters with 'locase' + * produces same digits or (maybe lowercased) letters + */ + locase = (type & SMALL); + if (type & LEFT) + type &= ~ZEROPAD; + if (base < 2 || base > 16) + return NULL; + c = (type & ZEROPAD) ? '0' : ' '; + sign = 0; + if (type & SIGN) { + if (num < 0) { + sign = '-'; + num = -num; + size--; + } else if (type & PLUS) { + sign = '+'; + size--; + } else if (type & SPACE) { + sign = ' '; + size--; + } + } + if (type & SPECIAL) { + if (base == 16) + size -= 2; + else if (base == 8) + size--; + } + i = 0; + if (num == 0) + tmp[i++] = '0'; + else + while (num != 0) + tmp[i++] = (digits[__do_div(num, base)] | locase); + if (i > precision) + precision = i; + size -= precision; + if (!(type & (ZEROPAD + LEFT))) + while (size-- > 0) + ASSIGN_AND_INC_SAFE(str, end, ' '); + if (sign) + ASSIGN_AND_INC_SAFE(str, end, sign); + if (type & SPECIAL) { + if (base == 8) + ASSIGN_AND_INC_SAFE(str, end, '0'); + else if (base == 16) { + ASSIGN_AND_INC_SAFE(str, end, '0'); + ASSIGN_AND_INC_SAFE(str, end, 'x'); + } + } + if (!(type & LEFT)) + while (size-- > 0) + ASSIGN_AND_INC_SAFE(str, end, c); + while (i < precision--) + ASSIGN_AND_INC_SAFE(str, end, '0'); + while (i-- > 0) + ASSIGN_AND_INC_SAFE(str, end, tmp[i]); + while (size-- > 0) + ASSIGN_AND_INC_SAFE(str, end, ' '); + + return str; +} + +int kvm_vsnprintf(char *buf, int n, const char *fmt, va_list args) +{ + char *str, *end; + const char *s; + uint64_t num; + int i, base; + int len; + + int flags; /* flags to number() */ + + int field_width; /* width of output field */ + int precision; /* + * min. # of digits for integers; max + * number of chars for from string + */ + int qualifier; /* 'h', 'l', or 'L' for integer fields */ + + end = buf + n; + /* Make sure end is always >= buf */ + if (end < buf) { + end = ((void *)-1); + n = end - buf; + } + + for (str = buf; *fmt; ++fmt) { + if (*fmt != '%') { + ASSIGN_AND_INC_SAFE(str, end, *fmt); + continue; + } + + /* process flags */ + flags = 0; +repeat: + ++fmt; /* this also skips first '%' */ + switch (*fmt) { + case '-': + flags |= LEFT; + goto repeat; + case '+': + flags |= PLUS; + goto repeat; + case ' ': + flags |= SPACE; + goto repeat; + case '#': + flags |= SPECIAL; + goto repeat; + case '0': + flags |= ZEROPAD; + goto repeat; + } + + /* get field width */ + field_width = -1; + if (isdigit(*fmt)) + field_width = skip_atoi(&fmt); + else if (*fmt == '*') { + ++fmt; + /* it's the next argument */ + field_width = va_arg(args, int); + if (field_width < 0) { + field_width = -field_width; + flags |= LEFT; + } + } + + /* get the precision */ + precision = -1; + if (*fmt == '.') { + ++fmt; + if (isdigit(*fmt)) + precision = skip_atoi(&fmt); + else if (*fmt == '*') { + ++fmt; + /* it's the next argument */ + precision = va_arg(args, int); + } + if (precision < 0) + precision = 0; + } + + /* get the conversion qualifier */ + qualifier = -1; + if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') { + qualifier = *fmt; + ++fmt; + } + + /* default base */ + base = 10; + + switch (*fmt) { + case 'c': + if (!(flags & LEFT)) + while (--field_width > 0) + ASSIGN_AND_INC_SAFE(str, end, ' '); + ASSIGN_AND_INC_SAFE(str, end, + (uint8_t)va_arg(args, int)); + while (--field_width > 0) + ASSIGN_AND_INC_SAFE(str, end, ' '); + continue; + + case 's': + s = va_arg(args, char *); + len = strnlen(s, precision); + + if (!(flags & LEFT)) + while (len < field_width--) + ASSIGN_AND_INC_SAFE(str, end, ' '); + for (i = 0; i < len; ++i) + ASSIGN_AND_INC_SAFE(str, end, *s++); + while (len < field_width--) + ASSIGN_AND_INC_SAFE(str, end, ' '); + continue; + + case 'p': + if (field_width == -1) { + field_width = 2 * sizeof(void *); + flags |= SPECIAL | SMALL | ZEROPAD; + } + str = number(str, end, + (uint64_t)va_arg(args, void *), 16, + field_width, precision, flags); + continue; + + case 'n': + if (qualifier == 'l') { + long *ip = va_arg(args, long *); + *ip = (str - buf); + } else { + int *ip = va_arg(args, int *); + *ip = (str - buf); + } + continue; + + case '%': + ASSIGN_AND_INC_SAFE(str, end, '%'); + continue; + + /* integer number formats - set up the flags and "break" */ + case 'o': + base = 8; + break; + + case 'x': + flags |= SMALL; + case 'X': + base = 16; + break; + + case 'd': + case 'i': + flags |= SIGN; + case 'u': + break; + + default: + ASSIGN_AND_INC_SAFE(str, end, '%'); + if (*fmt) + ASSIGN_AND_INC_SAFE(str, end, *fmt); + else + --fmt; + continue; + } + if (qualifier == 'l') + num = va_arg(args, uint64_t); + else if (qualifier == 'h') { + num = (uint16_t)va_arg(args, int); + if (flags & SIGN) + num = (int16_t)num; + } else if (flags & SIGN) + num = va_arg(args, int); + else + num = va_arg(args, uint32_t); + str = number(str, end, num, base, field_width, precision, flags); + } + + if (n > 0) { + if (str < end) + *str = '\0'; + else + end[-1] = '\0'; + } + return str - buf; +} + +int kvm_snprintf(char *buf, int n, const char *fmt, ...) +{ + va_list va; + int len; + + va_start(va, fmt); + len = kvm_vsnprintf(buf, n, fmt, va); + va_end(va); + + return len; +} From patchwork Mon Apr 24 22:58:51 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Lewis X-Patchwork-Id: 13222657 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id AED00C7618E for ; Mon, 24 Apr 2023 22:59:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232901AbjDXW7G (ORCPT ); Mon, 24 Apr 2023 18:59:06 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59342 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232614AbjDXW7F (ORCPT ); Mon, 24 Apr 2023 18:59:05 -0400 Received: from mail-pg1-x54a.google.com (mail-pg1-x54a.google.com [IPv6:2607:f8b0:4864:20::54a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D247C9016 for ; Mon, 24 Apr 2023 15:59:03 -0700 (PDT) Received: by mail-pg1-x54a.google.com with SMTP id 41be03b00d2f7-52503bfeb07so1251799a12.3 for ; Mon, 24 Apr 2023 15:59:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1682377143; x=1684969143; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=tFdJlULW+RSlKDezjU5UBSNY1Khq0ApSCM2c+f/Cudg=; b=YXwi6TY9j7KPw4NvQBhzCtQMyWITMb0YPtI1t13fDl1YE0aukmrNsCZtcRYhJuPDQB xhVsJ4p7viGN/SfZOScTa/wTM13k/aYTA+8QXbK+Xd99R8sxcWNNeIJ7FMYg7chL2vlo 3Uwh5FqgoVti3rR+JTueNTS53hFIzggQHgd1SwuUlseVgOge3XtFg9KTkuSEMFKAgq3x LUWYNpNrmIfRzk6E5nTGuso2e4VVfiJsTdsbKdi1kmg6gFvYeHPPcagY/kCyRiPp3oTU 7yQeLg5f+hqbN7yAjIw4bEfxrhvg1V+1fdy2Wl8DiRA+GupS7oisd0R5UQjgI0sLwfl7 vvTA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1682377143; x=1684969143; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=tFdJlULW+RSlKDezjU5UBSNY1Khq0ApSCM2c+f/Cudg=; b=enpoTdaS8ls+Vozti2GdEuFQjGek+emVcvVuM/8duAKvrXwoUGFQSkS6EW+G7S2fGs cOb9zAuutzyG6iVH/ZvOEWo3XVdTdB3oTfanlDqDojFr8IkC4Xs3/YHwaInkkp1mJqHu cPwTM0lznio4gKylAoHt8Rb+zJSrtzHm8FIjiF4EwiTFwXVRv6J5Gw/e2YlOXT7Kaqz+ ALhgzrcENJBScEHxOynx8Ab8+QSF4w9Yizm5/fB2I/NsPXQsVuyz2yf25JX++gu/t928 7dkus4zC6FWWuqfkcD61sDO4RZivWOZL8M25rK6/FdlRO5dExRqefek3lbl+/IErVpmM wkdw== X-Gm-Message-State: AAQBX9cagOlXaUVoYzW/gWqIglR1AYcx1JV+c8Icr0vZZzg1zfNDdWHg qQ99E2mMcvo3SnM95oCQllDx9Un3xKFYmXYYS4SM31Pp0z4StIdpRJUx0LWlA++ijSXg5Vk5cex DtdBG75DWDLUoWDlV+89R7BcFaZLokrjgw0NEWcSz7V6RpDFiebo742zebeDQ8+qtJrxr X-Google-Smtp-Source: AKy350Yh66TOrWXBeU7sxJK2vE4NYBg+wVgLzId6VnNl4cgTkS3vAzOl6JqvFMF2YrY57Tjf+HU1MfC6dCm4WBP1 X-Received: from aaronlewis-2.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:519c]) (user=aaronlewis job=sendgmr) by 2002:a63:5f83:0:b0:520:4c05:221 with SMTP id t125-20020a635f83000000b005204c050221mr3496809pgb.9.1682377143275; Mon, 24 Apr 2023 15:59:03 -0700 (PDT) Date: Mon, 24 Apr 2023 22:58:51 +0000 In-Reply-To: <20230424225854.4023978-1-aaronlewis@google.com> Mime-Version: 1.0 References: <20230424225854.4023978-1-aaronlewis@google.com> X-Mailer: git-send-email 2.40.0.634.g4ca3ef3211-goog Message-ID: <20230424225854.4023978-4-aaronlewis@google.com> Subject: [PATCH v2 3/6] KVM: selftests: Add additional pages to the guest to accommodate ucall From: Aaron Lewis To: kvm@vger.kernel.org Cc: pbonzini@redhat.com, jmattson@google.com, seanjc@google.com, Aaron Lewis Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Add additional pages to the guest to account for the number of pages the ucall framework uses. This is done in preparation for adding string formatting options to the guest through ucall helpers. Signed-off-by: Aaron Lewis --- tools/testing/selftests/kvm/include/ucall_common.h | 1 + tools/testing/selftests/kvm/lib/kvm_util.c | 4 ++++ tools/testing/selftests/kvm/lib/ucall_common.c | 5 +++++ 3 files changed, 10 insertions(+) diff --git a/tools/testing/selftests/kvm/include/ucall_common.h b/tools/testing/selftests/kvm/include/ucall_common.h index 1a6aaef5ccae..bcbb362aa77f 100644 --- a/tools/testing/selftests/kvm/include/ucall_common.h +++ b/tools/testing/selftests/kvm/include/ucall_common.h @@ -34,6 +34,7 @@ void *ucall_arch_get_ucall(struct kvm_vcpu *vcpu); void ucall(uint64_t cmd, int nargs, ...); uint64_t get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc); void ucall_init(struct kvm_vm *vm, vm_paddr_t mmio_gpa); +int ucall_nr_pages_required(uint64_t page_size); /* * Perform userspace call without any associated data. This bare call avoids diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c index 298c4372fb1a..80b3df2a79e6 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -312,6 +312,7 @@ static uint64_t vm_nr_pages_required(enum vm_guest_mode mode, uint32_t nr_runnable_vcpus, uint64_t extra_mem_pages) { + uint64_t page_size = vm_guest_mode_params[mode].page_size; uint64_t nr_pages; TEST_ASSERT(nr_runnable_vcpus, @@ -340,6 +341,9 @@ static uint64_t vm_nr_pages_required(enum vm_guest_mode mode, */ nr_pages += (nr_pages + extra_mem_pages) / PTES_PER_MIN_PAGE * 2; + /* Account for the number of pages needed by ucall. */ + nr_pages += ucall_nr_pages_required(page_size); + return vm_adjust_num_guest_pages(mode, nr_pages); } diff --git a/tools/testing/selftests/kvm/lib/ucall_common.c b/tools/testing/selftests/kvm/lib/ucall_common.c index 2f0e2ea941cc..77ada362273d 100644 --- a/tools/testing/selftests/kvm/lib/ucall_common.c +++ b/tools/testing/selftests/kvm/lib/ucall_common.c @@ -11,6 +11,11 @@ struct ucall_header { struct ucall ucalls[KVM_MAX_VCPUS]; }; +int ucall_nr_pages_required(uint64_t page_size) +{ + return align_up(sizeof(struct ucall_header), page_size) / page_size; +} + /* * ucall_pool holds per-VM values (global data is duplicated by each VM), it * must not be accessed from host code. From patchwork Mon Apr 24 22:58:52 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Lewis X-Patchwork-Id: 13222658 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0E244C77B61 for ; Mon, 24 Apr 2023 22:59:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232384AbjDXW7J (ORCPT ); Mon, 24 Apr 2023 18:59:09 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59400 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232614AbjDXW7H (ORCPT ); Mon, 24 Apr 2023 18:59:07 -0400 Received: from mail-pl1-x64a.google.com (mail-pl1-x64a.google.com [IPv6:2607:f8b0:4864:20::64a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E17D27AA3 for ; Mon, 24 Apr 2023 15:59:05 -0700 (PDT) Received: by mail-pl1-x64a.google.com with SMTP id d9443c01a7336-1a6ee59714aso32363405ad.0 for ; Mon, 24 Apr 2023 15:59:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1682377145; x=1684969145; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=7pGoz+Bqh9o5ewll2j0pCufns/tQJxlKIWLlecHHcHQ=; b=FN03f9IGQjmYwOkFRkjbK4Q1TQXK7uOPGXHHJNGacGJ9RORpedCQtMxDS7paEZDUlR CE52/h4hpeVBh8R4dLSjiU40rVd7WnNjy3JpS3TsH2yV6lu8akDxXvAf0nf9XsenjCzd jJlYxCdnSqFITGOF3uL1ZsqyXuHHwl8vJjtl3R77+CZUlalViYlv7xLkN6WD0iyl6Q0s UOJFkWjRRTDiSERbcfC5XVjBVAba626vYVpT80lYaTY9ppAKtlpZcOLMDwYbRy1PTHg6 689OUy9ojWZBWFSMdIHimZ6EVJgVUCQmSvDSPFk3Pl3M8Rlf40ZOWWUpU5uLRNNBgliZ vRHA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1682377145; x=1684969145; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=7pGoz+Bqh9o5ewll2j0pCufns/tQJxlKIWLlecHHcHQ=; b=I8K04GmTB1D6YOBGyaI5cz0lgVFyTF10cGbfjSi3y62FyqQrKwL4Ywo/FsMRf8dkf5 a8slfvok+Cjbu3UoN2H93W2OyUbVoOj7QNgwlp8SbMBRk3uFkjeoXSbG55QgH12X04Ru 9ctR57EQTlZOxUxMi2N5O2z78sZS1yPuNtzcYMW40FKUoWaFvIaAs+ee9iz/PrSUziWh T8J1U5YawGAX/YjMCGmXB23Dbj90V64TW6HM38PMhaGeOBQSG7KnQdjqQNlazpECjJOP zFYftTdQQsVIeph9+HOse2Bdoxkx+YHzT73o2RC4fxm5ifzIN8DNKAGybCYqoCBkb873 QDGg== X-Gm-Message-State: AAQBX9e/AJVuLmGvsdAazi7kVhot7S/0XK3DsH3CEyxmFvjWI/GaJfdC VU+8VSSGM9/8ci4t8F8MuKqI0WFLrRzjvvyB+O3Qr2Q4dTnyS7gfZ1g9dw8RINWJzk727087BzJ Tc4G5Gtn+MRX0BRN+VS+48FP+giplNZk2rxoGwLTvVIYutlxRVp61uKnzr7kmOehKOxhq X-Google-Smtp-Source: AKy350b4pfh/YlMsuaW4rZYYpj+dNsTeLX7ThDimiW3q1dl4TEbtQOjEsR1jlHbRhJh4oeTWGHERtrvifYCWb9N4 X-Received: from aaronlewis-2.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:519c]) (user=aaronlewis job=sendgmr) by 2002:a17:902:d151:b0:1a1:e48b:98b8 with SMTP id t17-20020a170902d15100b001a1e48b98b8mr4387408plt.10.1682377145113; Mon, 24 Apr 2023 15:59:05 -0700 (PDT) Date: Mon, 24 Apr 2023 22:58:52 +0000 In-Reply-To: <20230424225854.4023978-1-aaronlewis@google.com> Mime-Version: 1.0 References: <20230424225854.4023978-1-aaronlewis@google.com> X-Mailer: git-send-email 2.40.0.634.g4ca3ef3211-goog Message-ID: <20230424225854.4023978-5-aaronlewis@google.com> Subject: [PATCH v2 4/6] KVM: selftests: Add string formatting options to ucall From: Aaron Lewis To: kvm@vger.kernel.org Cc: pbonzini@redhat.com, jmattson@google.com, seanjc@google.com, Aaron Lewis Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Add more flexibility to guest debugging and testing by adding GUEST_PRINTF() and GUEST_ASSERT_FMT() to the ucall framework. A buffer to hold the formatted string was added to the ucall struct. That allows the guest/host to avoid the problem of passing an arbitrary number of parameters between themselves when resolving the string. Instead, the string is resolved in the guest then passed back to the host to be logged. The formatted buffer is set to 1024 bytes which increases the size of the ucall struct. As a result, this will increase the number of pages requested for the guest. The buffer size was chosen to accommodate most use cases, and based on similar usage. E.g. printf() uses the same size buffer in arch/x86/boot/printf.c. Signed-off-by: Aaron Lewis --- .../selftests/kvm/include/ucall_common.h | 18 ++++++++++++++++++ tools/testing/selftests/kvm/lib/ucall_common.c | 18 ++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/tools/testing/selftests/kvm/include/ucall_common.h b/tools/testing/selftests/kvm/include/ucall_common.h index bcbb362aa77f..7281a6892779 100644 --- a/tools/testing/selftests/kvm/include/ucall_common.h +++ b/tools/testing/selftests/kvm/include/ucall_common.h @@ -13,15 +13,18 @@ enum { UCALL_NONE, UCALL_SYNC, UCALL_ABORT, + UCALL_PRINTF, UCALL_DONE, UCALL_UNHANDLED, }; #define UCALL_MAX_ARGS 7 +#define UCALL_BUFFER_LEN 1024 struct ucall { uint64_t cmd; uint64_t args[UCALL_MAX_ARGS]; + char buffer[UCALL_BUFFER_LEN]; /* Host virtual address of this struct. */ struct ucall *hva; @@ -32,6 +35,7 @@ void ucall_arch_do_ucall(vm_vaddr_t uc); void *ucall_arch_get_ucall(struct kvm_vcpu *vcpu); void ucall(uint64_t cmd, int nargs, ...); +void ucall_fmt(uint64_t cmd, const char *fmt, ...); uint64_t get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc); void ucall_init(struct kvm_vm *vm, vm_paddr_t mmio_gpa); int ucall_nr_pages_required(uint64_t page_size); @@ -47,6 +51,7 @@ int ucall_nr_pages_required(uint64_t page_size); #define GUEST_SYNC_ARGS(stage, arg1, arg2, arg3, arg4) \ ucall(UCALL_SYNC, 6, "hello", stage, arg1, arg2, arg3, arg4) #define GUEST_SYNC(stage) ucall(UCALL_SYNC, 2, "hello", stage) +#define GUEST_PRINTF(_fmt, _args...) ucall_fmt(UCALL_PRINTF, _fmt, ##_args) #define GUEST_DONE() ucall(UCALL_DONE, 0) enum guest_assert_builtin_args { @@ -56,6 +61,17 @@ enum guest_assert_builtin_args { GUEST_ASSERT_BUILTIN_NARGS }; +#define __GUEST_ASSERT_FMT(_condition, _condstr, _fmt, _args...) \ +do { \ + if (!(_condition)) \ + ucall_fmt(UCALL_ABORT, \ + "Failed guest assert: " _condstr " at %s:%ld\n " _fmt, \ + , __FILE__, __LINE__, ##_args); \ +} while (0) + +#define GUEST_ASSERT_FMT(_condition, _fmt, _args...) \ + __GUEST_ASSERT_FMT(_condition, #_condition, _fmt, ##_args) + #define __GUEST_ASSERT(_condition, _condstr, _nargs, _args...) \ do { \ if (!(_condition)) \ @@ -81,6 +97,8 @@ do { \ #define GUEST_ASSERT_EQ(a, b) __GUEST_ASSERT((a) == (b), #a " == " #b, 2, a, b) +#define REPORT_GUEST_ASSERT_FMT(_ucall) TEST_FAIL("%s", _ucall.buffer) + #define __REPORT_GUEST_ASSERT(_ucall, fmt, _args...) \ TEST_FAIL("%s at %s:%ld\n" fmt, \ (const char *)(_ucall).args[GUEST_ERROR_STRING], \ diff --git a/tools/testing/selftests/kvm/lib/ucall_common.c b/tools/testing/selftests/kvm/lib/ucall_common.c index 77ada362273d..c09e57c8ef77 100644 --- a/tools/testing/selftests/kvm/lib/ucall_common.c +++ b/tools/testing/selftests/kvm/lib/ucall_common.c @@ -55,6 +55,7 @@ static struct ucall *ucall_alloc(void) if (!test_and_set_bit(i, ucall_pool->in_use)) { uc = &ucall_pool->ucalls[i]; memset(uc->args, 0, sizeof(uc->args)); + memset(uc->buffer, 0, sizeof(uc->buffer)); return uc; } } @@ -75,6 +76,23 @@ static void ucall_free(struct ucall *uc) clear_bit(uc - ucall_pool->ucalls, ucall_pool->in_use); } +void ucall_fmt(uint64_t cmd, const char *fmt, ...) +{ + struct ucall *uc; + va_list va; + + uc = ucall_alloc(); + uc->cmd = cmd; + + va_start(va, fmt); + kvm_vsnprintf(uc->buffer, UCALL_BUFFER_LEN, fmt, va); + va_end(va); + + ucall_arch_do_ucall((vm_vaddr_t)uc->hva); + + ucall_free(uc); +} + void ucall(uint64_t cmd, int nargs, ...) { struct ucall *uc; From patchwork Mon Apr 24 22:58:53 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Lewis X-Patchwork-Id: 13222659 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 755B7C77B76 for ; Mon, 24 Apr 2023 22:59:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232681AbjDXW7K (ORCPT ); Mon, 24 Apr 2023 18:59:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59428 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233020AbjDXW7I (ORCPT ); Mon, 24 Apr 2023 18:59:08 -0400 Received: from mail-pg1-x54a.google.com (mail-pg1-x54a.google.com [IPv6:2607:f8b0:4864:20::54a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0EC0B9025 for ; Mon, 24 Apr 2023 15:59:07 -0700 (PDT) Received: by mail-pg1-x54a.google.com with SMTP id 41be03b00d2f7-52503bfeb07so1251805a12.3 for ; Mon, 24 Apr 2023 15:59:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1682377146; x=1684969146; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=hbOymScOo75LUEkrgYekJoiRx67W5YRYoUgYkSf+Iw0=; b=I8UYl8b6RChd3RSlGjrJh5uJwG+eQ1eF4yDeileuL3L06Bmsy1LCK4cKGsKknmR+/T 7+XVazxbwgO+MlKLyuwI/KLT1+6DbEFZzy6+WsUHEix6Ya2uVVD5WN8j/RgbCpug1uo/ wDNw9Vk+9dJVeOG4wWwfgTA5V/7+ymggp2pT9uZnlsFi3rFayReeuBrnn/aabNJcrPEO igLvIS+8fKmwx6+ijZkg8xjxspuhNhcjUvHjF2hRyaHFstuDKxk/4kyIiFkR3Z7uoUt5 BC+KsW4NS9ogzmNCIVuTbxA3uvtQr1YCOPRFR+BUvr09CXrhjAFVxo52KAQBd34RWFhN CNpQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1682377146; x=1684969146; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=hbOymScOo75LUEkrgYekJoiRx67W5YRYoUgYkSf+Iw0=; b=WYZbBZ4B2/mWe252/ZkuDfNjfVG0Dao8wue9v4tiYeRytBBFNaLAP9PmFdzB0FNosV T/+wsraBtNoobY7Pi5entEsE7nrzufKO8Cn5/9afL2zDJSRLOyrF7lUAP0eFSYzVv5N+ 4LBeSW7BUWse9oV78kMJLgecIIU56S83Fj2GF6QfuV4NddK2WcWCRkHPc1x53skyCzjV GKz7HfaYDqztlJbZRunGn157evJDtR9fRNH3Jg0q3MkOiD8ns1lOISHDoQN/jX048M33 AoOjiV4y/mFQo56SY7b3T/zo2pV0vNW8BAAlqb8qhViIFOziKU87sTU/8mVTpKMRVQcs hi/w== X-Gm-Message-State: AAQBX9d/ab2B1Jafep7Hauex7xihNIZ+tDX/pI1y++zzKON6nwXWcMXv 02GrLdWsn3RMu+yytlgu+PFmOcZan58IHrwjHyjIS1jVNjKPAKm3W2ciEXffzb5sKGDizb3ZmD5 iGqLCuZtDKRQJLL7bqTp7baT295XJ2DmFr9/nwevUZGWLYpgz1p4STG+OCQ+gxkDMmX2I X-Google-Smtp-Source: AKy350azkvYPOXXoggpdpuQ1osIj+QMvmReGe4f96bDDGccPVftOm8sqqpa0I742jmQjy5fYY9wzPupeS9Iaruw1 X-Received: from aaronlewis-2.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:519c]) (user=aaronlewis job=sendgmr) by 2002:a63:5f83:0:b0:520:4c05:221 with SMTP id t125-20020a635f83000000b005204c050221mr3496835pgb.9.1682377146661; Mon, 24 Apr 2023 15:59:06 -0700 (PDT) Date: Mon, 24 Apr 2023 22:58:53 +0000 In-Reply-To: <20230424225854.4023978-1-aaronlewis@google.com> Mime-Version: 1.0 References: <20230424225854.4023978-1-aaronlewis@google.com> X-Mailer: git-send-email 2.40.0.634.g4ca3ef3211-goog Message-ID: <20230424225854.4023978-6-aaronlewis@google.com> Subject: [PATCH v2 5/6] KVM: selftests: Add ucall_fmt2() From: Aaron Lewis To: kvm@vger.kernel.org Cc: pbonzini@redhat.com, jmattson@google.com, seanjc@google.com, Aaron Lewis Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Add a second ucall_fmt() function that takes two format strings instead of one. This provides more flexibility because the string format in GUEST_ASSERT_FMT() is no linger limited to only using literals. This provides better consistency between GUEST_PRINTF() and GUEST_ASSERT_FMT() as GUEST_PRINTF() is not limited to only using literals either. Signed-off-by: Aaron Lewis --- .../selftests/kvm/include/ucall_common.h | 13 +++++----- .../testing/selftests/kvm/lib/ucall_common.c | 24 +++++++++++++++++++ 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/tools/testing/selftests/kvm/include/ucall_common.h b/tools/testing/selftests/kvm/include/ucall_common.h index 7281a6892779..3e8135aaa812 100644 --- a/tools/testing/selftests/kvm/include/ucall_common.h +++ b/tools/testing/selftests/kvm/include/ucall_common.h @@ -36,6 +36,7 @@ void *ucall_arch_get_ucall(struct kvm_vcpu *vcpu); void ucall(uint64_t cmd, int nargs, ...); void ucall_fmt(uint64_t cmd, const char *fmt, ...); +void ucall_fmt2(uint64_t cmd, const char *fmt1, const char *fmt2, ...); uint64_t get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc); void ucall_init(struct kvm_vm *vm, vm_paddr_t mmio_gpa); int ucall_nr_pages_required(uint64_t page_size); @@ -61,12 +62,12 @@ enum guest_assert_builtin_args { GUEST_ASSERT_BUILTIN_NARGS }; -#define __GUEST_ASSERT_FMT(_condition, _condstr, _fmt, _args...) \ -do { \ - if (!(_condition)) \ - ucall_fmt(UCALL_ABORT, \ - "Failed guest assert: " _condstr " at %s:%ld\n " _fmt, \ - , __FILE__, __LINE__, ##_args); \ +#define __GUEST_ASSERT_FMT(_condition, _condstr, _fmt, _args...) \ +do { \ + if (!(_condition)) \ + ucall_fmt2(UCALL_ABORT, \ + "Failed guest assert: " _condstr " at %s:%ld\n ",\ + _fmt, __FILE__, __LINE__, ##_args); \ } while (0) #define GUEST_ASSERT_FMT(_condition, _fmt, _args...) \ diff --git a/tools/testing/selftests/kvm/lib/ucall_common.c b/tools/testing/selftests/kvm/lib/ucall_common.c index c09e57c8ef77..d0f1ad6c0c44 100644 --- a/tools/testing/selftests/kvm/lib/ucall_common.c +++ b/tools/testing/selftests/kvm/lib/ucall_common.c @@ -76,6 +76,30 @@ static void ucall_free(struct ucall *uc) clear_bit(uc - ucall_pool->ucalls, ucall_pool->in_use); } +void ucall_fmt2(uint64_t cmd, const char *fmt1, const char *fmt2, ...) +{ + const int fmt_len = 128; + char fmt[fmt_len]; + struct ucall *uc; + va_list va; + int len; + + len = kvm_snprintf(fmt, fmt_len, "%s%s", fmt1, fmt2); + if (len > fmt_len) + ucall_arch_do_ucall(GUEST_UCALL_FAILED); + + uc = ucall_alloc(); + uc->cmd = cmd; + + va_start(va, fmt2); + kvm_vsnprintf(uc->buffer, UCALL_BUFFER_LEN, fmt, va); + va_end(va); + + ucall_arch_do_ucall((vm_vaddr_t)uc->hva); + + ucall_free(uc); +} + void ucall_fmt(uint64_t cmd, const char *fmt, ...) { struct ucall *uc; From patchwork Mon Apr 24 22:58:54 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Lewis X-Patchwork-Id: 13222660 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 53D1DC7618E for ; Mon, 24 Apr 2023 22:59:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233150AbjDXW7M (ORCPT ); Mon, 24 Apr 2023 18:59:12 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59490 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233015AbjDXW7K (ORCPT ); Mon, 24 Apr 2023 18:59:10 -0400 Received: from mail-pj1-x1049.google.com (mail-pj1-x1049.google.com [IPv6:2607:f8b0:4864:20::1049]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0E0A093C1 for ; Mon, 24 Apr 2023 15:59:08 -0700 (PDT) Received: by mail-pj1-x1049.google.com with SMTP id 98e67ed59e1d1-24763adb145so4951959a91.2 for ; Mon, 24 Apr 2023 15:59:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1682377148; x=1684969148; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=ZuwyeqJU2ec2RnXFc6oVuANOVQcHu6d+sHkMhDN9j9E=; b=Wb2urpN/5j7jJtUVBrNfy+U2bPKKCkuLnZrQBBb88jPHXgUC2NQlh+33DbJiMzT5i7 xAGZDsydldLCELgwg54aD7uDUa5oKAD6eUWc1Vcr1Gr0hSyeOETBwzIYxhTHNbDuiMnO jOAqJP/bpDeeFomcz/Ifo+IBnuX46iS8/fOm7s5GrX8mopaUVP+2fZ3tfOM1NSJTJWmM yjvOfhtQPhNHb10Fxzm8dRYCm2g8FF3Cy+VXgqi4enfUT0MsSnz0etiGU+1uRizqozeD HanOGzf54gTYsxC8Xt7UZzQolBjm3zDfnORbezyb/wG2PXcpcxaIxIJ5RX1KcF3baPdI uYtg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1682377148; x=1684969148; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=ZuwyeqJU2ec2RnXFc6oVuANOVQcHu6d+sHkMhDN9j9E=; b=GvHlgxSH694qPI6wrFwqE4NwMOVTQo91JWWO3Se334gC0FMnDax7hLLPqh+b/55MzS 3vVvkJw1n+EWHrobvw3/RVSWk3T2ueqgPmSnd2H2X/fLCcdV/nzElFymlX7/WG9grBpv dRDEitWn4qIi4Zg1qT65Mo4EmMn22TrtAPu3INr3WZlR7FLGu/iB/Pai4w+s0T55FHrd GRv8qwHQyRDo0tTgVs2QjbdSbDdX06hvZN7A6h/mzxmvGq43knDNyVREVvZmEC12Et8d fvwl0zKNZRxki3+CCtLmR486qoXFNja7eBH7S0TkLvRo+daN7oZ8yEyIIs9vGcypzqHA z2OQ== X-Gm-Message-State: AAQBX9dQW6pjz0EbJIxXVp19RnzRc9fUzdw0OoE4eEuvLKYkg7ogUrlA 7JmR3HDvxMShpcqrD1WHwovLRrCs/cyQVXTrEp+u5fDaGkXoywsWHOOpFz6S1bO/2UYaLI6Zcsg jGa+Qa1Z7SpLURdt4NzaMn0irZQQ8anouOCBO6OvbRHMnjRRYaX/w6GqnmlunS39eD6r2 X-Google-Smtp-Source: AKy350Yy/Ppyj3DYTKUlNH28a4PB95v78vuIxkSV3S96Nb40A3gbVAjw7w66sASo3wtSCFhFQrEQHue7zmw/Cpu/ X-Received: from aaronlewis-2.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:519c]) (user=aaronlewis job=sendgmr) by 2002:a17:90a:4ecc:b0:246:66d6:f24e with SMTP id v12-20020a17090a4ecc00b0024666d6f24emr3787625pjl.2.1682377148361; Mon, 24 Apr 2023 15:59:08 -0700 (PDT) Date: Mon, 24 Apr 2023 22:58:54 +0000 In-Reply-To: <20230424225854.4023978-1-aaronlewis@google.com> Mime-Version: 1.0 References: <20230424225854.4023978-1-aaronlewis@google.com> X-Mailer: git-send-email 2.40.0.634.g4ca3ef3211-goog Message-ID: <20230424225854.4023978-7-aaronlewis@google.com> Subject: [PATCH v2 6/6] KVM: selftests: Add a selftest for guest prints and formatted asserts From: Aaron Lewis To: kvm@vger.kernel.org Cc: pbonzini@redhat.com, jmattson@google.com, seanjc@google.com, Aaron Lewis Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org The purpose of this test is to exercise the various features in KVM's local snprintf() and compare them to LIBC's snprintf() to ensure they behave the same. This is not an exhaustive test. KVM's local snprintf() does not implement all the features LIBC does, e.g. KVM's local snprintf() does not support floats or doubles, so testing for those features were excluded. Testing was added for the features that are expected to work to support a minimal version of printf() in the guest. Signed-off-by: Aaron Lewis --- tools/testing/selftests/kvm/Makefile | 1 + .../testing/selftests/kvm/guest_print_test.c | 207 ++++++++++++++++++ 2 files changed, 208 insertions(+) create mode 100644 tools/testing/selftests/kvm/guest_print_test.c diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index 84b126398729..31587a0e2efb 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -121,6 +121,7 @@ TEST_GEN_PROGS_x86_64 += access_tracking_perf_test TEST_GEN_PROGS_x86_64 += demand_paging_test TEST_GEN_PROGS_x86_64 += dirty_log_test TEST_GEN_PROGS_x86_64 += dirty_log_perf_test +TEST_GEN_PROGS_x86_64 += guest_print_test TEST_GEN_PROGS_x86_64 += hardware_disable_test TEST_GEN_PROGS_x86_64 += kvm_create_max_vcpus TEST_GEN_PROGS_x86_64 += kvm_page_table_test diff --git a/tools/testing/selftests/kvm/guest_print_test.c b/tools/testing/selftests/kvm/guest_print_test.c new file mode 100644 index 000000000000..57489055e5cb --- /dev/null +++ b/tools/testing/selftests/kvm/guest_print_test.c @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * A test for GUEST_PRINTF + * + * Copyright 2022, Google, Inc. and/or its affiliates. + */ + +#include +#include +#include +#include +#include + +#include "test_util.h" +#include "kvm_util.h" +#include "processor.h" + +/* GUEST_PRINTF()/GUEST_ASSERT_FMT() does not support float or double. */ +#define TYPE_LIST \ +TYPE(test_type_i64, I64, "%ld", int64_t) \ +TYPE(test_type_u64, U64u, "%lu", uint64_t) \ +TYPE(test_type_x64, U64x, "0x%lx", uint64_t) \ +TYPE(test_type_X64, U64X, "0x%lX", uint64_t) \ +TYPE(test_type_u32, U32u, "%u", uint32_t) \ +TYPE(test_type_x32, U32x, "0x%x", uint32_t) \ +TYPE(test_type_X32, U32X, "0x%X", uint32_t) \ +TYPE(test_type_int, INT, "%d", int) \ +TYPE(test_type_char, CHAR, "%c", char) \ +TYPE(test_type_str, STR, "'%s'", const char *) \ +TYPE(test_type_ptr, PTR, "%p", uintptr_t) + +enum args_type { +#define TYPE(fn, ext, fmt_t, T) TYPE_##ext, + TYPE_LIST +#undef TYPE +}; + +static void run_test(struct kvm_vcpu *vcpu, const char *expected_printf, + const char *expected_assert); + +#define BUILD_TYPE_STRINGS_AND_HELPER(fn, ext, fmt_t, T) \ +const char *PRINTF_FMT_##ext = "Got params a = " fmt_t " and b = " fmt_t; \ +const char *ASSERT_FMT_##ext = "Expected " fmt_t ", got " fmt_t " instead"; \ +static void fn(struct kvm_vcpu *vcpu, T a, T b) \ +{ \ + char expected_printf[UCALL_BUFFER_LEN]; \ + char expected_assert[UCALL_BUFFER_LEN]; \ + \ + snprintf(expected_printf, UCALL_BUFFER_LEN, PRINTF_FMT_##ext, a, b); \ + snprintf(expected_assert, UCALL_BUFFER_LEN, ASSERT_FMT_##ext, a, b); \ + vcpu_args_set(vcpu, 3, a, b, TYPE_##ext); \ + run_test(vcpu, expected_printf, expected_assert); \ +} + +#define TYPE(fn, ext, fmt_t, T) \ + BUILD_TYPE_STRINGS_AND_HELPER(fn, ext, fmt_t, T) + TYPE_LIST +#undef TYPE + +static void guest_code(uint64_t a, uint64_t b, uint64_t type) +{ + switch (type) { +#define TYPE(fn, ext, fmt_t, T) case TYPE_##ext: \ + GUEST_PRINTF(PRINTF_FMT_##ext, a, b); \ + GUEST_ASSERT_FMT(a == b, ASSERT_FMT_##ext, a, b); \ + break; + TYPE_LIST +#undef TYPE + default: + GUEST_SYNC(type); + } + + GUEST_DONE(); +} + +/* + * Unfortunately this gets a little messy because 'assert_msg' doesn't + * just contains the matching string, it also contains additional assert + * info. Fortunately the part that matches should be at the very end of + * 'assert_msg'. + */ +static void ucall_abort(const char *assert_msg, const char *expected_assert_msg) +{ + int len_str = strlen(assert_msg); + int len_substr = strlen(expected_assert_msg); + int offset = len_str - len_substr; + + TEST_ASSERT(len_substr <= len_str, + "Expected to find a substring, len_str: %d, len_substr: %d", + len_str, len_substr); + + TEST_ASSERT(strcmp(&assert_msg[offset], expected_assert_msg) == 0, + "Unexpected mismatch. Expected: '%s', got: '%s'", + expected_assert_msg, &assert_msg[offset]); +} + +static void run_test(struct kvm_vcpu *vcpu, const char *expected_printf, + const char *expected_assert) +{ + struct kvm_run *run = vcpu->run; + struct kvm_regs regs; + struct ucall uc; + + /* + * The guest takes 3 parameters (T val1, T val2, TYPE) which are set + * in the parent call to allow run_tests() to be type-agnostic. + */ + + vcpu_regs_get(vcpu, ®s); + regs.rip = (uintptr_t)guest_code; + vcpu_regs_set(vcpu, ®s); + + while (1) { + vcpu_run(vcpu); + + TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, + "Unexpected exit reason: %u (%s),\n", + run->exit_reason, + exit_reason_str(run->exit_reason)); + + switch (get_ucall(vcpu, &uc)) { + case UCALL_SYNC: + TEST_FAIL("Unknown 'args_type' = %lu", uc.args[1]); + break; + case UCALL_PRINTF: + TEST_ASSERT(strcmp(uc.buffer, expected_printf) == 0, + "Unexpected mismatch. Expected: '%s', got: '%s'", + expected_printf, uc.buffer); + break; + case UCALL_ABORT: + ucall_abort(uc.buffer, expected_assert); + break; + case UCALL_DONE: + return; + default: + TEST_FAIL("Unknown ucall %lu", uc.cmd); + } + } +} + +static void test_limits(void) +{ + const int buffer_len = UCALL_BUFFER_LEN + 10; + char test_str[buffer_len]; + char test_res[buffer_len]; + int r; + + memset(test_str, 'a', buffer_len); + test_str[buffer_len - 1] = 0; + + r = kvm_snprintf(test_res, UCALL_BUFFER_LEN, "%s", test_str); + TEST_ASSERT(r == (buffer_len - 1), + "Unexpected kvm_snprintf() length. Expected: %d, got: %d", + buffer_len - 1, r); + + r = strlen(test_res); + TEST_ASSERT(r == (UCALL_BUFFER_LEN - 1), + "Unexpected strlen() length. Expected: %d, got: %d", + UCALL_BUFFER_LEN - 1, r); +} + +int main(int argc, char *argv[]) +{ + struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + + vm = vm_create_with_one_vcpu(&vcpu, NULL); + + test_type_i64(vcpu, -1, -1); + test_type_i64(vcpu, -1, 1); + test_type_i64(vcpu, 0x1234567890abcdef, 0x1234567890abcdef); + test_type_i64(vcpu, 0x1234567890abcdef, 0x1234567890abcdee); + + test_type_u64(vcpu, 0x1234567890abcdef, 0x1234567890abcdef); + test_type_u64(vcpu, 0x1234567890abcdef, 0x1234567890abcdee); + test_type_x64(vcpu, 0x1234567890abcdef, 0x1234567890abcdef); + test_type_x64(vcpu, 0x1234567890abcdef, 0x1234567890abcdee); + test_type_X64(vcpu, 0x1234567890abcdef, 0x1234567890abcdef); + test_type_X64(vcpu, 0x1234567890abcdef, 0x1234567890abcdee); + + test_type_u32(vcpu, 0x90abcdef, 0x90abcdef); + test_type_u32(vcpu, 0x90abcdef, 0x90abcdee); + test_type_x32(vcpu, 0x90abcdef, 0x90abcdef); + test_type_x32(vcpu, 0x90abcdef, 0x90abcdee); + test_type_X32(vcpu, 0x90abcdef, 0x90abcdef); + test_type_X32(vcpu, 0x90abcdef, 0x90abcdee); + + test_type_int(vcpu, -1, -1); + test_type_int(vcpu, -1, 1); + test_type_int(vcpu, 1, 1); + + test_type_char(vcpu, 'a', 'a'); + test_type_char(vcpu, 'a', 'A'); + test_type_char(vcpu, 'a', 'b'); + + test_type_str(vcpu, "foo", "foo"); + test_type_str(vcpu, "foo", "bar"); + + test_type_ptr(vcpu, 0x1234567890abcdef, 0x1234567890abcdef); + test_type_ptr(vcpu, 0x1234567890abcdef, 0x1234567890abcdee); + + kvm_vm_free(vm); + + test_limits(); + + return 0; +}