Commit e02f2f56 authored by David Mosberger's avatar David Mosberger

ia64: Fix EFI physical-mode stubs to correctly calculate physical address

This fixes a bug in which the Ski simulator ended up getting the wrong
time, since phys_get_time() ended up storing the correct time in the
wrong place if a region-5 virtual address was passed (as would happen
for stack variables of the init-task).  On real machines, this bug
likely would have caused a crash on machines which don't support
switching EFI into virtual mode.
parent a5ea33f8
...@@ -43,18 +43,20 @@ static unsigned long mem_limit = ~0UL, max_addr = ~0UL; ...@@ -43,18 +43,20 @@ static unsigned long mem_limit = ~0UL, max_addr = ~0UL;
#define efi_call_virt(f, args...) (*(f))(args) #define efi_call_virt(f, args...) (*(f))(args)
#define STUB_GET_TIME(prefix, adjust_arg) \ #define STUB_GET_TIME(prefix, adjust_arg) \
static efi_status_t \ static efi_status_t \
prefix##_get_time (efi_time_t *tm, efi_time_cap_t *tc) \ prefix##_get_time (efi_time_t *tm, efi_time_cap_t *tc) \
{ \ { \
struct ia64_fpreg fr[6]; \ struct ia64_fpreg fr[6]; \
efi_status_t ret; \ efi_time_cap_t *atc = 0; \
\ efi_status_t ret; \
ia64_save_scratch_fpregs(fr); \ \
ret = efi_call_##prefix((efi_get_time_t *) __va(runtime->get_time), adjust_arg(tm), \ if (tc) \
adjust_arg(tc)); \ atc = adjust_arg(tc); \
ia64_load_scratch_fpregs(fr); \ ia64_save_scratch_fpregs(fr); \
return ret; \ ret = efi_call_##prefix((efi_get_time_t *) __va(runtime->get_time), adjust_arg(tm), atc); \
ia64_load_scratch_fpregs(fr); \
return ret; \
} }
#define STUB_SET_TIME(prefix, adjust_arg) \ #define STUB_SET_TIME(prefix, adjust_arg) \
...@@ -89,11 +91,14 @@ static efi_status_t \ ...@@ -89,11 +91,14 @@ static efi_status_t \
prefix##_set_wakeup_time (efi_bool_t enabled, efi_time_t *tm) \ prefix##_set_wakeup_time (efi_bool_t enabled, efi_time_t *tm) \
{ \ { \
struct ia64_fpreg fr[6]; \ struct ia64_fpreg fr[6]; \
efi_time_t *atm = 0; \
efi_status_t ret; \ efi_status_t ret; \
\ \
if (tm) \
atm = adjust_arg(tm); \
ia64_save_scratch_fpregs(fr); \ ia64_save_scratch_fpregs(fr); \
ret = efi_call_##prefix((efi_set_wakeup_time_t *) __va(runtime->set_wakeup_time), \ ret = efi_call_##prefix((efi_set_wakeup_time_t *) __va(runtime->set_wakeup_time), \
enabled, adjust_arg(tm)); \ enabled, atm); \
ia64_load_scratch_fpregs(fr); \ ia64_load_scratch_fpregs(fr); \
return ret; \ return ret; \
} }
...@@ -104,11 +109,14 @@ prefix##_get_variable (efi_char16_t *name, efi_guid_t *vendor, u32 *attr, \ ...@@ -104,11 +109,14 @@ prefix##_get_variable (efi_char16_t *name, efi_guid_t *vendor, u32 *attr, \
unsigned long *data_size, void *data) \ unsigned long *data_size, void *data) \
{ \ { \
struct ia64_fpreg fr[6]; \ struct ia64_fpreg fr[6]; \
u32 *aattr = 0; \
efi_status_t ret; \ efi_status_t ret; \
\ \
if (attr) \
aattr = adjust_arg(attr); \
ia64_save_scratch_fpregs(fr); \ ia64_save_scratch_fpregs(fr); \
ret = efi_call_##prefix((efi_get_variable_t *) __va(runtime->get_variable), \ ret = efi_call_##prefix((efi_get_variable_t *) __va(runtime->get_variable), \
adjust_arg(name), adjust_arg(vendor), adjust_arg(attr), \ adjust_arg(name), adjust_arg(vendor), aattr, \
adjust_arg(data_size), adjust_arg(data)); \ adjust_arg(data_size), adjust_arg(data)); \
ia64_load_scratch_fpregs(fr); \ ia64_load_scratch_fpregs(fr); \
return ret; \ return ret; \
...@@ -164,33 +172,41 @@ prefix##_reset_system (int reset_type, efi_status_t status, \ ...@@ -164,33 +172,41 @@ prefix##_reset_system (int reset_type, efi_status_t status, \
unsigned long data_size, efi_char16_t *data) \ unsigned long data_size, efi_char16_t *data) \
{ \ { \
struct ia64_fpreg fr[6]; \ struct ia64_fpreg fr[6]; \
efi_char16_t *adata = 0; \
\
if (data) \
adata = adjust_arg(data); \
\ \
ia64_save_scratch_fpregs(fr); \ ia64_save_scratch_fpregs(fr); \
efi_call_##prefix((efi_reset_system_t *) __va(runtime->reset_system), \ efi_call_##prefix((efi_reset_system_t *) __va(runtime->reset_system), \
reset_type, status, data_size, adjust_arg(data)); \ reset_type, status, data_size, adata); \
/* should not return, but just in case... */ \ /* should not return, but just in case... */ \
ia64_load_scratch_fpregs(fr); \ ia64_load_scratch_fpregs(fr); \
} }
STUB_GET_TIME(phys, __pa) #define phys_ptr(arg) ((__typeof__(arg)) ia64_tpa(arg))
STUB_SET_TIME(phys, __pa)
STUB_GET_WAKEUP_TIME(phys, __pa) STUB_GET_TIME(phys, phys_ptr)
STUB_SET_WAKEUP_TIME(phys, __pa) STUB_SET_TIME(phys, phys_ptr)
STUB_GET_VARIABLE(phys, __pa) STUB_GET_WAKEUP_TIME(phys, phys_ptr)
STUB_GET_NEXT_VARIABLE(phys, __pa) STUB_SET_WAKEUP_TIME(phys, phys_ptr)
STUB_SET_VARIABLE(phys, __pa) STUB_GET_VARIABLE(phys, phys_ptr)
STUB_GET_NEXT_HIGH_MONO_COUNT(phys, __pa) STUB_GET_NEXT_VARIABLE(phys, phys_ptr)
STUB_RESET_SYSTEM(phys, __pa) STUB_SET_VARIABLE(phys, phys_ptr)
STUB_GET_NEXT_HIGH_MONO_COUNT(phys, phys_ptr)
STUB_GET_TIME(virt, ) STUB_RESET_SYSTEM(phys, phys_ptr)
STUB_SET_TIME(virt, )
STUB_GET_WAKEUP_TIME(virt, ) #define id(arg) arg
STUB_SET_WAKEUP_TIME(virt, )
STUB_GET_VARIABLE(virt, ) STUB_GET_TIME(virt, id)
STUB_GET_NEXT_VARIABLE(virt, ) STUB_SET_TIME(virt, id)
STUB_SET_VARIABLE(virt, ) STUB_GET_WAKEUP_TIME(virt, id)
STUB_GET_NEXT_HIGH_MONO_COUNT(virt, ) STUB_SET_WAKEUP_TIME(virt, id)
STUB_RESET_SYSTEM(virt, ) STUB_GET_VARIABLE(virt, id)
STUB_GET_NEXT_VARIABLE(virt, id)
STUB_SET_VARIABLE(virt, id)
STUB_GET_NEXT_HIGH_MONO_COUNT(virt, id)
STUB_RESET_SYSTEM(virt, id)
void void
efi_gettimeofday (struct timespec *ts) efi_gettimeofday (struct timespec *ts)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment