From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1NXJ4D-0001ri-7h for qemu-devel@nongnu.org; Tue, 19 Jan 2010 13:44:41 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1NXJ47-0001pg-Tx for qemu-devel@nongnu.org; Tue, 19 Jan 2010 13:44:40 -0500 Received: from [199.232.76.173] (port=36475 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NXJ47-0001pW-Ex for qemu-devel@nongnu.org; Tue, 19 Jan 2010 13:44:35 -0500 Received: from mail-pz0-f186.google.com ([209.85.222.186]:41744) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1NXJ46-0002Kj-ML for qemu-devel@nongnu.org; Tue, 19 Jan 2010 13:44:35 -0500 Received: by pzk16 with SMTP id 16so3025707pzk.18 for ; Tue, 19 Jan 2010 10:44:33 -0800 (PST) MIME-Version: 1.0 In-Reply-To: <20100118222820.25394.64889.stgit@skyserv> References: <20100118222820.25394.64889.stgit@skyserv> From: Blue Swirl Date: Tue, 19 Jan 2010 18:44:13 +0000 Message-ID: Subject: Re: [Qemu-devel] [PATCH] sparc64: reimplement tick timers v2 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: "Igor V. Kovalenko" Cc: qemu-devel@nongnu.org On Mon, Jan 18, 2010 at 10:28 PM, Igor V. Kovalenko wrote: > From: Igor V. Kovalenko > > sparc64 timer has tick counter which can be set and read, > and tick compare value used as deadline to fire timer interrupt. > The timer is not used as periodic timer, instead deadline > is set each time new timer interrupt is needed. Does not compile: CC sparc64-softmmu/sun4u.o cc1: warnings being treated as errors /src/qemu/hw/sun4u.c: In function 'cpu_tick_set_count': /src/qemu/hw/sun4u.c:467: error: implicit declaration of function 'TIMER_DPRINTF' make[1]: *** [sun4u.o] Error 1 If I add the missing TIMER_DPRINTF, Linux still crashes: Memory: 117376k available (2136k kernel code, 664k data, 184k init) [fffff80000000000,0000000007e80000] SLUB: Genslabs=3D14, HWalign=3D32, Order=3D0-3, MinObjects=3D0, CPUs=3D1, N= odes=3D1 Hierarchical RCU implementation. NR_IRQS:255 clocksource: mult[a0000] shift[16] clockevent: mult[19999999] shift[32] Console: colour dummy device 80x25 Unable to handle kernel NULL pointer dereference tsk->{mm,active_mm}->context =3D 0000000000000000 tsk->{mm,active_mm}->pgd =3D fffff800006fdaa4 \|/ ____ \|/ "@'/ .. \`@" /_| \__/ |_\ \__U_/ swapper(0): Oops [#1] TSTATE: 0000004480001607 TPC: 00000000006e32f4 TNPC: 00000000006e32f8 Y: 00000000 Not tainted TPC: g0: 00000000006a6100 g1: 0000000021bd5b03 g2: 0000000000698f10 g3: 00000000ffff0001 g4: 000000000069d300 g5: fffff8000090e000 g6: 0000000000688000 g7: 0000000000000000 o0: 0000000000000000 o1: 0000000000000220 o2: 0000000000000000 o3: 0000000000040000 o4: 0000000000000000 o5: 00000000006a4ec0 sp: 000000000068b581 ret_pc: 00000000006e32ec RPC: l0: 0000000000000000 l1: 00000000006f3dc8 l2: 0000000000000000 l3: 000000000068be50 l4: 000000000068be40 l5: 0000000000000000 l6: 0000000000000000 l7: 0000000000000000 i0: 0000000000000000 i1: fffff80001002028 i2: 0000000000710470 i3: 0000001000000000 i4: 000000000068be38 i5: fffffffffffffed4 i6: fffff80007e6b501 i7: 000000000048b434 I7: <__rcu_process_callbacks+0x74/0x360> Disabling lock debugging due to kernel taint Caller[000000000048b434]: __rcu_process_callbacks+0x74/0x360 Instruction DUMP: 90100013 7ffca49d c277a7e7 80a04010 086ffffb c25fa7df 9010001d 7ffca496 Kernel panic - not syncing: Attempted to kill the idle task! Call Trace: Impossible unaligned trap. insn=3D81cfe008 \|/ ____ \|/ "@'/ .. \`@" /_| \__/ |_\ \__U_/ swapper(0): Byte sized unaligned access?!?! [#2] TSTATE: 0000000000000000 TPC: 0000000000000000 TNPC: 0000000000000000 Y: 00000000 Tainted: G D TPC: <(null)> etc. > > v1 -> v2: > - new conversion helpers cpu_to_timer_ticks and timer_to_cpu_ticks > - save offset from clock source to implement cpu_tick_set_count > - renamed struct sun4u_timer to CPUTimer > - load and save cpu timers The registered savevm version needs to be increased and we can't handle the old savevm version 5 format any more. > > v0 -> v1: > - coding style > > Signed-off-by: Igor V. Kovalenko > --- > =C2=A0hw/sun4u.c =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 | =C2=A0214 ++= +++++++++++++++++++++++++++++++++++++++------- > =C2=A0target-sparc/cpu.h =C2=A0 =C2=A0 | =C2=A0 =C2=A09 ++ > =C2=A0target-sparc/machine.c | =C2=A0 12 +-- > =C2=A03 files changed, 197 insertions(+), 38 deletions(-) > > diff --git a/hw/sun4u.c b/hw/sun4u.c > index a39b28e..f9db758 100644 > --- a/hw/sun4u.c > +++ b/hw/sun4u.c > @@ -280,6 +280,12 @@ void cpu_check_irqs(CPUState *env) > =C2=A0 =C2=A0 } > =C2=A0} > > +static void cpu_kick_irq(CPUState *env) > +{ > + =C2=A0 =C2=A0env->halted =3D 0; > + =C2=A0 =C2=A0cpu_check_irqs(env); > +} > + > =C2=A0static void cpu_set_irq(void *opaque, int irq, int level) > =C2=A0{ > =C2=A0 =C2=A0 CPUState *env =3D opaque; > @@ -301,6 +307,68 @@ typedef struct ResetData { > =C2=A0 =C2=A0 uint64_t prom_addr; > =C2=A0} ResetData; > > +struct CPUTimer > +{ > + =C2=A0 =C2=A0const char *name; > + =C2=A0 =C2=A0uint32_t =C2=A0 =C2=A0frequency; > + =C2=A0 =C2=A0uint32_t =C2=A0 =C2=A0disabled; > + =C2=A0 =C2=A0uint64_t =C2=A0 =C2=A0disabled_mask; > + =C2=A0 =C2=A0int64_t =C2=A0 =C2=A0 clock_offset; > + =C2=A0 =C2=A0QEMUTimer =C2=A0*qtimer; > +}; > + > +typedef struct CPUTimer CPUTimer; > + > +void cpu_put_timer(QEMUFile *f, CPUTimer *s) > +{ > + =C2=A0 =C2=A0qemu_put_be32s(f, &s->frequency); > + =C2=A0 =C2=A0qemu_put_be32s(f, &s->disabled); > + =C2=A0 =C2=A0qemu_put_be64s(f, &s->disabled_mask); > + =C2=A0 =C2=A0qemu_put_sbe64s(f, &s->clock_offset); > + =C2=A0 =C2=A0if (s->qtimer) { > + =C2=A0 =C2=A0 =C2=A0 =C2=A0qemu_put_timer(f, s->qtimer); > + =C2=A0 =C2=A0} > +} > + > +void cpu_get_timer(QEMUFile *f, CPUTimer *s) > +{ > + =C2=A0 =C2=A0qemu_get_be32s(f, &s->frequency); > + =C2=A0 =C2=A0qemu_get_be32s(f, &s->disabled); > + =C2=A0 =C2=A0qemu_get_be64s(f, &s->disabled_mask); > + =C2=A0 =C2=A0qemu_get_sbe64s(f, &s->clock_offset); > + =C2=A0 =C2=A0if (s->qtimer) { > + =C2=A0 =C2=A0 =C2=A0 =C2=A0qemu_get_timer(f, s->qtimer); > + =C2=A0 =C2=A0} Whether the old state had qtimer non-NULL or not shouldn't affect loading. Likewise, we always want to save. Dynamical state may not affect savevm format. This kind of conditional save/load would be OK, if for example some class of timers didn't ever have the missing piece (because of some hardware difference). > +} > + > +static CPUTimer* cpu_timer_create(const char* name, CPUState *env, > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0QEMUBHFunc *cb, uint32_t fr= equency, > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0uint64_t disabled_mask) > +{ > + =C2=A0 =C2=A0CPUTimer *timer; > + > + =C2=A0 =C2=A0timer =3D qemu_mallocz(sizeof (CPUTimer)); > + > + =C2=A0 =C2=A0timer->name =3D name; > + =C2=A0 =C2=A0timer->frequency =3D frequency; > + =C2=A0 =C2=A0timer->disabled_mask =3D disabled_mask; > + > + =C2=A0 =C2=A0timer->disabled =3D 1; > + =C2=A0 =C2=A0timer->clock_offset =3D qemu_get_clock(vm_clock); > + > + =C2=A0 =C2=A0timer->qtimer =3D qemu_new_timer(vm_clock, cb, env); > + > + =C2=A0 =C2=A0return timer; > +} > + > +static void cpu_timer_reset(CPUTimer *timer) > +{ > + =C2=A0 =C2=A0timer->disabled =3D 1; > + =C2=A0 =C2=A0timer->clock_offset =3D qemu_get_clock(vm_clock); > + > + =C2=A0 =C2=A0qemu_del_timer(timer->qtimer); > +} > + > =C2=A0static void main_cpu_reset(void *opaque) > =C2=A0{ > =C2=A0 =C2=A0 ResetData *s =3D (ResetData *)opaque; > @@ -308,15 +376,11 @@ static void main_cpu_reset(void *opaque) > =C2=A0 =C2=A0 static unsigned int nr_resets; > > =C2=A0 =C2=A0 cpu_reset(env); > - =C2=A0 =C2=A0env->tick_cmpr =3D TICK_INT_DIS | 0; > - =C2=A0 =C2=A0ptimer_set_limit(env->tick, TICK_MAX, 1); > - =C2=A0 =C2=A0ptimer_run(env->tick, 1); > - =C2=A0 =C2=A0env->stick_cmpr =3D TICK_INT_DIS | 0; > - =C2=A0 =C2=A0ptimer_set_limit(env->stick, TICK_MAX, 1); > - =C2=A0 =C2=A0ptimer_run(env->stick, 1); > - =C2=A0 =C2=A0env->hstick_cmpr =3D TICK_INT_DIS | 0; > - =C2=A0 =C2=A0ptimer_set_limit(env->hstick, TICK_MAX, 1); > - =C2=A0 =C2=A0ptimer_run(env->hstick, 1); > + > + =C2=A0 =C2=A0cpu_timer_reset(env->tick); > + =C2=A0 =C2=A0cpu_timer_reset(env->stick); > + =C2=A0 =C2=A0cpu_timer_reset(env->hstick); > + > =C2=A0 =C2=A0 env->gregs[1] =3D 0; // Memory start > =C2=A0 =C2=A0 env->gregs[2] =3D ram_size; // Memory size > =C2=A0 =C2=A0 env->gregs[3] =3D 0; // Machine description XXX > @@ -333,44 +397,133 @@ static void tick_irq(void *opaque) > =C2=A0{ > =C2=A0 =C2=A0 CPUState *env =3D opaque; > > - =C2=A0 =C2=A0if (!(env->tick_cmpr & TICK_INT_DIS)) { > - =C2=A0 =C2=A0 =C2=A0 =C2=A0env->softint |=3D SOFTINT_TIMER; > - =C2=A0 =C2=A0 =C2=A0 =C2=A0cpu_interrupt(env, CPU_INTERRUPT_TIMER); > + =C2=A0 =C2=A0CPUTimer* timer =3D (CPUTimer*) env->tick; I think the cast could be avoided if the typedef were moved into cpu.h. Then also cpu_tick_set_count() and friends could take a non-opaque parameter. > + > + =C2=A0 =C2=A0if (timer->disabled) { > + =C2=A0 =C2=A0 =C2=A0 =C2=A0CPUIRQ_DPRINTF("tick_irq: softint disabled\n= "); > + =C2=A0 =C2=A0 =C2=A0 =C2=A0return; > + =C2=A0 =C2=A0} else { > + =C2=A0 =C2=A0 =C2=A0 =C2=A0CPUIRQ_DPRINTF("tick: fire\n"); > =C2=A0 =C2=A0 } > + > + =C2=A0 =C2=A0env->softint |=3D SOFTINT_TIMER; > + =C2=A0 =C2=A0cpu_kick_irq(env); > =C2=A0} > > =C2=A0static void stick_irq(void *opaque) > =C2=A0{ > =C2=A0 =C2=A0 CPUState *env =3D opaque; > > - =C2=A0 =C2=A0if (!(env->stick_cmpr & TICK_INT_DIS)) { > - =C2=A0 =C2=A0 =C2=A0 =C2=A0env->softint |=3D SOFTINT_STIMER; > - =C2=A0 =C2=A0 =C2=A0 =C2=A0cpu_interrupt(env, CPU_INTERRUPT_TIMER); > + =C2=A0 =C2=A0CPUTimer* timer =3D (CPUTimer*) env->stick; > + > + =C2=A0 =C2=A0if (timer->disabled) { > + =C2=A0 =C2=A0 =C2=A0 =C2=A0CPUIRQ_DPRINTF("stick_irq: softint disabled\= n"); > + =C2=A0 =C2=A0 =C2=A0 =C2=A0return; > + =C2=A0 =C2=A0} else { > + =C2=A0 =C2=A0 =C2=A0 =C2=A0CPUIRQ_DPRINTF("stick: fire\n"); > =C2=A0 =C2=A0 } > + > + =C2=A0 =C2=A0env->softint |=3D SOFTINT_STIMER; > + =C2=A0 =C2=A0cpu_kick_irq(env); > =C2=A0} > > =C2=A0static void hstick_irq(void *opaque) > =C2=A0{ > =C2=A0 =C2=A0 CPUState *env =3D opaque; > > - =C2=A0 =C2=A0if (!(env->hstick_cmpr & TICK_INT_DIS)) { > - =C2=A0 =C2=A0 =C2=A0 =C2=A0cpu_interrupt(env, CPU_INTERRUPT_TIMER); > + =C2=A0 =C2=A0CPUTimer* timer =3D (CPUTimer*) env->hstick; > + > + =C2=A0 =C2=A0if (timer->disabled) { > + =C2=A0 =C2=A0 =C2=A0 =C2=A0CPUIRQ_DPRINTF("hstick_irq: softint disabled= \n"); > + =C2=A0 =C2=A0 =C2=A0 =C2=A0return; > + =C2=A0 =C2=A0} else { > + =C2=A0 =C2=A0 =C2=A0 =C2=A0CPUIRQ_DPRINTF("hstick: fire\n"); > =C2=A0 =C2=A0 } > + > + =C2=A0 =C2=A0env->softint |=3D SOFTINT_STIMER; > + =C2=A0 =C2=A0cpu_kick_irq(env); > +} > + > +static int64_t cpu_to_timer_ticks(int64_t cpu_ticks, uint32_t frequency) > +{ > + =C2=A0 =C2=A0return muldiv64(cpu_ticks, get_ticks_per_sec(), frequency)= ; > +} > + > +static uint64_t timer_to_cpu_ticks(int64_t timer_ticks, uint32_t frequen= cy) > +{ > + =C2=A0 =C2=A0return muldiv64(timer_ticks, frequency, get_ticks_per_sec(= )); > =C2=A0} > > =C2=A0void cpu_tick_set_count(void *opaque, uint64_t count) > =C2=A0{ > - =C2=A0 =C2=A0ptimer_set_count(opaque, -count); > + =C2=A0 =C2=A0CPUTimer *timer =3D opaque; > + > + =C2=A0 =C2=A0uint64_t real_count =C2=A0 =3D count & ~timer->disabled_ma= sk; > + =C2=A0 =C2=A0uint64_t disabled_bit =3D count & timer->disabled_mask; > + > + =C2=A0 =C2=A0int64_t vm_clock_offset =3D qemu_get_clock(vm_clock) - > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0cp= u_to_timer_ticks(real_count, timer->frequency); > + > + =C2=A0 =C2=A0TIMER_DPRINTF("%s set_count count=3D0x%016lx (%s) p=3D%p\n= ", > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0timer->na= me, real_count, > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0timer->di= sabled?"disabled":"enabled", opaque); > + > + =C2=A0 =C2=A0timer->disabled =C2=A0 =C2=A0 =3D disabled_bit ? 1 : 0; > + =C2=A0 =C2=A0timer->clock_offset =3D vm_clock_offset; > =C2=A0} > > =C2=A0uint64_t cpu_tick_get_count(void *opaque) > =C2=A0{ > - =C2=A0 =C2=A0return -ptimer_get_count(opaque); > + =C2=A0 =C2=A0CPUTimer *timer =3D opaque; > + > + =C2=A0 =C2=A0uint64_t real_count =3D timer_to_cpu_ticks( > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0qe= mu_get_clock(vm_clock) - timer->clock_offset, > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ti= mer->frequency); > + > + =C2=A0 =C2=A0TIMER_DPRINTF("%s get_count count=3D0x%016lx (%s) p=3D%p\n= ", > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 timer->name, real_count, > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 timer->disabled?"disabled":"enabled"= , opaque); > + > + =C2=A0 =C2=A0if (timer->disabled) > + =C2=A0 =C2=A0 =C2=A0 =C2=A0real_count |=3D timer->disabled_mask; > + > + =C2=A0 =C2=A0return real_count; > =C2=A0} > > =C2=A0void cpu_tick_set_limit(void *opaque, uint64_t limit) > =C2=A0{ > - =C2=A0 =C2=A0ptimer_set_limit(opaque, -limit, 0); > + =C2=A0 =C2=A0CPUTimer *timer =3D opaque; > + > + =C2=A0 =C2=A0int64_t now =3D qemu_get_clock(vm_clock); > + > + =C2=A0 =C2=A0uint64_t real_limit =3D limit & ~timer->disabled_mask; > + =C2=A0 =C2=A0timer->disabled =3D (limit & timer->disabled_mask) ? 1 : 0= ; > + > + =C2=A0 =C2=A0int64_t expires =3D cpu_to_timer_ticks(real_limit, timer->= frequency) + > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ti= mer->clock_offset; > + > + =C2=A0 =C2=A0if (expires < now) { > + =C2=A0 =C2=A0 =C2=A0 =C2=A0expires =3D now + 1; > + =C2=A0 =C2=A0} > + > + =C2=A0 =C2=A0TIMER_DPRINTF("%s set_limit limit=3D0x%016lx (%s) p=3D%p " > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0"called w= ith limit=3D0x%016lx at 0x%016lx (delta=3D0x%016lx)\n", > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0timer->na= me, real_limit, > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0timer->di= sabled?"disabled":"enabled", > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0opaque, l= imit, > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0timer_to_= cpu_ticks(now - timer->clock_offset, > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 timer->frequency), > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0timer_to_= cpu_ticks(expires - now, timer->frequency)); > + > + =C2=A0 =C2=A0if (!real_limit) { > + =C2=A0 =C2=A0 =C2=A0 =C2=A0TIMER_DPRINTF("%s set_limit limit=3DZERO - n= ot starting timer\n", > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0timer->name); > + =C2=A0 =C2=A0 =C2=A0 =C2=A0qemu_del_timer(timer->qtimer); > + =C2=A0 =C2=A0} else if (timer->disabled) { > + =C2=A0 =C2=A0 =C2=A0 =C2=A0qemu_del_timer(timer->qtimer); > + =C2=A0 =C2=A0} else { > + =C2=A0 =C2=A0 =C2=A0 =C2=A0qemu_mod_timer(timer->qtimer, expires); > + =C2=A0 =C2=A0} > =C2=A0} > > =C2=A0static void ebus_mmio_mapfunc(PCIDevice *pci_dev, int region_num, > @@ -557,9 +710,12 @@ device_init(ram_register_devices); > =C2=A0static CPUState *cpu_devinit(const char *cpu_model, const struct hw= def *hwdef) > =C2=A0{ > =C2=A0 =C2=A0 CPUState *env; > - =C2=A0 =C2=A0QEMUBH *bh; > =C2=A0 =C2=A0 ResetData *reset_info; > > + =C2=A0 =C2=A0uint32_t =C2=A0 tick_frequency =3D 100*1000000; > + =C2=A0 =C2=A0uint32_t =C2=A0stick_frequency =3D 100*1000000; > + =C2=A0 =C2=A0uint32_t hstick_frequency =3D 100*1000000; > + > =C2=A0 =C2=A0 if (!cpu_model) > =C2=A0 =C2=A0 =C2=A0 =C2=A0 cpu_model =3D hwdef->default_cpu_model; > =C2=A0 =C2=A0 env =3D cpu_init(cpu_model); > @@ -567,17 +723,15 @@ static CPUState *cpu_devinit(const char *cpu_model,= const struct hwdef *hwdef) > =C2=A0 =C2=A0 =C2=A0 =C2=A0 fprintf(stderr, "Unable to find Sparc CPU def= inition\n"); > =C2=A0 =C2=A0 =C2=A0 =C2=A0 exit(1); > =C2=A0 =C2=A0 } > - =C2=A0 =C2=A0bh =3D qemu_bh_new(tick_irq, env); > - =C2=A0 =C2=A0env->tick =3D ptimer_init(bh); > - =C2=A0 =C2=A0ptimer_set_period(env->tick, 1ULL); > > - =C2=A0 =C2=A0bh =3D qemu_bh_new(stick_irq, env); > - =C2=A0 =C2=A0env->stick =3D ptimer_init(bh); > - =C2=A0 =C2=A0ptimer_set_period(env->stick, 1ULL); > + =C2=A0 =C2=A0env->tick =3D cpu_timer_create("tick", env, tick_irq, > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0tick_frequency, TICK_NPT_MA= SK); > + > + =C2=A0 =C2=A0env->stick =3D cpu_timer_create("stick", env, stick_irq, > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 stick_frequency, TICK_INT_= DIS); > > - =C2=A0 =C2=A0bh =3D qemu_bh_new(hstick_irq, env); > - =C2=A0 =C2=A0env->hstick =3D ptimer_init(bh); > - =C2=A0 =C2=A0ptimer_set_period(env->hstick, 1ULL); > + =C2=A0 =C2=A0env->hstick =3D cpu_timer_create("hstick", env, hstick_irq= , > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0hstick_frequency, TI= CK_INT_DIS); > > =C2=A0 =C2=A0 reset_info =3D qemu_mallocz(sizeof(ResetData)); > =C2=A0 =C2=A0 reset_info->env =3D env; > diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h > index 50859c7..e50a2ab 100644 > --- a/target-sparc/cpu.h > +++ b/target-sparc/cpu.h > @@ -292,6 +292,11 @@ typedef struct SparcTLBEntry { > =C2=A0 =C2=A0 uint64_t tte; > =C2=A0} SparcTLBEntry; > > +struct CPUTimer; > +struct QEMUFile; > +extern void cpu_put_timer(struct QEMUFile *f, struct CPUTimer *s); > +extern void cpu_get_timer(struct QEMUFile *f, struct CPUTimer *s); "extern" is not needed these days. > + > =C2=A0typedef struct CPUSPARCState { > =C2=A0 =C2=A0 target_ulong gregs[8]; /* general registers */ > =C2=A0 =C2=A0 target_ulong *regwptr; /* pointer to current register windo= w */ > @@ -393,14 +398,14 @@ typedef struct CPUSPARCState { > =C2=A0 =C2=A0 uint64_t mgregs[8]; /* mmu general registers */ > =C2=A0 =C2=A0 uint64_t fprs; > =C2=A0 =C2=A0 uint64_t tick_cmpr, stick_cmpr; > - =C2=A0 =C2=A0void *tick, *stick; > + =C2=A0 =C2=A0struct CPUTimer *tick, *stick; > =C2=A0#define TICK_NPT_MASK =C2=A0 =C2=A0 =C2=A0 =C2=A00x8000000000000000= ULL > =C2=A0#define TICK_INT_DIS =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x8000000000000000= ULL > =C2=A0 =C2=A0 uint64_t gsr; > =C2=A0 =C2=A0 uint32_t gl; // UA2005 > =C2=A0 =C2=A0 /* UA 2005 hyperprivileged registers */ > =C2=A0 =C2=A0 uint64_t hpstate, htstate[MAXTL_MAX], hintp, htba, hver, hs= tick_cmpr, ssr; > - =C2=A0 =C2=A0void *hstick; // UA 2005 > + =C2=A0 =C2=A0struct CPUTimer *hstick; // UA 2005 > =C2=A0 =C2=A0 uint32_t softint; > =C2=A0#define SOFTINT_TIMER =C2=A0 1 > =C2=A0#define SOFTINT_STIMER =C2=A0(1 << 16) > diff --git a/target-sparc/machine.c b/target-sparc/machine.c > index c7c03b6..3fa8232 100644 > --- a/target-sparc/machine.c > +++ b/target-sparc/machine.c > @@ -84,8 +84,8 @@ void cpu_save(QEMUFile *f, void *opaque) > =C2=A0 =C2=A0 qemu_put_be64s(f, &env->fprs); > =C2=A0 =C2=A0 qemu_put_be64s(f, &env->tick_cmpr); > =C2=A0 =C2=A0 qemu_put_be64s(f, &env->stick_cmpr); > - =C2=A0 =C2=A0qemu_put_ptimer(f, env->tick); > - =C2=A0 =C2=A0qemu_put_ptimer(f, env->stick); > + =C2=A0 =C2=A0cpu_put_timer(f, env->tick); > + =C2=A0 =C2=A0cpu_put_timer(f, env->stick); > =C2=A0 =C2=A0 qemu_put_be64s(f, &env->gsr); > =C2=A0 =C2=A0 qemu_put_be32s(f, &env->gl); > =C2=A0 =C2=A0 qemu_put_be64s(f, &env->hpstate); > @@ -96,7 +96,7 @@ void cpu_save(QEMUFile *f, void *opaque) > =C2=A0 =C2=A0 qemu_put_be64s(f, &env->hver); > =C2=A0 =C2=A0 qemu_put_be64s(f, &env->hstick_cmpr); > =C2=A0 =C2=A0 qemu_put_be64s(f, &env->ssr); > - =C2=A0 =C2=A0qemu_put_ptimer(f, env->hstick); > + =C2=A0 =C2=A0cpu_put_timer(f, env->hstick); > =C2=A0#endif > =C2=A0} > > @@ -180,8 +180,8 @@ int cpu_load(QEMUFile *f, void *opaque, int version_i= d) > =C2=A0 =C2=A0 qemu_get_be64s(f, &env->fprs); > =C2=A0 =C2=A0 qemu_get_be64s(f, &env->tick_cmpr); > =C2=A0 =C2=A0 qemu_get_be64s(f, &env->stick_cmpr); > - =C2=A0 =C2=A0qemu_get_ptimer(f, env->tick); > - =C2=A0 =C2=A0qemu_get_ptimer(f, env->stick); > + =C2=A0 =C2=A0cpu_get_timer(f, env->tick); > + =C2=A0 =C2=A0cpu_get_timer(f, env->stick); > =C2=A0 =C2=A0 qemu_get_be64s(f, &env->gsr); > =C2=A0 =C2=A0 qemu_get_be32s(f, &env->gl); > =C2=A0 =C2=A0 qemu_get_be64s(f, &env->hpstate); > @@ -192,7 +192,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_i= d) > =C2=A0 =C2=A0 qemu_get_be64s(f, &env->hver); > =C2=A0 =C2=A0 qemu_get_be64s(f, &env->hstick_cmpr); > =C2=A0 =C2=A0 qemu_get_be64s(f, &env->ssr); > - =C2=A0 =C2=A0qemu_get_ptimer(f, env->hstick); > + =C2=A0 =C2=A0cpu_get_timer(f, env->hstick); > =C2=A0#endif > =C2=A0 =C2=A0 tlb_flush(env, 1); > =C2=A0 =C2=A0 return 0; > > > >