aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrandon Bergren <bdragon@FreeBSD.org>2021-02-25 18:55:58 +0000
committerBrandon Bergren <bdragon@FreeBSD.org>2021-03-08 18:35:56 +0000
commit102e7117bcf32f9bee513f948815213575cfebd4 (patch)
tree5761bd1c5bc8a4cf16871a8d4cb27b0fa5dfcb34
parentcc24f5bc6f6eb56a959bd23ebb051d3bf6ebf670 (diff)
downloadsrc-102e7117bcf32f9bee513f948815213575cfebd4.tar.gz
src-102e7117bcf32f9bee513f948815213575cfebd4.zip
[PowerPC64LE] pseries: Fix input buffering logic.
In uart_phyp_get(), when the internal buffer is empty, we make a hypercall to retrieve up to 16 bytes of input data from the hypervisor. As this is specified to be returned in BE format, we need to do a 64-bit byte swap on the first and second half of the data. If the buffer being passed in was insufficient to return the fetched data, we store the remainder in the internal buffer and use it to satisfy the following calls to uart_phyp_get() until it is drained. However, in this case, we were accidentally byteswapping the internal buffer again. Move the byteswapping code to just after the hypercall so it only gets swapped when we're filling the buffer. Fixes arrow keys in qemu on pseries, among other console oddities. Sponsored by: Tag1 Consulting, Inc. (cherry picked from commit 5001c579baff78719919d79ec054207aa2938dbd)
-rw-r--r--sys/powerpc/pseries/phyp_console.c9
1 files changed, 4 insertions, 5 deletions
diff --git a/sys/powerpc/pseries/phyp_console.c b/sys/powerpc/pseries/phyp_console.c
index 84ab292dae94..484952177d51 100644
--- a/sys/powerpc/pseries/phyp_console.c
+++ b/sys/powerpc/pseries/phyp_console.c
@@ -295,6 +295,10 @@ uart_phyp_get(struct uart_phyp_softc *sc, void *buffer, size_t bufsize)
err = phyp_pft_hcall(H_GET_TERM_CHAR, sc->vtermid,
0, 0, 0, &sc->inbuflen, &sc->phyp_inbuf.u64[0],
&sc->phyp_inbuf.u64[1]);
+#if BYTE_ORDER == LITTLE_ENDIAN
+ sc->phyp_inbuf.u64[0] = be64toh(sc->phyp_inbuf.u64[0]);
+ sc->phyp_inbuf.u64[1] = be64toh(sc->phyp_inbuf.u64[1]);
+#endif
if (err != H_SUCCESS) {
uart_unlock(&sc->sc_mtx);
return (-1);
@@ -307,11 +311,6 @@ uart_phyp_get(struct uart_phyp_softc *sc, void *buffer, size_t bufsize)
return (0);
}
-#if BYTE_ORDER == LITTLE_ENDIAN
- sc->phyp_inbuf.u64[0] = be64toh(sc->phyp_inbuf.u64[0]);
- sc->phyp_inbuf.u64[1] = be64toh(sc->phyp_inbuf.u64[1]);
-#endif
-
if ((sc->protocol == HVTERMPROT) && (hdr == 1)) {
sc->inbuflen = sc->inbuflen - 4;
/* The VTERM protocol has a 4 byte header, skip it here. */