From 85ca3371f6f5284d54202aec091e7cb3a49e5135 Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Thu, 28 Aug 2014 13:58:49 +0200 Subject: [PATCH 01/19] s390x/kvm: run guest triggered resets on the target vcpu thread Currently, load_normal_reset() and modified_clear_reset() as triggered by a guest vcpu will initiate cpu resets on the current vcpu thread for all cpus. The reset should happen on the individual vcpu thread instead, so let's use run_on_cpu() for this. This avoids calls to synchronize_rcu() in the kernel. Reviewed-by: Cornelia Huck Acked-by: Christian Borntraeger Signed-off-by: David Hildenbrand Signed-off-by: Jens Freimann Signed-off-by: Christian Borntraeger --- target-s390x/cpu.h | 15 +++++++++++++++ target-s390x/misc_helper.c | 30 ++++++++---------------------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index b13761d925..17a3df4d06 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -353,6 +353,21 @@ static inline hwaddr decode_basedisp_s(CPUS390XState *env, uint32_t ipb) /* Base/displacement are at the same locations. */ #define decode_basedisp_rs decode_basedisp_s +/* helper functions for run_on_cpu() */ +static inline void s390_do_cpu_reset(void *arg) +{ + CPUState *cs = arg; + S390CPUClass *scc = S390_CPU_GET_CLASS(cs); + + scc->cpu_reset(cs); +} +static inline void s390_do_cpu_full_reset(void *arg) +{ + CPUState *cs = arg; + + cpu_reset(cs); +} + void s390x_tod_timer(void *opaque); void s390x_cpu_timer(void *opaque); diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c index 0b625826ef..ef9758a96a 100644 --- a/target-s390x/misc_helper.c +++ b/target-s390x/misc_helper.c @@ -114,33 +114,16 @@ uint32_t HELPER(servc)(CPUS390XState *env, uint64_t r1, uint64_t r2) } #ifndef CONFIG_USER_ONLY -static void cpu_reset_all(void) -{ - CPUState *cs; - S390CPUClass *scc; - - CPU_FOREACH(cs) { - scc = S390_CPU_GET_CLASS(cs); - scc->cpu_reset(cs); - } -} - -static void cpu_full_reset_all(void) -{ - CPUState *cpu; - - CPU_FOREACH(cpu) { - cpu_reset(cpu); - } -} - static int modified_clear_reset(S390CPU *cpu) { S390CPUClass *scc = S390_CPU_GET_CLASS(cpu); + CPUState *t; pause_all_vcpus(); cpu_synchronize_all_states(); - cpu_full_reset_all(); + CPU_FOREACH(t) { + run_on_cpu(t, s390_do_cpu_full_reset, t); + } cmma_reset(cpu); io_subsystem_reset(); scc->load_normal(CPU(cpu)); @@ -152,10 +135,13 @@ static int modified_clear_reset(S390CPU *cpu) static int load_normal_reset(S390CPU *cpu) { S390CPUClass *scc = S390_CPU_GET_CLASS(cpu); + CPUState *t; pause_all_vcpus(); cpu_synchronize_all_states(); - cpu_reset_all(); + CPU_FOREACH(t) { + run_on_cpu(t, s390_do_cpu_reset, t); + } cmma_reset(cpu); io_subsystem_reset(); scc->initial_cpu_reset(CPU(cpu)); From 6e6ad8db11343ccd84934687efeb36937c20c363 Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Thu, 28 Aug 2014 13:58:50 +0200 Subject: [PATCH 02/19] s390x/kvm: execute sigp orders on the target vcpu thread All sigp orders that can result in ioctls on the target vcpu should be executed on the associated vcpu thread. Reviewed-by: Cornelia Huck Acked-by: Christian Borntraeger Signed-off-by: David Hildenbrand Signed-off-by: Jens Freimann Signed-off-by: Christian Borntraeger --- target-s390x/kvm.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index a32d91aa01..421ff436e4 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -916,23 +916,30 @@ static int handle_diag(S390CPU *cpu, struct kvm_run *run, uint32_t ipb) return r; } -static int kvm_s390_cpu_start(S390CPU *cpu) +static void sigp_cpu_start(void *arg) { + CPUState *cs = arg; + S390CPU *cpu = S390_CPU(cs); + s390_add_running_cpu(cpu); - qemu_cpu_kick(CPU(cpu)); DPRINTF("DONE: KVM cpu start: %p\n", &cpu->env); - return 0; } -int kvm_s390_cpu_restart(S390CPU *cpu) +static void sigp_cpu_restart(void *arg) { + CPUState *cs = arg; + S390CPU *cpu = S390_CPU(cs); struct kvm_s390_irq irq = { .type = KVM_S390_RESTART, }; kvm_s390_vcpu_interrupt(cpu, &irq); s390_add_running_cpu(cpu); - qemu_cpu_kick(CPU(cpu)); +} + +int kvm_s390_cpu_restart(S390CPU *cpu) +{ + run_on_cpu(CPU(cpu), sigp_cpu_restart, CPU(cpu)); DPRINTF("DONE: KVM cpu restart: %p\n", &cpu->env); return 0; } @@ -980,10 +987,12 @@ static int handle_sigp(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1) switch (order_code) { case SIGP_START: - cc = kvm_s390_cpu_start(target_cpu); + run_on_cpu(CPU(target_cpu), sigp_cpu_start, CPU(target_cpu)); + cc = 0; break; case SIGP_RESTART: - cc = kvm_s390_cpu_restart(target_cpu); + run_on_cpu(CPU(target_cpu), sigp_cpu_restart, CPU(target_cpu)); + cc = 0; break; case SIGP_SET_ARCH: *statusreg &= 0xffffffff00000000UL; From 1fad8b3be32c2e91acbd55f2b0af57ed0723b1bb Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Thu, 28 Aug 2014 13:58:51 +0200 Subject: [PATCH 03/19] s390x/kvm: execute "system reset" cpu resets on the vcpu thread Let's execute resets triggered by qemu system resets on the target vcpu thread. This will avoid synchronize_rcu's in the kernel. Reviewed-by: Cornelia Huck Acked-by: Christian Borntraeger Signed-off-by: David Hildenbrand Signed-off-by: Jens Freimann Signed-off-by: Christian Borntraeger --- target-s390x/cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target-s390x/cpu.c b/target-s390x/cpu.c index c3082b73c5..4633282764 100644 --- a/target-s390x/cpu.c +++ b/target-s390x/cpu.c @@ -165,7 +165,7 @@ static void s390_cpu_machine_reset_cb(void *opaque) { S390CPU *cpu = opaque; - cpu_reset(CPU(cpu)); + run_on_cpu(CPU(cpu), s390_do_cpu_full_reset, CPU(cpu)); } #endif From 159855f098489160df9cb13ce1667a4d6dd76895 Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Thu, 28 Aug 2014 13:58:52 +0200 Subject: [PATCH 04/19] s390x/kvm: execute the first cpu reset on the vcpu thread As all full cpu resets currently call into the kernel to do initial cpu reset, let's run this reset (triggered by cpu_s390x_init()) on the proper vcpu thread. Reviewed-by: Cornelia Huck Acked-by: Christian Borntraeger Signed-off-by: David Hildenbrand Signed-off-by: Jens Freimann Signed-off-by: Christian Borntraeger --- target-s390x/cpu.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/target-s390x/cpu.c b/target-s390x/cpu.c index 4633282764..505a2fa3da 100644 --- a/target-s390x/cpu.c +++ b/target-s390x/cpu.c @@ -175,7 +175,11 @@ static void s390_cpu_realizefn(DeviceState *dev, Error **errp) S390CPUClass *scc = S390_CPU_GET_CLASS(dev); qemu_init_vcpu(cs); +#if !defined(CONFIG_USER_ONLY) + run_on_cpu(cs, s390_do_cpu_full_reset, cs); +#else cpu_reset(cs); +#endif scc->parent_realize(dev, errp); } From 92cb05574b7bd489be81f9c58497dc7dfe5d8859 Mon Sep 17 00:00:00 2001 From: "Eugene (jno) Dvurechenski" Date: Fri, 29 Aug 2014 11:01:36 +0200 Subject: [PATCH 05/19] pc-bios/s390-ccw: support all virtio block size The block size value may be given "as is" OR as a base value and a shift count (exponent). So, we have to use calculation to get the proper number in the code. The main expression reads as (blk_cfg.blk_size << blk_cfg.physical_block_exp) E.g., various combinations between blk_size=1/physical_block_exp=12 and blk_size=4096/physical_block_exp=0 are valid for 4K blocks. Signed-off-by: Eugene (jno) Dvurechenski Acked-by: Christian Borntraeger Reviewed-by: David Hildenbrand Signed-off-by: Jens Freimann Signed-off-by: Christian Borntraeger --- pc-bios/s390-ccw/virtio.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c index 31b23b086c..04977e4ab8 100644 --- a/pc-bios/s390-ccw/virtio.c +++ b/pc-bios/s390-ccw/virtio.c @@ -275,12 +275,14 @@ void virtio_assume_scsi(void) { guessed_disk_nature = true; blk_cfg.blk_size = 512; + blk_cfg.physical_block_exp = 0; } void virtio_assume_eckd(void) { guessed_disk_nature = true; blk_cfg.blk_size = 4096; + blk_cfg.physical_block_exp = 0; /* this must be here to calculate code segment position */ blk_cfg.geometry.heads = 15; @@ -290,31 +292,31 @@ void virtio_assume_eckd(void) bool virtio_disk_is_scsi(void) { if (guessed_disk_nature) { - return (blk_cfg.blk_size == 512); + return (virtio_get_block_size() == 512); } return (blk_cfg.geometry.heads == 255) && (blk_cfg.geometry.sectors == 63) - && (blk_cfg.blk_size == 512); + && (virtio_get_block_size() == 512); } bool virtio_disk_is_eckd(void) { if (guessed_disk_nature) { - return (blk_cfg.blk_size == 4096); + return (virtio_get_block_size() == 4096); } return (blk_cfg.geometry.heads == 15) && (blk_cfg.geometry.sectors == 12) - && (blk_cfg.blk_size == 4096); + && (virtio_get_block_size() == 4096); } bool virtio_ipl_disk_is_valid(void) { - return blk_cfg.blk_size && (virtio_disk_is_scsi() || virtio_disk_is_eckd()); + return virtio_disk_is_scsi() || virtio_disk_is_eckd(); } int virtio_get_block_size(void) { - return blk_cfg.blk_size; + return blk_cfg.blk_size << blk_cfg.physical_block_exp; } uint16_t virtio_get_cylinders(void) From 00a47e7e71a2fbceb4ec565593738b0b3f06a42b Mon Sep 17 00:00:00 2001 From: "Eugene (jno) Dvurechenski" Date: Fri, 29 Aug 2014 11:01:37 +0200 Subject: [PATCH 06/19] pc-bios/s390-ccw: handle more ECKD DASD block sizes Using dasdfmt(8) to format a DASD allows to choose a block size. There are four supported values: 512, 1024, 2048, and 4096 bytes per block. Each block size leads to selection of new count of sectors per track. The head count remains always the same: 15. This empiric knowledge is used to detect ECKD DASD to IPL from. Signed-off-by: Eugene (jno) Dvurechenski Reviewed-by: David Hildenbrand Acked-by: Christian Borntraeger Signed-off-by: Jens Freimann Signed-off-by: Christian Borntraeger --- pc-bios/s390-ccw/virtio.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c index 04977e4ab8..6ed3dc9cc2 100644 --- a/pc-bios/s390-ccw/virtio.c +++ b/pc-bios/s390-ccw/virtio.c @@ -299,14 +299,35 @@ bool virtio_disk_is_scsi(void) && (virtio_get_block_size() == 512); } +/* + * Other supported value pairs, if any, would need to be added here. + * Note: head count is always 15. + */ +static inline u8 virtio_eckd_sectors_for_block_size(int size) +{ + switch (size) { + case 512: + return 49; + case 1024: + return 33; + case 2048: + return 21; + case 4096: + return 12; + } + return 0; +} + bool virtio_disk_is_eckd(void) { + const int block_size = virtio_get_block_size(); + if (guessed_disk_nature) { - return (virtio_get_block_size() == 4096); + return (block_size == 4096); } return (blk_cfg.geometry.heads == 15) - && (blk_cfg.geometry.sectors == 12) - && (virtio_get_block_size() == 4096); + && (blk_cfg.geometry.sectors == + virtio_eckd_sectors_for_block_size(block_size)); } bool virtio_ipl_disk_is_valid(void) From b0885f7599739ed1d7002774f9be2ba1f8212cc7 Mon Sep 17 00:00:00 2001 From: "Eugene (jno) Dvurechenski" Date: Fri, 29 Aug 2014 11:01:38 +0200 Subject: [PATCH 07/19] pc-bios/s390-ccw Improve ECKD informational message Add block size display to ECKD scheme report. Signed-off-by: Eugene (jno) Dvurechenski Reviewed-by: David Hildenbrand Acked-by: Christian Borntraeger Acked-by: Cornelia Huck Signed-off-by: Jens Freimann Signed-off-by: Christian Borntraeger --- pc-bios/s390-ccw/bootmap.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c index f1756796df..e4352b16cd 100644 --- a/pc-bios/s390-ccw/bootmap.c +++ b/pc-bios/s390-ccw/bootmap.c @@ -298,6 +298,25 @@ static void ipl_eckd(ECKD_IPL_mode_t mode) } } +static void print_eckd_msg(void) +{ + char msg[] = "Using ECKD scheme (block size *****), "; + char *p = &msg[34], *q = &msg[30]; + int n = virtio_get_block_size(); + + /* Fill in the block size and show up the message */ + if (n > 0 && n <= 99999) { + while (n) { + *p-- = '0' + (n % 10); + n /= 10; + } + while (p >= q) { + *p-- = ' '; + } + } + sclp_print(msg); +} + /*********************************************************************** * IPL a SCSI disk */ @@ -447,12 +466,11 @@ void zipl_load(void) } /* We have failed to follow the SCSI scheme, so */ - sclp_print("Using ECKD scheme.\n"); if (virtio_guessed_disk_nature()) { sclp_print("Using guessed DASD geometry.\n"); virtio_assume_eckd(); } - + print_eckd_msg(); if (magic_match(mbr->magic, IPL1_MAGIC)) { ipl_eckd(ECKD_CDL); /* no return */ } From f04db28b86654d1c7ff805b40eff27bba6b0f686 Mon Sep 17 00:00:00 2001 From: "Eugene (jno) Dvurechenski" Date: Fri, 29 Aug 2014 11:01:39 +0200 Subject: [PATCH 08/19] pc-bios/s390-ccw Really big EAV ECKD DASD handling For EAV ECKD DASD, the cylinder count will have the magic value 0xfffeU. Therefore, use the block number to test for valid eckd addresses instead. Signed-off-by: Eugene (jno) Dvurechenski Acked-by: Cornelia Huck Acked-by: Christian Borntraeger Reviewed-by: David Hildenbrand Signed-off-by: Jens Freimann Signed-off-by: Christian Borntraeger --- pc-bios/s390-ccw/bootmap.c | 37 ++++++++++++++++++------------------- pc-bios/s390-ccw/virtio.c | 11 ++++++----- pc-bios/s390-ccw/virtio.h | 2 +- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c index e4352b16cd..d4c579c245 100644 --- a/pc-bios/s390-ccw/bootmap.c +++ b/pc-bios/s390-ccw/bootmap.c @@ -93,25 +93,6 @@ static inline void verify_boot_info(BootInfo *bip) "Bad block size in zIPL section of the 1st record."); } -static bool eckd_valid_address(BootMapPointer *p) -{ - const uint64_t cylinder = p->eckd.cylinder - + ((p->eckd.head & 0xfff0) << 12); - const uint64_t head = p->eckd.head & 0x000f; - - if (head >= virtio_get_heads() - || p->eckd.sector > virtio_get_sectors() - || p->eckd.sector <= 0) { - return false; - } - - if (!virtio_guessed_disk_nature() && cylinder >= virtio_get_cylinders()) { - return false; - } - - return true; -} - static block_number_t eckd_block_num(BootMapPointer *p) { const uint64_t sectors = virtio_get_sectors(); @@ -126,6 +107,24 @@ static block_number_t eckd_block_num(BootMapPointer *p) return block; } +static bool eckd_valid_address(BootMapPointer *p) +{ + const uint64_t head = p->eckd.head & 0x000f; + + if (head >= virtio_get_heads() + || p->eckd.sector > virtio_get_sectors() + || p->eckd.sector <= 0) { + return false; + } + + if (!virtio_guessed_disk_nature() && + eckd_block_num(p) >= virtio_get_blocks()) { + return false; + } + + return true; +} + static block_number_t load_eckd_segments(block_number_t blk, uint64_t *address) { block_number_t block_nr; diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c index 6ed3dc9cc2..c0540d1cd4 100644 --- a/pc-bios/s390-ccw/virtio.c +++ b/pc-bios/s390-ccw/virtio.c @@ -340,11 +340,6 @@ int virtio_get_block_size(void) return blk_cfg.blk_size << blk_cfg.physical_block_exp; } -uint16_t virtio_get_cylinders(void) -{ - return blk_cfg.geometry.cylinders; -} - uint8_t virtio_get_heads(void) { return blk_cfg.geometry.heads; @@ -355,6 +350,12 @@ uint8_t virtio_get_sectors(void) return blk_cfg.geometry.sectors; } +uint64_t virtio_get_blocks(void) +{ + return blk_cfg.capacity / + (virtio_get_block_size() / VIRTIO_SECTOR_SIZE); +} + void virtio_setup_block(struct subchannel_id schid) { struct vq_info_block info; diff --git a/pc-bios/s390-ccw/virtio.h b/pc-bios/s390-ccw/virtio.h index f1fb1b08fa..c23466b8db 100644 --- a/pc-bios/s390-ccw/virtio.h +++ b/pc-bios/s390-ccw/virtio.h @@ -192,9 +192,9 @@ extern bool virtio_disk_is_scsi(void); extern bool virtio_disk_is_eckd(void); extern bool virtio_ipl_disk_is_valid(void); extern int virtio_get_block_size(void); -extern uint16_t virtio_get_cylinders(void); extern uint8_t virtio_get_heads(void); extern uint8_t virtio_get_sectors(void); +extern uint64_t virtio_get_blocks(void); extern int virtio_read_many(ulong sector, void *load_addr, int sec_num); #define VIRTIO_SECTOR_SIZE 512 From 14f56a2e359df01faff986ea6c8c07be7de49501 Mon Sep 17 00:00:00 2001 From: "Eugene (jno) Dvurechenski" Date: Fri, 29 Aug 2014 11:01:40 +0200 Subject: [PATCH 09/19] pc-bios/s390-ccw: IPL from DASD with format variations There are two known cases of DASD format where signatures are incomplete or absent: 1. result of (ECKD_LDL_UNLABELED) 2. CDL with zero keys in IPL1 and IPL2 records Now the code attempts to 1. find zIPL and use SCSI layout 2. find IPL1 and use CDL layout 3. find CMS1 and use LDL layout 3. find LNX1 and use LDL layout 4. find zIPL and use unlabeled LDL layout 5. find zIPL and use CDL layout 6. die in this sequence. Signed-off-by: Eugene (jno) Dvurechenski Acked-by: Cornelia Huck Acked-by: Christian Borntraeger Reviewed-by: David Hildenbrand Signed-off-by: Jens Freimann Signed-off-by: Christian Borntraeger --- pc-bios/s390-ccw/bootmap.c | 52 +++++++++++++++++++++----------------- pc-bios/s390-ccw/bootmap.h | 2 +- 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c index d4c579c245..aa1cf802be 100644 --- a/pc-bios/s390-ccw/bootmap.c +++ b/pc-bios/s390-ccw/bootmap.c @@ -222,7 +222,6 @@ static void ipl_eckd_cdl(void) memset(sec, FREE_SPACE_FILLER, sizeof(sec)); read_block(1, ipl2, "Cannot read IPL2 record at block 1"); - IPL_assert(magic_match(ipl2, IPL2_MAGIC), "No IPL2 record"); mbr = &ipl2->u.x.mbr; IPL_assert(magic_match(mbr, ZIPL_MAGIC), "No zIPL section in IPL2 record."); @@ -246,12 +245,10 @@ static void ipl_eckd_cdl(void) /* no return */ } -static void ipl_eckd_ldl(ECKD_IPL_mode_t mode) +static void print_eckd_ldl_msg(ECKD_IPL_mode_t mode) { LDL_VTOC *vlbl = (void *)sec; /* already read, 3rd block */ char msg[4] = { '?', '.', '\n', '\0' }; - block_number_t block_nr; - BootInfo *bip; sclp_print((mode == ECKD_CMS) ? "CMS" : "LDL"); sclp_print(" version "); @@ -271,12 +268,27 @@ static void ipl_eckd_ldl(ECKD_IPL_mode_t mode) } sclp_print(msg); print_volser(vlbl->volser); +} + +static void ipl_eckd_ldl(ECKD_IPL_mode_t mode) +{ + block_number_t block_nr; + BootInfo *bip = (void *)(sec + 0x70); /* BootInfo is MBR for LDL */ + + if (mode != ECKD_LDL_UNLABELED) { + print_eckd_ldl_msg(mode); + } /* DO NOT read BootMap pointer (only one, xECKD) at block #2 */ memset(sec, FREE_SPACE_FILLER, sizeof(sec)); - read_block(0, sec, "Cannot read block 0"); - bip = (void *)(sec + 0x70); /* "boot info" is "eckd mbr" for LDL */ + read_block(0, sec, "Cannot read block 0 to grab boot info."); + if (mode == ECKD_LDL_UNLABELED) { + if (!magic_match(bip->magic, ZIPL_MAGIC)) { + return; /* not applicable layout */ + } + sclp_print("unlabeled LDL.\n"); + } verify_boot_info(bip); block_nr = eckd_block_num((void *)&(bip->bp.ipl.bm_ptr.eckd.bptr)); @@ -284,19 +296,6 @@ static void ipl_eckd_ldl(ECKD_IPL_mode_t mode) /* no return */ } -static void ipl_eckd(ECKD_IPL_mode_t mode) -{ - switch (mode) { - case ECKD_CDL: - ipl_eckd_cdl(); /* no return */ - case ECKD_CMS: - case ECKD_LDL: - ipl_eckd_ldl(mode); /* no return */ - default: - virtio_panic("\n! Unknown ECKD IPL mode !\n"); - } -} - static void print_eckd_msg(void) { char msg[] = "Using ECKD scheme (block size *****), "; @@ -471,7 +470,7 @@ void zipl_load(void) } print_eckd_msg(); if (magic_match(mbr->magic, IPL1_MAGIC)) { - ipl_eckd(ECKD_CDL); /* no return */ + ipl_eckd_cdl(); /* no return */ } /* LDL/CMS? */ @@ -479,11 +478,18 @@ void zipl_load(void) read_block(2, vlbl, "Cannot read block 2"); if (magic_match(vlbl->magic, CMS1_MAGIC)) { - ipl_eckd(ECKD_CMS); /* no return */ + ipl_eckd_ldl(ECKD_CMS); /* no return */ } if (magic_match(vlbl->magic, LNX1_MAGIC)) { - ipl_eckd(ECKD_LDL); /* no return */ + ipl_eckd_ldl(ECKD_LDL); /* no return */ } - virtio_panic("\n* invalid MBR magic *\n"); + ipl_eckd_ldl(ECKD_LDL_UNLABELED); /* it still may return */ + /* + * Ok, it is not a LDL by any means. + * It still might be a CDL with zero record keys for IPL1 and IPL2 + */ + ipl_eckd_cdl(); + + virtio_panic("\n* this can never happen *\n"); } diff --git a/pc-bios/s390-ccw/bootmap.h b/pc-bios/s390-ccw/bootmap.h index 30ef22fe61..6a4823d544 100644 --- a/pc-bios/s390-ccw/bootmap.h +++ b/pc-bios/s390-ccw/bootmap.h @@ -257,9 +257,9 @@ typedef struct IplVolumeLabel { typedef enum { ECKD_NO_IPL, - ECKD_CDL, ECKD_CMS, ECKD_LDL, + ECKD_LDL_UNLABELED, } ECKD_IPL_mode_t; /* utility code below */ From 1aa7f4c6aa55604b3924a08d5527f124460f6acf Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Fri, 29 Aug 2014 11:01:41 +0200 Subject: [PATCH 10/19] pc-bios/s390-ccw: Do proper console setup The final newline/return must happen before we reset the sclp via diag 308. Signed-off-by: Christian Borntraeger Reviewed-by: David Hildenbrand Acked-by: Cornelia Huck Signed-off-by: Jens Freimann Signed-off-by: Christian Borntraeger --- pc-bios/s390-ccw/bootmap.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c index aa1cf802be..115d8bbac6 100644 --- a/pc-bios/s390-ccw/bootmap.c +++ b/pc-bios/s390-ccw/bootmap.c @@ -40,11 +40,6 @@ static void jump_to_IPL_2(void) ResetInfo *current = 0; void (*ipl)(void) = (void *) (uint64_t) current->ipl_continue; - debug_print_addr("set IPL addr to", ipl); - - /* Ensure the guest output starts fresh */ - sclp_print("\n"); - *current = save; ipl(); /* should not return */ } @@ -64,6 +59,11 @@ static void jump_to_IPL_code(uint64_t address) current->ipl_addr = (uint32_t) (uint64_t) &jump_to_IPL_2; current->ipl_continue = address & 0x7fffffff; + debug_print_int("set IPL addr to", current->ipl_continue); + + /* Ensure the guest output starts fresh */ + sclp_print("\n"); + /* * HACK ALERT. * We use the load normal reset to keep r15 unchanged. jump_to_IPL_2 From f3602219884127c6f15958148c540302db5cf77b Mon Sep 17 00:00:00 2001 From: "Eugene (jno) Dvurechenski" Date: Fri, 29 Aug 2014 11:01:42 +0200 Subject: [PATCH 11/19] pc-bios/s390-ccw.img binary update Rebuild of s390-ccw.img containing these patches: pc-bios/s390-ccw: Do proper console setup pc-bios/s390-ccw: support all virtio block size pc-bios/s390-ccw: handle more ECKD DASD block sizes pc-bios/s390-ccw Improve ECKD informational message pc-bios/s390-ccw Really big EAV ECKD DASD handling pc-bios/s390-ccw: IPL from DASD with format variations Signed-off-by: Jens Freimann Signed-off-by: Christian Borntraeger --- pc-bios/s390-ccw.img | Bin 17752 -> 17752 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/pc-bios/s390-ccw.img b/pc-bios/s390-ccw.img index e3ea0d5664f01ff472d3531980941fb5f163ff02..44873ad1817f44a5610ea556f86394b2c4a4c1ff 100644 GIT binary patch literal 17752 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 literal 17752 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 From 0844df77fdf9cd115a3b8f414333d41b3a88bc9d Mon Sep 17 00:00:00 2001 From: Matthew Rosato Date: Thu, 28 Aug 2014 11:25:32 -0400 Subject: [PATCH 12/19] sclp-s390: Add device to manage s390 memory hotplug Add sclpMemoryHotplugDev to contain associated data structures, etc. Signed-off-by: Matthew Rosato Signed-off-by: Christian Borntraeger --- hw/s390x/sclp.c | 30 ++++++++++++++++++++++++++++++ include/hw/s390x/sclp.h | 20 ++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c index d8ddf35e58..769d7c346f 100644 --- a/hw/s390x/sclp.c +++ b/hw/s390x/sclp.c @@ -183,3 +183,33 @@ void s390_sclp_init(void) OBJECT(dev), NULL); qdev_init_nofail(dev); } + +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)); +} + +static TypeInfo sclp_memory_hotplug_dev_info = { + .name = TYPE_SCLP_MEMORY_HOTPLUG_DEV, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(sclpMemoryHotplugDev), +}; + +static void register_types(void) +{ + type_register_static(&sclp_memory_hotplug_dev_info); +} +type_init(register_types); diff --git a/include/hw/s390x/sclp.h b/include/hw/s390x/sclp.h index 7ef16226df..5c435749e1 100644 --- a/include/hw/s390x/sclp.h +++ b/include/hw/s390x/sclp.h @@ -37,6 +37,7 @@ #define SCLP_STARTING_SUBINCREMENT_ID 0x10001 #define SCLP_INCREMENT_UNIT 0x10000 #define MAX_AVAIL_SLOTS 32 +#define MAX_STORAGE_INCREMENTS 1020 /* CPU hotplug SCLP codes */ #define SCLP_HAS_CPU_INFO 0x0C00000000000000ULL @@ -156,6 +157,23 @@ typedef struct SCCB { char data[SCCB_DATA_LEN]; } QEMU_PACKED SCCB; +typedef struct sclpMemoryHotplugDev sclpMemoryHotplugDev; + +#define TYPE_SCLP_MEMORY_HOTPLUG_DEV "sclp-memory-hotplug-dev" +#define SCLP_MEMORY_HOTPLUG_DEV(obj) \ + OBJECT_CHECK(sclpMemoryHotplugDev, (obj), TYPE_SCLP_MEMORY_HOTPLUG_DEV) + +struct sclpMemoryHotplugDev { + SysBusDevice parent; + ram_addr_t standby_mem_size; + ram_addr_t padded_ram_size; + ram_addr_t pad_size; + ram_addr_t standby_subregion_size; + ram_addr_t rzm; + int increment_size; + char *standby_state_map; +}; + static inline int sccb_data_len(SCCB *sccb) { return be16_to_cpu(sccb->h.length) - sizeof(sccb->h); @@ -163,6 +181,8 @@ static inline int sccb_data_len(SCCB *sccb) void s390_sclp_init(void); +sclpMemoryHotplugDev *init_sclp_memory_hotplug_dev(void); +sclpMemoryHotplugDev *get_sclp_memory_hotplug_dev(void); void sclp_service_interrupt(uint32_t sccb); void raise_irq_cpu_hotplug(void); From b6fe01248e66a3c1b1b22a9cd640bfa86d4c358c Mon Sep 17 00:00:00 2001 From: Matthew Rosato Date: Thu, 28 Aug 2014 11:25:33 -0400 Subject: [PATCH 13/19] virtio-ccw: Include standby memory when calculating storage increment When determining the memory increment size, use the maxmem size if it was specified. Signed-off-by: Matthew Rosato Signed-off-by: Christian Borntraeger --- hw/s390x/s390-virtio-ccw.c | 44 ++++++++++++++++++++++++++++++++------ qemu-options.hx | 3 ++- target-s390x/cpu.h | 3 +++ 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index 004b2c20c5..e538b1f686 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -17,6 +17,7 @@ #include "ioinst.h" #include "css.h" #include "virtio-ccw.h" +#include "qemu/config-file.h" #define TYPE_S390_CCW_MACHINE "s390-ccw-machine" @@ -86,17 +87,35 @@ static void ccw_init(MachineState *machine) ram_addr_t my_ram_size = machine->ram_size; MemoryRegion *sysmem = get_system_memory(); MemoryRegion *ram = g_new(MemoryRegion, 1); - int shift = 0; + sclpMemoryHotplugDev *mhd = init_sclp_memory_hotplug_dev(); uint8_t *storage_keys; int ret; VirtualCssBus *css_bus; + QemuOpts *opts = qemu_opts_find(qemu_find_opts("memory"), NULL); + ram_addr_t pad_size = 0; + ram_addr_t maxmem = qemu_opt_get_size(opts, "maxmem", my_ram_size); + ram_addr_t standby_mem_size = maxmem - my_ram_size; - /* s390x ram size detection needs a 16bit multiplier + an increment. So - guests > 64GB can be specified in 2MB steps etc. */ - while ((my_ram_size >> (20 + shift)) > 65535) { - shift++; + /* 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 'mhd->increment_size' is an exponent of 2 that can be + * used to calculate the size (in bytes) of an increment. */ + mhd->increment_size = 20; + while ((my_ram_size >> mhd->increment_size) > MAX_STORAGE_INCREMENTS) { + mhd->increment_size++; } - my_ram_size = my_ram_size >> (20 + shift) << (20 + shift); + while ((standby_mem_size >> mhd->increment_size) > MAX_STORAGE_INCREMENTS) { + mhd->increment_size++; + } + + /* 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. */ + standby_mem_size = standby_mem_size >> mhd->increment_size + << mhd->increment_size; + my_ram_size = my_ram_size >> mhd->increment_size + << mhd->increment_size; /* let's propagate the changed ram size into the global variable. */ ram_size = my_ram_size; @@ -111,11 +130,22 @@ static void ccw_init(MachineState *machine) /* register hypercalls */ virtio_ccw_register_hcalls(); - /* allocate RAM */ + /* allocate RAM for core */ memory_region_init_ram(ram, NULL, "s390.ram", my_ram_size); vmstate_register_ram_global(ram); memory_region_add_subregion(sysmem, 0, ram); + /* If the size of ram is not on a MEM_SECTION_SIZE boundary, + calculate the pad size necessary to force this boundary. */ + if (standby_mem_size) { + if (my_ram_size % MEM_SECTION_SIZE) { + pad_size = MEM_SECTION_SIZE - my_ram_size % MEM_SECTION_SIZE; + } + my_ram_size += standby_mem_size + pad_size; + mhd->pad_size = pad_size; + mhd->standby_mem_size = standby_mem_size; + } + /* allocate storage keys */ storage_keys = g_malloc0(my_ram_size / TARGET_PAGE_SIZE); diff --git a/qemu-options.hx b/qemu-options.hx index c573dd8893..98289520ec 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -225,7 +225,8 @@ DEF("m", HAS_ARG, QEMU_OPTION_m, " size: initial amount of guest memory (default: " stringify(DEFAULT_RAM_SIZE) "MiB)\n" " slots: number of hotplug slots (default: none)\n" - " maxmem: maximum amount of guest memory (default: none)\n", + " maxmem: maximum amount of guest memory (default: none)\n" + "NOTE: Some architectures might enforce a specific granularity\n", QEMU_ARCH_ALL) STEXI @item -m [size=]@var{megs} diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index 17a3df4d06..f2715c6e72 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -1060,6 +1060,9 @@ static inline void cpu_inject_crw_mchk(S390CPU *cpu) cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD); } +/* from s390-virtio-ccw */ +#define MEM_SECTION_SIZE 0x10000000UL + /* fpu_helper.c */ uint32_t set_cc_nz_f32(float32 v); uint32_t set_cc_nz_f64(float64 v); From e7f1314f97a8e9e035100e9aa4e9613f245fb00c Mon Sep 17 00:00:00 2001 From: Matthew Rosato Date: Thu, 28 Aug 2014 11:25:34 -0400 Subject: [PATCH 14/19] s390-virtio: Apply same memory boundaries as virtio-ccw Although s390-virtio won't support memory hotplug, it should enforce the same memory boundaries so that it can use shared codepaths (like read_SCP_info). Signed-off-by: Matthew Rosato Signed-off-by: Christian Borntraeger --- hw/s390x/s390-virtio.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/hw/s390x/s390-virtio.c b/hw/s390x/s390-virtio.c index 1a75a1cf81..4ca52b7190 100644 --- a/hw/s390x/s390-virtio.c +++ b/hw/s390x/s390-virtio.c @@ -230,18 +230,21 @@ static void s390_init(MachineState *machine) ram_addr_t my_ram_size = machine->ram_size; MemoryRegion *sysmem = get_system_memory(); MemoryRegion *ram = g_new(MemoryRegion, 1); - int shift = 0; + int increment_size = 20; uint8_t *storage_keys; void *virtio_region; hwaddr virtio_region_len; hwaddr virtio_region_start; - /* s390x ram size detection needs a 16bit multiplier + an increment. So - guests > 64GB can be specified in 2MB steps etc. */ - while ((my_ram_size >> (20 + shift)) > 65535) { - shift++; + /* + * 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. + */ + while ((my_ram_size >> increment_size) > MAX_STORAGE_INCREMENTS) { + increment_size++; } - my_ram_size = my_ram_size >> (20 + shift) << (20 + shift); + my_ram_size = my_ram_size >> increment_size << increment_size; /* let's propagate the changed ram size into the global variable. */ ram_size = my_ram_size; From 1def6656b61c65757a02beb0318249e0b1c4e634 Mon Sep 17 00:00:00 2001 From: Matthew Rosato Date: Thu, 28 Aug 2014 11:25:35 -0400 Subject: [PATCH 15/19] sclp-s390: Add memory hotplug SCLPs Add memory information to read SCP info and add handlers for Read Storage Element Information, Attach Storage Element, Assign Storage and Unassign Storage. Signed-off-by: Matthew Rosato Signed-off-by: Christian Borntraeger --- hw/s390x/sclp.c | 259 +++++++++++++++++++++++++++++++++++++++++++-- target-s390x/cpu.h | 15 +++ target-s390x/kvm.c | 5 + 3 files changed, 273 insertions(+), 6 deletions(-) diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c index 769d7c346f..02b3275132 100644 --- a/hw/s390x/sclp.c +++ b/hw/s390x/sclp.c @@ -16,7 +16,8 @@ #include "sysemu/kvm.h" #include "exec/memory.h" #include "sysemu/sysemu.h" - +#include "exec/address-spaces.h" +#include "qemu/config-file.h" #include "hw/s390x/sclp.h" #include "hw/s390x/event-facility.h" @@ -33,10 +34,19 @@ static inline SCLPEventFacility *get_event_facility(void) static void read_SCP_info(SCCB *sccb) { ReadInfo *read_info = (ReadInfo *) sccb; + sclpMemoryHotplugDev *mhd = get_sclp_memory_hotplug_dev(); CPUState *cpu; - int shift = 0; int cpu_count = 0; int i = 0; + int increment_size = 20; + int rnsize, rnmax; + QemuOpts *opts = qemu_opts_find(qemu_find_opts("memory"), NULL); + int slots = qemu_opt_get_number(opts, "slots", 0); + int max_avail_slots = s390_get_memslot_count(kvm_state); + + if (slots > max_avail_slots) { + slots = max_avail_slots; + } CPU_FOREACH(cpu) { cpu_count++; @@ -54,14 +64,235 @@ static void read_SCP_info(SCCB *sccb) read_info->facilities = cpu_to_be64(SCLP_HAS_CPU_INFO); - while ((ram_size >> (20 + shift)) > 65535) { - shift++; + /* + * 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. + */ + while ((ram_size >> increment_size) > MAX_STORAGE_INCREMENTS) { + increment_size++; } - read_info->rnmax = cpu_to_be16(ram_size >> (20 + shift)); - read_info->rnsize = 1 << shift; + rnmax = ram_size >> increment_size; + + /* Memory Hotplug is only supported for the ccw machine type */ + if (mhd) { + while ((mhd->standby_mem_size >> increment_size) > + MAX_STORAGE_INCREMENTS) { + increment_size++; + } + assert(increment_size == mhd->increment_size); + + 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; + rnmax = ((ram_size + mhd->standby_mem_size + mhd->pad_size) + >> mhd->increment_size); + + read_info->facilities |= cpu_to_be64(SCLP_FC_ASSIGN_ATTACH_READ_STOR); + } + + rnsize = 1 << (increment_size - 20); + if (rnsize <= 128) { + read_info->rnsize = rnsize; + } else { + read_info->rnsize = 0; + read_info->rnsize2 = cpu_to_be32(rnsize); + } + + 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); + } + sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_READ_COMPLETION); } +static void read_storage_element0_info(SCCB *sccb) +{ + int i, assigned; + int subincrement_id = SCLP_STARTING_SUBINCREMENT_ID; + ReadStorageElementInfo *storage_info = (ReadStorageElementInfo *) sccb; + sclpMemoryHotplugDev *mhd = get_sclp_memory_hotplug_dev(); + + assert(mhd); + + 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; + } + sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_READ_COMPLETION); +} + +static void read_storage_element1_info(SCCB *sccb) +{ + ReadStorageElementInfo *storage_info = (ReadStorageElementInfo *) sccb; + sclpMemoryHotplugDev *mhd = get_sclp_memory_hotplug_dev(); + + assert(mhd); + + 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); +} + +static void attach_storage_element(SCCB *sccb, uint16_t element) +{ + int i, assigned, subincrement_id; + AttachStorageElement *attach_info = (AttachStorageElement *) sccb; + sclpMemoryHotplugDev *mhd = get_sclp_memory_hotplug_dev(); + + assert(mhd); + + 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); +} + +static void assign_storage(SCCB *sccb) +{ + MemoryRegion *mr = NULL; + uint64_t this_subregion_size; + AssignStorage *assign_info = (AssignStorage *) sccb; + sclpMemoryHotplugDev *mhd = get_sclp_memory_hotplug_dev(); + assert(mhd); + ram_addr_t assign_addr = (assign_info->rn - 1) * mhd->rzm; + MemoryRegion *sysmem = get_system_memory(); + + 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; + 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; + } + + memory_region_init_ram(standby_ram, NULL, id, this_subregion_size); + vmstate_register_ram_global(standby_ram); + 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); +} + +static void unassign_storage(SCCB *sccb) +{ + MemoryRegion *mr = NULL; + AssignStorage *assign_info = (AssignStorage *) sccb; + sclpMemoryHotplugDev *mhd = get_sclp_memory_hotplug_dev(); + assert(mhd); + ram_addr_t unassign_addr = (assign_info->rn - 1) * mhd->rzm; + MemoryRegion *sysmem = get_system_memory(); + + /* 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; + 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); + object_unparent(OBJECT(mr)); + g_free(mr); + } + } + } + sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_COMPLETION); +} + /* Provide information about the CPU */ static void sclp_read_cpu_info(SCCB *sccb) { @@ -103,6 +334,22 @@ static void sclp_execute(SCCB *sccb, uint32_t code) case SCLP_CMDW_READ_CPU_INFO: sclp_read_cpu_info(sccb); break; + case SCLP_READ_STORAGE_ELEMENT_INFO: + if (code & 0xff00) { + read_storage_element1_info(sccb); + } else { + read_storage_element0_info(sccb); + } + break; + case SCLP_ATTACH_STORAGE_ELEMENT: + attach_storage_element(sccb, (code & 0xff00) >> 8); + break; + case SCLP_ASSIGN_STORAGE: + assign_storage(sccb); + break; + case SCLP_UNASSIGN_STORAGE: + unassign_storage(sccb); + break; default: efc->command_handler(ef, sccb, code); break; diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index f2715c6e72..772d513c01 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -1062,6 +1062,7 @@ static inline void cpu_inject_crw_mchk(S390CPU *cpu) /* from s390-virtio-ccw */ #define MEM_SECTION_SIZE 0x10000000UL +#define MAX_AVAIL_SLOTS 32 /* fpu_helper.c */ uint32_t set_cc_nz_f32(float32 v); @@ -1085,6 +1086,7 @@ void kvm_s390_enable_css_support(S390CPU *cpu); int kvm_s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch, int vq, bool assign); int kvm_s390_cpu_restart(S390CPU *cpu); +int kvm_s390_get_memslot_count(KVMState *s); void kvm_s390_clear_cmma_callback(void *opaque); #else static inline void kvm_s390_io_interrupt(uint16_t subchannel_id, @@ -1112,6 +1114,10 @@ static inline int kvm_s390_cpu_restart(S390CPU *cpu) static inline void kvm_s390_clear_cmma_callback(void *opaque) { } +static inline int kvm_s390_get_memslot_count(KVMState *s) +{ + return MAX_AVAIL_SLOTS; +} #endif static inline void cmma_reset(S390CPU *cpu) @@ -1130,6 +1136,15 @@ static inline int s390_cpu_restart(S390CPU *cpu) return -ENOSYS; } +static inline int s390_get_memslot_count(KVMState *s) +{ + if (kvm_enabled()) { + return kvm_s390_get_memslot_count(s); + } else { + return MAX_AVAIL_SLOTS; + } +} + void s390_io_interrupt(uint16_t subchannel_id, uint16_t subchannel_nr, uint32_t io_int_parm, uint32_t io_int_word); void s390_crw_mchk(void); diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index 421ff436e4..a85a480c6a 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -1315,3 +1315,8 @@ int kvm_s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch, } return kvm_vm_ioctl(kvm_state, KVM_IOEVENTFD, &kick); } + +int kvm_s390_get_memslot_count(KVMState *s) +{ + return kvm_check_extension(s, KVM_CAP_NR_MEMSLOTS); +} From 97fa52f0971bf503c424d69f9d5db89ce9c3b717 Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Fri, 29 Aug 2014 15:52:14 +0200 Subject: [PATCH 16/19] s390x/gdb: don't touch the cc if tcg is not enabled When reading/writing the psw mask, the condition code may only be touched if running on tcg. Signed-off-by: David Hildenbrand Signed-off-by: Jens Freimann Signed-off-by: Christian Borntraeger --- target-s390x/gdbstub.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/target-s390x/gdbstub.c b/target-s390x/gdbstub.c index a129742e2f..8d55006706 100644 --- a/target-s390x/gdbstub.c +++ b/target-s390x/gdbstub.c @@ -31,9 +31,13 @@ int s390_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n) switch (n) { case S390_PSWM_REGNUM: - cc_op = calc_cc(env, env->cc_op, env->cc_src, env->cc_dst, env->cc_vr); - val = deposit64(env->psw.mask, 44, 2, cc_op); - return gdb_get_regl(mem_buf, val); + if (tcg_enabled()) { + cc_op = calc_cc(env, env->cc_op, env->cc_src, env->cc_dst, + env->cc_vr); + val = deposit64(env->psw.mask, 44, 2, cc_op); + return gdb_get_regl(mem_buf, val); + } + return gdb_get_regl(mem_buf, env->psw.mask); case S390_PSWA_REGNUM: return gdb_get_regl(mem_buf, env->psw.addr); case S390_R0_REGNUM ... S390_R15_REGNUM: @@ -62,7 +66,9 @@ int s390_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) switch (n) { case S390_PSWM_REGNUM: env->psw.mask = tmpl; - env->cc_op = extract64(tmpl, 44, 2); + if (tcg_enabled()) { + env->cc_op = extract64(tmpl, 44, 2); + } break; case S390_PSWA_REGNUM: env->psw.addr = tmpl; From 6117afac348c8e94ca02c9b5ff68c9f0abcfdb85 Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Fri, 29 Aug 2014 15:52:15 +0200 Subject: [PATCH 17/19] s390x/gdb: add the feature xml files for s390x This patch adds the relevant s390x feature xml files taken from gdb. Signed-off-by: David Hildenbrand Acked-by: Cornelia Huck Acked-by: Christian Borntraeger Signed-off-by: Jens Freimann Signed-off-by: Christian Borntraeger --- configure | 1 + gdb-xml/s390-acr.xml | 26 ++++++++++++++++++++++++++ gdb-xml/s390-fpr.xml | 27 +++++++++++++++++++++++++++ gdb-xml/s390x-core64.xml | 28 ++++++++++++++++++++++++++++ 4 files changed, 82 insertions(+) create mode 100644 gdb-xml/s390-acr.xml create mode 100644 gdb-xml/s390-fpr.xml create mode 100644 gdb-xml/s390x-core64.xml diff --git a/configure b/configure index 2063cf6a3c..15201f980f 100755 --- a/configure +++ b/configure @@ -5093,6 +5093,7 @@ case "$target_name" in echo "TARGET_ABI32=y" >> $config_target_mak ;; s390x) + gdb_xml_files="s390x-core64.xml s390-acr.xml s390-fpr.xml" ;; unicore32) ;; diff --git a/gdb-xml/s390-acr.xml b/gdb-xml/s390-acr.xml new file mode 100644 index 0000000000..71dfb20528 --- /dev/null +++ b/gdb-xml/s390-acr.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/gdb-xml/s390-fpr.xml b/gdb-xml/s390-fpr.xml new file mode 100644 index 0000000000..7de0c136ad --- /dev/null +++ b/gdb-xml/s390-fpr.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gdb-xml/s390x-core64.xml b/gdb-xml/s390x-core64.xml new file mode 100644 index 0000000000..15234378ee --- /dev/null +++ b/gdb-xml/s390x-core64.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + From 73d510c9d3f67378759447fd78af10b22e39620f Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Fri, 29 Aug 2014 15:52:16 +0200 Subject: [PATCH 18/19] s390x/gdb: generate target.xml and handle fp/ac as coprocessors This patch reduces the core registers to the psw and the general purpose registers. The fpc and ac registers are handled as coprocessors registers by gdb. This allows to reuse the feature xml files taken from gdb without further modification and is what other architectures do. The target.xml is now generated and provided to the gdb client. Therefore, the client doesn't have to guess which registers are available at which logical register number. Signed-off-by: David Hildenbrand Acked-by: Cornelia Huck Acked-by: Christian Borntraeger Signed-off-by: Jens Freimann Signed-off-by: Christian Borntraeger --- target-s390x/cpu-qom.h | 1 + target-s390x/cpu.c | 4 +- target-s390x/cpu.h | 40 +---------------- target-s390x/gdbstub.c | 97 +++++++++++++++++++++++++++++++----------- 4 files changed, 79 insertions(+), 63 deletions(-) diff --git a/target-s390x/cpu-qom.h b/target-s390x/cpu-qom.h index f9c96d13a9..80dd74142c 100644 --- a/target-s390x/cpu-qom.h +++ b/target-s390x/cpu-qom.h @@ -89,5 +89,6 @@ hwaddr s390_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); hwaddr s390_cpu_get_phys_addr_debug(CPUState *cpu, vaddr addr); int s390_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg); int s390_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); +void s390_cpu_gdb_init(CPUState *cs); #endif diff --git a/target-s390x/cpu.c b/target-s390x/cpu.c index 505a2fa3da..97a92168a8 100644 --- a/target-s390x/cpu.c +++ b/target-s390x/cpu.c @@ -174,6 +174,7 @@ static void s390_cpu_realizefn(DeviceState *dev, Error **errp) CPUState *cs = CPU(dev); S390CPUClass *scc = S390_CPU_GET_CLASS(dev); + s390_cpu_gdb_init(cs); qemu_init_vcpu(cs); #if !defined(CONFIG_USER_ONLY) run_on_cpu(cs, s390_do_cpu_full_reset, cs); @@ -263,7 +264,8 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data) cc->write_elf64_qemunote = s390_cpu_write_elf64_qemunote; #endif dc->vmsd = &vmstate_s390_cpu; - cc->gdb_num_core_regs = S390_NUM_REGS; + cc->gdb_num_core_regs = S390_NUM_CORE_REGS; + cc->gdb_core_xml_file = "s390x-core64.xml"; } static const TypeInfo s390_cpu_type_info = { diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index 772d513c01..62940c398a 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -566,44 +566,8 @@ void s390_cpu_list(FILE *f, fprintf_function cpu_fprintf); #define S390_R13_REGNUM 15 #define S390_R14_REGNUM 16 #define S390_R15_REGNUM 17 -/* Access Registers. */ -#define S390_A0_REGNUM 18 -#define S390_A1_REGNUM 19 -#define S390_A2_REGNUM 20 -#define S390_A3_REGNUM 21 -#define S390_A4_REGNUM 22 -#define S390_A5_REGNUM 23 -#define S390_A6_REGNUM 24 -#define S390_A7_REGNUM 25 -#define S390_A8_REGNUM 26 -#define S390_A9_REGNUM 27 -#define S390_A10_REGNUM 28 -#define S390_A11_REGNUM 29 -#define S390_A12_REGNUM 30 -#define S390_A13_REGNUM 31 -#define S390_A14_REGNUM 32 -#define S390_A15_REGNUM 33 -/* Floating Point Control Word. */ -#define S390_FPC_REGNUM 34 -/* Floating Point Registers. */ -#define S390_F0_REGNUM 35 -#define S390_F1_REGNUM 36 -#define S390_F2_REGNUM 37 -#define S390_F3_REGNUM 38 -#define S390_F4_REGNUM 39 -#define S390_F5_REGNUM 40 -#define S390_F6_REGNUM 41 -#define S390_F7_REGNUM 42 -#define S390_F8_REGNUM 43 -#define S390_F9_REGNUM 44 -#define S390_F10_REGNUM 45 -#define S390_F11_REGNUM 46 -#define S390_F12_REGNUM 47 -#define S390_F13_REGNUM 48 -#define S390_F14_REGNUM 49 -#define S390_F15_REGNUM 50 -/* Total. */ -#define S390_NUM_REGS 51 +/* Total Core Registers. */ +#define S390_NUM_CORE_REGS 18 /* CC optimization */ diff --git a/target-s390x/gdbstub.c b/target-s390x/gdbstub.c index 8d55006706..cda80530e4 100644 --- a/target-s390x/gdbstub.c +++ b/target-s390x/gdbstub.c @@ -42,14 +42,7 @@ int s390_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n) return gdb_get_regl(mem_buf, env->psw.addr); case S390_R0_REGNUM ... S390_R15_REGNUM: return gdb_get_regl(mem_buf, env->regs[n-S390_R0_REGNUM]); - case S390_A0_REGNUM ... S390_A15_REGNUM: - return gdb_get_reg32(mem_buf, env->aregs[n-S390_A0_REGNUM]); - case S390_FPC_REGNUM: - return gdb_get_reg32(mem_buf, env->fpc); - case S390_F0_REGNUM ... S390_F15_REGNUM: - return gdb_get_reg64(mem_buf, env->fregs[n-S390_F0_REGNUM].ll); } - return 0; } @@ -57,11 +50,7 @@ int s390_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) { S390CPU *cpu = S390_CPU(cs); CPUS390XState *env = &cpu->env; - target_ulong tmpl; - uint32_t tmp32; - int r = 8; - tmpl = ldtul_p(mem_buf); - tmp32 = ldl_p(mem_buf); + target_ulong tmpl = ldtul_p(mem_buf); switch (n) { case S390_PSWM_REGNUM: @@ -76,19 +65,79 @@ int s390_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) case S390_R0_REGNUM ... S390_R15_REGNUM: env->regs[n-S390_R0_REGNUM] = tmpl; break; - case S390_A0_REGNUM ... S390_A15_REGNUM: - env->aregs[n-S390_A0_REGNUM] = tmp32; - r = 4; - break; - case S390_FPC_REGNUM: - env->fpc = tmp32; - r = 4; - break; - case S390_F0_REGNUM ... S390_F15_REGNUM: - env->fregs[n-S390_F0_REGNUM].ll = tmpl; - break; default: return 0; } - return r; + return 8; +} + +/* the values represent the positions in s390-acr.xml */ +#define S390_A0_REGNUM 0 +#define S390_A15_REGNUM 15 +/* total number of registers in s390-acr.xml */ +#define S390_NUM_AC_REGS 16 + +static int cpu_read_ac_reg(CPUS390XState *env, uint8_t *mem_buf, int n) +{ + switch (n) { + case S390_A0_REGNUM ... S390_A15_REGNUM: + return gdb_get_reg32(mem_buf, env->aregs[n]); + default: + return 0; + } +} + +static int cpu_write_ac_reg(CPUS390XState *env, uint8_t *mem_buf, int n) +{ + switch (n) { + case S390_A0_REGNUM ... S390_A15_REGNUM: + env->aregs[n] = ldl_p(mem_buf); + return 4; + default: + return 0; + } +} + +/* the values represent the positions in s390-fpr.xml */ +#define S390_FPC_REGNUM 0 +#define S390_F0_REGNUM 1 +#define S390_F15_REGNUM 16 +/* total number of registers in s390-fpr.xml */ +#define S390_NUM_FP_REGS 17 + +static int cpu_read_fp_reg(CPUS390XState *env, uint8_t *mem_buf, int n) +{ + switch (n) { + case S390_FPC_REGNUM: + return gdb_get_reg32(mem_buf, env->fpc); + case S390_F0_REGNUM ... S390_F15_REGNUM: + return gdb_get_reg64(mem_buf, env->fregs[n - S390_F0_REGNUM].ll); + default: + return 0; + } +} + +static int cpu_write_fp_reg(CPUS390XState *env, uint8_t *mem_buf, int n) +{ + switch (n) { + case S390_FPC_REGNUM: + env->fpc = ldl_p(mem_buf); + return 4; + case S390_F0_REGNUM ... S390_F15_REGNUM: + env->fregs[n - S390_F0_REGNUM].ll = ldtul_p(mem_buf); + return 8; + default: + return 0; + } +} + +void s390_cpu_gdb_init(CPUState *cs) +{ + gdb_register_coprocessor(cs, cpu_read_ac_reg, + cpu_write_ac_reg, + S390_NUM_AC_REGS, "s390-acr.xml", 0); + + gdb_register_coprocessor(cs, cpu_read_fp_reg, + cpu_write_fp_reg, + S390_NUM_FP_REGS, "s390-fpr.xml", 0); } From 218829db2303e3d61f901f1d12fd4f7cd03644e1 Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Fri, 29 Aug 2014 15:52:17 +0200 Subject: [PATCH 19/19] s390x/gdb: coding style fixes This patch cleanes up two coding style issues (missing whitespaces). Signed-off-by: David Hildenbrand Acked-by: Cornelia Huck Acked-by: Christian Borntraeger Signed-off-by: Jens Freimann Signed-off-by: Christian Borntraeger --- target-s390x/gdbstub.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target-s390x/gdbstub.c b/target-s390x/gdbstub.c index cda80530e4..8945f0271d 100644 --- a/target-s390x/gdbstub.c +++ b/target-s390x/gdbstub.c @@ -41,7 +41,7 @@ int s390_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n) case S390_PSWA_REGNUM: return gdb_get_regl(mem_buf, env->psw.addr); case S390_R0_REGNUM ... S390_R15_REGNUM: - return gdb_get_regl(mem_buf, env->regs[n-S390_R0_REGNUM]); + return gdb_get_regl(mem_buf, env->regs[n - S390_R0_REGNUM]); } return 0; } @@ -63,7 +63,7 @@ int s390_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) env->psw.addr = tmpl; break; case S390_R0_REGNUM ... S390_R15_REGNUM: - env->regs[n-S390_R0_REGNUM] = tmpl; + env->regs[n - S390_R0_REGNUM] = tmpl; break; default: return 0;