diff options
Diffstat (limited to 'target')
| -rw-r--r-- | target/arm/cpu.c | 2 | ||||
| -rw-r--r-- | target/s390x/Makefile.objs | 1 | ||||
| -rw-r--r-- | target/s390x/cpu.c | 57 | ||||
| -rw-r--r-- | target/s390x/cpu.h | 4 | ||||
| -rw-r--r-- | target/s390x/gen-features.c | 2 | ||||
| -rw-r--r-- | target/s390x/helper.h | 1 | ||||
| -rw-r--r-- | target/s390x/insn-data.def | 3 | ||||
| -rw-r--r-- | target/s390x/internal.h | 15 | ||||
| -rw-r--r-- | target/s390x/kvm-stub.c | 4 | ||||
| -rw-r--r-- | target/s390x/kvm.c | 27 | ||||
| -rw-r--r-- | target/s390x/kvm_s390x.h | 6 | ||||
| -rw-r--r-- | target/s390x/machine.c | 6 | ||||
| -rw-r--r-- | target/s390x/misc_helper.c | 66 | ||||
| -rw-r--r-- | target/s390x/tcg-stub.c | 20 | ||||
| -rw-r--r-- | target/s390x/tcg_s390x.h | 18 | ||||
| -rw-r--r-- | target/s390x/translate.c | 9 |
16 files changed, 150 insertions, 91 deletions
diff --git a/target/arm/cpu.c b/target/arm/cpu.c index 82ff450f9a..64a8005a4b 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -239,7 +239,7 @@ static void arm_cpu_reset(CPUState *s) /* Load the initial SP and PC from offset 0 and 4 in the vector table */ vecbase = env->v7m.vecbase[env->v7m.secure]; - rom = rom_ptr(vecbase); + rom = rom_ptr(vecbase, 8); if (rom) { /* Address zero is covered by ROM which hasn't yet been * copied into physical memory. diff --git a/target/s390x/Makefile.objs b/target/s390x/Makefile.objs index 31932de9cf..22a9a9927a 100644 --- a/target/s390x/Makefile.objs +++ b/target/s390x/Makefile.objs @@ -5,6 +5,7 @@ obj-$(CONFIG_SOFTMMU) += machine.o ioinst.o arch_dump.o mmu_helper.o diag.o obj-$(CONFIG_SOFTMMU) += sigp.o obj-$(CONFIG_KVM) += kvm.o obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o +obj-$(call lnot,$(CONFIG_TCG)) += tcg-stub.o # build and run feature list generator feat-src = $(SRC_PATH)/target/$(TARGET_BASE_ARCH)/ diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c index c268065887..271c5ce652 100644 --- a/target/s390x/cpu.c +++ b/target/s390x/cpu.c @@ -30,7 +30,6 @@ #include "kvm_s390x.h" #include "sysemu/kvm.h" #include "qemu-common.h" -#include "qemu/cutils.h" #include "qemu/timer.h" #include "qemu/error-report.h" #include "trace.h" @@ -219,11 +218,18 @@ static void s390_cpu_realizefn(DeviceState *dev, Error **errp) #endif s390_cpu_gdb_init(cs); qemu_init_vcpu(cs); -#if !defined(CONFIG_USER_ONLY) - run_on_cpu(cs, s390_do_cpu_full_reset, RUN_ON_CPU_NULL); -#else - cpu_reset(cs); -#endif + + /* + * KVM requires the initial CPU reset ioctl to be executed on the target + * CPU thread. CPU hotplug under single-threaded TCG will not work with + * run_on_cpu(), as run_on_cpu() will not work properly if called while + * the main thread is already running but the CPU hasn't been realized. + */ + if (kvm_enabled()) { + run_on_cpu(cs, s390_do_cpu_full_reset, RUN_ON_CPU_NULL); + } else { + cpu_reset(cs); + } scc->parent_realize(dev, &err); out: @@ -275,9 +281,6 @@ static void s390_cpu_initfn(Object *obj) CPUState *cs = CPU(obj); S390CPU *cpu = S390_CPU(obj); CPUS390XState *env = &cpu->env; -#if !defined(CONFIG_USER_ONLY) - struct tm tm; -#endif cs->env_ptr = env; cs->halted = 1; @@ -286,10 +289,6 @@ static void s390_cpu_initfn(Object *obj) s390_cpu_get_crash_info_qom, NULL, NULL, NULL, NULL); s390_cpu_model_register_props(obj); #if !defined(CONFIG_USER_ONLY) - qemu_get_timedate(&tm, 0); - env->tod_offset = TOD_UNIX_EPOCH + - (time2tod(mktimegm(&tm)) * 1000000000ULL); - env->tod_basetime = 0; env->tod_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, s390x_tod_timer, cpu); env->cpu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, s390x_cpu_timer, cpu); s390_cpu_set_state(S390_CPU_STATE_STOPPED, cpu); @@ -390,38 +389,6 @@ unsigned int s390_cpu_set_state(uint8_t cpu_state, S390CPU *cpu) return s390_count_running_cpus(); } -int s390_get_clock(uint8_t *tod_high, uint64_t *tod_low) -{ - int r = 0; - - if (kvm_enabled()) { - r = kvm_s390_get_clock_ext(tod_high, tod_low); - if (r == -ENXIO) { - return kvm_s390_get_clock(tod_high, tod_low); - } - } else { - /* Fixme TCG */ - *tod_high = 0; - *tod_low = 0; - } - - return r; -} - -int s390_set_clock(uint8_t *tod_high, uint64_t *tod_low) -{ - int r = 0; - - if (kvm_enabled()) { - r = kvm_s390_set_clock_ext(tod_high, tod_low); - if (r == -ENXIO) { - return kvm_s390_set_clock(tod_high, tod_low); - } - } - /* Fixme TCG */ - return r; -} - int s390_set_memory_limit(uint64_t new_limit, uint64_t *hw_limit) { if (kvm_enabled()) { diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h index 6629a533f3..2c3dd2d189 100644 --- a/target/s390x/cpu.h +++ b/target/s390x/cpu.h @@ -130,8 +130,6 @@ struct CPUS390XState { uint64_t cpuid; #endif - uint64_t tod_offset; - uint64_t tod_basetime; QEMUTimer *tod_timer; QEMUTimer *cpu_timer; @@ -714,8 +712,6 @@ static inline void s390_do_cpu_load_normal(CPUState *cs, run_on_cpu_data arg) /* cpu.c */ -int s390_get_clock(uint8_t *tod_high, uint64_t *tod_low); -int s390_set_clock(uint8_t *tod_high, uint64_t *tod_low); void s390_crypto_reset(void); bool s390_get_squash_mcss(void); int s390_set_memory_limit(uint64_t new_limit, uint64_t *hw_limit); diff --git a/target/s390x/gen-features.c b/target/s390x/gen-features.c index 0cdbc15378..6626b6f565 100644 --- a/target/s390x/gen-features.c +++ b/target/s390x/gen-features.c @@ -512,6 +512,8 @@ static uint16_t default_GEN11_GA1[] = { S390_FEAT_IPTE_RANGE, S390_FEAT_ACCESS_EXCEPTION_FS_INDICATION, S390_FEAT_GROUP_MSA_EXT_4, + S390_FEAT_PPA15, + S390_FEAT_BPB, }; #define default_GEN11_GA2 EmptyFeat diff --git a/target/s390x/helper.h b/target/s390x/helper.h index 59cba86a27..97c60ca7bc 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -127,6 +127,7 @@ DEF_HELPER_4(diag, void, env, i32, i32, i32) DEF_HELPER_3(load_psw, noreturn, env, i64, i64) DEF_HELPER_FLAGS_2(spx, TCG_CALL_NO_RWG, void, env, i64) DEF_HELPER_FLAGS_1(stck, TCG_CALL_NO_RWG_SE, i64, env) +DEF_HELPER_FLAGS_2(sck, TCG_CALL_NO_RWG, i32, env, i64) DEF_HELPER_FLAGS_2(sckc, TCG_CALL_NO_RWG, void, env, i64) DEF_HELPER_FLAGS_2(sckpf, TCG_CALL_NO_RWG, void, env, i64) DEF_HELPER_FLAGS_1(stckc, TCG_CALL_NO_RWG, i64, env) diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index 157619403d..5c6f33ed9c 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -997,8 +997,7 @@ /* SET ADDRESS SPACE CONTROL FAST */ C(0xb279, SACF, S, Z, 0, a2, 0, 0, sacf, 0) /* SET CLOCK */ - /* ??? Not implemented - is it necessary? */ - C(0xb204, SCK, S, Z, 0, 0, 0, 0, 0, 0) + C(0xb204, SCK, S, Z, la2, 0, 0, 0, sck, 0) /* SET CLOCK COMPARATOR */ C(0xb206, SCKC, S, Z, 0, m2_64a, 0, 0, sckc, 0) /* SET CLOCK PROGRAMMABLE FIELD */ diff --git a/target/s390x/internal.h b/target/s390x/internal.h index e392a02d12..f2a771e2b4 100644 --- a/target/s390x/internal.h +++ b/target/s390x/internal.h @@ -237,21 +237,6 @@ enum cc_op { CC_OP_MAX }; -/* The value of the TOD clock for 1.1.1970. */ -#define TOD_UNIX_EPOCH 0x7d91048bca000000ULL - -/* Converts ns to s390's clock format */ -static inline uint64_t time2tod(uint64_t ns) -{ - return (ns << 9) / 125; -} - -/* Converts s390's clock format to ns */ -static inline uint64_t tod2time(uint64_t t) -{ - return (t * 125) >> 9; -} - static inline hwaddr decode_basedisp_s(CPUS390XState *env, uint32_t ipb, uint8_t *ar) { diff --git a/target/s390x/kvm-stub.c b/target/s390x/kvm-stub.c index 29b10542cc..bf7795e47a 100644 --- a/target/s390x/kvm-stub.c +++ b/target/s390x/kvm-stub.c @@ -60,12 +60,12 @@ int kvm_s390_get_clock_ext(uint8_t *tod_high, uint64_t *tod_low) return -ENOSYS; } -int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_low) +int kvm_s390_set_clock(uint8_t tod_high, uint64_t tod_low) { return -ENOSYS; } -int kvm_s390_set_clock_ext(uint8_t *tod_high, uint64_t *tod_low) +int kvm_s390_set_clock_ext(uint8_t tod_high, uint64_t tod_low) { return -ENOSYS; } diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c index ac370da281..d923cf4240 100644 --- a/target/s390x/kvm.c +++ b/target/s390x/kvm.c @@ -666,13 +666,13 @@ int kvm_s390_get_clock_ext(uint8_t *tod_high, uint64_t *tod_low) return r; } -int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_low) +int kvm_s390_set_clock(uint8_t tod_high, uint64_t tod_low) { int r; struct kvm_device_attr attr = { .group = KVM_S390_VM_TOD, .attr = KVM_S390_VM_TOD_LOW, - .addr = (uint64_t)tod_low, + .addr = (uint64_t)&tod_low, }; r = kvm_vm_ioctl(kvm_state, KVM_SET_DEVICE_ATTR, &attr); @@ -681,15 +681,15 @@ int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_low) } attr.attr = KVM_S390_VM_TOD_HIGH; - attr.addr = (uint64_t)tod_high; + attr.addr = (uint64_t)&tod_high; return kvm_vm_ioctl(kvm_state, KVM_SET_DEVICE_ATTR, &attr); } -int kvm_s390_set_clock_ext(uint8_t *tod_high, uint64_t *tod_low) +int kvm_s390_set_clock_ext(uint8_t tod_high, uint64_t tod_low) { struct kvm_s390_vm_tod_clock gtod = { - .epoch_idx = *tod_high, - .tod = *tod_low, + .epoch_idx = tod_high, + .tod = tod_low, }; struct kvm_device_attr attr = { .group = KVM_S390_VM_TOD, @@ -752,12 +752,23 @@ int kvm_s390_mem_op(S390CPU *cpu, vaddr addr, uint8_t ar, void *hostbuf, */ static void *legacy_s390_alloc(size_t size, uint64_t *align, bool shared) { - void *mem; + static void *mem; + + if (mem) { + /* we only support one allocation, which is enough for initial ram */ + return NULL; + } mem = mmap((void *) 0x800000000ULL, size, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED, -1, 0); - return mem == MAP_FAILED ? NULL : mem; + if (mem == MAP_FAILED) { + mem = NULL; + } + if (mem && align) { + *align = QEMU_VMALLOC_ALIGN; + } + return mem; } static uint8_t const *sw_bp_inst; diff --git a/target/s390x/kvm_s390x.h b/target/s390x/kvm_s390x.h index c383bf4ee9..6e52287da3 100644 --- a/target/s390x/kvm_s390x.h +++ b/target/s390x/kvm_s390x.h @@ -10,6 +10,8 @@ #ifndef KVM_S390X_H #define KVM_S390X_H +#include "cpu-qom.h" + struct kvm_s390_irq; void kvm_s390_floating_interrupt_legacy(struct kvm_s390_irq *irq); @@ -25,8 +27,8 @@ int kvm_s390_get_ri(void); int kvm_s390_get_gs(void); int kvm_s390_get_clock(uint8_t *tod_high, uint64_t *tod_clock); int kvm_s390_get_clock_ext(uint8_t *tod_high, uint64_t *tod_clock); -int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_clock); -int kvm_s390_set_clock_ext(uint8_t *tod_high, uint64_t *tod_clock); +int kvm_s390_set_clock(uint8_t tod_high, uint64_t tod_clock); +int kvm_s390_set_clock_ext(uint8_t tod_high, uint64_t tod_clock); void kvm_s390_enable_css_support(S390CPU *cpu); int kvm_s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch, int vq, bool assign); diff --git a/target/s390x/machine.c b/target/s390x/machine.c index 84b4928755..bd3230d027 100644 --- a/target/s390x/machine.c +++ b/target/s390x/machine.c @@ -19,6 +19,7 @@ #include "cpu.h" #include "internal.h" #include "kvm_s390x.h" +#include "tcg_s390x.h" #include "sysemu/kvm.h" static int cpu_post_load(void *opaque, int version_id) @@ -34,6 +35,11 @@ static int cpu_post_load(void *opaque, int version_id) return kvm_s390_vcpu_interrupt_post_load(cpu); } + if (tcg_enabled()) { + /* Rearm the CKC timer if necessary */ + tcg_s390_tod_updated(CPU(cpu), RUN_ON_CPU_NULL); + } + return 0; } diff --git a/target/s390x/misc_helper.c b/target/s390x/misc_helper.c index de1ced2082..3f91579570 100644 --- a/target/s390x/misc_helper.c +++ b/target/s390x/misc_helper.c @@ -28,6 +28,8 @@ #include "qemu/timer.h" #include "exec/exec-all.h" #include "exec/cpu_ldst.h" +#include "qapi/error.h" +#include "tcg_s390x.h" #if !defined(CONFIG_USER_ONLY) #include "sysemu/cpus.h" @@ -39,6 +41,7 @@ #include "hw/s390x/ioinst.h" #include "hw/s390x/s390-pci-inst.h" #include "hw/boards.h" +#include "hw/s390x/tod.h" #endif /* #define DEBUG_HELPER */ @@ -138,30 +141,69 @@ void HELPER(spx)(CPUS390XState *env, uint64_t a1) /* Store Clock */ uint64_t HELPER(stck)(CPUS390XState *env) { - uint64_t time; - - time = env->tod_offset + - time2tod(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - env->tod_basetime); + S390TODState *td = s390_get_todstate(); + S390TODClass *tdc = S390_TOD_GET_CLASS(td); + S390TOD tod; - return time; + tdc->get(td, &tod, &error_abort); + return tod.low; } -/* Set Clock Comparator */ -void HELPER(sckc)(CPUS390XState *env, uint64_t time) +static void update_ckc_timer(CPUS390XState *env) { - if (time == -1ULL) { + S390TODState *td = s390_get_todstate(); + uint64_t time; + + /* stop the timer and remove pending CKC IRQs */ + timer_del(env->tod_timer); + g_assert(qemu_mutex_iothread_locked()); + env->pending_int &= ~INTERRUPT_EXT_CLOCK_COMPARATOR; + + /* the tod has to exceed the ckc, this can never happen if ckc is all 1's */ + if (env->ckc == -1ULL) { return; } - env->ckc = time; - /* difference between origins */ - time -= env->tod_offset; + time = env->ckc - td->base.low; /* nanoseconds */ time = tod2time(time); - timer_mod(env->tod_timer, env->tod_basetime + time); + timer_mod(env->tod_timer, time); +} + +/* Set Clock Comparator */ +void HELPER(sckc)(CPUS390XState *env, uint64_t ckc) +{ + env->ckc = ckc; + + qemu_mutex_lock_iothread(); + update_ckc_timer(env); + qemu_mutex_unlock_iothread(); +} + +void tcg_s390_tod_updated(CPUState *cs, run_on_cpu_data opaque) +{ + S390CPU *cpu = S390_CPU(cs); + + update_ckc_timer(&cpu->env); +} + +/* Set Clock */ +uint32_t HELPER(sck)(CPUS390XState *env, uint64_t tod_low) +{ + S390TODState *td = s390_get_todstate(); + S390TODClass *tdc = S390_TOD_GET_CLASS(td); + S390TOD tod = { + .high = 0, + .low = tod_low, + }; + + qemu_mutex_lock_iothread(); + tdc->set(td, &tod, &error_abort); + qemu_mutex_unlock_iothread(); + return 0; } /* Set Tod Programmable Field */ diff --git a/target/s390x/tcg-stub.c b/target/s390x/tcg-stub.c new file mode 100644 index 0000000000..c93501db0b --- /dev/null +++ b/target/s390x/tcg-stub.c @@ -0,0 +1,20 @@ +/* + * QEMU TCG support -- s390x specific function stubs. + * + * Copyright (C) 2018 Red Hat Inc + * + * Authors: + * David Hildenbrand <david@redhat.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "cpu.h" +#include "tcg_s390x.h" + +void tcg_s390_tod_updated(CPUState *cs, run_on_cpu_data opaque) +{ +} diff --git a/target/s390x/tcg_s390x.h b/target/s390x/tcg_s390x.h new file mode 100644 index 0000000000..4e308aa0ce --- /dev/null +++ b/target/s390x/tcg_s390x.h @@ -0,0 +1,18 @@ +/* + * QEMU TCG support -- s390x specific functions. + * + * Copyright 2018 Red Hat, Inc. + * + * Authors: + * David Hildenbrand <david@redhat.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef TCG_S390X_H +#define TCG_S390X_H + +void tcg_s390_tod_updated(CPUState *cs, run_on_cpu_data opaque); + +#endif /* TCG_S390X_H */ diff --git a/target/s390x/translate.c b/target/s390x/translate.c index fdfec7feba..57c03cbf58 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -4016,6 +4016,15 @@ static DisasJumpType op_stcke(DisasContext *s, DisasOps *o) return DISAS_NEXT; } +static DisasJumpType op_sck(DisasContext *s, DisasOps *o) +{ + check_privileged(s); + tcg_gen_qemu_ld_i64(o->in1, o->addr1, get_mem_index(s), MO_TEQ | MO_ALIGN); + gen_helper_sck(cc_op, cpu_env, o->in1); + set_cc_static(s); + return DISAS_NEXT; +} + static DisasJumpType op_sckc(DisasContext *s, DisasOps *o) { check_privileged(s); |