All of lore.kernel.org
 help / color / mirror / Atom feed
From: Warner Losh <imp@bsdimp.com>
To: qemu-devel@nongnu.org
Cc: "Kyle Evans" <kevans@freebsd.org>,
	richard.henderson@linaro.org,
	"Alex Bennée" <alex.bennee@linaro.org>,
	f4bug@amsat.org, "Warner Losh" <imp@bsdimp.com>,
	"Paolo Bonzini" <pbonzini@redhat.com>,
	"Thomas Huth" <thuth@redhat.com>,
	"Sean Bruno" <sbruno@FreeBSD.org>,
	"Juergen Lock" <nox@jelal.kn-bremen.de>,
	"Raphael Kubo da Costa" <rakuco@FreeBSD.org>,
	"Stacey Son" <sson@FreeBSD.org>
Subject: [PATCH v3 06/11] bsd-user: Helper routines h2g_old_sysctl
Date: Thu, 16 Feb 2023 16:33:48 -0700	[thread overview]
Message-ID: <20230216233353.13944-7-imp@bsdimp.com> (raw)
In-Reply-To: <20230216233353.13944-1-imp@bsdimp.com>

h2g_old_sysctl does the byte swapping in the data to return it to the
target for the 'well known' types. For most of the types, either the
data is returned verbatim (strings, byte size, opaque we don't know
about) or it's returned with byte swapping (for all the integer
types). However, for ABI32 targets, LONG and ULONG are different sizes,
and need to be carefully converted (along with help from the caller).

Co-Authored-by: Sean Bruno <sbruno@FreeBSD.org>
Signed-off-by: Sean Bruno <sbruno@FreeBSD.org>
Co-Authored-by: Juergen Lock <nox@jelal.kn-bremen.de>
Signed-off-by: Juergen Lock <nox@jelal.kn-bremen.de>
Co-Authored-by: Raphael Kubo da Costa <rakuco@FreeBSD.org>
Signed-off-by: Raphael Kubo da Costa <rakuco@FreeBSD.org>
Co-Authored-by: Stacey Son <sson@FreeBSD.org>
Signed-off-by: Stacey Son <sson@FreeBSD.org>
Signed-off-by: Warner Losh <imp@bsdimp.com>
---
 bsd-user/freebsd/os-sys.c | 100 ++++++++++++++++++++++++++++++++++++--
 1 file changed, 96 insertions(+), 4 deletions(-)

diff --git a/bsd-user/freebsd/os-sys.c b/bsd-user/freebsd/os-sys.c
index 1bf2b51820e..77c2b157c61 100644
--- a/bsd-user/freebsd/os-sys.c
+++ b/bsd-user/freebsd/os-sys.c
@@ -29,7 +29,7 @@
  * Compare with sys/kern_sysctl.c ctl_size
  * Note: Not all types appear to be used in-tree.
  */
-static const int G_GNUC_UNUSED guest_ctl_size[CTLTYPE+1] = {
+static const int guest_ctl_size[CTLTYPE+1] = {
         [CTLTYPE_INT] = sizeof(abi_int),
         [CTLTYPE_UINT] = sizeof(abi_uint),
         [CTLTYPE_LONG] = sizeof(abi_long),
@@ -44,7 +44,7 @@ static const int G_GNUC_UNUSED guest_ctl_size[CTLTYPE+1] = {
         [CTLTYPE_U64] = sizeof(uint64_t),
 };
 
-static const int G_GNUC_UNUSED host_ctl_size[CTLTYPE+1] = {
+static const int host_ctl_size[CTLTYPE+1] = {
         [CTLTYPE_INT] = sizeof(int),
         [CTLTYPE_UINT] = sizeof(u_int),
         [CTLTYPE_LONG] = sizeof(long),
@@ -86,7 +86,7 @@ static abi_ulong G_GNUC_UNUSED scale_to_guest_pages(uint64_t pages)
 
 #ifdef TARGET_ABI32
 /* Used only for TARGET_ABI32 */
-static abi_long G_GNUC_UNUSED h2g_long_sat(long l)
+static abi_long h2g_long_sat(long l)
 {
     if (l > INT32_MAX) {
         l = INT32_MAX;
@@ -96,7 +96,7 @@ static abi_long G_GNUC_UNUSED h2g_long_sat(long l)
     return l;
 }
 
-static abi_ulong G_GNUC_UNUSED h2g_ulong_sat(u_long ul)
+static abi_ulong h2g_ulong_sat(u_long ul)
 {
     return MIN(ul, UINT32_MAX);
 }
@@ -139,6 +139,98 @@ static int G_GNUC_UNUSED oidfmt(int *oid, int len, char *fmt, uint32_t *kind)
     return 0;
 }
 
+/*
+ * Convert the old value from host to guest.
+ *
+ * For LONG and ULONG on ABI32, we need to 'down convert' the 8 byte quantities
+ * to 4 bytes. The caller setup a buffer in host memory to get this data from
+ * the kernel and pass it to us. We do the down conversion and adjust the length
+ * so the caller knows what to write as the returned length into the target when
+ * it copies the down converted values into the target.
+ *
+ * For normal integral types, we just need to byte swap. No size changes.
+ *
+ * For strings and node data, there's no conversion needed.
+ *
+ * For opaque data, per sysctl OID converts take care of it.
+ */
+static void G_GNUC_UNUSED h2g_old_sysctl(void *holdp, size_t *holdlen, uint32_t kind)
+{
+    size_t len;
+    int hlen, glen;
+    uint8_t *hp, *gp;
+
+    /*
+     * Although rare, we can have arrays of sysctl. Both sysctl_old_ddb in
+     * kern_sysctl.c and show_var in sbin/sysctl/sysctl.c have code that loops
+     * this way.  *holdlen has been set by the kernel to the host's length.
+     * Only LONG and ULONG on ABI32 have different sizes: see below.
+     */
+    gp = hp = (uint8_t *)holdp;
+    len = 0;
+    hlen = host_ctl_size[kind & CTLTYPE];
+    glen = guest_ctl_size[kind & CTLTYPE];
+
+    /*
+     * hlen == 0 for CTLTYPE_STRING and CTLTYPE_NODE, which need no conversion
+     * as well as CTLTYPE_OPAQUE, which needs special converters.
+     */
+    if (hlen == 0) {
+        return;
+    }
+
+    while (len < *holdlen) {
+        if (hlen == glen) {
+            switch (hlen) {
+            case 1:
+                /* Nothing needed: no byteswapping and assigning in place */
+                break;
+            case 2:
+                *(uint16_t *)gp = tswap16(*(uint16_t *)hp);
+                break;
+            case 4:
+                *(uint32_t *)gp = tswap32(*(uint32_t *)hp);
+                break;
+            case 8:
+                *(uint64_t *)gp = tswap64(*(uint64_t *)hp);
+                break;
+            default:
+                g_assert_not_reached();
+            }
+        }
+        else {
+#ifdef TARGET_ABI32
+            /*
+             * Saturating assignment for the only two types that differ between
+             * 32-bit and 64-bit machines. All other integral types have the
+             * same, fixed size and will be converted w/o loss of precision
+             * in the above switch.
+             */
+            switch (kind & CTLTYPE) {
+            case CTLTYPE_LONG:
+                *(abi_long *)gp = tswap32(h2g_long_sat(*(long *)hp));
+                break;
+            case CTLTYPE_ULONG:
+                *(abi_ulong *)gp = tswap32(h2g_ulong_sat(*(u_long *)hp));
+                break;
+            default:
+                g_assert_not_reached();
+            }
+#else
+            g_assert_not_reached();
+#endif
+        }
+        gp += glen;
+        hp += hlen;
+        len += hlen;
+    }
+#ifdef TARGET_ABI32
+    if (hlen != glen) {
+        *holdlen = (*holdlen / hlen) * glen;
+    }
+#endif
+}
+
 /* sysarch() is architecture dependent. */
 abi_long do_freebsd_sysarch(void *cpu_env, abi_long arg1, abi_long arg2)
 {
-- 
2.39.1



  parent reply	other threads:[~2023-02-16 23:35 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-02-16 23:33 [PATCH v3 00/11] 2023 Q1 bsd-user upstreaming: bugfixes and sysctl Warner Losh
2023-02-16 23:33 ` [PATCH v3 01/11] bsd-user: Don't truncate the return value from freebsd_syscall Warner Losh
2023-02-16 23:33 ` [PATCH v3 02/11] build: Don't specify -no-pie for --static user-mode programs Warner Losh
2023-02-17  0:38   ` Alex Bennée
2023-02-16 23:33 ` [PATCH v3 03/11] bsd-user: Add sysarch syscall Warner Losh
2023-02-16 23:33 ` [PATCH v3 04/11] bsd-user: various helper routines for sysctl Warner Losh
2023-02-17 17:38   ` Richard Henderson
2023-02-16 23:33 ` [PATCH v3 05/11] bsd-user: Helper routines oidfmt Warner Losh
2023-02-16 23:33 ` Warner Losh [this message]
2023-02-17 17:41   ` [PATCH v3 06/11] bsd-user: Helper routines h2g_old_sysctl Richard Henderson
2023-02-16 23:33 ` [PATCH v3 07/11] bsd-user: sysctl helper funtions: sysctl_name2oid and sysctl_oidfmt Warner Losh
2023-02-16 23:33 ` [PATCH v3 08/11] bsd-user: common routine do_freebsd_sysctl_oid for all sysctl variants Warner Losh
2023-02-16 23:33 ` [PATCH v3 09/11] bsd-user: Start translation of arch-specific sysctls Warner Losh
2023-02-16 23:33 ` [PATCH v3 10/11] bsd-user: do_freebsd_sysctl helper for sysctl(2) Warner Losh
2023-02-16 23:33 ` [PATCH v3 11/11] bsd-user: implement sysctlbyname(2) Warner Losh

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230216233353.13944-7-imp@bsdimp.com \
    --to=imp@bsdimp.com \
    --cc=alex.bennee@linaro.org \
    --cc=f4bug@amsat.org \
    --cc=kevans@freebsd.org \
    --cc=nox@jelal.kn-bremen.de \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=rakuco@FreeBSD.org \
    --cc=richard.henderson@linaro.org \
    --cc=sbruno@FreeBSD.org \
    --cc=sson@FreeBSD.org \
    --cc=thuth@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.