diff options
Diffstat (limited to 'hw')
-rw-r--r-- | hw/block/dataplane/virtio-blk.c | 2 | ||||
-rw-r--r-- | hw/cris/Makefile.objs | 1 | ||||
-rw-r--r-- | hw/cris/axis_dev88.c | 7 | ||||
-rw-r--r-- | hw/cris/pic_cpu.c | 47 | ||||
-rw-r--r-- | hw/i386/bios-linker-loader.c | 3 | ||||
-rw-r--r-- | hw/ppc/ppc4xx_devs.c | 2 | ||||
-rw-r--r-- | hw/s390x/Makefile.objs | 1 | ||||
-rw-r--r-- | hw/s390x/event-facility.c | 6 | ||||
-rw-r--r-- | hw/s390x/sclp.c | 53 | ||||
-rw-r--r-- | hw/s390x/sclpcpu.c | 112 |
10 files changed, 176 insertions, 58 deletions
diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c index 456d437ac3..2237edb4eb 100644 --- a/hw/block/dataplane/virtio-blk.c +++ b/hw/block/dataplane/virtio-blk.c @@ -145,7 +145,7 @@ static void do_get_id_cmd(VirtIOBlockDataPlane *s, { char id[VIRTIO_BLK_ID_BYTES]; - /* Serial number not NUL-terminated when shorter than buffer */ + /* Serial number not NUL-terminated when longer than buffer */ strncpy(id, s->blk->serial ? s->blk->serial : "", sizeof(id)); iov_from_buf(iov, iov_cnt, 0, id, sizeof(id)); complete_request_early(s, elem, inhdr, VIRTIO_BLK_S_OK); diff --git a/hw/cris/Makefile.objs b/hw/cris/Makefile.objs index 776db7c5cd..7624173f77 100644 --- a/hw/cris/Makefile.objs +++ b/hw/cris/Makefile.objs @@ -1,3 +1,2 @@ -obj-y += pic_cpu.o obj-y += boot.o obj-y += axis_dev88.o diff --git a/hw/cris/axis_dev88.c b/hw/cris/axis_dev88.c index 55240886f5..645e45ccdf 100644 --- a/hw/cris/axis_dev88.c +++ b/hw/cris/axis_dev88.c @@ -254,7 +254,7 @@ void axisdev88_init(QEMUMachineInitArgs *args) DeviceState *dev; SysBusDevice *s; DriveInfo *nand; - qemu_irq irq[30], nmi[2], *cpu_irq; + qemu_irq irq[30], nmi[2]; void *etraxfs_dmac; struct etraxfs_dma_client *dma_eth; int i; @@ -296,15 +296,14 @@ void axisdev88_init(QEMUMachineInitArgs *args) &gpio_state.iomem); - cpu_irq = cris_pic_init_cpu(env); dev = qdev_create(NULL, "etraxfs,pic"); /* FIXME: Is there a proper way to signal vectors to the CPU core? */ qdev_prop_set_ptr(dev, "interrupt_vector", &env->interrupt_vector); qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); sysbus_mmio_map(s, 0, 0x3001c000); - sysbus_connect_irq(s, 0, cpu_irq[0]); - sysbus_connect_irq(s, 1, cpu_irq[1]); + sysbus_connect_irq(s, 0, qdev_get_gpio_in(DEVICE(cpu), CRIS_CPU_IRQ)); + sysbus_connect_irq(s, 1, qdev_get_gpio_in(DEVICE(cpu), CRIS_CPU_NMI)); for (i = 0; i < 30; i++) { irq[i] = qdev_get_gpio_in(dev, i); } diff --git a/hw/cris/pic_cpu.c b/hw/cris/pic_cpu.c deleted file mode 100644 index bd47bf1a5d..0000000000 --- a/hw/cris/pic_cpu.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * QEMU CRIS CPU interrupt wrapper logic. - * - * Copyright (c) 2009 Edgar E. Iglesias, Axis Communications AB. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "hw/sysbus.h" -#include "hw/hw.h" -#include "hw/cris/etraxfs.h" - -#define D(x) - -static void cris_pic_cpu_handler(void *opaque, int irq, int level) -{ - CRISCPU *cpu = opaque; - CPUState *cs = CPU(cpu); - int type = irq ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD; - - if (level) { - cpu_interrupt(cs, type); - } else { - cpu_reset_interrupt(cs, type); - } -} - -qemu_irq *cris_pic_init_cpu(CPUCRISState *env) -{ - return qemu_allocate_irqs(cris_pic_cpu_handler, cris_env_get_cpu(env), 2); -} diff --git a/hw/i386/bios-linker-loader.c b/hw/i386/bios-linker-loader.c index fd23611008..aa56184e9a 100644 --- a/hw/i386/bios-linker-loader.c +++ b/hw/i386/bios-linker-loader.c @@ -18,11 +18,10 @@ * with this program; if not, see <http://www.gnu.org/licenses/>. */ +#include "qemu-common.h" #include "bios-linker-loader.h" #include "hw/nvram/fw_cfg.h" -#include <string.h> -#include <assert.h> #include "qemu/bswap.h" #define BIOS_LINKER_LOADER_FILESZ FW_CFG_MAX_FILE_PATH diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c index 239aada193..9160ee7769 100644 --- a/hw/ppc/ppc4xx_devs.c +++ b/hw/ppc/ppc4xx_devs.c @@ -27,8 +27,6 @@ #include "qemu/log.h" #include "exec/address-spaces.h" -//#define DEBUG_MMIO -//#define DEBUG_UNASSIGNED #define DEBUG_UIC diff --git a/hw/s390x/Makefile.objs b/hw/s390x/Makefile.objs index 77e1218447..1ba6c3ab70 100644 --- a/hw/s390x/Makefile.objs +++ b/hw/s390x/Makefile.objs @@ -3,6 +3,7 @@ obj-y += s390-virtio-hcall.o obj-y += sclp.o obj-y += event-facility.o obj-y += sclpquiesce.o +obj-y += sclpcpu.o obj-y += ipl.o obj-y += css.o obj-y += s390-virtio-ccw.o diff --git a/hw/s390x/event-facility.c b/hw/s390x/event-facility.c index 25951a020a..a73c0b924a 100644 --- a/hw/s390x/event-facility.c +++ b/hw/s390x/event-facility.c @@ -32,6 +32,8 @@ struct SCLPEventFacility { unsigned int receive_mask; }; +SCLPEvent cpu_hotplug; + /* return true if any child has event pending set */ static bool event_pending(SCLPEventFacility *ef) { @@ -335,6 +337,10 @@ static int init_event_facility(S390SCLPDevice *sdev) } qdev_init_nofail(quiesce); + object_initialize(&cpu_hotplug, sizeof(cpu_hotplug), TYPE_SCLP_CPU_HOTPLUG); + qdev_set_parent_bus(DEVICE(&cpu_hotplug), BUS(&event_facility->sbus)); + object_property_set_bool(OBJECT(&cpu_hotplug), true, "realized", NULL); + return 0; } diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c index 86d6ae0023..4e0c564c5c 100644 --- a/hw/s390x/sclp.c +++ b/hw/s390x/sclp.c @@ -15,6 +15,7 @@ #include "cpu.h" #include "sysemu/kvm.h" #include "exec/memory.h" +#include "sysemu/sysemu.h" #include "hw/s390x/sclp.h" @@ -31,7 +32,26 @@ static inline S390SCLPDevice *get_event_facility(void) static void read_SCP_info(SCCB *sccb) { ReadInfo *read_info = (ReadInfo *) sccb; + CPUState *cpu; int shift = 0; + int cpu_count = 0; + int i = 0; + + 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); + + for (i = 0; i < cpu_count; i++) { + read_info->entries[i].address = i; + read_info->entries[i].type = 0; + } + + read_info->facilities = cpu_to_be64(SCLP_HAS_CPU_INFO); while ((ram_size >> (20 + shift)) > 65535) { shift++; @@ -41,15 +61,46 @@ static void read_SCP_info(SCCB *sccb) sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_READ_COMPLETION); } +/* Provide information about the CPU */ +static void sclp_read_cpu_info(SCCB *sccb) +{ + ReadCpuInfo *cpu_info = (ReadCpuInfo *) sccb; + CPUState *cpu; + int cpu_count = 0; + int i = 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)); + + for (i = 0; i < cpu_count; i++) { + cpu_info->entries[i].address = i; + cpu_info->entries[i].type = 0; + } + + sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_READ_COMPLETION); +} + static void sclp_execute(SCCB *sccb, uint64_t code) { S390SCLPDevice *sdev = get_event_facility(); - switch (code) { + switch (code & SCLP_CMD_CODE_MASK) { case SCLP_CMDW_READ_SCP_INFO: case SCLP_CMDW_READ_SCP_INFO_FORCED: read_SCP_info(sccb); break; + case SCLP_CMDW_READ_CPU_INFO: + sclp_read_cpu_info(sccb); + break; default: sdev->sclp_command_handler(sdev->ef, sccb, code); break; diff --git a/hw/s390x/sclpcpu.c b/hw/s390x/sclpcpu.c new file mode 100644 index 0000000000..b9c238a0da --- /dev/null +++ b/hw/s390x/sclpcpu.c @@ -0,0 +1,112 @@ +/* + * SCLP event type + * Signal CPU - Trigger SCLP interrupt for system CPU configure or + * de-configure + * + * Copyright IBM, Corp. 2013 + * + * Authors: + * Thang Pham <thang.pham@us.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. + * + */ +#include "sysemu/sysemu.h" +#include "hw/s390x/sclp.h" +#include "hw/s390x/event-facility.h" +#include "cpu.h" +#include "sysemu/cpus.h" +#include "sysemu/kvm.h" + +typedef struct ConfigMgtData { + EventBufferHeader ebh; + uint8_t reserved; + uint8_t event_qualifier; +} QEMU_PACKED ConfigMgtData; + +static qemu_irq irq_cpu_hotplug; /* Only used in this file */ + +#define EVENT_QUAL_CPU_CHANGE 1 + +void raise_irq_cpu_hotplug(void) +{ + qemu_irq_raise(irq_cpu_hotplug); +} + +static unsigned int send_mask(void) +{ + return SCLP_EVENT_MASK_CONFIG_MGT_DATA; +} + +static unsigned int receive_mask(void) +{ + return 0; +} + +static int read_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr, + int *slen) +{ + ConfigMgtData *cdata = (ConfigMgtData *) evt_buf_hdr; + if (*slen < sizeof(ConfigMgtData)) { + return 0; + } + + /* Event is no longer pending */ + if (!event->event_pending) { + return 0; + } + event->event_pending = false; + + /* Event header data */ + cdata->ebh.length = cpu_to_be16(sizeof(ConfigMgtData)); + cdata->ebh.type = SCLP_EVENT_CONFIG_MGT_DATA; + cdata->ebh.flags |= SCLP_EVENT_BUFFER_ACCEPTED; + + /* Trigger a rescan of CPUs by setting event qualifier */ + cdata->event_qualifier = EVENT_QUAL_CPU_CHANGE; + *slen -= sizeof(ConfigMgtData); + + return 1; +} + +static void trigger_signal(void *opaque, int n, int level) +{ + SCLPEvent *event = opaque; + event->event_pending = true; + + /* Trigger SCLP read operation */ + sclp_service_interrupt(0); +} + +static int irq_cpu_hotplug_init(SCLPEvent *event) +{ + irq_cpu_hotplug = *qemu_allocate_irqs(trigger_signal, event, 1); + return 0; +} + +static void cpu_class_init(ObjectClass *oc, void *data) +{ + SCLPEventClass *k = SCLP_EVENT_CLASS(oc); + + k->init = irq_cpu_hotplug_init; + k->get_send_mask = send_mask; + k->get_receive_mask = receive_mask; + k->read_event_data = read_event_data; + k->write_event_data = NULL; +} + +static const TypeInfo sclp_cpu_info = { + .name = "sclp-cpu-hotplug", + .parent = TYPE_SCLP_EVENT, + .instance_size = sizeof(SCLPEvent), + .class_init = cpu_class_init, + .class_size = sizeof(SCLPEventClass), +}; + +static void sclp_cpu_register_types(void) +{ + type_register_static(&sclp_cpu_info); +} + +type_init(sclp_cpu_register_types) |