mirror of
https://github.com/ipxe/ipxe
synced 2025-12-13 07:20:47 +03:00
[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:
@@ -241,7 +241,7 @@ static int nbi_process_segments ( struct image *image,
|
|||||||
*/
|
*/
|
||||||
static int nbi_boot16 ( struct image *image, struct imgheader *imgheader ) {
|
static int nbi_boot16 ( struct image *image, struct imgheader *imgheader ) {
|
||||||
int discard_D, discard_S, discard_b;
|
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,
|
DBGC ( image, "NBI %p executing 16-bit image at %04x:%04x\n", image,
|
||||||
imgheader->execaddr.segoff.segment,
|
imgheader->execaddr.segoff.segment,
|
||||||
@@ -283,7 +283,7 @@ static int nbi_boot32 ( struct image *image, struct imgheader *imgheader ) {
|
|||||||
0
|
0
|
||||||
};
|
};
|
||||||
int discard_D, discard_S, discard_b;
|
int discard_D, discard_S, discard_b;
|
||||||
int rc;
|
int32_t rc;
|
||||||
|
|
||||||
DBGC ( image, "NBI %p executing 32-bit image at %lx\n",
|
DBGC ( image, "NBI %p executing 32-bit image at %lx\n",
|
||||||
image, imgheader->execaddr.linear );
|
image, imgheader->execaddr.linear );
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ static int meme820 ( struct memory_map *memmap ) {
|
|||||||
struct memory_region *prev_region = NULL;
|
struct memory_region *prev_region = NULL;
|
||||||
uint32_t next = 0;
|
uint32_t next = 0;
|
||||||
uint32_t smap;
|
uint32_t smap;
|
||||||
size_t size;
|
uint32_t size;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
unsigned int discard_D;
|
unsigned int discard_D;
|
||||||
|
|
||||||
@@ -216,7 +216,7 @@ static int meme820 ( struct memory_map *memmap ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ( size < E820_MIN_SIZE ) {
|
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;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ static int pcibios_num_bus ( void ) {
|
|||||||
*/
|
*/
|
||||||
int pcibios_read ( struct pci_device *pci, uint32_t command, uint32_t *value ){
|
int pcibios_read ( struct pci_device *pci, uint32_t command, uint32_t *value ){
|
||||||
int discard_b, discard_D;
|
int discard_b, discard_D;
|
||||||
int status;
|
uint16_t status;
|
||||||
|
|
||||||
__asm__ __volatile__ ( REAL_CODE ( "stc\n\t"
|
__asm__ __volatile__ ( REAL_CODE ( "stc\n\t"
|
||||||
"int $0x1a\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 )
|
"b" ( pci->busdevfn )
|
||||||
: "edx" );
|
: "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 pcibios_write ( struct pci_device *pci, uint32_t command, uint32_t value ){
|
||||||
int discard_b, discard_c, discard_D;
|
int discard_b, discard_c, discard_D;
|
||||||
int status;
|
uint16_t status;
|
||||||
|
|
||||||
__asm__ __volatile__ ( REAL_CODE ( "stc\n\t"
|
__asm__ __volatile__ ( REAL_CODE ( "stc\n\t"
|
||||||
"int $0x1a\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 )
|
"b" ( pci->busdevfn ), "c" ( value )
|
||||||
: "edx" );
|
: "edx" );
|
||||||
|
|
||||||
return ( ( status >> 8 ) & 0xff );
|
return ( status >> 8 );
|
||||||
}
|
}
|
||||||
|
|
||||||
PROVIDE_PCIAPI ( pcbios, pci_num_bus, pcibios_num_bus );
|
PROVIDE_PCIAPI ( pcbios, pci_num_bus, pcibios_num_bus );
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ uint8_t rtc_sample ( void ) {
|
|||||||
/* Disable interrupts */
|
/* Disable interrupts */
|
||||||
"cli\n\t"
|
"cli\n\t"
|
||||||
)
|
)
|
||||||
: "=a" ( after ), "=d" ( before ), "=q" ( temp )
|
: "=a" ( after ), "=d" ( before ), "=Q" ( temp )
|
||||||
: "2" ( 0 ) );
|
: "2" ( 0 ) );
|
||||||
|
|
||||||
return ( after - before );
|
return ( after - before );
|
||||||
|
|||||||
@@ -208,8 +208,10 @@ int pxeparent_call ( SEGOFF16_t entry, unsigned int function,
|
|||||||
void *params, size_t params_len ) {
|
void *params, size_t params_len ) {
|
||||||
struct pxeparent_profiler *profiler = pxeparent_profiler ( function );
|
struct pxeparent_profiler *profiler = pxeparent_profiler ( function );
|
||||||
PXENV_EXIT_t exit;
|
PXENV_EXIT_t exit;
|
||||||
unsigned long started;
|
uint32_t before;
|
||||||
unsigned long stopped;
|
uint32_t started;
|
||||||
|
uint32_t stopped;
|
||||||
|
uint32_t after;
|
||||||
int discard_D;
|
int discard_D;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
@@ -240,12 +242,14 @@ int pxeparent_call ( SEGOFF16_t entry, unsigned int function,
|
|||||||
"D" ( __from_data16 ( &pxeparent_params ) )
|
"D" ( __from_data16 ( &pxeparent_params ) )
|
||||||
: "ecx", "esi" );
|
: "ecx", "esi" );
|
||||||
profile_stop ( &profiler->total );
|
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_stop_at ( &profiler->p2r, started );
|
||||||
profile_start_at ( &profiler->ext, started );
|
profile_start_at ( &profiler->ext, started );
|
||||||
profile_stop_at ( &profiler->ext, stopped );
|
profile_stop_at ( &profiler->ext, stopped );
|
||||||
profile_start_at ( &profiler->r2p, 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
|
/* Determine return status code based on PXENV_EXIT and
|
||||||
* PXENV_STATUS
|
* PXENV_STATUS
|
||||||
|
|||||||
Reference in New Issue
Block a user