sclp.c 21.4 KB
Newer Older
H
Heinz Graalfs 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/*
 * SCLP Support
 *
 * Copyright IBM, Corp. 2012
 *
 * Authors:
 *  Christian Borntraeger <borntraeger@de.ibm.com>
 *  Heinz Graalfs <graalfs@linux.vnet.ibm.com>
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or (at your
 * option) any later version.  See the COPYING file in the top-level directory.
 *
 */

P
Peter Maydell 已提交
15
#include "qemu/osdep.h"
16
#include "qapi/error.h"
H
Heinz Graalfs 已提交
17
#include "cpu.h"
18
#include "sysemu/kvm.h"
19
#include "exec/memory.h"
J
Jason J. Herne 已提交
20
#include "sysemu/sysemu.h"
21
#include "exec/address-spaces.h"
22
#include "hw/boards.h"
23
#include "hw/s390x/sclp.h"
24
#include "hw/s390x/event-facility.h"
F
Frank Blaschka 已提交
25
#include "hw/s390x/s390-pci-bus.h"
26
#include "hw/s390x/ipl.h"
H
Heinz Graalfs 已提交
27

28 29
static inline SCLPDevice *get_sclp_device(void)
{
30 31 32 33 34 35
    static SCLPDevice *sclp;

    if (!sclp) {
        sclp = SCLP(object_resolve_path_type("", TYPE_SCLP, NULL));
    }
    return sclp;
36 37
}

38 39
static void prepare_cpu_entries(SCLPDevice *sclp, CPUEntry *entry, int count)
{
40
    uint8_t features[SCCB_CPU_FEATURE_LEN] = { 0 };
41 42
    int i;

43
    s390_get_feat_block(S390_FEAT_TYPE_SCLP_CPU, features);
44 45 46
    for (i = 0; i < count; i++) {
        entry[i].address = i;
        entry[i].type = 0;
47
        memcpy(entry[i].features, features, sizeof(entry[i].features));
48 49 50
    }
}

H
Heinz Graalfs 已提交
51
/* Provide information about the configuration, CPUs and storage */
52
static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb)
H
Heinz Graalfs 已提交
53 54
{
    ReadInfo *read_info = (ReadInfo *) sccb;
55
    MachineState *machine = MACHINE(qdev_get_machine());
56
    sclpMemoryHotplugDev *mhd = get_sclp_memory_hotplug_dev();
J
Jason J. Herne 已提交
57 58
    CPUState *cpu;
    int cpu_count = 0;
59
    int rnsize, rnmax;
60
    int slots = MIN(machine->ram_slots, s390_get_memslot_count(kvm_state));
61
    IplParameterBlock *ipib = s390_ipl_get_iplb();
J
Jason J. Herne 已提交
62 63 64 65 66 67 68 69 70 71

    CPU_FOREACH(cpu) {
        cpu_count++;
    }

    /* CPU information */
    read_info->entries_cpu = cpu_to_be16(cpu_count);
    read_info->offset_cpu = cpu_to_be16(offsetof(ReadInfo, entries));
    read_info->highest_cpu = cpu_to_be16(max_cpus);

72 73
    read_info->ibc_val = cpu_to_be32(s390_get_ibc_val());

74 75 76 77 78 79
    /* Configuration Characteristic (Extension) */
    s390_get_feat_block(S390_FEAT_TYPE_SCLP_CONF_CHAR,
                         read_info->conf_char);
    s390_get_feat_block(S390_FEAT_TYPE_SCLP_CONF_CHAR_EXT,
                         read_info->conf_char_ext);

80
    prepare_cpu_entries(sclp, read_info->entries, cpu_count);
J
Jason J. Herne 已提交
81

F
Frank Blaschka 已提交
82 83
    read_info->facilities = cpu_to_be64(SCLP_HAS_CPU_INFO |
                                        SCLP_HAS_PCI_RECONFIG);
H
Heinz Graalfs 已提交
84

85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
    /* Memory Hotplug is only supported for the ccw machine type */
    if (mhd) {
        mhd->standby_subregion_size = MEM_SECTION_SIZE;
        /* Deduct the memory slot already used for core */
        if (slots > 0) {
            while ((mhd->standby_subregion_size * (slots - 1)
                    < mhd->standby_mem_size)) {
                mhd->standby_subregion_size = mhd->standby_subregion_size << 1;
            }
        }
        /*
         * Initialize mapping of guest standby memory sections indicating which
         * are and are not online. Assume all standby memory begins offline.
         */
        if (mhd->standby_state_map == 0) {
            if (mhd->standby_mem_size % mhd->standby_subregion_size) {
                mhd->standby_state_map = g_malloc0((mhd->standby_mem_size /
                                             mhd->standby_subregion_size + 1) *
                                             (mhd->standby_subregion_size /
                                             MEM_SECTION_SIZE));
            } else {
                mhd->standby_state_map = g_malloc0(mhd->standby_mem_size /
                                                   MEM_SECTION_SIZE);
            }
        }
        mhd->padded_ram_size = ram_size + mhd->pad_size;
        mhd->rzm = 1 << mhd->increment_size;

        read_info->facilities |= cpu_to_be64(SCLP_FC_ASSIGN_ATTACH_READ_STOR);
    }
115
    read_info->mha_pow = s390_get_mha_pow();
D
David Hildenbrand 已提交
116
    read_info->hmfai = cpu_to_be32(s390_get_hmfai());
117

118
    rnsize = 1 << (sclp->increment_size - 20);
119 120 121 122 123 124 125
    if (rnsize <= 128) {
        read_info->rnsize = rnsize;
    } else {
        read_info->rnsize = 0;
        read_info->rnsize2 = cpu_to_be32(rnsize);
    }

126
    rnmax = machine->maxram_size >> sclp->increment_size;
127 128 129 130 131 132 133
    if (rnmax < 0x10000) {
        read_info->rnmax = cpu_to_be16(rnmax);
    } else {
        read_info->rnmax = cpu_to_be16(0);
        read_info->rnmax2 = cpu_to_be64(rnmax);
    }

134 135 136 137 138 139 140
    if (ipib && ipib->flags & DIAG308_FLAGS_LP_VALID) {
        memcpy(&read_info->loadparm, &ipib->loadparm,
               sizeof(read_info->loadparm));
    } else {
        s390_ipl_set_loadparm(read_info->loadparm);
    }

141 142 143
    sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_READ_COMPLETION);
}

144
static void read_storage_element0_info(SCLPDevice *sclp, SCCB *sccb)
145 146 147 148 149 150
{
    int i, assigned;
    int subincrement_id = SCLP_STARTING_SUBINCREMENT_ID;
    ReadStorageElementInfo *storage_info = (ReadStorageElementInfo *) sccb;
    sclpMemoryHotplugDev *mhd = get_sclp_memory_hotplug_dev();

151 152 153 154
    if (!mhd) {
        sccb->h.response_code = cpu_to_be16(SCLP_RC_INVALID_SCLP_COMMAND);
        return;
    }
155 156 157 158 159 160 161 162 163 164 165 166 167 168

    if ((ram_size >> mhd->increment_size) >= 0x10000) {
        sccb->h.response_code = cpu_to_be16(SCLP_RC_SCCB_BOUNDARY_VIOLATION);
        return;
    }

    /* Return information regarding core memory */
    storage_info->max_id = cpu_to_be16(mhd->standby_mem_size ? 1 : 0);
    assigned = ram_size >> mhd->increment_size;
    storage_info->assigned = cpu_to_be16(assigned);

    for (i = 0; i < assigned; i++) {
        storage_info->entries[i] = cpu_to_be32(subincrement_id);
        subincrement_id += SCLP_INCREMENT_UNIT;
H
Heinz Graalfs 已提交
169 170 171 172
    }
    sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_READ_COMPLETION);
}

173
static void read_storage_element1_info(SCLPDevice *sclp, SCCB *sccb)
174 175 176 177
{
    ReadStorageElementInfo *storage_info = (ReadStorageElementInfo *) sccb;
    sclpMemoryHotplugDev *mhd = get_sclp_memory_hotplug_dev();

178 179 180 181
    if (!mhd) {
        sccb->h.response_code = cpu_to_be16(SCLP_RC_INVALID_SCLP_COMMAND);
        return;
    }
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196

    if ((mhd->standby_mem_size >> mhd->increment_size) >= 0x10000) {
        sccb->h.response_code = cpu_to_be16(SCLP_RC_SCCB_BOUNDARY_VIOLATION);
        return;
    }

    /* Return information regarding standby memory */
    storage_info->max_id = cpu_to_be16(mhd->standby_mem_size ? 1 : 0);
    storage_info->assigned = cpu_to_be16(mhd->standby_mem_size >>
                                         mhd->increment_size);
    storage_info->standby = cpu_to_be16(mhd->standby_mem_size >>
                                        mhd->increment_size);
    sccb->h.response_code = cpu_to_be16(SCLP_RC_STANDBY_READ_COMPLETION);
}

197 198
static void attach_storage_element(SCLPDevice *sclp, SCCB *sccb,
                                   uint16_t element)
199 200 201 202 203
{
    int i, assigned, subincrement_id;
    AttachStorageElement *attach_info = (AttachStorageElement *) sccb;
    sclpMemoryHotplugDev *mhd = get_sclp_memory_hotplug_dev();

204 205 206 207
    if (!mhd) {
        sccb->h.response_code = cpu_to_be16(SCLP_RC_INVALID_SCLP_COMMAND);
        return;
    }
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224

    if (element != 1) {
        sccb->h.response_code = cpu_to_be16(SCLP_RC_INVALID_SCLP_COMMAND);
        return;
    }

    assigned = mhd->standby_mem_size >> mhd->increment_size;
    attach_info->assigned = cpu_to_be16(assigned);
    subincrement_id = ((ram_size >> mhd->increment_size) << 16)
                      + SCLP_STARTING_SUBINCREMENT_ID;
    for (i = 0; i < assigned; i++) {
        attach_info->entries[i] = cpu_to_be32(subincrement_id);
        subincrement_id += SCLP_INCREMENT_UNIT;
    }
    sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_COMPLETION);
}

225
static void assign_storage(SCLPDevice *sclp, SCCB *sccb)
226 227 228 229 230
{
    MemoryRegion *mr = NULL;
    uint64_t this_subregion_size;
    AssignStorage *assign_info = (AssignStorage *) sccb;
    sclpMemoryHotplugDev *mhd = get_sclp_memory_hotplug_dev();
231
    ram_addr_t assign_addr;
232 233
    MemoryRegion *sysmem = get_system_memory();

234 235 236 237 238 239
    if (!mhd) {
        sccb->h.response_code = cpu_to_be16(SCLP_RC_INVALID_SCLP_COMMAND);
        return;
    }
    assign_addr = (assign_info->rn - 1) * mhd->rzm;

240 241 242 243
    if ((assign_addr % MEM_SECTION_SIZE == 0) &&
        (assign_addr >= mhd->padded_ram_size)) {
        /* Re-use existing memory region if found */
        mr = memory_region_find(sysmem, assign_addr, 1).mr;
244
        memory_region_unref(mr);
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
        if (!mr) {

            MemoryRegion *standby_ram = g_new(MemoryRegion, 1);

            /* offset to align to standby_subregion_size for allocation */
            ram_addr_t offset = assign_addr -
                                (assign_addr - mhd->padded_ram_size)
                                % mhd->standby_subregion_size;

            /* strlen("standby.ram") + 4 (Max of KVM_MEMORY_SLOTS) +  NULL */
            char id[16];
            snprintf(id, 16, "standby.ram%d",
                     (int)((offset - mhd->padded_ram_size) /
                     mhd->standby_subregion_size) + 1);

            /* Allocate a subregion of the calculated standby_subregion_size */
            if (offset + mhd->standby_subregion_size >
                mhd->padded_ram_size + mhd->standby_mem_size) {
                this_subregion_size = mhd->padded_ram_size +
                  mhd->standby_mem_size - offset;
            } else {
                this_subregion_size = mhd->standby_subregion_size;
            }

269
            memory_region_init_ram(standby_ram, NULL, id, this_subregion_size,
270
                                   &error_fatal);
271 272 273 274 275
            /* This is a hack to make memory hotunplug work again. Once we have
             * subdevices, we have to unparent them when unassigning memory,
             * instead of doing it via the ref count of the MemoryRegion. */
            object_ref(OBJECT(standby_ram));
            object_unparent(OBJECT(standby_ram));
276 277 278 279 280 281 282 283 284
            memory_region_add_subregion(sysmem, offset, standby_ram);
        }
        /* The specified subregion is no longer in standby */
        mhd->standby_state_map[(assign_addr - mhd->padded_ram_size)
                               / MEM_SECTION_SIZE] = 1;
    }
    sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_COMPLETION);
}

285
static void unassign_storage(SCLPDevice *sclp, SCCB *sccb)
286 287 288 289
{
    MemoryRegion *mr = NULL;
    AssignStorage *assign_info = (AssignStorage *) sccb;
    sclpMemoryHotplugDev *mhd = get_sclp_memory_hotplug_dev();
290
    ram_addr_t unassign_addr;
291 292
    MemoryRegion *sysmem = get_system_memory();

293 294 295 296 297 298
    if (!mhd) {
        sccb->h.response_code = cpu_to_be16(SCLP_RC_INVALID_SCLP_COMMAND);
        return;
    }
    unassign_addr = (assign_info->rn - 1) * mhd->rzm;

299 300 301 302 303 304 305 306
    /* if the addr is a multiple of 256 MB */
    if ((unassign_addr % MEM_SECTION_SIZE == 0) &&
        (unassign_addr >= mhd->padded_ram_size)) {
        mhd->standby_state_map[(unassign_addr -
                           mhd->padded_ram_size) / MEM_SECTION_SIZE] = 0;

        /* find the specified memory region and destroy it */
        mr = memory_region_find(sysmem, unassign_addr, 1).mr;
307
        memory_region_unref(mr);
308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325
        if (mr) {
            int i;
            int is_removable = 1;
            ram_addr_t map_offset = (unassign_addr - mhd->padded_ram_size -
                                     (unassign_addr - mhd->padded_ram_size)
                                     % mhd->standby_subregion_size);
            /* Mark all affected subregions as 'standby' once again */
            for (i = 0;
                 i < (mhd->standby_subregion_size / MEM_SECTION_SIZE);
                 i++) {

                if (mhd->standby_state_map[i + map_offset / MEM_SECTION_SIZE]) {
                    is_removable = 0;
                    break;
                }
            }
            if (is_removable) {
                memory_region_del_subregion(sysmem, mr);
326
                object_unref(OBJECT(mr));
327 328 329 330 331 332
            }
        }
    }
    sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_COMPLETION);
}

J
Jason J. Herne 已提交
333
/* Provide information about the CPU */
334
static void sclp_read_cpu_info(SCLPDevice *sclp, SCCB *sccb)
J
Jason J. Herne 已提交
335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351
{
    ReadCpuInfo *cpu_info = (ReadCpuInfo *) sccb;
    CPUState *cpu;
    int cpu_count = 0;

    CPU_FOREACH(cpu) {
        cpu_count++;
    }

    cpu_info->nr_configured = cpu_to_be16(cpu_count);
    cpu_info->offset_configured = cpu_to_be16(offsetof(ReadCpuInfo, entries));
    cpu_info->nr_standby = cpu_to_be16(0);

    /* The standby offset is 16-byte for each CPU */
    cpu_info->offset_standby = cpu_to_be16(cpu_info->offset_configured
        + cpu_info->nr_configured*sizeof(CPUEntry));

352
    prepare_cpu_entries(sclp, cpu_info->entries, cpu_count);
J
Jason J. Herne 已提交
353 354 355 356

    sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_READ_COMPLETION);
}

357
static void sclp_execute(SCLPDevice *sclp, SCCB *sccb, uint32_t code)
H
Heinz Graalfs 已提交
358
{
359 360
    SCLPDeviceClass *sclp_c = SCLP_GET_CLASS(sclp);
    SCLPEventFacility *ef = sclp->event_facility;
361
    SCLPEventFacilityClass *efc = EVENT_FACILITY_GET_CLASS(ef);
H
Heinz Graalfs 已提交
362

363
    switch (code & SCLP_CMD_CODE_MASK) {
H
Heinz Graalfs 已提交
364 365
    case SCLP_CMDW_READ_SCP_INFO:
    case SCLP_CMDW_READ_SCP_INFO_FORCED:
366
        sclp_c->read_SCP_info(sclp, sccb);
H
Heinz Graalfs 已提交
367
        break;
J
Jason J. Herne 已提交
368
    case SCLP_CMDW_READ_CPU_INFO:
369
        sclp_c->read_cpu_info(sclp, sccb);
J
Jason J. Herne 已提交
370
        break;
371 372
    case SCLP_READ_STORAGE_ELEMENT_INFO:
        if (code & 0xff00) {
373
            sclp_c->read_storage_element1_info(sclp, sccb);
374
        } else {
375
            sclp_c->read_storage_element0_info(sclp, sccb);
376 377 378
        }
        break;
    case SCLP_ATTACH_STORAGE_ELEMENT:
379
        sclp_c->attach_storage_element(sclp, sccb, (code & 0xff00) >> 8);
380 381
        break;
    case SCLP_ASSIGN_STORAGE:
382
        sclp_c->assign_storage(sclp, sccb);
383 384
        break;
    case SCLP_UNASSIGN_STORAGE:
385
        sclp_c->unassign_storage(sclp, sccb);
386
        break;
F
Frank Blaschka 已提交
387
    case SCLP_CMDW_CONFIGURE_PCI:
388
        s390_pci_sclp_configure(sccb);
F
Frank Blaschka 已提交
389 390
        break;
    case SCLP_CMDW_DECONFIGURE_PCI:
391
        s390_pci_sclp_deconfigure(sccb);
F
Frank Blaschka 已提交
392
        break;
H
Heinz Graalfs 已提交
393
    default:
394
        efc->command_handler(ef, sccb, code);
H
Heinz Graalfs 已提交
395 396 397 398
        break;
    }
}

399
int sclp_service_call(CPUS390XState *env, uint64_t sccb, uint32_t code)
H
Heinz Graalfs 已提交
400
{
401 402
    SCLPDevice *sclp = get_sclp_device();
    SCLPDeviceClass *sclp_c = SCLP_GET_CLASS(sclp);
H
Heinz Graalfs 已提交
403 404 405 406 407 408
    int r = 0;
    SCCB work_sccb;

    hwaddr sccb_len = sizeof(SCCB);

    /* first some basic checks on program checks */
409 410 411 412
    if (env->psw.mask & PSW_MASK_PSTATE) {
        r = -PGM_PRIVILEGED;
        goto out;
    }
H
Heinz Graalfs 已提交
413 414 415 416
    if (cpu_physical_memory_is_io(sccb)) {
        r = -PGM_ADDRESSING;
        goto out;
    }
417 418
    if ((sccb & ~0x1fffUL) == 0 || (sccb & ~0x1fffUL) == env->psa
        || (sccb & ~0x7ffffff8UL) != 0) {
H
Heinz Graalfs 已提交
419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436
        r = -PGM_SPECIFICATION;
        goto out;
    }

    /*
     * we want to work on a private copy of the sccb, to prevent guests
     * from playing dirty tricks by modifying the memory content after
     * the host has checked the values
     */
    cpu_physical_memory_read(sccb, &work_sccb, sccb_len);

    /* Valid sccb sizes */
    if (be16_to_cpu(work_sccb.h.length) < sizeof(SCCBHeader) ||
        be16_to_cpu(work_sccb.h.length) > SCCB_SIZE) {
        r = -PGM_SPECIFICATION;
        goto out;
    }

L
Laurent Vivier 已提交
437
    sclp_c->execute(sclp, &work_sccb, code);
H
Heinz Graalfs 已提交
438 439 440 441

    cpu_physical_memory_write(sccb, &work_sccb,
                              be16_to_cpu(work_sccb.h.length));

442
    sclp_c->service_interrupt(sclp, sccb);
H
Heinz Graalfs 已提交
443 444 445 446 447

out:
    return r;
}

448
static void service_interrupt(SCLPDevice *sclp, uint32_t sccb)
H
Heinz Graalfs 已提交
449
{
450
    SCLPEventFacility *ef = sclp->event_facility;
451 452
    SCLPEventFacilityClass *efc = EVENT_FACILITY_GET_CLASS(ef);

H
Heinz Graalfs 已提交
453 454 455
    uint32_t param = sccb & ~3;

    /* Indicate whether an event is still pending */
456
    param |= efc->event_pending(ef) ? 1 : 0;
H
Heinz Graalfs 已提交
457 458 459 460 461 462

    if (!param) {
        /* No need to send an interrupt, there's nothing to be notified about */
        return;
    }
    s390_sclp_extint(param);
H
Heinz Graalfs 已提交
463 464
}

465 466 467 468 469 470 471 472
void sclp_service_interrupt(uint32_t sccb)
{
    SCLPDevice *sclp = get_sclp_device();
    SCLPDeviceClass *sclp_c = SCLP_GET_CLASS(sclp);

    sclp_c->service_interrupt(sclp, sccb);
}

H
Heinz Graalfs 已提交
473 474
/* qemu object creation and initialization functions */

H
Heinz Graalfs 已提交
475 476
void s390_sclp_init(void)
{
477
    Object *new = object_new(TYPE_SCLP);
H
Heinz Graalfs 已提交
478

479 480 481 482
    object_property_add_child(qdev_get_machine(), TYPE_SCLP, new,
                              NULL);
    object_unref(OBJECT(new));
    qdev_init_nofail(DEVICE(new));
H
Heinz Graalfs 已提交
483
}
484

485 486
static void sclp_realize(DeviceState *dev, Error **errp)
{
487
    MachineState *machine = MACHINE(qdev_get_machine());
488
    SCLPDevice *sclp = SCLP(dev);
489
    Error *err = NULL;
490 491
    uint64_t hw_limit;
    int ret;
492 493

    object_property_set_bool(OBJECT(sclp->event_facility), true, "realized",
494 495
                             &err);
    if (err) {
496
        goto out;
497
    }
498 499 500 501 502 503
    /*
     * qdev_device_add searches the sysbus for TYPE_SCLP_EVENTS_BUS. As long
     * as we can't find a fitting bus via the qom tree, we have to add the
     * event facility to the sysbus, so e.g. a sclp console can be created.
     */
    qdev_set_parent_bus(DEVICE(sclp->event_facility), sysbus_get_default());
504 505 506

    ret = s390_set_memory_limit(machine->maxram_size, &hw_limit);
    if (ret == -E2BIG) {
507
        error_setg(&err, "host supports a maximum of %" PRIu64 " GB",
508 509
                   hw_limit >> 30);
    } else if (ret) {
510
        error_setg(&err, "setting the guest size failed");
511
    }
512 513

out:
514
    error_propagate(errp, err);
515 516
}

517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537
static void sclp_memory_init(SCLPDevice *sclp)
{
    MachineState *machine = MACHINE(qdev_get_machine());
    ram_addr_t initial_mem = machine->ram_size;
    ram_addr_t max_mem = machine->maxram_size;
    ram_addr_t standby_mem = max_mem - initial_mem;
    ram_addr_t pad_mem = 0;
    int increment_size = 20;

    /* The storage increment size is a multiple of 1M and is a power of 2.
     * The number of storage increments must be MAX_STORAGE_INCREMENTS or fewer.
     * The variable 'increment_size' is an exponent of 2 that can be
     * used to calculate the size (in bytes) of an increment. */
    while ((initial_mem >> increment_size) > MAX_STORAGE_INCREMENTS) {
        increment_size++;
    }
    if (machine->ram_slots) {
        while ((standby_mem >> increment_size) > MAX_STORAGE_INCREMENTS) {
            increment_size++;
        }
    }
538
    sclp->increment_size = increment_size;
539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564

    /* The core and standby memory areas need to be aligned with
     * the increment size.  In effect, this can cause the
     * user-specified memory size to be rounded down to align
     * with the nearest increment boundary. */
    initial_mem = initial_mem >> increment_size << increment_size;
    standby_mem = standby_mem >> increment_size << increment_size;

    /* If the size of ram is not on a MEM_SECTION_SIZE boundary,
       calculate the pad size necessary to force this boundary. */
    if (machine->ram_slots && standby_mem) {
        sclpMemoryHotplugDev *mhd = init_sclp_memory_hotplug_dev();

        if (initial_mem % MEM_SECTION_SIZE) {
            pad_mem = MEM_SECTION_SIZE - initial_mem % MEM_SECTION_SIZE;
        }
        mhd->increment_size = increment_size;
        mhd->pad_size = pad_mem;
        mhd->standby_mem_size = standby_mem;
    }
    machine->ram_size = initial_mem;
    machine->maxram_size = initial_mem + pad_mem + standby_mem;
    /* let's propagate the changed ram size into the global variable. */
    ram_size = initial_mem;
}

565 566 567 568 569 570 571 572 573
static void sclp_init(Object *obj)
{
    SCLPDevice *sclp = SCLP(obj);
    Object *new;

    new = object_new(TYPE_SCLP_EVENT_FACILITY);
    object_property_add_child(obj, TYPE_SCLP_EVENT_FACILITY, new, NULL);
    object_unref(new);
    sclp->event_facility = EVENT_FACILITY(new);
574 575

    sclp_memory_init(sclp);
576 577 578 579
}

static void sclp_class_init(ObjectClass *oc, void *data)
{
580
    SCLPDeviceClass *sc = SCLP_CLASS(oc);
581 582 583 584 585 586
    DeviceClass *dc = DEVICE_CLASS(oc);

    dc->desc = "SCLP (Service-Call Logical Processor)";
    dc->realize = sclp_realize;
    dc->hotpluggable = false;
    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
587 588 589 590 591 592 593 594 595

    sc->read_SCP_info = read_SCP_info;
    sc->read_storage_element0_info = read_storage_element0_info;
    sc->read_storage_element1_info = read_storage_element1_info;
    sc->attach_storage_element = attach_storage_element;
    sc->assign_storage = assign_storage;
    sc->unassign_storage = unassign_storage;
    sc->read_cpu_info = sclp_read_cpu_info;
    sc->execute = sclp_execute;
596
    sc->service_interrupt = service_interrupt;
597 598 599 600 601 602 603 604 605 606 607
}

static TypeInfo sclp_info = {
    .name = TYPE_SCLP,
    .parent = TYPE_DEVICE,
    .instance_init = sclp_init,
    .instance_size = sizeof(SCLPDevice),
    .class_init = sclp_class_init,
    .class_size = sizeof(SCLPDeviceClass),
};

608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625
sclpMemoryHotplugDev *init_sclp_memory_hotplug_dev(void)
{
    DeviceState *dev;
    dev = qdev_create(NULL, TYPE_SCLP_MEMORY_HOTPLUG_DEV);
    object_property_add_child(qdev_get_machine(),
                              TYPE_SCLP_MEMORY_HOTPLUG_DEV,
                              OBJECT(dev), NULL);
    qdev_init_nofail(dev);
    return SCLP_MEMORY_HOTPLUG_DEV(object_resolve_path(
                                   TYPE_SCLP_MEMORY_HOTPLUG_DEV, NULL));
}

sclpMemoryHotplugDev *get_sclp_memory_hotplug_dev(void)
{
    return SCLP_MEMORY_HOTPLUG_DEV(object_resolve_path(
                                   TYPE_SCLP_MEMORY_HOTPLUG_DEV, NULL));
}

C
Cornelia Huck 已提交
626 627 628 629 630 631 632 633
static void sclp_memory_hotplug_dev_class_init(ObjectClass *klass,
                                               void *data)
{
    DeviceClass *dc = DEVICE_CLASS(klass);

    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
}

634 635 636 637
static TypeInfo sclp_memory_hotplug_dev_info = {
    .name = TYPE_SCLP_MEMORY_HOTPLUG_DEV,
    .parent = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(sclpMemoryHotplugDev),
C
Cornelia Huck 已提交
638
    .class_init = sclp_memory_hotplug_dev_class_init,
639 640 641 642 643
};

static void register_types(void)
{
    type_register_static(&sclp_memory_hotplug_dev_info);
644
    type_register_static(&sclp_info);
645 646
}
type_init(register_types);