Re: [Qemu-devel] sparc32 counter/timer issues

2007-09-23 Thread Blue Swirl
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

2007-09-21 Thread Robert Reif

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

2007-09-21 Thread Blue Swirl
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

2007-09-21 Thread Robert Reif

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.