Commit 75c0b3b4 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'fixes' of master.kernel.org:/home/rmk/linux-2.6-arm

* 'fixes' of master.kernel.org:/home/rmk/linux-2.6-arm:
  ARM: 6870/1: The mandatory barrier rmb() must be a dsb() in for device accesses
  ARM: 6892/1: handle ptrace requests to change PC during interrupted system calls
  ARM: 6890/1: memmap: only free allocated memmap entries when using SPARSEMEM
  ARM: zImage: the page table memory must be considered before relocation
  ARM: zImage: make sure not to relocate on top of the relocation code
  ARM: zImage: Fix bad SP address after relocating kernel
  ARM: zImage: make sure the stack is 64-bit aligned
  ARM: RiscPC: acornfb: fix section mismatches
  ARM: RiscPC: etherh: fix section mismatches
parents 3568bd97 a904f5f9
...@@ -74,7 +74,7 @@ ZTEXTADDR := $(CONFIG_ZBOOT_ROM_TEXT) ...@@ -74,7 +74,7 @@ ZTEXTADDR := $(CONFIG_ZBOOT_ROM_TEXT)
ZBSSADDR := $(CONFIG_ZBOOT_ROM_BSS) ZBSSADDR := $(CONFIG_ZBOOT_ROM_BSS)
else else
ZTEXTADDR := 0 ZTEXTADDR := 0
ZBSSADDR := ALIGN(4) ZBSSADDR := ALIGN(8)
endif endif
SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/ SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/
......
...@@ -179,15 +179,14 @@ not_angel: ...@@ -179,15 +179,14 @@ not_angel:
bl cache_on bl cache_on
restart: adr r0, LC0 restart: adr r0, LC0
ldmia r0, {r1, r2, r3, r5, r6, r9, r11, r12} ldmia r0, {r1, r2, r3, r6, r9, r11, r12}
ldr sp, [r0, #32] ldr sp, [r0, #28]
/* /*
* We might be running at a different address. We need * We might be running at a different address. We need
* to fix up various pointers. * to fix up various pointers.
*/ */
sub r0, r0, r1 @ calculate the delta offset sub r0, r0, r1 @ calculate the delta offset
add r5, r5, r0 @ _start
add r6, r6, r0 @ _edata add r6, r6, r0 @ _edata
#ifndef CONFIG_ZBOOT_ROM #ifndef CONFIG_ZBOOT_ROM
...@@ -206,31 +205,40 @@ restart: adr r0, LC0 ...@@ -206,31 +205,40 @@ restart: adr r0, LC0
/* /*
* Check to see if we will overwrite ourselves. * Check to see if we will overwrite ourselves.
* r4 = final kernel address * r4 = final kernel address
* r5 = start of this image
* r9 = size of decompressed image * r9 = size of decompressed image
* r10 = end of this image, including bss/stack/malloc space if non XIP * r10 = end of this image, including bss/stack/malloc space if non XIP
* We basically want: * We basically want:
* r4 >= r10 -> OK * r4 - 16k page directory >= r10 -> OK
* r4 + image length <= r5 -> OK * r4 + image length <= current position (pc) -> OK
*/ */
add r10, r10, #16384
cmp r4, r10 cmp r4, r10
bhs wont_overwrite bhs wont_overwrite
add r10, r4, r9 add r10, r4, r9
cmp r10, r5 ARM( cmp r10, pc )
THUMB( mov lr, pc )
THUMB( cmp r10, lr )
bls wont_overwrite bls wont_overwrite
/* /*
* Relocate ourselves past the end of the decompressed kernel. * Relocate ourselves past the end of the decompressed kernel.
* r5 = start of this image
* r6 = _edata * r6 = _edata
* r10 = end of the decompressed kernel * r10 = end of the decompressed kernel
* Because we always copy ahead, we need to do it from the end and go * Because we always copy ahead, we need to do it from the end and go
* backward in case the source and destination overlap. * backward in case the source and destination overlap.
*/ */
/* Round up to next 256-byte boundary. */ /*
add r10, r10, #256 * Bump to the next 256-byte boundary with the size of
* the relocation code added. This avoids overwriting
* ourself when the offset is small.
*/
add r10, r10, #((reloc_code_end - restart + 256) & ~255)
bic r10, r10, #255 bic r10, r10, #255
/* Get start of code we want to copy and align it down. */
adr r5, restart
bic r5, r5, #31
sub r9, r6, r5 @ size to copy sub r9, r6, r5 @ size to copy
add r9, r9, #31 @ rounded up to a multiple add r9, r9, #31 @ rounded up to a multiple
bic r9, r9, #31 @ ... of 32 bytes bic r9, r9, #31 @ ... of 32 bytes
...@@ -245,6 +253,11 @@ restart: adr r0, LC0 ...@@ -245,6 +253,11 @@ restart: adr r0, LC0
/* Preserve offset to relocated code. */ /* Preserve offset to relocated code. */
sub r6, r9, r6 sub r6, r9, r6
#ifndef CONFIG_ZBOOT_ROM
/* cache_clean_flush may use the stack, so relocate it */
add sp, sp, r6
#endif
bl cache_clean_flush bl cache_clean_flush
adr r0, BSYM(restart) adr r0, BSYM(restart)
...@@ -333,7 +346,6 @@ not_relocated: mov r0, #0 ...@@ -333,7 +346,6 @@ not_relocated: mov r0, #0
LC0: .word LC0 @ r1 LC0: .word LC0 @ r1
.word __bss_start @ r2 .word __bss_start @ r2
.word _end @ r3 .word _end @ r3
.word _start @ r5
.word _edata @ r6 .word _edata @ r6
.word _image_size @ r9 .word _image_size @ r9
.word _got_start @ r11 .word _got_start @ r11
...@@ -1062,6 +1074,7 @@ memdump: mov r12, r0 ...@@ -1062,6 +1074,7 @@ memdump: mov r12, r0
#endif #endif
.ltorg .ltorg
reloc_code_end:
.align .align
.section ".stack", "aw", %nobits .section ".stack", "aw", %nobits
......
...@@ -54,6 +54,7 @@ SECTIONS ...@@ -54,6 +54,7 @@ SECTIONS
.bss : { *(.bss) } .bss : { *(.bss) }
_end = .; _end = .;
. = ALIGN(8); /* the stack must be 64-bit aligned */
.stack : { *(.stack) } .stack : { *(.stack) }
.stab 0 : { *(.stab) } .stab 0 : { *(.stab) }
......
...@@ -159,7 +159,7 @@ extern unsigned int user_debug; ...@@ -159,7 +159,7 @@ extern unsigned int user_debug;
#include <mach/barriers.h> #include <mach/barriers.h>
#elif defined(CONFIG_ARM_DMA_MEM_BUFFERABLE) || defined(CONFIG_SMP) #elif defined(CONFIG_ARM_DMA_MEM_BUFFERABLE) || defined(CONFIG_SMP)
#define mb() do { dsb(); outer_sync(); } while (0) #define mb() do { dsb(); outer_sync(); } while (0)
#define rmb() dmb() #define rmb() dsb()
#define wmb() mb() #define wmb() mb()
#else #else
#include <asm/memory.h> #include <asm/memory.h>
......
...@@ -597,45 +597,19 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, ...@@ -597,45 +597,19 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
return err; return err;
} }
static inline void setup_syscall_restart(struct pt_regs *regs)
{
regs->ARM_r0 = regs->ARM_ORIG_r0;
regs->ARM_pc -= thumb_mode(regs) ? 2 : 4;
}
/* /*
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static int static int
handle_signal(unsigned long sig, struct k_sigaction *ka, handle_signal(unsigned long sig, struct k_sigaction *ka,
siginfo_t *info, sigset_t *oldset, siginfo_t *info, sigset_t *oldset,
struct pt_regs * regs, int syscall) struct pt_regs * regs)
{ {
struct thread_info *thread = current_thread_info(); struct thread_info *thread = current_thread_info();
struct task_struct *tsk = current; struct task_struct *tsk = current;
int usig = sig; int usig = sig;
int ret; int ret;
/*
* If we were from a system call, check for system call restarting...
*/
if (syscall) {
switch (regs->ARM_r0) {
case -ERESTART_RESTARTBLOCK:
case -ERESTARTNOHAND:
regs->ARM_r0 = -EINTR;
break;
case -ERESTARTSYS:
if (!(ka->sa.sa_flags & SA_RESTART)) {
regs->ARM_r0 = -EINTR;
break;
}
/* fallthrough */
case -ERESTARTNOINTR:
setup_syscall_restart(regs);
}
}
/* /*
* translate the signal * translate the signal
*/ */
...@@ -685,6 +659,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, ...@@ -685,6 +659,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
*/ */
static void do_signal(struct pt_regs *regs, int syscall) static void do_signal(struct pt_regs *regs, int syscall)
{ {
unsigned int retval = 0, continue_addr = 0, restart_addr = 0;
struct k_sigaction ka; struct k_sigaction ka;
siginfo_t info; siginfo_t info;
int signr; int signr;
...@@ -698,18 +673,61 @@ static void do_signal(struct pt_regs *regs, int syscall) ...@@ -698,18 +673,61 @@ static void do_signal(struct pt_regs *regs, int syscall)
if (!user_mode(regs)) if (!user_mode(regs))
return; return;
/*
* If we were from a system call, check for system call restarting...
*/
if (syscall) {
continue_addr = regs->ARM_pc;
restart_addr = continue_addr - (thumb_mode(regs) ? 2 : 4);
retval = regs->ARM_r0;
/*
* Prepare for system call restart. We do this here so that a
* debugger will see the already changed PSW.
*/
switch (retval) {
case -ERESTARTNOHAND:
case -ERESTARTSYS:
case -ERESTARTNOINTR:
regs->ARM_r0 = regs->ARM_ORIG_r0;
regs->ARM_pc = restart_addr;
break;
case -ERESTART_RESTARTBLOCK:
regs->ARM_r0 = -EINTR;
break;
}
}
if (try_to_freeze()) if (try_to_freeze())
goto no_signal; goto no_signal;
/*
* Get the signal to deliver. When running under ptrace, at this
* point the debugger may change all our registers ...
*/
signr = get_signal_to_deliver(&info, &ka, regs, NULL); signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) { if (signr > 0) {
sigset_t *oldset; sigset_t *oldset;
/*
* Depending on the signal settings we may need to revert the
* decision to restart the system call. But skip this if a
* debugger has chosen to restart at a different PC.
*/
if (regs->ARM_pc == restart_addr) {
if (retval == -ERESTARTNOHAND
|| (retval == -ERESTARTSYS
&& !(ka.sa.sa_flags & SA_RESTART))) {
regs->ARM_r0 = -EINTR;
regs->ARM_pc = continue_addr;
}
}
if (test_thread_flag(TIF_RESTORE_SIGMASK)) if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask; oldset = &current->saved_sigmask;
else else
oldset = &current->blocked; oldset = &current->blocked;
if (handle_signal(signr, &ka, &info, oldset, regs, syscall) == 0) { if (handle_signal(signr, &ka, &info, oldset, regs) == 0) {
/* /*
* A signal was successfully delivered; the saved * A signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame, * sigmask will have been stored in the signal frame,
...@@ -723,11 +741,14 @@ static void do_signal(struct pt_regs *regs, int syscall) ...@@ -723,11 +741,14 @@ static void do_signal(struct pt_regs *regs, int syscall)
} }
no_signal: no_signal:
/*
* No signal to deliver to the process - restart the syscall.
*/
if (syscall) { if (syscall) {
if (regs->ARM_r0 == -ERESTART_RESTARTBLOCK) { /*
* Handle restarting a different system call. As above,
* if a debugger has chosen to restart at a different PC,
* ignore the restart.
*/
if (retval == -ERESTART_RESTARTBLOCK
&& regs->ARM_pc == continue_addr) {
if (thumb_mode(regs)) { if (thumb_mode(regs)) {
regs->ARM_r7 = __NR_restart_syscall - __NR_SYSCALL_BASE; regs->ARM_r7 = __NR_restart_syscall - __NR_SYSCALL_BASE;
regs->ARM_pc -= 2; regs->ARM_pc -= 2;
...@@ -750,11 +771,6 @@ static void do_signal(struct pt_regs *regs, int syscall) ...@@ -750,11 +771,6 @@ static void do_signal(struct pt_regs *regs, int syscall)
#endif #endif
} }
} }
if (regs->ARM_r0 == -ERESTARTNOHAND ||
regs->ARM_r0 == -ERESTARTSYS ||
regs->ARM_r0 == -ERESTARTNOINTR) {
setup_syscall_restart(regs);
}
/* If there's no signal to deliver, we just put the saved sigmask /* If there's no signal to deliver, we just put the saved sigmask
* back. * back.
......
...@@ -4,5 +4,5 @@ ...@@ -4,5 +4,5 @@
* operation to deadlock the system. * operation to deadlock the system.
*/ */
#define mb() dsb() #define mb() dsb()
#define rmb() dmb() #define rmb() dsb()
#define wmb() mb() #define wmb() mb()
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
#include <asm/outercache.h> #include <asm/outercache.h>
#define rmb() dmb() #define rmb() dsb()
#define wmb() do { dsb(); outer_sync(); } while (0) #define wmb() do { dsb(); outer_sync(); } while (0)
#define mb() wmb() #define mb() wmb()
......
...@@ -392,7 +392,7 @@ free_memmap(unsigned long start_pfn, unsigned long end_pfn) ...@@ -392,7 +392,7 @@ free_memmap(unsigned long start_pfn, unsigned long end_pfn)
* Convert start_pfn/end_pfn to a struct page pointer. * Convert start_pfn/end_pfn to a struct page pointer.
*/ */
start_pg = pfn_to_page(start_pfn - 1) + 1; start_pg = pfn_to_page(start_pfn - 1) + 1;
end_pg = pfn_to_page(end_pfn); end_pg = pfn_to_page(end_pfn - 1) + 1;
/* /*
* Convert to physical addresses, and * Convert to physical addresses, and
...@@ -426,6 +426,14 @@ static void __init free_unused_memmap(struct meminfo *mi) ...@@ -426,6 +426,14 @@ static void __init free_unused_memmap(struct meminfo *mi)
bank_start = bank_pfn_start(bank); bank_start = bank_pfn_start(bank);
#ifdef CONFIG_SPARSEMEM
/*
* Take care not to free memmap entries that don't exist
* due to SPARSEMEM sections which aren't present.
*/
bank_start = min(bank_start,
ALIGN(prev_bank_end, PAGES_PER_SECTION));
#endif
/* /*
* If we had a previous bank, and there is a space * If we had a previous bank, and there is a space
* between the current bank and the previous, free it. * between the current bank and the previous, free it.
...@@ -440,6 +448,12 @@ static void __init free_unused_memmap(struct meminfo *mi) ...@@ -440,6 +448,12 @@ static void __init free_unused_memmap(struct meminfo *mi)
*/ */
prev_bank_end = ALIGN(bank_pfn_end(bank), MAX_ORDER_NR_PAGES); prev_bank_end = ALIGN(bank_pfn_end(bank), MAX_ORDER_NR_PAGES);
} }
#ifdef CONFIG_SPARSEMEM
if (!IS_ALIGNED(prev_bank_end, PAGES_PER_SECTION))
free_memmap(prev_bank_end,
ALIGN(prev_bank_end, PAGES_PER_SECTION));
#endif
} }
static void __init free_highpages(void) static void __init free_highpages(void)
......
...@@ -527,7 +527,7 @@ static void __init etherh_banner(void) ...@@ -527,7 +527,7 @@ static void __init etherh_banner(void)
* Read the ethernet address string from the on board rom. * Read the ethernet address string from the on board rom.
* This is an ascii string... * This is an ascii string...
*/ */
static int __init etherh_addr(char *addr, struct expansion_card *ec) static int __devinit etherh_addr(char *addr, struct expansion_card *ec)
{ {
struct in_chunk_dir cd; struct in_chunk_dir cd;
char *s; char *s;
...@@ -655,7 +655,7 @@ static const struct net_device_ops etherh_netdev_ops = { ...@@ -655,7 +655,7 @@ static const struct net_device_ops etherh_netdev_ops = {
static u32 etherh_regoffsets[16]; static u32 etherh_regoffsets[16];
static u32 etherm_regoffsets[16]; static u32 etherm_regoffsets[16];
static int __init static int __devinit
etherh_probe(struct expansion_card *ec, const struct ecard_id *id) etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
{ {
const struct etherh_data *data = id->data; const struct etherh_data *data = id->data;
......
...@@ -66,7 +66,7 @@ ...@@ -66,7 +66,7 @@
* have. Allow 1% either way on the nominal for TVs. * have. Allow 1% either way on the nominal for TVs.
*/ */
#define NR_MONTYPES 6 #define NR_MONTYPES 6
static struct fb_monspecs monspecs[NR_MONTYPES] __initdata = { static struct fb_monspecs monspecs[NR_MONTYPES] __devinitdata = {
{ /* TV */ { /* TV */
.hfmin = 15469, .hfmin = 15469,
.hfmax = 15781, .hfmax = 15781,
...@@ -873,7 +873,7 @@ static struct fb_ops acornfb_ops = { ...@@ -873,7 +873,7 @@ static struct fb_ops acornfb_ops = {
/* /*
* Everything after here is initialisation!!! * Everything after here is initialisation!!!
*/ */
static struct fb_videomode modedb[] __initdata = { static struct fb_videomode modedb[] __devinitdata = {
{ /* 320x256 @ 50Hz */ { /* 320x256 @ 50Hz */
NULL, 50, 320, 256, 125000, 92, 62, 35, 19, 38, 2, NULL, 50, 320, 256, 125000, 92, 62, 35, 19, 38, 2,
FB_SYNC_COMP_HIGH_ACT, FB_SYNC_COMP_HIGH_ACT,
...@@ -925,8 +925,7 @@ static struct fb_videomode modedb[] __initdata = { ...@@ -925,8 +925,7 @@ static struct fb_videomode modedb[] __initdata = {
} }
}; };
static struct fb_videomode __initdata static struct fb_videomode acornfb_default_mode __devinitdata = {
acornfb_default_mode = {
.name = NULL, .name = NULL,
.refresh = 60, .refresh = 60,
.xres = 640, .xres = 640,
...@@ -942,7 +941,7 @@ acornfb_default_mode = { ...@@ -942,7 +941,7 @@ acornfb_default_mode = {
.vmode = FB_VMODE_NONINTERLACED .vmode = FB_VMODE_NONINTERLACED
}; };
static void __init acornfb_init_fbinfo(void) static void __devinit acornfb_init_fbinfo(void)
{ {
static int first = 1; static int first = 1;
...@@ -1018,8 +1017,7 @@ static void __init acornfb_init_fbinfo(void) ...@@ -1018,8 +1017,7 @@ static void __init acornfb_init_fbinfo(void)
* size can optionally be followed by 'M' or 'K' for * size can optionally be followed by 'M' or 'K' for
* MB or KB respectively. * MB or KB respectively.
*/ */
static void __init static void __devinit acornfb_parse_mon(char *opt)
acornfb_parse_mon(char *opt)
{ {
char *p = opt; char *p = opt;
...@@ -1066,8 +1064,7 @@ acornfb_parse_mon(char *opt) ...@@ -1066,8 +1064,7 @@ acornfb_parse_mon(char *opt)
current_par.montype = -1; current_par.montype = -1;
} }
static void __init static void __devinit acornfb_parse_montype(char *opt)
acornfb_parse_montype(char *opt)
{ {
current_par.montype = -2; current_par.montype = -2;
...@@ -1108,8 +1105,7 @@ acornfb_parse_montype(char *opt) ...@@ -1108,8 +1105,7 @@ acornfb_parse_montype(char *opt)
} }
} }
static void __init static void __devinit acornfb_parse_dram(char *opt)
acornfb_parse_dram(char *opt)
{ {
unsigned int size; unsigned int size;
...@@ -1134,15 +1130,14 @@ acornfb_parse_dram(char *opt) ...@@ -1134,15 +1130,14 @@ acornfb_parse_dram(char *opt)
static struct options { static struct options {
char *name; char *name;
void (*parse)(char *opt); void (*parse)(char *opt);
} opt_table[] __initdata = { } opt_table[] __devinitdata = {
{ "mon", acornfb_parse_mon }, { "mon", acornfb_parse_mon },
{ "montype", acornfb_parse_montype }, { "montype", acornfb_parse_montype },
{ "dram", acornfb_parse_dram }, { "dram", acornfb_parse_dram },
{ NULL, NULL } { NULL, NULL }
}; };
int __init static int __devinit acornfb_setup(char *options)
acornfb_setup(char *options)
{ {
struct options *optp; struct options *optp;
char *opt; char *opt;
...@@ -1179,8 +1174,7 @@ acornfb_setup(char *options) ...@@ -1179,8 +1174,7 @@ acornfb_setup(char *options)
* Detect type of monitor connected * Detect type of monitor connected
* For now, we just assume SVGA * For now, we just assume SVGA
*/ */
static int __init static int __devinit acornfb_detect_monitortype(void)
acornfb_detect_monitortype(void)
{ {
return 4; return 4;
} }
......
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