qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] ARM ethernet fixes
@ 2005-12-14 22:17 Daniel Jacobowitz
  2005-12-15  0:00 ` Paul Brook
  0 siblings, 1 reply; 16+ messages in thread
From: Daniel Jacobowitz @ 2005-12-14 22:17 UTC (permalink / raw)
  To: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 430 bytes --]

This is enough to let me use apt-get within qemu-system-arm :-)

What it doesn't have, today, is a hard drive.  I have some truly
hideous qemu patches, and a Linux block driver that Paul wrote, that
use ARM "semihosting" traps to simulate a block device using a host
file.  Ideally someone'll get around to emulating the Integrator/AP,
which has a PCI bus, and then we can do it normally.

-- 
Daniel Jacobowitz
CodeSourcery, LLC

[-- Attachment #2: qemu-arm-ethernet.patch --]
[-- Type: text/plain, Size: 2478 bytes --]

Index: qemu/hw/smc91c111.c
===================================================================
--- qemu.orig/hw/smc91c111.c	2005-12-13 19:31:38.000000000 -0800
+++ qemu/hw/smc91c111.c	2005-12-13 19:32:29.000000000 -0800
@@ -35,8 +35,10 @@ typedef struct {
     int tx_fifo[NUM_PACKETS];
     int rx_fifo_len;
     int rx_fifo[NUM_PACKETS];
+    int tx_fifo_done_len;
+    int tx_fifo_done[NUM_PACKETS];
     /* Packet buffer memory.  */
-    uint8_t data[2048][NUM_PACKETS];
+    uint8_t data[NUM_PACKETS][2048];
     uint8_t int_level;
     uint8_t int_mask;
     uint8_t macaddr[6];
@@ -128,6 +130,18 @@ static void smc91c111_pop_rx_fifo(smc91c
     smc91c111_update(s);
 }
 
+/* Remove an item from the TX completion FIFO.  */
+static void smc91c111_pop_tx_fifo_done(smc91c111_state *s)
+{
+    int i;
+
+    if (s->tx_fifo_done_len == 0)
+        return;
+    s->tx_fifo_done_len--;
+    for (i = 0; i < s->tx_fifo_done_len; i++)
+        s->tx_fifo_done[i] = s->tx_fifo_done[i + 1];
+}
+
 /* Release the memory allocated to a packet.  */
 static void smc91c111_release_packet(smc91c111_state *s, int packet)
 {
@@ -184,12 +198,15 @@ static void smc91c111_do_tx(smc91c111_st
         add_crc = 0;
 #endif
         if (s->ctr & CTR_AUTO_RELEASE)
+            /* Race?  */
             smc91c111_release_packet(s, packetnum);
+        else if (s->tx_fifo_done_len < NUM_PACKETS)
+            s->tx_fifo_done[s->tx_fifo_done_len++] = packetnum;
         qemu_send_packet(s->vc, p, len);
     }
-    s->tx_fifo_len = 0;
     if ((s->ctr & CTR_AUTO_RELEASE) == 0)
         s->int_level |= INT_TX;
+    s->tx_fifo_len = 0;
     smc91c111_update(s);
 }
 
@@ -364,6 +381,8 @@ static void smc91c111_writeb(void *opaqu
             return;
         case 12: /* Interrupt ACK.  */
             s->int_level &= ~(value & 0xd6);
+            if (value & INT_TX)
+                smc91c111_pop_tx_fifo_done(s);
             smc91c111_update(s);
             return;
         case 13: /* Interrupt mask.  */
@@ -473,10 +492,10 @@ static uint32_t smc91c111_readb(void *op
         case 3: /* Allocation Result.  */
             return s->tx_alloc;
         case 4: /* TX FIFO */
-            if (s->tx_fifo_len == 0)
+            if (s->tx_fifo_done_len == 0)
                 return 0x80;
             else
-                return s->tx_fifo[0];
+                return s->tx_fifo_done[0];
         case 5: /* RX FIFO */
             if (s->rx_fifo_len == 0)
                 return 0x80;

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] ARM ethernet fixes
  2005-12-14 22:17 [Qemu-devel] ARM ethernet fixes Daniel Jacobowitz
@ 2005-12-15  0:00 ` Paul Brook
  2005-12-18 16:51   ` Paul Brook
  0 siblings, 1 reply; 16+ messages in thread
From: Paul Brook @ 2005-12-15  0:00 UTC (permalink / raw)
  To: qemu-devel

On Wednesday 14 December 2005 22:17, Daniel Jacobowitz wrote:
> This is enough to let me use apt-get within qemu-system-arm :-)

I'd totally missed that there were _two_ TX FIFOs.

> @@ -364,6 +381,8 @@ static void smc91c111_writeb(void *opaqu
>              return;
>          case 12: /* Interrupt ACK.  */
>              s->int_level &= ~(value & 0xd6);
> +            if (value & INT_TX)
> +                smc91c111_pop_tx_fifo_done(s);
>              smc91c111_update(s);
>              return;

I'm fairly sure this is still wrong. We should only clear INT_TX if the tx 
completion fifo is empty. Maybe have smc91c111_update set the INT_TX bit if 
tx_fifo_done_len != 0.

You also need to make smc91c111_reset, smc91c111_writeb: bank 2 offset 0 cmd 2 
(Reset MMU) and smc91c111_writeb: bank 2 offset 0 cmd 7 (Reset TX FIFO) set 
s->tx_fifo_done_len = 0.

Paul

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] ARM ethernet fixes
  2005-12-15  0:00 ` Paul Brook
@ 2005-12-18 16:51   ` Paul Brook
  2005-12-18 17:25     ` Daniel Jacobowitz
  0 siblings, 1 reply; 16+ messages in thread
From: Paul Brook @ 2005-12-18 16:51 UTC (permalink / raw)
  To: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 991 bytes --]

On Thursday 15 December 2005 00:00, Paul Brook wrote:
> On Wednesday 14 December 2005 22:17, Daniel Jacobowitz wrote:
> > This is enough to let me use apt-get within qemu-system-arm :-)
>
> I'd totally missed that there were _two_ TX FIFOs.
>
> > @@ -364,6 +381,8 @@ static void smc91c111_writeb(void *opaqu
> >              return;
> >          case 12: /* Interrupt ACK.  */
> >              s->int_level &= ~(value & 0xd6);
> > +            if (value & INT_TX)
> > +                smc91c111_pop_tx_fifo_done(s);
> >              smc91c111_update(s);
> >              return;
>
> I'm fairly sure this is still wrong. We should only clear INT_TX if the tx
> completion fifo is empty. Maybe have smc91c111_update set the INT_TX bit if
> tx_fifo_done_len != 0.
>
> You also need to make smc91c111_reset, smc91c111_writeb: bank 2 offset 0
> cmd 2 (Reset MMU) and smc91c111_writeb: bank 2 offset 0 cmd 7 (Reset TX
> FIFO) set s->tx_fifo_done_len = 0.

Something like the attached patch.

Paul

[-- Attachment #2: patch --]
[-- Type: text/x-diff, Size: 3115 bytes --]

=== hw/smc91c111.c
==================================================================
--- hw/smc91c111.c	(revision 1912)
+++ hw/smc91c111.c	(local)
@@ -35,8 +35,10 @@
     int tx_fifo[NUM_PACKETS];
     int rx_fifo_len;
     int rx_fifo[NUM_PACKETS];
+    int tx_fifo_done_len;
+    int tx_fifo_done[NUM_PACKETS];
     /* Packet buffer memory.  */
-    uint8_t data[2048][NUM_PACKETS];
+    uint8_t data[NUM_PACKETS][2048];
     uint8_t int_level;
     uint8_t int_mask;
     uint8_t macaddr[6];
@@ -81,6 +83,8 @@
 
     if (s->tx_fifo_len == 0)
         s->int_level |= INT_TX_EMPTY;
+    if (s->tx_fifo_done_len != 0)
+        s->int_level |= INT_TX;
     level = (s->int_level & s->int_mask) != 0;
     pic_set_irq_new(s->pic, s->irq, level);
 }
@@ -128,6 +132,18 @@
     smc91c111_update(s);
 }
 
+/* Remove an item from the TX completion FIFO.  */
+static void smc91c111_pop_tx_fifo_done(smc91c111_state *s)
+{
+    int i;
+
+    if (s->tx_fifo_done_len == 0)
+        return;
+    s->tx_fifo_done_len--;
+    for (i = 0; i < s->tx_fifo_done_len; i++)
+        s->tx_fifo_done[i] = s->tx_fifo_done[i + 1];
+}
+
 /* Release the memory allocated to a packet.  */
 static void smc91c111_release_packet(smc91c111_state *s, int packet)
 {
@@ -184,12 +200,13 @@
         add_crc = 0;
 #endif
         if (s->ctr & CTR_AUTO_RELEASE)
+            /* Race?  */
             smc91c111_release_packet(s, packetnum);
+        else if (s->tx_fifo_done_len < NUM_PACKETS)
+            s->tx_fifo_done[s->tx_fifo_done_len++] = packetnum;
         qemu_send_packet(s->vc, p, len);
     }
     s->tx_fifo_len = 0;
-    if ((s->ctr & CTR_AUTO_RELEASE) == 0)
-        s->int_level |= INT_TX;
     smc91c111_update(s);
 }
 
@@ -206,6 +223,7 @@
 {
     s->bank = 0;
     s->tx_fifo_len = 0;
+    s->tx_fifo_done_len = 0;
     s->rx_fifo_len = 0;
     s->allocated = 0;
     s->packet_num = 0;
@@ -306,6 +324,7 @@
             case 2: /* Reset MMU.  */
                 s->allocated = 0;
                 s->tx_fifo_len = 0;
+                s->tx_fifo_done_len = 0;
                 s->rx_fifo_len = 0;
                 s->tx_alloc = 0;
                 break;
@@ -326,6 +345,7 @@
                 break;
             case 7: /* Reset TX FIFO.  */
                 s->tx_fifo_len = 0;
+                s->tx_fifo_done_len = 0;
                 break;
             }
             return;
@@ -364,6 +384,8 @@
             return;
         case 12: /* Interrupt ACK.  */
             s->int_level &= ~(value & 0xd6);
+            if (value & INT_TX)
+                smc91c111_pop_tx_fifo_done(s);
             smc91c111_update(s);
             return;
         case 13: /* Interrupt mask.  */
@@ -473,10 +495,10 @@
         case 3: /* Allocation Result.  */
             return s->tx_alloc;
         case 4: /* TX FIFO */
-            if (s->tx_fifo_len == 0)
+            if (s->tx_fifo_done_len == 0)
                 return 0x80;
             else
-                return s->tx_fifo[0];
+                return s->tx_fifo_done[0];
         case 5: /* RX FIFO */
             if (s->rx_fifo_len == 0)
                 return 0x80;

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] ARM ethernet fixes
  2005-12-18 16:51   ` Paul Brook
@ 2005-12-18 17:25     ` Daniel Jacobowitz
  2005-12-18 17:42       ` M. Warner Losh
  0 siblings, 1 reply; 16+ messages in thread
From: Daniel Jacobowitz @ 2005-12-18 17:25 UTC (permalink / raw)
  To: Paul Brook; +Cc: qemu-devel

On Sun, Dec 18, 2005 at 04:51:02PM +0000, Paul Brook wrote:
> Something like the attached patch.

After getting myself, and probably Paul, completely confused about
array indexing, I agree that this version is right :-)  It also boots
and appears to work.  Network performance is not very good (averaging
about 10K/s - 30K/s most of the time, but occasionally spiking higher),
but there may be something we can do about that later.  Thanks.


-- 
Daniel Jacobowitz
CodeSourcery, LLC

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] ARM ethernet fixes
  2005-12-18 17:25     ` Daniel Jacobowitz
@ 2005-12-18 17:42       ` M. Warner Losh
  2005-12-18 17:53         ` Paul Brook
  2005-12-18 17:54         ` Daniel Jacobowitz
  0 siblings, 2 replies; 16+ messages in thread
From: M. Warner Losh @ 2005-12-18 17:42 UTC (permalink / raw)
  To: qemu-devel, drow; +Cc: paul

In message: <20051218172558.GA446@nevyn.them.org>
            Daniel Jacobowitz <drow@false.org> writes:
: On Sun, Dec 18, 2005 at 04:51:02PM +0000, Paul Brook wrote:
: > Something like the attached patch.
: 
: After getting myself, and probably Paul, completely confused about
: array indexing, I agree that this version is right :-)  It also boots
: and appears to work.  Network performance is not very good (averaging
: about 10K/s - 30K/s most of the time, but occasionally spiking higher),
: but there may be something we can do about that later.  Thanks.

Given all these improvements in arm support, what's the status of
system level support for arm, and what system is emulated?  You don't
need device emulation to do userland stuf...

Warner

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] ARM ethernet fixes
  2005-12-18 17:42       ` M. Warner Losh
@ 2005-12-18 17:53         ` Paul Brook
  2005-12-18 20:31           ` M. Warner Losh
  2005-12-18 17:54         ` Daniel Jacobowitz
  1 sibling, 1 reply; 16+ messages in thread
From: Paul Brook @ 2005-12-18 17:53 UTC (permalink / raw)
  To: M. Warner Losh; +Cc: qemu-devel

> Given all these improvements in arm support, what's the status of
> system level support for arm, and what system is emulated?  

Short answer is it should work. A default linux kernel config doesn't quite 
work because it hangs probing for a non-existant VGA card. Disable the VGA 
console driver and it's fine.

It emulates most of an Arm Integrator/CP board with an arm1026E cpu.
Available peripherals are two UARTs, and a NIC. More than enough to boot 
linux :-)

> You don't need device emulation to do userland stuf...

No, but it's a diskless board. You either run everything off an initrd, or you 
need network.

Paul

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] ARM ethernet fixes
  2005-12-18 17:42       ` M. Warner Losh
  2005-12-18 17:53         ` Paul Brook
@ 2005-12-18 17:54         ` Daniel Jacobowitz
  2005-12-18 18:50           ` Dave Feustel
  2005-12-18 21:57           ` [Qemu-devel] " Antti P Miettinen
  1 sibling, 2 replies; 16+ messages in thread
From: Daniel Jacobowitz @ 2005-12-18 17:54 UTC (permalink / raw)
  To: M. Warner Losh; +Cc: qemu-devel, paul

On Sun, Dec 18, 2005 at 10:42:16AM -0700, M. Warner Losh wrote:
> In message: <20051218172558.GA446@nevyn.them.org>
>             Daniel Jacobowitz <drow@false.org> writes:
> : On Sun, Dec 18, 2005 at 04:51:02PM +0000, Paul Brook wrote:
> : > Something like the attached patch.
> : 
> : After getting myself, and probably Paul, completely confused about
> : array indexing, I agree that this version is right :-)  It also boots
> : and appears to work.  Network performance is not very good (averaging
> : about 10K/s - 30K/s most of the time, but occasionally spiking higher),
> : but there may be something we can do about that later.  Thanks.
> 
> Given all these improvements in arm support, what's the status of
> system level support for arm, and what system is emulated?  You don't
> need device emulation to do userland stuf...

It's an Integrator/CP.  It has a network card and a serial port, and
that's about it - NFS root works, now that the network card's been
fixed.  I use some "fake hard drive" patches inspired by Paul, and I'll
post them if anyone really, really wants to see them, but they're
hideous.  Emulation of something with PCI and an IDE controller is pretty
high up on my list :-)

It appears to work fairly well.  I was able to run debian-installer in
it with only a few glitches (d-i does not like systems without hard
drives!).

-- 
Daniel Jacobowitz
CodeSourcery, LLC

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] ARM ethernet fixes
  2005-12-18 17:54         ` Daniel Jacobowitz
@ 2005-12-18 18:50           ` Dave Feustel
  2005-12-18 21:57           ` [Qemu-devel] " Antti P Miettinen
  1 sibling, 0 replies; 16+ messages in thread
From: Dave Feustel @ 2005-12-18 18:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: paul

On Sunday 18 December 2005 12:54, Daniel Jacobowitz wrote:
>  Emulation of something with PCI and an IDE controller is pretty
> high up on my list :

Does qemu do StrongARM emulations? There is a nice
StrongARM PCI motherboard from CATS with IDE controllers, etc.
-- 
Lose, v., experience a loss, get rid of, "lose the weight"
Loose, adj., not tight, let go, free, "loose clothing"

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] ARM ethernet fixes
  2005-12-18 17:53         ` Paul Brook
@ 2005-12-18 20:31           ` M. Warner Losh
  0 siblings, 0 replies; 16+ messages in thread
From: M. Warner Losh @ 2005-12-18 20:31 UTC (permalink / raw)
  To: paul; +Cc: qemu-devel

In message: <200512181753.40316.paul@codesourcery.com>
            Paul Brook <paul@codesourcery.com> writes:
: > Given all these improvements in arm support, what's the status of
: > system level support for arm, and what system is emulated?  
: 
: Short answer is it should work. A default linux kernel config doesn't quite 
: work because it hangs probing for a non-existant VGA card. Disable the VGA 
: console driver and it's fine.
: 
: It emulates most of an Arm Integrator/CP board with an arm1026E cpu.
: Available peripherals are two UARTs, and a NIC. More than enough to boot 
: linux :-)

Well, I'm hoping to boot FreeBSD/arm on the thing.  two uarts and a
nic is more than enough to boot FreeBSD as well :-)

: > You don't need device emulation to do userland stuf...
: 
: No, but it's a diskless board. You either run everything off an initrd, or you 
: need network.

That's good to know.

Warner

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Qemu-devel] Re: ARM ethernet fixes
  2005-12-18 17:54         ` Daniel Jacobowitz
  2005-12-18 18:50           ` Dave Feustel
@ 2005-12-18 21:57           ` Antti P Miettinen
  2005-12-18 22:29             ` [Qemu-devel] ARM page crossing inside insn? (Re: ARM ethernet fixes) Antti P Miettinen
  1 sibling, 1 reply; 16+ messages in thread
From: Antti P Miettinen @ 2005-12-18 21:57 UTC (permalink / raw)
  To: qemu-devel

Daniel Jacobowitz <drow@false.org> writes:
> It appears to work fairly well.

I can confirm that. I'm currently debugging a segmentation fault in
compiling one source file of firefox. Something that the current ARM
sysemu can do is e.g.
- boot debian/sid NFS root
- compile gcc far enough to produce a cc1plus with debug info
- run gdb inside emacs to debug cc1plus compiling a ff source file
- run cc1plus under gdb with a breakpoint with ignorecount
- be debugged with arm-linux-gdb

IMHO, thats quite impressive :-)

Might as well describe the thing I'm trying to debug. Dunno what the
exact problem is but it is repeatable. The complete test case is a bit
large, but the segfaulting code qestion looks like:

(gdb) disas $pc-16 $pc+16
Dump of assembler code from 0x31bdac to 0x31bdcc:
0x0031bdac <global_alloc+1016>:	ldr	r1, [r2, #28]
0x0031bdb0 <global_alloc+1020>:	add	r3, r3, r1
0x0031bdb4 <global_alloc+1024>:	str	r3, [r4, #8]
0x0031bdb8 <global_alloc+1028>:	add	r1, r4, #12	; 0xc
0x0031bdbc <global_alloc+1032>:	ldmia	r1, {r1, lr}
0x0031bdc0 <global_alloc+1036>:	ldr	r3, [r0, #16]
0x0031bdc4 <global_alloc+1040>:	ldr	r2, [r3, #32]
0x0031bdc8 <global_alloc+1044>:	add	r1, r1, r2
End of assembler dump.

And the registers before SIGSEGV look like:

(gdb) info reg
r0             0x58ff48	5832520
r1             0x4205effc	1107685372
r2             0x41fc7320	1107063584
r3             0x0	0
r4             0x4205eff0	1107685360
r5             0x29e	670
r6             0x42059008	1107660808
r7             0x5d0ab0	6097584
r8             0x3ba8ea	3909866
r9             0x43d9e8	4446696
r10            0x1	1
r11            0x3ecd20	4115744
r12            0xc	12
sp             0xbef3b234	-1091325388
lr             0x2	2
pc             0x31bdbc	3259836
fps            0x1001010	16781328
cpsr           0x10	16

So it looks like we are about to load a couple of longs from
0x4205effc. But when I step:

(gdb) si

Program received signal SIGSEGV, Segmentation fault.
0x0031bdbc in global_alloc (file=0x0) at ../../src/gcc/global.c:490

Looks like the kernel somehow ends up thinking that we are loading
something from zero. Hmm.. the value being loaded to r1 is zero. So
could this be related to crossing a page boundary in the middle of an
instruction? But anyway - I'll try to debug this further..

-- 
http://www.iki.fi/~ananaza/

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Qemu-devel] ARM page crossing inside insn? (Re: ARM ethernet fixes)
  2005-12-18 21:57           ` [Qemu-devel] " Antti P Miettinen
@ 2005-12-18 22:29             ` Antti P Miettinen
  2005-12-19  9:40               ` [Qemu-devel] " Antti P Miettinen
  0 siblings, 1 reply; 16+ messages in thread
From: Antti P Miettinen @ 2005-12-18 22:29 UTC (permalink / raw)
  To: qemu-devel

Antti P Miettinen <ananaza@iki.fi> writes:
> Looks like the kernel somehow ends up thinking that we are loading
> something from zero. Hmm.. the value being loaded to r1 is zero. So
> could this be related to crossing a page boundary in the middle of an
> instruction? But anyway - I'll try to debug this further..

Looks like it might be the page crossing. The below little program is
a  bit smaller test case. Without args, no segfault, with arg it
segfaults (inside ARM sysemu - at least for me):

#include <stdio.h>
#include <string.h>

long buf[8192/4];

int
main(int ac, char **av)
{
    unsigned long base = (unsigned long)(void *)(buf + 4096/4);
    unsigned long dummy;

    if (ac > 1)
    {
	base &= ~0xfff;
	base -= 4;
    }
    printf("buf: %p, base: 0x%08lx, dummy: 0x%08lx\n", buf, base, dummy);
    __asm__ __volatile__ ("ldmia %0,{%1,%2}"
			  : "=r" (base) : "0" (base), "r" (dummy));
    printf("base: 0x%08lx, dummy: 0x%08lx\n", base, dummy);
    return 0;
}

-- 
http://www.iki.fi/~ananaza/

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Qemu-devel] Re: ARM page crossing inside insn? (Re: ARM ethernet fixes)
  2005-12-18 22:29             ` [Qemu-devel] ARM page crossing inside insn? (Re: ARM ethernet fixes) Antti P Miettinen
@ 2005-12-19  9:40               ` Antti P Miettinen
  2005-12-19 15:24                 ` Antti P Miettinen
  0 siblings, 1 reply; 16+ messages in thread
From: Antti P Miettinen @ 2005-12-19  9:40 UTC (permalink / raw)
  To: qemu-devel

Antti P Miettinen <ananaza@iki.fi> writes:
>     __asm__ __volatile__ ("ldmia %0,{%1,%2}"
> 			  : "=r" (base) : "0" (base), "r" (dummy));

Hmm.. thats probably wrong.. is this closer:

    __asm__ __volatile__ ("ldmia %0,{%0,%1}"
			  : "+r" (base), "=r" (dummy));

or

    __asm__ __volatile__ ("ldmia %2,{%0,%1}"
			  : "=r" (base), "=r" (dummy)
                          : "0" (base));

but anyway - how would the ldm register update be made atomic? Or
should the restart be able to continue in the middle? How are the
atomicity issues handled in qemu?

-- 
http://www.iki.fi/~ananaza/

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Qemu-devel] Re: ARM page crossing inside insn? (Re: ARM ethernet fixes)
  2005-12-19  9:40               ` [Qemu-devel] " Antti P Miettinen
@ 2005-12-19 15:24                 ` Antti P Miettinen
  2005-12-19 16:53                   ` Daniel Jacobowitz
  0 siblings, 1 reply; 16+ messages in thread
From: Antti P Miettinen @ 2005-12-19 15:24 UTC (permalink / raw)
  To: qemu-devel

Antti P Miettinen <ananaza@iki.fi> writes:
> but anyway - how would the ldm register update be made atomic? Or
> should the restart be able to continue in the middle? How are the
> atomicity issues handled in qemu?

I wonder how the ARM implementations handle it..

The below is a quick test how the atomicity could be achieved with
shadow registers. Is this a feasible approach? The diff is not a
proper/complete patch - I just wanted to see whether it makes a
different. It does - the firefox compile proceeds..

Hmm.. do people prefer inline diffs or attachments?

Index: target-arm/cpu.h
===================================================================
RCS file: /sources/qemu/qemu/target-arm/cpu.h,v
retrieving revision 1.13
diff -u -r1.13 cpu.h
--- target-arm/cpu.h	26 Nov 2005 10:46:39 -0000	1.13
+++ target-arm/cpu.h	19 Dec 2005 15:17:14 -0000
@@ -46,6 +46,8 @@
 typedef struct CPUARMState {
     /* Regs for current mode.  */
     uint32_t regs[16];
+    /* Shadow regs for atomic update.  */
+    uint32_t newregs[16];
     /* Frequently accessed CPSR bits are stored separately for efficiently.
        This contains all the other bits.  Use cpsr_{read,write} to accless
        the whole CPSR.  */
Index: target-arm/op.c
===================================================================
RCS file: /sources/qemu/qemu/target-arm/op.c,v
retrieving revision 1.17
diff -u -r1.17 op.c
--- target-arm/op.c	26 Nov 2005 10:46:39 -0000	1.17
+++ target-arm/op.c	19 Dec 2005 15:17:14 -0000
@@ -1175,3 +1175,20 @@
     }
     FORCE_RET();
 }
+
+void OPPROTO op_commit_newregs(void)
+{
+    int regs = PARAM1;
+    int i;
+    //cpu_lock();
+    for (i = 0; i < 15; ++i) {
+	if (regs & (1 << i))
+	    env->regs[i] = env->newregs[i];
+    }
+    //cpu_unlock();
+}
+
+void OPPROTO op_movl_T0_newpc(void)
+{
+  T0 = env->newregs[15];
+}
Index: target-arm/op_template.h
===================================================================
RCS file: /sources/qemu/qemu/target-arm/op_template.h,v
retrieving revision 1.2
diff -u -r1.2 op_template.h
--- target-arm/op_template.h	31 Jan 2005 20:43:28 -0000	1.2
+++ target-arm/op_template.h	19 Dec 2005 15:17:14 -0000
@@ -48,6 +48,21 @@
     SET_REG (T1);
 }
 
+/* For storing to shadow regs to make ldm register update atomic */
+#define regs newregs
+
+void OPPROTO glue(glue(op_movl_, glue(new_, REGNAME)), _T0)(void)
+{
+    SET_REG (T0);
+}
+
+void OPPROTO glue(glue(op_movl_, glue(new_, REGNAME)), _T1)(void)
+{
+    SET_REG (T1);
+}
+
+#undef regs
+
 #undef REG
 #undef REGNAME
 #undef SET_REG
Index: target-arm/translate.c
===================================================================
RCS file: /sources/qemu/qemu/target-arm/translate.c,v
retrieving revision 1.35
diff -u -r1.35 translate.c
--- target-arm/translate.c	18 Dec 2005 16:55:25 -0000	1.35
+++ target-arm/translate.c	19 Dec 2005 15:17:15 -0000
@@ -267,6 +267,45 @@
     },
 };
 
+static GenOpFunc *gen_op_movl_newreg_TN[2][16] = {
+    {
+        gen_op_movl_new_r0_T0,
+        gen_op_movl_new_r1_T0,
+        gen_op_movl_new_r2_T0,
+        gen_op_movl_new_r3_T0,
+        gen_op_movl_new_r4_T0,
+        gen_op_movl_new_r5_T0,
+        gen_op_movl_new_r6_T0,
+        gen_op_movl_new_r7_T0,
+        gen_op_movl_new_r8_T0,
+        gen_op_movl_new_r9_T0,
+        gen_op_movl_new_r10_T0,
+        gen_op_movl_new_r11_T0,
+        gen_op_movl_new_r12_T0,
+        gen_op_movl_new_r13_T0,
+        gen_op_movl_new_r14_T0,
+        gen_op_movl_new_r15_T0,
+    },
+    {
+        gen_op_movl_new_r0_T1,
+        gen_op_movl_new_r1_T1,
+        gen_op_movl_new_r2_T1,
+        gen_op_movl_new_r3_T1,
+        gen_op_movl_new_r4_T1,
+        gen_op_movl_new_r5_T1,
+        gen_op_movl_new_r6_T1,
+        gen_op_movl_new_r7_T1,
+        gen_op_movl_new_r8_T1,
+        gen_op_movl_new_r9_T1,
+        gen_op_movl_new_r10_T1,
+        gen_op_movl_new_r11_T1,
+        gen_op_movl_new_r12_T1,
+        gen_op_movl_new_r13_T1,
+        gen_op_movl_new_r14_T1,
+        gen_op_movl_new_r15_T1,
+    },
+};
+
 static GenOpFunc1 *gen_op_movl_TN_im[3] = {
     gen_op_movl_T0_im,
     gen_op_movl_T1_im,
@@ -341,6 +380,16 @@
     gen_movl_reg_TN(s, reg, 0);
 }
 
+static inline void gen_movl_newreg_T0(int reg)
+{
+    gen_op_movl_newreg_TN[0][reg]();
+}
+
+static inline void gen_movl_newreg_T1(int reg)
+{
+    gen_op_movl_newreg_TN[1][reg]();
+}
+
 static inline void gen_movl_reg_T1(DisasContext *s, int reg)
 {
     gen_movl_reg_TN(s, reg, 1);
@@ -1665,12 +1714,13 @@
                         if (insn & (1 << 20)) {
                             /* load */
                             gen_ldst(ldl, s);
-                            if (i == 15) {
+                            if (0 && i == 15) {
                                 gen_bx(s);
                             } else if (user) {
                                 gen_op_movl_user_T0(i);
                             } else {
-                                gen_movl_reg_T0(s, i);
+                                gen_movl_newreg_T0(i);
+				//gen_movl_reg_T0(s, i);
                             }
                         } else {
                             /* store */
@@ -1691,6 +1741,15 @@
                             gen_op_addl_T1_im(4);
                     }
                 }
+		if (/*0 &&*/ (insn & (1 << 20)) && !user) {
+		    /* commit the loaded registers */
+		    gen_op_commit_newregs(insn & 0xffff);
+		    if (insn & (1 << 15)) {
+			/* PC updated */
+			gen_op_movl_T0_newpc();
+			gen_bx(s);
+		    }
+		}
                 if (insn & (1 << 21)) {
                     /* write back */
                     if (insn & (1 << 23)) {

-- 
http://www.iki.fi/~ananaza/

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] Re: ARM page crossing inside insn? (Re: ARM ethernet fixes)
  2005-12-19 15:24                 ` Antti P Miettinen
@ 2005-12-19 16:53                   ` Daniel Jacobowitz
  2005-12-19 19:25                     ` Antti P Miettinen
  0 siblings, 1 reply; 16+ messages in thread
From: Daniel Jacobowitz @ 2005-12-19 16:53 UTC (permalink / raw)
  To: ananaza, qemu-devel

On Mon, Dec 19, 2005 at 05:24:48PM +0200, Antti P Miettinen wrote:
> Antti P Miettinen <ananaza@iki.fi> writes:
> > but anyway - how would the ldm register update be made atomic? Or
> > should the restart be able to continue in the middle? How are the
> > atomicity issues handled in qemu?
> 
> I wonder how the ARM implementations handle it..
> 
> The below is a quick test how the atomicity could be achieved with
> shadow registers. Is this a feasible approach? The diff is not a
> proper/complete patch - I just wanted to see whether it makes a
> different. It does - the firefox compile proceeds..

You don't need anything near this complicated: if the register being
set is the base register, copy it into T2 instead of overwriting the
base register.  Then at the end, if the base register was loaded, copy
T2 into the base register.  That's all the atomicity you need; the
instruction is being restarted after the base register was clobbered.

-- 
Daniel Jacobowitz
CodeSourcery, LLC

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Qemu-devel] Re: ARM page crossing inside insn? (Re: ARM ethernet fixes)
  2005-12-19 16:53                   ` Daniel Jacobowitz
@ 2005-12-19 19:25                     ` Antti P Miettinen
  2005-12-26  2:30                       ` Antti P Miettinen
  0 siblings, 1 reply; 16+ messages in thread
From: Antti P Miettinen @ 2005-12-19 19:25 UTC (permalink / raw)
  To: qemu-devel

Daniel Jacobowitz <drow@false.org> writes:
> You don't need anything near this complicated: if the register being
> set is the base register, copy it into T2 instead of overwriting the
> base register.  Then at the end, if the base register was loaded, copy
> T2 into the base register.  That's all the atomicity you need; the
> instruction is being restarted after the base register was clobbered.

Eee.. I knew that. I was just.. practicing my fingers (ahem.. is there
a saying in english about how the whole body suffers from a stupid
head? :-)

Something like this?

Index: target-arm/op.c
===================================================================
RCS file: /sources/qemu/qemu/target-arm/op.c,v
retrieving revision 1.17
diff -u -r1.17 op.c
--- target-arm/op.c	26 Nov 2005 10:46:39 -0000	1.17
+++ target-arm/op.c	19 Dec 2005 19:14:45 -0000
@@ -106,6 +106,11 @@
     T0 = T1;
 }
 
+void OPPROTO op_movl_T2_T0(void)
+{
+    T2 = T0;
+}
+
 void OPPROTO op_movl_T1_im(void)
 {
     T1 = PARAM1;
@@ -1175,3 +1180,18 @@
     }
     FORCE_RET();
 }
+
+void OPPROTO op_movl_user_T2(void)
+{
+    int regno = PARAM1;
+    if (regno == 13) {
+        env->banked_r13[0] = T2;
+    } else if (regno == 14) {
+        env->banked_r14[0] = T2;
+    } else if ((env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_FIQ) {
+        env->usr_regs[regno - 8] = T2;
+    } else {
+        env->regs[regno] = T2;
+    }
+    FORCE_RET();
+}
Index: target-arm/op_template.h
===================================================================
RCS file: /sources/qemu/qemu/target-arm/op_template.h,v
retrieving revision 1.2
diff -u -r1.2 op_template.h
--- target-arm/op_template.h	31 Jan 2005 20:43:28 -0000	1.2
+++ target-arm/op_template.h	19 Dec 2005 19:14:45 -0000
@@ -48,6 +48,11 @@
     SET_REG (T1);
 }
 
+void OPPROTO glue(glue(op_movl_, REGNAME), _T2)(void)
+{
+    SET_REG (T2);
+}
+
 #undef REG
 #undef REGNAME
 #undef SET_REG
Index: target-arm/translate.c
===================================================================
RCS file: /sources/qemu/qemu/target-arm/translate.c,v
retrieving revision 1.35
diff -u -r1.35 translate.c
--- target-arm/translate.c	18 Dec 2005 16:55:25 -0000	1.35
+++ target-arm/translate.c	19 Dec 2005 19:14:46 -0000
@@ -228,7 +228,7 @@
     },
 };
 
-static GenOpFunc *gen_op_movl_reg_TN[2][16] = {
+static GenOpFunc *gen_op_movl_reg_TN[3][16] = {
     {
         gen_op_movl_r0_T0,
         gen_op_movl_r1_T0,
@@ -265,6 +265,24 @@
         gen_op_movl_r14_T1,
         gen_op_movl_r15_T1,
     },
+    {
+        gen_op_movl_r0_T2,
+        gen_op_movl_r1_T2,
+        gen_op_movl_r2_T2,
+        gen_op_movl_r3_T2,
+        gen_op_movl_r4_T2,
+        gen_op_movl_r5_T2,
+        gen_op_movl_r6_T2,
+        gen_op_movl_r7_T2,
+        gen_op_movl_r8_T2,
+        gen_op_movl_r9_T2,
+        gen_op_movl_r10_T2,
+        gen_op_movl_r11_T2,
+        gen_op_movl_r12_T2,
+        gen_op_movl_r13_T2,
+        gen_op_movl_r14_T2,
+        gen_op_movl_r15_T2,
+    },
 };
 
 static GenOpFunc1 *gen_op_movl_TN_im[3] = {
@@ -1665,8 +1683,11 @@
                         if (insn & (1 << 20)) {
                             /* load */
                             gen_ldst(ldl, s);
-                            if (i == 15) {
-                                gen_bx(s);
+			    if (i == 15) {
+				/* later */
+			    } else if (i == rn) {
+				/* base register */
+				gen_op_movl_T2_T0();
                             } else if (user) {
                                 gen_op_movl_user_T0(i);
                             } else {
@@ -1691,6 +1712,19 @@
                             gen_op_addl_T1_im(4);
                     }
                 }
+		if (insn & (1 << 20)) {
+		    /* check if base register and pc were loaded */
+		    if (insn & (1 << rn)) {
+			if (user)
+			    gen_op_movl_user_T2(rn);
+			else
+			    gen_op_movl_reg_TN[2][rn]();
+		    }
+		    if (insn & (1 << 15)) {
+			/* r15 is loaded last - value should be in T0 */
+			gen_bx(s);
+		    }
+		}
                 if (insn & (1 << 21)) {
                     /* write back */
                     if (insn & (1 << 23)) {


-- 
http://www.iki.fi/~ananaza/

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Qemu-devel] Re: ARM page crossing inside insn? (Re: ARM ethernet fixes)
  2005-12-19 19:25                     ` Antti P Miettinen
@ 2005-12-26  2:30                       ` Antti P Miettinen
  0 siblings, 0 replies; 16+ messages in thread
From: Antti P Miettinen @ 2005-12-26  2:30 UTC (permalink / raw)
  To: qemu-devel

Antti P Miettinen <ananaza@iki.fi> writes:
> Something like this?

Hmm.. I suppose the branch should be the last op to generate if PC is
loaded by the ldm. So the possible gen_bx should be after the
writeback? But what about the S bit? Or is this all highly academic?
Does ldm ever load pc in practice?

Anyway - I managed to rebuild firefox with debug info and found where
it segfaulted. And with the below change it runs :-)

diff -ur firefox-1.4.99+1.5rc3.dfsg/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_arm.cpp /usr/local/arm/sid/home/apm/src/firefox-1.4.99+1.5rc3.dfsg/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_arm.cpp
--- firefox-1.4.99+1.5rc3.dfsg/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_arm.cpp	2005-10-14 00:33:10.000000000 +0300
+++ /usr/local/arm/sid/home/apm/src/firefox-1.4.99+1.5rc3.dfsg/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_arm.cpp	2005-12-25 15:15:46.000000000 +0200
@@ -212,7 +212,7 @@
     "add	sp, sp, r4	\n\t"	/* restore stack pointer		*/
     "mov	%0, r0		\n\t"	/* the result...			*/
     : "=r" (result)
-    : "r" (&my_params)
+    : "r" (&my_params), "m" (my_params)
     : "r0", "r1", "r2", "r3", "r4", "ip", "lr", "sp"
     );
     
-- 
http://www.iki.fi/~ananaza/

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2005-12-26  2:32 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-12-14 22:17 [Qemu-devel] ARM ethernet fixes Daniel Jacobowitz
2005-12-15  0:00 ` Paul Brook
2005-12-18 16:51   ` Paul Brook
2005-12-18 17:25     ` Daniel Jacobowitz
2005-12-18 17:42       ` M. Warner Losh
2005-12-18 17:53         ` Paul Brook
2005-12-18 20:31           ` M. Warner Losh
2005-12-18 17:54         ` Daniel Jacobowitz
2005-12-18 18:50           ` Dave Feustel
2005-12-18 21:57           ` [Qemu-devel] " Antti P Miettinen
2005-12-18 22:29             ` [Qemu-devel] ARM page crossing inside insn? (Re: ARM ethernet fixes) Antti P Miettinen
2005-12-19  9:40               ` [Qemu-devel] " Antti P Miettinen
2005-12-19 15:24                 ` Antti P Miettinen
2005-12-19 16:53                   ` Daniel Jacobowitz
2005-12-19 19:25                     ` Antti P Miettinen
2005-12-26  2:30                       ` Antti P Miettinen

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).