aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2009-12-21 12:24:17 +0100
committerAurelien Jarno <aurelien@aurel32.net>2009-12-21 13:42:37 +0100
commite3ea652962383a2ffc05b2f1b10a0e97542eb6f8 (patch)
tree7ce782d8d043830083b0aed139da7f28ea591383
parentc4b3be39661d158b3480ad6982dfdee36ec67c7a (diff)
PPC64: Fix timebase
On PPC we have a 64-bit time base. Usually (PPC32) this is accessed using two separate 32 bit SPR accesses to SPR_TBU and SPR_TBL. On PPC64 the SPR_TBL register acts as 64 bit though, so we get the full 64 bits as return value. If we only take the lower ones, fine. But Linux wants to see all 64 bits or it breaks. This patch makes PPC64 Linux work even after TB crossed the 32-bit boundary, which usually happened a few seconds after bootup. Signed-off-by: Alexander Graf <agraf@suse.de> Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
-rw-r--r--darwin-user/main.c4
-rw-r--r--hw/ppc.c4
-rw-r--r--linux-user/main.c4
-rw-r--r--target-ppc/cpu.h2
-rw-r--r--target-ppc/op_helper.c2
5 files changed, 8 insertions, 8 deletions
diff --git a/darwin-user/main.c b/darwin-user/main.c
index 5fd314ecd..2f4a0f827 100644
--- a/darwin-user/main.c
+++ b/darwin-user/main.c
@@ -82,9 +82,9 @@ static inline uint64_t cpu_ppc_get_tb (CPUState *env)
return 0;
}
-uint32_t cpu_ppc_load_tbl (CPUState *env)
+uint64_t cpu_ppc_load_tbl (CPUState *env)
{
- return cpu_ppc_get_tb(env) & 0xFFFFFFFF;
+ return cpu_ppc_get_tb(env);
}
uint32_t cpu_ppc_load_tbu (CPUState *env)
diff --git a/hw/ppc.c b/hw/ppc.c
index 52080394f..b4bf2d37a 100644
--- a/hw/ppc.c
+++ b/hw/ppc.c
@@ -401,7 +401,7 @@ static inline uint64_t cpu_ppc_get_tb(ppc_tb_t *tb_env, uint64_t vmclk,
return muldiv64(vmclk, tb_env->tb_freq, get_ticks_per_sec()) + tb_offset;
}
-uint32_t cpu_ppc_load_tbl (CPUState *env)
+uint64_t cpu_ppc_load_tbl (CPUState *env)
{
ppc_tb_t *tb_env = env->tb_env;
uint64_t tb;
@@ -409,7 +409,7 @@ uint32_t cpu_ppc_load_tbl (CPUState *env)
tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
- return tb & 0xFFFFFFFF;
+ return tb;
}
static inline uint32_t _cpu_ppc_load_tbu(CPUState *env)
diff --git a/linux-user/main.c b/linux-user/main.c
index 12502ad17..5aa9daceb 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -1068,9 +1068,9 @@ static inline uint64_t cpu_ppc_get_tb (CPUState *env)
return 0;
}
-uint32_t cpu_ppc_load_tbl (CPUState *env)
+uint64_t cpu_ppc_load_tbl (CPUState *env)
{
- return cpu_ppc_get_tb(env) & 0xFFFFFFFF;
+ return cpu_ppc_get_tb(env);
}
uint32_t cpu_ppc_load_tbu (CPUState *env)
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 2535cbc0c..2dc301d1e 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -741,7 +741,7 @@ int cpu_ppc_register_internal (CPUPPCState *env, const ppc_def_t *def);
/* Time-base and decrementer management */
#ifndef NO_CPU_IO_DEFS
-uint32_t cpu_ppc_load_tbl (CPUPPCState *env);
+uint64_t cpu_ppc_load_tbl (CPUPPCState *env);
uint32_t cpu_ppc_load_tbu (CPUPPCState *env);
void cpu_ppc_store_tbu (CPUPPCState *env, uint32_t value);
void cpu_ppc_store_tbl (CPUPPCState *env, uint32_t value);
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index e3bd29cc1..e7bcd71f9 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -68,7 +68,7 @@ void helper_store_dump_spr (uint32_t sprn)
target_ulong helper_load_tbl (void)
{
- return cpu_ppc_load_tbl(env);
+ return (target_ulong)cpu_ppc_load_tbl(env);
}
target_ulong helper_load_tbu (void)