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);
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)
{
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)
{

View file

@ -103,6 +103,9 @@
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[] = {};
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);
}
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);
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);
}
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,
pc_i440fx_4_2_machine_options);

View file

@ -348,7 +348,7 @@ static void pc_q35_machine_options(MachineClass *m)
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);
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);
}
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,
pc_q35_4_2_machine_options);

View file

@ -4491,15 +4491,26 @@ static const TypeInfo spapr_machine_info = {
} \
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
*/
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);
}
DEFINE_SPAPR_MACHINE(4_2, "4.2", true);
DEFINE_SPAPR_MACHINE(4_2, "4.2", false);
/*
* pseries-4.1

View file

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

View file

@ -348,6 +348,9 @@ static void s390_machine_reset(MachineState *machine)
break;
case S390_RESET_LOAD_NORMAL:
CPU_FOREACH(t) {
if (t == cs) {
continue;
}
run_on_cpu(t, s390_do_cpu_reset, RUN_ON_CPU_NULL);
}
subsystem_reset();
@ -639,15 +642,26 @@ bool css_migration_enabled(void)
} \
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)
{
ccw_machine_5_0_instance_options(machine);
}
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);
}
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)
{

View file

@ -102,7 +102,7 @@ again:
if (errno == EAGAIN) {
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;
} else {
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,
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 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;
Error *local_err = NULL;
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 (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,
* 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);
_exit(EXIT_FAILURE);
} else if (pid < 0) {

View file

@ -34,6 +34,12 @@
typedef struct S390CPUModel S390CPUModel;
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:
* @parent_realize: The parent class' realize handler.
@ -57,8 +63,7 @@ typedef struct S390CPUClass {
DeviceRealize parent_realize;
void (*parent_reset)(CPUState *cpu);
void (*load_normal)(CPUState *cpu);
void (*cpu_reset)(CPUState *cpu);
void (*initial_cpu_reset)(CPUState *cpu);
void (*reset)(CPUState *cpu, cpu_reset_type type);
} S390CPUClass;
typedef struct S390CPU S390CPU;

View file

@ -82,53 +82,8 @@ static void s390_cpu_load_normal(CPUState *s)
}
#endif
/* S390CPUClass::cpu_reset() */
static void s390_cpu_reset(CPUState *s)
{
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)
/* S390CPUClass::reset() */
static void s390_cpu_reset(CPUState *s, cpu_reset_type type)
{
S390CPU *cpu = S390_CPU(s);
S390CPUClass *scc = S390_CPU_GET_CLASS(cpu);
@ -138,31 +93,50 @@ static void s390_cpu_full_reset(CPUState *s)
cpu->env.sigp_order = 0;
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 */
env->cregs[0] = CR0_RESET;
env->cregs[14] = CR14_RESET;
/* architectured initial value for Breaking-Event-Address register */
env->gbea = 1;
/* architectured initial values for CR 0 and 14 */
env->cregs[0] = CR0_RESET;
env->cregs[14] = CR14_RESET;
#if defined(CONFIG_USER_ONLY)
/* user mode should always be allowed to use the full FPU */
env->cregs[0] |= CR0_AFP;
if (s390_has_feat(S390_FEAT_VECTOR)) {
env->cregs[0] |= CR0_VECTOR;
}
/* user mode should always be allowed to use the full FPU */
env->cregs[0] |= CR0_AFP;
if (s390_has_feat(S390_FEAT_VECTOR)) {
env->cregs[0] |= CR0_VECTOR;
}
#endif
/* architectured initial value for Breaking-Event-Address register */
env->gbea = 1;
/* tininess for underflow is detected before rounding */
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;
/* tininess for underflow is detected before rounding */
set_float_detect_tininess(float_tininess_before_rounding,
&env->fpu_status);
env->pfault_token = -1UL;
env->bpbc = false;
break;
default:
g_assert_not_reached();
}
/* 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);
}
}
@ -458,6 +432,11 @@ static Property s390x_cpu_properties[] = {
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)
{
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)
scc->load_normal = s390_cpu_load_normal;
#endif
scc->cpu_reset = s390_cpu_reset;
scc->initial_cpu_reset = s390_cpu_initial_reset;
cc->reset = s390_cpu_full_reset;
scc->reset = s390_cpu_reset;
cc->reset = s390_cpu_reset_full;
cc->class_by_name = s390_cpu_class_by_name,
cc->has_work = s390_cpu_has_work;
#ifdef CONFIG_TCG

View file

@ -58,7 +58,6 @@ struct CPUS390XState {
*/
uint64_t vregs[32][2] QEMU_ALIGNED(16); /* vector registers */
uint32_t aregs[16]; /* access registers */
uint8_t riccb[64]; /* runtime instrumentation control */
uint64_t gscb[4]; /* guarded storage control */
uint64_t etoken; /* etoken */
uint64_t etoken_extension; /* etoken extension */
@ -99,10 +98,6 @@ struct CPUS390XState {
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 cputm;
uint32_t todpr;
@ -114,6 +109,14 @@ struct CPUS390XState {
uint64_t gbea;
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 */
struct {} end_reset_fields;
@ -252,6 +255,7 @@ extern const VMStateDescription vmstate_s390_cpu;
#undef PSW_SHIFT_ASC
#undef PSW_MASK_CC
#undef PSW_MASK_PM
#undef PSW_MASK_RI
#undef PSW_SHIFT_MASK_PM
#undef PSW_MASK_64
#undef PSW_MASK_32
@ -273,6 +277,7 @@ extern const VMStateDescription vmstate_s390_cpu;
#define PSW_MASK_CC 0x0000300000000000ULL
#define PSW_MASK_PM 0x00000F0000000000ULL
#define PSW_SHIFT_MASK_PM 40
#define PSW_MASK_RI 0x0000008000000000ULL
#define PSW_MASK_64 0x0000000100000000ULL
#define PSW_MASK_32 0x0000000080000000ULL
#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);
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)
{
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)

View file

@ -462,11 +462,7 @@ CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
.list = NULL,
};
list_data.model = get_max_cpu_model(errp);
if (*errp) {
error_free(*errp);
*errp = NULL;
}
list_data.model = get_max_cpu_model(NULL);
object_class_foreach(create_cpu_model_list, TYPE_S390_CPU, false,
&list_data);
@ -477,6 +473,7 @@ CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
static void cpu_model_from_info(S390CPUModel *model, const CpuModelInfo *info,
Error **errp)
{
Error *err = NULL;
const QDict *qdict = NULL;
const QDictEntry *e;
Visitor *visitor;
@ -513,24 +510,26 @@ static void cpu_model_from_info(S390CPUModel *model, const CpuModelInfo *info,
if (qdict) {
visitor = qobject_input_visitor_new(info->props);
visit_start_struct(visitor, NULL, NULL, 0, errp);
if (*errp) {
visit_start_struct(visitor, NULL, NULL, 0, &err);
if (err) {
error_propagate(errp, err);
visit_free(visitor);
object_unref(obj);
return;
}
for (e = qdict_first(qdict); e; e = qdict_next(qdict, e)) {
object_property_set(obj, visitor, e->key, errp);
if (*errp) {
object_property_set(obj, visitor, e->key, &err);
if (err) {
break;
}
}
if (!*errp) {
if (!err) {
visit_check_struct(visitor, errp);
}
visit_end_struct(visitor, NULL);
visit_free(visitor);
if (*errp) {
if (err) {
error_propagate(errp, err);
object_unref(obj);
return;
}
@ -595,13 +594,15 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
CpuModelInfo *model,
Error **errp)
{
Error *err = NULL;
CpuModelExpansionInfo *expansion_info = NULL;
S390CPUModel s390_model;
bool delta_changes = false;
/* convert it to our internal representation */
cpu_model_from_info(&s390_model, model, errp);
if (*errp) {
cpu_model_from_info(&s390_model, model, &err);
if (err) {
error_propagate(errp, err);
return NULL;
}
@ -634,18 +635,21 @@ CpuModelCompareInfo *qmp_query_cpu_model_comparison(CpuModelInfo *infoa,
CpuModelInfo *infob,
Error **errp)
{
Error *err = NULL;
CpuModelCompareResult feat_result, gen_result;
CpuModelCompareInfo *compare_info;
S390FeatBitmap missing, added;
S390CPUModel modela, modelb;
/* convert both models to our internal representation */
cpu_model_from_info(&modela, infoa, errp);
if (*errp) {
cpu_model_from_info(&modela, infoa, &err);
if (err) {
error_propagate(errp, err);
return NULL;
}
cpu_model_from_info(&modelb, infob, errp);
if (*errp) {
cpu_model_from_info(&modelb, infob, &err);
if (err) {
error_propagate(errp, err);
return NULL;
}
compare_info = g_new0(CpuModelCompareInfo, 1);
@ -707,6 +711,7 @@ CpuModelBaselineInfo *qmp_query_cpu_model_baseline(CpuModelInfo *infoa,
CpuModelInfo *infob,
Error **errp)
{
Error *err = NULL;
CpuModelBaselineInfo *baseline_info;
S390CPUModel modela, modelb, model;
uint16_t cpu_type;
@ -714,13 +719,15 @@ CpuModelBaselineInfo *qmp_query_cpu_model_baseline(CpuModelInfo *infoa,
uint8_t max_gen;
/* convert both models to our internal representation */
cpu_model_from_info(&modela, infoa, errp);
if (*errp) {
cpu_model_from_info(&modela, infoa, &err);
if (err) {
error_propagate(errp, err);
return NULL;
}
cpu_model_from_info(&modelb, infob, errp);
if (*errp) {
cpu_model_from_info(&modelb, infob, &err);
if (err) {
error_propagate(errp, err);
return NULL;
}
@ -870,6 +877,7 @@ static void check_compatibility(const S390CPUModel *max_model,
static S390CPUModel *get_max_cpu_model(Error **errp)
{
Error *err = NULL;
static S390CPUModel max_model;
static bool cached;
@ -878,22 +886,24 @@ static S390CPUModel *get_max_cpu_model(Error **errp)
}
if (kvm_enabled()) {
kvm_s390_get_host_cpu_model(&max_model, errp);
kvm_s390_get_host_cpu_model(&max_model, &err);
} else {
max_model.def = s390_find_cpu_def(QEMU_MAX_CPU_TYPE, QEMU_MAX_CPU_GEN,
QEMU_MAX_CPU_EC_GA, NULL);
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)
{
#ifndef CONFIG_USER_ONLY
Error *err = NULL;
static S390CPUModel applied_model;
static bool applied;
@ -909,20 +919,23 @@ static inline void apply_cpu_model(const S390CPUModel *model, Error **errp)
}
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;
if (model) {
applied_model = *model;
}
applied = true;
if (model) {
applied_model = *model;
}
#endif
}
void s390_realize_cpu_model(CPUState *cs, Error **errp)
{
Error *err = NULL;
S390CPUClass *xcc = S390_CPU_GET_CLASS(cs);
S390CPU *cpu = S390_CPU(cs);
const S390CPUModel *max_model;
@ -939,7 +952,7 @@ void s390_realize_cpu_model(CPUState *cs, Error **errp)
}
max_model = get_max_cpu_model(errp);
if (*errp) {
if (!max_model) {
error_prepend(errp, "CPU models are not available: ");
return;
}
@ -951,8 +964,9 @@ void s390_realize_cpu_model(CPUState *cs, Error **errp)
cpu->model->cpu_ver = max_model->cpu_ver;
check_consistency(cpu->model);
check_compatibility(max_model, cpu->model, errp);
if (*errp) {
check_compatibility(max_model, cpu->model, &err);
if (err) {
error_propagate(errp, err);
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,
void *opaque, Error **errp)
{
Error *err = NULL;
S390Feat feat = (S390Feat) opaque;
DeviceState *dev = DEVICE(obj);
S390CPU *cpu = S390_CPU(obj);
@ -1002,8 +1017,9 @@ static void set_feature(Object *obj, Visitor *v, const char *name,
return;
}
visit_type_bool(v, name, &value, errp);
if (*errp) {
visit_type_bool(v, name, &value, &err);
if (err) {
error_propagate(errp, err);
return;
}
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,
void *opaque, Error **errp)
{
Error *err = NULL;
S390FeatGroup group = (S390FeatGroup) opaque;
const S390FeatGroupDef *def = s390_feat_group_def(group);
DeviceState *dev = DEVICE(obj);
@ -1059,8 +1076,9 @@ static void set_feature_group(Object *obj, Visitor *v, const char *name,
return;
}
visit_type_bool(v, name, &value, errp);
if (*errp) {
visit_type_bool(v, name, &value, &err);
if (err) {
error_propagate(errp, err);
return;
}
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_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)
{
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;
}
if ((subcode & ~0x0ffffULL) || (subcode > 6)) {
if (subcode & ~0x0ffffULL) {
s390_program_interrupt(env, PGM_SPECIFICATION, ra);
return;
}
switch (subcode) {
case 0:
case DIAG308_RESET_MOD_CLR:
s390_ipl_reset_request(cs, S390_RESET_MODIFIED_CLEAR);
break;
case 1:
case DIAG308_RESET_LOAD_NORM:
s390_ipl_reset_request(cs, S390_RESET_LOAD_NORMAL);
break;
case 3:
case DIAG308_LOAD_CLEAR:
/* Well we still lack the clearing bit... */
s390_ipl_reset_request(cs, S390_RESET_REIPL);
break;
case 5:
if ((r1 & 1) || (addr & 0x0fffULL)) {
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);
case DIAG308_SET:
if (diag308_parm_check(env, r1, addr, ra, false)) {
return;
}
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:
g_free(iplb);
return;
case 6:
if ((r1 & 1) || (addr & 0x0fffULL)) {
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);
case DIAG308_STORE:
if (diag308_parm_check(env, r1, addr, ra, true)) {
return;
}
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);
}
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)
{
CPUS390XState *env = &cpu->env;
uint64_t sccb;
uint32_t code;
int r = 0;
int r;
sccb = env->regs[ipbh0 & 0xf];
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);
if (r < 0) {
kvm_s390_program_interrupt(cpu, -r);
} else {
setcc(cpu, r);
return;
}
return 0;
setcc(cpu, r);
}
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);
break;
case PRIV_B2_SCLP_CALL:
rc = kvm_sclp_service_call(cpu, run, ipbh0);
kvm_sclp_service_call(cpu, run, ipbh0);
break;
default:
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;
cpu_synchronize_state(cs);
scc->initial_cpu_reset(cs);
scc->reset(cs, S390_CPU_RESET_INITIAL);
cpu_synchronize_post_reset(cs);
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;
cpu_synchronize_state(cs);
scc->cpu_reset(cs);
scc->reset(cs, S390_CPU_RESET_NORMAL);
cpu_synchronize_post_reset(cs);
si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
}