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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.