Re: [TEST] PREEMPT on PPC
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
How recent of a 2.6.x kernel does this patch require? I tried applying it to a
Gentoo ppc-development-sources kernel, both versions 2.6.3-benh2 and
2.6.4-pegasos0. I realize it could have failed due to Gentoo modifications to
those kernels, but should it apply to these versions assuming no further
modification (beyond benh patches)? (I guess I could go download the vanilla
sources to find out, hehe)
I'd like to test this feature, but only 2 hunks of the entire patch seem to be
suceeding (and those are a little fuzzy). Thanks.
Wes Morgan
On Thursday 25 March 2004 01:01 am, Benjamin Herrenschmidt wrote:
> On Thu, 2004-03-25 at 17:47, Benjamin Herrenschmidt wrote:
> > Hi !
> >
> > I've start looking into the various issues of running
> > CONFIG_PREEMPT on ppc32. I found some problems, there
> > may be more, but here's a first patch that should apply on a
> > recent 2.6.x.
> >
> > I suggest if you want to try this out that you run with the
> > various kernel debugging options enabled. Report me remaining
> > problems.
>
> And here's an updated version of that patch that doesn't break
> sleep on laptops.
>
> Ben.
>
> ===== arch/ppc/kernel/entry.S 1.44 vs edited =====
> --- 1.44/arch/ppc/kernel/entry.S Mon Feb 16 18:06:27 2004
> +++ edited/arch/ppc/kernel/entry.S Thu Mar 25 14:10:41 2004
> @@ -171,9 +171,10 @@
> bl do_show_syscall
> #endif /* SHOW_SYSCALLS */
> rlwinm r10,r1,0,0,18 /* current_thread_info() */
> + lwz r11,TI_LOCAL_FLAGS(r10)
> + rlwinm r11,r11,0,~_TIFL_FORCE_NOERROR
> + stw r11,TI_LOCAL_FLAGS(r10)
> lwz r11,TI_FLAGS(r10)
> - rlwinm r11,r11,0,~_TIF_FORCE_NOERROR
> - stw r11,TI_FLAGS(r10)
> andi. r11,r11,_TIF_SYSCALL_TRACE
> bne- syscall_dotrace
> syscall_dotrace_cont:
> @@ -196,8 +197,8 @@
> cmpl 0,r3,r11
> rlwinm r12,r1,0,0,18 /* current_thread_info() */
> blt+ 30f
> - lwz r11,TI_FLAGS(r12)
> - andi. r11,r11,_TIF_FORCE_NOERROR
> + lwz r11,TI_LOCAL_FLAGS(r12)
> + andi. r11,r11,_TIFL_FORCE_NOERROR
> bne 30f
> neg r3,r3
> lwz r10,_CCR(r1) /* Set SO bit in CR */
> ===== arch/ppc/kernel/pci.c 1.57 vs edited =====
> --- 1.57/arch/ppc/kernel/pci.c Tue Mar 23 16:42:53 2004
> +++ edited/arch/ppc/kernel/pci.c Thu Mar 25 15:09:51 2004
> @@ -1557,6 +1557,7 @@
> }
>
> vma->vm_pgoff = offset >> PAGE_SHIFT;
> +
> return ret;
> }
>
> ===== arch/ppc/kernel/process.c 1.57 vs edited =====
> --- 1.57/arch/ppc/kernel/process.c Mon Nov 17 12:29:47 2003
> +++ edited/arch/ppc/kernel/process.c Thu Mar 25 14:35:07 2004
> @@ -164,6 +164,7 @@
> void
> enable_kernel_altivec(void)
> {
> + preempt_disable();
> #ifdef CONFIG_SMP
> if (current->thread.regs && (current->thread.regs->msr & MSR_VEC))
> giveup_altivec(current);
> @@ -172,12 +173,14 @@
> #else
> giveup_altivec(last_task_used_altivec);
> #endif /* __SMP __ */
> + preempt_enable();
> }
> #endif /* CONFIG_ALTIVEC */
>
> void
> enable_kernel_fp(void)
> {
> + preempt_disable();
> #ifdef CONFIG_SMP
> if (current->thread.regs && (current->thread.regs->msr & MSR_FP))
> giveup_fpu(current);
> @@ -186,13 +189,16 @@
> #else
> giveup_fpu(last_task_used_math);
> #endif /* CONFIG_SMP */
> + preempt_enable();
> }
>
> int
> dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs)
> {
> + preempt_disable();
> if (regs->msr & MSR_FP)
> giveup_fpu(current);
> + preempt_enable();
> memcpy(fpregs, ¤t->thread.fpr[0], sizeof(*fpregs));
> return 1;
> }
> @@ -330,12 +336,14 @@
>
> if (regs == NULL)
> return;
> + preempt_disable();
> if (regs->msr & MSR_FP)
> giveup_fpu(current);
> #ifdef CONFIG_ALTIVEC
> if (regs->msr & MSR_VEC)
> giveup_altivec(current);
> #endif /* CONFIG_ALTIVEC */
> + preempt_enable();
> }
>
> /*
> @@ -480,12 +488,14 @@
> error = PTR_ERR(filename);
> if (IS_ERR(filename))
> goto out;
> + preempt_disable();
> if (regs->msr & MSR_FP)
> giveup_fpu(current);
> #ifdef CONFIG_ALTIVEC
> if (regs->msr & MSR_VEC)
> giveup_altivec(current);
> #endif /* CONFIG_ALTIVEC */
> + preempt_enable();
> error = do_execve(filename, (char __user *__user *) a1,
> (char __user *__user *) a2, regs);
> if (error == 0)
> ===== arch/ppc/kernel/traps.c 1.44 vs edited =====
> --- 1.44/arch/ppc/kernel/traps.c Tue Mar 23 12:46:58 2004
> +++ edited/arch/ppc/kernel/traps.c Thu Mar 25 13:21:47 2004
> @@ -438,8 +438,14 @@
> int code = 0;
> u32 fpscr;
>
> + /* We must make sure the FP state is consistent with
> + * our MSR_FP in regs
> + */
> + preempt_disable();
> if (regs->msr & MSR_FP)
> giveup_fpu(current);
> + preempt_enable();
> +
> fpscr = current->thread.fpscr;
> fpscr &= fpscr << 22; /* mask summary bits with enables */
> if (fpscr & FPSCR_VX)
> @@ -603,8 +609,11 @@
> void
> AltivecAssistException(struct pt_regs *regs)
> {
> + preempt_disable();
> if (regs->msr & MSR_VEC)
> giveup_altivec(current);
> + preempt_enable();
> +
> /* XXX quick hack for now: set the non-Java bit in the VSCR */
> current->thread.vscr.u[3] |= 0x10000;
> }
> ===== arch/ppc/syslib/prom_init.c 1.26 vs edited =====
> --- 1.26/arch/ppc/syslib/prom_init.c Sat Feb 14 19:29:14 2004
> +++ edited/arch/ppc/syslib/prom_init.c Wed Mar 24 12:35:20 2004
> @@ -44,8 +44,12 @@
> * things like "driver,AAPL,MacOS,PowerPC" properties. But this value
> * does need to be big enough to ensure that we don't lose things
> * like the interrupt-map property on a PCI-PCI bridge.
> + *
> + * 24/03/2004 - BenH: Bump that limitation to 512k and remove the
> + * filter for the MacOS drivers as we may now run
> + * those in a shell
> */
> -#define MAX_PROPERTY_LENGTH 4096
> +#define MAX_PROPERTY_LENGTH (512 * 1024)
>
> #ifndef FB_MAX /* avoid pulling in all of the fb stuff */
> #define FB_MAX 8
> ===== drivers/macintosh/adbhid.c 1.33 vs edited =====
> --- 1.33/drivers/macintosh/adbhid.c Sat Feb 14 19:29:16 2004
> +++ edited/drivers/macintosh/adbhid.c Thu Mar 25 16:16:56 2004
> @@ -107,7 +107,6 @@
> static void adbhid_probe(void);
>
> static void adbhid_input_keycode(int, int, int, struct pt_regs *);
> -static void leds_done(struct adb_request *);
>
> static void init_trackpad(int id);
> static void init_trackball(int id);
> @@ -446,24 +445,54 @@
>
> static struct adb_request led_request;
> static int leds_pending[16];
> +static int leds_req_pending;
> static int pending_devs[16];
> static int pending_led_start=0;
> static int pending_led_end=0;
> +static spinlock_t leds_lock = SPIN_LOCK_UNLOCKED;
> +
> +static void leds_done(struct adb_request *req)
> +{
> + int leds, device;
> + unsigned long flags;
> +
> + spin_lock_irqsave(&leds_lock, flags);
> +
> + if (pending_led_start != pending_led_end) {
> + device = pending_devs[pending_led_start];
> + leds = leds_pending[device] & 0xff;
> + leds_pending[device] = 0;
> + pending_led_start++;
> + pending_led_start = (pending_led_start < 16) ? pending_led_start : 0;
> + } else
> + leds_req_pending = 0;
> +
> + spin_unlock_irqrestore(&leds_lock, flags);
> + if (leds_req_pending)
> + adb_request(&led_request, leds_done, 0, 3,
> + ADB_WRITEREG(device, KEYB_LEDREG), 0xff, ~leds);
> +}
>
> static void real_leds(unsigned char leds, int device)
> {
> - if (led_request.complete) {
> - adb_request(&led_request, leds_done, 0, 3,
> - ADB_WRITEREG(device, KEYB_LEDREG), 0xff,
> - ~leds);
> - } else {
> - if (!(leds_pending[device] & 0x100)) {
> - pending_devs[pending_led_end] = device;
> - pending_led_end++;
> - pending_led_end = (pending_led_end < 16) ? pending_led_end : 0;
> + unsigned long flags;
> +
> + spin_lock_irqsave(&leds_lock, flags);
> + if (!leds_req_pending) {
> + leds_req_pending = 1;
> + spin_unlock_irqrestore(&leds_lock, flags);
> + adb_request(&led_request, leds_done, 0, 3,
> + ADB_WRITEREG(device, KEYB_LEDREG), 0xff, ~leds);
> + return;
> + } else {
> + if (!(leds_pending[device] & 0x100)) {
> + pending_devs[pending_led_end] = device;
> + pending_led_end++;
> + pending_led_end = (pending_led_end < 16) ? pending_led_end : 0;
> + }
> + leds_pending[device] = leds | 0x100;
> }
> - leds_pending[device] = leds | 0x100;
> - }
> + spin_unlock_irqrestore(&leds_lock, flags);
> }
>
> /*
> @@ -487,21 +516,6 @@
> return -1;
> }
>
> -static void leds_done(struct adb_request *req)
> -{
> - int leds,device;
> -
> - if (pending_led_start != pending_led_end) {
> - device = pending_devs[pending_led_start];
> - leds = leds_pending[device] & 0xff;
> - leds_pending[device] = 0;
> - pending_led_start++;
> - pending_led_start = (pending_led_start < 16) ? pending_led_start : 0;
> - real_leds(leds,device);
> - }
> -
> -}
> -
> static int
> adb_message_handler(struct notifier_block *this, unsigned long code, void
> *x) {
> @@ -518,7 +532,7 @@
> }
>
> /* Stop pending led requests */
> - while(!led_request.complete)
> + while(leds_req_pending)
> adb_poll();
> break;
>
> ===== drivers/macintosh/via-pmu.c 1.61 vs edited =====
> --- 1.61/drivers/macintosh/via-pmu.c Thu Mar 4 13:04:36 2004
> +++ edited/drivers/macintosh/via-pmu.c Thu Mar 25 18:52:00 2004
> @@ -137,7 +137,8 @@
> static int data_len;
> static volatile int adb_int_pending;
> static volatile int disable_poll;
> -static struct adb_request bright_req_1, bright_req_2, bright_req_3;
> +static struct adb_request bright_req_1, bright_req_2;
> +static unsigned long async_req_locks;
> static struct device_node *vias;
> static int pmu_kind = PMU_UNKNOWN;
> static int pmu_fully_inited = 0;
> @@ -404,7 +405,6 @@
>
> bright_req_1.complete = 1;
> bright_req_2.complete = 1;
> - bright_req_3.complete = 1;
> #ifdef CONFIG_PMAC_PBOOK
> batt_req.complete = 1;
> if (pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) >= 0)
> @@ -710,6 +710,8 @@
> pmu_batteries[pmu_cur_battery].amperage = amperage;
> pmu_batteries[pmu_cur_battery].voltage = voltage;
> pmu_batteries[pmu_cur_battery].time_remaining = time;
> +
> + clear_bit(0, &async_req_locks);
> }
>
> static void __pmac
> @@ -785,12 +787,14 @@
> pmu_batteries[pmu_cur_battery].time_remaining = 0;
>
> pmu_cur_battery = (pmu_cur_battery + 1) % pmu_battery_count;
> +
> + clear_bit(0, &async_req_locks);
> }
>
> static void __pmac
> query_battery_state(void)
> {
> - if (!batt_req.complete)
> + if (test_and_set_bit(0, &async_req_locks))
> return;
> if (pmu_kind == PMU_OHARE_BASED)
> pmu_request(&batt_req, done_battery_state_ohare,
> @@ -1690,20 +1694,30 @@
> return 0;
> }
>
> +static void __openfirmware
> +pmu_bright_complete(struct adb_request *req)
> +{
> + if (req == &bright_req_1)
> + clear_bit(1, &async_req_locks);
> + if (req == &bright_req_2)
> + clear_bit(2, &async_req_locks);
> +}
> +
> static int __openfirmware
> pmu_set_backlight_level(int level, void* data)
> {
> if (vias == NULL)
> return -ENODEV;
>
> - if (!bright_req_1.complete)
> + if (test_and_set_bit(1, &async_req_locks))
> return -EAGAIN;
> - pmu_request(&bright_req_1, NULL, 2, PMU_BACKLIGHT_BRIGHT,
> + pmu_request(&bright_req_1, pmu_bright_complete, 2, PMU_BACKLIGHT_BRIGHT,
> backlight_to_bright[level]);
> - if (!bright_req_2.complete)
> + if (test_and_set_bit(2, &async_req_locks))
> return -EAGAIN;
> - pmu_request(&bright_req_2, NULL, 2, PMU_POWER_CTRL, PMU_POW_BACKLIGHT
> - | (level > BACKLIGHT_OFF ? PMU_POW_ON : PMU_POW_OFF));
> + pmu_request(&bright_req_2, pmu_bright_complete, 2, PMU_POWER_CTRL,
> + PMU_POW_BACKLIGHT | (level > BACKLIGHT_OFF ?
> + PMU_POW_ON : PMU_POW_OFF));
>
> return 0;
> }
> @@ -2330,6 +2344,8 @@
> return -EBUSY;
> }
>
> + preempt_disable();
> +
> /* Make sure the decrementer won't interrupt us */
> asm volatile("mtdec %0" : : "r" (0x7fffffff));
> /* Make sure any pending DEC interrupt occurring while we did
> @@ -2352,6 +2368,7 @@
> if (ret) {
> wakeup_decrementer();
> local_irq_enable();
> + preempt_enable();
> device_resume();
> broadcast_wake();
> printk(KERN_ERR "Driver powerdown failed\n");
> @@ -2360,7 +2377,8 @@
>
> /* Wait for completion of async backlight requests */
> while (!bright_req_1.complete || !bright_req_2.complete ||
> - !bright_req_3.complete || !batt_req.complete)
> +
> + !batt_req.complete)
> pmu_poll();
>
> /* Giveup the lazy FPU & vec so we don't have to back them
> @@ -2398,6 +2416,8 @@
>
> pmu_blink(1);
>
> + preempt_enable();
> +
> /* Resume devices */
> device_resume();
>
> @@ -2673,9 +2693,9 @@
> mb();
>
> pmac_wakeup_devices();
> -
> pbook_free_pci_save();
> iounmap(mem_ctrl);
> +
> return 0;
> }
>
> ===== include/asm-ppc/ptrace.h 1.11 vs edited =====
> --- 1.11/include/asm-ppc/ptrace.h Tue Jun 24 14:45:56 2003
> +++ edited/include/asm-ppc/ptrace.h Thu Mar 25 14:02:44 2004
> @@ -49,7 +49,10 @@
> #define instruction_pointer(regs) ((regs)->nip)
> #define user_mode(regs) (((regs)->msr & MSR_PR) != 0)
>
> -#define force_successful_syscall_return()
> set_thread_flag(TIF_FORCE_NOERROR) +#define
> force_successful_syscall_return() \
> + do { \
> + current_thread_info()->local_flags |= _TIFL_FORCE_NOERROR; \
> + } while(0)
>
> /*
> * We use the least-significant bit of the trap field to indicate
> ===== include/asm-ppc/thread_info.h 1.17 vs edited =====
> --- 1.17/include/asm-ppc/thread_info.h Tue Oct 14 17:28:08 2003
> +++ edited/include/asm-ppc/thread_info.h Thu Mar 25 14:03:56 2004
> @@ -18,6 +18,7 @@
> struct task_struct *task; /* main task structure */
> struct exec_domain *exec_domain; /* execution domain */
> unsigned long flags; /* low level flags */
> + unsigned long local_flags; /* non-racy flags */
> int cpu; /* cpu we're on */
> int preempt_count;
> struct restart_block restart_block;
> @@ -28,6 +29,7 @@
> .task = &tsk, \
> .exec_domain = &default_exec_domain, \
> .flags = 0, \
> + .local_flags = 0, \
> .cpu = 0, \
> .preempt_count = 1, \
> .restart_block = { \
> @@ -69,8 +71,9 @@
> #define TI_TASK 0
> #define TI_EXECDOMAIN 4
> #define TI_FLAGS 8
> -#define TI_CPU 12
> -#define TI_PREEMPT 16
> +#define TI_LOCAL_FLAGS 12
> +#define TI_CPU 16
> +#define TI_PREEMPT 20
>
> #define PREEMPT_ACTIVE 0x4000000
>
> @@ -83,16 +86,22 @@
> #define TIF_NEED_RESCHED 3 /* rescheduling necessary */
> #define TIF_POLLING_NRFLAG 4 /* true if poll_idle() is polling
> TIF_NEED_RESCHED */
> -#define TIF_FORCE_NOERROR 5 /* don't return error from current
> - syscall even if result < 0 */
> -
> /* as above, but as bit values */
> #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
> #define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
> #define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
> #define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
> #define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
> -#define _TIF_FORCE_NOERROR (1<<TIF_FORCE_NOERROR)
> +
> +/*
> + * Non racy (local) flags bit numbers
> + */
> +#define TIFL_FORCE_NOERROR 0 /* don't return error from current
> + syscall even if result < 0 */
> +
> +/* as above, but as bit values */
> +#define _TIFL_FORCE_NOERROR (1<<TIFL_FORCE_NOERROR)
> +
>
> #endif /* __KERNEL__ */
>
> ===== sound/oss/dmasound/dmasound_core.c 1.22 vs edited =====
> --- 1.22/sound/oss/dmasound/dmasound_core.c Mon Feb 9 13:18:52 2004
> +++ edited/sound/oss/dmasound/dmasound_core.c Thu Mar 25 18:41:02 2004
> @@ -1004,6 +1004,7 @@
> static int sq_fsync(struct file *filp, struct dentry *dentry)
> {
> int rc = 0;
> + int timeout = 5;
>
> write_sq.syncing |= 1;
> sq_play(); /* there may be an incomplete frame waiting */
> @@ -1016,6 +1017,12 @@
> * and clear the queue. */
> sq_reset_output();
> rc = -EINTR;
> + break;
> + }
> + if (!--timeout) {
> + printk(KERN_WARNING "dmasound: Timeout draining output\n");
> + sq_reset_output();
> + rc = -EIO;
> break;
> }
> }
- --
We shall not cease from exploration
And the end of all our exploring
Will be to arrive where we started
And know the place for the first time.
- - T. S. Eliot
- ----------------------------------
Libretech.org - Technology Is Free (http://www.libretech.org)
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (GNU/Linux)
iD8DBQFAbg99I89ooLagmnQRAvPfAKCXEtXtmWmZJjxBzecz0wXY4GWuQwCgwNuQ
NxvG+7/YKYK3WoAZHZz5si0=
=7XME
-----END PGP SIGNATURE-----
Reply to: