]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[bios] Make uses of REAL_CODE() and PHYS_CODE() 64-bit clean
authorMichael Brown <mcb30@ipxe.org>
Thu, 18 Feb 2016 14:38:41 +0000 (14:38 +0000)
committerMichael Brown <mcb30@ipxe.org>
Thu, 18 Feb 2016 15:12:51 +0000 (15:12 +0000)
On a 64-bit CPU, any modification of a register by 32-bit or 16-bit
code will destroy the invisible upper 32 bits of the corresponding
64-bit register.  For example: a 32-bit "pushl %eax" followed by a
"popl %eax" will zero the upper half of %rax.  This differs from the
treatment of upper halves of 32-bit registers by 16-bit code: a
"pushw %ax" followed by a "popw %ax" will leave the upper 16 bits of
%eax unmodified.

Inline assembly generated using REAL_CODE() or PHYS_CODE() will
therefore have to preserve the upper halves of all registers, to avoid
clobbering registers that gcc expects to be preserved.

Output operands from REAL_CODE() and PHYS_CODE() assembly may
therefore contain undefined values in the upper 32 bits.

Fix by using explicit variable widths (e.g. uint32_t) for
non-discarded output operands, to ensure that undefined values in the
upper 32 bits of 64-bit registers are ignored.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/arch/x86/image/nbi.c
src/arch/x86/interface/pcbios/memmap.c
src/arch/x86/interface/pcbios/pcibios.c
src/arch/x86/interface/pcbios/rtc_entropy.c
src/arch/x86/interface/pxeparent/pxeparent.c

index 99046144d5bc8a1f4e5e1741c8c27cab9ba3f70d..b691bee20ea9eb34d392ce8ee46de671113888c6 100644 (file)
@@ -241,7 +241,7 @@ static int nbi_process_segments ( struct image *image,
  */
 static int nbi_boot16 ( struct image *image, struct imgheader *imgheader ) {
        int discard_D, discard_S, discard_b;
-       int rc;
+       int32_t rc;
 
        DBGC ( image, "NBI %p executing 16-bit image at %04x:%04x\n", image,
               imgheader->execaddr.segoff.segment,
@@ -283,7 +283,7 @@ static int nbi_boot32 ( struct image *image, struct imgheader *imgheader ) {
                0
        };
        int discard_D, discard_S, discard_b;
-       int rc;
+       int32_t rc;
 
        DBGC ( image, "NBI %p executing 32-bit image at %lx\n",
               image, imgheader->execaddr.linear );
index 88bfec9f4816d8fa24e9842597f82150625e0ecb..daae382b8226659d28022141dbd4593cb1f58d71 100644 (file)
@@ -174,7 +174,7 @@ static int meme820 ( struct memory_map *memmap ) {
        struct memory_region *prev_region = NULL;
        uint32_t next = 0;
        uint32_t smap;
-       size_t size;
+       uint32_t size;
        unsigned int flags;
        unsigned int discard_D;
 
@@ -216,7 +216,7 @@ static int meme820 ( struct memory_map *memmap ) {
                }
 
                if ( size < E820_MIN_SIZE ) {
-                       DBG ( "INT 15,e820 returned only %zd bytes\n", size );
+                       DBG ( "INT 15,e820 returned only %d bytes\n", size );
                        return -EINVAL;
                }
 
index 34efa0b39ab011f2eb64d0b14af7ac1419964487..07ac0c18d3d997c03d7c87ae021d599574b8b855 100644 (file)
@@ -70,7 +70,7 @@ static int pcibios_num_bus ( void ) {
  */
 int pcibios_read ( struct pci_device *pci, uint32_t command, uint32_t *value ){
        int discard_b, discard_D;
-       int status;
+       uint16_t status;
 
        __asm__ __volatile__ ( REAL_CODE ( "stc\n\t"
                                           "int $0x1a\n\t"
@@ -85,7 +85,7 @@ int pcibios_read ( struct pci_device *pci, uint32_t command, uint32_t *value ){
                                 "b" ( pci->busdevfn )
                               : "edx" );
 
-       return ( ( status >> 8 ) & 0xff );
+       return ( status >> 8 );
 }
 
 /**
@@ -98,7 +98,7 @@ int pcibios_read ( struct pci_device *pci, uint32_t command, uint32_t *value ){
  */
 int pcibios_write ( struct pci_device *pci, uint32_t command, uint32_t value ){
        int discard_b, discard_c, discard_D;
-       int status;
+       uint16_t status;
 
        __asm__ __volatile__ ( REAL_CODE ( "stc\n\t"
                                           "int $0x1a\n\t"
@@ -111,7 +111,7 @@ int pcibios_write ( struct pci_device *pci, uint32_t command, uint32_t value ){
                                 "b" ( pci->busdevfn ), "c" ( value )
                               : "edx" );
        
-       return ( ( status >> 8 ) & 0xff );
+       return ( status >> 8 );
 }
 
 PROVIDE_PCIAPI ( pcbios, pci_num_bus, pcibios_num_bus );
index 6e7ac833e3f36f2aaee3ffcdced77c1268952dea..83c2445f869dcda75a18faf290fce2e5ac035ebd 100644 (file)
@@ -187,7 +187,7 @@ uint8_t rtc_sample ( void ) {
                            /* Disable interrupts */
                            "cli\n\t"
                            )
-               : "=a" ( after ), "=d" ( before ), "=q" ( temp )
+               : "=a" ( after ), "=d" ( before ), "=Q" ( temp )
                : "2" ( 0 ) );
 
        return ( after - before );
index 0b6be9a0309001b1141a97a2d6a4a3a8c22eee45..cc6101c1f8f3e4d9ae460f80b64f38bda84d117d 100644 (file)
@@ -208,8 +208,10 @@ int pxeparent_call ( SEGOFF16_t entry, unsigned int function,
                     void *params, size_t params_len ) {
        struct pxeparent_profiler *profiler = pxeparent_profiler ( function );
        PXENV_EXIT_t exit;
-       unsigned long started;
-       unsigned long stopped;
+       uint32_t before;
+       uint32_t started;
+       uint32_t stopped;
+       uint32_t after;
        int discard_D;
        int rc;
 
@@ -240,12 +242,14 @@ int pxeparent_call ( SEGOFF16_t entry, unsigned int function,
                                 "D" ( __from_data16 ( &pxeparent_params ) )
                               : "ecx", "esi" );
        profile_stop ( &profiler->total );
-       profile_start_at ( &profiler->p2r, profile_started ( &profiler->total));
+       before = profile_started ( &profiler->total );
+       after = profile_stopped ( &profiler->total );
+       profile_start_at ( &profiler->p2r, before );
        profile_stop_at ( &profiler->p2r, started );
        profile_start_at ( &profiler->ext, started );
        profile_stop_at ( &profiler->ext, stopped );
        profile_start_at ( &profiler->r2p, stopped );
-       profile_stop_at ( &profiler->r2p, profile_stopped ( &profiler->total ));
+       profile_stop_at ( &profiler->r2p, after );
 
        /* Determine return status code based on PXENV_EXIT and
         * PXENV_STATUS