Re: [Qemu-devel] Porting QEMU to new hosts with unusual ABI (sizeof(long) != sizeof(void *))

2011-02-11 Thread Anthony Liguori

On 02/05/2011 03:39 PM, Stefan Weil wrote:

Currently, most QEMU code assumes that pointers and long integers have
the same size, typically 32 bit on 32 bit hosts, 64 bit on 64 bit hosts.

While this assumption works on QEMU's major hosts, it is not generally 
true.


There exist 64 bit host OS which use an ABI with 32 bit long integers,
maybe to be more compatible with an older 32 bit OS version, so here is
sizeof(long)  sizeof(void *).

Other ABIs might use near pointers which may reduce code size and 
improve

code speed. This results in sizeof(long)  sizeof(void *).

Both cases will break current QEMU, because lots of code lines use
type casts from pointer to long or vice versa like these two examples:

start = (long)mmap((void *)host_start, host_len ...
code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + ...))

Both variants (unsigned long) and (long) can be found (relation 3:2).

Changing the existing limitation of QEMU's code simply needs replacing
all those type casts, variable declarations and printf format specifiers
by portable code.

The standard integral type which matches the size of a pointer is defined
in stdint.h (which also defines int8_t, ...). It is intptr_t (signed 
version)

or uintptr_t (unsigned version). There is no need to use both.

= Replace (unsigned long), (long) type casts of pointers by (uintptr_t).

All variables (auto, struct members, parameters) which hold such values
must be fixed, too. In the following examples, ptr_var is of that kind.

= Replace unsigned long ptr_var, long ptr_var by uintptr_t ptr_var.

Finally, the fixed variables are used in printf-like statements,
so here the format specifier needs a change. inttypes.h defines
PRIxPTR which should be used.

= Replace %lx by % PRIxPTR to print the integer value ptr_var.

A single patch which includes all these changes touches 39 files.
Splitting it into smaller patches is not trivial because of cross
dependencies. Because of its size, it will raise merge conflicts
when it is not applied soon.

Would these kind of changes be interesting for QEMU?


Portability is not a binary concept.  We could constantly change the 
code base to work around some silly decision that a random platform 
makes (like negative errno values).


So on their own, these changes are not useful and I'm not in favor of 
it.  However, if someone was going to do proper w64 support that was 
maintained, tested, and enhanced over the next few years, it'd be 
something I'd be very supportive of.


A, hey, look what I did last weekend port is not terribly interesting 
to me.  It'll just bitrot like the current w32 is.


Regards,

Anthony Liguori


Are there suggestions how it should be done?
What about ram_addr_t? Should it be replaced by uintptr_t?
Should we use macros like QEMU_PTR2UINT(p), QEMU_UINT2PTR(u)?

My current version of the patch is available from
http://qemu.weilnetz.de/0001-Fix-conversions-from-pointer-to-integral-type-and-vi.patch. 



Kind regards,
Stefan Weil







Re: [Qemu-devel] Porting QEMU to new hosts with unusual ABI (sizeof(long) != sizeof(void *))

2011-02-10 Thread Rob Landley
On 02/05/2011 08:39 AM, Stefan Weil wrote:
 Currently, most QEMU code assumes that pointers and long integers have
 the same size, typically 32 bit on 32 bit hosts, 64 bit on 64 bit hosts.

This is called the LP64 standard:

  http://www.unix.org/whitepapers/64bit.html

Which was created for a reason:

  http://www.unix.org/version2/whatsnew/lp64_wp.html

And which Linux, MacOSX, BSD, Solaris, android, iphone, you name it,
they all comply with.

 While this assumption works on QEMU's major hosts, it is not generally
 true.

It is generally true.  There is exactly one operating system that
decided to go its own way, and the insane legacy reasons they did so are
explained here:

  http://blogs.msdn.com/oldnewthing/archive/2005/01/31/363790.aspx

 There exist 64 bit host OS which use an ABI with 32 bit long integers,
 maybe to be more compatible with an older 32 bit OS version, so here is
 sizeof(long)  sizeof(void *).

You're implying that someone actually uses 64 bit windows?

On 32 bit hosts, LP64 is fine.  Long and pointer match.  So the obvious
fix is to build QEMU for 32 bits on windows.

 Other ABIs might use near pointers which may reduce code size and improve
 code speed. This results in sizeof(long)  sizeof(void *).

Um, near pointer was dos.  That went away long enough ago that its
absence is just about old enough to vote.

 Both cases will break current QEMU, because lots of code lines use
 type casts from pointer to long or vice versa like these two examples:

Sucks to be Microsoft, doesn't it?  They have billions of dollars to
comfort them.

Rob



[Qemu-devel] Porting QEMU to new hosts with unusual ABI (sizeof(long) != sizeof(void *))

2011-02-05 Thread Stefan Weil

Currently, most QEMU code assumes that pointers and long integers have
the same size, typically 32 bit on 32 bit hosts, 64 bit on 64 bit hosts.

While this assumption works on QEMU's major hosts, it is not generally true.

There exist 64 bit host OS which use an ABI with 32 bit long integers,
maybe to be more compatible with an older 32 bit OS version, so here is
sizeof(long)  sizeof(void *).

Other ABIs might use near pointers which may reduce code size and improve
code speed. This results in sizeof(long)  sizeof(void *).

Both cases will break current QEMU, because lots of code lines use
type casts from pointer to long or vice versa like these two examples:

start = (long)mmap((void *)host_start, host_len ...
code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + ...))

Both variants (unsigned long) and (long) can be found (relation 3:2).

Changing the existing limitation of QEMU's code simply needs replacing
all those type casts, variable declarations and printf format specifiers
by portable code.

The standard integral type which matches the size of a pointer is defined
in stdint.h (which also defines int8_t, ...). It is intptr_t (signed 
version)

or uintptr_t (unsigned version). There is no need to use both.

= Replace (unsigned long), (long) type casts of pointers by (uintptr_t).

All variables (auto, struct members, parameters) which hold such values
must be fixed, too. In the following examples, ptr_var is of that kind.

= Replace unsigned long ptr_var, long ptr_var by uintptr_t ptr_var.

Finally, the fixed variables are used in printf-like statements,
so here the format specifier needs a change. inttypes.h defines
PRIxPTR which should be used.

= Replace %lx by % PRIxPTR to print the integer value ptr_var.

A single patch which includes all these changes touches 39 files.
Splitting it into smaller patches is not trivial because of cross
dependencies. Because of its size, it will raise merge conflicts
when it is not applied soon.

Would these kind of changes be interesting for QEMU?
Are there suggestions how it should be done?
What about ram_addr_t? Should it be replaced by uintptr_t?
Should we use macros like QEMU_PTR2UINT(p), QEMU_UINT2PTR(u)?

My current version of the patch is available from
http://qemu.weilnetz.de/0001-Fix-conversions-from-pointer-to-integral-type-and-vi.patch.

Kind regards,
Stefan Weil




Re: [Qemu-devel] Porting QEMU to new hosts with unusual ABI (sizeof(long) != sizeof(void *))

2011-02-05 Thread Stefan Hajnoczi
On Sat, Feb 5, 2011 at 2:39 PM, Stefan Weil w...@mail.berlios.de wrote:
 My current version of the patch is available from
 http://qemu.weilnetz.de/0001-Fix-conversions-from-pointer-to-integral-type-and-vi.patch.

Out of interest, did you audit the code manually or use something like
coccinelle?

Stefan



Re: [Qemu-devel] Porting QEMU to new hosts with unusual ABI (sizeof(long) != sizeof(void *))

2011-02-05 Thread Stefan Weil

Am 05.02.2011 17:03, schrieb Stefan Hajnoczi:

On Sat, Feb 5, 2011 at 2:39 PM, Stefan Weilw...@mail.berlios.de  wrote:
   

My current version of the patch is available from
http://qemu.weilnetz.de/0001-Fix-conversions-from-pointer-to-integral-type-and-vi.patch.
 

Out of interest, did you audit the code manually or use something like
coccinelle?

Stefan
   


Quite simple:
I cross-compiled using MinGW-w64 and fixed the gcc warnings manually.

Stefan