From: Fabien Chouteau <chouteau@adacore.com>
To: Scott Wood <scottwood@freescale.com>
Cc: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH] [PowerPC][RFC] booke timers
Date: Tue, 28 Jun 2011 15:35:00 +0200 [thread overview]
Message-ID: <4E09D884.8090700@adacore.com> (raw)
In-Reply-To: <20110627152851.2ad8d560@schlenkerla.am.freescale.net>
Subject: Re: [Qemu-devel] [PATCH] [PowerPC][RFC] booke timers
To: Scott Wood <scottwood@freescale.com>
Cc: qemu-devel@nongnu.org
Bcc:
-=-=-=-=-=-=-=-=-=# Don't remove this line #=-=-=-=-=-=-=-=-=-w
On 27/06/2011 22:28, Scott Wood wrote:
> On Mon, 27 Jun 2011 18:14:06 +0200
> Fabien Chouteau <chouteau@adacore.com> wrote:
>
>> While working on the emulation of the freescale p2010 (e500v2) I realized that
>> there's no implementation of booke's timers features. Currently mpc8544 uses
>> ppc_emb (ppc_emb_timers_init) which is close but not exactly like booke (for
>> example booke uses different SPR).
>
> ppc_emb_timers_init should be renamed something less generic, then.
Agreed, can you help me to find a better name?
>
>> +/* Timer Control Register */
>> +
>> +#define TCR_WP_MASK 0x3 /* Watchdog Timer Period */
>> +#define TCR_WP_SHIFT 30
>> +#define TCR_WRC_MASK 0x3 /* Watchdog Timer Reset Control */
>> +#define TCR_WRC_SHIFT 28
>
> Usually such MASK defines are before shifting right:
>
> #define TCR_WP_MASK 0xc0000000
> #define TCR_WP_SHIFT 30
> #define TCR_WRC_MASK 0x30000000
> #define TCR_WRC_SHIFT 28
>
> That way you can do things like
>
> if (tcr & TCR_WRC_MASK) {
> ...
> }
OK, I will use this kind of declaration:
#define TCR_WP_SHIFT 30 /* Watchdog Timer Period */
#define TCR_WP_MASK (0x3 << TCR_WP_SHIFT)
>
>> +/* Return the time base value at which the FIT will raise an interrupt */
>> +static uint64_t booke_get_fit_target(CPUState *env)
>> +{
>> + uint32_t fp = (env->spr[SPR_BOOKE_TCR] >> TCR_FP_SHIFT) & TCR_FP_MASK;
>> +
>> + /* Only for e500 */
>> + if (env->insns_flags2 & PPC2_BOOKE206) {
>> + uint32_t fpext = (env->spr[SPR_BOOKE_TCR] >> TCR_E500_FPEXT_SHIFT)
>> + & TCR_E500_FPEXT_MASK;
>> + fp |= fpext << 2;
>> + }
>
> BOOKE206 does not mean e500. FPEXT does not exist in Power ISA V2.06 Book
> III-E.
I will try to fix this for v2.
>
>> +
>> + return 1 << fp;
>> +}
>
> The particular bits selected by the possible values of FP are
> implementation-dependent. e500 uses fpext to make all values possible, but
> on 440 the four values of fp select from 2^13, 2^17, 2^21, and 2^25.
>
Maybe I can do something like:
static uint64_t booke_get_fit_target(CPUState *env)
{
uint32_t fp = (env->spr[SPR_BOOKE_TCR] & TCR_FP_MASK) >> TCR_FP_SHIFT;
/* Only for e500 */
if (/* CPU is e500 */) {
uint32_t fpext = (env->spr[SPR_BOOKE_TCR] & TCR_E500_FPEXT_MASK)
>> TCR_E500_FPEXT_SHIFT;
fp |= fpext << 2;
} else {
fp = env->fit_period[fp];
}
return 1 << fp;
}
>> +/* Return the time base value at which the WDT will raise an interrupt */
>> +static uint64_t booke_get_wdt_target(CPUState *env)
>> +{
>> + uint32_t fp = (env->spr[SPR_BOOKE_TCR] >> TCR_WP_SHIFT) & TCR_WP_MASK;
>> +
>> + /* Only for e500 */
>> + if (env->insns_flags2 & PPC2_BOOKE206) {
>> + uint32_t fpext = (env->spr[SPR_BOOKE_TCR] >> TCR_E500_WPEXT_SHIFT)
>> + & TCR_E500_WPEXT_MASK;
>> + fp |= fpext << 2;
>> + }
>> +
>> + return 1 << fp;
>> +}
>
> s/fp/wp/
>
> Avoiding the confusion is especially important on 440, since a different
> interval is selected by a given value in FP versus WP.
Fixed.
>
>> +static void booke_update_fixed_timer(CPUState *env,
>> + uint64_t tb_target,
>> + uint64_t *next,
>> + struct QEMUTimer *timer)
>> +{
>> + ppc_tb_t *tb_env = env->tb_env;
>> + uint64_t lapse;
>> + uint64_t tb;
>> + uint64_t now;
>> +
>> + now = qemu_get_clock_ns(vm_clock);
>> + tb = cpu_ppc_get_tb(tb_env, now, tb_env->tb_offset);
>> +
>> + if (tb_target < tb) {
>> + qemu_del_timer(timer);
>
> You're treating the target as the timebase value that has only the selected
> bit and nothing else -- you want to expire the next time that bit
> transitions from zero to one, regardless of the other bits.
>
> The timer should never be outright disabled.
That's right, I will fix this for v2.
>
>> +static void booke_decr_cb (void *opaque)
>> +{
>> + CPUState *env;
>> + ppc_tb_t *tb_env;
>> + booke_timer_t *booke_timer;
>> +
>> + env = opaque;
>> + tb_env = env->tb_env;
>> + booke_timer = tb_env->opaque;
>> + env->spr[SPR_BOOKE_TSR] |= TSR_DIS;
>> + if (env->spr[SPR_BOOKE_TCR] & TCR_DIE) {
>> + ppc_set_irq(env, booke_timer->decr_excp, 1);
>> + }
>> +
>> + if (env->spr[SPR_BOOKE_TCR] & TCR_ARE) {
>> + /* Auto Reload */
>> + cpu_ppc_store_decr(env, env->spr[SPR_BOOKE_DECAR]);
>> + }
>> +}
>
> I think some changes in the decrementer code are needed to provide booke
> semantics -- no raising the interrupt based on the high bit of decr, and
> stop counting when reach zero.
Can you please explain, I don't see where I'm not compliant with booke's
decrementer.
>
>> +static void booke_wdt_cb (void *opaque)
>> +{
>> + CPUState *env;
>> + ppc_tb_t *tb_env;
>> + booke_timer_t *booke_timer;
>> +
>> + env = opaque;
>> + tb_env = env->tb_env;
>> + booke_timer = tb_env->opaque;
>> +
>> + /* TODO: There's lots of complicated stuff to do here */
>> + abort();
>> +
>> + booke_update_fixed_timer(env,
>> + booke_get_wdt_target(env),
>> + &booke_timer->wdt_next,
>> + booke_timer->wdt_timer);
>> +}
>
> Might want to avoid arming this one until that abort() is fixed...
>
>> +
>> +void store_booke_tsr (CPUState *env, target_ulong val)
>> +{
>> + ppc_tb_t *tb_env = env->tb_env;
>> + booke_timer_t *booke_timer;
>> +
>> + booke_timer = tb_env->opaque;
>> +
>> + env->spr[SPR_BOOKE_TSR] &= ~(val & 0xFC000000);
>
> Do we really need the "& 0xFC000000"? Likewise in TCR.
It's just a mask to keep only the defined bits.
>
>> +
>> + if (val & TSR_DIS) {
>> + ppc_set_irq(env, booke_timer->decr_excp, 0);
>> + }
>> +
>> + if (val & TSR_FIS) {
>> + ppc_set_irq(env, booke_timer->fit_excp, 0);
>> + }
>> +
>> + if (val & TSR_WIS) {
>> + ppc_set_irq(env, booke_timer->wdt_excp, 0);
>> + }
>> +}
>
> It looks like ppc_hw_interrupt() is currently treating these as
> edge-triggered, deasserting upon delivery. It should be level for booke.
This is beyond the scope of this patch.
>
>> +void store_booke_tcr (CPUState *env, target_ulong val)
>> +{
>> + ppc_tb_t *tb_env = env->tb_env;
>> + booke_timer_t *booke_timer = tb_env->opaque;
>> +
>> + tb_env = env->tb_env;
>> + env->spr[SPR_BOOKE_TCR] = val & 0xFFC00000;
>> +
>> + booke_update_fixed_timer(env,
>> + booke_get_fit_target(env),
>> + &booke_timer->fit_next,
>> + booke_timer->fit_timer);
>> +
>> + booke_update_fixed_timer(env,
>> + booke_get_wdt_target(env),
>> + &booke_timer->wdt_next,
>> + booke_timer->wdt_timer);
>> +}
>
> Check for FIS/DIS/WIS -- the corresponding enable bit might have just been
> set.
Can you explain, I don't see the problem.
>
>> + booke_timer->decr_excp = PPC_INTERRUPT_DECR;
>> + booke_timer->fit_excp = PPC_INTERRUPT_FIT;
>> + booke_timer->wdt_excp = PPC_INTERRUPT_WDT;
>
> What do we gain by using this instead of PPC_INTERRUPT_foo directly?
Nothing...
Thanks for your review.
--
Fabien Chouteau
next prev parent reply other threads:[~2011-06-28 13:35 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-06-27 16:14 [Qemu-devel] [PATCH] [PowerPC][RFC] booke timers Fabien Chouteau
2011-06-27 20:28 ` Scott Wood
2011-06-28 13:35 ` Fabien Chouteau [this message]
2011-06-28 17:49 ` Scott Wood
2011-06-30 15:51 ` Fabien Chouteau
2011-06-30 19:26 ` Scott Wood
2011-07-01 8:42 ` Fabien Chouteau
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4E09D884.8090700@adacore.com \
--to=chouteau@adacore.com \
--cc=qemu-devel@nongnu.org \
--cc=scottwood@freescale.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).