Commit a9dd68b8 authored by David Mosberger's avatar David Mosberger

ia64: Fix EFI runtime callbacks so they cannot corrupt fp regs. A few minor

	other fixes.
parent 6af1b374
...@@ -60,67 +60,157 @@ struct proc_dir_entry *efi_dir = NULL; ...@@ -60,67 +60,157 @@ struct proc_dir_entry *efi_dir = NULL;
static unsigned long mem_limit = ~0UL; static unsigned long mem_limit = ~0UL;
static efi_status_t #define efi_call_virt(f, args...) (*(f))(args)
phys_get_time (efi_time_t *tm, efi_time_cap_t *tc)
{ #define STUB_GET_TIME(prefix, adjust_arg) \
return efi_call_phys(__va(runtime->get_time), __pa(tm), __pa(tc)); static efi_status_t \
prefix##_get_time (efi_time_t *tm, efi_time_cap_t *tc) \
{ \
struct ia64_fpreg fr[6]; \
efi_status_t ret; \
\
ia64_save_scratch_fpregs(fr); \
ret = efi_call_##prefix((efi_get_time_t *) __va(runtime->get_time), adjust_arg(tm), \
adjust_arg(tc)); \
ia64_load_scratch_fpregs(fr); \
return ret; \
} }
static efi_status_t #define STUB_SET_TIME(prefix, adjust_arg) \
phys_set_time (efi_time_t *tm) static efi_status_t \
{ prefix##_set_time (efi_time_t *tm) \
return efi_call_phys(__va(runtime->set_time), __pa(tm)); { \
struct ia64_fpreg fr[6]; \
efi_status_t ret; \
\
ia64_save_scratch_fpregs(fr); \
ret = efi_call_##prefix((efi_set_time_t *) __va(runtime->set_time), adjust_arg(tm)); \
ia64_load_scratch_fpregs(fr); \
return ret; \
} }
static efi_status_t #define STUB_GET_WAKEUP_TIME(prefix, adjust_arg) \
phys_get_wakeup_time (efi_bool_t *enabled, efi_bool_t *pending, efi_time_t *tm) static efi_status_t \
{ prefix##_get_wakeup_time (efi_bool_t *enabled, efi_bool_t *pending, efi_time_t *tm) \
return efi_call_phys(__va(runtime->get_wakeup_time), __pa(enabled), __pa(pending), { \
__pa(tm)); struct ia64_fpreg fr[6]; \
efi_status_t ret; \
\
ia64_save_scratch_fpregs(fr); \
ret = efi_call_##prefix((efi_get_wakeup_time_t *) __va(runtime->get_wakeup_time), \
adjust_arg(enabled), adjust_arg(pending), adjust_arg(tm)); \
ia64_load_scratch_fpregs(fr); \
return ret; \
} }
static efi_status_t #define STUB_SET_WAKEUP_TIME(prefix, adjust_arg) \
phys_set_wakeup_time (efi_bool_t enabled, efi_time_t *tm) static efi_status_t \
{ prefix##_set_wakeup_time (efi_bool_t enabled, efi_time_t *tm) \
return efi_call_phys(__va(runtime->set_wakeup_time), enabled, __pa(tm)); { \
struct ia64_fpreg fr[6]; \
efi_status_t ret; \
\
ia64_save_scratch_fpregs(fr); \
ret = efi_call_##prefix((efi_set_wakeup_time_t *) __va(runtime->set_wakeup_time), \
enabled, adjust_arg(tm)); \
ia64_load_scratch_fpregs(fr); \
return ret; \
} }
static efi_status_t #define STUB_GET_VARIABLE(prefix, adjust_arg) \
phys_get_variable (efi_char16_t *name, efi_guid_t *vendor, u32 *attr, static efi_status_t \
unsigned long *data_size, void *data) prefix##_get_variable (efi_char16_t *name, efi_guid_t *vendor, u32 *attr, \
{ unsigned long *data_size, void *data) \
return efi_call_phys(__va(runtime->get_variable), __pa(name), __pa(vendor), __pa(attr), { \
__pa(data_size), __pa(data)); struct ia64_fpreg fr[6]; \
efi_status_t ret; \
\
ia64_save_scratch_fpregs(fr); \
ret = efi_call_##prefix((efi_get_variable_t *) __va(runtime->get_variable), \
adjust_arg(name), adjust_arg(vendor), adjust_arg(attr), \
adjust_arg(data_size), adjust_arg(data)); \
ia64_load_scratch_fpregs(fr); \
return ret; \
} }
static efi_status_t #define STUB_GET_NEXT_VARIABLE(prefix, adjust_arg) \
phys_get_next_variable (unsigned long *name_size, efi_char16_t *name, efi_guid_t *vendor) static efi_status_t \
{ prefix##_get_next_variable (unsigned long *name_size, efi_char16_t *name, efi_guid_t *vendor) \
return efi_call_phys(__va(runtime->get_next_variable), __pa(name_size), __pa(name), { \
__pa(vendor)); struct ia64_fpreg fr[6]; \
efi_status_t ret; \
\
ia64_save_scratch_fpregs(fr); \
ret = efi_call_##prefix((efi_get_next_variable_t *) __va(runtime->get_next_variable), \
adjust_arg(name_size), adjust_arg(name), adjust_arg(vendor)); \
ia64_load_scratch_fpregs(fr); \
return ret; \
} }
static efi_status_t #define STUB_SET_VARIABLE(prefix, adjust_arg) \
phys_set_variable (efi_char16_t *name, efi_guid_t *vendor, u32 attr, static efi_status_t \
unsigned long data_size, void *data) prefix##_set_variable (efi_char16_t *name, efi_guid_t *vendor, u32 attr, \
{ unsigned long data_size, void *data) \
return efi_call_phys(__va(runtime->set_variable), __pa(name), __pa(vendor), attr, { \
data_size, __pa(data)); struct ia64_fpreg fr[6]; \
efi_status_t ret; \
\
ia64_save_scratch_fpregs(fr); \
ret = efi_call_##prefix((efi_set_variable_t *) __va(runtime->set_variable), \
adjust_arg(name), adjust_arg(vendor), attr, data_size, \
adjust_arg(data)); \
ia64_load_scratch_fpregs(fr); \
return ret; \
} }
static efi_status_t #define STUB_GET_NEXT_HIGH_MONO_COUNT(prefix, adjust_arg) \
phys_get_next_high_mono_count (u64 *count) static efi_status_t \
{ prefix##_get_next_high_mono_count (u64 *count) \
return efi_call_phys(__va(runtime->get_next_high_mono_count), __pa(count)); { \
struct ia64_fpreg fr[6]; \
efi_status_t ret; \
\
ia64_save_scratch_fpregs(fr); \
ret = efi_call_##prefix((efi_get_next_high_mono_count_t *) \
__va(runtime->get_next_high_mono_count), adjust_arg(count)); \
ia64_load_scratch_fpregs(fr); \
return ret; \
} }
static void #define STUB_RESET_SYSTEM(prefix, adjust_arg) \
phys_reset_system (int reset_type, efi_status_t status, static void \
unsigned long data_size, efi_char16_t *data) prefix##_reset_system (int reset_type, efi_status_t status, \
{ unsigned long data_size, efi_char16_t *data) \
efi_call_phys(__va(runtime->reset_system), status, data_size, __pa(data)); { \
struct ia64_fpreg fr[6]; \
\
ia64_save_scratch_fpregs(fr); \
efi_call_##prefix((efi_reset_system_t *) __va(runtime->reset_system), \
reset_type, status, data_size, adjust_arg(data)); \
/* should not return, but just in case... */ \
ia64_load_scratch_fpregs(fr); \
} }
STUB_GET_TIME(phys, __pa)
STUB_SET_TIME(phys, __pa)
STUB_GET_WAKEUP_TIME(phys, __pa)
STUB_SET_WAKEUP_TIME(phys, __pa)
STUB_GET_VARIABLE(phys, __pa)
STUB_GET_NEXT_VARIABLE(phys, __pa)
STUB_SET_VARIABLE(phys, __pa)
STUB_GET_NEXT_HIGH_MONO_COUNT(phys, __pa)
STUB_RESET_SYSTEM(phys, __pa)
STUB_GET_TIME(virt, )
STUB_SET_TIME(virt, )
STUB_GET_WAKEUP_TIME(virt, )
STUB_SET_WAKEUP_TIME(virt, )
STUB_GET_VARIABLE(virt, )
STUB_GET_NEXT_VARIABLE(virt, )
STUB_SET_VARIABLE(virt, )
STUB_GET_NEXT_HIGH_MONO_COUNT(virt, )
STUB_RESET_SYSTEM(virt, )
void void
efi_gettimeofday (struct timeval *tv) efi_gettimeofday (struct timeval *tv)
{ {
...@@ -574,18 +664,17 @@ efi_enter_virtual_mode (void) ...@@ -574,18 +664,17 @@ efi_enter_virtual_mode (void)
} }
/* /*
* Now that EFI is in virtual mode, we arrange for EFI functions to be * Now that EFI is in virtual mode, we call the EFI functions more efficiently:
* called directly:
*/ */
efi.get_time = __va(runtime->get_time); efi.get_time = virt_get_time;
efi.set_time = __va(runtime->set_time); efi.set_time = virt_set_time;
efi.get_wakeup_time = __va(runtime->get_wakeup_time); efi.get_wakeup_time = virt_get_wakeup_time;
efi.set_wakeup_time = __va(runtime->set_wakeup_time); efi.set_wakeup_time = virt_set_wakeup_time;
efi.get_variable = __va(runtime->get_variable); efi.get_variable = virt_get_variable;
efi.get_next_variable = __va(runtime->get_next_variable); efi.get_next_variable = virt_get_next_variable;
efi.set_variable = __va(runtime->set_variable); efi.set_variable = virt_set_variable;
efi.get_next_high_mono_count = __va(runtime->get_next_high_mono_count); efi.get_next_high_mono_count = virt_get_next_high_mono_count;
efi.reset_system = __va(runtime->reset_system); efi.reset_system = virt_reset_system;
} }
/* /*
......
...@@ -133,12 +133,8 @@ find_iosapic (unsigned int gsi) ...@@ -133,12 +133,8 @@ find_iosapic (unsigned int gsi)
return -1; return -1;
} }
/* static inline int
* Translate GSI number to the corresponding IA-64 interrupt vector. If no _gsi_to_vector (unsigned int gsi)
* entry exists, return -1.
*/
int
gsi_to_vector (unsigned int gsi)
{ {
struct iosapic_intr_info *info; struct iosapic_intr_info *info;
...@@ -148,6 +144,26 @@ gsi_to_vector (unsigned int gsi) ...@@ -148,6 +144,26 @@ gsi_to_vector (unsigned int gsi)
return -1; return -1;
} }
/*
* Translate GSI number to the corresponding IA-64 interrupt vector. If no
* entry exists, return -1.
*/
inline int
gsi_to_vector (unsigned int gsi)
{
return _gsi_to_vector(gsi);
}
int
gsi_to_irq (unsigned int gsi)
{
/*
* XXX fix me: this assumes an identity mapping vetween IA-64 vector and Linux irq
* numbers...
*/
return _gsi_to_vector(gsi);
}
static void static void
set_rte (unsigned int vector, unsigned int dest) set_rte (unsigned int vector, unsigned int dest)
{ {
...@@ -157,7 +173,7 @@ set_rte (unsigned int vector, unsigned int dest) ...@@ -157,7 +173,7 @@ set_rte (unsigned int vector, unsigned int dest)
int rte_index; int rte_index;
char redir; char redir;
DBG(KERN_DEBUG"IOSAPIC: routing vector %d to %x\n", vector, dest); DBG(KERN_DEBUG"IOSAPIC: routing vector %d to 0x%x\n", vector, dest);
rte_index = iosapic_intr_info[vector].rte_index; rte_index = iosapic_intr_info[vector].rte_index;
if (rte_index < 0) if (rte_index < 0)
......
...@@ -78,7 +78,7 @@ ia64_init_addr_space (void) ...@@ -78,7 +78,7 @@ ia64_init_addr_space (void)
vma->vm_mm = current->mm; vma->vm_mm = current->mm;
vma->vm_start = IA64_RBS_BOT; vma->vm_start = IA64_RBS_BOT;
vma->vm_end = vma->vm_start + PAGE_SIZE; vma->vm_end = vma->vm_start + PAGE_SIZE;
vma->vm_page_prot = protection_map[VM_READ | VM_WRITE]; vma->vm_page_prot = protection_map[VM_DATA_DEFAULT_FLAGS & 0x7];
vma->vm_flags = VM_READ|VM_WRITE|VM_MAYREAD|VM_MAYWRITE|VM_GROWSUP; vma->vm_flags = VM_READ|VM_WRITE|VM_MAYREAD|VM_MAYWRITE|VM_GROWSUP;
vma->vm_ops = NULL; vma->vm_ops = NULL;
vma->vm_pgoff = 0; vma->vm_pgoff = 0;
......
...@@ -55,6 +55,8 @@ extern void __devinit iosapic_init (unsigned long address, ...@@ -55,6 +55,8 @@ extern void __devinit iosapic_init (unsigned long address,
unsigned int gsi_base, unsigned int gsi_base,
int pcat_compat); int pcat_compat);
extern int gsi_to_vector (unsigned int gsi); extern int gsi_to_vector (unsigned int gsi);
extern int gsi_to_irq (unsigned int gsi);
extern void iosapic_parse_prt (void);
extern int iosapic_register_intr (unsigned int gsi, unsigned long polarity, extern int iosapic_register_intr (unsigned int gsi, unsigned long polarity,
unsigned long edge_triggered, unsigned long edge_triggered,
u32 gsi_base, char *iosapic_address); u32 gsi_base, char *iosapic_address);
......
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