Commit 22277879 authored by Linus Torvalds's avatar Linus Torvalds

Merge http://lia64.bkbits.net/to-linus-2.5

into home.osdl.org:/home/torvalds/v2.5/linux
parents 80d63a94 60b75a3c
...@@ -711,6 +711,32 @@ efi_mem_attributes (unsigned long phys_addr) ...@@ -711,6 +711,32 @@ efi_mem_attributes (unsigned long phys_addr)
return 0; return 0;
} }
int
valid_phys_addr_range (unsigned long phys_addr, unsigned long *size)
{
void *efi_map_start, *efi_map_end, *p;
efi_memory_desc_t *md;
u64 efi_desc_size;
efi_map_start = __va(ia64_boot_param->efi_memmap);
efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
efi_desc_size = ia64_boot_param->efi_memdesc_size;
for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
md = p;
if (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT)) {
if (!(md->attribute & EFI_MEMORY_WB))
return 0;
if (*size > md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - phys_addr)
*size = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - phys_addr;
return 1;
}
}
return 0;
}
static void __exit static void __exit
efivars_exit (void) efivars_exit (void)
{ {
......
.section .data.gate, "ax" .section .data.gate, "aw"
.incbin "arch/ia64/kernel/gate.so" .incbin "arch/ia64/kernel/gate.so"
...@@ -405,7 +405,7 @@ void enable_irq(unsigned int irq) ...@@ -405,7 +405,7 @@ void enable_irq(unsigned int irq)
spin_lock_irqsave(&desc->lock, flags); spin_lock_irqsave(&desc->lock, flags);
switch (desc->depth) { switch (desc->depth) {
case 1: { case 1: {
unsigned int status = desc->status & ~(IRQ_DISABLED | IRQ_INPROGRESS); unsigned int status = desc->status & ~IRQ_DISABLED;
desc->status = status; desc->status = status;
if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) { if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
desc->status = status | IRQ_REPLAY; desc->status = status | IRQ_REPLAY;
......
...@@ -322,6 +322,10 @@ module_alloc (unsigned long size) ...@@ -322,6 +322,10 @@ module_alloc (unsigned long size)
void void
module_free (struct module *mod, void *module_region) module_free (struct module *mod, void *module_region)
{ {
if (mod->arch.init_unw_table && module_region == mod->module_init) {
unw_remove_unwind_table(mod->arch.init_unw_table);
mod->arch.init_unw_table = NULL;
}
vfree(module_region); vfree(module_region);
} }
...@@ -843,28 +847,92 @@ apply_relocate (Elf64_Shdr *sechdrs, const char *strtab, unsigned int symindex, ...@@ -843,28 +847,92 @@ apply_relocate (Elf64_Shdr *sechdrs, const char *strtab, unsigned int symindex,
return -ENOEXEC; return -ENOEXEC;
} }
/*
* Modules contain a single unwind table which covers both the core and the init text
* sections but since the two are not contiguous, we need to split this table up such that
* we can register (and unregister) each "segment" seperately. Fortunately, this sounds
* more complicated than it really is.
*/
static void
register_unwind_table (struct module *mod)
{
struct unw_table_entry *start = (void *) mod->arch.unwind->sh_addr;
struct unw_table_entry *end = start + mod->arch.unwind->sh_size / sizeof (*start);
struct unw_table_entry tmp, *e1, *e2, *core, *init;
unsigned long num_init = 0, num_core = 0;
/* First, count how many init and core unwind-table entries there are. */
for (e1 = start; e1 < end; ++e1)
if (in_init(mod, e1->start_offset))
++num_init;
else
++num_core;
/*
* Second, sort the table such that all unwind-table entries for the init and core
* text sections are nicely separated. We do this with a stupid bubble sort
* (unwind tables don't get ridiculously huge).
*/
for (e1 = start; e1 < end; ++e1) {
for (e2 = e1 + 1; e2 < end; ++e2) {
if (e2->start_offset < e1->start_offset) {
tmp = *e1;
*e1 = *e2;
*e2 = tmp;
}
}
}
/*
* Third, locate the init and core segments in the unwind table:
*/
if (in_init(mod, start->start_offset)) {
init = start;
core = start + num_init;
} else {
core = start;
init = start + num_core;
}
DEBUGP("%s: name=%s, gp=%lx, num_init=%lu, num_core=%lu\n", __FUNCTION__,
mod->name, mod->arch.gp, num_init, num_core);
/*
* Fourth, register both tables (if not empty).
*/
if (num_core > 0) {
mod->arch.core_unw_table = unw_add_unwind_table(mod->name, 0, mod->arch.gp,
core, core + num_core);
DEBUGP("%s: core: handle=%p [%p-%p)\n", __FUNCTION__,
mod->arch.core_unw_table, core, core + num_core);
}
if (num_init > 0) {
mod->arch.init_unw_table = unw_add_unwind_table(mod->name, 0, mod->arch.gp,
init, init + num_init);
DEBUGP("%s: init: handle=%p [%p-%p)\n", __FUNCTION__,
mod->arch.init_unw_table, init, init + num_init);
}
}
int int
module_finalize (const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *mod) module_finalize (const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *mod)
{ {
DEBUGP("%s: init: entry=%p\n", __FUNCTION__, mod->init); DEBUGP("%s: init: entry=%p\n", __FUNCTION__, mod->init);
if (mod->arch.unwind) if (mod->arch.unwind)
mod->arch.unw_table = unw_add_unwind_table(mod->name, 0, mod->arch.gp, register_unwind_table(mod);
(void *) mod->arch.unwind->sh_addr,
((void *) mod->arch.unwind->sh_addr
+ mod->arch.unwind->sh_size));
return 0; return 0;
} }
void void
module_arch_cleanup (struct module *mod) module_arch_cleanup (struct module *mod)
{ {
if (mod->arch.unwind) if (mod->arch.init_unw_table)
unw_remove_unwind_table(mod->arch.unw_table); unw_remove_unwind_table(mod->arch.init_unw_table);
if (mod->arch.core_unw_table)
unw_remove_unwind_table(mod->arch.core_unw_table);
} }
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
void void
percpu_modcopy (void *pcpudst, const void *src, unsigned long size) percpu_modcopy (void *pcpudst, const void *src, unsigned long size)
{ {
unsigned int i; unsigned int i;
for (i = 0; i < NR_CPUS; i++) for (i = 0; i < NR_CPUS; i++)
......
This diff is collapsed.
...@@ -353,9 +353,13 @@ copy_thread (int nr, unsigned long clone_flags, ...@@ -353,9 +353,13 @@ copy_thread (int nr, unsigned long clone_flags,
/* copy parts of thread_struct: */ /* copy parts of thread_struct: */
p->thread.ksp = (unsigned long) child_stack - 16; p->thread.ksp = (unsigned long) child_stack - 16;
/* stop some PSR bits from being inherited: */ /* stop some PSR bits from being inherited.
* the psr.up/psr.pp bits must be cleared on fork but inherited on execve()
* therefore we must specify them explicitly here and not include them in
* IA64_PSR_BITS_TO_CLEAR.
*/
child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET) child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET)
& ~IA64_PSR_BITS_TO_CLEAR); & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP));
/* /*
* NOTE: The calling convention considers all floating point * NOTE: The calling convention considers all floating point
......
/* /*
* Copyright (C) 2000, 2002 Hewlett-Packard Co * Copyright (C) 2000, 2002-2003 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com> * David Mosberger-Tang <davidm@hpl.hp.com>
* *
* Kernel unwind support. * Kernel unwind support.
...@@ -45,12 +45,6 @@ struct unw_info_block { ...@@ -45,12 +45,6 @@ struct unw_info_block {
/* personality routine and language-specific data follow behind descriptors */ /* personality routine and language-specific data follow behind descriptors */
}; };
struct unw_table_entry {
u64 start_offset;
u64 end_offset;
u64 info_offset;
};
struct unw_table { struct unw_table {
struct unw_table *next; /* must be first member! */ struct unw_table *next; /* must be first member! */
const char *name; const char *name;
......
...@@ -72,6 +72,9 @@ phys_to_virt (unsigned long address) ...@@ -72,6 +72,9 @@ phys_to_virt (unsigned long address)
return (void *) (address + PAGE_OFFSET); return (void *) (address + PAGE_OFFSET);
} }
#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
extern int valid_phys_addr_range (unsigned long addr, size_t *count); /* efi.c */
/* /*
* The following two macros are deprecated and scheduled for removal. * The following two macros are deprecated and scheduled for removal.
* Please use the PCI-DMA interface defined in <asm/pci.h> instead. * Please use the PCI-DMA interface defined in <asm/pci.h> instead.
......
...@@ -18,7 +18,8 @@ struct mod_arch_specific { ...@@ -18,7 +18,8 @@ struct mod_arch_specific {
struct elf64_shdr *unwind; /* unwind-table section */ struct elf64_shdr *unwind; /* unwind-table section */
unsigned long gp; /* global-pointer for module */ unsigned long gp; /* global-pointer for module */
void *unw_table; /* unwind-table cookie returned by unwinder */ void *core_unw_table; /* core unwind-table cookie returned by unwinder */
void *init_unw_table; /* init unwind-table cookie returned by unwinder */
unsigned int next_got_entry; /* index of next available got entry */ unsigned int next_got_entry; /* index of next available got entry */
}; };
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <asm/system.h> #include <asm/system.h>
#define EMUL_PREFIX_LINUX_IA32 "emul/ia32-linux/" #define EMUL_PREFIX_LINUX_IA32 "/emul/ia32-linux/"
static inline char * static inline char *
__emul_prefix (void) __emul_prefix (void)
......
...@@ -93,6 +93,12 @@ struct unw_frame_info { ...@@ -93,6 +93,12 @@ struct unw_frame_info {
* The official API follows below: * The official API follows below:
*/ */
struct unw_table_entry {
u64 start_offset;
u64 end_offset;
u64 info_offset;
};
/* /*
* Initialize unwind support. * Initialize unwind support.
*/ */
......
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