summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--hw/char/sclpconsole-lm.c12
-rw-r--r--hw/char/sclpconsole.c12
-rw-r--r--target-s390x/kvm.c10
3 files changed, 24 insertions, 10 deletions
diff --git a/hw/char/sclpconsole-lm.c b/hw/char/sclpconsole-lm.c
index 80dd0a9e13..a9f5e62f24 100644
--- a/hw/char/sclpconsole-lm.c
+++ b/hw/char/sclpconsole-lm.c
@@ -52,7 +52,8 @@ typedef struct SCLPConsoleLM {
  * event_pending is set when a newline character is encountered
  *
  * The maximum command line length is limited by the maximum
- * space available in an SCCB
+ * space available in an SCCB. Line mode console input is sent
+ * truncated to the guest in case it doesn't fit into the SCCB.
  */
 
 static int chr_can_read(void *opaque)
@@ -61,10 +62,8 @@ static int chr_can_read(void *opaque)
 
     if (scon->event.event_pending) {
         return 0;
-    } else if (SIZE_CONSOLE_BUFFER - scon->length) {
-        return 1;
     }
-    return 0;
+    return 1;
 }
 
 static void chr_read(void *opaque, const uint8_t *buf, int size)
@@ -78,6 +77,10 @@ static void chr_read(void *opaque, const uint8_t *buf, int size)
         sclp_service_interrupt(0);
         return;
     }
+    if (scon->length == SIZE_CONSOLE_BUFFER) {
+        /* Eat the character, but still process CR and LF.  */
+        return;
+    }
     scon->buf[scon->length] = *buf;
     scon->length += 1;
     if (scon->echo) {
@@ -125,6 +128,7 @@ static int get_console_data(SCLPEvent *event, uint8_t *buf, size_t *size,
     cons->length = 0;
     /* data provided and no more data pending */
     event->event_pending = false;
+    qemu_notify_event();
     return 0;
 }
 
diff --git a/hw/char/sclpconsole.c b/hw/char/sclpconsole.c
index fca105db4e..79891dfc58 100644
--- a/hw/char/sclpconsole.c
+++ b/hw/char/sclpconsole.c
@@ -36,6 +36,7 @@ typedef struct SCLPConsole {
     uint32_t iov_bs;        /* offset in buf for char layer read operation */
     uint32_t iov_data_len;  /* length of byte stream in buffer             */
     uint32_t iov_sclp_rest; /* length of byte stream not read via SCLP     */
+    bool notify;            /* qemu_notify_event() req'd if true           */
 } SCLPConsole;
 
 /* character layer call-back functions */
@@ -44,8 +45,12 @@ typedef struct SCLPConsole {
 static int chr_can_read(void *opaque)
 {
     SCLPConsole *scon = opaque;
+    int avail = SIZE_BUFFER_VT220 - scon->iov_data_len;
 
-    return SIZE_BUFFER_VT220 - scon->iov_data_len;
+    if (avail == 0) {
+        scon->notify = true;
+    }
+    return avail;
 }
 
 /* Send data from a char device over to the guest */
@@ -113,6 +118,10 @@ static void get_console_data(SCLPEvent *event, uint8_t *buf, size_t *size,
         cons->iov_sclp += avail;
         /* more data pending */
     }
+    if (cons->notify) {
+        cons->notify = false;
+        qemu_notify_event();
+    }
 }
 
 static int read_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr,
@@ -229,6 +238,7 @@ static void console_reset(DeviceState *dev)
    scon->iov_bs = 0;
    scon->iov_data_len = 0;
    scon->iov_sclp_rest = 0;
+   scon->notify = false;
 }
 
 static int console_exit(SCLPEvent *event)
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index 5b10a255ed..d247471119 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -827,18 +827,18 @@ static int handle_b9(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1)
     return r;
 }
 
-static int handle_eb(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1)
+static int handle_eb(S390CPU *cpu, struct kvm_run *run, uint8_t ipbl)
 {
     int r = 0;
 
-    switch (ipa1) {
+    switch (ipbl) {
     case PRIV_EB_SQBS:
         /* just inject exception */
         r = -1;
         break;
     default:
         r = -1;
-        DPRINTF("KVM: unhandled PRIV: 0xeb%x\n", ipa1);
+        DPRINTF("KVM: unhandled PRIV: 0xeb%x\n", ipbl);
         break;
     }
 
@@ -1039,7 +1039,7 @@ static int handle_instruction(S390CPU *cpu, struct kvm_run *run)
         r = handle_b9(cpu, run, ipa1);
         break;
     case IPA0_EB:
-        r = handle_eb(cpu, run, ipa1);
+        r = handle_eb(cpu, run, run->s390_sieic.ipb & 0xff);
         break;
     case IPA0_DIAG:
         r = handle_diag(cpu, run, run->s390_sieic.ipb);
@@ -1272,7 +1272,7 @@ void kvm_s390_crw_mchk(void)
     struct kvm_s390_irq irq = {
         .type = KVM_S390_MCHK,
         .u.mchk.cr14 = 1 << 28,
-        .u.mchk.mcic = 0x00400f1d40330000,
+        .u.mchk.mcic = 0x00400f1d40330000ULL,
     };
     kvm_s390_floating_interrupt(&irq);
 }