[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>
This commit is contained in:
Michael Brown
2016-02-18 14:38:41 +00:00
parent 4e4727079b
commit a3b4d6328c
5 changed files with 17 additions and 13 deletions

View 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;
}

View 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 );

View 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 );