First s390x update for 5.0:

- compat machines (also for other architectures)
 - cleanups and fixes in reset handling
 - fence off guest-set-time, as we have no hwclock
 - fix some misuses of the error API
 - further cleanups
 -----BEGIN PGP SIGNATURE-----
 
 iQJGBAABCAAwFiEEw9DWbcNiT/aowBjO3s9rk8bwL68FAl30rF0SHGNvaHVja0By
 ZWRoYXQuY29tAAoJEN7Pa5PG8C+vFRoP/jtP96JsnbyOssm8JSZGd7sWKIUt1RU5
 3up4hzPXh+tRs5auKvihf30cPO8UB7DXhYN3KGQVJHvXJ7x+jJfomyiYUcsz0aNo
 gpF2gBgQAwjuPzVc5foqHDFHRVpopxGo5y6yH0woeQtfBsZBbUMD2XgeCHaRID81
 pOfv7Vg43XTETzgR959zAES3wRMYhoS1xYtqrhUqOv/RjduKlE4JVFeKEPDTsnsw
 E8kc3w5+vq/5RpvnpEfhl8SSscB23Pz3tFQ+qXSlT7oUNZPPvt9noy5TChmFf5Fh
 tqll1bhwK57MYrvKiVjGbf+elhYmMcJ5BcJbGgwvBB9kuTlOJ9LxGTEendI5Gk6Y
 0vAVnKmYm6pZU12dFi4pzRUWUvC0+ixT8T3zgEIDQ8iV6sxf+gZsUl5B9BiIyEsr
 cg/7R7FvXVFgWV0vXURtLizEyMFsIjGjlpxg0n0GQ0s0Dkmjj4N3jkphSdQB2FzC
 KNyAzp1DSJVXtsYVlVUHwZHHIrxxNigI3FoEuptGJv5AlyqzuBL1dgiOBv8ZT440
 KGMcLAB3qLo/Pyt1VvMi67G3v9nvtms0R+eXaIRH/3GyoQBf4qnWw5vJ8V+e2x1r
 3aqCF7pDO6DoEOmEDH17hV+0F90cWrniLovELvcLBRKZITjF/cLpXxPVbIwv4J6F
 cot++wt90Ena
 =yt5l
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20191214-2' into staging

First s390x update for 5.0:
- compat machines (also for other architectures)
- cleanups and fixes in reset handling
- fence off guest-set-time, as we have no hwclock
- fix some misuses of the error API
- further cleanups

# gpg: Signature made Sat 14 Dec 2019 09:33:17 GMT
# gpg:                using RSA key C3D0D66DC3624FF6A8C018CEDECF6B93C6F02FAF
# gpg:                issuer "cohuck@redhat.com"
# gpg: Good signature from "Cornelia Huck <conny@cornelia-huck.de>" [unknown]
# gpg:                 aka "Cornelia Huck <huckc@linux.vnet.ibm.com>" [full]
# gpg:                 aka "Cornelia Huck <cornelia.huck@de.ibm.com>" [full]
# gpg:                 aka "Cornelia Huck <cohuck@kernel.org>" [unknown]
# gpg:                 aka "Cornelia Huck <cohuck@redhat.com>" [unknown]
# Primary key fingerprint: C3D0 D66D C362 4FF6 A8C0  18CE DECF 6B93 C6F0 2FAF

* remotes/cohuck/tags/s390x-20191214-2:
  qga: fence guest-set-time if hwclock not available
  s390x/tcg: clear local interrupts on reset normal
  s390x/cpumodel: Fix query-cpu-definitions error API violations
  s390x/cpumodel: Fix query-cpu-model-FOO error API violations
  s390x/cpumodel: Fix realize() error API violations
  s390x/cpumodel: Fix feature property error API violations
  s390x/event-facility: Fix realize() error API violations
  s390x: Fix cpu normal reset ri clearing
  s390x: kvm: Make kvm_sclp_service_call void
  s390x: Beautify diag308 handling
  s390x: Move clear reset
  s390x: Move initial reset
  s390x: Move reset normal to shared reset handler
  s390x: Don't do a normal reset on the initial cpu
  hw: add compat machines for 5.0
  vfio-ccw: Fix error message

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2019-12-16 10:35:33 +00:00
commit 7697ac55fc
17 changed files with 242 additions and 156 deletions

View File

@ -2147,11 +2147,16 @@ static void machvirt_machine_init(void)
} }
type_init(machvirt_machine_init); type_init(machvirt_machine_init);
static void virt_machine_5_0_options(MachineClass *mc)
{
}
DEFINE_VIRT_MACHINE_AS_LATEST(5, 0)
static void virt_machine_4_2_options(MachineClass *mc) static void virt_machine_4_2_options(MachineClass *mc)
{ {
compat_props_add(mc->compat_props, hw_compat_4_2, hw_compat_4_2_len); compat_props_add(mc->compat_props, hw_compat_4_2, hw_compat_4_2_len);
} }
DEFINE_VIRT_MACHINE_AS_LATEST(4, 2) DEFINE_VIRT_MACHINE(4, 2)
static void virt_machine_4_1_options(MachineClass *mc) static void virt_machine_4_1_options(MachineClass *mc)
{ {

View File

@ -103,6 +103,9 @@
struct hpet_fw_config hpet_cfg = {.count = UINT8_MAX}; struct hpet_fw_config hpet_cfg = {.count = UINT8_MAX};
GlobalProperty pc_compat_4_2[] = {};
const size_t pc_compat_4_2_len = G_N_ELEMENTS(pc_compat_4_2);
GlobalProperty pc_compat_4_1[] = {}; GlobalProperty pc_compat_4_1[] = {};
const size_t pc_compat_4_1_len = G_N_ELEMENTS(pc_compat_4_1); const size_t pc_compat_4_1_len = G_N_ELEMENTS(pc_compat_4_1);

View File

@ -424,7 +424,7 @@ static void pc_i440fx_machine_options(MachineClass *m)
machine_class_allow_dynamic_sysbus_dev(m, TYPE_RAMFB_DEVICE); machine_class_allow_dynamic_sysbus_dev(m, TYPE_RAMFB_DEVICE);
} }
static void pc_i440fx_4_2_machine_options(MachineClass *m) static void pc_i440fx_5_0_machine_options(MachineClass *m)
{ {
PCMachineClass *pcmc = PC_MACHINE_CLASS(m); PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
pc_i440fx_machine_options(m); pc_i440fx_machine_options(m);
@ -434,6 +434,18 @@ static void pc_i440fx_4_2_machine_options(MachineClass *m)
compat_props_add(m->compat_props, hw_compat_4_2, hw_compat_4_2_len); compat_props_add(m->compat_props, hw_compat_4_2, hw_compat_4_2_len);
} }
DEFINE_I440FX_MACHINE(v5_0, "pc-i440fx-5.0", NULL,
pc_i440fx_5_0_machine_options);
static void pc_i440fx_4_2_machine_options(MachineClass *m)
{
pc_i440fx_5_0_machine_options(m);
m->alias = NULL;
m->is_default = 0;
compat_props_add(m->compat_props, hw_compat_4_2, hw_compat_4_2_len);
compat_props_add(m->compat_props, pc_compat_4_2, pc_compat_4_2_len);
}
DEFINE_I440FX_MACHINE(v4_2, "pc-i440fx-4.2", NULL, DEFINE_I440FX_MACHINE(v4_2, "pc-i440fx-4.2", NULL,
pc_i440fx_4_2_machine_options); pc_i440fx_4_2_machine_options);

View File

@ -348,7 +348,7 @@ static void pc_q35_machine_options(MachineClass *m)
m->max_cpus = 288; m->max_cpus = 288;
} }
static void pc_q35_4_2_machine_options(MachineClass *m) static void pc_q35_5_0_machine_options(MachineClass *m)
{ {
PCMachineClass *pcmc = PC_MACHINE_CLASS(m); PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
pc_q35_machine_options(m); pc_q35_machine_options(m);
@ -357,6 +357,17 @@ static void pc_q35_4_2_machine_options(MachineClass *m)
compat_props_add(m->compat_props, hw_compat_4_2, hw_compat_4_2_len); compat_props_add(m->compat_props, hw_compat_4_2, hw_compat_4_2_len);
} }
DEFINE_Q35_MACHINE(v5_0, "pc-q35-5.0", NULL,
pc_q35_5_0_machine_options);
static void pc_q35_4_2_machine_options(MachineClass *m)
{
pc_q35_5_0_machine_options(m);
m->alias = NULL;
compat_props_add(m->compat_props, hw_compat_4_2, hw_compat_4_2_len);
compat_props_add(m->compat_props, pc_compat_4_2, pc_compat_4_2_len);
}
DEFINE_Q35_MACHINE(v4_2, "pc-q35-4.2", NULL, DEFINE_Q35_MACHINE(v4_2, "pc-q35-4.2", NULL,
pc_q35_4_2_machine_options); pc_q35_4_2_machine_options);

View File

@ -4491,15 +4491,26 @@ static const TypeInfo spapr_machine_info = {
} \ } \
type_init(spapr_machine_register_##suffix) type_init(spapr_machine_register_##suffix)
/*
* pseries-5.0
*/
static void spapr_machine_5_0_class_options(MachineClass *mc)
{
/* Defaults for the latest behaviour inherited from the base class */
}
DEFINE_SPAPR_MACHINE(5_0, "5.0", true);
/* /*
* pseries-4.2 * pseries-4.2
*/ */
static void spapr_machine_4_2_class_options(MachineClass *mc) static void spapr_machine_4_2_class_options(MachineClass *mc)
{ {
spapr_machine_5_0_class_options(mc);
compat_props_add(mc->compat_props, hw_compat_4_2, hw_compat_4_2_len); compat_props_add(mc->compat_props, hw_compat_4_2, hw_compat_4_2_len);
} }
DEFINE_SPAPR_MACHINE(4_2, "4.2", true); DEFINE_SPAPR_MACHINE(4_2, "4.2", false);
/* /*
* pseries-4.1 * pseries-4.1

View File

@ -339,14 +339,16 @@ out:
static void sclp_events_bus_realize(BusState *bus, Error **errp) static void sclp_events_bus_realize(BusState *bus, Error **errp)
{ {
Error *err = NULL;
BusChild *kid; BusChild *kid;
/* TODO: recursive realization has to be done in common code */ /* TODO: recursive realization has to be done in common code */
QTAILQ_FOREACH(kid, &bus->children, sibling) { QTAILQ_FOREACH(kid, &bus->children, sibling) {
DeviceState *dev = kid->child; DeviceState *dev = kid->child;
object_property_set_bool(OBJECT(dev), true, "realized", errp); object_property_set_bool(OBJECT(dev), true, "realized", &err);
if (*errp) { if (errp) {
error_propagate(errp, err);
return; return;
} }
} }

View File

@ -348,6 +348,9 @@ static void s390_machine_reset(MachineState *machine)
break; break;
case S390_RESET_LOAD_NORMAL: case S390_RESET_LOAD_NORMAL:
CPU_FOREACH(t) { CPU_FOREACH(t) {
if (t == cs) {
continue;
}
run_on_cpu(t, s390_do_cpu_reset, RUN_ON_CPU_NULL); run_on_cpu(t, s390_do_cpu_reset, RUN_ON_CPU_NULL);
} }
subsystem_reset(); subsystem_reset();
@ -639,15 +642,26 @@ bool css_migration_enabled(void)
} \ } \
type_init(ccw_machine_register_##suffix) type_init(ccw_machine_register_##suffix)
static void ccw_machine_5_0_instance_options(MachineState *machine)
{
}
static void ccw_machine_5_0_class_options(MachineClass *mc)
{
}
DEFINE_CCW_MACHINE(5_0, "5.0", true);
static void ccw_machine_4_2_instance_options(MachineState *machine) static void ccw_machine_4_2_instance_options(MachineState *machine)
{ {
ccw_machine_5_0_instance_options(machine);
} }
static void ccw_machine_4_2_class_options(MachineClass *mc) static void ccw_machine_4_2_class_options(MachineClass *mc)
{ {
ccw_machine_5_0_class_options(mc);
compat_props_add(mc->compat_props, hw_compat_4_2, hw_compat_4_2_len); compat_props_add(mc->compat_props, hw_compat_4_2, hw_compat_4_2_len);
} }
DEFINE_CCW_MACHINE(4_2, "4.2", true); DEFINE_CCW_MACHINE(4_2, "4.2", false);
static void ccw_machine_4_1_instance_options(MachineState *machine) static void ccw_machine_4_1_instance_options(MachineState *machine)
{ {

View File

@ -102,7 +102,7 @@ again:
if (errno == EAGAIN) { if (errno == EAGAIN) {
goto again; goto again;
} }
error_report("vfio-ccw: wirte I/O region failed with errno=%d", errno); error_report("vfio-ccw: write I/O region failed with errno=%d", errno);
ret = -errno; ret = -errno;
} else { } else {
ret = region->ret_code; ret = region->ret_code;

View File

@ -237,6 +237,9 @@ void pc_system_firmware_init(PCMachineState *pcms, MemoryRegion *rom_memory);
void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid, void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
const CPUArchIdList *apic_ids, GArray *entry); const CPUArchIdList *apic_ids, GArray *entry);
extern GlobalProperty pc_compat_4_2[];
extern const size_t pc_compat_4_2_len;
extern GlobalProperty pc_compat_4_1[]; extern GlobalProperty pc_compat_4_1[];
extern const size_t pc_compat_4_1_len; extern const size_t pc_compat_4_1_len;

View File

@ -156,6 +156,17 @@ void qmp_guest_set_time(bool has_time, int64_t time_ns, Error **errp)
pid_t pid; pid_t pid;
Error *local_err = NULL; Error *local_err = NULL;
struct timeval tv; struct timeval tv;
static const char hwclock_path[] = "/sbin/hwclock";
static int hwclock_available = -1;
if (hwclock_available < 0) {
hwclock_available = (access(hwclock_path, X_OK) == 0);
}
if (!hwclock_available) {
error_setg(errp, QERR_UNSUPPORTED);
return;
}
/* If user has passed a time, validate and set it. */ /* If user has passed a time, validate and set it. */
if (has_time) { if (has_time) {
@ -195,7 +206,7 @@ void qmp_guest_set_time(bool has_time, int64_t time_ns, Error **errp)
/* Use '/sbin/hwclock -w' to set RTC from the system time, /* Use '/sbin/hwclock -w' to set RTC from the system time,
* or '/sbin/hwclock -s' to set the system time from RTC. */ * or '/sbin/hwclock -s' to set the system time from RTC. */
execle("/sbin/hwclock", "hwclock", has_time ? "-w" : "-s", execle(hwclock_path, "hwclock", has_time ? "-w" : "-s",
NULL, environ); NULL, environ);
_exit(EXIT_FAILURE); _exit(EXIT_FAILURE);
} else if (pid < 0) { } else if (pid < 0) {

View File

@ -34,6 +34,12 @@
typedef struct S390CPUModel S390CPUModel; typedef struct S390CPUModel S390CPUModel;
typedef struct S390CPUDef S390CPUDef; typedef struct S390CPUDef S390CPUDef;
typedef enum cpu_reset_type {
S390_CPU_RESET_NORMAL,
S390_CPU_RESET_INITIAL,
S390_CPU_RESET_CLEAR,
} cpu_reset_type;
/** /**
* S390CPUClass: * S390CPUClass:
* @parent_realize: The parent class' realize handler. * @parent_realize: The parent class' realize handler.
@ -57,8 +63,7 @@ typedef struct S390CPUClass {
DeviceRealize parent_realize; DeviceRealize parent_realize;
void (*parent_reset)(CPUState *cpu); void (*parent_reset)(CPUState *cpu);
void (*load_normal)(CPUState *cpu); void (*load_normal)(CPUState *cpu);
void (*cpu_reset)(CPUState *cpu); void (*reset)(CPUState *cpu, cpu_reset_type type);
void (*initial_cpu_reset)(CPUState *cpu);
} S390CPUClass; } S390CPUClass;
typedef struct S390CPU S390CPU; typedef struct S390CPU S390CPU;

View File

@ -82,53 +82,8 @@ static void s390_cpu_load_normal(CPUState *s)
} }
#endif #endif
/* S390CPUClass::cpu_reset() */ /* S390CPUClass::reset() */
static void s390_cpu_reset(CPUState *s) static void s390_cpu_reset(CPUState *s, cpu_reset_type type)
{
S390CPU *cpu = S390_CPU(s);
S390CPUClass *scc = S390_CPU_GET_CLASS(cpu);
CPUS390XState *env = &cpu->env;
env->pfault_token = -1UL;
env->bpbc = false;
scc->parent_reset(s);
cpu->env.sigp_order = 0;
s390_cpu_set_state(S390_CPU_STATE_STOPPED, cpu);
}
/* S390CPUClass::initial_reset() */
static void s390_cpu_initial_reset(CPUState *s)
{
S390CPU *cpu = S390_CPU(s);
CPUS390XState *env = &cpu->env;
s390_cpu_reset(s);
/* initial reset does not clear everything! */
memset(&env->start_initial_reset_fields, 0,
offsetof(CPUS390XState, end_reset_fields) -
offsetof(CPUS390XState, start_initial_reset_fields));
/* architectured initial values for CR 0 and 14 */
env->cregs[0] = CR0_RESET;
env->cregs[14] = CR14_RESET;
/* architectured initial value for Breaking-Event-Address register */
env->gbea = 1;
env->pfault_token = -1UL;
/* tininess for underflow is detected before rounding */
set_float_detect_tininess(float_tininess_before_rounding,
&env->fpu_status);
/* Reset state inside the kernel that we cannot access yet from QEMU. */
if (kvm_enabled()) {
kvm_s390_reset_vcpu(cpu);
}
}
/* CPUClass:reset() */
static void s390_cpu_full_reset(CPUState *s)
{ {
S390CPU *cpu = S390_CPU(s); S390CPU *cpu = S390_CPU(s);
S390CPUClass *scc = S390_CPU_GET_CLASS(cpu); S390CPUClass *scc = S390_CPU_GET_CLASS(cpu);
@ -138,31 +93,50 @@ static void s390_cpu_full_reset(CPUState *s)
cpu->env.sigp_order = 0; cpu->env.sigp_order = 0;
s390_cpu_set_state(S390_CPU_STATE_STOPPED, cpu); s390_cpu_set_state(S390_CPU_STATE_STOPPED, cpu);
memset(env, 0, offsetof(CPUS390XState, end_reset_fields)); switch (type) {
case S390_CPU_RESET_CLEAR:
memset(env, 0, offsetof(CPUS390XState, start_initial_reset_fields));
/* fall through */
case S390_CPU_RESET_INITIAL:
/* initial reset does not clear everything! */
memset(&env->start_initial_reset_fields, 0,
offsetof(CPUS390XState, start_normal_reset_fields) -
offsetof(CPUS390XState, start_initial_reset_fields));
/* architectured initial values for CR 0 and 14 */ /* architectured initial value for Breaking-Event-Address register */
env->cregs[0] = CR0_RESET; env->gbea = 1;
env->cregs[14] = CR14_RESET;
/* architectured initial values for CR 0 and 14 */
env->cregs[0] = CR0_RESET;
env->cregs[14] = CR14_RESET;
#if defined(CONFIG_USER_ONLY) #if defined(CONFIG_USER_ONLY)
/* user mode should always be allowed to use the full FPU */ /* user mode should always be allowed to use the full FPU */
env->cregs[0] |= CR0_AFP; env->cregs[0] |= CR0_AFP;
if (s390_has_feat(S390_FEAT_VECTOR)) { if (s390_has_feat(S390_FEAT_VECTOR)) {
env->cregs[0] |= CR0_VECTOR; env->cregs[0] |= CR0_VECTOR;
} }
#endif #endif
/* architectured initial value for Breaking-Event-Address register */ /* tininess for underflow is detected before rounding */
env->gbea = 1; set_float_detect_tininess(float_tininess_before_rounding,
&env->fpu_status);
/* fall through */
case S390_CPU_RESET_NORMAL:
env->psw.mask &= ~PSW_MASK_RI;
memset(&env->start_normal_reset_fields, 0,
offsetof(CPUS390XState, end_reset_fields) -
offsetof(CPUS390XState, start_normal_reset_fields));
env->pfault_token = -1UL; env->pfault_token = -1UL;
env->bpbc = false;
/* tininess for underflow is detected before rounding */ break;
set_float_detect_tininess(float_tininess_before_rounding, default:
&env->fpu_status); g_assert_not_reached();
}
/* Reset state inside the kernel that we cannot access yet from QEMU. */ /* Reset state inside the kernel that we cannot access yet from QEMU. */
if (kvm_enabled()) { if (kvm_enabled() && type != S390_CPU_RESET_NORMAL) {
kvm_s390_reset_vcpu(cpu); kvm_s390_reset_vcpu(cpu);
} }
} }
@ -458,6 +432,11 @@ static Property s390x_cpu_properties[] = {
DEFINE_PROP_END_OF_LIST() DEFINE_PROP_END_OF_LIST()
}; };
static void s390_cpu_reset_full(CPUState *s)
{
return s390_cpu_reset(s, S390_CPU_RESET_CLEAR);
}
static void s390_cpu_class_init(ObjectClass *oc, void *data) static void s390_cpu_class_init(ObjectClass *oc, void *data)
{ {
S390CPUClass *scc = S390_CPU_CLASS(oc); S390CPUClass *scc = S390_CPU_CLASS(oc);
@ -473,9 +452,8 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data)
#if !defined(CONFIG_USER_ONLY) #if !defined(CONFIG_USER_ONLY)
scc->load_normal = s390_cpu_load_normal; scc->load_normal = s390_cpu_load_normal;
#endif #endif
scc->cpu_reset = s390_cpu_reset; scc->reset = s390_cpu_reset;
scc->initial_cpu_reset = s390_cpu_initial_reset; cc->reset = s390_cpu_reset_full;
cc->reset = s390_cpu_full_reset;
cc->class_by_name = s390_cpu_class_by_name, cc->class_by_name = s390_cpu_class_by_name,
cc->has_work = s390_cpu_has_work; cc->has_work = s390_cpu_has_work;
#ifdef CONFIG_TCG #ifdef CONFIG_TCG

View File

@ -58,7 +58,6 @@ struct CPUS390XState {
*/ */
uint64_t vregs[32][2] QEMU_ALIGNED(16); /* vector registers */ uint64_t vregs[32][2] QEMU_ALIGNED(16); /* vector registers */
uint32_t aregs[16]; /* access registers */ uint32_t aregs[16]; /* access registers */
uint8_t riccb[64]; /* runtime instrumentation control */
uint64_t gscb[4]; /* guarded storage control */ uint64_t gscb[4]; /* guarded storage control */
uint64_t etoken; /* etoken */ uint64_t etoken; /* etoken */
uint64_t etoken_extension; /* etoken extension */ uint64_t etoken_extension; /* etoken extension */
@ -99,10 +98,6 @@ struct CPUS390XState {
uint64_t cregs[16]; /* control registers */ uint64_t cregs[16]; /* control registers */
int pending_int;
uint16_t external_call_addr;
DECLARE_BITMAP(emergency_signals, S390_MAX_CPUS);
uint64_t ckc; uint64_t ckc;
uint64_t cputm; uint64_t cputm;
uint32_t todpr; uint32_t todpr;
@ -114,6 +109,14 @@ struct CPUS390XState {
uint64_t gbea; uint64_t gbea;
uint64_t pp; uint64_t pp;
/* Fields up to this point are not cleared by normal CPU reset */
struct {} start_normal_reset_fields;
uint8_t riccb[64]; /* runtime instrumentation control */
int pending_int;
uint16_t external_call_addr;
DECLARE_BITMAP(emergency_signals, S390_MAX_CPUS);
/* Fields up to this point are cleared by a CPU reset */ /* Fields up to this point are cleared by a CPU reset */
struct {} end_reset_fields; struct {} end_reset_fields;
@ -252,6 +255,7 @@ extern const VMStateDescription vmstate_s390_cpu;
#undef PSW_SHIFT_ASC #undef PSW_SHIFT_ASC
#undef PSW_MASK_CC #undef PSW_MASK_CC
#undef PSW_MASK_PM #undef PSW_MASK_PM
#undef PSW_MASK_RI
#undef PSW_SHIFT_MASK_PM #undef PSW_SHIFT_MASK_PM
#undef PSW_MASK_64 #undef PSW_MASK_64
#undef PSW_MASK_32 #undef PSW_MASK_32
@ -273,6 +277,7 @@ extern const VMStateDescription vmstate_s390_cpu;
#define PSW_MASK_CC 0x0000300000000000ULL #define PSW_MASK_CC 0x0000300000000000ULL
#define PSW_MASK_PM 0x00000F0000000000ULL #define PSW_MASK_PM 0x00000F0000000000ULL
#define PSW_SHIFT_MASK_PM 40 #define PSW_SHIFT_MASK_PM 40
#define PSW_MASK_RI 0x0000008000000000ULL
#define PSW_MASK_64 0x0000000100000000ULL #define PSW_MASK_64 0x0000000100000000ULL
#define PSW_MASK_32 0x0000000080000000ULL #define PSW_MASK_32 0x0000000080000000ULL
#define PSW_MASK_ESA_ADDR 0x000000007fffffffULL #define PSW_MASK_ESA_ADDR 0x000000007fffffffULL
@ -741,14 +746,14 @@ static inline void s390_do_cpu_reset(CPUState *cs, run_on_cpu_data arg)
{ {
S390CPUClass *scc = S390_CPU_GET_CLASS(cs); S390CPUClass *scc = S390_CPU_GET_CLASS(cs);
scc->cpu_reset(cs); scc->reset(cs, S390_CPU_RESET_NORMAL);
} }
static inline void s390_do_cpu_initial_reset(CPUState *cs, run_on_cpu_data arg) static inline void s390_do_cpu_initial_reset(CPUState *cs, run_on_cpu_data arg)
{ {
S390CPUClass *scc = S390_CPU_GET_CLASS(cs); S390CPUClass *scc = S390_CPU_GET_CLASS(cs);
scc->initial_cpu_reset(cs); scc->reset(cs, S390_CPU_RESET_INITIAL);
} }
static inline void s390_do_cpu_load_normal(CPUState *cs, run_on_cpu_data arg) static inline void s390_do_cpu_load_normal(CPUState *cs, run_on_cpu_data arg)

View File

@ -462,11 +462,7 @@ CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
.list = NULL, .list = NULL,
}; };
list_data.model = get_max_cpu_model(errp); list_data.model = get_max_cpu_model(NULL);
if (*errp) {
error_free(*errp);
*errp = NULL;
}
object_class_foreach(create_cpu_model_list, TYPE_S390_CPU, false, object_class_foreach(create_cpu_model_list, TYPE_S390_CPU, false,
&list_data); &list_data);
@ -477,6 +473,7 @@ CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
static void cpu_model_from_info(S390CPUModel *model, const CpuModelInfo *info, static void cpu_model_from_info(S390CPUModel *model, const CpuModelInfo *info,
Error **errp) Error **errp)
{ {
Error *err = NULL;
const QDict *qdict = NULL; const QDict *qdict = NULL;
const QDictEntry *e; const QDictEntry *e;
Visitor *visitor; Visitor *visitor;
@ -513,24 +510,26 @@ static void cpu_model_from_info(S390CPUModel *model, const CpuModelInfo *info,
if (qdict) { if (qdict) {
visitor = qobject_input_visitor_new(info->props); visitor = qobject_input_visitor_new(info->props);
visit_start_struct(visitor, NULL, NULL, 0, errp); visit_start_struct(visitor, NULL, NULL, 0, &err);
if (*errp) { if (err) {
error_propagate(errp, err);
visit_free(visitor); visit_free(visitor);
object_unref(obj); object_unref(obj);
return; return;
} }
for (e = qdict_first(qdict); e; e = qdict_next(qdict, e)) { for (e = qdict_first(qdict); e; e = qdict_next(qdict, e)) {
object_property_set(obj, visitor, e->key, errp); object_property_set(obj, visitor, e->key, &err);
if (*errp) { if (err) {
break; break;
} }
} }
if (!*errp) { if (!err) {
visit_check_struct(visitor, errp); visit_check_struct(visitor, errp);
} }
visit_end_struct(visitor, NULL); visit_end_struct(visitor, NULL);
visit_free(visitor); visit_free(visitor);
if (*errp) { if (err) {
error_propagate(errp, err);
object_unref(obj); object_unref(obj);
return; return;
} }
@ -595,13 +594,15 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
CpuModelInfo *model, CpuModelInfo *model,
Error **errp) Error **errp)
{ {
Error *err = NULL;
CpuModelExpansionInfo *expansion_info = NULL; CpuModelExpansionInfo *expansion_info = NULL;
S390CPUModel s390_model; S390CPUModel s390_model;
bool delta_changes = false; bool delta_changes = false;
/* convert it to our internal representation */ /* convert it to our internal representation */
cpu_model_from_info(&s390_model, model, errp); cpu_model_from_info(&s390_model, model, &err);
if (*errp) { if (err) {
error_propagate(errp, err);
return NULL; return NULL;
} }
@ -634,18 +635,21 @@ CpuModelCompareInfo *qmp_query_cpu_model_comparison(CpuModelInfo *infoa,
CpuModelInfo *infob, CpuModelInfo *infob,
Error **errp) Error **errp)
{ {
Error *err = NULL;
CpuModelCompareResult feat_result, gen_result; CpuModelCompareResult feat_result, gen_result;
CpuModelCompareInfo *compare_info; CpuModelCompareInfo *compare_info;
S390FeatBitmap missing, added; S390FeatBitmap missing, added;
S390CPUModel modela, modelb; S390CPUModel modela, modelb;
/* convert both models to our internal representation */ /* convert both models to our internal representation */
cpu_model_from_info(&modela, infoa, errp); cpu_model_from_info(&modela, infoa, &err);
if (*errp) { if (err) {
error_propagate(errp, err);
return NULL; return NULL;
} }
cpu_model_from_info(&modelb, infob, errp); cpu_model_from_info(&modelb, infob, &err);
if (*errp) { if (err) {
error_propagate(errp, err);
return NULL; return NULL;
} }
compare_info = g_new0(CpuModelCompareInfo, 1); compare_info = g_new0(CpuModelCompareInfo, 1);
@ -707,6 +711,7 @@ CpuModelBaselineInfo *qmp_query_cpu_model_baseline(CpuModelInfo *infoa,
CpuModelInfo *infob, CpuModelInfo *infob,
Error **errp) Error **errp)
{ {
Error *err = NULL;
CpuModelBaselineInfo *baseline_info; CpuModelBaselineInfo *baseline_info;
S390CPUModel modela, modelb, model; S390CPUModel modela, modelb, model;
uint16_t cpu_type; uint16_t cpu_type;
@ -714,13 +719,15 @@ CpuModelBaselineInfo *qmp_query_cpu_model_baseline(CpuModelInfo *infoa,
uint8_t max_gen; uint8_t max_gen;
/* convert both models to our internal representation */ /* convert both models to our internal representation */
cpu_model_from_info(&modela, infoa, errp); cpu_model_from_info(&modela, infoa, &err);
if (*errp) { if (err) {
error_propagate(errp, err);
return NULL; return NULL;
} }
cpu_model_from_info(&modelb, infob, errp); cpu_model_from_info(&modelb, infob, &err);
if (*errp) { if (err) {
error_propagate(errp, err);
return NULL; return NULL;
} }
@ -870,6 +877,7 @@ static void check_compatibility(const S390CPUModel *max_model,
static S390CPUModel *get_max_cpu_model(Error **errp) static S390CPUModel *get_max_cpu_model(Error **errp)
{ {
Error *err = NULL;
static S390CPUModel max_model; static S390CPUModel max_model;
static bool cached; static bool cached;
@ -878,22 +886,24 @@ static S390CPUModel *get_max_cpu_model(Error **errp)
} }
if (kvm_enabled()) { if (kvm_enabled()) {
kvm_s390_get_host_cpu_model(&max_model, errp); kvm_s390_get_host_cpu_model(&max_model, &err);
} else { } else {
max_model.def = s390_find_cpu_def(QEMU_MAX_CPU_TYPE, QEMU_MAX_CPU_GEN, max_model.def = s390_find_cpu_def(QEMU_MAX_CPU_TYPE, QEMU_MAX_CPU_GEN,
QEMU_MAX_CPU_EC_GA, NULL); QEMU_MAX_CPU_EC_GA, NULL);
bitmap_copy(max_model.features, qemu_max_cpu_feat, S390_FEAT_MAX); bitmap_copy(max_model.features, qemu_max_cpu_feat, S390_FEAT_MAX);
}
if (!*errp) {
cached = true;
return &max_model;
} }
return NULL; if (err) {
error_propagate(errp, err);
return NULL;
}
cached = true;
return &max_model;
} }
static inline void apply_cpu_model(const S390CPUModel *model, Error **errp) static inline void apply_cpu_model(const S390CPUModel *model, Error **errp)
{ {
#ifndef CONFIG_USER_ONLY #ifndef CONFIG_USER_ONLY
Error *err = NULL;
static S390CPUModel applied_model; static S390CPUModel applied_model;
static bool applied; static bool applied;
@ -909,20 +919,23 @@ static inline void apply_cpu_model(const S390CPUModel *model, Error **errp)
} }
if (kvm_enabled()) { if (kvm_enabled()) {
kvm_s390_apply_cpu_model(model, errp); kvm_s390_apply_cpu_model(model, &err);
if (err) {
error_propagate(errp, err);
return;
}
} }
if (!*errp) { applied = true;
applied = true; if (model) {
if (model) { applied_model = *model;
applied_model = *model;
}
} }
#endif #endif
} }
void s390_realize_cpu_model(CPUState *cs, Error **errp) void s390_realize_cpu_model(CPUState *cs, Error **errp)
{ {
Error *err = NULL;
S390CPUClass *xcc = S390_CPU_GET_CLASS(cs); S390CPUClass *xcc = S390_CPU_GET_CLASS(cs);
S390CPU *cpu = S390_CPU(cs); S390CPU *cpu = S390_CPU(cs);
const S390CPUModel *max_model; const S390CPUModel *max_model;
@ -939,7 +952,7 @@ void s390_realize_cpu_model(CPUState *cs, Error **errp)
} }
max_model = get_max_cpu_model(errp); max_model = get_max_cpu_model(errp);
if (*errp) { if (!max_model) {
error_prepend(errp, "CPU models are not available: "); error_prepend(errp, "CPU models are not available: ");
return; return;
} }
@ -951,8 +964,9 @@ void s390_realize_cpu_model(CPUState *cs, Error **errp)
cpu->model->cpu_ver = max_model->cpu_ver; cpu->model->cpu_ver = max_model->cpu_ver;
check_consistency(cpu->model); check_consistency(cpu->model);
check_compatibility(max_model, cpu->model, errp); check_compatibility(max_model, cpu->model, &err);
if (*errp) { if (err) {
error_propagate(errp, err);
return; return;
} }
@ -987,6 +1001,7 @@ static void get_feature(Object *obj, Visitor *v, const char *name,
static void set_feature(Object *obj, Visitor *v, const char *name, static void set_feature(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp) void *opaque, Error **errp)
{ {
Error *err = NULL;
S390Feat feat = (S390Feat) opaque; S390Feat feat = (S390Feat) opaque;
DeviceState *dev = DEVICE(obj); DeviceState *dev = DEVICE(obj);
S390CPU *cpu = S390_CPU(obj); S390CPU *cpu = S390_CPU(obj);
@ -1002,8 +1017,9 @@ static void set_feature(Object *obj, Visitor *v, const char *name,
return; return;
} }
visit_type_bool(v, name, &value, errp); visit_type_bool(v, name, &value, &err);
if (*errp) { if (err) {
error_propagate(errp, err);
return; return;
} }
if (value) { if (value) {
@ -1043,6 +1059,7 @@ static void get_feature_group(Object *obj, Visitor *v, const char *name,
static void set_feature_group(Object *obj, Visitor *v, const char *name, static void set_feature_group(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp) void *opaque, Error **errp)
{ {
Error *err = NULL;
S390FeatGroup group = (S390FeatGroup) opaque; S390FeatGroup group = (S390FeatGroup) opaque;
const S390FeatGroupDef *def = s390_feat_group_def(group); const S390FeatGroupDef *def = s390_feat_group_def(group);
DeviceState *dev = DEVICE(obj); DeviceState *dev = DEVICE(obj);
@ -1059,8 +1076,9 @@ static void set_feature_group(Object *obj, Visitor *v, const char *name,
return; return;
} }
visit_type_bool(v, name, &value, errp); visit_type_bool(v, name, &value, &err);
if (*errp) { if (err) {
error_propagate(errp, err);
return; return;
} }
if (value) { if (value) {

View File

@ -53,6 +53,29 @@ int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3)
#define DIAG_308_RC_NO_CONF 0x0102 #define DIAG_308_RC_NO_CONF 0x0102
#define DIAG_308_RC_INVALID 0x0402 #define DIAG_308_RC_INVALID 0x0402
#define DIAG308_RESET_MOD_CLR 0
#define DIAG308_RESET_LOAD_NORM 1
#define DIAG308_LOAD_CLEAR 3
#define DIAG308_LOAD_NORMAL_DUMP 4
#define DIAG308_SET 5
#define DIAG308_STORE 6
static int diag308_parm_check(CPUS390XState *env, uint64_t r1, uint64_t addr,
uintptr_t ra, bool write)
{
if ((r1 & 1) || (addr & ~TARGET_PAGE_MASK)) {
s390_program_interrupt(env, PGM_SPECIFICATION, ra);
return -1;
}
if (!address_space_access_valid(&address_space_memory, addr,
sizeof(IplParameterBlock), write,
MEMTXATTRS_UNSPECIFIED)) {
s390_program_interrupt(env, PGM_ADDRESSING, ra);
return -1;
}
return 0;
}
void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra) void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra)
{ {
CPUState *cs = env_cpu(env); CPUState *cs = env_cpu(env);
@ -65,30 +88,24 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra)
return; return;
} }
if ((subcode & ~0x0ffffULL) || (subcode > 6)) { if (subcode & ~0x0ffffULL) {
s390_program_interrupt(env, PGM_SPECIFICATION, ra); s390_program_interrupt(env, PGM_SPECIFICATION, ra);
return; return;
} }
switch (subcode) { switch (subcode) {
case 0: case DIAG308_RESET_MOD_CLR:
s390_ipl_reset_request(cs, S390_RESET_MODIFIED_CLEAR); s390_ipl_reset_request(cs, S390_RESET_MODIFIED_CLEAR);
break; break;
case 1: case DIAG308_RESET_LOAD_NORM:
s390_ipl_reset_request(cs, S390_RESET_LOAD_NORMAL); s390_ipl_reset_request(cs, S390_RESET_LOAD_NORMAL);
break; break;
case 3: case DIAG308_LOAD_CLEAR:
/* Well we still lack the clearing bit... */
s390_ipl_reset_request(cs, S390_RESET_REIPL); s390_ipl_reset_request(cs, S390_RESET_REIPL);
break; break;
case 5: case DIAG308_SET:
if ((r1 & 1) || (addr & 0x0fffULL)) { if (diag308_parm_check(env, r1, addr, ra, false)) {
s390_program_interrupt(env, PGM_SPECIFICATION, ra);
return;
}
if (!address_space_access_valid(&address_space_memory, addr,
sizeof(IplParameterBlock), false,
MEMTXATTRS_UNSPECIFIED)) {
s390_program_interrupt(env, PGM_ADDRESSING, ra);
return; return;
} }
iplb = g_new0(IplParameterBlock, 1); iplb = g_new0(IplParameterBlock, 1);
@ -110,15 +127,8 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra)
out: out:
g_free(iplb); g_free(iplb);
return; return;
case 6: case DIAG308_STORE:
if ((r1 & 1) || (addr & 0x0fffULL)) { if (diag308_parm_check(env, r1, addr, ra, true)) {
s390_program_interrupt(env, PGM_SPECIFICATION, ra);
return;
}
if (!address_space_access_valid(&address_space_memory, addr,
sizeof(IplParameterBlock), true,
MEMTXATTRS_UNSPECIFIED)) {
s390_program_interrupt(env, PGM_ADDRESSING, ra);
return; return;
} }
iplb = s390_ipl_get_iplb(); iplb = s390_ipl_get_iplb();

View File

@ -1159,13 +1159,13 @@ void kvm_s390_access_exception(S390CPU *cpu, uint16_t code, uint64_t te_code)
kvm_s390_vcpu_interrupt(cpu, &irq); kvm_s390_vcpu_interrupt(cpu, &irq);
} }
static int kvm_sclp_service_call(S390CPU *cpu, struct kvm_run *run, static void kvm_sclp_service_call(S390CPU *cpu, struct kvm_run *run,
uint16_t ipbh0) uint16_t ipbh0)
{ {
CPUS390XState *env = &cpu->env; CPUS390XState *env = &cpu->env;
uint64_t sccb; uint64_t sccb;
uint32_t code; uint32_t code;
int r = 0; int r;
sccb = env->regs[ipbh0 & 0xf]; sccb = env->regs[ipbh0 & 0xf];
code = env->regs[(ipbh0 & 0xf0) >> 4]; code = env->regs[(ipbh0 & 0xf0) >> 4];
@ -1173,11 +1173,9 @@ static int kvm_sclp_service_call(S390CPU *cpu, struct kvm_run *run,
r = sclp_service_call(env, sccb, code); r = sclp_service_call(env, sccb, code);
if (r < 0) { if (r < 0) {
kvm_s390_program_interrupt(cpu, -r); kvm_s390_program_interrupt(cpu, -r);
} else { return;
setcc(cpu, r);
} }
setcc(cpu, r);
return 0;
} }
static int handle_b2(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1) static int handle_b2(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1)
@ -1240,7 +1238,7 @@ static int handle_b2(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1)
setcc(cpu, 3); setcc(cpu, 3);
break; break;
case PRIV_B2_SCLP_CALL: case PRIV_B2_SCLP_CALL:
rc = kvm_sclp_service_call(cpu, run, ipbh0); kvm_sclp_service_call(cpu, run, ipbh0);
break; break;
default: default:
rc = -1; rc = -1;

View File

@ -254,7 +254,7 @@ static void sigp_initial_cpu_reset(CPUState *cs, run_on_cpu_data arg)
SigpInfo *si = arg.host_ptr; SigpInfo *si = arg.host_ptr;
cpu_synchronize_state(cs); cpu_synchronize_state(cs);
scc->initial_cpu_reset(cs); scc->reset(cs, S390_CPU_RESET_INITIAL);
cpu_synchronize_post_reset(cs); cpu_synchronize_post_reset(cs);
si->cc = SIGP_CC_ORDER_CODE_ACCEPTED; si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
} }
@ -266,7 +266,7 @@ static void sigp_cpu_reset(CPUState *cs, run_on_cpu_data arg)
SigpInfo *si = arg.host_ptr; SigpInfo *si = arg.host_ptr;
cpu_synchronize_state(cs); cpu_synchronize_state(cs);
scc->cpu_reset(cs); scc->reset(cs, S390_CPU_RESET_NORMAL);
cpu_synchronize_post_reset(cs); cpu_synchronize_post_reset(cs);
si->cc = SIGP_CC_ORDER_CODE_ACCEPTED; si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
} }