diff mbox series

[02/13] target/hppa: Add "diag 0x101" for console output support

Message ID 20240207182023.36316-3-deller@kernel.org
State New
Headers show
Series target/hppa: Enhancements and fixes | expand

Commit Message

Helge Deller Feb. 7, 2024, 6:20 p.m. UTC
From: Helge Deller <deller@gmx.de>

For debugging purposes at the early stage of the bootup process,
the SeaBIOS-hppa firmware sometimes needs to output characters to the
serial console. Note that the serial console is the default output
method for parisc machines.

At this stage PCI busses and other devices haven't been initialized
yet. So, SeaBIOS-hppa will not be able to find the correct I/O ports
for the serial ports yet.

Instead, add an emulation for the "diag 0x101" opcode to assist here.
Without any other dependencies, SeaBIOS-hppa can then load the character
to be printed in register %r26 and issue the diag assembly instruction.

The qemu diag_console_output() helper function will then print
that character to the first serial port.

Signed-off-by: Helge Deller <deller@gmx.de>
---
 target/hppa/helper.h    |  1 +
 target/hppa/op_helper.c | 32 ++++++++++++++++++++++++++++++++
 target/hppa/translate.c |  6 ++++++
 3 files changed, 39 insertions(+)

Comments

Richard Henderson Feb. 8, 2024, 8:15 p.m. UTC | #1
On 2/7/24 08:20, deller@kernel.org wrote:
> @@ -484,3 +486,33 @@ uint64_t HELPER(hshradd)(uint64_t r1, uint64_t r2, uint32_t sh)
>       }
>       return ret;
>   }
> +
> +/*
> + * diag_console_output() is a helper function used during the initial bootup
> + * process of the SeaBIOS-hppa firmware.  During the bootup phase, addresses of
> + * serial ports on e.g. PCI busses are unknown and most other devices haven't
> + * been initialized and configured yet.  With help of a simple "diag" assembler
> + * instruction and an ASCII character code in register %r26 firmware can easily
> + * print debug output without any dependencies to the first serial port and use
> + * that as serial console.
> + */
> +void HELPER(diag_console_output)(CPUHPPAState *env)
> +{
> +    CharBackend *serial_backend;
> +    Chardev *serial_port;
> +    unsigned char c;
> +
> +    /* find first serial port */
> +    serial_port = serial_hd(0);
> +    if (!serial_port)
> +        return;
> +
> +    /* get serial_backend for the serial port */
> +    serial_backend = serial_port->be;
> +    if (!serial_backend ||
> +        !qemu_chr_fe_backend_connected(serial_backend))
> +        return;
> +
> +    c = (unsigned char)env->gr[26];
> +    qemu_chr_fe_write(serial_backend, &c, sizeof(c));
> +}

Looks like this should go in sys_helper.c instead.
Missing ifdefs break hppa-linux-user?

Also, missing braces.


r~
diff mbox series

Patch

diff --git a/target/hppa/helper.h b/target/hppa/helper.h
index 20698f68ed..1bdbcd8f98 100644
--- a/target/hppa/helper.h
+++ b/target/hppa/helper.h
@@ -103,4 +103,5 @@  DEF_HELPER_FLAGS_1(ptlbe, TCG_CALL_NO_RWG, void, env)
 DEF_HELPER_FLAGS_2(lpa, TCG_CALL_NO_WG, tl, env, tl)
 DEF_HELPER_FLAGS_1(change_prot_id, TCG_CALL_NO_RWG, void, env)
 DEF_HELPER_1(diag_btlb, void, env)
+DEF_HELPER_1(diag_console_output, void, env)
 #endif
diff --git a/target/hppa/op_helper.c b/target/hppa/op_helper.c
index b1f24a5aad..2c2c4aa183 100644
--- a/target/hppa/op_helper.c
+++ b/target/hppa/op_helper.c
@@ -24,6 +24,8 @@ 
 #include "exec/helper-proto.h"
 #include "exec/cpu_ldst.h"
 #include "qemu/timer.h"
+#include "sysemu/sysemu.h"
+#include "chardev/char-fe.h"
 #include "trace.h"
 
 G_NORETURN void HELPER(excp)(CPUHPPAState *env, int excp)
@@ -484,3 +486,33 @@  uint64_t HELPER(hshradd)(uint64_t r1, uint64_t r2, uint32_t sh)
     }
     return ret;
 }
+
+/*
+ * diag_console_output() is a helper function used during the initial bootup
+ * process of the SeaBIOS-hppa firmware.  During the bootup phase, addresses of
+ * serial ports on e.g. PCI busses are unknown and most other devices haven't
+ * been initialized and configured yet.  With help of a simple "diag" assembler
+ * instruction and an ASCII character code in register %r26 firmware can easily
+ * print debug output without any dependencies to the first serial port and use
+ * that as serial console.
+ */
+void HELPER(diag_console_output)(CPUHPPAState *env)
+{
+    CharBackend *serial_backend;
+    Chardev *serial_port;
+    unsigned char c;
+
+    /* find first serial port */
+    serial_port = serial_hd(0);
+    if (!serial_port)
+        return;
+
+    /* get serial_backend for the serial port */
+    serial_backend = serial_port->be;
+    if (!serial_backend ||
+        !qemu_chr_fe_backend_connected(serial_backend))
+        return;
+
+    c = (unsigned char)env->gr[26];
+    qemu_chr_fe_write(serial_backend, &c, sizeof(c));
+}
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 08d09d50d7..53ec57ee86 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -4411,6 +4411,12 @@  static bool trans_diag(DisasContext *ctx, arg_diag *a)
         gen_helper_diag_btlb(tcg_env);
         return nullify_end(ctx);
     }
+    if (a->i == 0x101) {
+        /* print char in %r26 to first serial console, used by SeaBIOS-hppa */
+        nullify_over(ctx);
+        gen_helper_diag_console_output(tcg_env);
+        return nullify_end(ctx);
+    }
 #endif
     qemu_log_mask(LOG_UNIMP, "DIAG opcode 0x%04x ignored\n", a->i);
     return true;