aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorBlue Swirl <blauwirbel@gmail.com>2011-11-19 11:17:58 +0000
committerBlue Swirl <blauwirbel@gmail.com>2011-11-19 11:17:58 +0000
commit25cc4a768d91817bc3b4bf9b3a270c4791509cd7 (patch)
tree78a65c66213c777fd87d68192ab82bc0f80b6d1e /hw
parent05a86f23e5ca83348eface349429341cefb8697b (diff)
parent326384d5b6dcea69ca44695ee807f8b50234ab71 (diff)
Merge branch 's390-1.0' of git://repo.or.cz/qemu/agraf
* 's390-1.0' of git://repo.or.cz/qemu/agraf: s390x: initialize virtio dev region tcg: Use TCGReg for standard tcg-target entry points. tcg: Standardize on TCGReg as the enum for hard registers s390x: Add shutdown for TCG s390-virtio machine s390: Fix cpu shutdown for KVM s390: fix short kernel command lines s390: fix reset hypercall to reset the status s390x: implement SIGP restart and shutdown s390x: implement rrbe instruction properly s390x: update R and C bits in storage key s390x: make ipte 31-bit aware s390x: add ldeb instruction
Diffstat (limited to 'hw')
-rw-r--r--hw/s390-virtio.c47
1 files changed, 44 insertions, 3 deletions
diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c
index 60c66e92c4..61b67e8c3a 100644
--- a/hw/s390-virtio.c
+++ b/hw/s390-virtio.c
@@ -97,6 +97,7 @@ int s390_virtio_hypercall(CPUState *env, uint64_t mem, uint64_t hypercall)
dev = s390_virtio_bus_find_mem(s390_bus, mem);
virtio_reset(dev->vdev);
+ stb_phys(dev->dev_offs + VIRTIO_DEV_OFFS_STATUS, 0);
s390_virtio_device_sync(dev);
break;
}
@@ -120,6 +121,34 @@ int s390_virtio_hypercall(CPUState *env, uint64_t mem, uint64_t hypercall)
return r;
}
+/*
+ * The number of running CPUs. On s390 a shutdown is the state of all CPUs
+ * being either stopped or disabled (for interrupts) waiting. We have to
+ * track this number to call the shutdown sequence accordingly. This
+ * number is modified either on startup or while holding the big qemu lock.
+ */
+static unsigned s390_running_cpus;
+
+void s390_add_running_cpu(CPUState *env)
+{
+ if (env->halted) {
+ s390_running_cpus++;
+ env->halted = 0;
+ env->exception_index = -1;
+ }
+}
+
+unsigned s390_del_running_cpu(CPUState *env)
+{
+ if (env->halted == 0) {
+ assert(s390_running_cpus >= 1);
+ s390_running_cpus--;
+ env->halted = 1;
+ env->exception_index = EXCP_HLT;
+ }
+ return s390_running_cpus;
+}
+
/* PC hardware initialisation */
static void s390_init(ram_addr_t my_ram_size,
const char *boot_device,
@@ -136,6 +165,9 @@ static void s390_init(ram_addr_t my_ram_size,
ram_addr_t initrd_size = 0;
int shift = 0;
uint8_t *storage_keys;
+ void *virtio_region;
+ target_phys_addr_t virtio_region_len;
+ target_phys_addr_t virtio_region_start;
int i;
/* s390x ram size detection needs a 16bit multiplier + an increment. So
@@ -155,6 +187,15 @@ static void s390_init(ram_addr_t my_ram_size,
memory_region_init_ram(ram, NULL, "s390.ram", my_ram_size);
memory_region_add_subregion(sysmem, 0, ram);
+ /* clear virtio region */
+ virtio_region_len = my_ram_size - ram_size;
+ virtio_region_start = ram_size;
+ virtio_region = cpu_physical_memory_map(virtio_region_start,
+ &virtio_region_len, true);
+ memset(virtio_region, 0, virtio_region_len);
+ cpu_physical_memory_unmap(virtio_region, virtio_region_len, 1,
+ virtio_region_len);
+
/* allocate storage keys */
storage_keys = g_malloc0(my_ram_size / TARGET_PAGE_SIZE);
@@ -178,8 +219,8 @@ static void s390_init(ram_addr_t my_ram_size,
tmp_env->storage_keys = storage_keys;
}
- env->halted = 0;
- env->exception_index = 0;
+ /* One CPU has to run */
+ s390_add_running_cpu(env);
if (kernel_filename) {
kernel_size = load_image(kernel_filename, qemu_get_ram_ptr(0));
@@ -229,7 +270,7 @@ static void s390_init(ram_addr_t my_ram_size,
if (kernel_cmdline) {
cpu_physical_memory_write(KERN_PARM_AREA, kernel_cmdline,
- strlen(kernel_cmdline));
+ strlen(kernel_cmdline) + 1);
}
/* Create VirtIO network adapters */