Statistics
| Branch: | Revision:

root / hw / s390x / sclp.c @ 0434e30a

History | View | Annotate | Download (4 kB)

1 f6c98f92 Heinz Graalfs
/*
2 f6c98f92 Heinz Graalfs
 * SCLP Support
3 f6c98f92 Heinz Graalfs
 *
4 f6c98f92 Heinz Graalfs
 * Copyright IBM, Corp. 2012
5 f6c98f92 Heinz Graalfs
 *
6 f6c98f92 Heinz Graalfs
 * Authors:
7 f6c98f92 Heinz Graalfs
 *  Christian Borntraeger <borntraeger@de.ibm.com>
8 f6c98f92 Heinz Graalfs
 *  Heinz Graalfs <graalfs@linux.vnet.ibm.com>
9 f6c98f92 Heinz Graalfs
 *
10 f6c98f92 Heinz Graalfs
 * This work is licensed under the terms of the GNU GPL, version 2 or (at your
11 f6c98f92 Heinz Graalfs
 * option) any later version.  See the COPYING file in the top-level directory.
12 f6c98f92 Heinz Graalfs
 *
13 f6c98f92 Heinz Graalfs
 */
14 f6c98f92 Heinz Graalfs
15 f6c98f92 Heinz Graalfs
#include "cpu.h"
16 9c17d615 Paolo Bonzini
#include "sysemu/kvm.h"
17 022c62cb Paolo Bonzini
#include "exec/memory.h"
18 f6c98f92 Heinz Graalfs
19 83c9f4ca Paolo Bonzini
#include "hw/s390x/sclp.h"
20 f6c98f92 Heinz Graalfs
21 559a17a1 Heinz Graalfs
static inline S390SCLPDevice *get_event_facility(void)
22 559a17a1 Heinz Graalfs
{
23 559a17a1 Heinz Graalfs
    ObjectProperty *op = object_property_find(qdev_get_machine(),
24 559a17a1 Heinz Graalfs
                                              "s390-sclp-event-facility",
25 559a17a1 Heinz Graalfs
                                              NULL);
26 559a17a1 Heinz Graalfs
    assert(op);
27 559a17a1 Heinz Graalfs
    return op->opaque;
28 559a17a1 Heinz Graalfs
}
29 559a17a1 Heinz Graalfs
30 f6c98f92 Heinz Graalfs
/* Provide information about the configuration, CPUs and storage */
31 f6c98f92 Heinz Graalfs
static void read_SCP_info(SCCB *sccb)
32 f6c98f92 Heinz Graalfs
{
33 f6c98f92 Heinz Graalfs
    ReadInfo *read_info = (ReadInfo *) sccb;
34 f6c98f92 Heinz Graalfs
    int shift = 0;
35 f6c98f92 Heinz Graalfs
36 f6c98f92 Heinz Graalfs
    while ((ram_size >> (20 + shift)) > 65535) {
37 f6c98f92 Heinz Graalfs
        shift++;
38 f6c98f92 Heinz Graalfs
    }
39 f6c98f92 Heinz Graalfs
    read_info->rnmax = cpu_to_be16(ram_size >> (20 + shift));
40 f6c98f92 Heinz Graalfs
    read_info->rnsize = 1 << shift;
41 f6c98f92 Heinz Graalfs
    sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_READ_COMPLETION);
42 f6c98f92 Heinz Graalfs
}
43 f6c98f92 Heinz Graalfs
44 f6c98f92 Heinz Graalfs
static void sclp_execute(SCCB *sccb, uint64_t code)
45 f6c98f92 Heinz Graalfs
{
46 559a17a1 Heinz Graalfs
    S390SCLPDevice *sdev = get_event_facility();
47 559a17a1 Heinz Graalfs
48 f6c98f92 Heinz Graalfs
    switch (code) {
49 f6c98f92 Heinz Graalfs
    case SCLP_CMDW_READ_SCP_INFO:
50 f6c98f92 Heinz Graalfs
    case SCLP_CMDW_READ_SCP_INFO_FORCED:
51 f6c98f92 Heinz Graalfs
        read_SCP_info(sccb);
52 f6c98f92 Heinz Graalfs
        break;
53 f6c98f92 Heinz Graalfs
    default:
54 559a17a1 Heinz Graalfs
        sdev->sclp_command_handler(sdev->ef, sccb, code);
55 f6c98f92 Heinz Graalfs
        break;
56 f6c98f92 Heinz Graalfs
    }
57 f6c98f92 Heinz Graalfs
}
58 f6c98f92 Heinz Graalfs
59 f6c98f92 Heinz Graalfs
int sclp_service_call(uint32_t sccb, uint64_t code)
60 f6c98f92 Heinz Graalfs
{
61 f6c98f92 Heinz Graalfs
    int r = 0;
62 f6c98f92 Heinz Graalfs
    SCCB work_sccb;
63 f6c98f92 Heinz Graalfs
64 f6c98f92 Heinz Graalfs
    hwaddr sccb_len = sizeof(SCCB);
65 f6c98f92 Heinz Graalfs
66 f6c98f92 Heinz Graalfs
    /* first some basic checks on program checks */
67 f6c98f92 Heinz Graalfs
    if (cpu_physical_memory_is_io(sccb)) {
68 f6c98f92 Heinz Graalfs
        r = -PGM_ADDRESSING;
69 f6c98f92 Heinz Graalfs
        goto out;
70 f6c98f92 Heinz Graalfs
    }
71 f6c98f92 Heinz Graalfs
    if (sccb & ~0x7ffffff8ul) {
72 f6c98f92 Heinz Graalfs
        r = -PGM_SPECIFICATION;
73 f6c98f92 Heinz Graalfs
        goto out;
74 f6c98f92 Heinz Graalfs
    }
75 f6c98f92 Heinz Graalfs
76 f6c98f92 Heinz Graalfs
    /*
77 f6c98f92 Heinz Graalfs
     * we want to work on a private copy of the sccb, to prevent guests
78 f6c98f92 Heinz Graalfs
     * from playing dirty tricks by modifying the memory content after
79 f6c98f92 Heinz Graalfs
     * the host has checked the values
80 f6c98f92 Heinz Graalfs
     */
81 f6c98f92 Heinz Graalfs
    cpu_physical_memory_read(sccb, &work_sccb, sccb_len);
82 f6c98f92 Heinz Graalfs
83 f6c98f92 Heinz Graalfs
    /* Valid sccb sizes */
84 f6c98f92 Heinz Graalfs
    if (be16_to_cpu(work_sccb.h.length) < sizeof(SCCBHeader) ||
85 f6c98f92 Heinz Graalfs
        be16_to_cpu(work_sccb.h.length) > SCCB_SIZE) {
86 f6c98f92 Heinz Graalfs
        r = -PGM_SPECIFICATION;
87 f6c98f92 Heinz Graalfs
        goto out;
88 f6c98f92 Heinz Graalfs
    }
89 f6c98f92 Heinz Graalfs
90 f6c98f92 Heinz Graalfs
    sclp_execute((SCCB *)&work_sccb, code);
91 f6c98f92 Heinz Graalfs
92 f6c98f92 Heinz Graalfs
    cpu_physical_memory_write(sccb, &work_sccb,
93 f6c98f92 Heinz Graalfs
                              be16_to_cpu(work_sccb.h.length));
94 f6c98f92 Heinz Graalfs
95 f6c98f92 Heinz Graalfs
    sclp_service_interrupt(sccb);
96 f6c98f92 Heinz Graalfs
97 f6c98f92 Heinz Graalfs
out:
98 f6c98f92 Heinz Graalfs
    return r;
99 f6c98f92 Heinz Graalfs
}
100 f6c98f92 Heinz Graalfs
101 f6c98f92 Heinz Graalfs
void sclp_service_interrupt(uint32_t sccb)
102 f6c98f92 Heinz Graalfs
{
103 559a17a1 Heinz Graalfs
    S390SCLPDevice *sdev = get_event_facility();
104 559a17a1 Heinz Graalfs
    uint32_t param = sccb & ~3;
105 559a17a1 Heinz Graalfs
106 559a17a1 Heinz Graalfs
    /* Indicate whether an event is still pending */
107 559a17a1 Heinz Graalfs
    param |= sdev->event_pending(sdev->ef) ? 1 : 0;
108 559a17a1 Heinz Graalfs
109 559a17a1 Heinz Graalfs
    if (!param) {
110 559a17a1 Heinz Graalfs
        /* No need to send an interrupt, there's nothing to be notified about */
111 559a17a1 Heinz Graalfs
        return;
112 559a17a1 Heinz Graalfs
    }
113 559a17a1 Heinz Graalfs
    s390_sclp_extint(param);
114 f6c98f92 Heinz Graalfs
}
115 f6c98f92 Heinz Graalfs
116 f6c98f92 Heinz Graalfs
/* qemu object creation and initialization functions */
117 f6c98f92 Heinz Graalfs
118 559a17a1 Heinz Graalfs
void s390_sclp_init(void)
119 559a17a1 Heinz Graalfs
{
120 559a17a1 Heinz Graalfs
    DeviceState *dev  = qdev_create(NULL, "s390-sclp-event-facility");
121 559a17a1 Heinz Graalfs
122 559a17a1 Heinz Graalfs
    object_property_add_child(qdev_get_machine(), "s390-sclp-event-facility",
123 559a17a1 Heinz Graalfs
                              OBJECT(dev), NULL);
124 559a17a1 Heinz Graalfs
    qdev_init_nofail(dev);
125 559a17a1 Heinz Graalfs
}
126 559a17a1 Heinz Graalfs
127 559a17a1 Heinz Graalfs
static int s390_sclp_dev_init(SysBusDevice *dev)
128 559a17a1 Heinz Graalfs
{
129 559a17a1 Heinz Graalfs
    int r;
130 559a17a1 Heinz Graalfs
    S390SCLPDevice *sdev = (S390SCLPDevice *)dev;
131 559a17a1 Heinz Graalfs
    S390SCLPDeviceClass *sclp = SCLP_S390_DEVICE_GET_CLASS(dev);
132 559a17a1 Heinz Graalfs
133 559a17a1 Heinz Graalfs
    r = sclp->init(sdev);
134 559a17a1 Heinz Graalfs
    if (!r) {
135 559a17a1 Heinz Graalfs
        assert(sdev->event_pending);
136 559a17a1 Heinz Graalfs
        assert(sdev->sclp_command_handler);
137 559a17a1 Heinz Graalfs
    }
138 559a17a1 Heinz Graalfs
139 559a17a1 Heinz Graalfs
    return r;
140 559a17a1 Heinz Graalfs
}
141 559a17a1 Heinz Graalfs
142 f6c98f92 Heinz Graalfs
static void s390_sclp_device_class_init(ObjectClass *klass, void *data)
143 f6c98f92 Heinz Graalfs
{
144 f6c98f92 Heinz Graalfs
    SysBusDeviceClass *dc = SYS_BUS_DEVICE_CLASS(klass);
145 f6c98f92 Heinz Graalfs
146 f6c98f92 Heinz Graalfs
    dc->init = s390_sclp_dev_init;
147 f6c98f92 Heinz Graalfs
}
148 f6c98f92 Heinz Graalfs
149 8c43a6f0 Andreas Färber
static const TypeInfo s390_sclp_device_info = {
150 f6c98f92 Heinz Graalfs
    .name = TYPE_DEVICE_S390_SCLP,
151 f6c98f92 Heinz Graalfs
    .parent = TYPE_SYS_BUS_DEVICE,
152 f6c98f92 Heinz Graalfs
    .instance_size = sizeof(S390SCLPDevice),
153 f6c98f92 Heinz Graalfs
    .class_init = s390_sclp_device_class_init,
154 f6c98f92 Heinz Graalfs
    .class_size = sizeof(S390SCLPDeviceClass),
155 f6c98f92 Heinz Graalfs
    .abstract = true,
156 f6c98f92 Heinz Graalfs
};
157 f6c98f92 Heinz Graalfs
158 f6c98f92 Heinz Graalfs
static void s390_sclp_register_types(void)
159 f6c98f92 Heinz Graalfs
{
160 f6c98f92 Heinz Graalfs
    type_register_static(&s390_sclp_device_info);
161 f6c98f92 Heinz Graalfs
}
162 f6c98f92 Heinz Graalfs
163 f6c98f92 Heinz Graalfs
type_init(s390_sclp_register_types)