Merge remote-tracking branch 'agraf/s390-for-upstream' into staging
* agraf/s390-for-upstream: s390: reset avail and used index on reboot S390: dont call system_shutdown on disabled wait S390: remove default cdrom, sd-card and floppy support S390: support reboot for kvm on s390 S390: reboot: reset device pages on reboot S390: fix error handling on kernel and initrd failures S390: fix kernel_commandline handling
This commit is contained in:
commit
174210fe70
|
@ -57,6 +57,29 @@ static ram_addr_t s390_virtio_device_num_vq(VirtIOS390Device *dev);
|
||||||
/* length of VirtIO device pages */
|
/* length of VirtIO device pages */
|
||||||
const target_phys_addr_t virtio_size = S390_DEVICE_PAGES * TARGET_PAGE_SIZE;
|
const target_phys_addr_t virtio_size = S390_DEVICE_PAGES * TARGET_PAGE_SIZE;
|
||||||
|
|
||||||
|
static void s390_virtio_bus_reset(void *opaque)
|
||||||
|
{
|
||||||
|
VirtIOS390Bus *bus = opaque;
|
||||||
|
bus->next_ring = bus->dev_page + TARGET_PAGE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void s390_virtio_reset_idx(VirtIOS390Device *dev)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
target_phys_addr_t idx_addr;
|
||||||
|
uint8_t num_vq;
|
||||||
|
|
||||||
|
num_vq = s390_virtio_device_num_vq(dev);
|
||||||
|
for (i = 0; i < num_vq; i++) {
|
||||||
|
idx_addr = virtio_queue_get_avail_addr(dev->vdev, i) +
|
||||||
|
VIRTIO_VRING_AVAIL_IDX_OFFS;
|
||||||
|
stw_phys(idx_addr, 0);
|
||||||
|
idx_addr = virtio_queue_get_used_addr(dev->vdev, i) +
|
||||||
|
VIRTIO_VRING_USED_IDX_OFFS;
|
||||||
|
stw_phys(idx_addr, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
VirtIOS390Bus *s390_virtio_bus_init(ram_addr_t *ram_size)
|
VirtIOS390Bus *s390_virtio_bus_init(ram_addr_t *ram_size)
|
||||||
{
|
{
|
||||||
VirtIOS390Bus *bus;
|
VirtIOS390Bus *bus;
|
||||||
|
@ -82,6 +105,7 @@ VirtIOS390Bus *s390_virtio_bus_init(ram_addr_t *ram_size)
|
||||||
/* Allocate RAM for VirtIO device pages (descriptors, queues, rings) */
|
/* Allocate RAM for VirtIO device pages (descriptors, queues, rings) */
|
||||||
*ram_size += S390_DEVICE_PAGES * TARGET_PAGE_SIZE;
|
*ram_size += S390_DEVICE_PAGES * TARGET_PAGE_SIZE;
|
||||||
|
|
||||||
|
qemu_register_reset(s390_virtio_bus_reset, bus);
|
||||||
return bus;
|
return bus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +138,7 @@ static int s390_virtio_device_init(VirtIOS390Device *dev, VirtIODevice *vdev)
|
||||||
virtio_bind_device(vdev, &virtio_s390_bindings, dev);
|
virtio_bind_device(vdev, &virtio_s390_bindings, dev);
|
||||||
dev->host_features = vdev->get_features(vdev, dev->host_features);
|
dev->host_features = vdev->get_features(vdev, dev->host_features);
|
||||||
s390_virtio_device_sync(dev);
|
s390_virtio_device_sync(dev);
|
||||||
|
s390_virtio_reset_idx(dev);
|
||||||
if (dev->qdev.hotplugged) {
|
if (dev->qdev.hotplugged) {
|
||||||
CPUS390XState *env = s390_cpu_addr2state(0);
|
CPUS390XState *env = s390_cpu_addr2state(0);
|
||||||
s390_virtio_irq(env, VIRTIO_PARAM_DEV_ADD, dev->dev_offs);
|
s390_virtio_irq(env, VIRTIO_PARAM_DEV_ADD, dev->dev_offs);
|
||||||
|
|
|
@ -34,6 +34,8 @@
|
||||||
#define VIRTIO_VQCONFIG_LEN 24
|
#define VIRTIO_VQCONFIG_LEN 24
|
||||||
|
|
||||||
#define VIRTIO_RING_LEN (TARGET_PAGE_SIZE * 3)
|
#define VIRTIO_RING_LEN (TARGET_PAGE_SIZE * 3)
|
||||||
|
#define VIRTIO_VRING_AVAIL_IDX_OFFS 2
|
||||||
|
#define VIRTIO_VRING_USED_IDX_OFFS 2
|
||||||
#define S390_DEVICE_PAGES 512
|
#define S390_DEVICE_PAGES 512
|
||||||
|
|
||||||
#define VIRTIO_PARAM_MASK 0xff
|
#define VIRTIO_PARAM_MASK 0xff
|
||||||
|
@ -90,3 +92,5 @@ VirtIOS390Device *s390_virtio_bus_find_vring(VirtIOS390Bus *bus,
|
||||||
ram_addr_t mem, int *vq_num);
|
ram_addr_t mem, int *vq_num);
|
||||||
VirtIOS390Device *s390_virtio_bus_find_mem(VirtIOS390Bus *bus, ram_addr_t mem);
|
VirtIOS390Device *s390_virtio_bus_find_mem(VirtIOS390Bus *bus, ram_addr_t mem);
|
||||||
void s390_virtio_device_sync(VirtIOS390Device *dev);
|
void s390_virtio_device_sync(VirtIOS390Device *dev);
|
||||||
|
void s390_virtio_reset_idx(VirtIOS390Device *dev);
|
||||||
|
|
||||||
|
|
|
@ -99,6 +99,7 @@ int s390_virtio_hypercall(CPUS390XState *env, uint64_t mem, uint64_t hypercall)
|
||||||
virtio_reset(dev->vdev);
|
virtio_reset(dev->vdev);
|
||||||
stb_phys(dev->dev_offs + VIRTIO_DEV_OFFS_STATUS, 0);
|
stb_phys(dev->dev_offs + VIRTIO_DEV_OFFS_STATUS, 0);
|
||||||
s390_virtio_device_sync(dev);
|
s390_virtio_device_sync(dev);
|
||||||
|
s390_virtio_reset_idx(dev);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case KVM_S390_VIRTIO_SET_STATUS:
|
case KVM_S390_VIRTIO_SET_STATUS:
|
||||||
|
@ -230,6 +231,11 @@ static void s390_init(ram_addr_t my_ram_size,
|
||||||
if (kernel_size == -1UL) {
|
if (kernel_size == -1UL) {
|
||||||
kernel_size = load_image_targphys(kernel_filename, 0, ram_size);
|
kernel_size = load_image_targphys(kernel_filename, 0, ram_size);
|
||||||
}
|
}
|
||||||
|
if (kernel_size == -1UL) {
|
||||||
|
fprintf(stderr, "qemu: could not load kernel '%s'\n",
|
||||||
|
kernel_filename);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* we can not rely on the ELF entry point, since up to 3.2 this
|
* we can not rely on the ELF entry point, since up to 3.2 this
|
||||||
* value was 0x800 (the SALIPL loader) and it wont work. For
|
* value was 0x800 (the SALIPL loader) and it wont work. For
|
||||||
|
@ -269,12 +275,18 @@ static void s390_init(ram_addr_t my_ram_size,
|
||||||
}
|
}
|
||||||
initrd_size = load_image_targphys(initrd_filename, initrd_offset,
|
initrd_size = load_image_targphys(initrd_filename, initrd_offset,
|
||||||
ram_size - initrd_offset);
|
ram_size - initrd_offset);
|
||||||
|
if (initrd_size == -1UL) {
|
||||||
|
fprintf(stderr, "qemu: could not load initrd '%s'\n",
|
||||||
|
initrd_filename);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
/* we have to overwrite values in the kernel image, which are "rom" */
|
/* we have to overwrite values in the kernel image, which are "rom" */
|
||||||
memcpy(rom_ptr(INITRD_PARM_START), &initrd_offset, 8);
|
memcpy(rom_ptr(INITRD_PARM_START), &initrd_offset, 8);
|
||||||
memcpy(rom_ptr(INITRD_PARM_SIZE), &initrd_size, 8);
|
memcpy(rom_ptr(INITRD_PARM_SIZE), &initrd_size, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kernel_cmdline) {
|
if (rom_ptr(KERN_PARM_AREA)) {
|
||||||
/* we have to overwrite values in the kernel image, which are "rom" */
|
/* we have to overwrite values in the kernel image, which are "rom" */
|
||||||
memcpy(rom_ptr(KERN_PARM_AREA), kernel_cmdline,
|
memcpy(rom_ptr(KERN_PARM_AREA), kernel_cmdline,
|
||||||
strlen(kernel_cmdline) + 1);
|
strlen(kernel_cmdline) + 1);
|
||||||
|
@ -320,8 +332,11 @@ static QEMUMachine s390_machine = {
|
||||||
.alias = "s390",
|
.alias = "s390",
|
||||||
.desc = "VirtIO based S390 machine",
|
.desc = "VirtIO based S390 machine",
|
||||||
.init = s390_init,
|
.init = s390_init,
|
||||||
|
.no_cdrom = 1,
|
||||||
|
.no_floppy = 1,
|
||||||
.no_serial = 1,
|
.no_serial = 1,
|
||||||
.no_parallel = 1,
|
.no_parallel = 1,
|
||||||
|
.no_sdcard = 1,
|
||||||
.use_virtcon = 1,
|
.use_virtcon = 1,
|
||||||
.max_cpus = 255,
|
.max_cpus = 255,
|
||||||
.is_default = 1,
|
.is_default = 1,
|
||||||
|
|
|
@ -407,6 +407,12 @@ static int handle_instruction(CPUS390XState *env, struct kvm_run *run)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool is_special_wait_psw(CPUS390XState *env)
|
||||||
|
{
|
||||||
|
/* signal quiesce */
|
||||||
|
return env->kvm_run->psw_addr == 0xfffUL;
|
||||||
|
}
|
||||||
|
|
||||||
static int handle_intercept(CPUS390XState *env)
|
static int handle_intercept(CPUS390XState *env)
|
||||||
{
|
{
|
||||||
struct kvm_run *run = env->kvm_run;
|
struct kvm_run *run = env->kvm_run;
|
||||||
|
@ -420,6 +426,12 @@ static int handle_intercept(CPUS390XState *env)
|
||||||
r = handle_instruction(env, run);
|
r = handle_instruction(env, run);
|
||||||
break;
|
break;
|
||||||
case ICPT_WAITPSW:
|
case ICPT_WAITPSW:
|
||||||
|
if (s390_del_running_cpu(env) == 0 &&
|
||||||
|
is_special_wait_psw(env)) {
|
||||||
|
qemu_system_shutdown_request();
|
||||||
|
}
|
||||||
|
r = EXCP_HALTED;
|
||||||
|
break;
|
||||||
case ICPT_CPU_STOP:
|
case ICPT_CPU_STOP:
|
||||||
if (s390_del_running_cpu(env) == 0) {
|
if (s390_del_running_cpu(env) == 0) {
|
||||||
qemu_system_shutdown_request();
|
qemu_system_shutdown_request();
|
||||||
|
@ -452,8 +464,7 @@ int kvm_arch_handle_exit(CPUS390XState *env, struct kvm_run *run)
|
||||||
ret = handle_intercept(env);
|
ret = handle_intercept(env);
|
||||||
break;
|
break;
|
||||||
case KVM_EXIT_S390_RESET:
|
case KVM_EXIT_S390_RESET:
|
||||||
fprintf(stderr, "RESET not implemented\n");
|
qemu_system_reset_request();
|
||||||
exit(1);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "Unknown KVM exit: %d\n", run->exit_reason);
|
fprintf(stderr, "Unknown KVM exit: %d\n", run->exit_reason);
|
||||||
|
|
Loading…
Reference in a new issue