diff options
author | Michael Brown <mcb30@ipxe.org> | 2016-02-18 14:38:41 +0000 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2016-02-18 15:12:51 +0000 |
commit | a3b4d6328c99c1c9bd731521e00bb8b495057931 (patch) | |
tree | 04e91621d78c47f37f5779121f113dcc2eb1157a | |
parent | 4e4727079b718a8c0c62629f7d0df2f492074853 (diff) | |
download | ipxe-a3b4d6328c99c1c9bd731521e00bb8b495057931.zip ipxe-a3b4d6328c99c1c9bd731521e00bb8b495057931.tar.gz ipxe-a3b4d6328c99c1c9bd731521e00bb8b495057931.tar.bz2 |
[bios] Make uses of REAL_CODE() and PHYS_CODE() 64-bit clean
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>
-rw-r--r-- | src/arch/x86/image/nbi.c | 4 | ||||
-rw-r--r-- | src/arch/x86/interface/pcbios/memmap.c | 4 | ||||
-rw-r--r-- | src/arch/x86/interface/pcbios/pcibios.c | 8 | ||||
-rw-r--r-- | src/arch/x86/interface/pcbios/rtc_entropy.c | 2 | ||||
-rw-r--r-- | src/arch/x86/interface/pxeparent/pxeparent.c | 12 |
5 files changed, 17 insertions, 13 deletions
diff --git a/src/arch/x86/image/nbi.c b/src/arch/x86/image/nbi.c index 9904614..b691bee 100644 --- a/src/arch/x86/image/nbi.c +++ b/src/arch/x86/image/nbi.c @@ -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 ); diff --git a/src/arch/x86/interface/pcbios/memmap.c b/src/arch/x86/interface/pcbios/memmap.c index 88bfec9..daae382 100644 --- a/src/arch/x86/interface/pcbios/memmap.c +++ b/src/arch/x86/interface/pcbios/memmap.c @@ -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; } diff --git a/src/arch/x86/interface/pcbios/pcibios.c b/src/arch/x86/interface/pcbios/pcibios.c index 34efa0b..07ac0c1 100644 --- a/src/arch/x86/interface/pcbios/pcibios.c +++ b/src/arch/x86/interface/pcbios/pcibios.c @@ -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 ); diff --git a/src/arch/x86/interface/pcbios/rtc_entropy.c b/src/arch/x86/interface/pcbios/rtc_entropy.c index 6e7ac83..83c2445 100644 --- a/src/arch/x86/interface/pcbios/rtc_entropy.c +++ b/src/arch/x86/interface/pcbios/rtc_entropy.c @@ -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 ); diff --git a/src/arch/x86/interface/pxeparent/pxeparent.c b/src/arch/x86/interface/pxeparent/pxeparent.c index 0b6be9a..cc6101c 100644 --- a/src/arch/x86/interface/pxeparent/pxeparent.c +++ b/src/arch/x86/interface/pxeparent/pxeparent.c @@ -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 |