LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] 0/3 Add pselect/ppoll()
From: David Woodhouse @ 2005-11-29  0:57 UTC (permalink / raw)
  To: linux-kernel; +Cc: akpm, linuxppc-dev, drepper

The following implementation of ppoll() and pselect() system calls
depends on the architecture providing a TIF_RESTORE_SIGMASK flag in the
thread_info.

These system calls have to change the signal mask during their
operation, and signal handlers must be invoked using the new, temporary
signal mask. The old signal mask must be restored either upon successful
exit from the system call, or upon returning from the invoked signal
handler if the system call is interrupted. We can't simply restore the
original signal mask and return to userspace, since the restored signal
mask may actually block the signal which interrupted the system call.

The TIF_RESTORE_SIGMASK flag deals with this by causing the syscall exit
path to trap into do_signal() just as TIF_SIGPENDING does, and by
causing do_signal() to use the saved signal mask instead of the current
signal mask when setting up the stack frame for the signal handler -- or
by causing do_signal() to simply restore the saved signal mask in the
case where there is no handler to be invoked.

The first patch implements the sys_pselect() and sys_ppoll() system
calls, which are present only if TIF_RESTORE_SIGMASK is defined. That
#ifdef should go away in time when all architectures have implemented
it. The second patch implements TIF_RESTORE_SIGMASK for the PowerPC
kernel (in the -mm tree), and the third patch then removes the
arch-specific implementations of sys_rt_sigsuspend() and replaces them
with generic versions using the same trick.

-- 
dwmw2

^ permalink raw reply

* [PATCH] 1/3 Add pselect/ppoll() system calls
From: David Woodhouse @ 2005-11-29  0:57 UTC (permalink / raw)
  To: linux-kernel; +Cc: akpm, linuxppc-dev, drepper
In-Reply-To: <1133225007.31573.86.camel@baythorne.infradead.org>

This patch adds the pselect() and ppoll() system calls. Most of this
implementation is as it was in the -mm kernel for a period of time
already before the difficulties with signal delivery became apparent.

Signed-off-by: David Woodhouse <dwmw2@infradead.org>

diff --git a/fs/select.c b/fs/select.c
index f10a103..4e0da96 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -179,12 +179,11 @@ get_max:
 #define POLLOUT_SET (POLLWRBAND | POLLWRNORM | POLLOUT | POLLERR)
 #define POLLEX_SET (POLLPRI)
 
-int do_select(int n, fd_set_bits *fds, long *timeout)
+int do_select(int n, fd_set_bits *fds, int64_t *timeout)
 {
 	struct poll_wqueues table;
 	poll_table *wait;
 	int retval, i;
-	long __timeout = *timeout;
 
 	rcu_read_lock();
 	retval = max_select_fd(n, fds);
@@ -196,11 +195,12 @@ int do_select(int n, fd_set_bits *fds, l
 
 	poll_initwait(&table);
 	wait = &table.pt;
-	if (!__timeout)
+	if (!*timeout)
 		wait = NULL;
 	retval = 0;
 	for (;;) {
 		unsigned long *rinp, *routp, *rexp, *inp, *outp, *exp;
+		long __timeout;
 
 		set_current_state(TASK_INTERRUPTIBLE);
 
@@ -255,22 +255,32 @@ int do_select(int n, fd_set_bits *fds, l
 				*rexp = res_ex;
 		}
 		wait = NULL;
-		if (retval || !__timeout || signal_pending(current))
+		if (retval || !*timeout || signal_pending(current))
 			break;
 		if(table.error) {
 			retval = table.error;
 			break;
 		}
+
+		if (*timeout < 0) {
+			/* Wait indefinitely */
+			__timeout = MAX_SCHEDULE_TIMEOUT;
+		} else if (unlikely(*timeout >= (int64_t)MAX_SCHEDULE_TIMEOUT - 1)) {
+			/* Wait for longer than MAX_SCHEDULE_TIMEOUT. Do it in a loop */
+			__timeout = MAX_SCHEDULE_TIMEOUT - 1;
+			*timeout -= __timeout;
+		} else {
+			__timeout = *timeout;
+			*timeout = 0;
+		}
 		__timeout = schedule_timeout(__timeout);
+		if (*timeout >= 0)
+			*timeout += __timeout;
 	}
 	__set_current_state(TASK_RUNNING);
 
 	poll_freewait(&table);
 
-	/*
-	 * Up-to-date the caller timeout.
-	 */
-	*timeout = __timeout;
 	return retval;
 }
 
@@ -295,36 +305,14 @@ static void select_bits_free(void *bits,
 #define MAX_SELECT_SECONDS \
 	((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
 
-asmlinkage long
-sys_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, struct timeval __user *tvp)
+static int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp,
+			   fd_set __user *exp, int64_t *timeout)
 {
 	fd_set_bits fds;
 	char *bits;
-	long timeout;
 	int ret, size, max_fdset;
 	struct fdtable *fdt;
 
-	timeout = MAX_SCHEDULE_TIMEOUT;
-	if (tvp) {
-		time_t sec, usec;
-
-		if (!access_ok(VERIFY_READ, tvp, sizeof(*tvp))
-		    || __get_user(sec, &tvp->tv_sec)
-		    || __get_user(usec, &tvp->tv_usec)) {
-			ret = -EFAULT;
-			goto out_nofds;
-		}
-
-		ret = -EINVAL;
-		if (sec < 0 || usec < 0)
-			goto out_nofds;
-
-		if ((unsigned long) sec < MAX_SELECT_SECONDS) {
-			timeout = ROUND_UP(usec, 1000000/HZ);
-			timeout += sec * (unsigned long) HZ;
-		}
-	}
-
 	ret = -EINVAL;
 	if (n < 0)
 		goto out_nofds;
@@ -362,18 +350,7 @@ sys_select(int n, fd_set __user *inp, fd
 	zero_fd_set(n, fds.res_out);
 	zero_fd_set(n, fds.res_ex);
 
-	ret = do_select(n, &fds, &timeout);
-
-	if (tvp && !(current->personality & STICKY_TIMEOUTS)) {
-		time_t sec = 0, usec = 0;
-		if (timeout) {
-			sec = timeout / HZ;
-			usec = timeout % HZ;
-			usec *= (1000000/HZ);
-		}
-		put_user(sec, &tvp->tv_sec);
-		put_user(usec, &tvp->tv_usec);
-	}
+	ret = do_select(n, &fds, timeout);
 
 	if (ret < 0)
 		goto out;
@@ -395,6 +372,150 @@ out_nofds:
 	return ret;
 }
 
+asmlinkage long sys_select(int n, fd_set __user *inp, fd_set __user *outp,
+			fd_set __user *exp, struct timeval __user *tvp)
+{
+	int64_t timeout = -1;
+	struct timeval tv;
+	int ret;
+
+	if (tvp) {
+		if (copy_from_user(&tv, tvp, sizeof(tv)))
+			return -EFAULT;
+
+		if (tv.tv_sec < 0 || tv.tv_usec < 0)
+			return -EINVAL;
+
+		/* Cast to uint64_t to make GCC stop complaining */
+		if ((uint64_t)tv.tv_sec >= (uint64_t)MAX_INT64_SECONDS)
+			timeout = -1;	/* infinite */
+		else {
+			timeout = ROUND_UP(tv.tv_sec, 1000000/HZ);
+			timeout += tv.tv_sec * HZ;
+		}
+	}
+
+	ret = core_sys_select(n, inp, outp, exp, &timeout);
+
+	if (tvp) {
+		if (current->personality & STICKY_TIMEOUTS)
+			goto sticky;
+		tv.tv_usec = jiffies_to_usecs(do_div((*(uint64_t*)&timeout), HZ));
+		tv.tv_sec = timeout;
+		if (copy_to_user(tvp, &tv, sizeof(tv))) {
+		sticky:
+			/*
+			 * If an application puts its timeval in read-only
+			 * memory, we don't want the Linux-specific update to
+			 * the timeval to cause a fault after the select has
+			 * completed successfully. However, because we're not
+			 * updating the timeval, we can't restart the system
+			 * call.
+			 */
+			if (ret == -ERESTARTNOHAND)
+				ret = -EINTR;
+		}
+	}
+
+	return ret;
+}
+
+#ifdef TIF_RESTORE_SIGMASK
+asmlinkage long sys_pselect7(int n, fd_set __user *inp, fd_set __user *outp,
+		fd_set __user *exp, struct timespec __user *tsp,
+		const sigset_t __user *sigmask, size_t sigsetsize)
+{
+	int64_t timeout = MAX_SCHEDULE_TIMEOUT;
+	sigset_t ksigmask, sigsaved;
+	struct timespec ts;
+	int ret;
+
+	if (tsp) {
+		if (copy_from_user(&ts, tsp, sizeof(ts)))
+			return -EFAULT;
+
+		if (ts.tv_sec < 0 || ts.tv_nsec < 0)
+			return -EINVAL;
+
+		/* Cast to uint64_t to make GCC stop complaining */
+		if ((uint64_t)ts.tv_sec >= (uint64_t)MAX_INT64_SECONDS)
+			timeout = -1;	/* infinite */
+		else {
+			timeout = ROUND_UP(ts.tv_sec, 1000000000/HZ);
+			timeout += ts.tv_sec * HZ;
+		}
+	}
+
+	if (sigmask) {
+		/* XXX: Don't preclude handling different sized sigset_t's.  */
+		if (sigsetsize != sizeof(sigset_t))
+			return -EINVAL;
+		if (copy_from_user(&ksigmask, sigmask, sizeof(ksigmask)))
+			return -EFAULT;
+
+		sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
+		sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
+	}
+
+	ret = core_sys_select(n, inp, outp, exp, &timeout);
+
+	if (tsp) {
+		if (current->personality & STICKY_TIMEOUTS)
+			goto sticky;
+		ts.tv_nsec = jiffies_to_usecs(do_div((*(uint64_t*)&timeout), HZ)) * 1000;
+		ts.tv_sec = timeout;
+		if (copy_to_user(tsp, &ts, sizeof(ts))) {
+		sticky:
+			/*
+			 * If an application puts its timeval in read-only
+			 * memory, we don't want the Linux-specific update to
+			 * the timeval to cause a fault after the select has
+			 * completed successfully. However, because we're not
+			 * updating the timeval, we can't restart the system
+			 * call.
+			 */
+			if (ret == -ERESTARTNOHAND)
+				ret = -EINTR;
+		}
+	}
+
+	if (ret == -ERESTARTNOHAND) {
+		/* Don't restore the signal mask yet. Let do_signal() deliver the signal
+		   on the way back to userspace, before the signal mask is restored. */
+		if (sigmask) {
+			memcpy(&current->saved_sigmask, &sigsaved, sizeof(sigsaved));
+			set_thread_flag(TIF_RESTORE_SIGMASK);
+		}
+	} else if (sigmask)
+		sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+
+	return ret;
+}
+
+/*
+ * Most architectures can't handle 7-argument syscalls. So we provide a
+ * 6-argument version where the sixth argument is a pointer to a structure
+ * which has a pointer to the sigset_t itself followed by a size_t containing
+ * the sigset size.
+ */
+asmlinkage long sys_pselect6(int n, fd_set __user *inp, fd_set __user *outp,
+	fd_set __user *exp, struct timespec __user *tsp, void __user *sig)
+{
+	size_t sigsetsize = 0;
+	sigset_t __user *up = NULL;
+
+	if (sig) {
+		if (!access_ok(VERIFY_READ, sig, sizeof(void *)+sizeof(size_t))
+		    || __get_user(up, (sigset_t * __user *)sig)
+		    || __get_user(sigsetsize,
+				(size_t * __user)(sig+sizeof(void *))))
+			return -EFAULT;
+	}
+
+	return sys_pselect7(n, inp, outp, exp, tsp, up, sigsetsize);
+}
+#endif /* TIF_RESTORE_SIGMASK */
+
 struct poll_list {
 	struct poll_list *next;
 	int len;
@@ -436,16 +557,19 @@ static void do_pollfd(unsigned int num, 
 }
 
 static int do_poll(unsigned int nfds,  struct poll_list *list,
-			struct poll_wqueues *wait, long timeout)
+		   struct poll_wqueues *wait, int64_t *timeout)
 {
 	int count = 0;
 	poll_table* pt = &wait->pt;
 
-	if (!timeout)
+	/* Optimise the no-wait case */
+	if (!(*timeout))
 		pt = NULL;
  
 	for (;;) {
 		struct poll_list *walk;
+		long __timeout;
+
 		set_current_state(TASK_INTERRUPTIBLE);
 		walk = list;
 		while(walk != NULL) {
@@ -453,18 +577,33 @@ static int do_poll(unsigned int nfds,  s
 			walk = walk->next;
 		}
 		pt = NULL;
-		if (count || !timeout || signal_pending(current))
+		if (count || !*timeout || signal_pending(current))
 			break;
 		count = wait->error;
 		if (count)
 			break;
-		timeout = schedule_timeout(timeout);
+
+		if (*timeout < 0) {
+			/* Wait indefinitely */
+			__timeout = MAX_SCHEDULE_TIMEOUT;
+		} else if (unlikely(*timeout >= (int64_t)MAX_SCHEDULE_TIMEOUT - 1)) {
+			/* Wait for longer than MAX_SCHEDULE_TIMEOUT. Do it in a loop */
+			__timeout = MAX_SCHEDULE_TIMEOUT - 1;
+			*timeout -= __timeout;
+		} else {
+			__timeout = *timeout;
+			*timeout = 0;
+		}
+
+		__timeout = schedule_timeout(__timeout);
+		if (*timeout >= 0)
+			*timeout += __timeout;
 	}
 	__set_current_state(TASK_RUNNING);
 	return count;
 }
 
-asmlinkage long sys_poll(struct pollfd __user * ufds, unsigned int nfds, long timeout)
+int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds, int64_t *timeout)
 {
 	struct poll_wqueues table;
  	int fdcount, err;
@@ -482,14 +621,6 @@ asmlinkage long sys_poll(struct pollfd _
 	if (nfds > max_fdset && nfds > OPEN_MAX)
 		return -EINVAL;
 
-	if (timeout) {
-		/* Careful about overflow in the intermediate values */
-		if ((unsigned long) timeout < MAX_SCHEDULE_TIMEOUT / HZ)
-			timeout = (unsigned long)(timeout*HZ+999)/1000+1;
-		else /* Negative or overflow */
-			timeout = MAX_SCHEDULE_TIMEOUT;
-	}
-
 	poll_initwait(&table);
 
 	head = NULL;
@@ -519,6 +650,7 @@ asmlinkage long sys_poll(struct pollfd _
 		}
 		i -= pp->len;
 	}
+
 	fdcount = do_poll(nfds, head, &table, timeout);
 
 	/* OK, now copy the revents fields back to user space. */
@@ -547,3 +679,94 @@ out_fds:
 	poll_freewait(&table);
 	return err;
 }
+
+asmlinkage long sys_poll(struct pollfd __user *ufds, unsigned int nfds,
+			long timeout_msecs)
+{
+	int64_t timeout_jiffies = 0;
+
+	if (timeout_msecs) {
+#if HZ > 1000
+		/* We can only overflow if HZ > 1000 */
+		if (timeout_msecs / 1000 > (int64_t)0x7fffffffffffffffULL / (int64_t)HZ)
+			timeout_jiffies = -1;
+		else
+#endif
+			timeout_jiffies = msecs_to_jiffies(timeout_msecs);
+	}
+
+	return do_sys_poll(ufds, nfds, &timeout_jiffies);
+}
+
+#ifdef TIF_RESTORE_SIGMASK
+asmlinkage long sys_ppoll(struct pollfd __user *ufds, unsigned int nfds,
+	struct timespec __user *tsp, const sigset_t __user *sigmask,
+	size_t sigsetsize)
+{
+	sigset_t ksigmask, sigsaved;
+	struct timespec ts;
+	int64_t timeout = -1;
+	int ret;
+
+	if (tsp) {
+		if (copy_from_user(&ts, tsp, sizeof(ts)))
+			return -EFAULT;
+
+		/* Cast to uint64_t to make GCC stop complaining */
+		if ((uint64_t)ts.tv_sec >= (uint64_t)MAX_INT64_SECONDS)
+			timeout = -1;	/* infinite */
+		else {
+			timeout = ROUND_UP(ts.tv_sec, 1000000000/HZ);
+			timeout += ts.tv_sec * HZ;
+		}
+	}
+
+	if (sigmask) {
+		/* XXX: Don't preclude handling different sized sigset_t's.  */
+		if (sigsetsize != sizeof(sigset_t))
+			return -EINVAL;
+		if (copy_from_user(&ksigmask, sigmask, sizeof(ksigmask)))
+			return -EFAULT;
+
+		sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
+		sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
+	}
+
+	ret = do_sys_poll(ufds, nfds, &timeout);
+
+	/* We can restart this syscall, usually */
+	if (ret == -EINTR) {
+		/* Don't restore the signal mask yet. Let do_signal() deliver the signal
+		   on the way back to userspace, before the signal mask is restored. */
+		if (sigmask) {
+			memcpy(&current->saved_sigmask, &sigsaved, sizeof(sigsaved));
+			set_thread_flag(TIF_RESTORE_SIGMASK);
+		}
+		ret = -ERESTARTNOHAND;
+	} else if (sigmask)
+		sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+
+	if (tsp && timeout >= 0) {
+		if (current->personality & STICKY_TIMEOUTS)
+			goto sticky;
+		/* Yes, we know it's actually an int64_t, but it's also positive. */
+		ts.tv_nsec = jiffies_to_usecs(do_div((*(uint64_t*)&timeout), HZ)) * 1000;
+		ts.tv_sec = timeout;
+		if (copy_to_user(tsp, &ts, sizeof(ts))) {
+		sticky:
+			/*
+			 * If an application puts its timeval in read-only
+			 * memory, we don't want the Linux-specific update to
+			 * the timeval to cause a fault after the select has
+			 * completed successfully. However, because we're not
+			 * updating the timeval, we can't restart the system
+			 * call.
+			 */
+			if (ret == -ERESTARTNOHAND && timeout >= 0)
+				ret = -EINTR;
+		}
+	}
+
+	return ret;
+}
+#endif /* TIF_RESTORE_SIGMASK */
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -53,6 +53,8 @@
 #include <asm/mmu_context.h>
 #include <asm/ioctls.h>
 
+extern void sigset_from_compat(sigset_t *set, compat_sigset_t *compat);
+
 /*
  * Not all architectures have sys_utime, so implement this in terms
  * of sys_utimes.
@@ -1607,36 +1609,14 @@ static void select_bits_free(void *bits,
 #define MAX_SELECT_SECONDS \
 	((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
 
-asmlinkage long
-compat_sys_select(int n, compat_ulong_t __user *inp, compat_ulong_t __user *outp,
-		compat_ulong_t __user *exp, struct compat_timeval __user *tvp)
+int compat_core_sys_select(int n, compat_ulong_t __user *inp,
+	compat_ulong_t __user *outp, compat_ulong_t __user *exp, int64_t *timeout)
 {
 	fd_set_bits fds;
 	char *bits;
-	long timeout;
 	int size, max_fdset, ret = -EINVAL;
 	struct fdtable *fdt;
 
-	timeout = MAX_SCHEDULE_TIMEOUT;
-	if (tvp) {
-		time_t sec, usec;
-
-		if (!access_ok(VERIFY_READ, tvp, sizeof(*tvp))
-		    || __get_user(sec, &tvp->tv_sec)
-		    || __get_user(usec, &tvp->tv_usec)) {
-			ret = -EFAULT;
-			goto out_nofds;
-		}
-
-		if (sec < 0 || usec < 0)
-			goto out_nofds;
-
-		if ((unsigned long) sec < MAX_SELECT_SECONDS) {
-			timeout = ROUND_UP(usec, 1000000/HZ);
-			timeout += sec * (unsigned long) HZ;
-		}
-	}
-
 	if (n < 0)
 		goto out_nofds;
 
@@ -1673,19 +1653,7 @@ compat_sys_select(int n, compat_ulong_t 
 	zero_fd_set(n, fds.res_out);
 	zero_fd_set(n, fds.res_ex);
 
-	ret = do_select(n, &fds, &timeout);
-
-	if (tvp && !(current->personality & STICKY_TIMEOUTS)) {
-		time_t sec = 0, usec = 0;
-		if (timeout) {
-			sec = timeout / HZ;
-			usec = timeout % HZ;
-			usec *= (1000000/HZ);
-		}
-		if (put_user(sec, &tvp->tv_sec) ||
-		    put_user(usec, &tvp->tv_usec))
-			ret = -EFAULT;
-	}
+	ret = do_select(n, &fds, timeout);
 
 	if (ret < 0)
 		goto out;
@@ -1706,6 +1674,216 @@ out_nofds:
 	return ret;
 }
 
+asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp,
+	compat_ulong_t __user *outp, compat_ulong_t __user *exp,
+	struct compat_timeval __user *tvp)
+{
+	int64_t timeout = -1;
+	struct compat_timeval tv;
+	int ret;
+
+	if (tvp) {
+		if (copy_from_user(&tv, tvp, sizeof(tv)))
+			return -EFAULT;
+
+		if (tv.tv_sec < 0 || tv.tv_usec < 0)
+			return -EINVAL;
+
+		/* Cast to uint64_t to make GCC stop complaining */
+		if ((uint64_t)tv.tv_sec >= (uint64_t)MAX_INT64_SECONDS)
+			timeout = -1;	/* infinite */
+		else {
+			timeout = ROUND_UP(tv.tv_sec, 1000000/HZ);
+			timeout += tv.tv_sec * HZ;
+		}
+	}
+
+	ret = compat_core_sys_select(n, inp, outp, exp, &timeout);
+
+	if (tvp) {
+		if (current->personality & STICKY_TIMEOUTS)
+			goto sticky;
+		tv.tv_usec = jiffies_to_usecs(do_div((*(uint64_t*)&timeout), HZ));
+		tv.tv_sec = timeout;
+		if (copy_to_user(tvp, &tv, sizeof(tv))) {
+		sticky:
+			/*
+			 * If an application puts its timeval in read-only
+			 * memory, we don't want the Linux-specific update to
+			 * the timeval to cause a fault after the select has
+			 * completed successfully. However, because we're not
+			 * updating the timeval, we can't restart the system
+			 * call.
+			 */
+			if (ret == -ERESTARTNOHAND)
+				ret = -EINTR;
+		}
+	}
+
+	return ret;
+}
+
+#ifdef TIF_RESTORE_SIGMASK
+asmlinkage long compat_sys_pselect7(int n, compat_ulong_t __user *inp,
+	compat_ulong_t __user *outp, compat_ulong_t __user *exp,
+	struct compat_timespec __user *tsp, compat_sigset_t __user *sigmask,
+	compat_size_t sigsetsize)
+{
+	compat_sigset_t s32;
+	sigset_t ksigmask, sigsaved;
+	long timeout = MAX_SCHEDULE_TIMEOUT;
+	struct compat_timespec ts;
+	int ret;
+
+	if (tsp) {
+		if (copy_from_user(&ts, tsp, sizeof(ts)))
+			return -EFAULT;
+
+		if (ts.tv_sec < 0 || ts.tv_nsec < 0)
+			return -EINVAL;
+	}
+
+	if (sigmask) {
+		if (sigsetsize != sizeof(compat_sigset_t))
+			return -EINVAL;
+		if (copy_from_user(&s32, sigmask, sizeof(s32)))
+			return -EFAULT;
+		sigset_from_compat(&ksigmask, &s32);
+
+		sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
+		sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
+	}
+
+	do {
+		if (tsp) {
+			if ((unsigned long)ts.tv_sec < MAX_SELECT_SECONDS) {
+				timeout = ROUND_UP(ts.tv_nsec, 1000000000/HZ);
+				timeout += ts.tv_sec * (unsigned long)HZ;
+				ts.tv_sec = 0;
+				ts.tv_nsec = 0;
+			} else {
+				ts.tv_sec -= MAX_SELECT_SECONDS;
+				timeout = MAX_SELECT_SECONDS * HZ;
+			}
+		}
+
+		ret = compat_core_sys_select(n, inp, outp, exp, &timeout);
+
+	} while (!ret && !timeout && tsp && (ts.tv_sec || ts.tv_nsec));
+
+	if (tsp && !(current->personality & STICKY_TIMEOUTS)) {
+		ts.tv_sec += timeout / HZ;
+		ts.tv_nsec += (timeout % HZ) * (1000000000/HZ);
+		if (ts.tv_nsec >= 1000000000) {
+			ts.tv_sec++;
+			ts.tv_nsec -= 1000000000;
+		}
+		(void)copy_to_user(tsp, &ts, sizeof(ts));
+	}
+
+	if (ret == -ERESTARTNOHAND) {
+		/* Don't restore the signal mask yet. Let do_signal() deliver the signal
+		   on the way back to userspace, before the signal mask is restored. */
+		if (sigmask) {
+			memcpy(&current->saved_sigmask, &sigsaved, sizeof(sigsaved));
+			set_thread_flag(TIF_RESTORE_SIGMASK);
+		}
+	} else if (sigmask)
+		sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+
+	return ret;
+}
+
+asmlinkage long compat_sys_pselect6(int n, compat_ulong_t __user *inp,
+	compat_ulong_t __user *outp, compat_ulong_t __user *exp,
+	struct compat_timespec __user *tsp, void __user *sig)
+{
+	compat_size_t sigsetsize = 0;
+	compat_uptr_t up = 0;
+
+	if (sig) {
+		if (!access_ok(VERIFY_READ, sig,
+				sizeof(compat_uptr_t)+sizeof(compat_size_t)) ||
+		    	__get_user(up, (compat_uptr_t __user *)sig) ||
+		    	__get_user(sigsetsize,
+				(compat_size_t __user *)(sig+sizeof(up))))
+			return -EFAULT;
+	}
+	return compat_sys_pselect7(n, inp, outp, exp, tsp, compat_ptr(up),
+					sigsetsize);
+}
+
+asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
+	unsigned int nfds, struct compat_timespec __user *tsp,
+	const compat_sigset_t __user *sigmask, compat_size_t sigsetsize)
+{
+	compat_sigset_t s32;
+	sigset_t ksigmask, sigsaved;
+	struct compat_timespec ts;
+	int64_t timeout = -1;
+	int ret;
+
+	if (tsp) {
+		if (copy_from_user(&ts, tsp, sizeof(ts)))
+			return -EFAULT;
+
+		/* We assume that ts.tv_sec is always lower than
+		   the number of seconds that can be expressed in
+		   an int64_t. Otherwise the compiler bitches at us */
+		timeout = ROUND_UP(ts.tv_sec, 1000000000/HZ);
+		timeout += ts.tv_sec * HZ;
+	}
+
+	if (sigmask) {
+		if (sigsetsize |= sizeof(compat_sigset_t))
+			return -EINVAL;
+		if (copy_from_user(&s32, sigmask, sizeof(s32)))
+			return -EFAULT;
+		sigset_from_compat(&ksigmask, &s32);
+
+		sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
+		sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
+	}
+
+	ret = do_sys_poll(ufds, nfds, &timeout);
+
+	/* We can restart this syscall, usually */
+	if (ret == -EINTR) {
+		/* Don't restore the signal mask yet. Let do_signal() deliver the signal
+		   on the way back to userspace, before the signal mask is restored. */
+		if (sigmask) {
+			memcpy(&current->saved_sigmask, &sigsaved, sizeof(sigsaved));
+			set_thread_flag(TIF_RESTORE_SIGMASK);
+		}
+		ret = -ERESTARTNOHAND;
+	} else if (sigmask)
+		sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+
+	if (tsp && timeout >= 0) {
+		if (current->personality & STICKY_TIMEOUTS)
+			goto sticky;
+		/* Yes, we know it's actually an int64_t, but it's also positive. */
+		ts.tv_nsec = jiffies_to_usecs(do_div((*(uint64_t*)&timeout), HZ)) * 1000;
+		ts.tv_sec = timeout;
+		if (copy_to_user(tsp, &ts, sizeof(ts))) {
+		sticky:
+			/*
+			 * If an application puts its timeval in read-only
+			 * memory, we don't want the Linux-specific update to
+			 * the timeval to cause a fault after the select has
+			 * completed successfully. However, because we're not
+			 * updating the timeval, we can't restart the system
+			 * call.
+			 */
+			if (ret == -ERESTARTNOHAND && timeout >= 0)
+				ret = -EINTR;
+		}
+	}
+
+	return ret;
+}
+#endif /* TIF_RESTORE_SIGMASK */
+
 #if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE)
 /* Stuff for NFS server syscalls... */
 struct compat_nfsctl_svc {
diff --git a/include/linux/poll.h b/include/linux/poll.h
index f6da702..5b9c85c 100644
--- a/include/linux/poll.h
+++ b/include/linux/poll.h
@@ -92,7 +92,11 @@ void zero_fd_set(unsigned long nr, unsig
 	memset(fdset, 0, FDS_BYTES(nr));
 }
 
-extern int do_select(int n, fd_set_bits *fds, long *timeout);
+#define MAX_INT64_SECONDS (((int64_t)(~((uint64_t)0)>>1)/HZ)-1)
+
+extern int do_select(int n, fd_set_bits *fds, int64_t *timeout);
+extern int do_sys_poll(struct pollfd __user * ufds, unsigned int nfds,
+		       int64_t *timeout);
 
 #endif /* KERNEL */
 
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 2038bd2..bf7db28 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -800,6 +800,7 @@ struct task_struct {
 	struct sighand_struct *sighand;
 
 	sigset_t blocked, real_blocked;
+	sigset_t saved_sigmask;		/* To be restored with TIF_RESTORE_SIGMASK */
 	struct sigpending pending;
 
 	unsigned long sas_ss_sp;



-- 
dwmw2

^ permalink raw reply related

* [PATCH] 2/3 Add TIF_RESTORE_SIGMASK support for arch/powerpc
From: David Woodhouse @ 2005-11-29  0:57 UTC (permalink / raw)
  To: linux-kernel; +Cc: akpm, linuxppc-dev, drepper
In-Reply-To: <1133225007.31573.86.camel@baythorne.infradead.org>

This patch implements the TIF_RESTORE_SIGMASK flag in the new
arch/powerpc kernel, for both 32-bit and 64-bit system call paths.

Mostly tested on 32-bit so far.

Signed-off-by: David Woodhouse <dwmw2@infradead.org>

diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index 036b71d..6aa7386 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -227,7 +227,7 @@ ret_from_syscall:
 	MTMSRD(r10)
 	lwz	r9,TI_FLAGS(r12)
 	li	r8,-_LAST_ERRNO
-	andi.	r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL)
+	andi.	r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL|_TIF_RESTORE_SIGMASK)
 	bne-	syscall_exit_work
 	cmplw	0,r3,r8
 	blt+	syscall_exit_cont
@@ -357,7 +357,7 @@ save_user_nvgprs_cont:
 	lwz	r5,_MSR(r1)
 	andi.	r5,r5,MSR_PR
 	beq	ret_from_except
-	andi.	r0,r9,_TIF_SIGPENDING
+	andi.	r0,r9,_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK
 	beq	ret_from_except
 	b	do_user_signal
 8:
@@ -683,7 +683,7 @@ user_exc_return:		/* r10 contains MSR_KE
 	/* Check current_thread_info()->flags */
 	rlwinm	r9,r1,0,0,(31-THREAD_SHIFT)
 	lwz	r9,TI_FLAGS(r9)
-	andi.	r0,r9,(_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL)
+	andi.	r0,r9,(_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL|_TIF_RESTORE_SIGMASK)
 	bne	do_work
 
 restore_user:
@@ -917,7 +917,7 @@ recheck:
 	lwz	r9,TI_FLAGS(r9)
 	andi.	r0,r9,_TIF_NEED_RESCHED
 	bne-	do_resched
-	andi.	r0,r9,_TIF_SIGPENDING
+	andi.	r0,r9,_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK
 	beq	restore_user
 do_user_signal:			/* r10 contains MSR_KERNEL here */
 	ori	r10,r10,MSR_EE
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index 2eb6f54..22e592d 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -160,7 +160,7 @@ syscall_exit:
 	mtmsrd	r10,1
 	ld	r9,TI_FLAGS(r12)
 	li	r11,-_LAST_ERRNO
-	andi.	r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL|_TIF_SAVE_NVGPRS|_TIF_NOERROR)
+	andi.	r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL|_TIF_SAVE_NVGPRS|_TIF_NOERROR|_TIF_RESTORE_SIGMASK)
 	bne-	syscall_exit_work
 	cmpld	r3,r11
 	ld	r5,_CCR(r1)
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -1177,7 +1131,7 @@ int do_signal(sigset_t *oldset, struct p
 {
 	siginfo_t info;
 	struct k_sigaction ka;
-	unsigned int frame, newsp;
+	unsigned int newsp;
 	int signr, ret;
 
 #ifdef CONFIG_PPC32
@@ -1188,11 +1142,11 @@ int do_signal(sigset_t *oldset, struct p
 	}
 #endif
 
-	if (!oldset)
+	if (test_thread_flag(TIF_RESTORE_SIGMASK))
+		oldset = &current->saved_sigmask;
+	else if (!oldset)
 		oldset = &current->blocked;
 
-	newsp = frame = 0;
-
 	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 #ifdef CONFIG_PPC32
 no_signal:
@@ -1222,8 +1176,14 @@ no_signal:
 		}
 	}
 
-	if (signr == 0)
+	if (signr == 0) {
+		/* No signal to deliver -- put the saved sigmask back */
+		if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+			clear_thread_flag(TIF_RESTORE_SIGMASK);
+			sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+		}
 		return 0;		/* no signals delivered */
+	}
 
 	if ((ka.sa.sa_flags & SA_ONSTACK) && current->sas_ss_size
 	    && !on_sig_stack(regs->gpr[1]))
@@ -1256,6 +1216,10 @@ no_signal:
 			sigaddset(&current->blocked, signr);
 		recalc_sigpending();
 		spin_unlock_irq(&current->sighand->siglock);
+		/* A signal was successfully delivered; the saved sigmask is in
+		   its frame, and we can clear the TIF_RESTORE_SIGMASK flag */
+		if (test_thread_flag(TIF_RESTORE_SIGMASK))
+			clear_thread_flag(TIF_RESTORE_SIGMASK);
 	}
 
 	return ret;
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index 5462bef..7a6f0f7 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -554,11 +518,15 @@ int do_signal(sigset_t *oldset, struct p
 	if (test_thread_flag(TIF_32BIT))
 		return do_signal32(oldset, regs);
 
-	if (!oldset)
+	if (test_thread_flag(TIF_RESTORE_SIGMASK))
+		oldset = &current->saved_sigmask;
+	else if (!oldset)
 		oldset = &current->blocked;
 
 	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 	if (signr > 0) {
+		int ret;
+
 		/* Whee!  Actually deliver the signal.  */
 		if (TRAP(regs) == 0x0C00)
 			syscall_restart(regs, &ka);
@@ -571,7 +539,14 @@ int do_signal(sigset_t *oldset, struct p
 		if (current->thread.dabr)
 			set_dabr(current->thread.dabr);
 
-		return handle_signal(signr, &ka, &info, oldset, regs);
+		ret = handle_signal(signr, &ka, &info, oldset, regs);
+
+		/* If a signal was successfully delivered, the saved sigmask is in
+		   its frame, and we can clear the TIF_RESTORE_SIGMASK flag */
+		if (ret && test_thread_flag(TIF_RESTORE_SIGMASK))
+			clear_thread_flag(TIF_RESTORE_SIGMASK);
+
+		return ret;
 	}
 
 	if (TRAP(regs) == 0x0C00) {	/* System Call! */
@@ -587,6 +562,11 @@ int do_signal(sigset_t *oldset, struct p
 			regs->result = 0;
 		}
 	}
+	/* No signal to deliver -- put the saved sigmask back */
+	if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+		clear_thread_flag(TIF_RESTORE_SIGMASK);
+		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+	}
 
 	return 0;
 }
diff --git a/arch/powerpc/kernel/systbl.S b/arch/powerpc/kernel/systbl.S
index 989f628..70bfff2 100644
--- a/arch/powerpc/kernel/systbl.S
+++ b/arch/powerpc/kernel/systbl.S
@@ -321,3 +321,5 @@ SYSCALL(inotify_add_watch)
 SYSCALL(inotify_rm_watch)
 SYSCALL(spu_run)
 SYSCALL(spu_create)
+COMPAT_SYS(pselect6)
+COMPAT_SYS(ppoll)	
diff --git a/fs/compat.c b/fs/compat.c
index 8186341..51747b9 100644
--- a/include/asm-powerpc/thread_info.h
+++ b/include/asm-powerpc/thread_info.h
@@ -125,6 +125,7 @@ static inline struct thread_info *curren
 #define TIF_RESTOREALL		12	/* Restore all regs (implies NOERROR) */
 #define TIF_SAVE_NVGPRS		13	/* Save r14-r31 in signal frame */
 #define TIF_NOERROR		14	/* Force successful syscall return */
+#define TIF_RESTORE_SIGMASK	15	/* Restore signal mask in do_signal */
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
@@ -141,10 +142,12 @@ static inline struct thread_info *curren
 #define _TIF_RESTOREALL		(1<<TIF_RESTOREALL)
 #define _TIF_SAVE_NVGPRS	(1<<TIF_SAVE_NVGPRS)
 #define _TIF_NOERROR		(1<<TIF_NOERROR)
+#define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_SYSCALL_T_OR_A	(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP)
 
 #define _TIF_USER_WORK_MASK	(_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | \
-				 _TIF_NEED_RESCHED | _TIF_RESTOREALL)
+				 _TIF_NEED_RESCHED | _TIF_RESTOREALL | \
+				 _TIF_RESTORE_SIGMASK)
 #define _TIF_PERSYSCALL_MASK	(_TIF_RESTOREALL|_TIF_NOERROR|_TIF_SAVE_NVGPRS)
 
 #endif /* __KERNEL__ */
diff --git a/include/asm-powerpc/unistd.h b/include/asm-powerpc/unistd.h
index 19eaac3..a40cdff 100644
--- a/include/asm-powerpc/unistd.h
+++ b/include/asm-powerpc/unistd.h
@@ -298,8 +298,10 @@
 #define __NR_inotify_rm_watch	277
 #define __NR_spu_run		278
 #define __NR_spu_create		279
+#define __NR_pselect6		280
+#define __NR_ppoll		281
 
-#define __NR_syscalls		280
+#define __NR_syscalls		282
 
 #ifdef __KERNEL__
 #define __NR__exit __NR_exit

-- 
dwmw2

^ permalink raw reply related

* [PATCH] 3/3 Generic sys_rt_sigsuspend
From: David Woodhouse @ 2005-11-29  0:57 UTC (permalink / raw)
  To: linux-kernel; +Cc: akpm, linuxppc-dev, drepper
In-Reply-To: <1133225007.31573.86.camel@baythorne.infradead.org>

The TIF_RESTORE_SIGMASK flag allows us to have a generic implementation
of sys_rt_sigsuspend() instead of duplicating it for each architecture.
This provides such an implementation and makes arch/powerpc use it.

It also tidies up the ppc32 sys_sigsuspend() to use TIF_RESTORE_SIGMASK.

Signed-off-by: David Woodhouse <dwmw2@infradead.org>

--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -252,8 +252,7 @@ int do_signal(sigset_t *oldset, struct p
 /*
  * Atomically swap in the new signal mask, and wait for a signal.
  */
-long sys_sigsuspend(old_sigset_t mask, int p2, int p3, int p4, int p6, int p7,
-	       struct pt_regs *regs)
+long sys_sigsuspend(old_sigset_t mask)
 {
 	sigset_t saveset;
 
@@ -264,55 +263,10 @@ long sys_sigsuspend(old_sigset_t mask, i
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
 
-	regs->result = -EINTR;
-	regs->gpr[3] = EINTR;
-	regs->ccr |= 0x10000000;
-	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule();
-		if (do_signal(&saveset, regs)) {
-			set_thread_flag(TIF_RESTOREALL);
-			return 0;
-		}
-	}
-}
-
-long sys_rt_sigsuspend(
-#ifdef CONFIG_PPC64
-		compat_sigset_t __user *unewset,
-#else
-		sigset_t __user *unewset,
-#endif
-		size_t sigsetsize, int p3, int p4,
-		int p6, int p7, struct pt_regs *regs)
-{
-	sigset_t saveset, newset;
-
-	/* XXX: Don't preclude handling different sized sigset_t's.  */
-	if (sigsetsize != sizeof(sigset_t))
-		return -EINVAL;
-
-	if (get_sigset_t(&newset, unewset))
-		return -EFAULT;
-	sigdelsetmask(&newset, ~_BLOCKABLE);
-
-	spin_lock_irq(&current->sighand->siglock);
-	saveset = current->blocked;
-	current->blocked = newset;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-
-	regs->result = -EINTR;
-	regs->gpr[3] = EINTR;
-	regs->ccr |= 0x10000000;
-	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule();
-		if (do_signal(&saveset, regs)) {
-			set_thread_flag(TIF_RESTOREALL);
-			return 0;
-		}
-	}
+ 	current->state = TASK_INTERRUPTIBLE;
+ 	schedule();
+ 	set_thread_flag(TIF_RESTORE_SIGMASK);
+ 	return -ERESTARTNOHAND;
 }
 
 #ifdef CONFIG_PPC32
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index 5462bef..7a6f0f7 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -67,42 +67,6 @@ struct rt_sigframe {
 	char abigap[288];
 } __attribute__ ((aligned (16)));
 
-
-/*
- * Atomically swap in the new signal mask, and wait for a signal.
- */
-long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, int p3, int p4,
-		       int p6, int p7, struct pt_regs *regs)
-{
-	sigset_t saveset, newset;
-
-	/* XXX: Don't preclude handling different sized sigset_t's.  */
-	if (sigsetsize != sizeof(sigset_t))
-		return -EINVAL;
-
-	if (copy_from_user(&newset, unewset, sizeof(newset)))
-		return -EFAULT;
-	sigdelsetmask(&newset, ~_BLOCKABLE);
-
-	spin_lock_irq(&current->sighand->siglock);
-	saveset = current->blocked;
-	current->blocked = newset;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-
-	regs->result = -EINTR;
-	regs->gpr[3] = EINTR;
-	regs->ccr |= 0x10000000;
-	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule();
-		if (do_signal(&saveset, regs)) {
-			set_thread_flag(TIF_RESTOREALL);
-			return 0;
-		}
-	}
-}
-
 long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, unsigned long r5,
 		     unsigned long r6, unsigned long r7, unsigned long r8,
 		     struct pt_regs *regs)
--- a/include/asm-powerpc/unistd.h
+++ b/include/asm-powerpc/unistd.h
@@ -444,11 +446,13 @@ type name(type1 arg1, type2 arg2, type3 
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
+#define __ARCH_WANT_SYS_RT_SIGSUSPEND
 #ifdef CONFIG_PPC32
 #define __ARCH_WANT_OLD_STAT
 #endif
 #ifdef CONFIG_PPC64
 #define __ARCH_WANT_COMPAT_SYS_TIME
+#define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
 #endif
 
 /*
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -855,3 +855,31 @@ asmlinkage long compat_sys_stime(compat_
 }
 
 #endif /* __ARCH_WANT_COMPAT_SYS_TIME */
+
+#ifdef __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
+long compat_sys_rt_sigsuspend(compat_sigset_t __user *unewset, compat_size_t sigsetsize)
+{
+	sigset_t saveset, newset;
+	compat_sigset_t newset32;
+
+	/* XXX: Don't preclude handling different sized sigset_t's.  */
+	if (sigsetsize != sizeof(sigset_t))
+		return -EINVAL;
+
+	if (copy_from_user(&newset32, unewset, sizeof(compat_sigset_t)))
+		return -EFAULT;
+	sigset_from_compat(&newset, &newset32);
+	sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP));
+
+	spin_lock_irq(&current->sighand->siglock);
+	saveset = current->blocked;
+	current->blocked = newset;
+	recalc_sigpending();
+	spin_unlock_irq(&current->sighand->siglock);
+
+	current->state = TASK_INTERRUPTIBLE;
+	schedule();
+	set_thread_flag(TIF_RESTORE_SIGMASK);
+	return -ERESTARTNOHAND;
+}
+#endif /* __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND */
diff --git a/kernel/signal.c b/kernel/signal.c
index d7611f1..5e4c240 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -2623,6 +2623,32 @@ sys_pause(void)
 
 #endif
 
+#ifdef __ARCH_WANT_SYS_RT_SIGSUSPEND
+long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
+{
+	sigset_t saveset, newset;
+
+	/* XXX: Don't preclude handling different sized sigset_t's.  */
+	if (sigsetsize != sizeof(sigset_t))
+		return -EINVAL;
+
+	if (copy_from_user(&newset, unewset, sizeof(newset)))
+		return -EFAULT;
+	sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP));
+
+	spin_lock_irq(&current->sighand->siglock);
+	saveset = current->blocked;
+	current->blocked = newset;
+	recalc_sigpending();
+	spin_unlock_irq(&current->sighand->siglock);
+
+	current->state = TASK_INTERRUPTIBLE;
+	schedule();
+	set_thread_flag(TIF_RESTORE_SIGMASK);
+	return -ERESTARTNOHAND;
+}
+#endif /* __ARCH_WANT_SYS_RT_SIGSUSPEND */
+
 void __init signals_init(void)
 {
 	sigqueue_cachep =

-- 
dwmw2

^ permalink raw reply related

* Re: Which way to store log in flash on mpc8xx?
From: David Ho @ 2005-11-29  1:06 UTC (permalink / raw)
  To: Wolfgang Denk; +Cc: David Jander, linuxppc-embedded
In-Reply-To: <20050920180758.9020C353AB3@atlas.denx.de>

Hi, just catching up on this problem as I have another unit that
showed the same symptom.
My system looks like this

MPC852T
128Mbytes SDRAM
64Mbytes Flash

Flash partitions
2*1.25Mbytes partitions for Kernel
61.5Mbytes for rootfs and applications.
Remaining 1Mbyte for U-boot, u-boot env and spare.

I get that same problem as well.  kernel BUG at gc.c: 139

I have compiled Perl, Openssl, Openssh, etc running NFS so SDRAM is
definitely not the issue.

David: have you gotten any new insights since?

Regards,
David Ho


On 9/20/05, Wolfgang Denk <wd@denx.de> wrote:
> In message <200509201117.40454.david.jander@protonic.nl> you wrote:
> >
> > Is there something like memtest86 for linux-ppc (i.e. written in portab=
le C)?
>
> Yes, there is. Run the system with root file system mounted over NFS,
> and then put some load on the system, like  by  compiling  the  linux
> kernel  on  the  target.  Anything  else which adds DMA load does not
> hurt, either. In such a situation, with a lots of  context  switches,
> stress  on  the  memory  management  system  and having a lots of DMA
> traffic going on you may see some memory problems. Unfortunately none
> of the standard memory tests will catch thse, as  the  tests  usually
> provide  only plain read / write accesses, while the problems show up
> only in burst mode, i. e. when filling the caches and/or doing DMA.
>
> There is an attempt of a burst mode memory test in the  U-Boot  code,
> but  I  have to admit that I didn't work to show the exact problem on
> the system it was written for.
>
> > Hmm, but.... there is no data corruption. I have not seen one file on f=
lash
> > that had other data than intended, and that inspite of the GC freaking =
out.
>
> Maybe there is no corruption of the data in flash. But are  you  sure
> that  correct  data are loaded to and read from RAM? We had a similar
> problem on a board where data got corrupted only when doing a lot  of
> transfers flash->RAM.
>
> > That commit only changed 3 files, non of them directly related to jffs2=
 code,
>
> This is correct.
>
> > and only seemed to add support for FUJITSU flash chips. What am I missi=
ng?
> > MTD developers say that cvs from march-2005 _is_ broken, so there must =
be some
>
> Yes, of course it's broken. Like  all  computer  code.  There  are  a
> couple  of  known  issues  (especially  with NAND flash), but I don't
> think they could explain the type of problems you are seeing.
>
> Best regards,
>
> Wolfgang Denk
>
> --
> Software Engineering:  Embedded and Realtime Systems,  Embedded Linux
> Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
> Einstein argued that there must be simplified explanations of nature,
> because God is not capricious or arbitrary. No  such  faith  comforts
> the software engineer.                             - Fred Brooks, Jr.
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
>

^ permalink raw reply

* Re: PPC32 memory models
From: Paul Mackerras @ 2005-11-29  1:58 UTC (permalink / raw)
  To: Andy Whitcroft; +Cc: linuxppc-dev, Anton Blanchard
In-Reply-To: <438B5523.40903@shadowen.org>

Andy Whitcroft writes:

> Attached is a patch to enable FLATMEM and disable SPARSEMEM for PPC32
> which seems to be the working combinations.  It may well not be what is
> intended.  But I offer it to start discussions.

Sounds right.

>  config ARCH_SPARSEMEM_DEFAULT
>  	def_bool y
> -	depends on SMP && PPC_PSERIES
> +	depends on SMP && PPC_PSERIES && NUMA

Shouldn't this depend on ARCH_SPARSEMEM_ENABLE?

Paul.

^ permalink raw reply

* RE: Booting hangs after "Calibrating delay loop..."
From: Nguyen Thanh Binh @ 2005-11-29  3:20 UTC (permalink / raw)
  To: Autran, Guillaume, 'linuxppc-embedded@ozlabs.org'
In-Reply-To: <19EE6EC66973A5408FBE4CB7772F6F0A2105B2@ltnmail.xyplex.com>

[-- Attachment #1: Type: text/plain, Size: 1478 bytes --]

Hi Guillaume,

I have tried with your suggestions. But I did not find
arch/ppc/syslib/m8xx_setup.c as you said, instead I
found arch/ppc/kernel/m8xx_setup.c.
I have modified as you showed me, but the result was
always the same.
It means that boot hangs after printing "Calibrating
delay loop...".

You can find what I have modified in the attached
files 
(time.c in arch/ppc/kernel, m8xx_setup.c in
arch/ppc/kernel).

Do you have any idea?

Thank you very much.

Binh Nguyen

--- "Autran, Guillaume" <gautran@mrv.com> wrote:

> Hi,
> 
> I remember there is some race condition before
> calling set_dec(..) in time.c
> Basically, what happens is that the external
> decrementer is set way before
> the interrupt gets enabled. When we get to enable
> the interrupt, the
> decrementer value already reached 0 and wrapped
> arround (at least in our
> case). 
> The fix was to comment the line in:
> arch/ppc/kernel/time.c:330:
> set_dec(tb_ticks_per_jiffy);
> 
> And move it to:
> arch/ppc/syslib/m8xx_setup.c
> inside m8xx_calibrate_decr() just before setting up
> the interrupt for the
> decrementer.
> 
> In time.c, you may also need to initialize stamp =
> get_native_tbl(); as this
> variable may not have been initialized since you are
> using an external
> decrementer.
> 
> Try that...
> 
> Guillaume.
> 


		
___________________________________________________________ 
WIN ONE OF THREE YAHOO! VESPAS - Enter now! - http://uk.cars.yahoo.com/features/competitions/vespa.html

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 2251979003-time.c --]
[-- Type: text/x-c; name="time.c", Size: 16570 bytes --]

/*
 * Common time routines among all ppc machines.
 *
 * Written by Cort Dougan (cort@cs.nmt.edu) to merge
 * Paul Mackerras' version and mine for PReP and Pmac.
 * MPC8xx/MBX changes by Dan Malek (dmalek@jlc.net).
 *
 * First round of bugfixes by Gabriel Paubert (paubert@iram.es)
 * to make clock more stable (2.4.0-test5). The only thing
 * that this code assumes is that the timebases have been synchronized
 * by firmware on SMP and are never stopped (never do sleep
 * on SMP then, nap and doze are OK).
 *
 * TODO (not necessarily in this file):
 * - improve precision and reproducibility of timebase frequency
 * measurement at boot time.
 * - get rid of xtime_lock for gettimeofday (generic kernel problem
 * to be implemented on all architectures for SMP scalability and
 * eventually implementing gettimeofday without entering the kernel).
 * - put all time/clock related variables in a single structure
 * to minimize number of cache lines touched by gettimeofday()
 * - for astronomical applications: add a new function to get
 * non ambiguous timestamps even around leap seconds. This needs
 * a new timestamp format and a good name.
 *
 *
 * The following comment is partially obsolete (at least the long wait
 * is no more a valid reason):
 * Since the MPC8xx has a programmable interrupt timer, I decided to
 * use that rather than the decrementer.  Two reasons: 1.) the clock
 * frequency is low, causing 2.) a long wait in the timer interrupt
 *		while ((d = get_dec()) == dval)
 * loop.  The MPC8xx can be driven from a variety of input clocks,
 * so a number of assumptions have been made here because the kernel
 * parameter HZ is a constant.  We assume (correctly, today :-) that
 * the MPC8xx on the MBX board is driven from a 32.768 kHz crystal.
 * This is then divided by 4, providing a 8192 Hz clock into the PIT.
 * Since it is not possible to get a nice 100 Hz clock out of this, without
 * creating a software PLL, I have set HZ to 128.  -- Dan
 *
 * 1997-09-10  Updated NTP code according to technical memorandum Jan '96
 *             "A Kernel Model for Precision Timekeeping" by Dave Mills
 */

#include <linux/config.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/param.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/timex.h>
#include <linux/kernel_stat.h>
#include <linux/mc146818rtc.h>
#include <linux/time.h>
#include <linux/init.h>

#include <linux/trace.h>

#include <asm/segment.h>
#include <asm/io.h>
#include <asm/processor.h>
#include <asm/nvram.h>
#include <asm/cache.h>
#include <asm/8xx_immap.h>
#include <asm/machdep.h>

#include <asm/time.h>

#ifdef CONFIG_HIGH_RES_TIMERS
#include <linux/hrtime.h>
int hr_time_resolution = CONFIG_HIGH_RES_RESOLUTION;
int arch_to_nsec;
int nsec_to_arch;
unsigned volatile jiffies_seq = 0;
#endif

unsigned long disarm_decr[NR_CPUS];

extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz);

/* keep track of when we need to update the rtc */
time_t last_rtc_update;
extern rwlock_t xtime_lock;

/* The decrementer counts down by 128 every 128ns on a 601. */
#define DECREMENTER_COUNT_601	(1000000000 / HZ)

unsigned tb_ticks_per_jiffy;
unsigned tb_to_us;
unsigned tb_last_stamp;
extern unsigned long wall_jiffies;

static long time_offset;

spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;

EXPORT_SYMBOL(rtc_lock);

/* Timer interrupt helper function */
static inline int tb_delta(unsigned *jiffy_stamp) {
	int delta;
	if (__USE_RTC()) {
		delta = get_rtcl();
		if (delta < *jiffy_stamp) *jiffy_stamp -= 1000000000;
		delta -= *jiffy_stamp;
	} else {
		delta = get_tbl() - *jiffy_stamp;
	}
	return delta;
}

extern unsigned long prof_cpu_mask;
extern unsigned int * prof_buffer;
extern unsigned long prof_len;
extern unsigned long prof_shift;
extern char _stext;

static inline void ppc_do_profile (unsigned long nip)
{
	if (!prof_buffer)
		return;

	/*
	 * Only measure the CPUs specified by /proc/irq/prof_cpu_mask.
	 * (default is all CPUs.)
	 */
	if (!((1<<smp_processor_id()) & prof_cpu_mask))
		return;

	nip -= (unsigned long) &_stext;
	nip >>= prof_shift;
	/*
	 * Don't ignore out-of-bounds EIP values silently,
	 * put them into the last histogram slot, so if
	 * present, they will show up as a sharp peak.
	 */
	if (nip > prof_len-1)
		nip = prof_len-1;
	atomic_inc((atomic_t *)&prof_buffer[nip]);
}

#ifdef CONFIG_HIGH_RES_TIMERS
int hr_set_dec(unsigned count) {

	if (time_before(count, get_tbl()))
		/* missed it */
		return 1;

	/* ok, we've got a shot */
	set_dec(count - get_tbl());

	if (time_before_eq(get_tbl(), count))
		/* made it */
		return 0;

	/*
	 * Ohh, just missed it. If we were slow enough to have loaded the
	 * decrementer with a negative value, we're going to have to wait
	 * an awfully long time for another decrementer interrupt. So, we'll
	 * trigger an interrupt right now and let timer_interrupt recover and
	 * re-schedule the next jiffie to make up for our mistake.
	 */
	set_dec(1);
	return 1;

}
int schedule_hr_timer_int(unsigned ref_jiffies, int cycles) {

	unsigned temp_jiffies, seq;
	unsigned req_tb, next_jiffy_tb;
	int flags, ret;

	while (unlikely(cycles >= tb_ticks_per_jiffy)) {
		ref_jiffies++;
		cycles -= tb_ticks_per_jiffy;
	}

	do {
		int jiffies_diff;

		seq = jiffies_seq;
		temp_jiffies = jiffies;
		barrier();

		req_tb = tb_last_stamp + cycles;
		if (unlikely(jiffies_diff = ref_jiffies - temp_jiffies))
			req_tb += (jiffies_diff) * tb_ticks_per_jiffy;

		next_jiffy_tb = tb_last_stamp + tb_ticks_per_jiffy;

		barrier();
	} while (unlikely((seq != jiffies_seq) || (seq & 1)));

	if (time_before(ref_jiffies, temp_jiffies))
		return 1;

	/* paranoia */
	if (time_after(ref_jiffies, temp_jiffies) ||
	    time_after(req_tb, next_jiffy_tb))
		BUG();

	local_irq_save(flags);
	ret = hr_set_dec(req_tb);
	local_irq_restore(flags);

	return ret;
}
void __init hr_time_init(void)
{
	unsigned tb_ticks_per_sec;

	/*
	 * Use mulhwu_scale_factor to find the number ticks needed to equal
	 * 1,000,000 uSecs (1 Sec).
	 */
	tb_ticks_per_sec = mulhwu_scale_factor(tb_to_us, USEC_PER_SEC);

	arch_to_nsec = div_sc_n(HR_TIME_SCALE_NSEC, NSEC_PER_SEC,
				tb_ticks_per_sec);
	nsec_to_arch = div_sc_n(HR_TIME_SCALE_CYCLES, tb_ticks_per_sec,
				NSEC_PER_SEC);

	printk("hr_time_init: arch_to_nsec = %u, nsec_to_arch = %u\n",
		arch_to_nsec, nsec_to_arch);
}
#endif
/*
 * timer_interrupt - gets called when the decrementer overflows,
 * with interrupts disabled.
 * We set it up to overflow again in 1/HZ seconds.
 */
int timer_interrupt(struct pt_regs * regs)
{
	int next_dec;
	unsigned long cpu = smp_processor_id();
	unsigned jiffy_stamp = last_jiffy_stamp(cpu);
#ifdef CONFIG_HIGH_RES_TIMERS
	int hr_tick = 1;
#endif
	extern void do_IRQ(struct pt_regs *);

	if (atomic_read(&ppc_n_lost_interrupts) != 0)
		do_IRQ(regs);

	TRACE_TRAP_ENTRY(regs->trap, instruction_pointer(regs));

	hardirq_enter(cpu);
	
	while ((next_dec = tb_ticks_per_jiffy - tb_delta(&jiffy_stamp)) < 0) {
		jiffy_stamp += tb_ticks_per_jiffy;
		if (!user_mode(regs))
			ppc_do_profile(instruction_pointer(regs));
		if (unlikely(!heartbeat_count(cpu)--) 
				&& heartbeat_reset(cpu)) {
			ppc_md.heartbeat();
			heartbeat_count(cpu) = heartbeat_reset(cpu);
		}
#ifdef CONFIG_HIGH_RES_TIMERS
		hr_tick = 0;
#endif
	  	if (cpu)
			continue;

		/* We are in an interrupt, no need to save/restore flags */
		write_lock(&xtime_lock);
		tb_last_stamp = jiffy_stamp;
#ifdef CONFIG_HIGH_RES_TIMERS
		jiffies_seq++;
#endif
		do_timer(regs);
#ifdef CONFIG_HIGH_RES_TIMERS
		jiffies_seq++;
#endif

		/*
		 * update the rtc when needed, this should be performed on the
		 * right fraction of a second. Half or full second ?
		 * Full second works on mk48t59 clocks, others need testing.
		 * Note that this update is basically only used through
		 * the adjtimex system calls. Setting the HW clock in
		 * any other way is a /dev/rtc and userland business.
		 * This is still wrong by -0.5/+1.5 jiffies because of the
		 * timer interrupt resolution and possible delay, but here we
		 * hit a quantization limit which can only be solved by higher
		 * resolution timers and decoupling time management from timer
		 * interrupts. This is also wrong on the clocks
		 * which require being written at the half second boundary.
		 * We should have an rtc call that only sets the minutes and
		 * seconds like on Intel to avoid problems with non UTC clocks.
		 */
		if ( ppc_md.set_rtc_time && (time_status & STA_UNSYNC) == 0 &&
		     xtime.tv_sec - last_rtc_update >= 659 &&
		     abs(xtime.tv_usec - (1000000-1000000/HZ)) < 500000/HZ &&
		     jiffies - wall_jiffies == 1) {
		  	if (ppc_md.set_rtc_time(xtime.tv_sec+1 + time_offset) == 0)
				last_rtc_update = xtime.tv_sec+1;
			else
				/* Try again one minute later */
				last_rtc_update += 60;
		}
		write_unlock(&xtime_lock);
	}
	if (!disarm_decr[cpu])
		set_dec(next_dec);
#ifdef CONFIG_HIGH_RES_TIMERS
	if (hr_tick)
		do_hr_timer_int();
#endif
	last_jiffy_stamp(cpu) = jiffy_stamp;

#ifdef CONFIG_SMP
	smp_local_timer_interrupt(regs);
#endif /* CONFIG_SMP */

	hardirq_exit(cpu);

	if (softirq_pending(cpu))
		do_softirq();

	TRACE_TRAP_EXIT();

	return 1; /* lets ret_from_int know we can do checks */
}

/*
 * This version of gettimeofday has microsecond resolution.
 */
void do_gettimeofday(struct timeval *tv)
{
	unsigned long flags;
	unsigned delta, lost_ticks, usec, sec;

	read_lock_irqsave(&xtime_lock, flags);
	sec = xtime.tv_sec;
	usec = xtime.tv_usec;
	delta = tb_ticks_since(tb_last_stamp);
#ifdef CONFIG_SMP
	/* As long as timebases are not in sync, gettimeofday can only
	 * have jiffy resolution on SMP.
	 */
	if (!smp_tb_synchronized)
		delta = 0;
#endif /* CONFIG_SMP */
	lost_ticks = jiffies - wall_jiffies;
	read_unlock_irqrestore(&xtime_lock, flags);

	usec += mulhwu(tb_to_us, tb_ticks_per_jiffy * lost_ticks + delta);
	while (usec >= 1000000) {
	  	sec++;
		usec -= 1000000;
	}
	tv->tv_sec = sec;
	tv->tv_usec = usec;
}

void do_settimeofday(struct timeval *tv)
{
	unsigned long flags;
	int tb_delta, new_usec, new_sec;

	write_lock_irqsave(&xtime_lock, flags);
	/* Updating the RTC is not the job of this code. If the time is
	 * stepped under NTP, the RTC will be update after STA_UNSYNC
	 * is cleared. Tool like clock/hwclock either copy the RTC
	 * to the system time, in which case there is no point in writing
	 * to the RTC again, or write to the RTC but then they don't call
	 * settimeofday to perform this operation. Note also that
	 * we don't touch the decrementer since:
	 * a) it would lose timer interrupt synchronization on SMP
	 * (if it is working one day)
	 * b) it could make one jiffy spuriously shorter or longer
	 * which would introduce another source of uncertainty potentially
	 * harmful to relatively short timers.
	 */

	/* This works perfectly on SMP only if the tb are in sync but 
	 * guarantees an error < 1 jiffy even if they are off by eons,
	 * still reasonable when gettimeofday resolution is 1 jiffy.
	 */
	tb_delta = tb_ticks_since(last_jiffy_stamp(smp_processor_id()));
	tb_delta += (jiffies - wall_jiffies) * tb_ticks_per_jiffy;
	new_sec = tv->tv_sec;
	new_usec = tv->tv_usec - mulhwu(tb_to_us, tb_delta);
	while (new_usec <0) {
		new_sec--; 
		new_usec += 1000000;
	}
	xtime.tv_usec = new_usec;
	xtime.tv_sec = new_sec;

	wall_to_monotonic.tv_sec += xtime.tv_sec - tv->tv_sec;
	wall_to_monotonic.tv_nsec += (xtime.tv_usec - tv->tv_usec) * 
		NSEC_PER_USEC;

	if (wall_to_monotonic.tv_nsec > NSEC_PER_SEC) {
		wall_to_monotonic.tv_nsec -= NSEC_PER_SEC;
		wall_to_monotonic.tv_sec++;
	}
	if (wall_to_monotonic.tv_nsec < 0) {
		wall_to_monotonic.tv_nsec += NSEC_PER_SEC;
		wall_to_monotonic.tv_sec--;
	}

	/* In case of a large backwards jump in time with NTP, we want the 
	 * clock to be updated as soon as the PLL is again in lock.
	 */
	last_rtc_update = new_sec - 658;

	time_adjust = 0;                /* stop active adjtime() */
	time_status |= STA_UNSYNC;
	time_state = TIME_ERROR;        /* p. 24, (a) */
	time_maxerror = NTP_PHASE_LIMIT;
	time_esterror = NTP_PHASE_LIMIT;
	write_unlock_irqrestore(&xtime_lock, flags);
	clock_was_set();
}

/* This function is only called on the boot processor */
void __init time_init(void)
{
	time_t sec, old_sec;
	unsigned old_stamp, stamp, elapsed;

	stamp = get_native_tbl(); /* Binh 25/11/05 */


        if (ppc_md.time_init != NULL)
                time_offset = ppc_md.time_init();

	if (__USE_RTC()) {
		/* 601 processor: dec counts down by 128 every 128ns */
		tb_ticks_per_jiffy = DECREMENTER_COUNT_601;
		/* mulhwu_scale_factor(1000000000, 1000000) is 0x418937 */
		tb_to_us = 0x418937;
        } else {
                ppc_md.calibrate_decr();
	}
#ifdef CONFIG_HIGH_RES_TIMERS
	hr_time_init();
#endif

	/* Now that the decrementer is calibrated, it can be used in case the 
	 * clock is stuck, but the fact that we have to handle the 601
	 * makes things more complex. Repeatedly read the RTC until the
	 * next second boundary to try to achieve some precision.  If there
	 * is no RTC, we still need to set tb_last_stamp and
	 * last_jiffy_stamp(cpu 0) to the current stamp.
	 */
	stamp = get_native_tbl();
	if (ppc_md.get_rtc_time) {
		sec = ppc_md.get_rtc_time();
		elapsed = 0;
		do {
			old_stamp = stamp; 
			old_sec = sec;
			stamp = get_native_tbl();
			if (__USE_RTC() && stamp < old_stamp)
				old_stamp -= 1000000000;
			elapsed += stamp - old_stamp;
			sec = ppc_md.get_rtc_time();
		} while ( sec == old_sec && elapsed < 2*HZ*tb_ticks_per_jiffy);
		if (sec == old_sec)
			printk("Warning: real time clock seems stuck!\n");
		xtime.tv_sec = sec;
		wall_to_monotonic.tv_sec = -sec;
		xtime.tv_usec = 0;
		wall_to_monotonic.tv_nsec = 0;

		/* No update now, we just read the time from the RTC ! */
		last_rtc_update = xtime.tv_sec;
	}

	last_jiffy_stamp(0) = tb_last_stamp = stamp;

	/* Not exact, but the timer interrupt takes care of this */
	/* set_dec(tb_ticks_per_jiffy); Binh 25/11/05 */

	/* If platform provided a timezone (pmac), we correct the time
	 * using do_sys_settimeofday() which in turn calls warp_clock()
	 */
        if (time_offset) {
        	struct timezone tz;
        	tz.tz_minuteswest = -time_offset / 60;
        	tz.tz_dsttime = 0;
        	do_sys_settimeofday(NULL, &tz);
        }
}

#define FEBRUARY		2
#define	STARTOFTIME		1970
#define SECDAY			86400L
#define SECYR			(SECDAY * 365)
#define	leapyear(y)		((!(y % 4) && (y % 100)) || !(y % 400))
#define	days_in_year(a) 	(leapyear(a) ? 366 : 365)
#define	days_in_month(a) 	(month_days[(a) - 1])

static int month_days[12] = {
	31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};

void to_tm(int tim, struct rtc_time * tm)
{
	register int i;
	register long hms, day, gday;

	gday = day = tim / SECDAY;
	hms = tim % SECDAY;

	/* Hours, minutes, seconds are easy */
	tm->tm_hour = hms / 3600;
	tm->tm_min = (hms % 3600) / 60;
	tm->tm_sec = (hms % 3600) % 60;

	/* Number of years in days */
	for (i = STARTOFTIME; day >= days_in_year(i); i++)
		day -= days_in_year(i);
	tm->tm_year = i;

	/* Number of months in days left */
	if (leapyear(tm->tm_year))
		days_in_month(FEBRUARY) = 29;
	for (i = 1; day >= days_in_month(i); i++)
		day -= days_in_month(i);
	days_in_month(FEBRUARY) = 28;
	tm->tm_mon = i;

	/* Days are what is left over (+1) from all that. */
	tm->tm_mday = day + 1;

	/*
	 * Determine the day of week. Jan. 1, 1970 was a Thursday.
	 */
	tm->tm_wday = (gday + 4) % 7;
}

/* Auxiliary function to compute scaling factors */
/* Actually the choice of a timebase running at 1/4 the of the bus
 * frequency giving resolution of a few tens of nanoseconds is quite nice.
 * It makes this computation very precise (27-28 bits typically) which
 * is optimistic considering the stability of most processor clock
 * oscillators and the precision with which the timebase frequency
 * is measured but does not harm.
 */
unsigned mulhwu_scale_factor(unsigned inscale, unsigned outscale) {
	unsigned mlt=0, tmp, err;
	/* No concern for performance, it's done once: use a stupid
	 * but safe and compact method to find the multiplier.
	 */
	for (tmp = 1U<<31; tmp != 0; tmp >>= 1) {
		if (mulhwu(inscale, mlt|tmp) < outscale) mlt|=tmp;
	}
	/* We might still be off by 1 for the best approximation.
	 * A side effect of this is that if outscale is too large
	 * the returned value will be zero.
	 * Many corner cases have been checked and seem to work,
	 * some might have been forgotten in the test however.
	 */
	err = inscale*(mlt+1);
	if (err <= inscale/2) mlt++;
	return mlt;
}


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: 980338913-m8xx_setup.c --]
[-- Type: text/x-c; name="m8xx_setup.c", Size: 13503 bytes --]

/*
 *  linux/arch/ppc/kernel/setup.c
 *
 *  Copyright (C) 1995  Linus Torvalds
 *  Adapted from 'alpha' version by Gary Thomas
 *  Modified by Cort Dougan (cort@cs.nmt.edu)
 *  Modified for MBX using prep/chrp/pmac functions by Dan (dmalek@jlc.net)
 *  Further modified for generic 8xx by Dan.
 */

/*
 * bootup setup stuff..
 */

#include <linux/config.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/stddef.h>
#include <linux/unistd.h>
#include <linux/ptrace.h>
#include <linux/slab.h>
#include <linux/user.h>
#include <linux/a.out.h>
#include <linux/tty.h>
#include <linux/major.h>
#include <linux/interrupt.h>
#include <linux/reboot.h>
#include <linux/init.h>
#include <linux/blk.h>
#include <linux/ioport.h>
#include <linux/console.h>
#include <linux/bootmem.h>
#include <linux/ide.h>
#include <linux/seq_file.h>

#include <asm/mmu.h>
#include <asm/processor.h>
#include <asm/residual.h>
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/mpc8xx.h>
#include <asm/8xx_immap.h>
#include <asm/machdep.h>
#include <asm/bootinfo.h>
#include <asm/time.h>
#include <asm/i8259.h>

#include "ppc8xx_pic.h"

extern int i8259_pic_irq_offset; /* defined in arch/ppc/kernel/i8259.c */

static int m8xx_set_rtc_time(unsigned long time);
static unsigned long m8xx_get_rtc_time(void);
void m8xx_calibrate_decr(void);

unsigned char __res[sizeof(bd_t)];

extern void m8xx_ide_init(void);
extern void m8xx_find_bridges(void);

extern unsigned long find_available_memory(void);
extern void m8xx_cpm_reset(uint);
extern void rpxfb_alloc_pages(void);

void __init
m8xx_setup_arch(void)
{
	int	cpm_page;

	cpm_page = (int) alloc_bootmem_pages(PAGE_SIZE);

	/* Reset the Communication Processor Module.
	*/
	m8xx_cpm_reset(cpm_page);

#ifdef CONFIG_FB_RPX
	rpxfb_alloc_pages();
#endif

#ifdef notdef
	ROOT_DEV = to_kdev_t(0x0301); /* hda1 */
#endif

#ifdef CONFIG_BLK_DEV_INITRD
#if 0
	ROOT_DEV = to_kdev_t(0x0200); /* floppy */
	rd_prompt = 1;
	rd_doload = 1;
	rd_image_start = 0;
#endif
#if 0	/* XXX this may need to be updated for the new bootmem stuff,
	   or possibly just deleted (see set_phys_avail() in init.c).
	   - paulus. */
	/* initrd_start and size are setup by boot/head.S and kernel/head.S */
	if ( initrd_start )
	{
		if (initrd_end > *memory_end_p)
		{
			printk("initrd extends beyond end of memory "
			       "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
			       initrd_end,*memory_end_p);
			initrd_start = 0;
		}
	}
#endif
#endif

#ifdef CONFIG_PCI
	m8xx_find_bridges();
#endif
}

void
abort(void)
{
#ifdef CONFIG_XMON
	xmon(0);
#endif
	machine_restart(NULL);

	/* not reached */
	for (;;);
}

/* A place holder for time base interrupts, if they are ever enabled. */
void timebase_interrupt(int irq, void * dev, struct pt_regs * regs)
{
	printk ("timebase_interrupt()\n");
}

/* The decrementer counts at the system (internal) clock frequency divided by
 * sixteen, or external oscillator divided by four.  We force the processor
 * to use system clock divided by sixteen.
 */
void __init m8xx_calibrate_decr(void)
{
	bd_t	*binfo = (bd_t *)__res;
	int freq, fp, divisor;

	/* Unlock the SCCR. */
	((volatile immap_t *)IMAP_ADDR)->im_clkrstk.cark_sccrk = ~KAPWR_KEY;
	((volatile immap_t *)IMAP_ADDR)->im_clkrstk.cark_sccrk = KAPWR_KEY;

	/* Force all 8xx processors to use divide by 16 processor clock. */
	((volatile immap_t *)IMAP_ADDR)->im_clkrst.car_sccr |= 0x02000000;

	/* Processor frequency is MHz.
	 * The value 'fp' is the number of decrementer ticks per second.
	 */
	fp = binfo->bi_intfreq / 16;
	freq = fp*60;	/* try to make freq/1e6 an integer */
        divisor = 60;
        printk("Decrementer Frequency = %d/%d\n", freq, divisor);
        tb_ticks_per_jiffy = freq / HZ / divisor;
	tb_to_us = mulhwu_scale_factor(freq / divisor, 1000000);
#ifdef CONFIG_ILATENCY
	{
		extern long ticks_per_usec;
		ticks_per_usec = freq / divisor / 1000000;
	}
#endif

	/* Perform some more timer/timebase initialization.  This used
	 * to be done elsewhere, but other changes caused it to get
	 * called more than once....that is a bad thing.
	 *
	 * First, unlock all of the registers we are going to modify.
	 * To protect them from corruption during power down, registers
	 * that are maintained by keep alive power are "locked".  To
	 * modify these registers we have to write the key value to
	 * the key location associated with the register.
	 * Some boards power up with these unlocked, while others
	 * are locked.  Writing anything (including the unlock code?)
	 * to the unlocked registers will lock them again.  So, here
	 * we guarantee the registers are locked, then we unlock them
	 * for our use.
	 */
	((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_tbscrk = ~KAPWR_KEY;
	((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_rtcsck = ~KAPWR_KEY;
	((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_tbk    = ~KAPWR_KEY;
	((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_tbscrk =  KAPWR_KEY;
	((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_rtcsck =  KAPWR_KEY;
	((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_tbk    =  KAPWR_KEY;

	/* Disable the RTC one second and alarm interrupts. */
	((volatile immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc &=
						~(RTCSC_SIE | RTCSC_ALE);
	/* Enable the RTC */
	((volatile immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc |=
						(RTCSC_RTF | RTCSC_RTE);

	/* Binh 25/11/05 */
	   set_dec(tb_ticks_per_jiffy); 
	

	/* Enabling the decrementer also enables the timebase interrupts
	 * (or from the other point of view, to get decrementer interrupts
	 * we have to enable the timebase).  The decrementer interrupt
	 * is wired into the vector table, nothing to do here for that.
	 */
	((volatile immap_t *)IMAP_ADDR)->im_sit.sit_tbscr =
				((mk_int_int_mask(DEC_INTERRUPT) << 8) |
					 (TBSCR_TBF | TBSCR_TBE));

	if (request_irq(DEC_INTERRUPT, timebase_interrupt, 0, "tbint",
				NULL) != 0)
		panic("Could not allocate timer IRQ!");
}

/* The RTC on the MPC8xx is an internal register.
 * We want to protect this during power down, so we need to unlock,
 * modify, and re-lock.
 */
static int
m8xx_set_rtc_time(unsigned long time)
{
	((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_rtck = KAPWR_KEY;
	((volatile immap_t *)IMAP_ADDR)->im_sit.sit_rtc = time;
	((volatile immap_t *)IMAP_ADDR)->im_sitk.sitk_rtck = ~KAPWR_KEY;
	return(0);
}

static unsigned long
m8xx_get_rtc_time(void)
{
	/* Get time from the RTC. */
	return((unsigned long)(((immap_t *)IMAP_ADDR)->im_sit.sit_rtc));
}

static void
m8xx_restart(char *cmd)
{
	__volatile__ unsigned char dummy;
	uint	msr;

	cli();
	((immap_t *)IMAP_ADDR)->im_clkrst.car_plprcr |= 0x00000080;

	/* Clear the ME bit in MSR to cause checkstop on machine check
	*/
	__asm__("mfmsr %0" : "=r" (msr) );
	msr &= ~0x1000;
	__asm__("mtmsr %0" : : "r" (msr) );

	dummy = ((immap_t *)IMAP_ADDR)->im_clkrst.res[0];
	printk("Restart failed\n");
	while(1);
}

static void
m8xx_power_off(void)
{
   m8xx_restart(NULL);
}

static void
m8xx_halt(void)
{
   m8xx_restart(NULL);
}


static int
m8xx_show_percpuinfo(struct seq_file *m, int i)
{
	bd_t	*bp;

	bp = (bd_t *)__res;

	seq_printf(m, "clock\t\t: %dMHz\n"
		   "bus clock\t: %dMHz\n",
		   bp->bi_intfreq / 1000000,
		   bp->bi_busfreq / 1000000);

	return 0;
}

/* Initialize the internal interrupt controller.  The number of
 * interrupts supported can vary with the processor type, and the
 * 82xx family can have up to 64.
 * External interrupts can be either edge or level triggered, and
 * need to be initialized by the appropriate driver.
 */
static void __init
m8xx_init_IRQ(void)
{
	int i;
	void cpm_interrupt_init(void);

	for (i = SIU_IRQ_OFFSET ; i < SIU_IRQ_OFFSET + NR_SIU_INTS ; i++)
		irq_desc[i].handler = &ppc8xx_pic;

	cpm_interrupt_init();

#if defined(CONFIG_PCI)
	for (i = I8259_IRQ_OFFSET ; i < I8259_IRQ_OFFSET + NR_8259_INTS ; i++)
		irq_desc[i].handler = &i8259_pic;

	i8259_pic_irq_offset = I8259_IRQ_OFFSET;
	i8259_init(0);

	/* The i8259 cascade interrupt must be level sensitive. */
	((immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel &= 
		~(0x80000000 >> ISA_BRIDGE_INT);

	if (request_irq(ISA_BRIDGE_INT, mbx_i8259_action, 0, "i8259 cascade",
				NULL) != 0)
		panic("Could not allocate 8259 IRQ!");
#endif	/* CONFIG_PCI */
}

/* -------------------------------------------------------------------- */

/*
 * This is a big hack right now, but it may turn into something real
 * someday.
 *
 * For the 8xx boards (at this time anyway), there is nothing to initialize
 * associated the PROM.  Rather than include all of the prom.c
 * functions in the image just to get prom_init, all we really need right
 * now is the initialization of the physical memory region.
 */
static unsigned long __init
m8xx_find_end_of_memory(void)
{
	bd_t	*binfo;
	extern unsigned char __res[];

	binfo = (bd_t *)__res;

	return binfo->bi_memsize;
}

#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
#if !defined(CONFIG_BLK_DEV_MPC8xx_IDE)
/*
 * IDE stuff.
 * These functions are to support an IDE device on the mpc8xx pcmcia interface
 * when using the pcmcia-cs module to manage the pcmcia interface.
 */
static int
m8xx_ide_check_region(ide_ioreg_t from, unsigned int extent)
{
	return check_region(from, extent);
}

static void
m8xx_ide_request_region(ide_ioreg_t from, unsigned int extent, const char *name)
{
	request_region(from, extent, name);
	return;
}

static void
m8xx_ide_release_region(ide_ioreg_t from, unsigned int extent)
{
	release_region(from, extent);
	return;
}

static int
m8xx_ide_default_irq(ide_ioreg_t base)
{
	return SIU_LEVEL4;
}

static ide_ioreg_t
m8xx_ide_default_io_base(int index)
{
	return index;
}
#endif	/* if !defined(CONFIG_BLK_DEV_MPC8xx_IDE) */
#endif	/* if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) */

/*
 * Now map in some of the I/O space that is generically needed
 * or shared with multiple devices.
 * All of this fits into the same 4Mbyte region, so it only
 * requires one page table page.  (or at least it used to  -- paulus)
 */
static void __init
m8xx_map_io(void)
{
        io_block_mapping(IMAP_ADDR, IMAP_ADDR, IMAP_SIZE, _PAGE_IO);
#ifdef CONFIG_MBX
        io_block_mapping(NVRAM_ADDR, NVRAM_ADDR, NVRAM_SIZE, _PAGE_IO);
        io_block_mapping(MBX_CSR_ADDR, MBX_CSR_ADDR, MBX_CSR_SIZE, _PAGE_IO);
        io_block_mapping(PCI_CSR_ADDR, PCI_CSR_ADDR, PCI_CSR_SIZE, _PAGE_IO);

#if !defined(CONFIG_PCI)
	/* Map some of the PCI/ISA I/O space to get the IDE interface.
	*/
        io_block_mapping(PCI_ISA_IO_ADDR, PCI_ISA_IO_ADDR, 0x4000, _PAGE_IO);
        io_block_mapping(PCI_IDE_ADDR, PCI_IDE_ADDR, 0x4000, _PAGE_IO);
#endif
#endif
#if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC)
	io_block_mapping(RPX_CSR_ADDR, RPX_CSR_ADDR, RPX_CSR_SIZE, _PAGE_IO);
#if !defined(CONFIG_PCI)
	io_block_mapping(_IO_BASE,_IO_BASE,_IO_BASE_SIZE, _PAGE_IO);
#endif
#endif
#if defined(CONFIG_HTDMSOUND) || defined(CONFIG_RPXTOUCH) || defined(CONFIG_FB_RPX)
	io_block_mapping(HIOX_CSR_ADDR, HIOX_CSR_ADDR, HIOX_CSR_SIZE, _PAGE_IO);
#endif
#ifdef CONFIG_FADS
	io_block_mapping(BCSR_ADDR, BCSR_ADDR, BCSR_SIZE, _PAGE_IO);
	io_block_mapping(_IO_BASE,_IO_BASE,_IO_BASE_SIZE, _PAGE_IO);
#endif
#ifdef CONFIG_PCI
        io_block_mapping(PCI_ISA_IO_ADDR, PCI_ISA_IO_ADDR, PCI_ISA_IO_SIZE,
			 _PAGE_IO);
        io_block_mapping(PCI_CSR_ADDR, PCI_CSR_ADDR, PCI_CSR_SIZE, _PAGE_IO);
#endif
}

void __init
platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
		unsigned long r6, unsigned long r7)
{
	parse_bootinfo(find_bootinfo());

	if ( r3 )
		memcpy( (void *)__res,(void *)(r3+KERNELBASE), sizeof(bd_t) );

#ifdef CONFIG_BLK_DEV_INITRD
	/* take care of initrd if we have one */
	if ( r4 )
	{
		initrd_start = r4 + KERNELBASE;
		initrd_end = r5 + KERNELBASE;
	}
#endif /* CONFIG_BLK_DEV_INITRD */
	/* take care of cmd line */
	if ( r6 )
	{
		*(char *)(r7+KERNELBASE) = 0;
		strcpy(cmd_line, (char *)(r6+KERNELBASE));
	}

#ifdef CONFIG_PCI
	isa_io_base = _IO_BASE;
	isa_mem_base = _ISA_MEM_BASE;
	pci_dram_offset = PCI_DRAM_OFFSET;
#endif

	ppc_md.setup_arch		= m8xx_setup_arch;
	ppc_md.show_percpuinfo		= m8xx_show_percpuinfo;
	ppc_md.irq_cannonicalize	= NULL;
	ppc_md.init_IRQ			= m8xx_init_IRQ;
	ppc_md.get_irq			= m8xx_get_irq;
	ppc_md.init			= NULL;

	ppc_md.restart			= m8xx_restart;
	ppc_md.power_off		= m8xx_power_off;
	ppc_md.halt			= m8xx_halt;

	ppc_md.time_init		= NULL;
	ppc_md.set_rtc_time		= m8xx_set_rtc_time;
	ppc_md.get_rtc_time		= m8xx_get_rtc_time;
	ppc_md.calibrate_decr		= m8xx_calibrate_decr;

	ppc_md.find_end_of_memory	= m8xx_find_end_of_memory;
	ppc_md.setup_io_mappings	= m8xx_map_io;

	ppc_md.kbd_setkeycode		= NULL;
	ppc_md.kbd_getkeycode		= NULL;
	ppc_md.kbd_translate		= NULL;
	ppc_md.kbd_unexpected_up	= NULL;
	ppc_md.kbd_leds			= NULL;
	ppc_md.kbd_init_hw		= NULL;
	ppc_md.ppc_kbd_sysrq_xlate	= NULL;

#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
#if defined(CONFIG_BLK_DEV_MPC8xx_IDE)
	m8xx_ide_init();
#else
	ppc_ide_md.ide_request_region 	= m8xx_ide_request_region;
	ppc_ide_md.ide_release_region 	= m8xx_ide_release_region;
	ppc_ide_md.ide_check_region 	= m8xx_ide_check_region;
	ppc_ide_md.default_irq		= m8xx_ide_default_irq;
	ppc_ide_md.default_io_base	= m8xx_ide_default_io_base;
	/* The default ppc_ide_md.ide_init_hwif function is sufficient. */
#endif	/* if defined(CONFIG_BLK_DEV_MPC8xx_IDE) */
#endif	/* if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) */

#ifdef CONFIG_DUMMY_CONSOLE
	conswitchp = &dummy_con;
#endif
}

^ permalink raw reply

* Re: [PATCH] ppc32 8xx: Added setbitsXX/clrbitsXX macro for read-modify-write operations
From: Paul Mackerras @ 2005-11-29  4:56 UTC (permalink / raw)
  To: Vitaly Bordug; +Cc: linuxppc-devel list, linuxppc-embedded list
In-Reply-To: <438B238F.9070804@ru.mvista.com>

Vitaly Bordug writes:

> This adds setbitsXX/clrbitsXX macro for read-modify-write operations
> and converts the 8xx core and drivers to use it.

Your mailer has munged the whitespace in the patch, unfortunately.

> +	clrbits32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr,(1 << cpm_vec));

This needs a space after the comma.

Regards,
Paul.

^ permalink raw reply

* Re: [PATCH] 3/3 Generic sys_rt_sigsuspend
From: Mika Penttilä @ 2005-11-29  5:18 UTC (permalink / raw)
  To: David Woodhouse; +Cc: akpm, linuxppc-dev, linux-kernel, drepper
In-Reply-To: <1133225852.31573.115.camel@baythorne.infradead.org>

David Woodhouse wrote:

>The TIF_RESTORE_SIGMASK flag allows us to have a generic implementation
>of sys_rt_sigsuspend() instead of duplicating it for each architecture.
>This provides such an implementation and makes arch/powerpc use it.
>
>It also tidies up the ppc32 sys_sigsuspend() to use TIF_RESTORE_SIGMASK.
>
>Signed-off-by: David Woodhouse <dwmw2@infradead.org>
>  
>
> 
>+#ifdef __ARCH_WANT_SYS_RT_SIGSUSPEND
>+long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
>+{
>+	sigset_t saveset, newset;
>+
>+	/* XXX: Don't preclude handling different sized sigset_t's.  */
>+	if (sigsetsize != sizeof(sigset_t))
>+		return -EINVAL;
>+
>+	if (copy_from_user(&newset, unewset, sizeof(newset)))
>+		return -EFAULT;
>+	sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP));
>+
>+	spin_lock_irq(&current->sighand->siglock);
>+	saveset = current->blocked;
>+	current->blocked = newset;
>+	recalc_sigpending();
>+	spin_unlock_irq(&current->sighand->siglock);
>+
>+	current->state = TASK_INTERRUPTIBLE;
>+	schedule();
>+	set_thread_flag(TIF_RESTORE_SIGMASK);
>+	return -ERESTARTNOHAND;
>+}
>+#endif /* __ARCH_WANT_SYS_RT_SIGSUSPEND */
>+
>  
>
You are not setting saved_sigmask here. And shouldn't it return -EINTR?

Thanks,
Mika

^ permalink raw reply

* Re: PowerBook5,8 - TrackPad update
From: Parag Warudkar @ 2005-11-29  6:11 UTC (permalink / raw)
  To: Michael Hanselmann; +Cc: linuxppc-dev, debian-powerpc, linux-kernel
In-Reply-To: <20051129000615.GA20843@hansmi.ch>

[-- Attachment #1: Type: text/plain, Size: 1055 bytes --]


On Nov 28, 2005, at 7:06 PM, Michael Hanselmann wrote:

> The product ID I have, 0x0215, was in none of the
> available drivers and the data format is somewhat different

Hi Michael

Is yours the 15" model or the 17"? Mine is 15" and the product id is  
0x0214.

> You find my hacked version attached -- be aware that in its current  
> form
> it will not work with any touchpad except 0x0215.

I haven't looked at your changes completely yet but are you saying it  
works? Meaning mouse
moves properly?

Also I find it strange that your model requires 80 bytes ATP_DATASIZE  
- mine isn't happy
at all with anything less than 256. The less number of sensors you  
defined is again a puzzle.

> As far as I see it, all methods can be built into one driver. Is there
> already someone working on combining them?

If the format of the data is same (which looks like it is with your  
model) then yes, but in my case
the data arrives is 64 byte blocks - there are 4 of them in one  
transfer, each a reading on it's own.

Hmm. More confusion.

Thanks

Parag

[-- Attachment #2: Type: text/html, Size: 2386 bytes --]

^ permalink raw reply

* Re: do_initcalls
From: Gil Madar @ 2005-11-29  6:27 UTC (permalink / raw)
  To: linuxppc-embedded; +Cc: Jaap de Jong
In-Reply-To: <6915D0AE8B9047438F320B466AE30FDD152557@nvs0003.nedap.local>

On Friday 25 November 2005 09:41, Jaap de Jong wrote:
>Hi,
>
>In linux-2.4.25/init/main.c this function is called:
>        
>        static void __init do_initcalls(void)
>        {
>                initcall_t *call;
>        
>                call = &__initcall_start;
>                do {
>                        (*call)();
>                        call++
>                } while (call < &__initcall_end);
>
>                /* Make sure there is no pending stuff from the initcall sequence */
>                flush_scheduled_tasks();
>        }
>
>What is supposed to be in the section __initcall_start ..
>__initcall_end?
>Mine is empty and therefore causing trouble...
>System.map:
>        //
>        //
>        c00ad880 A __initcall_end
>        c00ad880 A __initcall_start
>        //
>        //
>
>The fix is obvious... But I guess I've missed something else?
>
>Thanks in advance,
>        Jaap de Jong
Hi Jaap,

This is what I got on kernel 2.4.25:

c016a890 A __initcall_start
c016a890 A __setup_end
c016a890 t __initcall_abi_register_sysctl
c016a894 t __initcall_spawn_ksoftirqd
c016a898 t __initcall_uid_cache_init
c016a89c t __initcall_kmem_cpucache_init
c016a8a0 t __initcall_kswapd_init
c016a8a4 t __initcall_init_tmpfs
c016a8a8 t __initcall_bdflush_init
c016a8ac t __initcall_init_pipe_fs
c016a8b0 t __initcall_fasync_init
c016a8b4 t __initcall_filelock_init
c016a8b8 t __initcall_dnotify_init
c016a8bc t __initcall_init_script_binfmt
c016a8c0 t __initcall_init_elf_binfmt
c016a8c4 t __initcall_init_ramfs_fs
c016a8c8 t __initcall_init_devfs_fs
c016a8cc t __initcall_init_nfs_fs
c016a8d0 t __initcall_nfsd_init
c016a8d4 t __initcall_init_smb_fs
c016a8d8 t __initcall_init_devpts_fs
c016a8dc t __initcall_chr_dev_init
c016a8e0 t __initcall_raw_init
c016a8e4 t __initcall_device_init
c016a8e8 t __initcall_rd_init
c016a8ec t __initcall_loop_init
c016a8f0 t __initcall_ppp_init
c016a8f4 t __initcall_ppp_async_init
c016a8f8 t __initcall_deflate_init
c016a8fc t __initcall_netlink_proto_init
c016a900 t __initcall_inet_init
c016a904 t __initcall_ip_auto_config
c016a908 t __initcall_af_unix_init
c016a90c t __initcall_packet_init
c016a910 t __initcall_init_sunrpc
c016a914 A __initcall_end

HTH,
Gil

^ permalink raw reply

* SPI and USB on MPC8272
From: Mike Rapoport @ 2005-11-29  6:42 UTC (permalink / raw)
  To: linuxppc-embedded list

Hi list,
I have a custom board based on MPC8272. I have a problem enabling the 
SPI and USB interfaces of the MPC8272 at the same time.
I'm running linux 2.6.12.3 with "custom" USB host driver. I tried to add 
the SPI driver present in denx linuxppc_2.4_devel git tree. When I 
enable the SPI driver first the USB host does not pass USB devices 
enumeration. When I enable the SPI driver after the USB, it hangs on 
while writing to CPCR.
Each driver works when used separately.
Does anybody have a clue why could it happen?
<http://source.denx.net/cgi-bin/gitweb.cgi?p=linuxppc_2_4_devel.git;a=summary> 


-- 
Sincerely yours,
Mike Rapoport

^ permalink raw reply

* Re: PowerBook5,8 - TrackPad update
From: Michael Hanselmann @ 2005-11-29  7:50 UTC (permalink / raw)
  To: Parag Warudkar; +Cc: linuxppc-dev, debian-powerpc, linux-kernel
In-Reply-To: <68465DDA-053F-4A85-9204-549E830B2269@comcast.net>

[-- Attachment #1: Type: text/plain, Size: 1184 bytes --]

Hello Parag

On Tue, Nov 29, 2005 at 01:11:00AM -0500, Parag Warudkar wrote:
> Is yours the 15" model or the 17"? Mine is 15" and the product id is  
> 0x0214.

It's the 15" one.

> I haven't looked at your changes completely yet but are you saying it
> works? Meaning mouse moves properly?

The mouse moves, but slowly. Maybe something isn't correct yet, but it
works basically.

> Also I find it strange that your model requires 80 bytes ATP_DATASIZE
> - mine isn't happy at all with anything less than 256. The less number
> of sensors you  defined is again a puzzle.

That are points I need to investigate further.

> If the format of the data is same (which looks like it is with your
> model) then yes, but in my case the data arrives is 64 byte blocks -
> there are 4 of them in one  transfer, each a reading on it's own.

I get 256 bytes in each transfer as well, but didn't look at the bytes
behind 40. Maybe that'll help to make it more responsive.

> Hmm. More confusion.

Oh yes. Why does Apple ship the basically same PowerBook with different
Touchpads?

Greets,
Michael

-- 
Gentoo Linux Developer using m0n0wall | http://hansmi.ch/

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* Re: Problem running kernel 2.6.14 (DENX) on MPC866
From: Wolfgang Denk @ 2005-11-29  8:08 UTC (permalink / raw)
  To: gil-ad; +Cc: linuxppc-embedded
In-Reply-To: <200511290147.05220.gil-ad@myrealbox.com>

In message <200511290147.05220.gil-ad@myrealbox.com> you wrote:
> 
> I load linux from u-boot, and manage to go all the way until the call to cpu_idle() from rest_init().
> The system claims mounts a root file system over NFS. Sniffer logs and host logs support this claim.
> If I do a while ( 1 ) printk( whatever ), just before cpu_idle(), the system continues to run.
> If I let it call cpu_idle(), the system hangs.

For 8xx you could / should use the kernel.org tree. We don't use  2.6
on 8xx yet.

> U-Boot 1.1.3 (Nov 22 2005 - 00:26:43)
> 
> CPU:   unknown MPC86x (0x08010004) at 133 MHz: 16 kB I-Cache 8 kB D-Cache FEC present
>          *** Warning: CPU Core has Silicon Bugs -- Check the Errata ***

You should fix this.

> Monitor Command Prompt:>setenv gatewayip 10.0.0.138;setenv ethaddr 00:01:02:03:04:05; setenv console ttyCPM0,38400n8; setenv

You use an illegal MAC address; please read the FAQ, especially
http://www.denx.de/wiki/view/DULG/EthernetDoesNotWork  and
http://www.denx.de/wiki/view/DULG/WhereCanIGetAValidMACAddress


Best regards,

Wolfgang Denk

-- 
Software Engineering:  Embedded and Realtime Systems,  Embedded Linux
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
How many seconds are there in a year? If I tell you there are 3.155 x
10^7, you won't even try to remember it. On the other hand, who could
forget that, to within half a percent, pi seconds is  a  nanocentury.
                                               -- Tom Duff, Bell Labs

^ permalink raw reply

* Re: SPI and USB on MPC8272
From: Wolfgang Denk @ 2005-11-29  8:10 UTC (permalink / raw)
  To: Mike Rapoport; +Cc: linuxppc-embedded list
In-Reply-To: <438BF854.1040408@compulab.co.il>

In message <438BF854.1040408@compulab.co.il> you wrote:
>
> I'm running linux 2.6.12.3 with "custom" USB host driver. I tried to add 
...
> <http://source.denx.net/cgi-bin/gitweb.cgi?p=linuxppc_2_4_devel.git;a=summary> 

What has our 2.4.25 source tree to do with your 2.6.12.3 kernel?

Best regards,

Wolfgang Denk

-- 
Software Engineering:  Embedded and Realtime Systems,  Embedded Linux
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
Lispers are among  the  best  grads  of  the  Sweep-It-Under-Someone-
Else's-Carpet  School of Simulated Simplicity. [Was that sufficiently
incendiary? :-)]  - Larry Wall in <1992Jan10.201804.11926@netlabs.com

^ permalink raw reply

* Re: SPI and USB on MPC8272
From: Mike Rapoport @ 2005-11-29  8:17 UTC (permalink / raw)
  To: Wolfgang Denk; +Cc: linuxppc-embedded list
In-Reply-To: <20051129081052.77DA1353F54@atlas.denx.de>

Wolfgang Denk wrote:

>In message <438BF854.1040408@compulab.co.il> you wrote:
>  
>
>>I'm running linux 2.6.12.3 with "custom" USB host driver. I tried to add 
>>    
>>
>...
>  
>
>><http://source.denx.net/cgi-bin/gitweb.cgi?p=linuxppc_2_4_devel.git;a=summary> 
>>    
>>
>
>What has our 2.4.25 source tree to do with your 2.6.12.3 kernel?
>  
>

Dear Wolfgang,
I've used the cpm_spi.[ch] from your 2.4.25 tree with my 2.6.12.3 
kernel. As for the URL it sneaked it by mistake.

>Best regards,
>
>Wolfgang Denk
>
>  
>


-- 
Sincerely yours,
Mike Rapoport
-----------------------------------------------------------------
CompuLab Ltd.
MALAT Bldg., Technion, Haifa, ISRAEL
Mailing address: P.O. Box 66, Nesher 36770, ISRAEL
Tel: 972-4-8290146
Fax: 972-4-8325251
Web: http://www.compulab.co.il

^ permalink raw reply

* RE: Problem running kernel 2.6.14 (DENX) on MPC866
From: Gil Madar @ 2005-11-29  8:41 UTC (permalink / raw)
  To: 'Wolfgang Denk', gil-ad; +Cc: linuxppc-embedded


Thanks for your reply Wolfgang!

	From: Wolfgang Denk [mailto:wd@denx.de]
	Sent: Tuesday, November 29, 2005 10:09 AM

	> 
	> I load linux from u-boot, and manage to go all the way until the
call to cpu_idle() from rest_init().
	> The system claims mounts a root file system over NFS. Sniffer logs
and host logs support this claim.
	> If I do a while ( 1 ) printk( whatever ), just before cpu_idle(),
the system continues to run.
	> If I let it call cpu_idle(), the system hangs.
	
	For 8xx you could / should use the kernel.org tree. We don't use
2.6
	on 8xx yet.

I will try that. 

	> U-Boot 1.1.3 (Nov 22 2005 - 00:26:43)
	> 
	> CPU:   unknown MPC86x (0x08010004) at 133 MHz: 16 kB I-Cache 8 kB
D-Cache FEC present
	>          *** Warning: CPU Core has Silicon Bugs -- Check the
Errata ***
	
	You should fix this.

OK.

	> Monitor Command Prompt:>setenv gatewayip 10.0.0.138;setenv ethaddr
00:01:02:03:04:05; setenv console ttyCPM0,38400n8; setenv
	
	You use an illegal MAC address; please read the FAQ, especially
	http://www.denx.de/wiki/view/DULG/EthernetDoesNotWork  and
	http://www.denx.de/wiki/view/DULG/WhereCanIGetAValidMACAddress

The ethernet address is ok. not mine, but legal ;-) I checked at
standards.ieee.org:
				 
00-01-02   (hex)		3COM CORPORATION
000102     (base 16)		3COM CORPORATION
				5400 Bayfront Plaza  - MS: 4220
				Santa Clara CA 95052
				UNITED STATES

Thanks for your time,
Gil

^ permalink raw reply

* Re: [PATCH] ppc32: Adds MPC885ADS, MPC866ADS and MPC8272ADS-specific platform stuff for fs_enet
From: Ingo Hornberger @ 2005-11-29 10:07 UTC (permalink / raw)
  To: linuxppc-embedded
In-Reply-To: <438B379B.6090904@ru.mvista.com>

Hi Vitaly,

OK, I don't really see the advantage of removing the identification
stuff, but perhaps I'm missing something. Was there any discussion in
the past that I've skipped while reading through the archive?

Because I found the identifcation code really nice. The only problem was
that my 8xx didn't support the SVR register.

regards,
	Ingo

On Mon, 2005-11-28 at 20:00 +0300, Vitaly Bordug wrote:
> Added proper ppc_sys identification and fs_platform_info's for MPC 885ADS, 866ADS and 
> 8272ADS. Assuming setbitsXX/clrbitsXX patch is applied.
> 
> 
> Signed-off-by: Vitaly Bordug <vbordug@ru.mvista.com>
> 
> ---
> Sincerely,
> Vitaly
> 
> 
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded

^ permalink raw reply

* Re: [PATCH] ppc32: Adds MPC885ADS, MPC866ADS and MPC8272ADS-specific platform stuff for fs_enet
From: Vitaly Bordug @ 2005-11-29 10:25 UTC (permalink / raw)
  To: ihornberger; +Cc: linuxppc-embedded
In-Reply-To: <1133258862.2664.13.camel@iho.sysgo.com>

Ingo Hornberger wrote:
> Hi Vitaly,
> 
> OK, I don't really see the advantage of removing the identification
> stuff, but perhaps I'm missing something. Was there any discussion in
> the past that I've skipped while reading through the archive?
> 
> Because I found the identifcation code really nice. The only problem was
> that my 8xx didn't support the SVR register.
> 
There was a number of discussions in this regard, which result finally that there no method to identify 8xx board 
uniquely just using board registers. Hence, we are making identification by board name; the names are presented in syslib/mpc8xx_sys.c.
You can see example in this patch.

> regards,
> 	Ingo
> 
> On Mon, 2005-11-28 at 20:00 +0300, Vitaly Bordug wrote:
>> Added proper ppc_sys identification and fs_platform_info's for MPC 885ADS, 866ADS and 
>> 8272ADS. Assuming setbitsXX/clrbitsXX patch is applied.
>>
>>
>> Signed-off-by: Vitaly Bordug <vbordug@ru.mvista.com>
>>
>> ---
>> Sincerely,
>> Vitaly
>>
>>
>> _______________________________________________
>> Linuxppc-embedded mailing list
>> Linuxppc-embedded@ozlabs.org
>> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
> 
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
> 
> 


-- 
Sincerely, 
Vitaly

^ permalink raw reply

* Re: PowerBook5,8 - TrackPad update
From: Johannes Berg @ 2005-11-29 10:38 UTC (permalink / raw)
  To: Michael Hanselmann
  Cc: linuxppc-dev, debian-powerpc, linux-kernel, Parag Warudkar
In-Reply-To: <20051129075047.GA26460@hansmi.ch>

Michael Hanselmann wrote:
>> I haven't looked at your changes completely yet but are you saying it
>> works? Meaning mouse moves properly?
>
> The mouse moves, but slowly. Maybe something isn't correct yet, but it
> works basically.

All this sounds almost like your touchpad is much more similar to the old
one. I'll most likely have access to a new powerbook within the next two
weeks, so I'll be able to take a look.

johannes

^ permalink raw reply

* Re: [PATCH] 3/3 Generic sys_rt_sigsuspend
From: David Woodhouse @ 2005-11-29 10:42 UTC (permalink / raw)
  To: Mika Penttilä; +Cc: akpm, linuxppc-dev, linux-kernel, drepper
In-Reply-To: <438BE48B.9060908@kolumbus.fi>

On Tue, 2005-11-29 at 07:18 +0200, Mika Penttilä wrote:
> You are not setting saved_sigmask here. 

Oops; well spotted. Thanks.

> And shouldn't it return -EINTR?

I believe not. The previous versions would loop until do_signal()
returned non-zero; i.e. until a signal was actually delivered.
By returning -ERESTARTNOHAND we achieve the same effect. If there's a
signal delivered, that gets magically converted to -EINTR, but if
there's no signal delivered, the syscall gets restarted.

diff -u b/kernel/compat.c b/kernel/compat.c
--- b/kernel/compat.c
+++ b/kernel/compat.c
@@ -859,7 +859,7 @@
 #ifdef __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
 long compat_sys_rt_sigsuspend(compat_sigset_t __user *unewset, compat_size_t sigsetsize)
 {
-	sigset_t saveset, newset;
+	sigset_t newset;
 	compat_sigset_t newset32;
 
 	/* XXX: Don't preclude handling different sized sigset_t's.  */
@@ -872,7 +872,7 @@
 	sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP));
 
 	spin_lock_irq(&current->sighand->siglock);
-	saveset = current->blocked;
+	current->saved_sigmask = current->blocked;
 	current->blocked = newset;
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
diff -u b/kernel/signal.c b/kernel/signal.c
--- b/kernel/signal.c
+++ b/kernel/signal.c
@@ -2626,7 +2626,7 @@
 #ifdef __ARCH_WANT_SYS_RT_SIGSUSPEND
 long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
 {
-	sigset_t saveset, newset;
+	sigset_t newset;
 
 	/* XXX: Don't preclude handling different sized sigset_t's.  */
 	if (sigsetsize != sizeof(sigset_t))
@@ -2637,7 +2637,7 @@
 	sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP));
 
 	spin_lock_irq(&current->sighand->siglock);
-	saveset = current->blocked;
+	current->saved_sigmask = current->blocked;
 	current->blocked = newset;
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);


-- 
dwmw2

^ permalink raw reply

* spi on mpc82xx
From: Thomas Arvanitis @ 2005-11-29 11:14 UTC (permalink / raw)
  To: linuxppc-embedded

Hi,

I was wondering what is the status for supporting spi devices with 2.6
on an mpc82xx device (I use an mpc8275). I checked and the kernel from
kernel.org does not include anything. Is there an spi bus
infrastructure (like i2c) coming any time soon, where one can add
support for specific chips, and then write a driver on top of that?
Or a plan for these things?

I found a patch for something like that, by Grant Likely, but I don't
know whether I should go that way.

I want to write a driver for controlling the micrel ks8995 ethernet
switch through spi. Should I just go for a self contained driver?

Thanks for you help,
-Thomas.

^ permalink raw reply

* error when compiling glibc on cygwin
From: Gao Bismar @ 2005-11-29 11:31 UTC (permalink / raw)
  To: linuxppc-embedded

I wanna complier a MPC860 crosstool on cygwin, and I use crosstool-0.38,but 
hit on error :

powerpc-860-linux-gnu-gcc  -nostdlib -nostartfiles -o 
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/iconv/iconv_prog 
 -Wl,-dynamic-linker=/lib/ld.so.1   
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/csu/crt1.o 
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/csu/crti.o 
`powerpc-860-linux-gnu-gcc  --print-file-name=crtbegin.o` 
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/iconv/iconv_prog.o 
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/iconv/iconv_charmap.o 
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/iconv/charmap.o 
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/iconv/charmap-dir.o 
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/iconv/linereader.o 
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/iconv/dummy-repertoire.o 
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/iconv/simple-hash.o 
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/iconv/xstrdup.o 
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/iconv/xmalloc.o 
 
-Wl,-rpath-link=/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc:/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/math:/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/elf:/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/dlfcn:/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/nss:/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/nis:/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/rt:/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/resolv:/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/crypt:/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/linuxthreads 
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc.so.6 
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc_nonshared.a 
-lgcc `powerpc-860-linux-gnu-gcc  --print-file-name=crtend.o` 
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/csu/crtn.o


/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/iconv/iconv_prog.o(.text+0x424): 
In function `main':: undefined reference to `close'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/iconv/iconv_prog.o(.text+0x498): 
In function `main':: undefined reference to `open'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/iconv/iconv_prog.o(.text+0x4f8): 
In function `main':: undefined reference to `__fxstat'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/iconv/iconv_prog.o(.text+0x530): 
In function `main':: undefined reference to `close'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/iconv/iconv_prog.o(.text+0x5bc): 
In function `main':: undefined reference to `close'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/iconv/iconv_prog.o(.text+0xb08): 
In function `process_fd':: undefined reference to `read'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/iconv/iconv_prog.o(.text+0xbbc): 
In function `process_fd':: undefined reference to `read'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/iconv/iconv_prog.o(.text+0x1044): 
In function `print_known_names':: undefined reference to `isatty'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/iconv/iconv_charmap.o(.text+0x108): 
In function `charmap_conversion':: undefined reference to `close'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/iconv/iconv_charmap.o(.text+0x170): 
In function `charmap_conversion':: undefined reference to `open'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/iconv/iconv_charmap.o(.text+0x1c8): 
In function `charmap_conversion':: undefined reference to `__fxstat'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/iconv/iconv_charmap.o(.text+0x200): 
In function `charmap_conversion':: undefined reference to `close'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/iconv/iconv_charmap.o(.text+0x288): 
In function `charmap_conversion':: undefined reference to `close'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/iconv/iconv_charmap.o(.text+0xa78): 
In function `process_fd':: undefined reference to `read'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/iconv/iconv_charmap.o(.text+0xb2c): 
In function `process_fd':: undefined reference to `read'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/iconv/charmap-dir.o(.text+0x254): 
In function `charmap_readdir':: undefined reference to `__xstat'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/iconv/charmap-dir.o(.text+0x388): 
In function `fopen_uncompressed':: undefined reference to `open'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/iconv/charmap-dir.o(.text+0x3a0): 
In function `fopen_uncompressed':: undefined reference to `__fxstat'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/iconv/charmap-dir.o(.text+0x3c8): 
In function `fopen_uncompressed':: undefined reference to `pipe'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/iconv/charmap-dir.o(.text+0x4b0): 
In function `fopen_uncompressed':: undefined reference to `close'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/iconv/charmap-dir.o(.text+0x4b8): 
In function `fopen_uncompressed':: undefined reference to `close'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/iconv/charmap-dir.o(.text+0x4dc): 
In function `fopen_uncompressed':: undefined reference to `close'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/iconv/charmap-dir.o(.text+0x4e4): 
In function `fopen_uncompressed':: undefined reference to `close'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/iconv/charmap-dir.o(.text+0x4ec): 
In function `fopen_uncompressed':: undefined reference to `close'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc.so.6: 
undefined reference to `__dup'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc.so.6: 
undefined reference to `utime'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc.so.6: 
undefined reference to `__libc_fcntl'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc.so.6: 
undefined reference to `__write'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc.so.6: 
undefined reference to `__getcwd'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc.so.6: 
undefined reference to `__dup2'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc.so.6: 
undefined reference to `__read'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc.so.6: 
undefined reference to `__unlink'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc.so.6: 
undefined reference to `__open'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc.so.6: 
undefined reference to `__libc_read'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc.so.6: 
undefined reference to `__xstat64'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc.so.6: 
undefined reference to `__lxstat'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc.so.6: 
undefined reference to `__chmod'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc.so.6: 
undefined reference to `__isatty'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc.so.6: 
undefined reference to `__statfs'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc.so.6: 
undefined reference to `__chdir'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc.so.6: 
undefined reference to `__readlink'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc.so.6: 
undefined reference to `__mkdir'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc.so.6: 
undefined reference to `__poll'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc.so.6: 
undefined reference to `__statvfs64'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc.so.6: 
undefined reference to `__pipe'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc.so.6: 
undefined reference to `__libc_open'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc.so.6: 
undefined reference to `__chown'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc.so.6: 
undefined reference to `__xmknod'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc.so.6: 
undefined reference to `__lseek'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc.so.6: 
undefined reference to `dup'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc.so.6: 
undefined reference to `atexit'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc.so.6: 
undefined reference to `__lxstat64'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc.so.6: 
undefined reference to `__ttyname_r'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc.so.6: 
undefined reference to `__libc_lseek'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc.so.6: 
undefined reference to `__rmdir'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc.so.6: 
undefined reference to `__fstatfs'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc.so.6: 
undefined reference to `__close'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc.so.6: 
undefined reference to `__fxstat64'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc.so.6: 
undefined reference to `__libc_write'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc.so.6: 
undefined reference to `__fcntl'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc.so.6: 
undefined reference to `__access'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc.so.6: 
undefined reference to `__open64'
/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/libc.so.6: 
undefined reference to `__fstatvfs64'
collect2: ld returned 1 exit status
make[2]: *** 
[/home/crosstool-0.38/build/powerpc-860-linux-gnu/gcc-2.95.3-glibc-2.2.3/build-glibc/iconv/iconv_prog] 
Error 1
make[2]: Leaving directory `/home/src/glibc-2.2.3/iconv'
make[1]: *** [iconv/others] Error 2
make[1]: Leaving directory `/home/src/glibc-2.2.3'
make: *** [all] Error 2

I use google to search the solution but faild. Many people hit on this 
error, but none solution was found.

Any help would be very much appreciated.

Thaks

                                                                     abutter

_________________________________________________________________
免费下载 MSN Explorer:   http://explorer.msn.com/lccn/  

^ permalink raw reply

* [PATCH] prevent stack corruption in call_prom_ret
From: Olaf Hering @ 2005-11-29 13:04 UTC (permalink / raw)
  To: Paul Mackeras, linuxppc-dev


Use the correct pointer to clear the memory of the return values,
to prevent stack corruption in the callers stackframe.

Signed-off-by: Olaf Hering <olh@suse.de>

 arch/powerpc/kernel/prom_init.c |    2 +-
 1 files changed, 1 insertion(+), 1 deletion(-)

Index: linux-2.6.15-rc3-olh/arch/powerpc/kernel/prom_init.c
===================================================================
--- linux-2.6.15-rc3-olh.orig/arch/powerpc/kernel/prom_init.c
+++ linux-2.6.15-rc3-olh/arch/powerpc/kernel/prom_init.c
@@ -265,7 +265,7 @@ static int __init call_prom_ret(const ch
 	va_end(list);
 
 	for (i = 0; i < nret; i++)
-		rets[nargs+i] = 0;
+		args.args[nargs+i] = 0;
 
 	if (enter_prom(&args, RELOC(prom_entry)) < 0)
 		return PROM_ERROR;
-- 
short story of a lazy sysadmin:
 alias appserv=wotan

^ permalink raw reply

* Re: Which way to store log in flash on mpc8xx?
From: David Jander @ 2005-11-29 14:17 UTC (permalink / raw)
  To: David Ho; +Cc: linuxppc-embedded
In-Reply-To: <4dd15d180511281706q388def30r42d3452c392bc92@mail.gmail.com>


Hi,

On Tuesday 29 November 2005 02:06, David Ho wrote:
> Hi, just catching up on this problem as I have another unit that
> showed the same symptom.
> My system looks like this
>
> MPC852T
> 128Mbytes SDRAM
> 64Mbytes Flash
>
> Flash partitions
> 2*1.25Mbytes partitions for Kernel
> 61.5Mbytes for rootfs and applications.
> Remaining 1Mbyte for U-boot, u-boot env and spare.
>
> I get that same problem as well.  kernel BUG at gc.c: 139
>
> I have compiled Perl, Openssl, Openssh, etc running NFS so SDRAM is
> definitely not the issue.

I have done almost the same (compiling Perl didn't succeed because of an 
out-of memory condition), and never had any other reason to suspect hardware 
problems.
After getting some advice from peoble at mtd-list, I switched to 2.6.14 for 
our new developments, and jffs2 seems a lot more stable now. I can only 
recommend you to consider switching. Besides consuming a little more RAM and 
Flash, 2.6.14 is miles ahead in terms of almost anything else, plus it's a 
bit faster on 8xx than 2.4.25!!
I have to warn you though, that it still seems not to be as rock-solid as one 
might want for an embedded system: We have a stress test running for a few 
weeks now simulating power-failures during writes to files on jffs2, and mtd 
has some occasional hick-ups. Those hick-ups seem to be far less serious than 
gc.c crashing, but we will have to take them into account in our application.
This is the situation: Sometimes the test application crashes giving a 
write-error on the mtd device, preceded by an error message from the 
mtd-driver (and jffs2, but the problem seems to come from mtd). The error 
message is like "MTD do_write_buffer(): software timeout", which normally 
means a flash programming error, most probably due to sector beeing worn out, 
but I don't think that is the case, since those problems began appearing 
quite early and went away all by them selves. Flash doesn't magically "fix" 
itself over time, does it?
Maybe it's a problem in the AMD flash driver (our device is a Spansion 
Mirror-bit S29GL256M11)

> David: have you gotten any new insights since?

Yes, see above.
Please keep me informed if you get to know something more about the 
problem ;-)
If you want more detail about what tests we are doing, and the problems we had 
so far, feel free to ask, or read my posts to the MTD list. Right now its 
46268 power-cycles and counting.

Greetings,

-- 
David Jander
Protonic Holland.

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox