[Libvir] big-endian support for libvirt - introduce GUEST_HANDLE infrastructure ?

Christian Ehrhardt ehrhardt at linux.vnet.ibm.com
Fri Jul 6 09:06:54 UTC 2007


Hello everyone,
we currently try to use/port libvirt to run on xenppc. While doing that 
I found a endianess issue.

First a simple example:

        Sample code:
                #include <stdio.h>
                
                union u {
                        int i;
                        long long l;
                };
                
                int main(void)
                {
                        union u u;
                        u.l = 0;
                        u.i = ~0;
                        printf("%016llx\n", u.l);
                
                        return 0;
                }
        
        Little-endian output: 00000000ffffffff
        Big-endian output:    ffffffff00000000
        
        Now look at the padding in e.g. xen_v2s3_getdomaininfolistop: it
        doesn't work on big-endian systems. This problem is why the
        GUEST_HANDLE infrastructure is present in Xen. To work on
        big-endian systems, libvirt will need this or a similar mechanism.



--- Current Questions ---
We could now add several ugly ifdefs to libvirt code to differentiate 
powerpc from the others and solve the issue described above, but I think 
thats not a good solution.
The GUEST_HANDLE mechanism would provide an architecture abstraction and 
is already implemented/working in libxc.
The question is, shouldn't libvirt actually use the GUEST_HANDLE 
mechanism like libxc does (at least for the _v2d5_ structures) or are 
there big arguments against it?
I would create a patch to add the GUEST_HANDLE stuff in libvirt if there 
is nothing against it, but I will need some help to test  it on 
x86/x86_64/ia64 since I have no such machines here.
If there is a major reason against the GUEST_HANDLE code, are there 
other suggestions/preferences how to solve this?


Below is the technical background in a more verbose way for anyone 
interested


--- Code Affected ---
More or less everything in libvirt that would use GUEST_HANDLE in libxc:
I saw the effect on a bad pointer passed down by the structure I use for 
my example below, but in the end it may affect all the stuff that uses 
the *GUEST_HANDLE* stuff in libxc which are e.g. uchar,ulong,... here an 
example:
 libxc:
   uint64_aligned_t max_pages;  // <- arch dependent mapping of 
uint64_aligned_t
 libvirt:
   #define ALIGN_64 __attribute__((aligned(8)))
   uint64_t max_pages ALIGN_64; // <- this align is fix on all 
architectures


--- The Issue in libvirt in one example ---
XEN_GUEST_HANDLE usage in libxc:
- XEN_GUEST_HANDLE is defined arch specific giving the arch the 
posibility to pad/align as needed. See 
xen/tools/libxc/xen/arch-powerpc.h for example.
- xen/tools use set_xen_guest_handle and get_xen_guest_handle to 
set/access these handles and let the arch the posibility to handle any 
specific needs.

Example:
struct xen_sysctl_getdomaininfolist {
 domid_t               first_domain;
 uint32_t              max_domains;
 XEN_GUEST_HANDLE_64(xen_domctl_getdomaininfo_t) buffer;
 uint32_t              num_domains;
};

The arch defined XEN_GUEST_HANDLE_64 leads to the following type for 
buffer on powerpc (see the initial padding):
   typedef struct { \
       int __pad[(sizeof (long long) - sizeof (void *)) / sizeof (int)]; \
       xen_domctl_getdomaininfo_t *p;
   } __attribute__((__aligned__(8))) 
__guest_handle_xen_domctl_getdomaininfo_t

In this scenario a 32bit pointer for *p with 0xFFFFFFFF will be stored 
as 0xPADPADPAFFFFFFFF and read in a valid way by the 64bit host that 
receives this syscall.

XEN_GUEST_HANDLE usage in libvirt:
- In my example where XEN_GUEST_HANDLE is in libxc libvirt currently 
uses a  union based structure like the following:
struct xen_v2s3_getdomaininfolistop {
   domid_t   first_domain;
   uint32_t  max_domains;
   union {
       struct xen_v2d5_getdomaininfo *v;
       uint64_t pad ALIGN_64;
   } buffer;
   uint32_t  num_domains;
};
typedef struct xen_v2s3_getdomaininfolistop xen_v2s3_getdomaininfolistop;

The union used here to add the 64 bit padding does not work on big 
endian powerpc because reading this two half words in 64bit receiver 
gives 0xFFFFFFFF00000000 (The two half words are stored in the wrong 
order) while  on ia64 it is read as the the valid 0x00000000FFFFFFFF.

P.S. Thanks Hollis for the simple example code

-- 

Grüsse / regards, 
Christian Ehrhardt

IBM Linux Technology Center, Open Virtualization
+49 7031/16-3385
Ehrhardt at linux.vnet.ibm.com
Ehrhardt at de.ibm.com

IBM Deutschland Entwicklung GmbH
Vorsitzender des Aufsichtsrats: Johann Weihen 
Geschäftsführung: Herbert Kircher 
Sitz der Gesellschaft: Böblingen
Registergericht: Amtsgericht Stuttgart, HRB 243294




More information about the libvir-list mailing list