- Patch series for parisc
Subsystems (2)
Helge Deller
maintainerPATCH 1/1 - Patch series for parisc
The following mails contain patches which I have sent to linux-parisc during the last weeks and which have not yet been applied.
I've cleaned them up for Linus' and Kyle's current trees.
Helge
Helge Deller
maintainerPATCH 1/1 compat_sys_ptrace conversions for parisc
This patch does the compat_sys_ptrace conversion for parisc. In addition it does convert the parisc ptrace code to use the architecture-independent ptrace infrastructure instead of own coding.
arch/parisc/include/asm/ptrace.h +10 -0
@@ -47,6 +47,16 @@ struct pt_regs {#define task_regs (task) ((struct pt_regs *) ((char *)(task) + TASK_REGS)) +#define __ARCH_WANT_COMPAT_SYS_PTRACE + +struct task_struct ; +#define arch_has_single_step () 1 +void user_disable_single_step (struct task_struct *task); +void user_enable_single_step (struct task_struct *task); + +#define arch_has_block_step () 1 +void user_enable_block_step (struct task_struct *task); +/* XXX should we use iaoq[1] or iaoq[0] ? */ #define user_mode (regs) (((regs)->iaoq[0] & 3) ? 1 : 0)#define user_space (regs) (((regs)->iasq[1] != 0) ? 1 : 0)
arch/parisc/kernel/ptrace.c +172 -257
484 lines not on this page · raw message
arch/parisc/kernel/syscall_table.S +1 -1
@@ -87,7 +87,7 @@ ENTRY_SAME(setuid) ENTRY_SAME(getuid) ENTRY_COMP(stime) /* 25 */ - ENTRY_SAME(ptrace) + ENTRY_COMP(ptrace) ENTRY_SAME(alarm) /* see stat comment */ ENTRY_COMP(newfstat)
Re: [PATCH] compat_sys_ptrace conversions for parisc
This should probably get a little review from Rland, I've added him to the Cc list. Although I suspect splitting this into at least two patches for compat_sys_ptrace vs the rest might make sense.
Quoted 524 lines · Helge Deller
This patch does the
compat_sys_ptraceconversion for parisc. In addition it does convert the parisc ptrace code to use the architecture-independent ptrace infrastructure instead of own coding.Signed-off-by Helge Deller <[email protected]>arch/parisc/include/asm/ptrace.h +10
-0@@ -47,6 +47,16 @@ struct pt_regs {#define task_regs (task) ((struct pt_regs *) ((char *)(task) + TASK_REGS)) +#define __ARCH_WANT_COMPAT_SYS_PTRACE + +struct task_struct ; +#define arch_has_single_step () 1 +void user_disable_single_step (struct task_struct *task); +void user_enable_single_step (struct task_struct *task); + +#define arch_has_block_step () 1 +void user_enable_block_step (struct task_struct *task); +/* XXX should we use iaoq[1] or iaoq[0] ? */ #define user_mode (regs) (((regs)->iaoq[0] & 3) ? 1 : 0)#define user_space (regs) (((regs)->iasq[1] != 0) ? 1 : 0)arch/parisc/kernel/ptrace.c +172
-257@@ -4,6 +4,7 @@* Copyright (C) 2000 Hewlett-Packard Co, Linuxcare Inc. * Copyright (C) 2000 Matthew Wilcox <[email protected]> * Copyright (C) 2000 David Huggins-Daines <[email protected]> +* Copyright (C) 2008 Helge Deller <[email protected]> */ #include <linux/kernel.h> @@ -27,15 +28,149 @@/* PSW bits we allow the debugger to modify */ #define USER_PSW_BITS (PSW_N | PSW_V | PSW_CB) -#undef DEBUG_PTRACE +/* +* Called by kernel/ptrace.c when detaching.. +* +* Make sure single step bits etc are not set. +*/ +void ptrace_disable (struct task_struct *task) +{ + task->ptrace &= ~(PT_SINGLESTEP |PT_BLOCKSTEP ); -#ifdef DEBUG_PTRACE -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif +/* make sure the trap bits are not set */ +pa_psw (task)->r =0 ; +pa_psw (task)->t =0 ; +pa_psw (task)->h =0 ; +pa_psw (task)->l =0 ; +} + +/* +* The following functions are called by ptrace_resume() when +* enabling or disabling single/block tracing. +*/ +void user_disable_single_step (struct task_struct *task) +{ +ptrace_disable (task); +} + +void user_enable_single_step (struct task_struct *task) +{ + task->ptrace &= ~PT_BLOCKSTEP ; + task->ptrace |=PT_SINGLESTEP ; + +if (pa_psw (task)->n) { +struct siginfo si; + +/* Nullified, just crank over the queue. */ +task_regs (task)->iaoq[0 ] =task_regs (task)->iaoq[1 ]; +task_regs (task)->iasq[0 ] =task_regs (task)->iasq[1 ]; +task_regs (task)->iaoq[1 ] =task_regs (task)->iaoq[0 ] +4 ; +pa_psw (task)->n =0 ; +pa_psw (task)->x =0 ; +pa_psw (task)->y =0 ; +pa_psw (task)->z =0 ; +pa_psw (task)->b =0 ; +ptrace_disable (task); +/* Don't wake up the task, but let the +parent know something happened. */ + si.si_code =TRAP_TRACE ; + si.si_addr = (void __user *) (task_regs (task)->iaoq[0 ] & ~3 ); + si.si_signo =SIGTRAP ; + si.si_errno =0 ; +force_sig_info (SIGTRAP , &si, task); +/* notify_parent(task, SIGCHLD); */ +return ; + } + +/* Enable recovery counter traps. The recovery counter +* itself will be set to zero on a task switch. If the +* task is suspended on a syscall then the syscall return +* path will overwrite the recovery counter with a suitable +* value such that it traps once back in user space. We +* disable interrupts in the tasks PSW here also, to avoid +* interrupts while the recovery counter is decrementing. +*/ +pa_psw (task)->r =1 ; +pa_psw (task)->t =0 ; +pa_psw (task)->h =0 ; +pa_psw (task)->l =0 ; +} + +void user_enable_block_step (struct task_struct *task) +{ + task->ptrace &= ~PT_SINGLESTEP ; + task->ptrace |=PT_BLOCKSTEP ; + +/* Enable taken branch trap. */ +pa_psw (task)->r =0 ; +pa_psw (task)->t =1 ; +pa_psw (task)->h =0 ; +pa_psw (task)->l =0 ; +} + +long arch_ptrace (struct task_struct *child,long request,long addr,long data) +{ +unsigned long tmp; +long ret = -EIO ; -#ifdef CONFIG_64BIT +switch (request) { + +/* Read the word at location addr in the USER area. For ptraced +processes, the kernel saves all regs on a syscall. */ +case PTRACE_PEEKUSR : +if ((addr & (sizeof (long )-1 )) || + (unsigned long ) addr >=sizeof (struct pt_regs )) +break ; + tmp = *(unsigned long *) ((char *)task_regs (child) + addr); + ret =put_user (tmp, (unsigned long *) data); +break ; + +/* Write the word at location addr in the USER area. This will need +to change when the kernel no longer saves all regs on a syscall. +FIXME. There is a problem at the moment in that r3-r18 are only +saved if the process is ptraced on syscall entry, and even then +those values are overwritten by actual register values on syscall +exit. */ +case PTRACE_POKEUSR : +/* Some register values written here may be ignored in +* entry.S:syscall_restore_rfi; e.g. iaoq is written with +* r31/r31+4, and not with the values in pt_regs. +*/ +if (addr ==PT_PSW ) { +/* Allow writing to Nullify, Divide-step-correction, +* and carry/borrow bits. +* BEWARE, if you set N, and then single step, it won't +* stop on the nullified instruction. +*/ + data &=USER_PSW_BITS ; +task_regs (child)->gr[0 ] &= ~USER_PSW_BITS ; +task_regs (child)->gr[0 ] |= data; + ret =0 ; +break ; + } + +if ((addr & (sizeof (long )-1 )) || + (unsigned long ) addr >=sizeof (struct pt_regs )) +break ; +if ((addr >=PT_GR1 && addr <=PT_GR31 ) || + addr ==PT_IAOQ0 || addr ==PT_IAOQ1 || + (addr >=PT_FR0 && addr <=PT_FR31 +4 ) || + addr ==PT_SAR ) { + *(unsigned long *) ((char *)task_regs (child) + addr) = data; + ret =0 ; + } +break ; + +default : + ret =ptrace_request (child, request, addr, data); +break ; + } + +return ret; +} + + +#ifdef CONFIG_COMPAT /* This function is needed to translate 32 bit pt_regs offsets in to * 64 bit pt_regs offsets. For example, a 32 bit gdb under a 64 bit kernel @@ -61,106 +196,25 @@ static long translate_usr_offset(long offset)else return -1 ; } -#endif -/* -* Called by kernel/ptrace.c when detaching.. -* -* Make sure single step bits etc are not set. -*/ -void ptrace_disable (struct task_struct *child) +long compat_arch_ptrace (struct task_struct *child,compat_long_t request, +compat_ulong_t addr,compat_ulong_t data) { -/* make sure the trap bits are not set */ -pa_psw (child)->r =0 ; -pa_psw (child)->t =0 ; -pa_psw (child)->h =0 ; -pa_psw (child)->l =0 ; -} - -long arch_ptrace (struct task_struct *child,long request,long addr,long data) -{ -long ret; -#ifdef DEBUG_PTRACE -long oaddr=addr, odata=data; -#endif +compat_uint_t tmp; +long ret = -EIO ;switch (request) { -case PTRACE_PEEKTEXT :/* read word at location addr. */ -case PTRACE_PEEKDATA : { -#ifdef CONFIG_64BIT -if (__is_compat_task (child)) { -int copied; -unsigned int tmp; - - addr &=0xffffffffL ; - copied =access_process_vm (child, addr, &tmp,sizeof (tmp),0 ); - ret = -EIO ; -if (copied !=sizeof (tmp)) - goto out_tsk; - ret =put_user (tmp,(unsigned int *) data); -DBG ("sys_ptrace(PEEK%s, %d, %lx, %lx) returning %ld, data %x\n" , - request ==PTRACE_PEEKTEXT ?"TEXT" :"DATA" , - pid, oaddr, odata, ret, tmp); - } - else -#endif - ret =generic_ptrace_peekdata (child, addr, data); - goto out_tsk; - } -/* when I and D space are separate, this will have to be fixed. */ -case PTRACE_POKETEXT :/* write the word at location addr. */ -case PTRACE_POKEDATA : - ret =0 ; -#ifdef CONFIG_64BIT -if (__is_compat_task (child)) { -unsigned int tmp = (unsigned int )data; -DBG ("sys_ptrace(POKE%s, %d, %lx, %lx)\n" , - request ==PTRACE_POKETEXT ?"TEXT" :"DATA" , - pid, oaddr, odata); - addr &=0xffffffffL ; -if (access_process_vm (child, addr, &tmp,sizeof (tmp),1 ) ==sizeof (tmp)) - goto out_tsk; - } - else -#endif - { -if (access_process_vm (child, addr, &data,sizeof (data),1 ) ==sizeof (data)) - goto out_tsk; - } - ret = -EIO ; - goto out_tsk; - -/* Read the word at location addr in the USER area. For ptraced -processes, the kernel saves all regs on a syscall. */ -case PTRACE_PEEKUSR : { - ret = -EIO ; -#ifdef CONFIG_64BIT -if (__is_compat_task (child)) { -unsigned int tmp; - -if (addr & (sizeof (int )-1 )) - goto out_tsk; -if ((addr =translate_usr_offset (addr)) <0 ) - goto out_tsk; - - tmp = *(unsigned int *) ((char *)task_regs (child) + addr); - ret =put_user (tmp, (unsigned int *) data); -DBG ("sys_ptrace(PEEKUSR, %d, %lx, %lx) returning %ld, addr %lx, data %x\n" , - pid, oaddr, odata, ret, addr, tmp); - } - else -#endif - { -unsigned long tmp; +case PTRACE_PEEKUSR : +if (addr & (sizeof (compat_uint_t)-1 )) +break ; + addr =translate_usr_offset (addr); +if (addr <0 ) +break ; -if ((addr & (sizeof (long )-1 )) || (unsigned long ) addr >=sizeof (struct pt_regs )) - goto out_tsk; - tmp = *(unsigned long *) ((char *)task_regs (child) + addr); - ret =put_user (tmp, (unsigned long *) data); - } - goto out_tsk; - } + tmp = *(compat_uint_t *) ((char *)task_regs (child) + addr); + ret =put_user (tmp, (compat_uint_t *) (unsigned long ) data); +break ;/* Write the word at location addr in the USER area. This will need to change when the kernel no longer saves all regs on a syscall. @@ -169,185 +223,46 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)those values are overwritten by actual register values on syscall exit. */ case PTRACE_POKEUSR : - ret = -EIO ;/* Some register values written here may be ignored in * entry.S:syscall_restore_rfi; e.g. iaoq is written with * r31/r31+4, and not with the values in pt_regs. */ -/* PT_PSW=0, so this is valid for 32 bit processes under 64 -* bit kernels. -*/ if (addr ==PT_PSW ) { -/* PT_PSW=0, so this is valid for 32 bit processes -* under 64 bit kernels. -* -* Allow writing to Nullify, Divide-step-correction, -* and carry/borrow bits. -* BEWARE, if you set N, and then single step, it won't -* stop on the nullified instruction. +/* Since PT_PSW==0, it is valid for 32 bit processes +* under 64 bit kernels as well. */ -DBG ("sys_ptrace(POKEUSR, %d, %lx, %lx)\n" , - pid, oaddr, odata); - data &=USER_PSW_BITS ; -task_regs (child)->gr[0 ] &= ~USER_PSW_BITS ; -task_regs (child)->gr[0 ] |= data; - ret =0 ; - goto out_tsk; - } -#ifdef CONFIG_64BIT -if (__is_compat_task (child)) { -if (addr & (sizeof (int )-1 )) - goto out_tsk; -if ((addr =translate_usr_offset (addr)) <0 ) - goto out_tsk; -DBG ("sys_ptrace(POKEUSR, %d, %lx, %lx) addr %lx\n" , - pid, oaddr, odata, addr); + ret =arch_ptrace (child, request, addr, data); + }else { +if (addr & (sizeof (compat_uint_t)-1 )) +break ; + addr =translate_usr_offset (addr); +if (addr <0 ) +break ;if (addr >=PT_FR0 && addr <=PT_FR31 +4 ) {/* Special case, fp regs are 64 bits anyway */ - *(unsigned int *) ((char *)task_regs (child) + addr) = data; + *(__u64 *) ((char *)task_regs (child) + addr) = data; ret =0 ; }else if ((addr >=PT_GR1 +4 && addr <=PT_GR31 +4 ) || addr ==PT_IAOQ0 +4 || addr ==PT_IAOQ1 +4 || addr ==PT_SAR +4 ) {/* Zero the top 32 bits */ - *(unsigned int *) ((char *)task_regs (child) + addr -4 ) =0 ; - *(unsigned int *) ((char *)task_regs (child) + addr) = data; + *(__u32 *) ((char *)task_regs (child) + addr -4 ) =0 ; + *(__u32 *) ((char *)task_regs (child) + addr) = data; ret =0 ; } - goto out_tsk; } - else -#endif - { -if ((addr & (sizeof (long )-1 )) || (unsigned long ) addr >=sizeof (struct pt_regs )) - goto out_tsk; -if ((addr >=PT_GR1 && addr <=PT_GR31 ) || - addr ==PT_IAOQ0 || addr ==PT_IAOQ1 || - (addr >=PT_FR0 && addr <=PT_FR31 +4 ) || - addr ==PT_SAR ) { - *(unsigned long *) ((char *)task_regs (child) + addr) = data; - ret =0 ; - } - goto out_tsk; - } - -case PTRACE_SYSCALL :/* continue and stop at next (return from) syscall */ -case PTRACE_CONT : - ret = -EIO ; -DBG ("sys_ptrace(%s)\n" , - request ==PTRACE_SYSCALL ?"SYSCALL" :"CONT" ); -if (!valid_signal (data)) - goto out_tsk; - child->ptrace &= ~(PT_SINGLESTEP |PT_BLOCKSTEP ); -if (request ==PTRACE_SYSCALL ) { -set_tsk_thread_flag (child,TIF_SYSCALL_TRACE ); - }else { -clear_tsk_thread_flag (child,TIF_SYSCALL_TRACE ); - } - child->exit_code = data; - goto out_wake_notrap; - -case PTRACE_KILL : -/* -* make the child exit. Best I can do is send it a -* sigkill. perhaps it should be put in the status -* that it wants to exit. -*/ - ret =0 ; -DBG ("sys_ptrace(KILL)\n" ); -if (child->exit_state ==EXIT_ZOMBIE )/* already dead */ - goto out_tsk; - child->exit_code =SIGKILL ; - goto out_wake_notrap; - -case PTRACE_SINGLEBLOCK : -DBG ("sys_ptrace(SINGLEBLOCK)\n" ); - ret = -EIO ; -if (!valid_signal (data)) - goto out_tsk; -clear_tsk_thread_flag (child,TIF_SYSCALL_TRACE ); - child->ptrace &= ~PT_SINGLESTEP ; - child->ptrace |=PT_BLOCKSTEP ; - child->exit_code = data; - -/* Enable taken branch trap. */ -pa_psw (child)->r =0 ; -pa_psw (child)->t =1 ; -pa_psw (child)->h =0 ; -pa_psw (child)->l =0 ; - goto out_wake; - -case PTRACE_SINGLESTEP : -DBG ("sys_ptrace(SINGLESTEP)\n" ); - ret = -EIO ; -if (!valid_signal (data)) - goto out_tsk; - -clear_tsk_thread_flag (child,TIF_SYSCALL_TRACE ); - child->ptrace &= ~PT_BLOCKSTEP ; - child->ptrace |=PT_SINGLESTEP ; - child->exit_code = data; - -if (pa_psw (child)->n) { -struct siginfo si; - -/* Nullified, just crank over the queue. */ -task_regs (child)->iaoq[0 ] =task_regs (child)->iaoq[1 ]; -task_regs (child)->iasq[0 ] =task_regs (child)->iasq[1 ]; -task_regs (child)->iaoq[1 ] =task_regs (child)->iaoq[0 ] +4 ; -pa_psw (child)->n =0 ; -pa_psw (child)->x =0 ; -pa_psw (child)->y =0 ; -pa_psw (child)->z =0 ; -pa_psw (child)->b =0 ; -ptrace_disable (child); -/* Don't wake up the child, but let the -parent know something happened. */ - si.si_code =TRAP_TRACE ; - si.si_addr = (void __user *) (task_regs (child)->iaoq[0 ] & ~3 ); - si.si_signo =SIGTRAP ; - si.si_errno =0 ; -force_sig_info (SIGTRAP , &si, child); -//notify_parent(child, SIGCHLD); -//ret = 0; - goto out_wake; - } - -/* Enable recovery counter traps. The recovery counter -* itself will be set to zero on a task switch. If the -* task is suspended on a syscall then the syscall return -* path will overwrite the recovery counter with a suitable -* value such that it traps once back in user space. We -* disable interrupts in the childs PSW here also, to avoid -* interrupts while the recovery counter is decrementing. -*/ -pa_psw (child)->r =1 ; -pa_psw (child)->t =0 ; -pa_psw (child)->h =0 ; -pa_psw (child)->l =0 ; -/* give it a chance to run. */ - goto out_wake; - -case PTRACE_GETEVENTMSG : - ret =put_user (child->ptrace_message, (unsigned int __user *) data); - goto out_tsk; +break ;default : - ret =ptrace_request (child, request, addr, data); - goto out_tsk; + ret =compat_ptrace_request (child, request, addr, data); + break; } -out_wake_notrap: -ptrace_disable (child); -out_wake: -wake_up_process (child); - ret =0 ; -out_tsk: -DBG ("arch_ptrace(%ld, %d, %lx, %lx) returning %ld\n" , - request, pid, oaddr, odata, ret);return ret; } +#endif +void syscall_trace (void ) {arch/parisc/kernel/syscall_table.S +0
-0
arch/parisc/kernel/syscall_table.S line 93
Quoted 8 lines
arch/parisc/kernel/syscall_table.S +1
-1@@ -87,7 +87,7 @@ ENTRY_SAME(setuid) ENTRY_SAME(getuid) ENTRY_COMP(stime) /* 25 */ - ENTRY_SAME(ptrace) + ENTRY_COMP(ptrace) ENTRY_SAME(alarm) /* see stat comment */ ENTRY_COMP(newfstat)
---end quoted text---
Re: [PATCH] compat_sys_ptrace conversions for parisc
Quoted 3 lines
This should probably get a little review from Rland, I've added him to the Cc list. Although I suspect splitting this into at least two patches for
compat_sys_ptracevs the rest might make sense.
For the machines where I've done this work, I've certainly been well-served by breaking it into many smaller incremental patches. That would make the meat of each patch far easier to read than this one big patch is.
It seems odd to have user_disable_single_step call ptrace_disable rather than vice versa. Otherwise, off hand I don't see anything particularly suspect in the patch, but I'll admit I didn't look too close because the one big diff is a pain to read.
Thanks,
Roland
Re: [PATCH] compat_sys_ptrace conversions for parisc
In reply to Helge DellerQuoted 4 lines · Helge Deller
This patch does the
compat_sys_ptraceconversion for parisc. In addition it does convert the parisc ptrace code to use the architecture-independent ptrace infrastructure instead of own coding.
This sounds like it should be two seperate patches, for at least the reason of making bisecting easier should there be a problem.
Helge Deller
maintainerRe: [PATCH] compat_sys_ptrace conversions for parisc
Hi Kyle, Hi Christoph,
Quoted 4 lines · Kyle McMartin
Quoted 3 lines · Helge Deller
This patch does the
compat_sys_ptraceconversion for parisc. In addition it does convert the parisc ptrace code to use the architecture-independent ptrace infrastructure instead of own coding.
Both of you said someting like this:
Quoted 2 lines
This sounds like it should be two seperate patches, for at least the reason of making bisecting easier should there be a problem.
I agree that my comment suggests that splitting the patch into two parts could make sense to track the changes easier, but if you look into the original code you'll see, that I would need to duplicate all of the arch_ptrace code and then make the copied part 64bit-ready. Then the second patch would delete all of this again and replacing it with the generic function calls. IMHO that's a lot of coding and changes without any need. You'll first need to understand coding in my first patch which is then deleted afterwards with the second patch again. And if you look at the final ptrace.c file after applying my patch which I posted here, you'll see that arch_ptrace is now really small and simple to understand.
That said, I'm not very motivated to split my patch.
Helge
Re: [PATCH] compat_sys_ptrace conversions for parisc
Quoted 12 lines · Helge Deller
I agree that my comment suggests that splitting the patch into two parts could make sense to track the changes easier, but if you look into the original code you'll see, that I would need to duplicate all of the
arch_ptracecode and then make the copied part 64bit-ready. Then the second patch would delete all of this again and replacing it with the generic function calls.
IMHO that's a lot of coding and changes without any need. You'll first need to understand coding in my first patch which is then deleted afterwards with the second patch again. And if you look at the finalptrace.cfile after applying my patch which I posted here, you'll see thatarch_ptraceis now really small and simple to understand.
Quoted 1 line
That said, I'm not very motivated to split my patch.
Oh, parisc actually uses sys_ptrace as the 32bit entry point. Yes, I see your point and take back the suggestion.
Helge Deller
maintainerPATCH 1/1 fix crash when trying to unwind user space
In reply to Helge DellerFix kernel to not to try to unwind functions when crash happens in userspace.
Without this patch kernel may needlessly crash for userspace faults.
arch/parisc/kernel/traps.c +6 -4
@@ -121,18 +121,19 @@ static void print_fr(char *level, struct pt_regs *regs)void show_regs (struct pt_regs *regs) { -int i; +int i, user;char *level;unsigned long cr30, cr31; - level =user_mode (regs) ?KERN_DEBUG :KERN_CRIT ; + user =user_mode (regs); + level = user ?KERN_DEBUG :KERN_CRIT ;print_gr (level, regs);for (i =0 ; i <8 ; i +=4 )PRINTREGS (level, regs->sr,"sr" ,RFMT , i); -if (user_mode (regs)) +if (user)print_fr (level, regs); cr30 =mfctl (30 );
@@ -152,7 +153,8 @@ void show_regs(struct pt_regs *regs)printk (level);print_symbol (" RP(r2): %s\n" , regs->gr[2 ]); -parisc_show_stack (current,NULL , regs); +if (!user) +parisc_show_stack (current,NULL , regs); }
Helge Deller
maintainerPATCH 1/1 drop superfluous .align 16
In reply to Helge DellerThis .align 16 is misplaced and should be in front of the ENTRY(lws_lock_start). Works because of pure luck since we have a .align PAGE_SIZE before it instead.
arch/parisc/kernel/syscall.S +0 -1
@@ -640,7 +640,6 @@ END(sys_call_table64) .align PAGE_SIZE ENTRY(lws_lock_start) /* lws locks */ - .align 16 .rept 16 /* Keep locks aligned at 16-bytes */ .word 1
James Bottomley
maintainerRe: [PATCH] drop superfluous .align 16
Quoted 10 lines · Helge Deller
This .align 16 is misplaced and should be in front of the
ENTRY(lws_lock_start). Works because of pure luck since we have a .alignPAGE_SIZEbefore it instead.Signed-off-by Helge Deller <[email protected]>arch/parisc/kernel/syscall.S +0
-0
arch/parisc/kernel/syscall.S END(sys_call_table64) · line 645
Quoted 7 lines
arch/parisc/kernel/syscall.S +0
-1@@ -640,7 +640,6 @@ END(sys_call_table64) .align PAGE_SIZE ENTRY(lws_lock_start) /* lws locks */ - .align 16 .rept 16 /* Keep locks aligned at 16-bytes */ .word 1
I think I'd really rather keep this. It may be technically superfluous because of the .align PAGE_SIZE above it, but that belongs to the syscall table. If anyone ever moved this section in head.S, the align 16 ensures nothing goes wrong.
James
Helge Deller
maintainerRe: [PATCH] drop superfluous .align 16
Quoted 23 lines · James Bottomley
Quoted 10 lines · Helge Deller
This .align 16 is misplaced and should be in front of the
ENTRY(lws_lock_start). Works because of pure luck since we have a .alignPAGE_SIZEbefore it instead.Signed-off-by Helge Deller <[email protected]>arch/parisc/kernel/syscall.S +0
-0arch/parisc/kernel/syscall.S END(sys_call_table64) · line 645
Quoted 7 lines
arch/parisc/kernel/syscall.S +0
-1@@ -640,7 +640,6 @@ END(sys_call_table64) .align PAGE_SIZE ENTRY(lws_lock_start) /* lws locks */ - .align 16 .rept 16 /* Keep locks aligned at 16-bytes */ .word 1I think I'd really rather keep this. It may be technically superfluous because of the .align
PAGE_SIZEabove it, but that belongs to the syscall table.
Quoted 2 lines
If anyone ever moved this section in
head.S, the align 16 ensures nothing goes wrong.
Hi James,
If the block is moved, then that's exactly what this .align does not ensure.
We had this discussion already here on the list. Please read the full thread: http://marc.info/?t=121554765000005&r=1&w=2
Helge
Re: [PATCH] drop superfluous .align 16
Quoted 28 lines · Helge Deller
Quoted 24 lines · James Bottomley
Quoted 12 lines · Helge Deller
This .align 16 is misplaced and should be in front of the
ENTRY(lws_lock_start).
Works because of pure luck since we have a .alignPAGE_SIZEbefore it instead.Signed-off-by Helge Deller <[email protected]>arch/parisc/kernel/syscall.S +0
-0arch/parisc/kernel/syscall.S END(sys_call_table64) · line 645
Quoted 7 lines
arch/parisc/kernel/syscall.S +0
-1@@ -640,7 +640,6 @@ END(sys_call_table64) .align PAGE_SIZE ENTRY(lws_lock_start) /* lws locks */ - .align 16 .rept 16 /* Keep locks aligned at 16-bytes */ .word 1I think I'd really rather keep this. It may be technically superfluous because of the .align
PAGE_SIZEabove it, but that belongs to the syscall table.Quoted 2 lines
If anyone ever moved this section in
head.S, the align 16 ensures nothing goes wrong.
Quoted 6 lines
Hi James,
If the block is moved, then that's exactly what this .align does not ensure.
We had this discussion already here on the list. Please read the full
thread: http://marc.info/?t=121554765000005&r=1&w=2
Helge,
Thanks for tracking and resubmitting this...Carlos already ACK'd and I think it would be good if kyle added it to his patch queue.
But I liked two other things proposed in this thread.
1) jejb's preference to document the alignement requirement
2) jda's proposal for ENTRY_ALIGN() (which accomplishes (1))
So I've hacked your patch to include those two things.
I've only build-tested this for 64-bit builds.
thanks,
grant
arch/parisc/kernel/syscall.S +2 -3
@@ -638,11 +638,10 @@ END(sys_call_table64) */ .section .data .align PAGE_SIZE -ENTRY(lws_lock_start) + +ENTRY_ALIGN(lws_lock_start,16) /* lws locks */ - .align 16 .rept 16 - /* Keep locks aligned at 16-bytes */ .word 1 .word 0 .word 0
include/asm-parisc/linkage.h +5 -0
@@ -17,6 +17,11 @@ ALIGN !\ name: +#define ENTRY_ALIGN(name,alignval) \ + .export name !\ + .align alignval !\ +name: + #ifdef CONFIG_64BIT #define ENDPROC(name) \ END(name)
Re: [PATCH] drop superfluous .align 16
Quoted 9 lines · Grant Grundler
Thanks for tracking and resubmitting this...Carlos already ACK'd and I think it would be good if kyle added it to his patch queue.
But I liked two other things proposed in this thread.
1) jejb's preference to document the alignement requirement
2) jda's proposal forENTRY_ALIGN()(which accomplishes (1))So I've hacked your patch to include those two things.
Quoted 7 lines
I've only build-tested this for 64-bit builds.
thanks,
grantSigned-off-by Helge Deller <[email protected]>Signed-off-by Grant Grundler <[email protected]>
I agree with both Helge's original patch and this one. Thanks for making an ENTRY_ALIGN macro. The macro keeps the symbol and alignment together. Well done.
Cheers,
Carlos.
James Bottomley
maintainerRe: [PATCH] drop superfluous .align 16
Quoted 11 lines · Carlos O'Donell
Quoted 9 lines · Grant Grundler
Thanks for tracking and resubmitting this...Carlos already ACK'd and I think it would be good if kyle added it to his patch queue.
But I liked two other things proposed in this thread.
1) jejb's preference to document the alignement requirement
2) jda's proposal forENTRY_ALIGN()(which accomplishes (1))So I've hacked your patch to include those two things.
Quoted 7 lines
Quoted 7 lines
I've only build-tested this for 64-bit builds.
thanks,
grantSigned-off-by Helge Deller <[email protected]>Signed-off-by Grant Grundler <[email protected]>
Can we get this right, please ... we'll get into awful penguin trouble if he catches us misusing the DCO:
Quoted 1 line
Signed-off-by Carlos O'Donell <[email protected]>
That's not signed off by you. You only get to add a signed-off-by if the patch physically passes through your hands. That means that Grant's above is correct because he modified the patch and resent it, but yours isn't because you did nothing with it (and you didn't pass it on).
You can add Acked-by: if you like (that usually means I'm the person in charge of the relevant code and I approved sending it through someone else's tree) or Reviewed-by: (I actually looked through the patch and it seems to be fine to me).
James
Carlos O'Donell
Acked-byRe: [PATCH] drop superfluous .align 16
Quoted 30 lines · James Bottomley
Quoted 11 lines · Carlos O'Donell
Quoted 9 lines · Grant Grundler
Thanks for tracking and resubmitting this...Carlos already ACK'd and I think it would be good if kyle added it to his patch queue.
But I liked two other things proposed in this thread.
1) jejb's preference to document the alignement requirement
2) jda's proposal forENTRY_ALIGN()(which accomplishes (1))So I've hacked your patch to include those two things.
Quoted 7 lines
Quoted 7 lines
I've only build-tested this for 64-bit builds.
thanks,
grantSigned-off-by Helge Deller <[email protected]>Signed-off-by Grant Grundler <[email protected]>Can we get this right, please ... we'll get into awful penguin trouble if he catches us misusing the DCO:
Quoted 1 line
Signed-off-by Carlos O'Donell <[email protected]>That's not signed off by you. You only get to add a signed-off-by if the patch physically passes through your hands. That means that Grant's above is correct because he modified the patch and resent it, but yours isn't because you did nothing with it (and you didn't pass it on).
Quoted 4 lines
You can add Acked-by: if you like (that usually means I'm the person in charge of the relevant code and I approved sending it through someone else's tree) or Reviewed-by: (I actually looked through the patch and it seems to be fine to me).
Quite right. Sorry for the cut-n-paste.
Since I wrote the code, I consider myself the maintainer.
Cheers,
Carlos.
Helge Deller
maintainerPATCH 1/1 ldcw inline assembler patch
In reply to Helge DellerThere are two reasons to expose the memory *a in the asm:
1) To prevent the compiler from discarding a preceeding write to *a, and
2) to prevent it from caching *a in a register over the asm.
The change has had a few days testing with a SMP build of 2.6.22.19 running on a rp3440.
This patch is about the correctness of the __ldcw() macro itself. The use of the macro should be confined to small inline functions to try to limit the effect of clobbering memory on GCC's optimization of loads and stores.
arch/parisc/include/asm/system.h +2 -2
@@ -168,8 +168,8 @@ static inline void set_eiem(unsigned long val)/* LDCW, the only atomic read-write operation PA-RISC has. *sigh*. */ #define __ldcw (a) ({ \ unsigned __ret; \ - __asm__ __volatile__(__LDCW " 0(%1),%0" \ - : "=r" (__ret) : "r" (a)); \ + __asm__ __volatile__(__LDCW " 0(%2),%0" \ + : "=r" (__ret), "+m" (*(a)) : "r" (a)); \ __ret; \ })
Helge Deller
maintainerPATCH 1/1 Change cpu_data[] and cpu_devices[] from array sized by NR_CPUS to per_cpu variables
In reply to Helge Deller!! Probably needs some testing on a SMP box before it can be applied !!
arch/parisc/include/asm/processor.h +2 -2
@@ -17,6 +17,7 @@#include <asm/ptrace.h> #include <asm/types.h> #include <asm/system.h> +#include <asm/percpu.h> #endif /* __ASSEMBLY__ */ #define KERNEL_STACK_SIZE (4*PAGE_SIZE)
@@ -109,8 +110,7 @@ struct cpuinfo_parisc { };extern struct system_cpuinfo_parisc boot_cpu_data; -extern struct cpuinfo_parisc cpu_data[NR_CPUS ]; -#define current_cpu_data cpu_data[smp_processor_id()] +DECLARE_PER_CPU(struct cpuinfo_parisc, cpu_data);#define CPU_HVERSION ((boot_cpu_data.hversion >> 4) & 0x0FFF)
arch/parisc/kernel/irq.c +6 -5
@@ -298,7 +298,7 @@ unsigned long txn_affinity_addr(unsigned int irq, int cpu) irq_desc[irq].affinity =cpumask_of_cpu (cpu);#endif -return cpu_data[cpu].txn_addr; +return per_cpu (cpu_data, cpu).txn_addr; }
@@ -309,8 +309,9 @@ unsigned long txn_alloc_addr(unsigned int virt_irq) next_cpu++;/* assign to "next" CPU we want this bugger on */ /* validate entry */ -while ((next_cpu <NR_CPUS ) && (!cpu_data[next_cpu].txn_addr || - !cpu_online (next_cpu))) +while ((next_cpu <NR_CPUS ) && + (!per_cpu (cpu_data, next_cpu).txn_addr || + !cpu_online (next_cpu))) next_cpu++;if (next_cpu >=NR_CPUS )
@@ -359,7 +360,7 @@ void do_cpu_irq_mask(struct pt_regs *regs)printk (KERN_DEBUG "redirecting irq %d from CPU %d to %d\n" , irq,smp_processor_id (), cpu);gsc_writel (irq +CPU_IRQ_BASE , - cpu_data[cpu].hpa); +per_cpu (cpu_data, cpu).hpa); goto set_out; }#endif
@@ -421,5 +422,5 @@ void __init init_IRQ(void)void ack_bad_irq (unsigned int irq) { -printk ("unexpected IRQ %d\n" , irq); +printk (KERN_WARNING "unexpected IRQ %d\n" , irq); }
arch/parisc/kernel/processor.c +35 -33
140 lines not on this page · raw message
arch/parisc/kernel/setup.c +1 -1
@@ -319,7 +319,7 @@ static int __init parisc_init(void)processor_init ();printk (KERN_INFO "CPU(s): %d x %s at %d.%06d MHz\n" , - boot_cpu_data.cpu_count, +num_present_cpus (), boot_cpu_data.cpu_name, boot_cpu_data.cpu_hz /1000000 , boot_cpu_data.cpu_hz %1000000 );
arch/parisc/kernel/smp.c +15 -17
@@ -56,16 +56,17 @@ static int smp_debug_lvl = 0;if (lvl >= smp_debug_lvl) \printk (printargs);#else -#define smp_debug (lvl, ...) +#define smp_debug (lvl, ...) do { } while(0)#endif /* DEBUG_SMP */ DEFINE_SPINLOCK (smp_lock);volatile struct task_struct *smp_init_current_idle_task; -static volatile int cpu_now_booting__read_mostly =0 ;/* track which CPU is booting */ +/* track which CPU is booting */ +static volatile int cpu_now_booting__cpuinitdata ; -static int parisc_max_cpus__read_mostly =1 ; +static int parisc_max_cpus__cpuinitdata =1 ;/* online cpus are ones that we've managed to bring up completely * possible cpus are all valid cpu
@@ -138,7 +139,7 @@ irqreturn_t ipi_interrupt(int irq, void *dev_id) { int this_cpu = smp_processor_id(); -struct cpuinfo_parisc *p = &cpu_data[this_cpu]; +struct cpuinfo_parisc *p = &per_cpu (cpu_data, this_cpu);unsigned long ops;unsigned long flags;
@@ -217,13 +218,13 @@ ipi_interrupt(int irq, void *dev_id)static inline void ipi_send (int cpu,enum ipi_message_type op) { -struct cpuinfo_parisc *p = &cpu_data[cpu]; +struct cpuinfo_parisc *p = &per_cpu (cpu_data, cpu);spinlock_t *lock = &per_cpu (ipi_lock, cpu);unsigned long flags;spin_lock_irqsave (lock, flags); p->pending_ipi |=1 << op; -gsc_writel (IPI_IRQ -CPU_IRQ_BASE , cpu_data[cpu].hpa); +gsc_writel (IPI_IRQ -CPU_IRQ_BASE , p->hpa);spin_unlock_irqrestore (lock, flags); }
@@ -239,10 +240,7 @@ send_IPI_mask(cpumask_t mask, enum ipi_message_type op)static inline void send_IPI_single (int dest_cpu,enum ipi_message_type op) { -if (dest_cpu ==NO_PROC_ID ) { -BUG (); -return ; - } +BUG_ON (dest_cpu ==NO_PROC_ID );ipi_send (dest_cpu, op); }
@@ -324,8 +322,7 @@ smp_cpu_init(int cpunum)/* Initialise the idle task for this CPU */ atomic_inc (&init_mm.mm_count); current->active_mm = &init_mm; -if (current->mm) -BUG (); +BUG_ON (current->mm);enter_lazy_tlb (&init_mm, current);init_IRQ ();/* make sure no IRQs are enabled or pending */
@@ -360,6 +357,7 @@ void __init smp_callin(void)*/ int __cpuinit smp_boot_one_cpu (int cpuid) { +const struct cpuinfo_parisc *p = &per_cpu (cpu_data, cpuid);struct task_struct *idle;long timeout;
@@ -391,7 +389,7 @@ int __cpuinit smp_boot_one_cpu(int cpuid) smp_init_current_idle_task = idle ;mb (); -printk ("Releasing cpu %d now, hpa=%lx\n" , cpuid, cpu_data[cpuid].hpa); +printk (KERN_INFO "Releasing cpu %d now, hpa=%lx\n" , cpuid, p->hpa);/* ** This gets PDC to release the CPU from a very tight loop.
@@ -402,7 +400,7 @@ int __cpuinit smp_boot_one_cpu(int cpuid)** EIR{0}). MEM_RENDEZ is valid only when it is nonzero and the ** contents of memory are valid." */ -gsc_writel (TIMER_IRQ -CPU_IRQ_BASE , cpu_data[cpuid].hpa); +gsc_writel (TIMER_IRQ -CPU_IRQ_BASE , p->hpa);mb ();/*
@@ -434,12 +432,12 @@ alive:return 0 ; } -void __devinit smp_prepare_boot_cpu (void ) +void __init smp_prepare_boot_cpu (void ) { -int bootstrap_processor=cpu_data[0 ].cpuid;/* CPU ID of BSP */ +int bootstrap_processor =per_cpu (cpu_data,0 ).cpuid;/* Setup BSP mappings */ -printk ("SMP: bootstrap CPU ID is %d\n" ,bootstrap_processor); +printk (KERN_INFO "SMP: bootstrap CPU ID is %d\n" , bootstrap_processor);cpu_set (bootstrap_processor, cpu_online_map);cpu_set (bootstrap_processor, cpu_present_map);
arch/parisc/kernel/time.c +2 -2
@@ -59,7 +59,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id)unsigned long cycles_elapsed, ticks_elapsed;unsigned long cycles_remainder;unsigned int cpu =smp_processor_id (); -struct cpuinfo_parisc *cpuinfo = &cpu_data[cpu]; +struct cpuinfo_parisc *cpuinfo = &per_cpu (cpu_data, cpu);/* gcc can optimize for "read-only" case with a local clocktick */ unsigned long cpt = clocktick;
@@ -212,7 +212,7 @@ void __init start_cpu_itimer(void)mtctl (next_tick,16 );/* kick off Interval Timer (CR16) */ - cpu_data[cpu].it_value = next_tick; +per_cpu (cpu_data, cpu).it_value = next_tick; }void __init time_init (void )
arch/parisc/kernel/topology.c +2 -2
@@ -22,14 +22,14 @@#include <linux/cpu.h> #include <linux/cache.h> -static struct cpu cpu_devices[NR_CPUS ]__read_mostly ; +static DEFINE_PER_CPU(struct cpu, cpu_devices);static int __init topology_init (void ) {int num;for_each_present_cpu (num) { -register_cpu (&cpu_devices[num], num); +register_cpu (&per_cpu (cpu_devices, num), num); }return 0 ; }
Helge Deller
maintainerRe: [PATCH] Change cpu_data[] and cpu_devices[] from array sized by NR_CPUS to per_cpu variables
Updated patch attached, which fixes some build problems and section mismatches. Boot-tested on a UP 32bit machine with CONFIG_SMP=y.
arch/parisc/include/asm/processor.h +2 -2
@@ -17,6 +17,7 @@#include <asm/ptrace.h> #include <asm/types.h> #include <asm/system.h> +#include <asm/percpu.h> #endif /* __ASSEMBLY__ */ #define KERNEL_STACK_SIZE (4*PAGE_SIZE)
@@ -109,8 +110,7 @@ struct cpuinfo_parisc { };extern struct system_cpuinfo_parisc boot_cpu_data; -extern struct cpuinfo_parisc cpu_data[NR_CPUS ]; -#define current_cpu_data cpu_data[smp_processor_id()] +DECLARE_PER_CPU(struct cpuinfo_parisc, cpu_data);#define CPU_HVERSION ((boot_cpu_data.hversion >> 4) & 0x0FFF)
arch/parisc/kernel/firmware.c +6 -6
@@ -151,7 +151,7 @@ static void convert_to_wide(unsigned long *addr) }#ifdef CONFIG_64BIT -void __init set_firmware_width_unlocked (void ) +void __cpuinit set_firmware_width_unlocked (void ) {int ret;
@@ -168,7 +168,7 @@ void __init set_firmware_width_unlocked(void)* This function must be called before any pdc_* function that uses the * convert_to_wide function. */ -void __init set_firmware_width (void ) +void __cpuinit set_firmware_width (void ) {unsigned long flags;spin_lock_irqsave (&pdc_lock, flags);
@@ -176,11 +176,11 @@ void __init set_firmware_width(void) spin_unlock_irqrestore(&pdc_lock, flags); }#else -void __init set_firmware_width_unlocked (void ) { +void __cpuinit set_firmware_width_unlocked (void ) {return ; } -void __init set_firmware_width (void ) { +void __cpuinit set_firmware_width (void ) {return ; }#endif /*CONFIG_64BIT*/
@@ -302,7 +302,7 @@ int pdc_chassis_warn(unsigned long *warn)return retval; } -int __init pdc_coproc_cfg_unlocked (struct pdc_coproc_cfg *pdc_coproc_info) +int __cpuinit pdc_coproc_cfg_unlocked (struct pdc_coproc_cfg *pdc_coproc_info) {int ret;
@@ -323,7 +323,7 @@ int __init pdc_coproc_cfg_unlocked(struct pdc_coproc_cfg *pdc_coproc_info)* This PDC call returns the presence and status of all the coprocessors * attached to the processor. */ -int __init pdc_coproc_cfg (struct pdc_coproc_cfg *pdc_coproc_info) +int __cpuinit pdc_coproc_cfg (struct pdc_coproc_cfg *pdc_coproc_info) {int ret;unsigned long flags;
arch/parisc/kernel/irq.c +6 -5
@@ -298,7 +298,7 @@ unsigned long txn_affinity_addr(unsigned int irq, int cpu) irq_desc[irq].affinity =cpumask_of_cpu (cpu);#endif -return cpu_data[cpu].txn_addr; +return per_cpu (cpu_data, cpu).txn_addr; }
@@ -309,8 +309,9 @@ unsigned long txn_alloc_addr(unsigned int virt_irq) next_cpu++;/* assign to "next" CPU we want this bugger on */ /* validate entry */ -while ((next_cpu <NR_CPUS ) && (!cpu_data[next_cpu].txn_addr || - !cpu_online (next_cpu))) +while ((next_cpu <NR_CPUS ) && + (!per_cpu (cpu_data, next_cpu).txn_addr || + !cpu_online (next_cpu))) next_cpu++;if (next_cpu >=NR_CPUS )
@@ -359,7 +360,7 @@ void do_cpu_irq_mask(struct pt_regs *regs)printk (KERN_DEBUG "redirecting irq %d from CPU %d to %d\n" , irq,smp_processor_id (), cpu);gsc_writel (irq +CPU_IRQ_BASE , - cpu_data[cpu].hpa); +per_cpu (cpu_data, cpu).hpa); goto set_out; }#endif
@@ -421,5 +422,5 @@ void __init init_IRQ(void)void ack_bad_irq (unsigned int irq) { -printk ("unexpected IRQ %d\n" , irq); +printk (KERN_WARNING "unexpected IRQ %d\n" , irq); }
arch/parisc/kernel/processor.c +35 -33
140 lines not on this page · raw message
arch/parisc/kernel/setup.c +3 -3
@@ -319,7 +319,7 @@ static int __init parisc_init(void)processor_init ();printk (KERN_INFO "CPU(s): %d x %s at %d.%06d MHz\n" , - boot_cpu_data.cpu_count, +num_present_cpus (), boot_cpu_data.cpu_name, boot_cpu_data.cpu_hz /1000000 , boot_cpu_data.cpu_hz %1000000 );
@@ -385,8 +385,8 @@ void start_parisc(void)if (ret >=0 && coproc_cfg.ccr_functional) {mtctl (coproc_cfg.ccr_functional,10 ); - cpu_data[cpunum].fp_rev = coproc_cfg.revision; - cpu_data[cpunum].fp_model = coproc_cfg.model; +per_cpu (cpu_data, cpunum).fp_rev = coproc_cfg.revision; +per_cpu (cpu_data, cpunum).fp_model = coproc_cfg.model; asmvolatile ("fstd %fr0,8(%sp)" ); }else {
arch/parisc/kernel/smp.c +15 -17
@@ -56,16 +56,17 @@ static int smp_debug_lvl = 0;if (lvl >= smp_debug_lvl) \printk (printargs);#else -#define smp_debug (lvl, ...) +#define smp_debug (lvl, ...) do { } while(0)#endif /* DEBUG_SMP */ DEFINE_SPINLOCK (smp_lock);volatile struct task_struct *smp_init_current_idle_task; -static volatile int cpu_now_booting__read_mostly =0 ;/* track which CPU is booting */ +/* track which CPU is booting */ +static volatile int cpu_now_booting__cpuinitdata ; -static int parisc_max_cpus__read_mostly =1 ; +static int parisc_max_cpus__cpuinitdata =1 ;/* online cpus are ones that we've managed to bring up completely * possible cpus are all valid cpu
@@ -138,7 +139,7 @@ irqreturn_t ipi_interrupt(int irq, void *dev_id) { int this_cpu = smp_processor_id(); -struct cpuinfo_parisc *p = &cpu_data[this_cpu]; +struct cpuinfo_parisc *p = &per_cpu (cpu_data, this_cpu);unsigned long ops;unsigned long flags;
@@ -217,13 +218,13 @@ ipi_interrupt(int irq, void *dev_id)static inline void ipi_send (int cpu,enum ipi_message_type op) { -struct cpuinfo_parisc *p = &cpu_data[cpu]; +struct cpuinfo_parisc *p = &per_cpu (cpu_data, cpu);spinlock_t *lock = &per_cpu (ipi_lock, cpu);unsigned long flags;spin_lock_irqsave (lock, flags); p->pending_ipi |=1 << op; -gsc_writel (IPI_IRQ -CPU_IRQ_BASE , cpu_data[cpu].hpa); +gsc_writel (IPI_IRQ -CPU_IRQ_BASE , p->hpa);spin_unlock_irqrestore (lock, flags); }
@@ -239,10 +240,7 @@ send_IPI_mask(cpumask_t mask, enum ipi_message_type op)static inline void send_IPI_single (int dest_cpu,enum ipi_message_type op) { -if (dest_cpu ==NO_PROC_ID ) { -BUG (); -return ; - } +BUG_ON (dest_cpu ==NO_PROC_ID );ipi_send (dest_cpu, op); }
@@ -324,8 +322,7 @@ smp_cpu_init(int cpunum)/* Initialise the idle task for this CPU */ atomic_inc (&init_mm.mm_count); current->active_mm = &init_mm; -if (current->mm) -BUG (); +BUG_ON (current->mm);enter_lazy_tlb (&init_mm, current);init_IRQ ();/* make sure no IRQs are enabled or pending */
@@ -360,6 +357,7 @@ void __init smp_callin(void)*/ int __cpuinit smp_boot_one_cpu (int cpuid) { +const struct cpuinfo_parisc *p = &per_cpu (cpu_data, cpuid);struct task_struct *idle;long timeout;
@@ -391,7 +389,7 @@ int __cpuinit smp_boot_one_cpu(int cpuid) smp_init_current_idle_task = idle ;mb (); -printk ("Releasing cpu %d now, hpa=%lx\n" , cpuid, cpu_data[cpuid].hpa); +printk (KERN_INFO "Releasing cpu %d now, hpa=%lx\n" , cpuid, p->hpa);/* ** This gets PDC to release the CPU from a very tight loop.
@@ -402,7 +400,7 @@ int __cpuinit smp_boot_one_cpu(int cpuid)** EIR{0}). MEM_RENDEZ is valid only when it is nonzero and the ** contents of memory are valid." */ -gsc_writel (TIMER_IRQ -CPU_IRQ_BASE , cpu_data[cpuid].hpa); +gsc_writel (TIMER_IRQ -CPU_IRQ_BASE , p->hpa);mb ();/*
@@ -434,12 +432,12 @@ alive:return 0 ; } -void __devinit smp_prepare_boot_cpu (void ) +void __init smp_prepare_boot_cpu (void ) { -int bootstrap_processor=cpu_data[0 ].cpuid;/* CPU ID of BSP */ +int bootstrap_processor =per_cpu (cpu_data,0 ).cpuid;/* Setup BSP mappings */ -printk ("SMP: bootstrap CPU ID is %d\n" ,bootstrap_processor); +printk (KERN_INFO "SMP: bootstrap CPU ID is %d\n" , bootstrap_processor);cpu_set (bootstrap_processor, cpu_online_map);cpu_set (bootstrap_processor, cpu_present_map);
arch/parisc/kernel/time.c +2 -2
@@ -59,7 +59,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id)unsigned long cycles_elapsed, ticks_elapsed;unsigned long cycles_remainder;unsigned int cpu =smp_processor_id (); -struct cpuinfo_parisc *cpuinfo = &cpu_data[cpu]; +struct cpuinfo_parisc *cpuinfo = &per_cpu (cpu_data, cpu);/* gcc can optimize for "read-only" case with a local clocktick */ unsigned long cpt = clocktick;
@@ -212,7 +212,7 @@ void __init start_cpu_itimer(void)mtctl (next_tick,16 );/* kick off Interval Timer (CR16) */ - cpu_data[cpu].it_value = next_tick; +per_cpu (cpu_data, cpu).it_value = next_tick; }void __init time_init (void )
arch/parisc/kernel/topology.c +2 -2
@@ -22,14 +22,14 @@#include <linux/cpu.h> #include <linux/cache.h> -static struct cpu cpu_devices[NR_CPUS ]__read_mostly ; +static DEFINE_PER_CPU(struct cpu, cpu_devices);static int __init topology_init (void ) {int num;for_each_present_cpu (num) { -register_cpu (&cpu_devices[num], num); +register_cpu (&per_cpu (cpu_devices, num), num); }return 0 ; }
Re: [PATCH] Change cpu_data[] and cpu_devices[] from array sized by NR_CPUS to per_cpu variables
Quoted 3 lines · Helge Deller
Updated patch attached, which fixes some build problems and section mismatches.
Boot-tested on a UP 32bit machine withCONFIG_SMP=y.
Fixed this build failure (64-bit):
CC arch/parisc/kernel/perf.oarch/parisc/kernel/perf.c: In function 'perf_init':arch/parisc/kernel/perf.c:544: error: 'cpu_data' undeclared (first use in this function) arch/parisc/kernel/perf.c:544: error: (Each undeclared identifier is reported only once arch/parisc/kernel/perf.c:544: error: for each function it appears in.) make[1]: *** [arch/parisc/kernel/perf.o] Error 1
arch/parisc/kernel/perf.c +3 -2
@@ -55,6 +55,7 @@#include <asm/processor.h> #include <asm/runway.h> #include <asm/io.h> /* for __raw_read() */ +#include <asm/percpu.h> #include "perf_images.h"
@@ -541,9 +542,9 @@ static int __init perf_init(void)spin_lock_init (&perf_lock);/* TODO: this only lets us access the first cpu.. what to do for SMP? */ - cpu_device = cpu_data[0 ].dev; + cpu_device =per_cpu (cpu_data,0 ).dev;printk ("Performance monitoring counters enabled for %s\n" , - cpu_data[0 ].dev->name); + cpu_device->name);return 0 ; }
Re: [PATCH] Change cpu_data[] and cpu_devices[] from array sized by NR_CPUS to per_cpu variables
Quoted 12 lines · Grant Grundler
Quoted 2 lines · Helge Deller
Updated patch attached, which fixes some build problems and section mismatches. Boot-tested on a UP 32bit machine with
CONFIG_SMP=y.Fixed this build failure (64-bit):
CCarch/parisc/kernel/perf.oarch/parisc/kernel/perf.c: In function 'perf_init':arch/parisc/kernel/perf.c:544: error: 'cpu_data' undeclared (first use in this function)arch/parisc/kernel/perf.c:544: error: (Each undeclared identifier is reported only oncearch/parisc/kernel/perf.c:544: error: for each function it appears in.) make[1]: *** [arch/parisc/kernel/perf.o] Error 1
Quoted 1 line
Signed-off-by Grant Grundler <[email protected]>
Thanks!
Quoted 24 lines
arch/parisc/kernel/perf.c +3
-2@@ -55,6 +55,7 @@#include <asm/processor.h> #include <asm/runway.h> #include <asm/io.h> /* for __raw_read() */ +#include <asm/percpu.h> #include "perf_images.h" @@ -541,9 +542,9 @@ static int __init perf_init(void)spin_lock_init (&perf_lock);/* TODO: this only lets us access the first cpu.. what to do for SMP? */ - cpu_device = cpu_data[0 ].dev; + cpu_device =per_cpu (cpu_data,0 ).dev;printk ("Performance monitoring counters enabled for %s\n" , - cpu_data[0 ].dev->name); + cpu_device->name);return 0 ; }
Helge Deller
maintainerQuoted 2 lines · Helge Deller
The following mails contain patches which I have sent to linux-parisc during the last weeks and which have not yet been applied.
Kyle, in addition to my patches it would be nice if you could apply a final LWS documentation patch on which Carlos and John still want to agree on.
For reference here is the thread:
http://marc.info/?t=121612540800004&r=1&w=2
Helge