mirror of https://github.com/xemu-project/xemu.git
s390x/tcg: implement extract-CPU-time facility
It only provides the EXTRACT CPU TIME instruction. We can reuse the stpt helper, which calculates the CPU timer value. As the instruction is not privileged, but we don't have a CPU timer value in case of linux user, we simply reuse cpu_get_host_ticks() to produce some descending value. Signed-off-by: David Hildenbrand <david@redhat.com> Message-Id: <20171208160207.26494-13-david@redhat.com> Signed-off-by: Cornelia Huck <cohuck@redhat.com>
This commit is contained in:
parent
ad0ccf1e6a
commit
4bac52f5c4
|
@ -834,6 +834,7 @@ static void add_qemu_cpu_model_features(S390FeatBitmap fbm)
|
|||
S390_FEAT_STORE_CLOCK_FAST,
|
||||
S390_FEAT_MOVE_WITH_OPTIONAL_SPEC,
|
||||
S390_FEAT_ETF3_ENH,
|
||||
S390_FEAT_EXTRACT_CPU_TIME,
|
||||
S390_FEAT_COMPARE_AND_SWAP_AND_STORE,
|
||||
S390_FEAT_COMPARE_AND_SWAP_AND_STORE_2,
|
||||
S390_FEAT_GENERAL_INSTRUCTIONS_EXT,
|
||||
|
|
|
@ -119,6 +119,7 @@ DEF_HELPER_4(cu24, i32, env, i32, i32, i32)
|
|||
DEF_HELPER_4(cu41, i32, env, i32, i32, i32)
|
||||
DEF_HELPER_4(cu42, i32, env, i32, i32, i32)
|
||||
DEF_HELPER_5(msa, i32, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_1(stpt, TCG_CALL_NO_RWG, i64, env)
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
DEF_HELPER_3(servc, i32, env, i64, i64)
|
||||
|
@ -130,7 +131,6 @@ 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)
|
||||
DEF_HELPER_FLAGS_2(spt, TCG_CALL_NO_RWG, void, env, i64)
|
||||
DEF_HELPER_FLAGS_1(stpt, TCG_CALL_NO_RWG, i64, env)
|
||||
DEF_HELPER_4(stsi, i32, env, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_4(lctl, TCG_CALL_NO_WG, void, env, i32, i64, i32)
|
||||
DEF_HELPER_FLAGS_4(lctlg, TCG_CALL_NO_WG, void, env, i32, i64, i32)
|
||||
|
|
|
@ -369,6 +369,8 @@
|
|||
C(0xb24f, EAR, RRE, Z, 0, 0, new, r1_32, ear, 0)
|
||||
/* EXTRACT CPU ATTRIBUTE */
|
||||
C(0xeb4c, ECAG, RSY_a, GIE, 0, a2, r1, 0, ecag, 0)
|
||||
/* EXTRACT CPU TIME */
|
||||
C(0xc801, ECTG, SSF, ECT, 0, 0, 0, 0, ectg, 0)
|
||||
/* EXTRACT FPC */
|
||||
C(0xb38c, EFPC, RRE, Z, 0, 0, new, r1_32, efpc, 0)
|
||||
/* EXTRACT PSW */
|
||||
|
|
|
@ -55,6 +55,21 @@ void HELPER(exception)(CPUS390XState *env, uint32_t excp)
|
|||
cpu_loop_exit(cs);
|
||||
}
|
||||
|
||||
/* Store CPU Timer (also used for EXTRACT CPU TIME) */
|
||||
uint64_t HELPER(stpt)(CPUS390XState *env)
|
||||
{
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
/*
|
||||
* Fake a descending CPU timer. We could get negative values here,
|
||||
* but we don't care as it is up to the OS when to process that
|
||||
* interrupt and reset to > 0.
|
||||
*/
|
||||
return UINT64_MAX - (uint64_t)cpu_get_host_ticks();
|
||||
#else
|
||||
return time2tod(env->cputm - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
|
||||
/* SCLP service call */
|
||||
|
@ -178,12 +193,6 @@ void HELPER(spt)(CPUS390XState *env, uint64_t time)
|
|||
timer_mod(env->cpu_timer, env->cputm);
|
||||
}
|
||||
|
||||
/* Store CPU Timer */
|
||||
uint64_t HELPER(stpt)(CPUS390XState *env)
|
||||
{
|
||||
return time2tod(env->cputm - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
|
||||
}
|
||||
|
||||
/* Store System Information */
|
||||
uint32_t HELPER(stsi)(CPUS390XState *env, uint64_t a0,
|
||||
uint64_t r0, uint64_t r1)
|
||||
|
|
|
@ -3917,6 +3917,36 @@ static ExitStatus op_spm(DisasContext *s, DisasOps *o)
|
|||
return NO_EXIT;
|
||||
}
|
||||
|
||||
static ExitStatus op_ectg(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
int b1 = get_field(s->fields, b1);
|
||||
int d1 = get_field(s->fields, d1);
|
||||
int b2 = get_field(s->fields, b2);
|
||||
int d2 = get_field(s->fields, d2);
|
||||
int r3 = get_field(s->fields, r3);
|
||||
TCGv_i64 tmp = tcg_temp_new_i64();
|
||||
|
||||
/* fetch all operands first */
|
||||
o->in1 = tcg_temp_new_i64();
|
||||
tcg_gen_addi_i64(o->in1, regs[b1], d1);
|
||||
o->in2 = tcg_temp_new_i64();
|
||||
tcg_gen_addi_i64(o->in2, regs[b2], d2);
|
||||
o->addr1 = get_address(s, 0, r3, 0);
|
||||
|
||||
/* load the third operand into r3 before modifying anything */
|
||||
tcg_gen_qemu_ld64(regs[r3], o->addr1, get_mem_index(s));
|
||||
|
||||
/* subtract CPU timer from first operand and store in GR0 */
|
||||
gen_helper_stpt(tmp, cpu_env);
|
||||
tcg_gen_sub_i64(regs[0], o->in1, tmp);
|
||||
|
||||
/* store second operand in GR1 */
|
||||
tcg_gen_mov_i64(regs[1], o->in2);
|
||||
|
||||
tcg_temp_free_i64(tmp);
|
||||
return NO_EXIT;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
static ExitStatus op_spka(DisasContext *s, DisasOps *o)
|
||||
{
|
||||
|
@ -5679,6 +5709,7 @@ enum DisasInsnEnum {
|
|||
#define FAC_MSA3 S390_FEAT_MSA_EXT_3 /* msa-extension-3 facility */
|
||||
#define FAC_MSA4 S390_FEAT_MSA_EXT_4 /* msa-extension-4 facility */
|
||||
#define FAC_MSA5 S390_FEAT_MSA_EXT_5 /* msa-extension-5 facility */
|
||||
#define FAC_ECT S390_FEAT_EXTRACT_CPU_TIME
|
||||
|
||||
static const DisasInsn insn_info[] = {
|
||||
#include "insn-data.def"
|
||||
|
|
Loading…
Reference in New Issue