[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v3 06/11] bsd-user: Helper routines h2g_old_sysctl
From: |
Warner Losh |
Subject: |
[PATCH v3 06/11] bsd-user: Helper routines h2g_old_sysctl |
Date: |
Thu, 16 Feb 2023 16:33:48 -0700 |
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
- [PATCH v3 00/11] 2023 Q1 bsd-user upstreaming: bugfixes and sysctl, Warner Losh, 2023/02/16
- [PATCH v3 01/11] bsd-user: Don't truncate the return value from freebsd_syscall, Warner Losh, 2023/02/16
- [PATCH v3 03/11] bsd-user: Add sysarch syscall, Warner Losh, 2023/02/16
- [PATCH v3 05/11] bsd-user: Helper routines oidfmt, Warner Losh, 2023/02/16
- [PATCH v3 06/11] bsd-user: Helper routines h2g_old_sysctl,
Warner Losh <=
- [PATCH v3 07/11] bsd-user: sysctl helper funtions: sysctl_name2oid and sysctl_oidfmt, Warner Losh, 2023/02/16
- [PATCH v3 02/11] build: Don't specify -no-pie for --static user-mode programs, Warner Losh, 2023/02/16
- [PATCH v3 09/11] bsd-user: Start translation of arch-specific sysctls, Warner Losh, 2023/02/16
- [PATCH v3 08/11] bsd-user: common routine do_freebsd_sysctl_oid for all sysctl variants, Warner Losh, 2023/02/16
- [PATCH v3 04/11] bsd-user: various helper routines for sysctl, Warner Losh, 2023/02/16
- [PATCH v3 10/11] bsd-user: do_freebsd_sysctl helper for sysctl(2), Warner Losh, 2023/02/16
- [PATCH v3 11/11] bsd-user: implement sysctlbyname(2), Warner Losh, 2023/02/16