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)
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
efivars_exit (void)
{
......
.section .data.gate, "ax"
.section .data.gate, "aw"
.incbin "arch/ia64/kernel/gate.so"
......@@ -405,7 +405,7 @@ void enable_irq(unsigned int irq)
spin_lock_irqsave(&desc->lock, flags);
switch (desc->depth) {
case 1: {
unsigned int status = desc->status & ~(IRQ_DISABLED | IRQ_INPROGRESS);
unsigned int status = desc->status & ~IRQ_DISABLED;
desc->status = status;
if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
desc->status = status | IRQ_REPLAY;
......
......@@ -322,6 +322,10 @@ module_alloc (unsigned long size)
void
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);
}
......@@ -843,23 +847,87 @@ apply_relocate (Elf64_Shdr *sechdrs, const char *strtab, unsigned int symindex,
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
module_finalize (const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *mod)
{
DEBUGP("%s: init: entry=%p\n", __FUNCTION__, mod->init);
if (mod->arch.unwind)
mod->arch.unw_table = unw_add_unwind_table(mod->name, 0, mod->arch.gp,
(void *) mod->arch.unwind->sh_addr,
((void *) mod->arch.unwind->sh_addr
+ mod->arch.unwind->sh_size));
register_unwind_table(mod);
return 0;
}
void
module_arch_cleanup (struct module *mod)
{
if (mod->arch.unwind)
unw_remove_unwind_table(mod->arch.unw_table);
if (mod->arch.init_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
......
This diff is collapsed.
......@@ -353,9 +353,13 @@ copy_thread (int nr, unsigned long clone_flags,
/* copy parts of thread_struct: */
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)
& ~IA64_PSR_BITS_TO_CLEAR);
& ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP));
/*
* 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>
*
* Kernel unwind support.
......@@ -45,12 +45,6 @@ struct unw_info_block {
/* 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 *next; /* must be first member! */
const char *name;
......
......@@ -72,6 +72,9 @@ phys_to_virt (unsigned long address)
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.
* Please use the PCI-DMA interface defined in <asm/pci.h> instead.
......
......@@ -18,7 +18,8 @@ struct mod_arch_specific {
struct elf64_shdr *unwind; /* unwind-table section */
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 */
};
......
......@@ -9,7 +9,7 @@
#include <asm/ptrace.h>
#include <asm/system.h>
#define EMUL_PREFIX_LINUX_IA32 "emul/ia32-linux/"
#define EMUL_PREFIX_LINUX_IA32 "/emul/ia32-linux/"
static inline char *
__emul_prefix (void)
......
......@@ -93,6 +93,12 @@ struct unw_frame_info {
* The official API follows below:
*/
struct unw_table_entry {
u64 start_offset;
u64 end_offset;
u64 info_offset;
};
/*
* 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