[Qemu-devel] [PATCH] linux-user/mmap v3: Testsuite + bugfixes

2008-02-22 Thread Edgar E. Iglesias
Hi,

This is the third version of the linux-user/mmap bugfix patches:

* Let the native mmap choose addresses for unfixed mappings.
* For file mappings, correct mapping of pages beyond EOF.
* Adds a small testsuite for linux-user/mmap.

Tested with test-mmap for CRIS, MIPS, ARM and i386, simulated on linux-i686 
 hosts.

Felipe, I think the problems you are seeing are related to large mmaps failing. 
By letting the native mmap choose the addresses for unfixed mmaps, I hope your 
segfaults will go away.

Thanks
-- 
Edgar E. Iglesias
Axis Communications AB

diff --git a/configure b/configure
index bbda3f7..3df08ab 100755
--- a/configure
+++ b/configure
@@ -1244,6 +1244,7 @@ if test $source_path_used = yes ; then
 DIRS=tests tests/cris slirp audio
 FILES=Makefile tests/Makefile
 FILES=$FILES tests/cris/Makefile tests/cris/.gdbinit
+FILES=$FILES tests/test-mmap.c
 for dir in $DIRS ; do
 mkdir -p $dir
 done
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 6292826..9d656ea 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -23,6 +23,8 @@
 #include string.h
 #include unistd.h
 #include errno.h
+#include sys/types.h
+#include sys/stat.h
 #include sys/mman.h
 
 #include qemu.h
@@ -151,53 +153,11 @@ static int mmap_frag(abi_ulong real_start,
 return 0;
 }
 
-#if defined(__CYGWIN__)
-/* Cygwin doesn't have a whole lot of address space.  */
-static abi_ulong mmap_next_start = 0x1800;
-#else
-static abi_ulong mmap_next_start = 0x4000;
-#endif
-
-/* find a free memory area of size 'size'. The search starts at
-   'start'. If 'start' == 0, then a default start address is used.
-   Return -1 if error.
-*/
-/* page_init() marks pages used by the host as reserved to be sure not
-   to use them. */
-static abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size)
-{
-abi_ulong addr, addr1, addr_start;
-int prot;
-
-size = HOST_PAGE_ALIGN(size);
-start = start  qemu_host_page_mask;
-addr = start;
-if (addr == 0)
-addr = mmap_next_start;
-addr_start = addr;
-for(;;) {
-prot = 0;
-for(addr1 = addr; addr1  (addr + size); addr1 += TARGET_PAGE_SIZE) {
-prot |= page_get_flags(addr1);
-}
-if (prot == 0)
-break;
-addr += qemu_host_page_size;
-/* we found nothing */
-if (addr == addr_start)
-return (abi_ulong)-1;
-}
-if (start == 0)
-mmap_next_start = addr + size;
-return addr;
-}
-
 /* NOTE: all the constants are the HOST ones */
 abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
  int flags, int fd, abi_ulong offset)
 {
 abi_ulong ret, end, real_start, real_end, retaddr, host_offset, host_len;
-unsigned long host_start;
 
 #ifdef DEBUG_MMAP
 {
@@ -234,38 +194,81 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int 
prot,
 len = TARGET_PAGE_ALIGN(len);
 if (len == 0)
 return start;
-real_start = start  qemu_host_page_mask;
 
+/* When mapping files into a memory area larger than the file, accesses
+   to pages beyond the file size will cause a SIGBUS. 
+
+   For example, if mmaping a file of 100 bytes on a host with 4K pages
+   emulating a target with 8K pages, the target expects to be able to
+   access the first 8K. But the host will trap us on any access beyond
+   4K.  
+
+   When emulating a target with a larger page-size than the hosts, we
+   may need to truncate file maps at EOF and add extra anonymous pages
+   up to the targets page boundary.  */
+
+if (!(flags  MAP_ANONYMOUS)) {
+   struct stat sb;
+
+   if (fstat (fd, sb) == -1)
+   return -1;
+
+   /* Are we trying to create a map beyond EOF?.  */
+   if (offset + len  sb.st_size) {
+   /* If so, truncate the file map at eof aligned with 
+  the hosts real pagesize. Additional anonymous maps
+  will be created beyond EOF.  */
+   len = (sb.st_size - offset);
+   len += qemu_real_host_page_size - 1;
+   len = ~(qemu_real_host_page_size - 1);
+   }
+}
+
+real_start = start  qemu_host_page_mask;
+end = start + len;
+real_end = HOST_PAGE_ALIGN(end);
+ 
 if (!(flags  MAP_FIXED)) {
-abi_ulong mmap_start;
-void *p;
-host_offset = offset  qemu_host_page_mask;
-host_len = len + offset - host_offset;
-host_len = HOST_PAGE_ALIGN(host_len);
-mmap_start = mmap_find_vma(real_start, host_len);
-if (mmap_start == (abi_ulong)-1) {
-errno = ENOMEM;
-return -1;
-}
-/* Note: we prefer to control the mapping address. It is
-   especially important if qemu_host_page_size 
-   qemu_real_host_page_size */
-p = mmap(g2h(mmap_start),
- host_len, prot, flags | MAP_FIXED, fd, host_offset);
-if (p == MAP_FAILED)
-return -1;

Re: [Qemu-devel] [PATCH, RFC, WIP] TCG for Qemu target Sparc32/64

2008-02-22 Thread Blue Swirl
On 2/22/08, Thiemo Seufer [EMAIL PROTECTED] wrote:
 Blue Swirl wrote:
   The attached patch enables most TCG ops for Qemu Sparc32/64 target.
   Sparc32 softmmu and linux-user are OK, but Sparc64 and Sparc32plus
   targets do not work.
  
   Comments?
  
   It would be nice to get rid of T2 usage in std (also stda and
   casa/casxa) but I don't know how to pass a 64-bit value from legacy op
   to TCG stores and loads on a 32-bit target and host.

[cut]

  This whole lot should probably move to generic code (conditionalized on
  TARGET_LONG_BITS), I have the same code in my MIPS prototype.

I agree. Also these lines, if they are really needed:
+#if TCG_TARGET_REG_BITS == 32
+#define tcg_gen_ld_ptr tcg_gen_ld_i32
+#else
+#define tcg_gen_ld_ptr tcg_gen_ld_i64
+#endif




[Qemu-devel] qemu curses.c

2008-02-22 Thread Andrzej Zaborowski
CVSROOT:/sources/qemu
Module name:qemu
Changes by: Andrzej Zaborowski balrog 08/02/22 18:21:28

Modified files:
.  : curses.c 

Log message:
The non-ncurses curses doesn't have resize_term, so make resizing 
conditional.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/qemu/curses.c?cvsroot=qemur1=1.1r2=1.2




[Qemu-devel] [PATCH] Don't explicitly set BAR values for VMware VGA

2008-02-22 Thread Anthony Liguori
Right now we set explict base addresses for the PCI IO regions in the VMware
VGA device.  We don't register the second region at all and instead directly
map the physical memory.

The problem is, the addresses we're setting in the BAR is not taken into
account in the e820 mapping.

This patch removes the explicit BARs and registers the second region through
the normal PCI code.

I've only tested with a Linux guest and the open source VMware VGA driver.

This patch needs -p2 to apply against the QEMU CVS tree.

Signed-off-by: Anthony Liguori [EMAIL PROTECTED]

diff --git a/qemu/hw/vmware_vga.c b/qemu/hw/vmware_vga.c
index bd96e6b..ec7b1cd 100644
--- a/qemu/hw/vmware_vga.c
+++ b/qemu/hw/vmware_vga.c
@@ -60,6 +60,8 @@ struct vmsvga_state_s {
 int vram_size;
 #endif
 uint8_t *vram;
+uint32_t vram_addr;
+int iomemtype;
 
 int index;
 int scratch_size;
@@ -644,7 +646,7 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t 
address)
 return ((s-depth + 7)  3) * s-new_width;
 
 case SVGA_REG_FB_START:
-return SVGA_MEM_BASE;
+return s-vram_addr;
 
 case SVGA_REG_FB_OFFSET:
 return 0x0;
@@ -671,7 +673,7 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t 
address)
 return caps;
 
 case SVGA_REG_MEM_START:
-return SVGA_MEM_BASE + s-vram_size - SVGA_FIFO_SIZE;
+return s-vram_addr + s-vram_size - SVGA_FIFO_SIZE;
 
 case SVGA_REG_MEM_SIZE:
 return SVGA_FIFO_SIZE;
@@ -953,7 +955,7 @@ static void vmsvga_screen_dump(void *opaque, const char 
*filename)
 static uint32_t vmsvga_vram_readb(void *opaque, target_phys_addr_t addr)
 {
 struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
-addr -= SVGA_MEM_BASE;
+addr -= s-vram_addr;
 if (addr  s-fb_size)
 return *(uint8_t *) (s-ds-data + addr);
 else
@@ -963,7 +965,7 @@ static uint32_t vmsvga_vram_readb(void *opaque, 
target_phys_addr_t addr)
 static uint32_t vmsvga_vram_readw(void *opaque, target_phys_addr_t addr)
 {
 struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
-addr -= SVGA_MEM_BASE;
+addr -= s-vram_addr;
 if (addr  s-fb_size)
 return *(uint16_t *) (s-ds-data + addr);
 else
@@ -973,7 +975,7 @@ static uint32_t vmsvga_vram_readw(void *opaque, 
target_phys_addr_t addr)
 static uint32_t vmsvga_vram_readl(void *opaque, target_phys_addr_t addr)
 {
 struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
-addr -= SVGA_MEM_BASE;
+addr -= s-vram_addr;
 if (addr  s-fb_size)
 return *(uint32_t *) (s-ds-data + addr);
 else
@@ -984,7 +986,7 @@ static void vmsvga_vram_writeb(void *opaque, 
target_phys_addr_t addr,
 uint32_t value)
 {
 struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
-addr -= SVGA_MEM_BASE;
+addr -= s-vram_addr;
 if (addr  s-fb_size)
 *(uint8_t *) (s-ds-data + addr) = value;
 else
@@ -995,7 +997,7 @@ static void vmsvga_vram_writew(void *opaque, 
target_phys_addr_t addr,
 uint32_t value)
 {
 struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
-addr -= SVGA_MEM_BASE;
+addr -= s-vram_addr;
 if (addr  s-fb_size)
 *(uint16_t *) (s-ds-data + addr) = value;
 else
@@ -1006,7 +1008,7 @@ static void vmsvga_vram_writel(void *opaque, 
target_phys_addr_t addr,
 uint32_t value)
 {
 struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
-addr -= SVGA_MEM_BASE;
+addr -= s-vram_addr;
 if (addr  s-fb_size)
 *(uint32_t *) (s-ds-data + addr) = value;
 else
@@ -1081,10 +1083,10 @@ static void vmsvga_init(struct vmsvga_state_s *s, 
DisplayState *ds,
 uint8_t *vga_ram_base, unsigned long vga_ram_offset,
 int vga_ram_size)
 {
-int iomemtype;
 s-ds = ds;
 s-vram = vga_ram_base;
 s-vram_size = vga_ram_size;
+s-vram_addr = 0;
 
 s-scratch_size = SVGA_SCRATCH_SIZE;
 s-scratch = (uint32_t *) qemu_malloc(s-scratch_size * 4);
@@ -1092,13 +1094,11 @@ static void vmsvga_init(struct vmsvga_state_s *s, 
DisplayState *ds,
 vmsvga_reset(s);
 
 #ifdef DIRECT_VRAM
-iomemtype = cpu_register_io_memory(0, vmsvga_vram_read,
-vmsvga_vram_write, s);
+s-iomemtype = cpu_register_io_memory(0, vmsvga_vram_read,
+ vmsvga_vram_write, s);
 #else
-iomemtype = vga_ram_offset | IO_MEM_RAM;
+s-iomemtype = vga_ram_offset | IO_MEM_RAM;
 #endif
-cpu_register_physical_memory(SVGA_MEM_BASE, vga_ram_size,
-iomemtype);
 
 graphic_console_init(ds, vmsvga_update_display,
 vmsvga_invalidate_display, vmsvga_screen_dump, s);
@@ -1133,24 +1133,30 @@ static int pci_vmsvga_load(QEMUFile *f, void *opaque, 
int version_id)
 return 0;
 }
 
-static void pci_vmsvga_map_ioport(PCIDevice *pci_dev, int region_num,
+static void pci_vmsvga_map(PCIDevice *pci_dev, int region_num,

[Qemu-devel] kqemu subversion

2008-02-22 Thread Ben Taylor
I have been maintaining a subversion repository for kqemu for the
last 8-9 months due to the large amount of changes required for
the Solaris port of kqemu  However, due to some life issues, I'm
not sure I have managed to get all the patches for kqemu into
the repository.

The current trunk for the code I have is at

http://svn9.cvsdude.com/kdesolaris/kqemu/trunk/1.0.3pre11

If anyone wants to test it out the code in there, and there's a
patch I'm missing, let me know.

Thanks,

Ben Taylor


[Qemu-devel] Re: [kvm-devel] [PATCH] Don't explicitly set BAR values for VMware VGA

2008-02-22 Thread Anthony Liguori

Anthony Liguori wrote:

Right now we set explict base addresses for the PCI IO regions in the VMware
VGA device.  We don't register the second region at all and instead directly
map the physical memory.

The problem is, the addresses we're setting in the BAR is not taken into
account in the e820 mapping.
  


Actually, it looks like the e820 map is okay, but I do get some errors 
in the gust about remapping that range so I do think this patch is correct.


Regards,

Anthony Liguori


This patch removes the explicit BARs and registers the second region through
the normal PCI code.

I've only tested with a Linux guest and the open source VMware VGA driver.

This patch needs -p2 to apply against the QEMU CVS tree.

  






[Qemu-devel] Bug (?) vl.c/qemu_loadvm() said qemu: warning: instance restoring from LUN/partition

2008-02-22 Thread Daniel Schwager
Hi list,

we use fedora-core8-xen linux, which is based 
on the qemu-0.9.0-5.fc8  and uses 
a qemue device_model (/usr/lib64/xen/bin/qemu-dm).

If I try to restore a saved domain, all works fine,
if the save-file is a plain file on the filesystem.

If I restore a domain from a LUN (e.g. /dev/sdb1), which
has MORE space than the filesize from the xm save /tmp/file,
I got a lot of errors (about in /var/log/xen/qemu-dm.PID.log:

qemu: warning: instance 0x0 of device '' not present in current VM
qemu: warning: instance 0x0 of device '' not present in current VM
qemu: warning: instance 0x0 of device '' not present in current VM
qemu: warning: instance 0x0 of device '' not present in current VM
qemu: warning: instance 0x0 of device '' not present in current VM
.

[EMAIL PROTECTED] xen]# grep qemu: warning: instance 0x0 of device  
qemu-dm.9747.log |wc -l
47875

 [EMAIL PROTECTED] xen]# ls -lah qemu-dm.9747.log
-rw-r--r-- 1 root root 3.1M 2008-02-22 21:41 qemu-dm.9747.log


You can also reproduce this bug by creating a save file
xm save domain-id /tmp/file

and append some additional space to it
dd if=/dev/zero of=/tmp/zero bs=1k count=100
cat /tmp/file /tmp/zero  /tmp/filezero

and restore the domain 
xm restore /tmp/filezero

and look at qemu-dm.PID.log.


Saving to LVM-Luns or iscsi-published LUN's is maybe a usecase for some people
e.g. for me (-:

Is this a bug or should you scan/interpret the save-file to the EOF ?

Could I restore from a LUN without errors ?

What's the minimum size of the LUN saving the domain to. 
I guess domain_memory + 15.899MB ... is it ?

Regards

Danny


---
DT Netsolution GmbH   -   Taläckerstr. 30-D-70437 Stuttgart
Geschäftsführer: Daniel Schwager, Stefan Hörz - HRB Stuttgart 19870
Tel: +49-711-849910-32, Fax: -932 - Mailto:[EMAIL PROTECTED]





[Qemu-devel] [PATCH] SH4,linux-user, Add pipe syscall support.

2008-02-22 Thread Takashi Yoshii
This one should be applied to run sh4-linux userland. /yoshii
---
add handling of return values of pipe syscall for SH4.

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -3514,6 +3514,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 CPUMIPSState *env = (CPUMIPSState*)cpu_env;
env-gpr[env-current_tc][3] = host_pipe[1];
ret = host_pipe[0];
+#elif defined(TARGET_SH4)
+   ((CPUSH4State*)cpu_env)-gregs[1] = host_pipe[1];
+   ret = host_pipe[0];
 #else
 if (put_user_s32(host_pipe[0], arg1)
 || put_user_s32(host_pipe[1], arg1 + sizeof(host_pipe[0])))




[Qemu-devel] Re: [PATCH] Don't explicitly set BAR values for VMware VGA

2008-02-22 Thread andrzej zaborowski
On 22/02/2008, Anthony Liguori [EMAIL PROTECTED] wrote:
 Right now we set explict base addresses for the PCI IO regions in the VMware
  VGA device.  We don't register the second region at all and instead directly
  map the physical memory.

  The problem is, the addresses we're setting in the BAR is not taken into
  account in the e820 mapping.

  This patch removes the explicit BARs and registers the second region through
  the normal PCI code.

  I've only tested with a Linux guest and the open source VMware VGA driver.

I have a very similar patch on my HD but I haven't included it because
it causes my testing Ms Windows install to stop detecting the card.  I
just tested your patch and the same thing happens, i.e. with the patch
it works as a vga card but is detected as an Unknown adapter and only
the 640x480x8 mode can be used.  I can't explain this.

Currently the io port numbers can be set by the guest and the memory
io regions are fixed.  Earlier both settings were hardcoded.  This is
because in one version of the X driver (which was/is the only
documentation available) these settings were metioned as *the* correct
values for this card.  This may of course cause different types of
breakage but so far worked ok, except when it was found that in
various combinations qemu segfaulted due to different PCI cards
registering the same port range as our default.  When this happened I
tried to make these settings settable through PCI registers but found
that this broke Ms Windows.  Luckily Ms Windows still worked if only
port ranges were assigned dynamically and the segfault went away so I
left it at this but it perhaps needs better looking at.
-- 
Please do not print this email unless absolutely necessary. Spread
environmental awareness.




[Qemu-devel] Re: [PATCH] Don't explicitly set BAR values for VMware VGA

2008-02-22 Thread Anthony Liguori

andrzej zaborowski wrote:

On 22/02/2008, Anthony Liguori [EMAIL PROTECTED] wrote:
  

Right now we set explict base addresses for the PCI IO regions in the VMware
 VGA device.  We don't register the second region at all and instead directly
 map the physical memory.

 The problem is, the addresses we're setting in the BAR is not taken into
 account in the e820 mapping.

 This patch removes the explicit BARs and registers the second region through
 the normal PCI code.

 I've only tested with a Linux guest and the open source VMware VGA driver.



I have a very similar patch on my HD but I haven't included it because
it causes my testing Ms Windows install to stop detecting the card.  I
just tested your patch and the same thing happens, i.e. with the patch
it works as a vga card but is detected as an Unknown adapter and only
the 640x480x8 mode can be used.  I can't explain this.
  


Can you describe how you setup your Windows install?  I'll try to 
reproduce it and dig into it.


Regards,

Anthony Liguori


Currently the io port numbers can be set by the guest and the memory
io regions are fixed.  Earlier both settings were hardcoded.  This is
because in one version of the X driver (which was/is the only
documentation available) these settings were metioned as *the* correct
values for this card.  This may of course cause different types of
breakage but so far worked ok, except when it was found that in
various combinations qemu segfaulted due to different PCI cards
registering the same port range as our default.  When this happened I
tried to make these settings settable through PCI registers but found
that this broke Ms Windows.  Luckily Ms Windows still worked if only
port ranges were assigned dynamically and the segfault went away so I
left it at this but it perhaps needs better looking at.
  






[Qemu-devel] Re: [PATCH] Don't explicitly set BAR values for VMware VGA

2008-02-22 Thread andrzej zaborowski
On 23/02/2008, Anthony Liguori [EMAIL PROTECTED] wrote:
 andrzej zaborowski wrote:
   I have a very similar patch on my HD but I haven't included it because
   it causes my testing Ms Windows install to stop detecting the card.  I
   just tested your patch and the same thing happens, i.e. with the patch
   it works as a vga card but is detected as an Unknown adapter and only
   the 640x480x8 mode can be used.  I can't explain this.
  


 Can you describe how you setup your Windows install?  I'll try to
  reproduce it and dig into it.

Oh, good question, and I think the answer be the reason why it's not
working here (*slaps self*).  I'll apply the patch if you can confirm
that it works with some Ms Windows install.

I just launched the VM and checked what kind of Ms Windows set up this
is and it's a Windows XP professional 2002 with VMware Tools
installed, and all the files on it have last modification date in 2004
or earlier.  Apparently I stole the already set up VM from my dad's
computer on which he used VMware, somewhere in 2004.  I then converted
the image to raw and always performed my tests with -snapshot on.
This may be why the system is unwilling to use different base
addresses.
-- 
Please do not print this email unless absolutely necessary. Spread
environmental awareness.




[Qemu-devel] qemu/hw omap.c

2008-02-22 Thread Andrzej Zaborowski
CVSROOT:/sources/qemu
Module name:qemu
Changes by: Andrzej Zaborowski balrog 08/02/23 02:08:35

Modified files:
hw : omap.c 

Log message:
Really stop the transfer when the DMA channel is being disabled.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/qemu/hw/omap.c?cvsroot=qemur1=1.34r2=1.35




[Qemu-devel] [PATCH] linux-user, fix getgroups/getgroups32 when both args are zero.

2008-02-22 Thread Takashi Yoshii
getgroups() and getgroups32() returns NGROUPS_MAX when both its two args are
zero. But because we pass a ptr to allocated space as 2nd arg, this function
are interfered. The patch attached fixed it.
/yoshii
---
linux-user/syscall.c: fix getgroups{,32} when both args are zero.

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5185,7 +5185,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 ret = get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
 break;
 case TARGET_NR_getgroups:
-{
+if (arg1 == 0  arg2 == 0)
+ret = get_errno(getgroups(0, 0));
+else {
 int gidsetsize = arg1;
 uint16_t *target_grouplist;
 gid_t *grouplist;
@@ -5335,7 +5337,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 #endif
 #ifdef TARGET_NR_getgroups32
 case TARGET_NR_getgroups32:
-{
+if (arg1 == 0  arg2 == 0)
+ret = get_errno(getgroups(0, 0));
+else {
 int gidsetsize = arg1;
 uint32_t *target_grouplist;
 gid_t *grouplist;




Re: [Qemu-devel] [PATCH] linux-user, fix getgroups/getgroups32 when both args are zero.

2008-02-22 Thread Kirill A. Shutemov
On [Sat, 23.02.2008 12:00], Takashi Yoshii wrote:
 getgroups() and getgroups32() returns NGROUPS_MAX when both its two args are
 zero. But because we pass a ptr to allocated space as 2nd arg, this function
 are interfered. The patch attached fixed it.
 /yoshii
 ---
 linux-user/syscall.c: fix getgroups{,32} when both args are zero.
 

My version of patch to fix same problem:

getgroups: return total number of supplementary group IDs for the
process if size == 0

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index ad97871..96a11a9 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5029,6 +5029,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 
 grouplist = alloca(gidsetsize * sizeof(gid_t));
 ret = get_errno(getgroups(gidsetsize, grouplist));
+if (gidsetsize == 0)
+break;
 if (!is_error(ret)) {
 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 
2, 0);
 if (!target_grouplist)
@@ -5179,6 +5181,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 
 grouplist = alloca(gidsetsize * sizeof(gid_t));
 ret = get_errno(getgroups(gidsetsize, grouplist));
+if (gidsetsize == 0)
+break;
 if (!is_error(ret)) {
 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 
4, 0);
 if (!target_grouplist) {

Another patch for getgroups:

Trivial optimization of getgroups syscall implementation:
swap only returned groups, not all group in list.

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 6f2872f..ad97871 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5033,7 +5033,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 
2, 0);
 if (!target_grouplist)
 goto efault;
-for(i = 0;i  gidsetsize; i++)
+for(i = 0;i  ret; i++)
 target_grouplist[i] = tswap16(grouplist[i]);
 unlock_user(target_grouplist, arg2, gidsetsize * 2);
 }
@@ -5185,7 +5185,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 ret = -TARGET_EFAULT;
 goto fail;
 }
-for(i = 0;i  gidsetsize; i++)
+for(i = 0;i  ret; i++)
 target_grouplist[i] = tswap32(grouplist[i]);
 unlock_user(target_grouplist, arg2, gidsetsize * 4);
 }

It makes getgroups much faster in some cases.

-- 
Regards,  Kirill A. Shutemov
 + Belarus, Minsk
 + Velesys Ltd, http://www.velesys.com/
 + ALT Linux Team, http://www.altlinux.com/


signature.asc
Description: Digital signature