Message ID | 20210704170736.617895-4-f4bug@amsat.org |
---|---|
State | New |
Headers | show |
Series | target/mips: Rewrite UHI errno_mips() to allow building on Haiku OS | expand |
On Sun, 4 Jul 2021 at 18:07, Philippe Mathieu-Daudé <f4bug@amsat.org> wrote: > > Linking on Haiku OS fails: > > /boot/system/develop/tools/bin/../lib/gcc/x86_64-unknown-haiku/8.3.0/../../../../x86_64-unknown-haiku/bin/ld: > error: libqemu-mips-softmmu.fa.p/target_mips_tcg_sysemu_mips-semi.c.o(.rodata) is too large (0xffff405a bytes) > /boot/system/develop/tools/bin/../lib/gcc/x86_64-unknown-haiku/8.3.0/../../../../x86_64-unknown-haiku/bin/ld: > final link failed: memory exhausted > collect2: error: ld returned 1 exit status > > This is because the host_to_mips_errno[] uses errno as index, > for example: > > static const uint16_t host_to_mips_errno[] = { > [ENAMETOOLONG] = 91, > ... > > and Haiku defines [*] ENAMETOOLONG as: > > 12 /* Error baselines */ > 13 #define B_GENERAL_ERROR_BASE INT_MIN > .. > 22 #define B_STORAGE_ERROR_BASE (B_GENERAL_ERROR_BASE + 0x6000) > ... > 106 #define B_NAME_TOO_LONG (B_STORAGE_ERROR_BASE + 4) > ... > 211 #define ENAMETOOLONG B_TO_POSIX_ERROR(B_NAME_TOO_LONG) > > so the array ends up beeing indeed too big. > > Since POSIX errno can't be use as indexes on Haiku, > rewrite errno_mips() using a GHashTable. > > [*] https://github.com/haiku/haiku/blob/r1beta3/headers/os/support/Errors.h#L130 > > Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org> > --- > target/mips/tcg/sysemu/mips-semi.c | 62 ++++++++++++++++++++++-------- > 1 file changed, 45 insertions(+), 17 deletions(-) > static int errno_mips(int host_errno) > { > - if (host_errno < 0 || host_errno >= ARRAY_SIZE(host_to_mips_errno)) { > - return EINVAL; > - } else if (host_to_mips_errno[host_errno]) { > - return host_to_mips_errno[host_errno]; > - } else { > - return host_errno; > + gpointer uhi_errno; > + > + if (uhi_errno_hash_table == NULL) { > + uhi_errno_init(); > } > + > + if (host_errno == 0) { > + return 0; > + } > + if (g_hash_table_lookup_extended(uhi_errno_hash_table, > + GINT_TO_POINTER(host_errno), > + NULL, &uhi_errno)) { > + return GPOINTER_TO_INT(uhi_errno); > + } > + return EINVAL; /* Not reachable per the specification */ Per whose specification? This function is passed the errno as set by various host OS functions like open(), lseek(), read(). POSIX allows those functions to set errno to any value, so this "we don't know a guest errno value for that" code is definitely reachable. thanks -- PMM
On 7/4/21 7:25 PM, Peter Maydell wrote: > On Sun, 4 Jul 2021 at 18:07, Philippe Mathieu-Daudé <f4bug@amsat.org> wrote: >> >> Linking on Haiku OS fails: >> >> /boot/system/develop/tools/bin/../lib/gcc/x86_64-unknown-haiku/8.3.0/../../../../x86_64-unknown-haiku/bin/ld: >> error: libqemu-mips-softmmu.fa.p/target_mips_tcg_sysemu_mips-semi.c.o(.rodata) is too large (0xffff405a bytes) >> /boot/system/develop/tools/bin/../lib/gcc/x86_64-unknown-haiku/8.3.0/../../../../x86_64-unknown-haiku/bin/ld: >> final link failed: memory exhausted >> collect2: error: ld returned 1 exit status >> >> This is because the host_to_mips_errno[] uses errno as index, >> for example: >> >> static const uint16_t host_to_mips_errno[] = { >> [ENAMETOOLONG] = 91, >> ... >> >> and Haiku defines [*] ENAMETOOLONG as: >> >> 12 /* Error baselines */ >> 13 #define B_GENERAL_ERROR_BASE INT_MIN >> .. >> 22 #define B_STORAGE_ERROR_BASE (B_GENERAL_ERROR_BASE + 0x6000) >> ... >> 106 #define B_NAME_TOO_LONG (B_STORAGE_ERROR_BASE + 4) >> ... >> 211 #define ENAMETOOLONG B_TO_POSIX_ERROR(B_NAME_TOO_LONG) >> >> so the array ends up beeing indeed too big. >> >> Since POSIX errno can't be use as indexes on Haiku, >> rewrite errno_mips() using a GHashTable. >> >> [*] https://github.com/haiku/haiku/blob/r1beta3/headers/os/support/Errors.h#L130 >> >> Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org> >> --- >> target/mips/tcg/sysemu/mips-semi.c | 62 ++++++++++++++++++++++-------- >> 1 file changed, 45 insertions(+), 17 deletions(-) > >> static int errno_mips(int host_errno) >> { >> - if (host_errno < 0 || host_errno >= ARRAY_SIZE(host_to_mips_errno)) { >> - return EINVAL; >> - } else if (host_to_mips_errno[host_errno]) { >> - return host_to_mips_errno[host_errno]; >> - } else { >> - return host_errno; >> + gpointer uhi_errno; >> + >> + if (uhi_errno_hash_table == NULL) { >> + uhi_errno_init(); >> } >> + >> + if (host_errno == 0) { >> + return 0; >> + } >> + if (g_hash_table_lookup_extended(uhi_errno_hash_table, >> + GINT_TO_POINTER(host_errno), >> + NULL, &uhi_errno)) { >> + return GPOINTER_TO_INT(uhi_errno); >> + } >> + return EINVAL; /* Not reachable per the specification */ > > Per whose specification? This function is passed the errno as set > by various host OS functions like open(), lseek(), read(). POSIX allows > those functions to set errno to any value, so this "we don't know > a guest errno value for that" code is definitely reachable. You are right, it is reachable. What I meant is other errnos are not expected, and returning EINVAL for them doesn't seem ideal, but the spec doesn't define a particular errno for unsupported errnos. I'll reword as "Unsupported errno is not specified, use EINVAL".
On 04/07/2021 19.07, Philippe Mathieu-Daudé wrote: > Linking on Haiku OS fails: > > /boot/system/develop/tools/bin/../lib/gcc/x86_64-unknown-haiku/8.3.0/../../../../x86_64-unknown-haiku/bin/ld: > error: libqemu-mips-softmmu.fa.p/target_mips_tcg_sysemu_mips-semi.c.o(.rodata) is too large (0xffff405a bytes) > /boot/system/develop/tools/bin/../lib/gcc/x86_64-unknown-haiku/8.3.0/../../../../x86_64-unknown-haiku/bin/ld: > final link failed: memory exhausted > collect2: error: ld returned 1 exit status > > This is because the host_to_mips_errno[] uses errno as index, > for example: > > static const uint16_t host_to_mips_errno[] = { > [ENAMETOOLONG] = 91, > ... > > and Haiku defines [*] ENAMETOOLONG as: > > 12 /* Error baselines */ > 13 #define B_GENERAL_ERROR_BASE INT_MIN > .. > 22 #define B_STORAGE_ERROR_BASE (B_GENERAL_ERROR_BASE + 0x6000) > ... > 106 #define B_NAME_TOO_LONG (B_STORAGE_ERROR_BASE + 4) > ... > 211 #define ENAMETOOLONG B_TO_POSIX_ERROR(B_NAME_TOO_LONG) > > so the array ends up beeing indeed too big. > > Since POSIX errno can't be use as indexes on Haiku, > rewrite errno_mips() using a GHashTable. > > [*] https://github.com/haiku/haiku/blob/r1beta3/headers/os/support/Errors.h#L130 > > Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org> > --- > target/mips/tcg/sysemu/mips-semi.c | 62 ++++++++++++++++++++++-------- > 1 file changed, 45 insertions(+), 17 deletions(-) > > diff --git a/target/mips/tcg/sysemu/mips-semi.c b/target/mips/tcg/sysemu/mips-semi.c > index 4c924273c1b..3e91c9eb76c 100644 > --- a/target/mips/tcg/sysemu/mips-semi.c > +++ b/target/mips/tcg/sysemu/mips-semi.c > @@ -4,6 +4,7 @@ > * Specifications: MD01069 Reference Manual (rev 1.1.6, 06 Jul 2015) > * > * Copyright (c) 2015 Imagination Technologies > + * Copyright (c) 2021 Philippe Mathieu-Daudé > * > * This library is free software; you can redistribute it and/or > * modify it under the terms of the GNU Lesser General Public > @@ -76,29 +77,56 @@ enum UHIOpenFlags { > UHIOpen_EXCL = 0x800 > }; > > -/* > - * Unified Hosting Interface (rev 1.1.6) > - * Appendix A. "Error values" > - */ > -static const uint16_t host_to_mips_errno[] = { > - [ENAMETOOLONG] = 91, > -#ifdef EOVERFLOW > - [EOVERFLOW] = 139, > -#endif > +static GHashTable *uhi_errno_hash_table; > + > +static void uhi_errno_insert(int host_errno, int uhi_errno) > +{ > + gboolean ret = TRUE; > + > + assert(uhi_errno_hash_table != NULL); > + ret = g_hash_table_insert(uhi_errno_hash_table, > + GINT_TO_POINTER(host_errno), > + GINT_TO_POINTER(uhi_errno)); > + assert(ret == TRUE); > +} > + > +static void uhi_errno_init(void) > +{ > + gboolean ret = TRUE; > + > + uhi_errno_hash_table = g_hash_table_new(NULL, NULL); > + > + /* > + * Unified Hosting Interface (rev 1.1.6) > + * Appendix A. "Error values" > + */ > + uhi_errno_insert(ENAMETOOLONG, 91); > #ifdef ELOOP > - [ELOOP] = 92, > + uhi_errno_insert(ELOOP, 92); > #endif > -}; > +#ifdef EOVERFLOW > + uhi_errno_insert(EOVERFLOW, 139); > +#endif > + assert(ret == TRUE); > +} > > static int errno_mips(int host_errno) > { > - if (host_errno < 0 || host_errno >= ARRAY_SIZE(host_to_mips_errno)) { > - return EINVAL; > - } else if (host_to_mips_errno[host_errno]) { > - return host_to_mips_errno[host_errno]; > - } else { > - return host_errno; > + gpointer uhi_errno; > + > + if (uhi_errno_hash_table == NULL) { > + uhi_errno_init(); > } > + > + if (host_errno == 0) { > + return 0; > + } > + if (g_hash_table_lookup_extended(uhi_errno_hash_table, > + GINT_TO_POINTER(host_errno), > + NULL, &uhi_errno)) { > + return GPOINTER_TO_INT(uhi_errno); > + } > + return EINVAL; /* Not reachable per the specification */ > } Why not simply use a switch-case statement instead? ... that's simpler and still allows to compiler to optimize if the errno values are in a compact range. Thomas
On 7/4/21 8:38 PM, Thomas Huth wrote: > On 04/07/2021 19.07, Philippe Mathieu-Daudé wrote: >> Linking on Haiku OS fails: >> >> >> /boot/system/develop/tools/bin/../lib/gcc/x86_64-unknown-haiku/8.3.0/../../../../x86_64-unknown-haiku/bin/ld: >> >> error: >> libqemu-mips-softmmu.fa.p/target_mips_tcg_sysemu_mips-semi.c.o(.rodata) is >> too large (0xffff405a bytes) >> >> /boot/system/develop/tools/bin/../lib/gcc/x86_64-unknown-haiku/8.3.0/../../../../x86_64-unknown-haiku/bin/ld: >> >> final link failed: memory exhausted >> collect2: error: ld returned 1 exit status >> >> This is because the host_to_mips_errno[] uses errno as index, >> for example: >> >> static const uint16_t host_to_mips_errno[] = { >> [ENAMETOOLONG] = 91, >> ... >> >> and Haiku defines [*] ENAMETOOLONG as: >> >> 12 /* Error baselines */ >> 13 #define B_GENERAL_ERROR_BASE INT_MIN >> .. >> 22 #define B_STORAGE_ERROR_BASE (B_GENERAL_ERROR_BASE >> + 0x6000) >> ... >> 106 #define B_NAME_TOO_LONG (B_STORAGE_ERROR_BASE >> + 4) >> ... >> 211 #define ENAMETOOLONG >> B_TO_POSIX_ERROR(B_NAME_TOO_LONG) >> >> so the array ends up beeing indeed too big. >> >> Since POSIX errno can't be use as indexes on Haiku, >> rewrite errno_mips() using a GHashTable. >> >> [*] >> https://github.com/haiku/haiku/blob/r1beta3/headers/os/support/Errors.h#L130 >> >> >> Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org> >> --- >> target/mips/tcg/sysemu/mips-semi.c | 62 ++++++++++++++++++++++-------- >> 1 file changed, 45 insertions(+), 17 deletions(-) >> +static void uhi_errno_init(void) >> +{ >> + gboolean ret = TRUE; >> + >> + uhi_errno_hash_table = g_hash_table_new(NULL, NULL); >> + >> + /* >> + * Unified Hosting Interface (rev 1.1.6) >> + * Appendix A. "Error values" >> + */ >> + uhi_errno_insert(ENAMETOOLONG, 91); >> #ifdef ELOOP >> - [ELOOP] = 92, >> + uhi_errno_insert(ELOOP, 92); >> #endif >> -}; >> +#ifdef EOVERFLOW >> + uhi_errno_insert(EOVERFLOW, 139); >> +#endif >> + assert(ret == TRUE); >> +} >> static int errno_mips(int host_errno) >> { >> - if (host_errno < 0 || host_errno >= >> ARRAY_SIZE(host_to_mips_errno)) { >> - return EINVAL; >> - } else if (host_to_mips_errno[host_errno]) { >> - return host_to_mips_errno[host_errno]; >> - } else { >> - return host_errno; >> + gpointer uhi_errno; >> + >> + if (uhi_errno_hash_table == NULL) { >> + uhi_errno_init(); >> } >> + >> + if (host_errno == 0) { >> + return 0; >> + } >> + if (g_hash_table_lookup_extended(uhi_errno_hash_table, >> + GINT_TO_POINTER(host_errno), >> + NULL, &uhi_errno)) { >> + return GPOINTER_TO_INT(uhi_errno); >> + } >> + return EINVAL; /* Not reachable per the specification */ >> } > > Why not simply use a switch-case statement instead? ... that's simpler > and still allows to compiler to optimize if the errno values are in a > compact range. I was expecting the #ifdef'ry to be ugly, but there isn't that many actually. Sigh :(
diff --git a/target/mips/tcg/sysemu/mips-semi.c b/target/mips/tcg/sysemu/mips-semi.c index 4c924273c1b..3e91c9eb76c 100644 --- a/target/mips/tcg/sysemu/mips-semi.c +++ b/target/mips/tcg/sysemu/mips-semi.c @@ -4,6 +4,7 @@ * Specifications: MD01069 Reference Manual (rev 1.1.6, 06 Jul 2015) * * Copyright (c) 2015 Imagination Technologies + * Copyright (c) 2021 Philippe Mathieu-Daudé * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -76,29 +77,56 @@ enum UHIOpenFlags { UHIOpen_EXCL = 0x800 }; -/* - * Unified Hosting Interface (rev 1.1.6) - * Appendix A. "Error values" - */ -static const uint16_t host_to_mips_errno[] = { - [ENAMETOOLONG] = 91, -#ifdef EOVERFLOW - [EOVERFLOW] = 139, -#endif +static GHashTable *uhi_errno_hash_table; + +static void uhi_errno_insert(int host_errno, int uhi_errno) +{ + gboolean ret = TRUE; + + assert(uhi_errno_hash_table != NULL); + ret = g_hash_table_insert(uhi_errno_hash_table, + GINT_TO_POINTER(host_errno), + GINT_TO_POINTER(uhi_errno)); + assert(ret == TRUE); +} + +static void uhi_errno_init(void) +{ + gboolean ret = TRUE; + + uhi_errno_hash_table = g_hash_table_new(NULL, NULL); + + /* + * Unified Hosting Interface (rev 1.1.6) + * Appendix A. "Error values" + */ + uhi_errno_insert(ENAMETOOLONG, 91); #ifdef ELOOP - [ELOOP] = 92, + uhi_errno_insert(ELOOP, 92); #endif -}; +#ifdef EOVERFLOW + uhi_errno_insert(EOVERFLOW, 139); +#endif + assert(ret == TRUE); +} static int errno_mips(int host_errno) { - if (host_errno < 0 || host_errno >= ARRAY_SIZE(host_to_mips_errno)) { - return EINVAL; - } else if (host_to_mips_errno[host_errno]) { - return host_to_mips_errno[host_errno]; - } else { - return host_errno; + gpointer uhi_errno; + + if (uhi_errno_hash_table == NULL) { + uhi_errno_init(); } + + if (host_errno == 0) { + return 0; + } + if (g_hash_table_lookup_extended(uhi_errno_hash_table, + GINT_TO_POINTER(host_errno), + NULL, &uhi_errno)) { + return GPOINTER_TO_INT(uhi_errno); + } + return EINVAL; /* Not reachable per the specification */ } static int copy_stat_to_target(CPUMIPSState *env, const struct stat *src,
Linking on Haiku OS fails: /boot/system/develop/tools/bin/../lib/gcc/x86_64-unknown-haiku/8.3.0/../../../../x86_64-unknown-haiku/bin/ld: error: libqemu-mips-softmmu.fa.p/target_mips_tcg_sysemu_mips-semi.c.o(.rodata) is too large (0xffff405a bytes) /boot/system/develop/tools/bin/../lib/gcc/x86_64-unknown-haiku/8.3.0/../../../../x86_64-unknown-haiku/bin/ld: final link failed: memory exhausted collect2: error: ld returned 1 exit status This is because the host_to_mips_errno[] uses errno as index, for example: static const uint16_t host_to_mips_errno[] = { [ENAMETOOLONG] = 91, ... and Haiku defines [*] ENAMETOOLONG as: 12 /* Error baselines */ 13 #define B_GENERAL_ERROR_BASE INT_MIN .. 22 #define B_STORAGE_ERROR_BASE (B_GENERAL_ERROR_BASE + 0x6000) ... 106 #define B_NAME_TOO_LONG (B_STORAGE_ERROR_BASE + 4) ... 211 #define ENAMETOOLONG B_TO_POSIX_ERROR(B_NAME_TOO_LONG) so the array ends up beeing indeed too big. Since POSIX errno can't be use as indexes on Haiku, rewrite errno_mips() using a GHashTable. [*] https://github.com/haiku/haiku/blob/r1beta3/headers/os/support/Errors.h#L130 Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org> --- target/mips/tcg/sysemu/mips-semi.c | 62 ++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 17 deletions(-)