Message ID | 20181108220356.GA16610@ls3530.dellerweb.de (mailing list archive) |
---|---|
State | Rejected, archived |
Headers | show |
Series | parisc: Improve alternative live patching | expand |
On 2018-11-08 5:03 p.m., Helge Deller wrote: > static inline int arch_spin_is_locked(arch_spinlock_t *x) > { > - volatile unsigned int *a = __ldcw_align(x); > + volatile unsigned int *a; > + > + if (asm_online_cpus() == 1) > + return 1; I think the return value should be 0 (unlocked) when asm_online_cpus() == 1. Dave
On 09.11.2018 01:11, John David Anglin wrote: > On 2018-11-08 5:03 p.m., Helge Deller wrote: >> static inline int arch_spin_is_locked(arch_spinlock_t *x) >> { >> - volatile unsigned int *a = __ldcw_align(x); >> + volatile unsigned int *a; >> + >> + if (asm_online_cpus() == 1) >> + return 1; > I think the return value should be 0 (unlocked) when asm_online_cpus() == 1. In that case, booting with 4 CPUs is working then, but when booting with only one CPU you get: [ 0.000000] Linux version 4.20.0-rc1-32bit+ (deller@ls3530) (gcc version 7.2.1 20170915 (Red Hat Cross 7.2.1-1) (GCC)) #943 SMP Fri Nov 9 08:08:13 CET 2018 [ 0.000000] CPU0: thread -1, cpu 0, socket 0 [ 0.000000] FP[0] enabled: Rev 1 Model 19 [ 0.000000] The 32-bit Kernel has started... [ 0.000000] Kernel default page size is 4 KB. Huge pages disabled. [ 0.000000] printk: bootconsole [ttyB0] enabled [ 0.000000] Initialized PDC Console for debugging. [ 0.000000] Determining PDC firmware type: System Map. [ 0.000000] model 00005020 00000481 00000000 02020202 7794d7fe 100000f0 00000004 000000ba 000000ba [ 0.000000] vers 00000008 [ 0.000000] CPUID vers 15 rev 8 (0x000001e8) [ 0.000000] capabilities 0x2 [ 0.000000] model 9000/778/B160L [ 0.000000] Memory Ranges: [ 0.000000] 0) Start 0x0000000000000000 End 0x000000001fffffff Size 512 MB [ 0.000000] Total Memory: 512 MB [ 0.000000] PDT: Firmware does not provide any page deallocation information. [ 0.000000] percpu: Embedded 22 pages/cpu @(ptrval) s61328 r8192 d20592 u90112 [ 0.000000] SMP: bootstrap CPU ID is 0 [ 0.000000] Built 1 zonelists, mobility grouping on. Total pages: 129920 [ 0.000000] Kernel command line: console=ttyS0 root=/dev/sda5 cryptomgr.notests [ 0.000000] Dentry cache hash table entries: 65536 (order: 6, 262144 bytes) [ 0.000000] Inode-cache hash table entries: 32768 (order: 5, 131072 bytes) [ 0.000000] Memory: 507412K/524288K available (7140K kernel code, 1036K rwdata, 1651K rodata, 780K init, 376K bss, 16876K reserved, 0K cma-reserved) [ 0.000000] rcu: Hierarchical RCU implementation. [ 0.000000] rcu: RCU calculated value of scheduler-enlistment delay is 10 jiffies. [ 0.000000] NR_IRQS: 96 [ 0.000298] sched_clock: 32 bits at 250MHz, resolution 4ns, wraps every 8589934590ns [ 0.007222] Console: colour dummy device 128x48 [ 0.008833] Calibrating delay loop... 1661.33 BogoMIPS (lpj=8306688) [ 0.232493] pid_max: default: 32768 minimum: 301 [ 0.236972] Mount-cache hash table entries: 1024 (order: 0, 4096 bytes) [ 0.237480] Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes) [ 0.285070] rcu: Hierarchical SRCU implementation. [ 0.292563] smp: Bringing up secondary CPUs ... [ 0.293128] smp: Brought up 1 node, 1 CPU [ 0.306444] devtmpfs: initialized [ 0.320533] random: get_random_u32 called from bucket_table_alloc+0x1ac/0x1d4 with crng_init=0 [ 0.326747] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns [ 0.328413] futex hash table entries: 1024 (order: 3, 49152 bytes) [ 0.341270] NET: Registered protocol family 16 [ 0.352413] EISA bus registered [ 0.354398] Searching for devices... [ 0.364975] Found devices: [ 0.366163] 1. Phantom PseudoBC GSC+ Port at 0xffc00000 [8] { 7, 0x0, 0x504, 0x00000 } [ 0.367071] 2. Dino PCI Bridge at 0xfff80000 [8/0] { 13, 0x3, 0x680, 0x0000a } [ 0.367621] 3. Merlin+ 132 Dino RS-232 at 0xfff83000 [8/0/63] { 10, 0x0, 0x022, 0x0008c } [ 0.368216] 4. Merlin L2 160 (9000/778/B160L) at 0xfff10000 [62] { 0, 0x0, 0x502, 0x00004 } [ 0.368799] 5. Memory at 0xfffbf000 [63] { 1, 0x0, 0x067, 0x00009 } [ 0.371441] CPU(s): 1 out of 1 PA7300LC (PCX-L2) at 250.000000 MHz online [ 0.378172] alternatives: applied 10030 out of 10030 patches [ 0.378648] BUG: spinlock already unlocked on CPU#0, swapper/0/1 [ 0.378648] lock: logbuf_lock+0x0/0x1c, .magic: dead4ead, .owner: swapper/0/1, .owner_cpu: 0 [ 0.378648] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.20.0-rc1-32bit+ #943 [ 0.378648] Hardware name: 9000/778/B160L [ 0.378648] Backtrace: [ 0.378648] [<101c728c>] show_stack+0x48/0x5c [ 0.378648] [<1089a3e0>] dump_stack+0x80/0x134 [ 0.378648] [<1024f734>] spin_bug+0xc4/0xec [ 0.378648] [<1024f9e4>] do_raw_spin_unlock+0x7c/0xfc [ 0.378648] [<108b9ed0>] _raw_spin_unlock+0x38/0x4c [ 0.378648] [<10255de4>] vprintk_emit+0xe8/0x234 [ 0.378648] [<10256110>] vprintk_default+0x54/0x6c [ 0.378648] [<10256f74>] vprintk_func+0x148/0x158 [ 0.378648] [<102566f8>] printk+0x54/0x6c [ 0.378648] [<101d4354>] apply_alternatives+0xc4/0x1c4 [ 0.378648] [<10107ca8>] 0x10107ca8 [ 0.378648] [<10105e24>] 0x10105e24 [ 0.378648] [<101c39a8>] do_one_initcall+0xd0/0x1dc [ 0.378648] [<101017b0>] 0x101017b0 [ 0.378648] [<108b2320>] kernel_init+0x34/0x158 [ 0.378648] [<101cc01c>] ret_from_kernel_thread+0x1c/0x24 [ 0.378648] [ 0.379288] Whole cache flush 12773 cycles, flushing 10448896 bytes 4675 cycles [ 0.379735] Cache flush threshold set to 512 KiB [ 0.393941] Whole TLB flush 10612 cycles, Range flush 10448896 bytes 1450591 cycles [ 0.394391] Calculated TLB flush threshold 4 KiB [ 0.394677] TLB flush threshold set to 16 KiB [ 0.397494] Dino version 3.1 found at 0xfff80000 [ 0.401648] ------------[ cut here ]------------ [ 0.401948] kernel BUG at /home/cvs/LINUX/git-kernel/linux-2.6/mm/slab.c:2910! [ 0.402565] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.20.0-rc1-32bit+ #943 [ 0.402903] Hardware name: 9000/778/B160L [ 0.403262] [ 0.403489] YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI [ 0.404065] PSW: 00000000000001001011111100001110 Not tainted [ 0.404668] r00-03 0004bf0e 10b1d670 10369034 2f4bc900 [ 0.404979] r04-07 2f401190 00000000 2f4001c0 2fb391a8 [ 0.405238] r08-11 101a01a8 0000003c 1f999000 00000200 [ 0.405495] r12-15 10ac7064 006080c0 2f4011ac 2f4011b4 [ 0.405942] r16-19 007fffff 00000200 00000020 00000000 [ 0.406450] r20-23 00000001 10b162a4 00000000 00000000 [ 0.407061] r24-27 2f4bc900 10368ffc 102af2d0 10ac6670 [ 0.407777] r28-31 2f40119f 000affff 2f4bc940 105a27f0 [ 0.408534] sr00-03 00000000 00000000 00000000 00000000 [ 0.409727] sr04-07 00000000 00000000 00000000 00000000 [ 0.410404] [ 0.410737] IASQ: 00000000 00000000 IAOQ: 10369050 10369054 [ 0.411122] IIR: 03ffe01f ISR: 00000000 IOR: 10369000 [ 0.411419] CPU: 0 CR30: 2f4bc000 CR31: 00000000 [ 0.411700] ORIG_R28: 00000000 [ 0.411962] IAOQ[0]: get_first_slab+0x54/0xd8 [ 0.412219] IAOQ[1]: get_first_slab+0x58/0xd8 [ 0.412467] RP(r2): get_first_slab+0x38/0xd8 [ 0.412720] Backtrace: [ 0.412908] [<1036a254>] cache_alloc_refill+0x278/0x474 [ 0.413186] [<1036b570>] __kmalloc+0x210/0x22c [ 0.413445] [<101f5580>] resource_list_create_entry+0x48/0x7c [ 0.413770] [<1057f2b4>] pci_add_resource_offset+0x48/0x98 [ 0.414083] [<10133058>] 0x10133058 [ 0.414306] [<101d3348>] parisc_driver_probe+0x48/0x6c [ 0.414603] [<10622734>] really_probe+0x2a8/0x3c8 [ 0.414877] [<10622ec4>] driver_probe_device+0x4dc/0x4e4 [ 0.415157] [<10622f84>] __driver_attach+0xb8/0x110 [ 0.415426] [<1061fe48>] bus_for_each_dev+0xa0/0xd8 [ 0.415771] [<10621e10>] driver_attach+0x48/0x5c [ 0.416086] [<106216f4>] bus_add_driver+0x1c0/0x20c [ 0.416429] [<10623ac0>] driver_register+0xec/0x12c [ 0.416761] [<101d3520>] register_parisc_driver+0xac/0xb4 [ 0.417115] [<10133478>] 0x10133478 [ 0.417362] [<10105e64>] 0x10105e64 [ 0.417633] [<101c39a8>] do_one_initcall+0xd0/0x1dc [ 0.417960] [<101017b0>] 0x101017b0 [ 0.418238] [<108b2320>] kernel_init+0x34/0x158 [ 0.418785] [<101cc01c>] ret_from_kernel_thread+0x1c/0x24 [ 0.419181] [ 0.419490] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.20.0-rc1-32bit+ #943 [ 0.420044] Hardware name: 9000/778/B160L [ 0.420337] Backtrace: [ 0.420519] [<101c728c>] show_stack+0x48/0x5c [ 0.420789] [<1089a3e0>] dump_stack+0x80/0x134 [ 0.421048] [<101c7468>] die_if_kernel+0x18c/0x1e8 [ 0.421330] [<101c7984>] handle_interruption+0x2ec/0x730 [ 0.421710] [<10369050>] get_first_slab+0x54/0xd8 [ 0.421990] [<1036a254>] cache_alloc_refill+0x278/0x474 [ 0.422432] [<1036b570>] __kmalloc+0x210/0x22c [ 0.422797] [<101f5580>] resource_list_create_entry+0x48/0x7c [ 0.423267] [<1057f2b4>] pci_add_resource_offset+0x48/0x98 [ 0.423724] [<10133058>] 0x10133058 [ 0.424023] [<101d3348>] parisc_driver_probe+0x48/0x6c [ 0.424474] [<10622734>] really_probe+0x2a8/0x3c8 [ 0.424863] [<10622ec4>] driver_probe_device+0x4dc/0x4e4 [ 0.425303] [<10622f84>] __driver_attach+0xb8/0x110 [ 0.425716] [<1061fe48>] bus_for_each_dev+0xa0/0xd8 [ 0.426155] [<10621e10>] driver_attach+0x48/0x5c [ 0.426553] [<106216f4>] bus_add_driver+0x1c0/0x20c [ 0.426978] [<10623ac0>] driver_register+0xec/0x12c [ 0.427428] [<101d3520>] register_parisc_driver+0xac/0xb4 [ 0.427843] [<10133478>] 0x10133478 [ 0.428148] [<10105e64>] 0x10105e64 [ 0.428509] [<101c39a8>] do_one_initcall+0xd0/0x1dc [ 0.428648] [<101017b0>] 0x101017b0 [ 0.428648] [<108b2320>] kernel_init+0x34/0x158 [ 0.428648] [<101cc01c>] ret_from_kernel_thread+0x1c/0x24 [ 0.428648] [ 0.429129] ---[ end trace 1a6ae02625c0f6ff ]--- [ 0.431183] Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b [ 0.432304] ---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b ]---
On 09.11.2018 08:25, Helge Deller wrote: > On 09.11.2018 01:11, John David Anglin wrote: >> On 2018-11-08 5:03 p.m., Helge Deller wrote: >>> static inline int arch_spin_is_locked(arch_spinlock_t *x) >>> { >>> - volatile unsigned int *a = __ldcw_align(x); >>> + volatile unsigned int *a; >>> + >>> + if (asm_online_cpus() == 1) >>> + return 1; > >> I think the return value should be 0 (unlocked) when asm_online_cpus() == 1. > > In that case, booting with 4 CPUs is working then, but when booting with only one CPU you get: I think it's a inconsistency in Linux code. [deller@ls3530 linux-2.6]$ grep -r assert_raw_spin_locked include/linux/spinlock.h:#define assert_spin_locked(lock) assert_raw_spin_locked(&(lock)->rlock) include/linux/spinlock_api_up.h:#define assert_raw_spin_locked(lock) do { (void)(lock); } while (0) include/linux/spinlock_api_smp.h:#define assert_raw_spin_locked(x) BUG_ON(!raw_spin_is_locked(x)) For UP, it's assumed the lock is held anyway, and assert_raw_spin_locked() is a NOP. For SMP, raw_spin_is_locked() is always called and checked. So, for our live patching we probably need to simulate that the lock is locked for asm_online_cpus() == 1 and thus we need to return 1 in arch_spin_is_locked(). Helge > [ 0.000000] Linux version 4.20.0-rc1-32bit+ (deller@ls3530) (gcc version 7.2.1 20170915 (Red Hat Cross 7.2.1-1) (GCC)) #943 SMP Fri Nov 9 08:08:13 CET 2018 > [ 0.000000] CPU0: thread -1, cpu 0, socket 0 > [ 0.000000] FP[0] enabled: Rev 1 Model 19 > [ 0.000000] The 32-bit Kernel has started... > [ 0.000000] Kernel default page size is 4 KB. Huge pages disabled. > [ 0.000000] printk: bootconsole [ttyB0] enabled > [ 0.000000] Initialized PDC Console for debugging. > [ 0.000000] Determining PDC firmware type: System Map. > [ 0.000000] model 00005020 00000481 00000000 02020202 7794d7fe 100000f0 00000004 000000ba 000000ba > [ 0.000000] vers 00000008 > [ 0.000000] CPUID vers 15 rev 8 (0x000001e8) > [ 0.000000] capabilities 0x2 > [ 0.000000] model 9000/778/B160L > [ 0.000000] Memory Ranges: > [ 0.000000] 0) Start 0x0000000000000000 End 0x000000001fffffff Size 512 MB > [ 0.000000] Total Memory: 512 MB > [ 0.000000] PDT: Firmware does not provide any page deallocation information. > [ 0.000000] percpu: Embedded 22 pages/cpu @(ptrval) s61328 r8192 d20592 u90112 > [ 0.000000] SMP: bootstrap CPU ID is 0 > [ 0.000000] Built 1 zonelists, mobility grouping on. Total pages: 129920 > [ 0.000000] Kernel command line: console=ttyS0 root=/dev/sda5 cryptomgr.notests > [ 0.000000] Dentry cache hash table entries: 65536 (order: 6, 262144 bytes) > [ 0.000000] Inode-cache hash table entries: 32768 (order: 5, 131072 bytes) > [ 0.000000] Memory: 507412K/524288K available (7140K kernel code, 1036K rwdata, 1651K rodata, 780K init, 376K bss, 16876K reserved, 0K cma-reserved) > [ 0.000000] rcu: Hierarchical RCU implementation. > [ 0.000000] rcu: RCU calculated value of scheduler-enlistment delay is 10 jiffies. > [ 0.000000] NR_IRQS: 96 > [ 0.000298] sched_clock: 32 bits at 250MHz, resolution 4ns, wraps every 8589934590ns > [ 0.007222] Console: colour dummy device 128x48 > [ 0.008833] Calibrating delay loop... 1661.33 BogoMIPS (lpj=8306688) > [ 0.232493] pid_max: default: 32768 minimum: 301 > [ 0.236972] Mount-cache hash table entries: 1024 (order: 0, 4096 bytes) > [ 0.237480] Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes) > [ 0.285070] rcu: Hierarchical SRCU implementation. > [ 0.292563] smp: Bringing up secondary CPUs ... > [ 0.293128] smp: Brought up 1 node, 1 CPU > [ 0.306444] devtmpfs: initialized > [ 0.320533] random: get_random_u32 called from bucket_table_alloc+0x1ac/0x1d4 with crng_init=0 > [ 0.326747] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns > [ 0.328413] futex hash table entries: 1024 (order: 3, 49152 bytes) > [ 0.341270] NET: Registered protocol family 16 > [ 0.352413] EISA bus registered > [ 0.354398] Searching for devices... > [ 0.364975] Found devices: > [ 0.366163] 1. Phantom PseudoBC GSC+ Port at 0xffc00000 [8] { 7, 0x0, 0x504, 0x00000 } > [ 0.367071] 2. Dino PCI Bridge at 0xfff80000 [8/0] { 13, 0x3, 0x680, 0x0000a } > [ 0.367621] 3. Merlin+ 132 Dino RS-232 at 0xfff83000 [8/0/63] { 10, 0x0, 0x022, 0x0008c } > [ 0.368216] 4. Merlin L2 160 (9000/778/B160L) at 0xfff10000 [62] { 0, 0x0, 0x502, 0x00004 } > [ 0.368799] 5. Memory at 0xfffbf000 [63] { 1, 0x0, 0x067, 0x00009 } > [ 0.371441] CPU(s): 1 out of 1 PA7300LC (PCX-L2) at 250.000000 MHz online > [ 0.378172] alternatives: applied 10030 out of 10030 patches > [ 0.378648] BUG: spinlock already unlocked on CPU#0, swapper/0/1 > [ 0.378648] lock: logbuf_lock+0x0/0x1c, .magic: dead4ead, .owner: swapper/0/1, .owner_cpu: 0 > [ 0.378648] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.20.0-rc1-32bit+ #943 > [ 0.378648] Hardware name: 9000/778/B160L > [ 0.378648] Backtrace: > [ 0.378648] [<101c728c>] show_stack+0x48/0x5c > [ 0.378648] [<1089a3e0>] dump_stack+0x80/0x134 > [ 0.378648] [<1024f734>] spin_bug+0xc4/0xec > [ 0.378648] [<1024f9e4>] do_raw_spin_unlock+0x7c/0xfc > [ 0.378648] [<108b9ed0>] _raw_spin_unlock+0x38/0x4c > [ 0.378648] [<10255de4>] vprintk_emit+0xe8/0x234 > [ 0.378648] [<10256110>] vprintk_default+0x54/0x6c > [ 0.378648] [<10256f74>] vprintk_func+0x148/0x158 > [ 0.378648] [<102566f8>] printk+0x54/0x6c > [ 0.378648] [<101d4354>] apply_alternatives+0xc4/0x1c4 > [ 0.378648] [<10107ca8>] 0x10107ca8 > [ 0.378648] [<10105e24>] 0x10105e24 > [ 0.378648] [<101c39a8>] do_one_initcall+0xd0/0x1dc > [ 0.378648] [<101017b0>] 0x101017b0 > [ 0.378648] [<108b2320>] kernel_init+0x34/0x158 > [ 0.378648] [<101cc01c>] ret_from_kernel_thread+0x1c/0x24 > [ 0.378648] > [ 0.379288] Whole cache flush 12773 cycles, flushing 10448896 bytes 4675 cycles > [ 0.379735] Cache flush threshold set to 512 KiB > [ 0.393941] Whole TLB flush 10612 cycles, Range flush 10448896 bytes 1450591 cycles > [ 0.394391] Calculated TLB flush threshold 4 KiB > [ 0.394677] TLB flush threshold set to 16 KiB > [ 0.397494] Dino version 3.1 found at 0xfff80000 > [ 0.401648] ------------[ cut here ]------------ > [ 0.401948] kernel BUG at /home/cvs/LINUX/git-kernel/linux-2.6/mm/slab.c:2910! > [ 0.402565] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.20.0-rc1-32bit+ #943 > [ 0.402903] Hardware name: 9000/778/B160L > [ 0.403262] > [ 0.403489] YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI > [ 0.404065] PSW: 00000000000001001011111100001110 Not tainted > [ 0.404668] r00-03 0004bf0e 10b1d670 10369034 2f4bc900 > [ 0.404979] r04-07 2f401190 00000000 2f4001c0 2fb391a8 > [ 0.405238] r08-11 101a01a8 0000003c 1f999000 00000200 > [ 0.405495] r12-15 10ac7064 006080c0 2f4011ac 2f4011b4 > [ 0.405942] r16-19 007fffff 00000200 00000020 00000000 > [ 0.406450] r20-23 00000001 10b162a4 00000000 00000000 > [ 0.407061] r24-27 2f4bc900 10368ffc 102af2d0 10ac6670 > [ 0.407777] r28-31 2f40119f 000affff 2f4bc940 105a27f0 > [ 0.408534] sr00-03 00000000 00000000 00000000 00000000 > [ 0.409727] sr04-07 00000000 00000000 00000000 00000000 > [ 0.410404] > [ 0.410737] IASQ: 00000000 00000000 IAOQ: 10369050 10369054 > [ 0.411122] IIR: 03ffe01f ISR: 00000000 IOR: 10369000 > [ 0.411419] CPU: 0 CR30: 2f4bc000 CR31: 00000000 > [ 0.411700] ORIG_R28: 00000000 > [ 0.411962] IAOQ[0]: get_first_slab+0x54/0xd8 > [ 0.412219] IAOQ[1]: get_first_slab+0x58/0xd8 > [ 0.412467] RP(r2): get_first_slab+0x38/0xd8 > [ 0.412720] Backtrace: > [ 0.412908] [<1036a254>] cache_alloc_refill+0x278/0x474 > [ 0.413186] [<1036b570>] __kmalloc+0x210/0x22c > [ 0.413445] [<101f5580>] resource_list_create_entry+0x48/0x7c > [ 0.413770] [<1057f2b4>] pci_add_resource_offset+0x48/0x98 > [ 0.414083] [<10133058>] 0x10133058 > [ 0.414306] [<101d3348>] parisc_driver_probe+0x48/0x6c > [ 0.414603] [<10622734>] really_probe+0x2a8/0x3c8 > [ 0.414877] [<10622ec4>] driver_probe_device+0x4dc/0x4e4 > [ 0.415157] [<10622f84>] __driver_attach+0xb8/0x110 > [ 0.415426] [<1061fe48>] bus_for_each_dev+0xa0/0xd8 > [ 0.415771] [<10621e10>] driver_attach+0x48/0x5c > [ 0.416086] [<106216f4>] bus_add_driver+0x1c0/0x20c > [ 0.416429] [<10623ac0>] driver_register+0xec/0x12c > [ 0.416761] [<101d3520>] register_parisc_driver+0xac/0xb4 > [ 0.417115] [<10133478>] 0x10133478 > [ 0.417362] [<10105e64>] 0x10105e64 > [ 0.417633] [<101c39a8>] do_one_initcall+0xd0/0x1dc > [ 0.417960] [<101017b0>] 0x101017b0 > [ 0.418238] [<108b2320>] kernel_init+0x34/0x158 > [ 0.418785] [<101cc01c>] ret_from_kernel_thread+0x1c/0x24 > [ 0.419181] > [ 0.419490] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.20.0-rc1-32bit+ #943 > [ 0.420044] Hardware name: 9000/778/B160L > [ 0.420337] Backtrace: > [ 0.420519] [<101c728c>] show_stack+0x48/0x5c > [ 0.420789] [<1089a3e0>] dump_stack+0x80/0x134 > [ 0.421048] [<101c7468>] die_if_kernel+0x18c/0x1e8 > [ 0.421330] [<101c7984>] handle_interruption+0x2ec/0x730 > [ 0.421710] [<10369050>] get_first_slab+0x54/0xd8 > [ 0.421990] [<1036a254>] cache_alloc_refill+0x278/0x474 > [ 0.422432] [<1036b570>] __kmalloc+0x210/0x22c > [ 0.422797] [<101f5580>] resource_list_create_entry+0x48/0x7c > [ 0.423267] [<1057f2b4>] pci_add_resource_offset+0x48/0x98 > [ 0.423724] [<10133058>] 0x10133058 > [ 0.424023] [<101d3348>] parisc_driver_probe+0x48/0x6c > [ 0.424474] [<10622734>] really_probe+0x2a8/0x3c8 > [ 0.424863] [<10622ec4>] driver_probe_device+0x4dc/0x4e4 > [ 0.425303] [<10622f84>] __driver_attach+0xb8/0x110 > [ 0.425716] [<1061fe48>] bus_for_each_dev+0xa0/0xd8 > [ 0.426155] [<10621e10>] driver_attach+0x48/0x5c > [ 0.426553] [<106216f4>] bus_add_driver+0x1c0/0x20c > [ 0.426978] [<10623ac0>] driver_register+0xec/0x12c > [ 0.427428] [<101d3520>] register_parisc_driver+0xac/0xb4 > [ 0.427843] [<10133478>] 0x10133478 > [ 0.428148] [<10105e64>] 0x10105e64 > [ 0.428509] [<101c39a8>] do_one_initcall+0xd0/0x1dc > [ 0.428648] [<101017b0>] 0x101017b0 > [ 0.428648] [<108b2320>] kernel_init+0x34/0x158 > [ 0.428648] [<101cc01c>] ret_from_kernel_thread+0x1c/0x24 > [ 0.428648] > [ 0.429129] ---[ end trace 1a6ae02625c0f6ff ]--- > [ 0.431183] Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b > [ 0.432304] ---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b ]--- >
On 2018-11-09 2:54 a.m., Helge Deller wrote: > On 09.11.2018 08:25, Helge Deller wrote: >> On 09.11.2018 01:11, John David Anglin wrote: >>> On 2018-11-08 5:03 p.m., Helge Deller wrote: >>>> static inline int arch_spin_is_locked(arch_spinlock_t *x) >>>> { >>>> - volatile unsigned int *a = __ldcw_align(x); >>>> + volatile unsigned int *a; >>>> + >>>> + if (asm_online_cpus() == 1) >>>> + return 1; >>> I think the return value should be 0 (unlocked) when asm_online_cpus() == 1. >> In that case, booting with 4 CPUs is working then, but when booting with only one CPU you get: > I think it's a inconsistency in Linux code. > > [deller@ls3530 linux-2.6]$ grep -r assert_raw_spin_locked > include/linux/spinlock.h:#define assert_spin_locked(lock) assert_raw_spin_locked(&(lock)->rlock) > include/linux/spinlock_api_up.h:#define assert_raw_spin_locked(lock) do { (void)(lock); } while (0) > include/linux/spinlock_api_smp.h:#define assert_raw_spin_locked(x) BUG_ON(!raw_spin_is_locked(x)) > > For UP, it's assumed the lock is held anyway, and assert_raw_spin_locked() is a NOP. > For SMP, raw_spin_is_locked() is always called and checked. > So, for our live patching we probably need to simulate that the lock is locked for asm_online_cpus() == 1 > and thus we need to return 1 in arch_spin_is_locked(). You are correct. arch_spin_is_locked() should return 1. Except for one startup situation, it is only called from debug_spin_unlock() where it is expected that the lock is held. Dave > >> [ 0.000000] Linux version 4.20.0-rc1-32bit+ (deller@ls3530) (gcc version 7.2.1 20170915 (Red Hat Cross 7.2.1-1) (GCC)) #943 SMP Fri Nov 9 08:08:13 CET 2018 >> [ 0.000000] CPU0: thread -1, cpu 0, socket 0 >> [ 0.000000] FP[0] enabled: Rev 1 Model 19 >> [ 0.000000] The 32-bit Kernel has started... >> [ 0.000000] Kernel default page size is 4 KB. Huge pages disabled. >> [ 0.000000] printk: bootconsole [ttyB0] enabled >> [ 0.000000] Initialized PDC Console for debugging. >> [ 0.000000] Determining PDC firmware type: System Map. >> [ 0.000000] model 00005020 00000481 00000000 02020202 7794d7fe 100000f0 00000004 000000ba 000000ba >> [ 0.000000] vers 00000008 >> [ 0.000000] CPUID vers 15 rev 8 (0x000001e8) >> [ 0.000000] capabilities 0x2 >> [ 0.000000] model 9000/778/B160L >> [ 0.000000] Memory Ranges: >> [ 0.000000] 0) Start 0x0000000000000000 End 0x000000001fffffff Size 512 MB >> [ 0.000000] Total Memory: 512 MB >> [ 0.000000] PDT: Firmware does not provide any page deallocation information. >> [ 0.000000] percpu: Embedded 22 pages/cpu @(ptrval) s61328 r8192 d20592 u90112 >> [ 0.000000] SMP: bootstrap CPU ID is 0 >> [ 0.000000] Built 1 zonelists, mobility grouping on. Total pages: 129920 >> [ 0.000000] Kernel command line: console=ttyS0 root=/dev/sda5 cryptomgr.notests >> [ 0.000000] Dentry cache hash table entries: 65536 (order: 6, 262144 bytes) >> [ 0.000000] Inode-cache hash table entries: 32768 (order: 5, 131072 bytes) >> [ 0.000000] Memory: 507412K/524288K available (7140K kernel code, 1036K rwdata, 1651K rodata, 780K init, 376K bss, 16876K reserved, 0K cma-reserved) >> [ 0.000000] rcu: Hierarchical RCU implementation. >> [ 0.000000] rcu: RCU calculated value of scheduler-enlistment delay is 10 jiffies. >> [ 0.000000] NR_IRQS: 96 >> [ 0.000298] sched_clock: 32 bits at 250MHz, resolution 4ns, wraps every 8589934590ns >> [ 0.007222] Console: colour dummy device 128x48 >> [ 0.008833] Calibrating delay loop... 1661.33 BogoMIPS (lpj=8306688) >> [ 0.232493] pid_max: default: 32768 minimum: 301 >> [ 0.236972] Mount-cache hash table entries: 1024 (order: 0, 4096 bytes) >> [ 0.237480] Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes) >> [ 0.285070] rcu: Hierarchical SRCU implementation. >> [ 0.292563] smp: Bringing up secondary CPUs ... >> [ 0.293128] smp: Brought up 1 node, 1 CPU >> [ 0.306444] devtmpfs: initialized >> [ 0.320533] random: get_random_u32 called from bucket_table_alloc+0x1ac/0x1d4 with crng_init=0 >> [ 0.326747] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns >> [ 0.328413] futex hash table entries: 1024 (order: 3, 49152 bytes) >> [ 0.341270] NET: Registered protocol family 16 >> [ 0.352413] EISA bus registered >> [ 0.354398] Searching for devices... >> [ 0.364975] Found devices: >> [ 0.366163] 1. Phantom PseudoBC GSC+ Port at 0xffc00000 [8] { 7, 0x0, 0x504, 0x00000 } >> [ 0.367071] 2. Dino PCI Bridge at 0xfff80000 [8/0] { 13, 0x3, 0x680, 0x0000a } >> [ 0.367621] 3. Merlin+ 132 Dino RS-232 at 0xfff83000 [8/0/63] { 10, 0x0, 0x022, 0x0008c } >> [ 0.368216] 4. Merlin L2 160 (9000/778/B160L) at 0xfff10000 [62] { 0, 0x0, 0x502, 0x00004 } >> [ 0.368799] 5. Memory at 0xfffbf000 [63] { 1, 0x0, 0x067, 0x00009 } >> [ 0.371441] CPU(s): 1 out of 1 PA7300LC (PCX-L2) at 250.000000 MHz online >> [ 0.378172] alternatives: applied 10030 out of 10030 patches >> [ 0.378648] BUG: spinlock already unlocked on CPU#0, swapper/0/1 >> [ 0.378648] lock: logbuf_lock+0x0/0x1c, .magic: dead4ead, .owner: swapper/0/1, .owner_cpu: 0 >> [ 0.378648] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.20.0-rc1-32bit+ #943 >> [ 0.378648] Hardware name: 9000/778/B160L >> [ 0.378648] Backtrace: >> [ 0.378648] [<101c728c>] show_stack+0x48/0x5c >> [ 0.378648] [<1089a3e0>] dump_stack+0x80/0x134 >> [ 0.378648] [<1024f734>] spin_bug+0xc4/0xec >> [ 0.378648] [<1024f9e4>] do_raw_spin_unlock+0x7c/0xfc >> [ 0.378648] [<108b9ed0>] _raw_spin_unlock+0x38/0x4c >> [ 0.378648] [<10255de4>] vprintk_emit+0xe8/0x234 >> [ 0.378648] [<10256110>] vprintk_default+0x54/0x6c >> [ 0.378648] [<10256f74>] vprintk_func+0x148/0x158 >> [ 0.378648] [<102566f8>] printk+0x54/0x6c >> [ 0.378648] [<101d4354>] apply_alternatives+0xc4/0x1c4 >> [ 0.378648] [<10107ca8>] 0x10107ca8 >> [ 0.378648] [<10105e24>] 0x10105e24 >> [ 0.378648] [<101c39a8>] do_one_initcall+0xd0/0x1dc >> [ 0.378648] [<101017b0>] 0x101017b0 >> [ 0.378648] [<108b2320>] kernel_init+0x34/0x158 >> [ 0.378648] [<101cc01c>] ret_from_kernel_thread+0x1c/0x24 >> [ 0.378648] >> [ 0.379288] Whole cache flush 12773 cycles, flushing 10448896 bytes 4675 cycles >> [ 0.379735] Cache flush threshold set to 512 KiB >> [ 0.393941] Whole TLB flush 10612 cycles, Range flush 10448896 bytes 1450591 cycles >> [ 0.394391] Calculated TLB flush threshold 4 KiB >> [ 0.394677] TLB flush threshold set to 16 KiB >> [ 0.397494] Dino version 3.1 found at 0xfff80000 >> [ 0.401648] ------------[ cut here ]------------ >> [ 0.401948] kernel BUG at /home/cvs/LINUX/git-kernel/linux-2.6/mm/slab.c:2910! >> [ 0.402565] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.20.0-rc1-32bit+ #943 >> [ 0.402903] Hardware name: 9000/778/B160L >> [ 0.403262] >> [ 0.403489] YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI >> [ 0.404065] PSW: 00000000000001001011111100001110 Not tainted >> [ 0.404668] r00-03 0004bf0e 10b1d670 10369034 2f4bc900 >> [ 0.404979] r04-07 2f401190 00000000 2f4001c0 2fb391a8 >> [ 0.405238] r08-11 101a01a8 0000003c 1f999000 00000200 >> [ 0.405495] r12-15 10ac7064 006080c0 2f4011ac 2f4011b4 >> [ 0.405942] r16-19 007fffff 00000200 00000020 00000000 >> [ 0.406450] r20-23 00000001 10b162a4 00000000 00000000 >> [ 0.407061] r24-27 2f4bc900 10368ffc 102af2d0 10ac6670 >> [ 0.407777] r28-31 2f40119f 000affff 2f4bc940 105a27f0 >> [ 0.408534] sr00-03 00000000 00000000 00000000 00000000 >> [ 0.409727] sr04-07 00000000 00000000 00000000 00000000 >> [ 0.410404] >> [ 0.410737] IASQ: 00000000 00000000 IAOQ: 10369050 10369054 >> [ 0.411122] IIR: 03ffe01f ISR: 00000000 IOR: 10369000 >> [ 0.411419] CPU: 0 CR30: 2f4bc000 CR31: 00000000 >> [ 0.411700] ORIG_R28: 00000000 >> [ 0.411962] IAOQ[0]: get_first_slab+0x54/0xd8 >> [ 0.412219] IAOQ[1]: get_first_slab+0x58/0xd8 >> [ 0.412467] RP(r2): get_first_slab+0x38/0xd8 >> [ 0.412720] Backtrace: >> [ 0.412908] [<1036a254>] cache_alloc_refill+0x278/0x474 >> [ 0.413186] [<1036b570>] __kmalloc+0x210/0x22c >> [ 0.413445] [<101f5580>] resource_list_create_entry+0x48/0x7c >> [ 0.413770] [<1057f2b4>] pci_add_resource_offset+0x48/0x98 >> [ 0.414083] [<10133058>] 0x10133058 >> [ 0.414306] [<101d3348>] parisc_driver_probe+0x48/0x6c >> [ 0.414603] [<10622734>] really_probe+0x2a8/0x3c8 >> [ 0.414877] [<10622ec4>] driver_probe_device+0x4dc/0x4e4 >> [ 0.415157] [<10622f84>] __driver_attach+0xb8/0x110 >> [ 0.415426] [<1061fe48>] bus_for_each_dev+0xa0/0xd8 >> [ 0.415771] [<10621e10>] driver_attach+0x48/0x5c >> [ 0.416086] [<106216f4>] bus_add_driver+0x1c0/0x20c >> [ 0.416429] [<10623ac0>] driver_register+0xec/0x12c >> [ 0.416761] [<101d3520>] register_parisc_driver+0xac/0xb4 >> [ 0.417115] [<10133478>] 0x10133478 >> [ 0.417362] [<10105e64>] 0x10105e64 >> [ 0.417633] [<101c39a8>] do_one_initcall+0xd0/0x1dc >> [ 0.417960] [<101017b0>] 0x101017b0 >> [ 0.418238] [<108b2320>] kernel_init+0x34/0x158 >> [ 0.418785] [<101cc01c>] ret_from_kernel_thread+0x1c/0x24 >> [ 0.419181] >> [ 0.419490] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.20.0-rc1-32bit+ #943 >> [ 0.420044] Hardware name: 9000/778/B160L >> [ 0.420337] Backtrace: >> [ 0.420519] [<101c728c>] show_stack+0x48/0x5c >> [ 0.420789] [<1089a3e0>] dump_stack+0x80/0x134 >> [ 0.421048] [<101c7468>] die_if_kernel+0x18c/0x1e8 >> [ 0.421330] [<101c7984>] handle_interruption+0x2ec/0x730 >> [ 0.421710] [<10369050>] get_first_slab+0x54/0xd8 >> [ 0.421990] [<1036a254>] cache_alloc_refill+0x278/0x474 >> [ 0.422432] [<1036b570>] __kmalloc+0x210/0x22c >> [ 0.422797] [<101f5580>] resource_list_create_entry+0x48/0x7c >> [ 0.423267] [<1057f2b4>] pci_add_resource_offset+0x48/0x98 >> [ 0.423724] [<10133058>] 0x10133058 >> [ 0.424023] [<101d3348>] parisc_driver_probe+0x48/0x6c >> [ 0.424474] [<10622734>] really_probe+0x2a8/0x3c8 >> [ 0.424863] [<10622ec4>] driver_probe_device+0x4dc/0x4e4 >> [ 0.425303] [<10622f84>] __driver_attach+0xb8/0x110 >> [ 0.425716] [<1061fe48>] bus_for_each_dev+0xa0/0xd8 >> [ 0.426155] [<10621e10>] driver_attach+0x48/0x5c >> [ 0.426553] [<106216f4>] bus_add_driver+0x1c0/0x20c >> [ 0.426978] [<10623ac0>] driver_register+0xec/0x12c >> [ 0.427428] [<101d3520>] register_parisc_driver+0xac/0xb4 >> [ 0.427843] [<10133478>] 0x10133478 >> [ 0.428148] [<10105e64>] 0x10105e64 >> [ 0.428509] [<101c39a8>] do_one_initcall+0xd0/0x1dc >> [ 0.428648] [<101017b0>] 0x101017b0 >> [ 0.428648] [<108b2320>] kernel_init+0x34/0x158 >> [ 0.428648] [<101cc01c>] ret_from_kernel_thread+0x1c/0x24 >> [ 0.428648] >> [ 0.429129] ---[ end trace 1a6ae02625c0f6ff ]--- >> [ 0.431183] Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b >> [ 0.432304] ---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b ]--- >> >
diff --git a/arch/parisc/include/asm/alternative.h b/arch/parisc/include/asm/alternative.h index bf485a94d0b4..a3630442111d 100644 --- a/arch/parisc/include/asm/alternative.h +++ b/arch/parisc/include/asm/alternative.h @@ -2,6 +2,7 @@ #ifndef __ASM_PARISC_ALTERNATIVE_H #define __ASM_PARISC_ALTERNATIVE_H +#define ALT_COND_ALWAYS 0x80 /* always replace instruction */ #define ALT_COND_NO_SMP 0x01 /* when running UP instead of SMP */ #define ALT_COND_NO_DCACHE 0x02 /* if system has no d-cache */ #define ALT_COND_NO_ICACHE 0x04 /* if system has no i-cache */ @@ -9,6 +10,7 @@ #define ALT_COND_NO_IOC_FDC 0x10 /* if I/O cache does not need flushes */ #define INSN_PxTLB 0x02 /* modify pdtlb, pitlb */ +#define INSN_LDI_CPUs 0x34000000 /* ldi val,%reg */ #define INSN_NOP 0x08000240 /* nop */ #ifndef __ASSEMBLY__ @@ -26,6 +28,9 @@ struct alt_instr { }; void set_kernel_text_rw(int enable_read_write); +void apply_alternatives_all(void); +void apply_alternatives(struct alt_instr *start, struct alt_instr *end, + const char *module_name); /* Alternative SMP implementation. */ #define ALTERNATIVE(cond, replacement) "!0:" \ diff --git a/arch/parisc/include/asm/cache.h b/arch/parisc/include/asm/cache.h index 006fb939cac8..4b6eb5a702f5 100644 --- a/arch/parisc/include/asm/cache.h +++ b/arch/parisc/include/asm/cache.h @@ -61,6 +61,15 @@ void parisc_setup_cache_timing(void); ALTERNATIVE(ALT_COND_NO_DCACHE, INSN_NOP) \ ALTERNATIVE(ALT_COND_NO_IOC_FDC, INSN_NOP) :: ) +#if CONFIG_SMP +#define asm_online_cpus() ({ unsigned long __num; \ + asm volatile("ldi 0,%0" /* 0 means yet unknown. */ \ + ALTERNATIVE(ALT_COND_ALWAYS, INSN_LDI_CPUs) \ + : "=r" (__num)); \ + __num; }) +#else +#define asm_online_cpus() (1) +#endif #endif /* ! __ASSEMBLY__ */ /* Classes of processor wrt: disabling space register hashing */ diff --git a/arch/parisc/include/asm/spinlock.h b/arch/parisc/include/asm/spinlock.h index 8a63515f03bf..e70c15ca0886 100644 --- a/arch/parisc/include/asm/spinlock.h +++ b/arch/parisc/include/asm/spinlock.h @@ -4,12 +4,18 @@ #include <asm/barrier.h> #include <asm/ldcw.h> +#include <asm/cache.h> #include <asm/processor.h> #include <asm/spinlock_types.h> static inline int arch_spin_is_locked(arch_spinlock_t *x) { - volatile unsigned int *a = __ldcw_align(x); + volatile unsigned int *a; + + if (asm_online_cpus() == 1) + return 1; + + a = __ldcw_align(x); return *a == 0; } @@ -20,6 +26,9 @@ static inline void arch_spin_lock_flags(arch_spinlock_t *x, { volatile unsigned int *a; + if (asm_online_cpus() == 1) + return; + a = __ldcw_align(x); while (__ldcw(a) == 0) while (*a == 0) @@ -36,6 +45,9 @@ static inline void arch_spin_unlock(arch_spinlock_t *x) { volatile unsigned int *a; + if (asm_online_cpus() == 1) + return; + a = __ldcw_align(x); mb(); *a = 1; @@ -46,6 +58,9 @@ static inline int arch_spin_trylock(arch_spinlock_t *x) volatile unsigned int *a; int ret; + if (asm_online_cpus() == 1) + return 1; + a = __ldcw_align(x); ret = __ldcw(a) != 0; diff --git a/arch/parisc/kernel/Makefile b/arch/parisc/kernel/Makefile index e5de34d00b1a..8e5f1ab65c68 100644 --- a/arch/parisc/kernel/Makefile +++ b/arch/parisc/kernel/Makefile @@ -7,7 +7,7 @@ extra-y := head.o vmlinux.lds obj-y := cache.o pacache.o setup.o pdt.o traps.o time.o irq.o \ pa7300lc.o syscall.o entry.o sys_parisc.o firmware.o \ - ptrace.o hardware.o inventory.o drivers.o \ + ptrace.o hardware.o inventory.o drivers.o alternative.o \ signal.o hpmc.o real2.o parisc_ksyms.o unaligned.o \ process.o processor.o pdc_cons.o pdc_chassis.o unwind.o diff --git a/arch/parisc/kernel/alternative.c b/arch/parisc/kernel/alternative.c new file mode 100644 index 000000000000..1a8383f22094 --- /dev/null +++ b/arch/parisc/kernel/alternative.c @@ -0,0 +1,106 @@ +/* + * Alternative live-patching for parisc. + * Copyright (C) 2018 Helge Deller <deller@gmx.de> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <asm/processor.h> +#include <asm/sections.h> +#include <asm/alternative.h> + +#include <linux/module.h> + +static int no_alternatives; +static int __init setup_no_alternatives(char *str) +{ + no_alternatives = 1; + return 1; +} +__setup("no-alternatives", setup_no_alternatives); + +void __init_or_module apply_alternatives(struct alt_instr *start, + struct alt_instr *end, const char *module_name) +{ + struct alt_instr *entry; + int index = 0, applied = 0; + int num_cpus = num_online_cpus(); + + for (entry = start; entry < end; entry++, index++) { + + u32 *from, len, cond, replacement; + + from = (u32 *)((ulong)&entry->orig_offset + entry->orig_offset); + len = entry->len; + cond = entry->cond; + replacement = entry->replacement; + + WARN_ON(!cond); + + if (cond != ALT_COND_ALWAYS && no_alternatives) + continue; + + pr_debug("Check %d: Cond 0x%x, Replace %02d instructions @ 0x%px with 0x%08x\n", + index, cond, len, from, replacement); + + if ((cond & ALT_COND_NO_SMP) && (num_cpus != 1)) + continue; + if ((cond & ALT_COND_NO_DCACHE) && (cache_info.dc_size != 0)) + continue; + if ((cond & ALT_COND_NO_ICACHE) && (cache_info.ic_size != 0)) + continue; + + /* + * If the PDC_MODEL capabilities has Non-coherent IO-PDIR bit + * set (bit #61, big endian), we have to flush and sync every + * time IO-PDIR is changed in Ike/Astro. + */ + if ((cond & ALT_COND_NO_IOC_FDC) && + (boot_cpu_data.pdc.capabilities & PDC_MODEL_IOPDIR_FDC)) + continue; + + /* Want to replace pdtlb by a pdtlb,l instruction? */ + if (replacement == INSN_PxTLB) { + replacement = *from; + if (boot_cpu_data.cpu_type >= pcxu) /* >= pa2.0 ? */ + replacement |= (1 << 10); /* set el bit */ + } + + /* Replace ldi num_cpus,%reg */ + if (replacement == INSN_LDI_CPUs) { + replacement = *from; + replacement &= ~(31 << 1); /* mask out old values */ + replacement |= (num_cpus << 1); + } + + /* + * Replace instruction with NOPs? + * For long distance insert a branch instruction instead. + */ + if (replacement == INSN_NOP && len > 1) + replacement = 0xe8000002 + (len-2)*8; /* "b,n .+8" */ + + pr_debug("Do %d: Cond 0x%x, Replace %02d instructions @ 0x%px with 0x%08x\n", + index, cond, len, from, replacement); + + /* Replace instruction */ + *from = replacement; + applied++; + } + + pr_info("%s%salternatives: applied %d out of %d patches\n", + module_name ? : "", module_name ? " " : "", + applied, index); +} + + +void __init apply_alternatives_all(void) +{ + set_kernel_text_rw(1); + + apply_alternatives((struct alt_instr *) &__alt_instructions, + (struct alt_instr *) &__alt_instructions_end, NULL); + + set_kernel_text_rw(0); +} + diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c index b5b3cb00f1fb..43778420614b 100644 --- a/arch/parisc/kernel/module.c +++ b/arch/parisc/kernel/module.c @@ -877,6 +877,8 @@ int module_finalize(const Elf_Ehdr *hdr, int i; unsigned long nsyms; const char *strtab = NULL; + const Elf_Shdr *s; + char *secstrings; Elf_Sym *newptr, *oldptr; Elf_Shdr *symhdr = NULL; #ifdef DEBUG @@ -948,6 +950,18 @@ int module_finalize(const Elf_Ehdr *hdr, nsyms = newptr - (Elf_Sym *)symhdr->sh_addr; DEBUGP("NEW num_symtab %lu\n", nsyms); symhdr->sh_size = nsyms * sizeof(Elf_Sym); + + /* find .altinstructions section */ + secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; + for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) { + void *aseg = (void *) s->sh_addr; + char *secname = secstrings + s->sh_name; + + if (!strcmp(".altinstructions", secname)) + /* patch .altinstructions */ + apply_alternatives(aseg, aseg + s->sh_size, me->name); + } + return 0; } diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c index cd227f1cf629..2b108ee3b217 100644 --- a/arch/parisc/kernel/setup.c +++ b/arch/parisc/kernel/setup.c @@ -305,86 +305,6 @@ static int __init parisc_init_resources(void) return 0; } -static int no_alternatives __initdata; -static int __init setup_no_alternatives(char *str) -{ - no_alternatives = 1; - return 1; -} -__setup("no-alternatives", setup_no_alternatives); - -static void __init apply_alternatives_all(void) -{ - struct alt_instr *entry; - int index = 0, applied = 0; - - - pr_info("alternatives: %spatching kernel code\n", - no_alternatives ? "NOT " : ""); - if (no_alternatives) - return; - - set_kernel_text_rw(1); - - for (entry = (struct alt_instr *) &__alt_instructions; - entry < (struct alt_instr *) &__alt_instructions_end; - entry++, index++) { - - u32 *from, len, cond, replacement; - - from = (u32 *)((ulong)&entry->orig_offset + entry->orig_offset); - len = entry->len; - cond = entry->cond; - replacement = entry->replacement; - - WARN_ON(!cond); - pr_debug("Check %d: Cond 0x%x, Replace %02d instructions @ 0x%px with 0x%08x\n", - index, cond, len, from, replacement); - - if ((cond & ALT_COND_NO_SMP) && (num_online_cpus() != 1)) - continue; - if ((cond & ALT_COND_NO_DCACHE) && (cache_info.dc_size != 0)) - continue; - if ((cond & ALT_COND_NO_ICACHE) && (cache_info.ic_size != 0)) - continue; - - /* - * If the PDC_MODEL capabilities has Non-coherent IO-PDIR bit - * set (bit #61, big endian), we have to flush and sync every - * time IO-PDIR is changed in Ike/Astro. - */ - if ((cond & ALT_COND_NO_IOC_FDC) && - (boot_cpu_data.pdc.capabilities & PDC_MODEL_IOPDIR_FDC)) - continue; - - /* Want to replace pdtlb by a pdtlb,l instruction? */ - if (replacement == INSN_PxTLB) { - replacement = *from; - if (boot_cpu_data.cpu_type >= pcxu) /* >= pa2.0 ? */ - replacement |= (1 << 10); /* set el bit */ - } - - /* - * Replace instruction with NOPs? - * For long distance insert a branch instruction instead. - */ - if (replacement == INSN_NOP && len > 1) - replacement = 0xe8000002 + (len-2)*8; /* "b,n .+8" */ - - pr_debug("Do %d: Cond 0x%x, Replace %02d instructions @ 0x%px with 0x%08x\n", - index, cond, len, from, replacement); - - /* Replace instruction */ - *from = replacement; - applied++; - } - - pr_info("alternatives: applied %d out of %d patches\n", applied, index); - - set_kernel_text_rw(0); -} - - extern void gsc_init(void); extern void processor_init(void); extern void ccio_init(void);
Move the alternative implemenation coding to alternative.c, add code to patch modules when loaded and improve internal arch spinlocks when running UP. Suggested-by: John David Anglin <dave.anglin@bell.net> Signed-off-by: Helge Deller <deller@gmx.de>