cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

sclp.c (3750B)


      1/*
      2 * SCLP ASCII access driver
      3 *
      4 * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
      5 *
      6 * This work is licensed under the terms of the GNU GPL, version 2 or (at
      7 * your option) any later version. See the COPYING file in the top-level
      8 * directory.
      9 */
     10
     11#include "libc.h"
     12#include "s390-ccw.h"
     13#include "sclp.h"
     14
     15long write(int fd, const void *str, size_t len);
     16
     17static char _sccb[PAGE_SIZE] __attribute__((__aligned__(4096)));
     18
     19const unsigned char ebc2asc[256] =
     20      /* 0123456789abcdef0123456789abcdef */
     21        "................................" /* 1F */
     22        "................................" /* 3F */
     23        " ...........<(+|&.........!$*);." /* 5F first.chr.here.is.real.space */
     24        "-/.........,%_>?.........`:#@'=\""/* 7F */
     25        ".abcdefghi.......jklmnopqr......" /* 9F */
     26        "..stuvwxyz......................" /* BF */
     27        ".ABCDEFGHI.......JKLMNOPQR......" /* DF */
     28        "..STUVWXYZ......0123456789......";/* FF */
     29
     30/* Perform service call. Return 0 on success, non-zero otherwise. */
     31static int sclp_service_call(unsigned int command, void *sccb)
     32{
     33        int cc;
     34
     35        asm volatile(
     36                "       .insn   rre,0xb2200000,%1,%2\n"  /* servc %1,%2 */
     37                "       ipm     %0\n"
     38                "       srl     %0,28"
     39                : "=&d" (cc) : "d" (command), "a" (__pa(sccb))
     40                : "cc", "memory");
     41        consume_sclp_int();
     42        if (cc == 3)
     43                return -EIO;
     44        if (cc == 2)
     45                return -EBUSY;
     46        return 0;
     47}
     48
     49void sclp_set_write_mask(uint32_t receive_mask, uint32_t send_mask)
     50{
     51    WriteEventMask *sccb = (void *)_sccb;
     52
     53    sccb->h.length = sizeof(WriteEventMask);
     54    sccb->mask_length = sizeof(unsigned int);
     55    sccb->cp_receive_mask = receive_mask;
     56    sccb->cp_send_mask = send_mask;
     57
     58    sclp_service_call(SCLP_CMD_WRITE_EVENT_MASK, sccb);
     59}
     60
     61void sclp_setup(void)
     62{
     63    sclp_set_write_mask(0, SCLP_EVENT_MASK_MSG_ASCII);
     64}
     65
     66long write(int fd, const void *str, size_t len)
     67{
     68    WriteEventData *sccb = (void *)_sccb;
     69    const char *p = str;
     70    size_t data_len = 0;
     71    size_t i;
     72
     73    if (fd != 1 && fd != 2) {
     74        return -EIO;
     75    }
     76
     77    for (i = 0; i < len; i++) {
     78        if ((data_len + 1) >= SCCB_DATA_LEN) {
     79            /* We would overflow the sccb buffer, abort early */
     80            len = i;
     81            break;
     82        }
     83
     84        if (*p == '\n') {
     85            /* Terminal emulators might need \r\n, so generate it */
     86            sccb->data[data_len++] = '\r';
     87        }
     88
     89        sccb->data[data_len++] = *p;
     90        p++;
     91    }
     92
     93    sccb->h.length = sizeof(WriteEventData) + data_len;
     94    sccb->h.function_code = SCLP_FC_NORMAL_WRITE;
     95    sccb->ebh.length = sizeof(EventBufferHeader) + data_len;
     96    sccb->ebh.type = SCLP_EVENT_ASCII_CONSOLE_DATA;
     97    sccb->ebh.flags = 0;
     98
     99    sclp_service_call(SCLP_CMD_WRITE_EVENT_DATA, sccb);
    100
    101    return len;
    102}
    103
    104void sclp_print(const char *str)
    105{
    106    write(1, str, strlen(str));
    107}
    108
    109void sclp_get_loadparm_ascii(char *loadparm)
    110{
    111
    112    ReadInfo *sccb = (void *)_sccb;
    113
    114    memset((char *)_sccb, 0, sizeof(ReadInfo));
    115    sccb->h.length = SCCB_SIZE;
    116    if (!sclp_service_call(SCLP_CMDW_READ_SCP_INFO, sccb)) {
    117        ebcdic_to_ascii((char *) sccb->loadparm, loadparm, LOADPARM_LEN);
    118    }
    119}
    120
    121int sclp_read(char *str, size_t count)
    122{
    123    ReadEventData *sccb = (void *)_sccb;
    124    char *buf = (char *)(&sccb->ebh) + 7;
    125
    126    /* If count exceeds max buffer size, then restrict it to the max size */
    127    if (count > SCCB_SIZE - 8) {
    128        count = SCCB_SIZE - 8;
    129    }
    130
    131    sccb->h.length = SCCB_SIZE;
    132    sccb->h.function_code = SCLP_UNCONDITIONAL_READ;
    133
    134    sclp_service_call(SCLP_CMD_READ_EVENT_DATA, sccb);
    135    memcpy(str, buf, count);
    136
    137    return sccb->ebh.length - 7;
    138}