Re: [Qemu-devel] sparc32 counter/timer issues
On 9/22/07, Robert Reif <[EMAIL PROTECTED]> wrote: > With the patch and ss10 boot prom I get: > > TIMER: write 000ff13c > TIMER: write 000ff1310010 0001 > TIMER: write 000ff130 > TIMER: write 000ff134 > TIMER: write 000ff13c 0001 > TIMER: write 000ff130 > TIMER: write 000ff134 > TIMER: get_out: limit 7e00 count 0 > TIMER: read 000ff130 = > > with the last two lines repeating forever. >From this I gather that the user timer mode is not very well implemented. Can you try if this updated version of the patch changes anything? Index: qemu/hw/slavio_timer.c === --- qemu.orig/hw/slavio_timer.c 2007-09-23 07:37:38.0 + +++ qemu/hw/slavio_timer.c 2007-09-23 12:03:07.0 + @@ -47,6 +47,8 @@ * */ +#define MAX_CPUS 16 + typedef struct SLAVIO_TIMERState { qemu_irq irq; ptimer_state *timer; @@ -54,10 +56,13 @@ uint64_t limit; int stopped; int mode; // 0 = processor, 1 = user, 2 = system +struct SLAVIO_TIMERState *slave[MAX_CPUS]; +uint32_t slave_mode; } SLAVIO_TIMERState; #define TIMER_MAXADDR 0x1f #define TIMER_SIZE (TIMER_MAXADDR + 1) +#define CPU_TIMER_SIZE 0x10 // Update count, set irq, update expire_time // Convert from ptimer countdown units @@ -120,7 +125,7 @@ break; case 4: // read user/system mode -ret = s->mode & 1; +ret = s->slave_mode; break; default: ret = 0; @@ -141,10 +146,20 @@ saddr = (addr & TIMER_MAXADDR) >> 2; switch (saddr) { case 0: - // set limit, reset counter +if (s->mode == 1) { +// set user counter limit MSW, reset counter +qemu_irq_lower(s->irq); +s->limit &= 0xfe00ULL; +s->limit |= (uint64_t)val << 32; +if (!s->limit) +s->limit = 0x7e00ULL; +ptimer_set_limit(s->timer, s->limit >> 9, 1); +break; +} +// set limit, reset counter reload = 1; - qemu_irq_lower(s->irq); - // fall through +qemu_irq_lower(s->irq); +// fall through case 2: // set limit without resetting counter s->limit = val & 0x7e00ULL; @@ -152,6 +167,17 @@ s->limit = 0x7e00ULL; ptimer_set_limit(s->timer, s->limit >> 9, reload); break; +case 1: + // set user counter limit LSW, reset counter +if (s->mode == 1) { +qemu_irq_lower(s->irq); +s->limit &= 0x7fffULL; +s->limit |= val & 0xfe00ULL; +if (!s->limit) +s->limit = 0x7e00ULL; +ptimer_set_limit(s->timer, s->limit >> 9, 1); +} +break; case 3: // start/stop user counter if (s->mode == 1) { @@ -167,13 +193,24 @@ break; case 4: // bit 0: user (1) or system (0) counter mode - if (s->mode == 0 || s->mode == 1) - s->mode = val & 1; -if (s->mode == 1) { -qemu_irq_lower(s->irq); -s->limit = -1ULL; +{ +unsigned int i; + +for (i = 0; i < MAX_CPUS; i++) { +if (val & (1 << i)) { +qemu_irq_lower(s->slave[i]->irq); +s->slave[i]->limit = -1ULL; +s->slave[i]->mode = 1; +} else { +s->slave[i]->mode = 0; +} +ptimer_stop(s->slave[i]->timer); +ptimer_set_limit(s->slave[i]->timer, s->slave[i]->limit >> 9, + 1); +ptimer_run(s->slave[i]->timer, 0); +} +s->slave_mode = val & ((1 << MAX_CPUS) - 1); } -ptimer_set_limit(s->timer, s->limit >> 9, 1); break; default: break; @@ -240,7 +277,8 @@ qemu_irq_lower(s->irq); } -void slavio_timer_init(target_phys_addr_t addr, qemu_irq irq, int mode) +static SLAVIO_TIMERState *slavio_timer_init(target_phys_addr_t addr, +qemu_irq irq, int mode) { int slavio_timer_io_memory; SLAVIO_TIMERState *s; @@ -248,7 +286,7 @@ s = qemu_mallocz(sizeof(SLAVIO_TIMERState)); if (!s) -return; +return s; s->irq = irq; s->mode = mode; bh = qemu_bh_new(slavio_timer_irq, s); @@ -257,8 +295,29 @@ slavio_timer_io_memory = cpu_register_io_memory(0, slavio_timer_mem_read, slavio_timer_mem_write, s); -cpu_register_physical_memory(addr, TIMER_SIZE, slavio_timer_io_memory); +if (mode < 2) +cpu_register_physical_memory(addr, CPU_TIMER_SIZE, slavio_timer_io_memory); +else +cpu_register_physical_memory(addr, TIMER_SIZE, + slavio_timer_io_memory); register_savevm("slavio_timer", addr, 2, slavio_timer_save,
Re: [Qemu-devel] sparc32 counter/timer issues
With the patch and ss10 boot prom I get: TIMER: write 000ff13c TIMER: write 000ff1310010 0001 TIMER: write 000ff130 TIMER: write 000ff134 TIMER: write 000ff13c 0001 TIMER: write 000ff130 TIMER: write 000ff134 TIMER: get_out: limit 7e00 count 0 TIMER: read 000ff130 = with the last two lines repeating forever.
Re: [Qemu-devel] sparc32 counter/timer issues
On 9/21/07, Robert Reif <[EMAIL PROTECTED]> wrote: > I'm trying to run a real ss10 openboot prom image rather than > the supplied prom image and found some issues with the way > counters and timers are implemented. It appears that the processor > and system counter/timers are not independent. The system > config register actually configures the processor counter/timers > and the config register is actually a bit mask of the counter/timer > to configure. 1, 2, 4, and 8 are used to as config values for each > processor counter/timer and 0xf is used for setting all of them. > This isn't apparent in the slaveio documentation because it is > for a single cpu only. > > Because the system config register configures the processor > timers, it needs access to all the processor timers (or the > processor timers need access to the system timer). This isn't > how it's currently implemented. Thanks for testing. This patch changes the config register to what you described, everything seems to work like before. Do you see any difference? Index: qemu/hw/slavio_timer.c === --- qemu.orig/hw/slavio_timer.c 2007-09-21 19:30:43.0 + +++ qemu/hw/slavio_timer.c 2007-09-21 20:08:51.0 + @@ -47,6 +47,8 @@ * */ +#define MAX_CPUS 16 + typedef struct SLAVIO_TIMERState { qemu_irq irq; ptimer_state *timer; @@ -54,10 +56,13 @@ uint64_t limit; int stopped; int mode; // 0 = processor, 1 = user, 2 = system +struct SLAVIO_TIMERState *slave[MAX_CPUS]; +uint32_t slave_mode; } SLAVIO_TIMERState; #define TIMER_MAXADDR 0x1f #define TIMER_SIZE (TIMER_MAXADDR + 1) +#define CPU_TIMER_SIZE 0x10 // Update count, set irq, update expire_time // Convert from ptimer countdown units @@ -120,7 +125,7 @@ break; case 4: // read user/system mode -ret = s->mode & 1; +ret = s->slave_mode; break; default: ret = 0; @@ -167,13 +172,22 @@ break; case 4: // bit 0: user (1) or system (0) counter mode - if (s->mode == 0 || s->mode == 1) - s->mode = val & 1; -if (s->mode == 1) { -qemu_irq_lower(s->irq); -s->limit = -1ULL; +{ +unsigned int i; + +for (i = 0; i < MAX_CPUS; i++) { +if (val & (1 << i)) { +qemu_irq_lower(s->slave[i]->irq); +s->slave[i]->limit = -1ULL; +s->slave[i]->mode = 1; +} else { +s->slave[i]->mode = 0; +} +ptimer_set_limit(s->slave[i]->timer, s->slave[i]->limit >> 9, + 1); +} +s->slave_mode = val & ((1 << MAX_CPUS) - 1); } -ptimer_set_limit(s->timer, s->limit >> 9, 1); break; default: break; @@ -240,7 +254,8 @@ qemu_irq_lower(s->irq); } -void slavio_timer_init(target_phys_addr_t addr, qemu_irq irq, int mode) +static SLAVIO_TIMERState *slavio_timer_init(target_phys_addr_t addr, +qemu_irq irq, int mode) { int slavio_timer_io_memory; SLAVIO_TIMERState *s; @@ -248,7 +263,7 @@ s = qemu_mallocz(sizeof(SLAVIO_TIMERState)); if (!s) -return; +return s; s->irq = irq; s->mode = mode; bh = qemu_bh_new(slavio_timer_irq, s); @@ -257,8 +272,29 @@ slavio_timer_io_memory = cpu_register_io_memory(0, slavio_timer_mem_read, slavio_timer_mem_write, s); -cpu_register_physical_memory(addr, TIMER_SIZE, slavio_timer_io_memory); +if (mode < 2) +cpu_register_physical_memory(addr, CPU_TIMER_SIZE, slavio_timer_io_memory); +else +cpu_register_physical_memory(addr, TIMER_SIZE, + slavio_timer_io_memory); register_savevm("slavio_timer", addr, 2, slavio_timer_save, slavio_timer_load, s); qemu_register_reset(slavio_timer_reset, s); slavio_timer_reset(s); + +return s; +} + +void slavio_timer_init_all(target_phys_addr_t base, qemu_irq master_irq, + qemu_irq *cpu_irqs) +{ +SLAVIO_TIMERState *master; +unsigned int i; + +master = slavio_timer_init(base + 0x1ULL, master_irq, 2); + +for (i = 0; i < MAX_CPUS; i++) { +master->slave[i] = slavio_timer_init(base + (target_phys_addr_t) + (i * TARGET_PAGE_SIZE), + cpu_irqs[i], 0); +} } Index: qemu/hw/sun4m.c === --- qemu.orig/hw/sun4m.c 2007-09-21 19:31:14.0 + +++ qemu/hw/sun4m.c 2007-09-21 19:49:54.0 + @@ -379,13 +379,10 @@ nvram = m48t59_init(slavio_irq[0], hwdef->nvram_base, 0, hwdef->nvram_size, 8); -for (i = 0; i < MAX_CPUS; i++) { -slavio_timer_init(hwdef->counter_base + -
[Qemu-devel] sparc32 counter/timer issues
I'm trying to run a real ss10 openboot prom image rather than the supplied prom image and found some issues with the way counters and timers are implemented. It appears that the processor and system counter/timers are not independent. The system config register actually configures the processor counter/timers and the config register is actually a bit mask of the counter/timer to configure. 1, 2, 4, and 8 are used to as config values for each processor counter/timer and 0xf is used for setting all of them. This isn't apparent in the slaveio documentation because it is for a single cpu only. Because the system config register configures the processor timers, it needs access to all the processor timers (or the processor timers need access to the system timer). This isn't how it's currently implemented.