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
This commit is contained in:
commit
75c0b3b466
10 changed files with 109 additions and 71 deletions
|
@ -74,7 +74,7 @@ ZTEXTADDR := $(CONFIG_ZBOOT_ROM_TEXT)
|
|||
ZBSSADDR := $(CONFIG_ZBOOT_ROM_BSS)
|
||||
else
|
||||
ZTEXTADDR := 0
|
||||
ZBSSADDR := ALIGN(4)
|
||||
ZBSSADDR := ALIGN(8)
|
||||
endif
|
||||
|
||||
SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/
|
||||
|
|
|
@ -179,15 +179,14 @@ not_angel:
|
|||
bl cache_on
|
||||
|
||||
restart: adr r0, LC0
|
||||
ldmia r0, {r1, r2, r3, r5, r6, r9, r11, r12}
|
||||
ldr sp, [r0, #32]
|
||||
ldmia r0, {r1, r2, r3, r6, r9, r11, r12}
|
||||
ldr sp, [r0, #28]
|
||||
|
||||
/*
|
||||
* We might be running at a different address. We need
|
||||
* to fix up various pointers.
|
||||
*/
|
||||
sub r0, r0, r1 @ calculate the delta offset
|
||||
add r5, r5, r0 @ _start
|
||||
add r6, r6, r0 @ _edata
|
||||
|
||||
#ifndef CONFIG_ZBOOT_ROM
|
||||
|
@ -206,31 +205,40 @@ restart: adr r0, LC0
|
|||
/*
|
||||
* Check to see if we will overwrite ourselves.
|
||||
* r4 = final kernel address
|
||||
* r5 = start of this image
|
||||
* r9 = size of decompressed image
|
||||
* r10 = end of this image, including bss/stack/malloc space if non XIP
|
||||
* We basically want:
|
||||
* r4 >= r10 -> OK
|
||||
* r4 + image length <= r5 -> OK
|
||||
* r4 - 16k page directory >= r10 -> OK
|
||||
* r4 + image length <= current position (pc) -> OK
|
||||
*/
|
||||
add r10, r10, #16384
|
||||
cmp r4, r10
|
||||
bhs wont_overwrite
|
||||
add r10, r4, r9
|
||||
cmp r10, r5
|
||||
ARM( cmp r10, pc )
|
||||
THUMB( mov lr, pc )
|
||||
THUMB( cmp r10, lr )
|
||||
bls wont_overwrite
|
||||
|
||||
/*
|
||||
* Relocate ourselves past the end of the decompressed kernel.
|
||||
* r5 = start of this image
|
||||
* r6 = _edata
|
||||
* r10 = end of the decompressed kernel
|
||||
* Because we always copy ahead, we need to do it from the end and go
|
||||
* 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
|
||||
|
||||
/* 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
|
||||
add r9, r9, #31 @ rounded up to a multiple
|
||||
bic r9, r9, #31 @ ... of 32 bytes
|
||||
|
@ -245,6 +253,11 @@ restart: adr r0, LC0
|
|||
/* Preserve offset to relocated code. */
|
||||
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
|
||||
|
||||
adr r0, BSYM(restart)
|
||||
|
@ -333,7 +346,6 @@ not_relocated: mov r0, #0
|
|||
LC0: .word LC0 @ r1
|
||||
.word __bss_start @ r2
|
||||
.word _end @ r3
|
||||
.word _start @ r5
|
||||
.word _edata @ r6
|
||||
.word _image_size @ r9
|
||||
.word _got_start @ r11
|
||||
|
@ -1062,6 +1074,7 @@ memdump: mov r12, r0
|
|||
#endif
|
||||
|
||||
.ltorg
|
||||
reloc_code_end:
|
||||
|
||||
.align
|
||||
.section ".stack", "aw", %nobits
|
||||
|
|
|
@ -54,6 +54,7 @@ SECTIONS
|
|||
.bss : { *(.bss) }
|
||||
_end = .;
|
||||
|
||||
. = ALIGN(8); /* the stack must be 64-bit aligned */
|
||||
.stack : { *(.stack) }
|
||||
|
||||
.stab 0 : { *(.stab) }
|
||||
|
|
|
@ -159,7 +159,7 @@ extern unsigned int user_debug;
|
|||
#include <mach/barriers.h>
|
||||
#elif defined(CONFIG_ARM_DMA_MEM_BUFFERABLE) || defined(CONFIG_SMP)
|
||||
#define mb() do { dsb(); outer_sync(); } while (0)
|
||||
#define rmb() dmb()
|
||||
#define rmb() dsb()
|
||||
#define wmb() mb()
|
||||
#else
|
||||
#include <asm/memory.h>
|
||||
|
|
|
@ -597,45 +597,19 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
|
|||
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
|
||||
*/
|
||||
static int
|
||||
handle_signal(unsigned long sig, struct k_sigaction *ka,
|
||||
siginfo_t *info, sigset_t *oldset,
|
||||
struct pt_regs * regs, int syscall)
|
||||
struct pt_regs * regs)
|
||||
{
|
||||
struct thread_info *thread = current_thread_info();
|
||||
struct task_struct *tsk = current;
|
||||
int usig = sig;
|
||||
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
|
||||
*/
|
||||
|
@ -685,6 +659,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
|
|||
*/
|
||||
static void do_signal(struct pt_regs *regs, int syscall)
|
||||
{
|
||||
unsigned int retval = 0, continue_addr = 0, restart_addr = 0;
|
||||
struct k_sigaction ka;
|
||||
siginfo_t info;
|
||||
int signr;
|
||||
|
@ -698,18 +673,61 @@ static void do_signal(struct pt_regs *regs, int syscall)
|
|||
if (!user_mode(regs))
|
||||
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())
|
||||
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);
|
||||
if (signr > 0) {
|
||||
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))
|
||||
oldset = ¤t->saved_sigmask;
|
||||
else
|
||||
oldset = ¤t->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
|
||||
* sigmask will have been stored in the signal frame,
|
||||
|
@ -723,11 +741,14 @@ static void do_signal(struct pt_regs *regs, int syscall)
|
|||
}
|
||||
|
||||
no_signal:
|
||||
/*
|
||||
* No signal to deliver to the process - restart the 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)) {
|
||||
regs->ARM_r7 = __NR_restart_syscall - __NR_SYSCALL_BASE;
|
||||
regs->ARM_pc -= 2;
|
||||
|
@ -750,11 +771,6 @@ static void do_signal(struct pt_regs *regs, int syscall)
|
|||
#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
|
||||
* back.
|
||||
|
|
|
@ -4,5 +4,5 @@
|
|||
* operation to deadlock the system.
|
||||
*/
|
||||
#define mb() dsb()
|
||||
#define rmb() dmb()
|
||||
#define rmb() dsb()
|
||||
#define wmb() mb()
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
#include <asm/outercache.h>
|
||||
|
||||
#define rmb() dmb()
|
||||
#define rmb() dsb()
|
||||
#define wmb() do { dsb(); outer_sync(); } while (0)
|
||||
#define mb() wmb()
|
||||
|
||||
|
|
|
@ -392,7 +392,7 @@ free_memmap(unsigned long start_pfn, unsigned long end_pfn)
|
|||
* Convert start_pfn/end_pfn to a struct page pointer.
|
||||
*/
|
||||
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
|
||||
|
@ -426,6 +426,14 @@ static void __init free_unused_memmap(struct meminfo *mi)
|
|||
|
||||
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
|
||||
* between the current bank and the previous, free it.
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
#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)
|
||||
|
|
|
@ -527,7 +527,7 @@ static void __init etherh_banner(void)
|
|||
* Read the ethernet address string from the on board rom.
|
||||
* 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;
|
||||
char *s;
|
||||
|
@ -655,7 +655,7 @@ static const struct net_device_ops etherh_netdev_ops = {
|
|||
static u32 etherh_regoffsets[16];
|
||||
static u32 etherm_regoffsets[16];
|
||||
|
||||
static int __init
|
||||
static int __devinit
|
||||
etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
|
||||
{
|
||||
const struct etherh_data *data = id->data;
|
||||
|
|
|
@ -66,7 +66,7 @@
|
|||
* have. Allow 1% either way on the nominal for TVs.
|
||||
*/
|
||||
#define NR_MONTYPES 6
|
||||
static struct fb_monspecs monspecs[NR_MONTYPES] __initdata = {
|
||||
static struct fb_monspecs monspecs[NR_MONTYPES] __devinitdata = {
|
||||
{ /* TV */
|
||||
.hfmin = 15469,
|
||||
.hfmax = 15781,
|
||||
|
@ -873,7 +873,7 @@ static struct fb_ops acornfb_ops = {
|
|||
/*
|
||||
* Everything after here is initialisation!!!
|
||||
*/
|
||||
static struct fb_videomode modedb[] __initdata = {
|
||||
static struct fb_videomode modedb[] __devinitdata = {
|
||||
{ /* 320x256 @ 50Hz */
|
||||
NULL, 50, 320, 256, 125000, 92, 62, 35, 19, 38, 2,
|
||||
FB_SYNC_COMP_HIGH_ACT,
|
||||
|
@ -925,8 +925,7 @@ static struct fb_videomode modedb[] __initdata = {
|
|||
}
|
||||
};
|
||||
|
||||
static struct fb_videomode __initdata
|
||||
acornfb_default_mode = {
|
||||
static struct fb_videomode acornfb_default_mode __devinitdata = {
|
||||
.name = NULL,
|
||||
.refresh = 60,
|
||||
.xres = 640,
|
||||
|
@ -942,7 +941,7 @@ acornfb_default_mode = {
|
|||
.vmode = FB_VMODE_NONINTERLACED
|
||||
};
|
||||
|
||||
static void __init acornfb_init_fbinfo(void)
|
||||
static void __devinit acornfb_init_fbinfo(void)
|
||||
{
|
||||
static int first = 1;
|
||||
|
||||
|
@ -1018,8 +1017,7 @@ static void __init acornfb_init_fbinfo(void)
|
|||
* size can optionally be followed by 'M' or 'K' for
|
||||
* MB or KB respectively.
|
||||
*/
|
||||
static void __init
|
||||
acornfb_parse_mon(char *opt)
|
||||
static void __devinit acornfb_parse_mon(char *opt)
|
||||
{
|
||||
char *p = opt;
|
||||
|
||||
|
@ -1066,8 +1064,7 @@ bad:
|
|||
current_par.montype = -1;
|
||||
}
|
||||
|
||||
static void __init
|
||||
acornfb_parse_montype(char *opt)
|
||||
static void __devinit acornfb_parse_montype(char *opt)
|
||||
{
|
||||
current_par.montype = -2;
|
||||
|
||||
|
@ -1108,8 +1105,7 @@ acornfb_parse_montype(char *opt)
|
|||
}
|
||||
}
|
||||
|
||||
static void __init
|
||||
acornfb_parse_dram(char *opt)
|
||||
static void __devinit acornfb_parse_dram(char *opt)
|
||||
{
|
||||
unsigned int size;
|
||||
|
||||
|
@ -1134,15 +1130,14 @@ acornfb_parse_dram(char *opt)
|
|||
static struct options {
|
||||
char *name;
|
||||
void (*parse)(char *opt);
|
||||
} opt_table[] __initdata = {
|
||||
} opt_table[] __devinitdata = {
|
||||
{ "mon", acornfb_parse_mon },
|
||||
{ "montype", acornfb_parse_montype },
|
||||
{ "dram", acornfb_parse_dram },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
int __init
|
||||
acornfb_setup(char *options)
|
||||
static int __devinit acornfb_setup(char *options)
|
||||
{
|
||||
struct options *optp;
|
||||
char *opt;
|
||||
|
@ -1179,8 +1174,7 @@ acornfb_setup(char *options)
|
|||
* Detect type of monitor connected
|
||||
* For now, we just assume SVGA
|
||||
*/
|
||||
static int __init
|
||||
acornfb_detect_monitortype(void)
|
||||
static int __devinit acornfb_detect_monitortype(void)
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue