int sclp_chp_deconfigure(struct chp_id chpid);
 int sclp_chp_read_info(struct sclp_chp_info *info);
 void sclp_get_ipl_info(struct sclp_ipl_info *info);
+bool sclp_has_linemode(void);
+bool sclp_has_vt220(void);
 
 #endif /* _ASM_S390_SCLP_H */
 
 #include <asm/kvm_virtio.h>
 #include <asm/diag.h>
 #include <asm/os_info.h>
+#include <asm/sclp.h>
 #include "entry.h"
 
 long psw_kernel_bits   = PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_ASC_PRIMARY |
 
 static void __init set_preferred_console(void)
 {
-       if (MACHINE_IS_KVM)
-               add_preferred_console("hvc", 0, NULL);
-       else if (CONSOLE_IS_3215 || CONSOLE_IS_SCLP)
+       if (MACHINE_IS_KVM) {
+               if (sclp_has_vt220())
+                       add_preferred_console("ttyS", 1, NULL);
+               else if (sclp_has_linemode())
+                       add_preferred_console("ttyS", 0, NULL);
+               else
+                       add_preferred_console("hvc", 0, NULL);
+       } else if (CONSOLE_IS_3215 || CONSOLE_IS_SCLP)
                add_preferred_console("ttyS", 0, NULL);
        else if (CONSOLE_IS_3270)
                add_preferred_console("tty3270", 0, NULL);
 
 
 EXPORT_SYMBOL(sclp_remove_processed);
 
-struct init_sccb {
-       struct sccb_header header;
-       u16 _reserved;
-       u16 mask_length;
-       sccb_mask_t receive_mask;
-       sccb_mask_t send_mask;
-       sccb_mask_t sclp_receive_mask;
-       sccb_mask_t sclp_send_mask;
-} __attribute__((packed));
-
 /* Prepare init mask request. Called while sclp_lock is locked. */
 static inline void
 __sclp_make_init_req(u32 receive_mask, u32 send_mask)
 
        u16     response_code;
 } __attribute__((packed));
 
+struct init_sccb {
+       struct sccb_header header;
+       u16 _reserved;
+       u16 mask_length;
+       sccb_mask_t receive_mask;
+       sccb_mask_t send_mask;
+       sccb_mask_t sclp_receive_mask;
+       sccb_mask_t sclp_send_mask;
+} __attribute__((packed));
+
 extern u64 sclp_facilities;
 #define SCLP_HAS_CHP_INFO      (sclp_facilities & 0x8000000000000000ULL)
 #define SCLP_HAS_CHP_RECONFIG  (sclp_facilities & 0x2000000000000000ULL)
 
        u8      _reserved5[4096 - 112]; /* 112-4095 */
 } __attribute__((packed, aligned(PAGE_SIZE)));
 
+static struct init_sccb __initdata early_event_mask_sccb __aligned(PAGE_SIZE);
 static struct read_info_sccb __initdata early_read_info_sccb;
 static int __initdata early_read_info_sccb_valid;
 
        }
 }
 
+static void __init sclp_event_mask_early(void)
+{
+       struct init_sccb *sccb = &early_event_mask_sccb;
+       int rc;
+
+       do {
+               memset(sccb, 0, sizeof(*sccb));
+               sccb->header.length = sizeof(*sccb);
+               sccb->mask_length = sizeof(sccb_mask_t);
+               rc = sclp_cmd_sync_early(SCLP_CMDW_WRITE_EVENT_MASK, sccb);
+       } while (rc == -EBUSY);
+}
+
 void __init sclp_facilities_detect(void)
 {
        struct read_info_sccb *sccb;
        rnmax = sccb->rnmax ? sccb->rnmax : sccb->rnmax2;
        rzm = sccb->rnsize ? sccb->rnsize : sccb->rnsize2;
        rzm <<= 20;
+
+       sclp_event_mask_early();
+}
+
+bool __init sclp_has_linemode(void)
+{
+       struct init_sccb *sccb = &early_event_mask_sccb;
+
+       if (sccb->header.response_code != 0x20)
+               return 0;
+       if (sccb->sclp_send_mask & (EVTYP_MSG_MASK | EVTYP_PMSGCMD_MASK))
+               return 1;
+       return 0;
+}
+
+bool __init sclp_has_vt220(void)
+{
+       struct init_sccb *sccb = &early_event_mask_sccb;
+
+       if (sccb->header.response_code != 0x20)
+               return 0;
+       if (sccb->sclp_send_mask & EVTYP_VT220MSG_MASK)
+               return 1;
+       return 0;
 }
 
 unsigned long long sclp_get_rnmax(void)
 
 #include <asm/io.h>
 #include <asm/kvm_para.h>
 #include <asm/kvm_virtio.h>
+#include <asm/sclp.h>
 #include <asm/setup.h>
 #include <asm/irq.h>
 
 
 static int __init s390_virtio_console_init(void)
 {
-       if (!MACHINE_IS_KVM)
+       if (sclp_has_vt220() || sclp_has_linemode())
                return -ENODEV;
        return virtio_cons_early_init(early_put_chars);
 }