From: Greg Kroah-Hartman Date: Tue, 3 Jan 2012 20:39:43 +0000 (-0800) Subject: 3.1-stable patches X-Git-Tag: v3.1.8~7 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b10e05f854d1c1b0217792374608954f93538cde;p=thirdparty%2Fkernel%2Fstable-queue.git 3.1-stable patches added patches: ipv4-flush-route-cache-after-change-accept_local.patch ipv4-reintroduce-route-cache-garbage-collector.patch ipv4-using-prefetch-requires-including-prefetch.h.patch ipv6-check-dest-prefix-length-on-original-route-not-copied-one-in-rt6_alloc_cow.patch llc-llc_cmsg_rcv-was-getting-called-after-sk_eat_skb.patch mqprio-avoid-panic-if-no-options-are-provided.patch net-add-a-flow_cache_flush_deferred-function.patch net-bpf_jit-fix-an-off-one-bug-in-x86_64-cond-jump-target.patch net-have-ipconfig-not-wait-if-no-dev-is-available.patch net-introduce-dst_nopeer-dst-flag.patch ppp-fix-pptp-double-release_sock-in-pptp_bind.patch sch_gred-should-not-use-gfp_kernel-while-holding-a-spinlock.patch sctp-do-not-account-for-sizeof-struct-sk_buff-in-estimated-rwnd.patch sctp-fix-incorrect-overflow-check-on-autoclose.patch sparc32-be-less-strict-in-matching-lo-part-of-relocation.patch sparc32-correct-the-return-value-of-memcpy.patch sparc32-remove-non-kernel-code-from-memcpy-implementation.patch sparc32-remove-uses-of-g7-in-memcpy-implementation.patch sparc64-fix-masking-and-shifting-in-vis-fpcmp-emulation.patch sparc64-fix-msiq-hv-call-ordering-in-pci_sun4v_msiq_build_irq.patch sparc64-patch-sun4v-code-sequences-properly-on-module-load.patch sparc-fix-handling-of-orig_i0-wrt.-debugging-when-restarting-syscalls.patch sparc-kill-custom-io_remap_pfn_range.patch --- diff --git a/queue-3.1/ipv4-flush-route-cache-after-change-accept_local.patch b/queue-3.1/ipv4-flush-route-cache-after-change-accept_local.patch new file mode 100644 index 00000000000..5fcbde09c1a --- /dev/null +++ b/queue-3.1/ipv4-flush-route-cache-after-change-accept_local.patch @@ -0,0 +1,43 @@ +From f9e1e7e59d60d85684a05366d282b6d6bdfdb687 Mon Sep 17 00:00:00 2001 +From: "Peter Pan(潘卫平)" +Date: Thu, 1 Dec 2011 15:47:06 +0000 +Subject: ipv4: flush route cache after change accept_local + + +From: Weiping Pan + +[ Upstream commit d01ff0a049f749e0bf10a35bb23edd012718c8c2 ] + +After reset ipv4_devconf->data[IPV4_DEVCONF_ACCEPT_LOCAL] to 0, +we should flush route cache, or it will continue receive packets with local +source address, which should be dropped. + +Signed-off-by: Weiping Pan +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/devinet.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/net/ipv4/devinet.c ++++ b/net/ipv4/devinet.c +@@ -1490,7 +1490,9 @@ static int devinet_conf_proc(ctl_table * + void __user *buffer, + size_t *lenp, loff_t *ppos) + { ++ int old_value = *(int *)ctl->data; + int ret = proc_dointvec(ctl, write, buffer, lenp, ppos); ++ int new_value = *(int *)ctl->data; + + if (write) { + struct ipv4_devconf *cnf = ctl->extra1; +@@ -1501,6 +1503,9 @@ static int devinet_conf_proc(ctl_table * + + if (cnf == net->ipv4.devconf_dflt) + devinet_copy_dflt_conf(net, i); ++ if (i == IPV4_DEVCONF_ACCEPT_LOCAL - 1) ++ if ((new_value == 0) && (old_value != 0)) ++ rt_cache_flush(net, 0); + } + + return ret; diff --git a/queue-3.1/ipv4-reintroduce-route-cache-garbage-collector.patch b/queue-3.1/ipv4-reintroduce-route-cache-garbage-collector.patch new file mode 100644 index 00000000000..74b334595ea --- /dev/null +++ b/queue-3.1/ipv4-reintroduce-route-cache-garbage-collector.patch @@ -0,0 +1,165 @@ +From 92023c1e1af8d82e1dce92a17efd0f1adffa2dd2 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Wed, 21 Dec 2011 15:47:16 -0500 +Subject: ipv4: reintroduce route cache garbage collector + + +From: Eric Dumazet + +[ Upstream commit 9f28a2fc0bd77511f649c0a788c7bf9a5fd04edb ] + +Commit 2c8cec5c10b (ipv4: Cache learned PMTU information in inetpeer) +removed IP route cache garbage collector a bit too soon, as this gc was +responsible for expired routes cleanup, releasing their neighbour +reference. + +As pointed out by Robert Gladewitz, recent kernels can fill and exhaust +their neighbour cache. + +Reintroduce the garbage collection, since we'll have to wait our +neighbour lookups become refcount-less to not depend on this stuff. + +Reported-by: Robert Gladewitz +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/route.c | 106 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 106 insertions(+) + +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -134,6 +134,9 @@ static int ip_rt_min_advmss __read_mostl + static int rt_chain_length_max __read_mostly = 20; + static int redirect_genid; + ++static struct delayed_work expires_work; ++static unsigned long expires_ljiffies; ++ + /* + * Interface to generic destination cache. + */ +@@ -831,6 +834,97 @@ static int has_noalias(const struct rtab + return ONE; + } + ++static void rt_check_expire(void) ++{ ++ static unsigned int rover; ++ unsigned int i = rover, goal; ++ struct rtable *rth; ++ struct rtable __rcu **rthp; ++ unsigned long samples = 0; ++ unsigned long sum = 0, sum2 = 0; ++ unsigned long delta; ++ u64 mult; ++ ++ delta = jiffies - expires_ljiffies; ++ expires_ljiffies = jiffies; ++ mult = ((u64)delta) << rt_hash_log; ++ if (ip_rt_gc_timeout > 1) ++ do_div(mult, ip_rt_gc_timeout); ++ goal = (unsigned int)mult; ++ if (goal > rt_hash_mask) ++ goal = rt_hash_mask + 1; ++ for (; goal > 0; goal--) { ++ unsigned long tmo = ip_rt_gc_timeout; ++ unsigned long length; ++ ++ i = (i + 1) & rt_hash_mask; ++ rthp = &rt_hash_table[i].chain; ++ ++ if (need_resched()) ++ cond_resched(); ++ ++ samples++; ++ ++ if (rcu_dereference_raw(*rthp) == NULL) ++ continue; ++ length = 0; ++ spin_lock_bh(rt_hash_lock_addr(i)); ++ while ((rth = rcu_dereference_protected(*rthp, ++ lockdep_is_held(rt_hash_lock_addr(i)))) != NULL) { ++ prefetch(rth->dst.rt_next); ++ if (rt_is_expired(rth)) { ++ *rthp = rth->dst.rt_next; ++ rt_free(rth); ++ continue; ++ } ++ if (rth->dst.expires) { ++ /* Entry is expired even if it is in use */ ++ if (time_before_eq(jiffies, rth->dst.expires)) { ++nofree: ++ tmo >>= 1; ++ rthp = &rth->dst.rt_next; ++ /* ++ * We only count entries on ++ * a chain with equal hash inputs once ++ * so that entries for different QOS ++ * levels, and other non-hash input ++ * attributes don't unfairly skew ++ * the length computation ++ */ ++ length += has_noalias(rt_hash_table[i].chain, rth); ++ continue; ++ } ++ } else if (!rt_may_expire(rth, tmo, ip_rt_gc_timeout)) ++ goto nofree; ++ ++ /* Cleanup aged off entries. */ ++ *rthp = rth->dst.rt_next; ++ rt_free(rth); ++ } ++ spin_unlock_bh(rt_hash_lock_addr(i)); ++ sum += length; ++ sum2 += length*length; ++ } ++ if (samples) { ++ unsigned long avg = sum / samples; ++ unsigned long sd = int_sqrt(sum2 / samples - avg*avg); ++ rt_chain_length_max = max_t(unsigned long, ++ ip_rt_gc_elasticity, ++ (avg + 4*sd) >> FRACT_BITS); ++ } ++ rover = i; ++} ++ ++/* ++ * rt_worker_func() is run in process context. ++ * we call rt_check_expire() to scan part of the hash table ++ */ ++static void rt_worker_func(struct work_struct *work) ++{ ++ rt_check_expire(); ++ schedule_delayed_work(&expires_work, ip_rt_gc_interval); ++} ++ + /* + * Perturbation of rt_genid by a small quantity [1..256] + * Using 8 bits of shuffling ensure we can call rt_cache_invalidate() +@@ -3176,6 +3270,13 @@ static ctl_table ipv4_route_table[] = { + .proc_handler = proc_dointvec_jiffies, + }, + { ++ .procname = "gc_interval", ++ .data = &ip_rt_gc_interval, ++ .maxlen = sizeof(int), ++ .mode = 0644, ++ .proc_handler = proc_dointvec_jiffies, ++ }, ++ { + .procname = "redirect_load", + .data = &ip_rt_redirect_load, + .maxlen = sizeof(int), +@@ -3385,6 +3486,11 @@ int __init ip_rt_init(void) + devinet_init(); + ip_fib_init(); + ++ INIT_DELAYED_WORK_DEFERRABLE(&expires_work, rt_worker_func); ++ expires_ljiffies = jiffies; ++ schedule_delayed_work(&expires_work, ++ net_random() % ip_rt_gc_interval + ip_rt_gc_interval); ++ + if (ip_rt_proc_init()) + printk(KERN_ERR "Unable to create route proc files\n"); + #ifdef CONFIG_XFRM diff --git a/queue-3.1/ipv4-using-prefetch-requires-including-prefetch.h.patch b/queue-3.1/ipv4-using-prefetch-requires-including-prefetch.h.patch new file mode 100644 index 00000000000..1a7124baa41 --- /dev/null +++ b/queue-3.1/ipv4-using-prefetch-requires-including-prefetch.h.patch @@ -0,0 +1,29 @@ +From 31a4e30815354c5e49eb20752409ef7c721fc6b0 Mon Sep 17 00:00:00 2001 +From: Stephen Rothwell +Date: Thu, 22 Dec 2011 17:03:29 +1100 +Subject: ipv4: using prefetch requires including prefetch.h + + +From: Stephen Rothwell + +[ Upstream commit b9eda06f80b0db61a73bd87c6b0eb67d8aca55ad ] + +Signed-off-by: Stephen Rothwell +Acked-by: Eric Dumazet +Acked-by: David Miller +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/route.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -91,6 +91,7 @@ + #include + #include + #include ++#include + #include + #include + #include diff --git a/queue-3.1/ipv6-check-dest-prefix-length-on-original-route-not-copied-one-in-rt6_alloc_cow.patch b/queue-3.1/ipv6-check-dest-prefix-length-on-original-route-not-copied-one-in-rt6_alloc_cow.patch new file mode 100644 index 00000000000..085474d3e3b --- /dev/null +++ b/queue-3.1/ipv6-check-dest-prefix-length-on-original-route-not-copied-one-in-rt6_alloc_cow.patch @@ -0,0 +1,37 @@ +From 5790d60ca9a1775b05c26da9f392a10234fd1ac7 Mon Sep 17 00:00:00 2001 +From: "David S. Miller" +Date: Tue, 13 Dec 2011 17:35:06 -0500 +Subject: ipv6: Check dest prefix length on original route not copied one in rt6_alloc_cow(). + + +From: "David S. Miller" + +[ Upstream commit bb3c36863e8001fc21a88bebfdead4da4c23e848 ] + +After commit 8e2ec639173f325977818c45011ee176ef2b11f6 ("ipv6: don't +use inetpeer to store metrics for routes.") the test in rt6_alloc_cow() +for setting the ANYCAST flag is now wrong. + +'rt' will always now have a plen of 128, because it is set explicitly +to 128 by ip6_rt_copy. + +So to restore the semantics of the test, check the destination prefix +length of 'ort'. + +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv6/route.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -725,7 +725,7 @@ static struct rt6_info *rt6_alloc_cow(co + int attempts = !in_softirq(); + + if (!(rt->rt6i_flags&RTF_GATEWAY)) { +- if (rt->rt6i_dst.plen != 128 && ++ if (ort->rt6i_dst.plen != 128 && + ipv6_addr_equal(&ort->rt6i_dst.addr, daddr)) + rt->rt6i_flags |= RTF_ANYCAST; + ipv6_addr_copy(&rt->rt6i_gateway, daddr); diff --git a/queue-3.1/llc-llc_cmsg_rcv-was-getting-called-after-sk_eat_skb.patch b/queue-3.1/llc-llc_cmsg_rcv-was-getting-called-after-sk_eat_skb.patch new file mode 100644 index 00000000000..16f3288b5f5 --- /dev/null +++ b/queue-3.1/llc-llc_cmsg_rcv-was-getting-called-after-sk_eat_skb.patch @@ -0,0 +1,57 @@ +From 76bcc2af1348ccf5a40421e1181f2547718a1e51 Mon Sep 17 00:00:00 2001 +From: Alex Juncu +Date: Thu, 15 Dec 2011 23:01:25 +0000 +Subject: llc: llc_cmsg_rcv was getting called after sk_eat_skb. + + +From: Alex Juncu + +[ Upstream commit 9cef310fcdee12b49b8b4c96fd8f611c8873d284 ] + +Received non stream protocol packets were calling llc_cmsg_rcv that used a +skb after that skb was released by sk_eat_skb. This caused received STP +packets to generate kernel panics. + +Signed-off-by: Alexandru Juncu +Signed-off-by: Kunjan Naik +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/llc/af_llc.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +--- a/net/llc/af_llc.c ++++ b/net/llc/af_llc.c +@@ -833,15 +833,15 @@ static int llc_ui_recvmsg(struct kiocb * + copied += used; + len -= used; + ++ /* For non stream protcols we get one packet per recvmsg call */ ++ if (sk->sk_type != SOCK_STREAM) ++ goto copy_uaddr; ++ + if (!(flags & MSG_PEEK)) { + sk_eat_skb(sk, skb, 0); + *seq = 0; + } + +- /* For non stream protcols we get one packet per recvmsg call */ +- if (sk->sk_type != SOCK_STREAM) +- goto copy_uaddr; +- + /* Partial read */ + if (used + offset < skb->len) + continue; +@@ -857,6 +857,12 @@ copy_uaddr: + } + if (llc_sk(sk)->cmsg_flags) + llc_cmsg_rcv(msg, skb); ++ ++ if (!(flags & MSG_PEEK)) { ++ sk_eat_skb(sk, skb, 0); ++ *seq = 0; ++ } ++ + goto out; + } + diff --git a/queue-3.1/mqprio-avoid-panic-if-no-options-are-provided.patch b/queue-3.1/mqprio-avoid-panic-if-no-options-are-provided.patch new file mode 100644 index 00000000000..655666e2fce --- /dev/null +++ b/queue-3.1/mqprio-avoid-panic-if-no-options-are-provided.patch @@ -0,0 +1,32 @@ +From 5e59a51890a259701718b9328560934407176b46 Mon Sep 17 00:00:00 2001 +From: Thomas Graf +Date: Thu, 22 Dec 2011 02:05:07 +0000 +Subject: mqprio: Avoid panic if no options are provided + + +From: Thomas Graf + +[ Upstream commit 7838f2ce36b6ab5c13ef20b1857e3bbd567f1759 ] + +Userspace may not provide TCA_OPTIONS, in fact tc currently does +so not do so if no arguments are specified on the command line. +Return EINVAL instead of panicing. + +Signed-off-by: Thomas Graf +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/sched/sch_mqprio.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/sched/sch_mqprio.c ++++ b/net/sched/sch_mqprio.c +@@ -106,7 +106,7 @@ static int mqprio_init(struct Qdisc *sch + if (!netif_is_multiqueue(dev)) + return -EOPNOTSUPP; + +- if (nla_len(opt) < sizeof(*qopt)) ++ if (!opt || nla_len(opt) < sizeof(*qopt)) + return -EINVAL; + + qopt = nla_data(opt); diff --git a/queue-3.1/net-add-a-flow_cache_flush_deferred-function.patch b/queue-3.1/net-add-a-flow_cache_flush_deferred-function.patch new file mode 100644 index 00000000000..f320efb7be6 --- /dev/null +++ b/queue-3.1/net-add-a-flow_cache_flush_deferred-function.patch @@ -0,0 +1,105 @@ +From fe032a0d6c13f13f66f7517ca72f2d8422333401 Mon Sep 17 00:00:00 2001 +From: Steffen Klassert +Date: Wed, 21 Dec 2011 16:48:08 -0500 +Subject: net: Add a flow_cache_flush_deferred function + + +From: Steffen Klassert + +[ Upstream commit c0ed1c14a72ca9ebacd51fb94a8aca488b0d361e ] + +flow_cach_flush() might sleep but can be called from +atomic context via the xfrm garbage collector. So add +a flow_cache_flush_deferred() function and use this if +the xfrm garbage colector is invoked from within the +packet path. + +Signed-off-by: Steffen Klassert +Acked-by: Timo Teräs +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + include/net/flow.h | 1 + + net/core/flow.c | 12 ++++++++++++ + net/xfrm/xfrm_policy.c | 18 ++++++++++++++---- + 3 files changed, 27 insertions(+), 4 deletions(-) + +--- a/include/net/flow.h ++++ b/include/net/flow.h +@@ -207,6 +207,7 @@ extern struct flow_cache_object *flow_ca + u8 dir, flow_resolve_t resolver, void *ctx); + + extern void flow_cache_flush(void); ++extern void flow_cache_flush_deferred(void); + extern atomic_t flow_cache_genid; + + #endif +--- a/net/core/flow.c ++++ b/net/core/flow.c +@@ -358,6 +358,18 @@ void flow_cache_flush(void) + put_online_cpus(); + } + ++static void flow_cache_flush_task(struct work_struct *work) ++{ ++ flow_cache_flush(); ++} ++ ++static DECLARE_WORK(flow_cache_flush_work, flow_cache_flush_task); ++ ++void flow_cache_flush_deferred(void) ++{ ++ schedule_work(&flow_cache_flush_work); ++} ++ + static int __cpuinit flow_cache_cpu_prepare(struct flow_cache *fc, int cpu) + { + struct flow_cache_percpu *fcp = per_cpu_ptr(fc->percpu, cpu); +--- a/net/xfrm/xfrm_policy.c ++++ b/net/xfrm/xfrm_policy.c +@@ -2276,8 +2276,6 @@ static void __xfrm_garbage_collect(struc + { + struct dst_entry *head, *next; + +- flow_cache_flush(); +- + spin_lock_bh(&xfrm_policy_sk_bundle_lock); + head = xfrm_policy_sk_bundles; + xfrm_policy_sk_bundles = NULL; +@@ -2290,6 +2288,18 @@ static void __xfrm_garbage_collect(struc + } + } + ++static void xfrm_garbage_collect(struct net *net) ++{ ++ flow_cache_flush(); ++ __xfrm_garbage_collect(net); ++} ++ ++static void xfrm_garbage_collect_deferred(struct net *net) ++{ ++ flow_cache_flush_deferred(); ++ __xfrm_garbage_collect(net); ++} ++ + static void xfrm_init_pmtu(struct dst_entry *dst) + { + do { +@@ -2420,7 +2430,7 @@ int xfrm_policy_register_afinfo(struct x + if (likely(dst_ops->neigh_lookup == NULL)) + dst_ops->neigh_lookup = xfrm_neigh_lookup; + if (likely(afinfo->garbage_collect == NULL)) +- afinfo->garbage_collect = __xfrm_garbage_collect; ++ afinfo->garbage_collect = xfrm_garbage_collect_deferred; + xfrm_policy_afinfo[afinfo->family] = afinfo; + } + write_unlock_bh(&xfrm_policy_afinfo_lock); +@@ -2514,7 +2524,7 @@ static int xfrm_dev_event(struct notifie + + switch (event) { + case NETDEV_DOWN: +- __xfrm_garbage_collect(dev_net(dev)); ++ xfrm_garbage_collect(dev_net(dev)); + } + return NOTIFY_DONE; + } diff --git a/queue-3.1/net-bpf_jit-fix-an-off-one-bug-in-x86_64-cond-jump-target.patch b/queue-3.1/net-bpf_jit-fix-an-off-one-bug-in-x86_64-cond-jump-target.patch new file mode 100644 index 00000000000..9b3d69a4940 --- /dev/null +++ b/queue-3.1/net-bpf_jit-fix-an-off-one-bug-in-x86_64-cond-jump-target.patch @@ -0,0 +1,37 @@ +From c9443fa522619b70cc9ea12d7f58e4cf633500c3 Mon Sep 17 00:00:00 2001 +From: Markus Kötter +Date: Sat, 17 Dec 2011 11:39:08 +0000 +Subject: net: bpf_jit: fix an off-one bug in x86_64 cond jump target + + +From: Markus Kötter + +[ Upstream commit a03ffcf873fe0f2565386ca8ef832144c42e67fa ] + +x86 jump instruction size is 2 or 5 bytes (near/long jump), not 2 or 6 +bytes. + +In case a conditional jump is followed by a long jump, conditional jump +target is one byte past the start of target instruction. + +Signed-off-by: Markus Kötter +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/net/bpf_jit_comp.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/arch/x86/net/bpf_jit_comp.c ++++ b/arch/x86/net/bpf_jit_comp.c +@@ -568,8 +568,8 @@ cond_branch: f_offset = addrs[i + filt + break; + } + if (filter[i].jt != 0) { +- if (filter[i].jf) +- t_offset += is_near(f_offset) ? 2 : 6; ++ if (filter[i].jf && f_offset) ++ t_offset += is_near(f_offset) ? 2 : 5; + EMIT_COND_JMP(t_op, t_offset); + if (filter[i].jf) + EMIT_JMP(f_offset); diff --git a/queue-3.1/net-have-ipconfig-not-wait-if-no-dev-is-available.patch b/queue-3.1/net-have-ipconfig-not-wait-if-no-dev-is-available.patch new file mode 100644 index 00000000000..f1adb9cdd0b --- /dev/null +++ b/queue-3.1/net-have-ipconfig-not-wait-if-no-dev-is-available.patch @@ -0,0 +1,40 @@ +From 2ec3264c7298c2326f33c482e787ec449638ed85 Mon Sep 17 00:00:00 2001 +From: Gerlando Falauto +Date: Mon, 19 Dec 2011 22:58:04 +0000 +Subject: net: have ipconfig not wait if no dev is available + + +From: Gerlando Falauto + +[ Upstream commit cd7816d14953c8af910af5bb92f488b0b277e29d ] + +previous commit 3fb72f1e6e6165c5f495e8dc11c5bbd14c73385c +makes IP-Config wait for carrier on at least one network device. + +Before waiting (predefined value 120s), check that at least one device +was successfully brought up. Otherwise (e.g. buggy bootloader +which does not set the MAC address) there is no point in waiting +for carrier. + +Cc: Micha Nelissen +Cc: Holger Brunck +Signed-off-by: Gerlando Falauto +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/ipconfig.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/net/ipv4/ipconfig.c ++++ b/net/ipv4/ipconfig.c +@@ -252,6 +252,10 @@ static int __init ic_open_devs(void) + } + } + ++ /* no point in waiting if we could not bring up at least one device */ ++ if (!ic_first_dev) ++ goto have_carrier; ++ + /* wait for a carrier on at least one device */ + start = jiffies; + while (jiffies - start < msecs_to_jiffies(CONF_CARRIER_TIMEOUT)) { diff --git a/queue-3.1/net-introduce-dst_nopeer-dst-flag.patch b/queue-3.1/net-introduce-dst_nopeer-dst-flag.patch new file mode 100644 index 00000000000..c79f692ba2d --- /dev/null +++ b/queue-3.1/net-introduce-dst_nopeer-dst-flag.patch @@ -0,0 +1,129 @@ +From 214c4df6cf051ae163659e2b9e5ee200eed06688 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Thu, 22 Dec 2011 04:15:53 +0000 +Subject: net: introduce DST_NOPEER dst flag + + +From: Eric Dumazet + +[ Upstream commit e688a604807647c9450f9c12a7cb6d027150a895 ] + +Chris Boot reported crashes occurring in ipv6_select_ident(). + +[ 461.457562] RIP: 0010:[] [] +ipv6_select_ident+0x31/0xa7 + +[ 461.578229] Call Trace: +[ 461.580742] +[ 461.582870] [] ? udp6_ufo_fragment+0x124/0x1a2 +[ 461.589054] [] ? ipv6_gso_segment+0xc0/0x155 +[ 461.595140] [] ? skb_gso_segment+0x208/0x28b +[ 461.601198] [] ? ipv6_confirm+0x146/0x15e +[nf_conntrack_ipv6] +[ 461.608786] [] ? nf_iterate+0x41/0x77 +[ 461.614227] [] ? dev_hard_start_xmit+0x357/0x543 +[ 461.620659] [] ? nf_hook_slow+0x73/0x111 +[ 461.626440] [] ? br_parse_ip_options+0x19a/0x19a +[bridge] +[ 461.633581] [] ? dev_queue_xmit+0x3af/0x459 +[ 461.639577] [] ? br_dev_queue_push_xmit+0x72/0x76 +[bridge] +[ 461.646887] [] ? br_nf_post_routing+0x17d/0x18f +[bridge] +[ 461.653997] [] ? nf_iterate+0x41/0x77 +[ 461.659473] [] ? br_flood+0xfa/0xfa [bridge] +[ 461.665485] [] ? nf_hook_slow+0x73/0x111 +[ 461.671234] [] ? br_flood+0xfa/0xfa [bridge] +[ 461.677299] [] ? +nf_bridge_update_protocol+0x20/0x20 [bridge] +[ 461.684891] [] ? nf_ct_zone+0xa/0x17 [nf_conntrack] +[ 461.691520] [] ? br_flood+0xfa/0xfa [bridge] +[ 461.697572] [] ? NF_HOOK.constprop.8+0x3c/0x56 +[bridge] +[ 461.704616] [] ? +nf_bridge_push_encap_header+0x1c/0x26 [bridge] +[ 461.712329] [] ? br_nf_forward_finish+0x8a/0x95 +[bridge] +[ 461.719490] [] ? +nf_bridge_pull_encap_header+0x1c/0x27 [bridge] +[ 461.727223] [] ? br_nf_forward_ip+0x1c0/0x1d4 [bridge] +[ 461.734292] [] ? nf_iterate+0x41/0x77 +[ 461.739758] [] ? __br_deliver+0xa0/0xa0 [bridge] +[ 461.746203] [] ? nf_hook_slow+0x73/0x111 +[ 461.751950] [] ? __br_deliver+0xa0/0xa0 [bridge] +[ 461.758378] [] ? NF_HOOK.constprop.4+0x56/0x56 +[bridge] + +This is caused by bridge netfilter special dst_entry (fake_rtable), a +special shared entry, where attaching an inetpeer makes no sense. + +Problem is present since commit 87c48fa3b46 (ipv6: make fragment +identifications less predictable) + +Introduce DST_NOPEER dst flag and make sure ipv6_select_ident() and +__ip_select_ident() fallback to the 'no peer attached' handling. + +Reported-by: Chris Boot +Tested-by: Chris Boot +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + include/net/dst.h | 1 + + net/bridge/br_netfilter.c | 2 +- + net/ipv4/route.c | 4 ++-- + net/ipv6/ip6_output.c | 2 +- + 4 files changed, 5 insertions(+), 4 deletions(-) + +--- a/include/net/dst.h ++++ b/include/net/dst.h +@@ -53,6 +53,7 @@ struct dst_entry { + #define DST_NOHASH 0x0008 + #define DST_NOCACHE 0x0010 + #define DST_NOCOUNT 0x0020 ++#define DST_NOPEER 0x0040 + + short error; + short obsolete; +--- a/net/bridge/br_netfilter.c ++++ b/net/bridge/br_netfilter.c +@@ -141,7 +141,7 @@ void br_netfilter_rtable_init(struct net + rt->dst.dev = br->dev; + rt->dst.path = &rt->dst; + dst_init_metrics(&rt->dst, br_dst_default_metrics, true); +- rt->dst.flags = DST_NOXFRM; ++ rt->dst.flags = DST_NOXFRM | DST_NOPEER; + rt->dst.ops = &fake_dst_ops; + } + +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -1272,7 +1272,7 @@ void __ip_select_ident(struct iphdr *iph + { + struct rtable *rt = (struct rtable *) dst; + +- if (rt) { ++ if (rt && !(rt->dst.flags & DST_NOPEER)) { + if (rt->peer == NULL) + rt_bind_peer(rt, rt->rt_dst, 1); + +@@ -1283,7 +1283,7 @@ void __ip_select_ident(struct iphdr *iph + iph->id = htons(inet_getid(rt->peer, more)); + return; + } +- } else ++ } else if (!rt) + printk(KERN_DEBUG "rt_bind_peer(0) @%p\n", + __builtin_return_address(0)); + +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -606,7 +606,7 @@ void ipv6_select_ident(struct frag_hdr * + static atomic_t ipv6_fragmentation_id; + int old, new; + +- if (rt) { ++ if (rt && !(rt->dst.flags & DST_NOPEER)) { + struct inet_peer *peer; + + if (!rt->rt6i_peer) diff --git a/queue-3.1/ppp-fix-pptp-double-release_sock-in-pptp_bind.patch b/queue-3.1/ppp-fix-pptp-double-release_sock-in-pptp_bind.patch new file mode 100644 index 00000000000..8f19e5b4720 --- /dev/null +++ b/queue-3.1/ppp-fix-pptp-double-release_sock-in-pptp_bind.patch @@ -0,0 +1,32 @@ +From 884aad5cf67fed3cc15003dbb9c8cdf9b6833b57 Mon Sep 17 00:00:00 2001 +From: Djalal Harouni +Date: Tue, 6 Dec 2011 15:47:12 +0000 +Subject: ppp: fix pptp double release_sock in pptp_bind() + + +From: Djalal Harouni + +[ Upstream commit a454daceb78844a09c08b6e2d8badcb76a5d73b9 ] + +Signed-off-by: Djalal Harouni +Acked-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/pptp.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/drivers/net/pptp.c ++++ b/drivers/net/pptp.c +@@ -423,10 +423,8 @@ static int pptp_bind(struct socket *sock + lock_sock(sk); + + opt->src_addr = sp->sa_addr.pptp; +- if (add_chan(po)) { +- release_sock(sk); ++ if (add_chan(po)) + error = -EBUSY; +- } + + release_sock(sk); + return error; diff --git a/queue-3.1/sch_gred-should-not-use-gfp_kernel-while-holding-a-spinlock.patch b/queue-3.1/sch_gred-should-not-use-gfp_kernel-while-holding-a-spinlock.patch new file mode 100644 index 00000000000..e65ef494900 --- /dev/null +++ b/queue-3.1/sch_gred-should-not-use-gfp_kernel-while-holding-a-spinlock.patch @@ -0,0 +1,36 @@ +From 8c7968a17315bcfa4b907334a35675129d84025f Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Sun, 11 Dec 2011 23:42:53 +0000 +Subject: sch_gred: should not use GFP_KERNEL while holding a spinlock + + +From: Eric Dumazet + +[ Upstream commit 3f1e6d3fd37bd4f25e5b19f1c7ca21850426c33f ] + +gred_change_vq() is called under sch_tree_lock(sch). + +This means a spinlock is held, and we are not allowed to sleep in this +context. + +We might pre-allocate memory using GFP_KERNEL before taking spinlock, +but this is not suitable for stable material. + +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/sched/sch_gred.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/sched/sch_gred.c ++++ b/net/sched/sch_gred.c +@@ -385,7 +385,7 @@ static inline int gred_change_vq(struct + struct gred_sched_data *q; + + if (table->tab[dp] == NULL) { +- table->tab[dp] = kzalloc(sizeof(*q), GFP_KERNEL); ++ table->tab[dp] = kzalloc(sizeof(*q), GFP_ATOMIC); + if (table->tab[dp] == NULL) + return -ENOMEM; + } diff --git a/queue-3.1/sctp-do-not-account-for-sizeof-struct-sk_buff-in-estimated-rwnd.patch b/queue-3.1/sctp-do-not-account-for-sizeof-struct-sk_buff-in-estimated-rwnd.patch new file mode 100644 index 00000000000..665021d837b --- /dev/null +++ b/queue-3.1/sctp-do-not-account-for-sizeof-struct-sk_buff-in-estimated-rwnd.patch @@ -0,0 +1,97 @@ +From 094b242b70f67ac3996934432f0a0d564e791cf6 Mon Sep 17 00:00:00 2001 +From: Thomas Graf +Date: Mon, 19 Dec 2011 04:11:40 +0000 +Subject: sctp: Do not account for sizeof(struct sk_buff) in estimated rwnd + + +From: Thomas Graf + +[ Upstream commit a76c0adf60f6ca5ff3481992e4ea0383776b24d2 ] + +When checking whether a DATA chunk fits into the estimated rwnd a +full sizeof(struct sk_buff) is added to the needed chunk size. This +quickly exhausts the available rwnd space and leads to packets being +sent which are much below the PMTU limit. This can lead to much worse +performance. + +The reason for this behaviour was to avoid putting too much memory +pressure on the receiver. The concept is not completely irational +because a Linux receiver does in fact clone an skb for each DATA chunk +delivered. However, Linux also reserves half the available socket +buffer space for data structures therefore usage of it is already +accounted for. + +When proposing to change this the last time it was noted that this +behaviour was introduced to solve a performance issue caused by rwnd +overusage in combination with small DATA chunks. + +Trying to reproduce this I found that with the sk_buff overhead removed, +the performance would improve significantly unless socket buffer limits +are increased. + +The following numbers have been gathered using a patched iperf +supporting SCTP over a live 1 Gbit ethernet network. The -l option +was used to limit DATA chunk sizes. The numbers listed are based on +the average of 3 test runs each. Default values have been used for +sk_(r|w)mem. + +Chunk +Size Unpatched No Overhead +------------------------------------- + 4 15.2 Kbit [!] 12.2 Mbit [!] + 8 35.8 Kbit [!] 26.0 Mbit [!] + 16 95.5 Kbit [!] 54.4 Mbit [!] + 32 106.7 Mbit 102.3 Mbit + 64 189.2 Mbit 188.3 Mbit + 128 331.2 Mbit 334.8 Mbit + 256 537.7 Mbit 536.0 Mbit + 512 766.9 Mbit 766.6 Mbit +1024 810.1 Mbit 808.6 Mbit + +Signed-off-by: Thomas Graf +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/sctp/output.c | 8 +------- + net/sctp/outqueue.c | 6 ++---- + 2 files changed, 3 insertions(+), 11 deletions(-) + +--- a/net/sctp/output.c ++++ b/net/sctp/output.c +@@ -697,13 +697,7 @@ static void sctp_packet_append_data(stru + /* Keep track of how many bytes are in flight to the receiver. */ + asoc->outqueue.outstanding_bytes += datasize; + +- /* Update our view of the receiver's rwnd. Include sk_buff overhead +- * while updating peer.rwnd so that it reduces the chances of a +- * receiver running out of receive buffer space even when receive +- * window is still open. This can happen when a sender is sending +- * sending small messages. +- */ +- datasize += sizeof(struct sk_buff); ++ /* Update our view of the receiver's rwnd. */ + if (datasize < rwnd) + rwnd -= datasize; + else +--- a/net/sctp/outqueue.c ++++ b/net/sctp/outqueue.c +@@ -411,8 +411,7 @@ void sctp_retransmit_mark(struct sctp_ou + chunk->transport->flight_size -= + sctp_data_size(chunk); + q->outstanding_bytes -= sctp_data_size(chunk); +- q->asoc->peer.rwnd += (sctp_data_size(chunk) + +- sizeof(struct sk_buff)); ++ q->asoc->peer.rwnd += sctp_data_size(chunk); + } + continue; + } +@@ -432,8 +431,7 @@ void sctp_retransmit_mark(struct sctp_ou + * (Section 7.2.4)), add the data size of those + * chunks to the rwnd. + */ +- q->asoc->peer.rwnd += (sctp_data_size(chunk) + +- sizeof(struct sk_buff)); ++ q->asoc->peer.rwnd += sctp_data_size(chunk); + q->outstanding_bytes -= sctp_data_size(chunk); + if (chunk->transport) + transport->flight_size -= sctp_data_size(chunk); diff --git a/queue-3.1/sctp-fix-incorrect-overflow-check-on-autoclose.patch b/queue-3.1/sctp-fix-incorrect-overflow-check-on-autoclose.patch new file mode 100644 index 00000000000..f7fbcfdb5db --- /dev/null +++ b/queue-3.1/sctp-fix-incorrect-overflow-check-on-autoclose.patch @@ -0,0 +1,121 @@ +From 4dff6c35f9ff1cf62dd4435517adae40a3dd2d8a Mon Sep 17 00:00:00 2001 +From: Xi Wang +Date: Fri, 16 Dec 2011 12:44:15 +0000 +Subject: sctp: fix incorrect overflow check on autoclose + + +From: Xi Wang + +[ Upstream commit 2692ba61a82203404abd7dd2a027bda962861f74 ] + +Commit 8ffd3208 voids the previous patches f6778aab and 810c0719 for +limiting the autoclose value. If userspace passes in -1 on 32-bit +platform, the overflow check didn't work and autoclose would be set +to 0xffffffff. + +This patch defines a max_autoclose (in seconds) for limiting the value +and exposes it through sysctl, with the following intentions. + +1) Avoid overflowing autoclose * HZ. + +2) Keep the default autoclose bound consistent across 32- and 64-bit + platforms (INT_MAX / HZ in this patch). + +3) Keep the autoclose value consistent between setsockopt() and + getsockopt() calls. + +Suggested-by: Vlad Yasevich +Signed-off-by: Xi Wang +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + include/net/sctp/structs.h | 4 ++++ + net/sctp/associola.c | 2 +- + net/sctp/protocol.c | 3 +++ + net/sctp/socket.c | 2 -- + net/sctp/sysctl.c | 13 +++++++++++++ + 5 files changed, 21 insertions(+), 3 deletions(-) + +--- a/include/net/sctp/structs.h ++++ b/include/net/sctp/structs.h +@@ -241,6 +241,9 @@ extern struct sctp_globals { + * bits is an indicator of when to send and window update SACK. + */ + int rwnd_update_shift; ++ ++ /* Threshold for autoclose timeout, in seconds. */ ++ unsigned long max_autoclose; + } sctp_globals; + + #define sctp_rto_initial (sctp_globals.rto_initial) +@@ -281,6 +284,7 @@ extern struct sctp_globals { + #define sctp_auth_enable (sctp_globals.auth_enable) + #define sctp_checksum_disable (sctp_globals.checksum_disable) + #define sctp_rwnd_upd_shift (sctp_globals.rwnd_update_shift) ++#define sctp_max_autoclose (sctp_globals.max_autoclose) + + /* SCTP Socket type: UDP or TCP style. */ + typedef enum { +--- a/net/sctp/associola.c ++++ b/net/sctp/associola.c +@@ -173,7 +173,7 @@ static struct sctp_association *sctp_ass + asoc->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] = 0; + asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = asoc->sackdelay; + asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] = +- (unsigned long)sp->autoclose * HZ; ++ min_t(unsigned long, sp->autoclose, sctp_max_autoclose) * HZ; + + /* Initializes the timers */ + for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i) +--- a/net/sctp/protocol.c ++++ b/net/sctp/protocol.c +@@ -1285,6 +1285,9 @@ SCTP_STATIC __init int sctp_init(void) + sctp_max_instreams = SCTP_DEFAULT_INSTREAMS; + sctp_max_outstreams = SCTP_DEFAULT_OUTSTREAMS; + ++ /* Initialize maximum autoclose timeout. */ ++ sctp_max_autoclose = INT_MAX / HZ; ++ + /* Initialize handle used for association ids. */ + idr_init(&sctp_assocs_id); + +--- a/net/sctp/socket.c ++++ b/net/sctp/socket.c +@@ -2199,8 +2199,6 @@ static int sctp_setsockopt_autoclose(str + return -EINVAL; + if (copy_from_user(&sp->autoclose, optval, optlen)) + return -EFAULT; +- /* make sure it won't exceed MAX_SCHEDULE_TIMEOUT */ +- sp->autoclose = min_t(long, sp->autoclose, MAX_SCHEDULE_TIMEOUT / HZ); + + return 0; + } +--- a/net/sctp/sysctl.c ++++ b/net/sctp/sysctl.c +@@ -53,6 +53,10 @@ static int sack_timer_min = 1; + static int sack_timer_max = 500; + static int addr_scope_max = 3; /* check sctp_scope_policy_t in include/net/sctp/constants.h for max entries */ + static int rwnd_scale_max = 16; ++static unsigned long max_autoclose_min = 0; ++static unsigned long max_autoclose_max = ++ (MAX_SCHEDULE_TIMEOUT / HZ > UINT_MAX) ++ ? UINT_MAX : MAX_SCHEDULE_TIMEOUT / HZ; + + extern long sysctl_sctp_mem[3]; + extern int sysctl_sctp_rmem[3]; +@@ -258,6 +262,15 @@ static ctl_table sctp_table[] = { + .extra1 = &one, + .extra2 = &rwnd_scale_max, + }, ++ { ++ .procname = "max_autoclose", ++ .data = &sctp_max_autoclose, ++ .maxlen = sizeof(unsigned long), ++ .mode = 0644, ++ .proc_handler = &proc_doulongvec_minmax, ++ .extra1 = &max_autoclose_min, ++ .extra2 = &max_autoclose_max, ++ }, + + { /* sentinel */ } + }; diff --git a/queue-3.1/series b/queue-3.1/series index f8a114c76d4..692017a6f31 100644 --- a/queue-3.1/series +++ b/queue-3.1/series @@ -48,3 +48,26 @@ drm-radeon-kms-bail-on-btc-parts-if-mc-ucode-is-missing.patch mm-hugetlb-fix-non-atomic-enqueue-of-huge-page.patch mm-mempolicy.c-refix-mbind_range-vma-issue.patch mpt2sas-crashes-on-shutdown.patch +sparc64-fix-msiq-hv-call-ordering-in-pci_sun4v_msiq_build_irq.patch +sparc32-be-less-strict-in-matching-lo-part-of-relocation.patch +sparc64-patch-sun4v-code-sequences-properly-on-module-load.patch +sparc-kill-custom-io_remap_pfn_range.patch +sparc32-remove-non-kernel-code-from-memcpy-implementation.patch +sparc32-remove-uses-of-g7-in-memcpy-implementation.patch +sparc32-correct-the-return-value-of-memcpy.patch +sparc64-fix-masking-and-shifting-in-vis-fpcmp-emulation.patch +sparc-fix-handling-of-orig_i0-wrt.-debugging-when-restarting-syscalls.patch +net-bpf_jit-fix-an-off-one-bug-in-x86_64-cond-jump-target.patch +ppp-fix-pptp-double-release_sock-in-pptp_bind.patch +llc-llc_cmsg_rcv-was-getting-called-after-sk_eat_skb.patch +mqprio-avoid-panic-if-no-options-are-provided.patch +net-have-ipconfig-not-wait-if-no-dev-is-available.patch +sch_gred-should-not-use-gfp_kernel-while-holding-a-spinlock.patch +sctp-fix-incorrect-overflow-check-on-autoclose.patch +sctp-do-not-account-for-sizeof-struct-sk_buff-in-estimated-rwnd.patch +net-add-a-flow_cache_flush_deferred-function.patch +ipv4-flush-route-cache-after-change-accept_local.patch +ipv6-check-dest-prefix-length-on-original-route-not-copied-one-in-rt6_alloc_cow.patch +net-introduce-dst_nopeer-dst-flag.patch +ipv4-reintroduce-route-cache-garbage-collector.patch +ipv4-using-prefetch-requires-including-prefetch.h.patch diff --git a/queue-3.1/sparc-fix-handling-of-orig_i0-wrt.-debugging-when-restarting-syscalls.patch b/queue-3.1/sparc-fix-handling-of-orig_i0-wrt.-debugging-when-restarting-syscalls.patch new file mode 100644 index 00000000000..4f5b047a1b4 --- /dev/null +++ b/queue-3.1/sparc-fix-handling-of-orig_i0-wrt.-debugging-when-restarting-syscalls.patch @@ -0,0 +1,179 @@ +From b167cbdeb37906bc30c1a618202e43373f96d09a Mon Sep 17 00:00:00 2001 +From: "David S. Miller" +Date: Mon, 26 Dec 2011 12:30:13 -0500 +Subject: sparc: Fix handling of orig_i0 wrt. debugging when restarting syscalls. + + +From: "David S. Miller" + +[ A combination of upstream commits 1d299bc7732c34d85bd43ac1a8745f5a2fed2078 and + e88d2468718b0789b4c33da2f7e1cef2a1eee279 ] + +Although we provide a proper way for a debugger to control whether +syscall restart occurs, we run into problems because orig_i0 is not +saved and restored properly. + +Luckily we can solve this problem without having to make debuggers +aware of the issue. Across system calls, several registers are +considered volatile and can be safely clobbered. + +Therefore we use the pt_regs save area of one of those registers, %g6, +as a place to save and restore orig_i0. + +Debuggers transparently will do the right thing because they save and +restore this register already. + +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + arch/sparc/kernel/signal32.c | 18 ++++++++++-------- + arch/sparc/kernel/signal_32.c | 30 +++++++++++++++++++++++++----- + arch/sparc/kernel/signal_64.c | 42 ++++++++++++++++++++++++++++-------------- + 3 files changed, 63 insertions(+), 27 deletions(-) + +--- a/arch/sparc/kernel/signal32.c ++++ b/arch/sparc/kernel/signal32.c +@@ -822,21 +822,23 @@ static inline void syscall_restart32(uns + * want to handle. Thus you cannot kill init even with a SIGKILL even by + * mistake. + */ +-void do_signal32(sigset_t *oldset, struct pt_regs * regs, +- int restart_syscall, unsigned long orig_i0) ++void do_signal32(sigset_t *oldset, struct pt_regs * regs) + { + struct k_sigaction ka; ++ unsigned long orig_i0; ++ int restart_syscall; + siginfo_t info; + int signr; + + signr = get_signal_to_deliver(&info, &ka, regs, NULL); + +- /* If the debugger messes with the program counter, it clears +- * the "in syscall" bit, directing us to not perform a syscall +- * restart. +- */ +- if (restart_syscall && !pt_regs_is_syscall(regs)) +- restart_syscall = 0; ++ restart_syscall = 0; ++ orig_i0 = 0; ++ if (pt_regs_is_syscall(regs) && ++ (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) { ++ restart_syscall = 1; ++ orig_i0 = regs->u_regs[UREG_G6]; ++ } + + if (signr > 0) { + if (restart_syscall) +--- a/arch/sparc/kernel/signal_32.c ++++ b/arch/sparc/kernel/signal_32.c +@@ -519,10 +519,26 @@ static void do_signal(struct pt_regs *re + siginfo_t info; + int signr; + ++ /* It's a lot of work and synchronization to add a new ptrace ++ * register for GDB to save and restore in order to get ++ * orig_i0 correct for syscall restarts when debugging. ++ * ++ * Although it should be the case that most of the global ++ * registers are volatile across a system call, glibc already ++ * depends upon that fact that we preserve them. So we can't ++ * just use any global register to save away the orig_i0 value. ++ * ++ * In particular %g2, %g3, %g4, and %g5 are all assumed to be ++ * preserved across a system call trap by various pieces of ++ * code in glibc. ++ * ++ * %g7 is used as the "thread register". %g6 is not used in ++ * any fixed manner. %g6 is used as a scratch register and ++ * a compiler temporary, but it's value is never used across ++ * a system call. Therefore %g6 is usable for orig_i0 storage. ++ */ + if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C)) +- restart_syscall = 1; +- else +- restart_syscall = 0; ++ regs->u_regs[UREG_G6] = orig_i0; + + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; +@@ -535,8 +551,12 @@ static void do_signal(struct pt_regs *re + * the software "in syscall" bit, directing us to not perform + * a syscall restart. + */ +- if (restart_syscall && !pt_regs_is_syscall(regs)) +- restart_syscall = 0; ++ restart_syscall = 0; ++ if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C)) { ++ restart_syscall = 1; ++ orig_i0 = regs->u_regs[UREG_G6]; ++ } ++ + + if (signr > 0) { + if (restart_syscall) +--- a/arch/sparc/kernel/signal_64.c ++++ b/arch/sparc/kernel/signal_64.c +@@ -529,11 +529,27 @@ static void do_signal(struct pt_regs *re + siginfo_t info; + int signr; + ++ /* It's a lot of work and synchronization to add a new ptrace ++ * register for GDB to save and restore in order to get ++ * orig_i0 correct for syscall restarts when debugging. ++ * ++ * Although it should be the case that most of the global ++ * registers are volatile across a system call, glibc already ++ * depends upon that fact that we preserve them. So we can't ++ * just use any global register to save away the orig_i0 value. ++ * ++ * In particular %g2, %g3, %g4, and %g5 are all assumed to be ++ * preserved across a system call trap by various pieces of ++ * code in glibc. ++ * ++ * %g7 is used as the "thread register". %g6 is not used in ++ * any fixed manner. %g6 is used as a scratch register and ++ * a compiler temporary, but it's value is never used across ++ * a system call. Therefore %g6 is usable for orig_i0 storage. ++ */ + if (pt_regs_is_syscall(regs) && +- (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) { +- restart_syscall = 1; +- } else +- restart_syscall = 0; ++ (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) ++ regs->u_regs[UREG_G6] = orig_i0; + + if (current_thread_info()->status & TS_RESTORE_SIGMASK) + oldset = ¤t->saved_sigmask; +@@ -542,22 +558,20 @@ static void do_signal(struct pt_regs *re + + #ifdef CONFIG_COMPAT + if (test_thread_flag(TIF_32BIT)) { +- extern void do_signal32(sigset_t *, struct pt_regs *, +- int restart_syscall, +- unsigned long orig_i0); +- do_signal32(oldset, regs, restart_syscall, orig_i0); ++ extern void do_signal32(sigset_t *, struct pt_regs *); ++ do_signal32(oldset, regs); + return; + } + #endif + + signr = get_signal_to_deliver(&info, &ka, regs, NULL); + +- /* If the debugger messes with the program counter, it clears +- * the software "in syscall" bit, directing us to not perform +- * a syscall restart. +- */ +- if (restart_syscall && !pt_regs_is_syscall(regs)) +- restart_syscall = 0; ++ restart_syscall = 0; ++ if (pt_regs_is_syscall(regs) && ++ (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) { ++ restart_syscall = 1; ++ orig_i0 = regs->u_regs[UREG_G6]; ++ } + + if (signr > 0) { + if (restart_syscall) diff --git a/queue-3.1/sparc-kill-custom-io_remap_pfn_range.patch b/queue-3.1/sparc-kill-custom-io_remap_pfn_range.patch new file mode 100644 index 00000000000..953c20905e4 --- /dev/null +++ b/queue-3.1/sparc-kill-custom-io_remap_pfn_range.patch @@ -0,0 +1,375 @@ +From 14e707a033b1266711adacb4629e7548e31a38e2 Mon Sep 17 00:00:00 2001 +From: "David S. Miller" +Date: Thu, 17 Nov 2011 18:17:59 -0800 +Subject: sparc: Kill custom io_remap_pfn_range(). + + +From: "David S. Miller" + +[ Upstream commit 3e37fd3153ac95088a74f5e7c569f7567e9f993a ] + +To handle the large physical addresses, just make a simple wrapper +around remap_pfn_range() like MIPS does. + +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + arch/sparc/include/asm/pgtable_32.h | 20 +++- + arch/sparc/include/asm/pgtable_64.h | 20 +++- + arch/sparc/mm/Makefile | 1 + arch/sparc/mm/generic_32.c | 98 --------------------- + arch/sparc/mm/generic_64.c | 164 ------------------------------------ + 5 files changed, 32 insertions(+), 271 deletions(-) + delete mode 100644 arch/sparc/mm/generic_32.c + delete mode 100644 arch/sparc/mm/generic_64.c + +--- a/arch/sparc/include/asm/pgtable_32.h ++++ b/arch/sparc/include/asm/pgtable_32.h +@@ -431,10 +431,6 @@ extern unsigned long *sparc_valid_addr_b + #define kern_addr_valid(addr) \ + (test_bit(__pa((unsigned long)(addr))>>20, sparc_valid_addr_bitmap)) + +-extern int io_remap_pfn_range(struct vm_area_struct *vma, +- unsigned long from, unsigned long pfn, +- unsigned long size, pgprot_t prot); +- + /* + * For sparc32&64, the pfn in io_remap_pfn_range() carries in + * its high 4 bits. These macros/functions put it there or get it from there. +@@ -443,6 +439,22 @@ extern int io_remap_pfn_range(struct vm_ + #define GET_IOSPACE(pfn) (pfn >> (BITS_PER_LONG - 4)) + #define GET_PFN(pfn) (pfn & 0x0fffffffUL) + ++extern int remap_pfn_range(struct vm_area_struct *, unsigned long, unsigned long, ++ unsigned long, pgprot_t); ++ ++static inline int io_remap_pfn_range(struct vm_area_struct *vma, ++ unsigned long from, unsigned long pfn, ++ unsigned long size, pgprot_t prot) ++{ ++ unsigned long long offset, space, phys_base; ++ ++ offset = ((unsigned long long) GET_PFN(pfn)) << PAGE_SHIFT; ++ space = GET_IOSPACE(pfn); ++ phys_base = offset | (space << 32ULL); ++ ++ return remap_pfn_range(vma, from, phys_base >> PAGE_SHIFT, size, prot); ++} ++ + #define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS + #define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \ + ({ \ +--- a/arch/sparc/include/asm/pgtable_64.h ++++ b/arch/sparc/include/asm/pgtable_64.h +@@ -757,10 +757,6 @@ static inline bool kern_addr_valid(unsig + + extern int page_in_phys_avail(unsigned long paddr); + +-extern int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from, +- unsigned long pfn, +- unsigned long size, pgprot_t prot); +- + /* + * For sparc32&64, the pfn in io_remap_pfn_range() carries in + * its high 4 bits. These macros/functions put it there or get it from there. +@@ -769,6 +765,22 @@ extern int io_remap_pfn_range(struct vm_ + #define GET_IOSPACE(pfn) (pfn >> (BITS_PER_LONG - 4)) + #define GET_PFN(pfn) (pfn & 0x0fffffffffffffffUL) + ++extern int remap_pfn_range(struct vm_area_struct *, unsigned long, unsigned long, ++ unsigned long, pgprot_t); ++ ++static inline int io_remap_pfn_range(struct vm_area_struct *vma, ++ unsigned long from, unsigned long pfn, ++ unsigned long size, pgprot_t prot) ++{ ++ unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT; ++ int space = GET_IOSPACE(pfn); ++ unsigned long phys_base; ++ ++ phys_base = offset | (((unsigned long) space) << 32UL); ++ ++ return remap_pfn_range(vma, from, phys_base >> PAGE_SHIFT, size, prot); ++} ++ + #include + + /* We provide our own get_unmapped_area to cope with VA holes and +--- a/arch/sparc/mm/Makefile ++++ b/arch/sparc/mm/Makefile +@@ -8,7 +8,6 @@ obj-$(CONFIG_SPARC64) += ultra.o tlb.o + obj-y += fault_$(BITS).o + obj-y += init_$(BITS).o + obj-$(CONFIG_SPARC32) += loadmmu.o +-obj-y += generic_$(BITS).o + obj-$(CONFIG_SPARC32) += extable.o btfixup.o srmmu.o iommu.o io-unit.o + obj-$(CONFIG_SPARC32) += hypersparc.o viking.o tsunami.o swift.o + obj-$(CONFIG_SPARC_LEON)+= leon_mm.o +--- a/arch/sparc/mm/generic_32.c ++++ /dev/null +@@ -1,98 +0,0 @@ +-/* +- * generic.c: Generic Sparc mm routines that are not dependent upon +- * MMU type but are Sparc specific. +- * +- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) +- */ +- +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +-#include +- +-/* Remap IO memory, the same way as remap_pfn_range(), but use +- * the obio memory space. +- * +- * They use a pgprot that sets PAGE_IO and does not check the +- * mem_map table as this is independent of normal memory. +- */ +-static inline void io_remap_pte_range(struct mm_struct *mm, pte_t * pte, unsigned long address, unsigned long size, +- unsigned long offset, pgprot_t prot, int space) +-{ +- unsigned long end; +- +- address &= ~PMD_MASK; +- end = address + size; +- if (end > PMD_SIZE) +- end = PMD_SIZE; +- do { +- set_pte_at(mm, address, pte, mk_pte_io(offset, prot, space)); +- address += PAGE_SIZE; +- offset += PAGE_SIZE; +- pte++; +- } while (address < end); +-} +- +-static inline int io_remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size, +- unsigned long offset, pgprot_t prot, int space) +-{ +- unsigned long end; +- +- address &= ~PGDIR_MASK; +- end = address + size; +- if (end > PGDIR_SIZE) +- end = PGDIR_SIZE; +- offset -= address; +- do { +- pte_t *pte = pte_alloc_map(mm, NULL, pmd, address); +- if (!pte) +- return -ENOMEM; +- io_remap_pte_range(mm, pte, address, end - address, address + offset, prot, space); +- address = (address + PMD_SIZE) & PMD_MASK; +- pmd++; +- } while (address < end); +- return 0; +-} +- +-int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from, +- unsigned long pfn, unsigned long size, pgprot_t prot) +-{ +- int error = 0; +- pgd_t * dir; +- unsigned long beg = from; +- unsigned long end = from + size; +- struct mm_struct *mm = vma->vm_mm; +- int space = GET_IOSPACE(pfn); +- unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT; +- +- /* See comment in mm/memory.c remap_pfn_range */ +- vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP; +- vma->vm_pgoff = (offset >> PAGE_SHIFT) | +- ((unsigned long)space << 28UL); +- +- offset -= from; +- dir = pgd_offset(mm, from); +- flush_cache_range(vma, beg, end); +- +- while (from < end) { +- pmd_t *pmd = pmd_alloc(mm, dir, from); +- error = -ENOMEM; +- if (!pmd) +- break; +- error = io_remap_pmd_range(mm, pmd, from, end - from, offset + from, prot, space); +- if (error) +- break; +- from = (from + PGDIR_SIZE) & PGDIR_MASK; +- dir++; +- } +- +- flush_tlb_range(vma, beg, end); +- return error; +-} +-EXPORT_SYMBOL(io_remap_pfn_range); +--- a/arch/sparc/mm/generic_64.c ++++ /dev/null +@@ -1,164 +0,0 @@ +-/* +- * generic.c: Generic Sparc mm routines that are not dependent upon +- * MMU type but are Sparc specific. +- * +- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) +- */ +- +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +- +-/* Remap IO memory, the same way as remap_pfn_range(), but use +- * the obio memory space. +- * +- * They use a pgprot that sets PAGE_IO and does not check the +- * mem_map table as this is independent of normal memory. +- */ +-static inline void io_remap_pte_range(struct mm_struct *mm, pte_t * pte, +- unsigned long address, +- unsigned long size, +- unsigned long offset, pgprot_t prot, +- int space) +-{ +- unsigned long end; +- +- /* clear hack bit that was used as a write_combine side-effect flag */ +- offset &= ~0x1UL; +- address &= ~PMD_MASK; +- end = address + size; +- if (end > PMD_SIZE) +- end = PMD_SIZE; +- do { +- pte_t entry; +- unsigned long curend = address + PAGE_SIZE; +- +- entry = mk_pte_io(offset, prot, space, PAGE_SIZE); +- if (!(address & 0xffff)) { +- if (PAGE_SIZE < (4 * 1024 * 1024) && +- !(address & 0x3fffff) && +- !(offset & 0x3ffffe) && +- end >= address + 0x400000) { +- entry = mk_pte_io(offset, prot, space, +- 4 * 1024 * 1024); +- curend = address + 0x400000; +- offset += 0x400000; +- } else if (PAGE_SIZE < (512 * 1024) && +- !(address & 0x7ffff) && +- !(offset & 0x7fffe) && +- end >= address + 0x80000) { +- entry = mk_pte_io(offset, prot, space, +- 512 * 1024 * 1024); +- curend = address + 0x80000; +- offset += 0x80000; +- } else if (PAGE_SIZE < (64 * 1024) && +- !(offset & 0xfffe) && +- end >= address + 0x10000) { +- entry = mk_pte_io(offset, prot, space, +- 64 * 1024); +- curend = address + 0x10000; +- offset += 0x10000; +- } else +- offset += PAGE_SIZE; +- } else +- offset += PAGE_SIZE; +- +- if (pte_write(entry)) +- entry = pte_mkdirty(entry); +- do { +- BUG_ON(!pte_none(*pte)); +- set_pte_at(mm, address, pte, entry); +- address += PAGE_SIZE; +- pte_val(entry) += PAGE_SIZE; +- pte++; +- } while (address < curend); +- } while (address < end); +-} +- +-static inline int io_remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size, +- unsigned long offset, pgprot_t prot, int space) +-{ +- unsigned long end; +- +- address &= ~PGDIR_MASK; +- end = address + size; +- if (end > PGDIR_SIZE) +- end = PGDIR_SIZE; +- offset -= address; +- do { +- pte_t *pte = pte_alloc_map(mm, NULL, pmd, address); +- if (!pte) +- return -ENOMEM; +- io_remap_pte_range(mm, pte, address, end - address, address + offset, prot, space); +- pte_unmap(pte); +- address = (address + PMD_SIZE) & PMD_MASK; +- pmd++; +- } while (address < end); +- return 0; +-} +- +-static inline int io_remap_pud_range(struct mm_struct *mm, pud_t * pud, unsigned long address, unsigned long size, +- unsigned long offset, pgprot_t prot, int space) +-{ +- unsigned long end; +- +- address &= ~PUD_MASK; +- end = address + size; +- if (end > PUD_SIZE) +- end = PUD_SIZE; +- offset -= address; +- do { +- pmd_t *pmd = pmd_alloc(mm, pud, address); +- if (!pud) +- return -ENOMEM; +- io_remap_pmd_range(mm, pmd, address, end - address, address + offset, prot, space); +- address = (address + PUD_SIZE) & PUD_MASK; +- pud++; +- } while (address < end); +- return 0; +-} +- +-int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from, +- unsigned long pfn, unsigned long size, pgprot_t prot) +-{ +- int error = 0; +- pgd_t * dir; +- unsigned long beg = from; +- unsigned long end = from + size; +- struct mm_struct *mm = vma->vm_mm; +- int space = GET_IOSPACE(pfn); +- unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT; +- unsigned long phys_base; +- +- phys_base = offset | (((unsigned long) space) << 32UL); +- +- /* See comment in mm/memory.c remap_pfn_range */ +- vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP; +- vma->vm_pgoff = phys_base >> PAGE_SHIFT; +- +- offset -= from; +- dir = pgd_offset(mm, from); +- flush_cache_range(vma, beg, end); +- +- while (from < end) { +- pud_t *pud = pud_alloc(mm, dir, from); +- error = -ENOMEM; +- if (!pud) +- break; +- error = io_remap_pud_range(mm, pud, from, end - from, offset + from, prot, space); +- if (error) +- break; +- from = (from + PGDIR_SIZE) & PGDIR_MASK; +- dir++; +- } +- +- flush_tlb_range(vma, beg, end); +- return error; +-} +-EXPORT_SYMBOL(io_remap_pfn_range); diff --git a/queue-3.1/sparc32-be-less-strict-in-matching-lo-part-of-relocation.patch b/queue-3.1/sparc32-be-less-strict-in-matching-lo-part-of-relocation.patch new file mode 100644 index 00000000000..f233d65949a --- /dev/null +++ b/queue-3.1/sparc32-be-less-strict-in-matching-lo-part-of-relocation.patch @@ -0,0 +1,33 @@ +From 20ef5b3fb98a8548235689c61080a7389a41145c Mon Sep 17 00:00:00 2001 +From: "David S. Miller" +Date: Wed, 14 Dec 2011 10:05:22 -0800 +Subject: sparc32: Be less strict in matching %lo part of relocation. + + +From: "David S. Miller" + +[ Upstream commit b1f44e13a525d2ffb7d5afe2273b7169d6f2222e ] + +The "(insn & 0x01800000) != 0x01800000" test matches 'restore' +but that is a legitimate place to see the %lo() part of a 32-bit +symbol relocation, particularly in tail calls. + +Signed-off-by: David S. Miller +Tested-by: Sergei Trofimovich +Signed-off-by: Greg Kroah-Hartman +--- + arch/sparc/mm/btfixup.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/arch/sparc/mm/btfixup.c ++++ b/arch/sparc/mm/btfixup.c +@@ -302,8 +302,7 @@ void __init btfixup(void) + case 'i': /* INT */ + if ((insn & 0xc1c00000) == 0x01000000) /* %HI */ + set_addr(addr, q[1], fmangled, (insn & 0xffc00000) | (p[1] >> 10)); +- else if ((insn & 0x80002000) == 0x80002000 && +- (insn & 0x01800000) != 0x01800000) /* %LO */ ++ else if ((insn & 0x80002000) == 0x80002000) /* %LO */ + set_addr(addr, q[1], fmangled, (insn & 0xffffe000) | (p[1] & 0x3ff)); + else { + prom_printf(insn_i, p, addr, insn); diff --git a/queue-3.1/sparc32-correct-the-return-value-of-memcpy.patch b/queue-3.1/sparc32-correct-the-return-value-of-memcpy.patch new file mode 100644 index 00000000000..3ce69c4983e --- /dev/null +++ b/queue-3.1/sparc32-correct-the-return-value-of-memcpy.patch @@ -0,0 +1,99 @@ +From 6bf220cd94d4ac023e1ad81ad2ad76f176d45892 Mon Sep 17 00:00:00 2001 +From: "David S. Miller" +Date: Wed, 19 Oct 2011 15:31:55 -0700 +Subject: sparc32: Correct the return value of memcpy. + + +From: "David S. Miller" + +[ Upstream commit a52312b88c8103e965979a79a07f6b34af82ca4b ] + +Properly return the original destination buffer pointer. + +Signed-off-by: David S. Miller +Tested-by: Kjetil Oftedal +Signed-off-by: Greg Kroah-Hartman +--- + arch/sparc/lib/memcpy.S | 22 +++++++--------------- + 1 file changed, 7 insertions(+), 15 deletions(-) + +--- a/arch/sparc/lib/memcpy.S ++++ b/arch/sparc/lib/memcpy.S +@@ -13,14 +13,6 @@ + .align 4; \ + x: + +- +-/* In kernel these functions don't return a value. +- * One should use macros in asm/string.h for that purpose. +- * We return 0, so that bugs are more apparent. +- */ +-#define SETUP_RETL +-#define RETL_INSN clr %o0 +- + /* Both these macros have to start with exactly the same insn */ + #define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \ + ldd [%src + (offset) + 0x00], %t0; \ +@@ -154,7 +146,7 @@ FUNC(__memmove) + #endif + FUNC(memmove) + cmp %o0, %o1 +- SETUP_RETL ++ mov %o0, %g7 + bleu 9f + sub %o0, %o1, %o4 + +@@ -178,7 +170,7 @@ FUNC(memmove) + sub %o0, 1, %o0 + + retl +- RETL_INSN ++ mov %g7, %o0 + + /* NOTE: This code is executed just for the cases, + where %src (=%o1) & 3 is != 0. +@@ -212,7 +204,7 @@ FUNC(memmove) + FUNC(memcpy) /* %o0=dst %o1=src %o2=len */ + + sub %o0, %o1, %o4 +- SETUP_RETL ++ mov %o0, %g7 + 9: + andcc %o4, 3, %o5 + 0: +@@ -308,7 +300,7 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len + stb %g2, [%o0] + 1: + retl +- RETL_INSN ++ mov %g7, %o0 + + 82: /* ldd_std */ + MOVE_BIGALIGNCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5) +@@ -373,7 +365,7 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len + stb %g2, [%o0] + 1: + retl +- RETL_INSN ++ mov %g7, %o0 + + 86: /* non_aligned */ + cmp %o2, 6 +@@ -498,7 +490,7 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len + stb %g2, [%i0 + 4] + 1: + ret +- restore %g0, %g0, %o0 ++ restore %g7, %g0, %o0 + + 88: /* short_end */ + +@@ -529,7 +521,7 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len + stb %g2, [%o0] + 1: + retl +- RETL_INSN ++ mov %g7, %o0 + + 90: /* short_aligned_end */ + bne 88b diff --git a/queue-3.1/sparc32-remove-non-kernel-code-from-memcpy-implementation.patch b/queue-3.1/sparc32-remove-non-kernel-code-from-memcpy-implementation.patch new file mode 100644 index 00000000000..a8bab3d8e65 --- /dev/null +++ b/queue-3.1/sparc32-remove-non-kernel-code-from-memcpy-implementation.patch @@ -0,0 +1,689 @@ +From 5a1b90af1e95b9ac5339f8d356c0a15a2b92c0d8 Mon Sep 17 00:00:00 2001 +From: "David S. Miller" +Date: Wed, 19 Oct 2011 15:15:58 -0700 +Subject: sparc32: Remove non-kernel code from memcpy implementation. + + +From: "David S. Miller" + +[ Upstream commit 045b7de9ca0cf09f1adc3efa467f668b89238390 ] + +Signed-off-by: David S. Miller +Tested-by: Kjetil Oftedal +Signed-off-by: Greg Kroah-Hartman +--- + arch/sparc/lib/memcpy.S | 607 ------------------------------------------------ + 1 file changed, 2 insertions(+), 605 deletions(-) + +--- a/arch/sparc/lib/memcpy.S ++++ b/arch/sparc/lib/memcpy.S +@@ -7,17 +7,12 @@ + * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz) + */ + +-#ifdef __KERNEL__ +- +-#define FUNC(x) \ ++#define FUNC(x) \ + .globl x; \ + .type x,@function; \ +- .align 4; \ ++ .align 4; \ + x: + +-#undef FASTER_REVERSE +-#undef FASTER_NONALIGNED +-#define FASTER_ALIGNED + + /* In kernel these functions don't return a value. + * One should use macros in asm/string.h for that purpose. +@@ -26,21 +21,6 @@ x: + #define SETUP_RETL + #define RETL_INSN clr %o0 + +-#else +- +-/* libc */ +- +-#include "DEFS.h" +- +-#define FASTER_REVERSE +-#define FASTER_NONALIGNED +-#define FASTER_ALIGNED +- +-#define SETUP_RETL mov %o0, %g6 +-#define RETL_INSN mov %g6, %o0 +- +-#endif +- + /* Both these macros have to start with exactly the same insn */ + #define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \ + ldd [%src + (offset) + 0x00], %t0; \ +@@ -164,30 +144,6 @@ x: + .text + .align 4 + +-#ifdef FASTER_REVERSE +- +-70: /* rdword_align */ +- +- andcc %o1, 1, %g0 +- be 4f +- andcc %o1, 2, %g0 +- +- ldub [%o1 - 1], %g2 +- sub %o1, 1, %o1 +- stb %g2, [%o0 - 1] +- sub %o2, 1, %o2 +- be 3f +- sub %o0, 1, %o0 +-4: +- lduh [%o1 - 2], %g2 +- sub %o1, 2, %o1 +- sth %g2, [%o0 - 2] +- sub %o2, 2, %o2 +- b 3f +- sub %o0, 2, %o0 +- +-#endif /* FASTER_REVERSE */ +- + 0: + retl + nop ! Only bcopy returns here and it retuns void... +@@ -207,8 +163,6 @@ FUNC(memmove) + bleu 0f + andcc %o4, 3, %o5 + +-#ifndef FASTER_REVERSE +- + add %o1, %o2, %o1 + add %o0, %o2, %o0 + sub %o1, 1, %o1 +@@ -226,294 +180,6 @@ FUNC(memmove) + retl + RETL_INSN + +-#else /* FASTER_REVERSE */ +- +- add %o1, %o2, %o1 +- add %o0, %o2, %o0 +- bne 77f +- cmp %o2, 15 +- bleu 91f +- andcc %o1, 3, %g0 +- bne 70b +-3: +- andcc %o1, 4, %g0 +- +- be 2f +- mov %o2, %g1 +- +- ld [%o1 - 4], %o4 +- sub %g1, 4, %g1 +- st %o4, [%o0 - 4] +- sub %o1, 4, %o1 +- sub %o0, 4, %o0 +-2: +- andcc %g1, 0xffffff80, %g7 +- be 3f +- andcc %o0, 4, %g0 +- +- be 74f + 4 +-5: +- RMOVE_BIGCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5) +- RMOVE_BIGCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5) +- RMOVE_BIGCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5) +- RMOVE_BIGCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5) +- subcc %g7, 128, %g7 +- sub %o1, 128, %o1 +- bne 5b +- sub %o0, 128, %o0 +-3: +- andcc %g1, 0x70, %g7 +- be 72f +- andcc %g1, 8, %g0 +- +- sethi %hi(72f), %o5 +- srl %g7, 1, %o4 +- add %g7, %o4, %o4 +- sub %o1, %g7, %o1 +- sub %o5, %o4, %o5 +- jmpl %o5 + %lo(72f), %g0 +- sub %o0, %g7, %o0 +- +-71: /* rmemcpy_table */ +- RMOVE_LASTCHUNK(o1, o0, 0x60, g2, g3, g4, g5) +- RMOVE_LASTCHUNK(o1, o0, 0x50, g2, g3, g4, g5) +- RMOVE_LASTCHUNK(o1, o0, 0x40, g2, g3, g4, g5) +- RMOVE_LASTCHUNK(o1, o0, 0x30, g2, g3, g4, g5) +- RMOVE_LASTCHUNK(o1, o0, 0x20, g2, g3, g4, g5) +- RMOVE_LASTCHUNK(o1, o0, 0x10, g2, g3, g4, g5) +- RMOVE_LASTCHUNK(o1, o0, 0x00, g2, g3, g4, g5) +- +-72: /* rmemcpy_table_end */ +- +- be 73f +- andcc %g1, 4, %g0 +- +- ldd [%o1 - 0x08], %g2 +- sub %o0, 8, %o0 +- sub %o1, 8, %o1 +- st %g2, [%o0] +- st %g3, [%o0 + 0x04] +- +-73: /* rmemcpy_last7 */ +- +- be 1f +- andcc %g1, 2, %g0 +- +- ld [%o1 - 4], %g2 +- sub %o1, 4, %o1 +- st %g2, [%o0 - 4] +- sub %o0, 4, %o0 +-1: +- be 1f +- andcc %g1, 1, %g0 +- +- lduh [%o1 - 2], %g2 +- sub %o1, 2, %o1 +- sth %g2, [%o0 - 2] +- sub %o0, 2, %o0 +-1: +- be 1f +- nop +- +- ldub [%o1 - 1], %g2 +- stb %g2, [%o0 - 1] +-1: +- retl +- RETL_INSN +- +-74: /* rldd_std */ +- RMOVE_BIGALIGNCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5) +- RMOVE_BIGALIGNCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5) +- RMOVE_BIGALIGNCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5) +- RMOVE_BIGALIGNCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5) +- subcc %g7, 128, %g7 +- sub %o1, 128, %o1 +- bne 74b +- sub %o0, 128, %o0 +- +- andcc %g1, 0x70, %g7 +- be 72b +- andcc %g1, 8, %g0 +- +- sethi %hi(72b), %o5 +- srl %g7, 1, %o4 +- add %g7, %o4, %o4 +- sub %o1, %g7, %o1 +- sub %o5, %o4, %o5 +- jmpl %o5 + %lo(72b), %g0 +- sub %o0, %g7, %o0 +- +-75: /* rshort_end */ +- +- and %o2, 0xe, %o3 +-2: +- sethi %hi(76f), %o5 +- sll %o3, 3, %o4 +- sub %o0, %o3, %o0 +- sub %o5, %o4, %o5 +- sub %o1, %o3, %o1 +- jmpl %o5 + %lo(76f), %g0 +- andcc %o2, 1, %g0 +- +- RMOVE_SHORTCHUNK(o1, o0, 0x0c, g2, g3) +- RMOVE_SHORTCHUNK(o1, o0, 0x0a, g2, g3) +- RMOVE_SHORTCHUNK(o1, o0, 0x08, g2, g3) +- RMOVE_SHORTCHUNK(o1, o0, 0x06, g2, g3) +- RMOVE_SHORTCHUNK(o1, o0, 0x04, g2, g3) +- RMOVE_SHORTCHUNK(o1, o0, 0x02, g2, g3) +- RMOVE_SHORTCHUNK(o1, o0, 0x00, g2, g3) +- +-76: /* rshort_table_end */ +- +- be 1f +- nop +- ldub [%o1 - 1], %g2 +- stb %g2, [%o0 - 1] +-1: +- retl +- RETL_INSN +- +-91: /* rshort_aligned_end */ +- +- bne 75b +- andcc %o2, 8, %g0 +- +- be 1f +- andcc %o2, 4, %g0 +- +- ld [%o1 - 0x08], %g2 +- ld [%o1 - 0x04], %g3 +- sub %o1, 8, %o1 +- st %g2, [%o0 - 0x08] +- st %g3, [%o0 - 0x04] +- sub %o0, 8, %o0 +-1: +- b 73b +- mov %o2, %g1 +- +-77: /* rnon_aligned */ +- cmp %o2, 15 +- bleu 75b +- andcc %o0, 3, %g0 +- be 64f +- andcc %o0, 1, %g0 +- be 63f +- andcc %o0, 2, %g0 +- ldub [%o1 - 1], %g5 +- sub %o1, 1, %o1 +- stb %g5, [%o0 - 1] +- sub %o0, 1, %o0 +- be 64f +- sub %o2, 1, %o2 +-63: +- ldub [%o1 - 1], %g5 +- sub %o1, 2, %o1 +- stb %g5, [%o0 - 1] +- sub %o0, 2, %o0 +- ldub [%o1], %g5 +- sub %o2, 2, %o2 +- stb %g5, [%o0] +-64: +- and %o1, 3, %g2 +- and %o1, -4, %o1 +- and %o2, 0xc, %g3 +- add %o1, 4, %o1 +- cmp %g3, 4 +- sll %g2, 3, %g4 +- mov 32, %g2 +- be 4f +- sub %g2, %g4, %g7 +- +- blu 3f +- cmp %g3, 8 +- +- be 2f +- srl %o2, 2, %g3 +- +- ld [%o1 - 4], %o3 +- add %o0, -8, %o0 +- ld [%o1 - 8], %o4 +- add %o1, -16, %o1 +- b 7f +- add %g3, 1, %g3 +-2: +- ld [%o1 - 4], %o4 +- add %o0, -4, %o0 +- ld [%o1 - 8], %g1 +- add %o1, -12, %o1 +- b 8f +- add %g3, 2, %g3 +-3: +- ld [%o1 - 4], %o5 +- add %o0, -12, %o0 +- ld [%o1 - 8], %o3 +- add %o1, -20, %o1 +- b 6f +- srl %o2, 2, %g3 +-4: +- ld [%o1 - 4], %g1 +- srl %o2, 2, %g3 +- ld [%o1 - 8], %o5 +- add %o1, -24, %o1 +- add %o0, -16, %o0 +- add %g3, -1, %g3 +- +- ld [%o1 + 12], %o3 +-5: +- sll %o5, %g4, %g2 +- srl %g1, %g7, %g5 +- or %g2, %g5, %g2 +- st %g2, [%o0 + 12] +-6: +- ld [%o1 + 8], %o4 +- sll %o3, %g4, %g2 +- srl %o5, %g7, %g5 +- or %g2, %g5, %g2 +- st %g2, [%o0 + 8] +-7: +- ld [%o1 + 4], %g1 +- sll %o4, %g4, %g2 +- srl %o3, %g7, %g5 +- or %g2, %g5, %g2 +- st %g2, [%o0 + 4] +-8: +- ld [%o1], %o5 +- sll %g1, %g4, %g2 +- srl %o4, %g7, %g5 +- addcc %g3, -4, %g3 +- or %g2, %g5, %g2 +- add %o1, -16, %o1 +- st %g2, [%o0] +- add %o0, -16, %o0 +- bne,a 5b +- ld [%o1 + 12], %o3 +- sll %o5, %g4, %g2 +- srl %g1, %g7, %g5 +- srl %g4, 3, %g3 +- or %g2, %g5, %g2 +- add %o1, %g3, %o1 +- andcc %o2, 2, %g0 +- st %g2, [%o0 + 12] +- be 1f +- andcc %o2, 1, %g0 +- +- ldub [%o1 + 15], %g5 +- add %o1, -2, %o1 +- stb %g5, [%o0 + 11] +- add %o0, -2, %o0 +- ldub [%o1 + 16], %g5 +- stb %g5, [%o0 + 12] +-1: +- be 1f +- nop +- ldub [%o1 + 15], %g5 +- stb %g5, [%o0 + 11] +-1: +- retl +- RETL_INSN +- +-#endif /* FASTER_REVERSE */ +- + /* NOTE: This code is executed just for the cases, + where %src (=%o1) & 3 is != 0. + We need to align it to 4. So, for (%src & 3) +@@ -653,22 +319,6 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len + bne 82b + add %o0, 128, %o0 + +-#ifndef FASTER_ALIGNED +- +- andcc %g1, 0x70, %g7 +- be 80b +- andcc %g1, 8, %g0 +- +- sethi %hi(80b), %o5 +- srl %g7, 1, %o4 +- add %g7, %o4, %o4 +- add %o1, %g7, %o1 +- sub %o5, %o4, %o5 +- jmpl %o5 + %lo(80b), %g0 +- add %o0, %g7, %o0 +- +-#else /* FASTER_ALIGNED */ +- + andcc %g1, 0x70, %g7 + be 84f + andcc %g1, 8, %g0 +@@ -723,19 +373,9 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len + retl + RETL_INSN + +-#endif /* FASTER_ALIGNED */ +- + 86: /* non_aligned */ + cmp %o2, 6 + bleu 88f +- +-#ifdef FASTER_NONALIGNED +- +- cmp %o2, 256 +- bcc 87f +- +-#endif /* FASTER_NONALIGNED */ +- + andcc %o0, 3, %g0 + be 61f + andcc %o0, 1, %g0 +@@ -855,249 +495,6 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len + retl + RETL_INSN + +-#ifdef FASTER_NONALIGNED +- +-87: /* faster_nonaligned */ +- +- andcc %o1, 3, %g0 +- be 3f +- andcc %o1, 1, %g0 +- +- be 4f +- andcc %o1, 2, %g0 +- +- ldub [%o1], %g2 +- add %o1, 1, %o1 +- stb %g2, [%o0] +- sub %o2, 1, %o2 +- bne 3f +- add %o0, 1, %o0 +-4: +- lduh [%o1], %g2 +- add %o1, 2, %o1 +- srl %g2, 8, %g3 +- sub %o2, 2, %o2 +- stb %g3, [%o0] +- add %o0, 2, %o0 +- stb %g2, [%o0 - 1] +-3: +- andcc %o1, 4, %g0 +- +- bne 2f +- cmp %o5, 1 +- +- ld [%o1], %o4 +- srl %o4, 24, %g2 +- stb %g2, [%o0] +- srl %o4, 16, %g3 +- stb %g3, [%o0 + 1] +- srl %o4, 8, %g2 +- stb %g2, [%o0 + 2] +- sub %o2, 4, %o2 +- stb %o4, [%o0 + 3] +- add %o1, 4, %o1 +- add %o0, 4, %o0 +-2: +- be 33f +- cmp %o5, 2 +- be 32f +- sub %o2, 4, %o2 +-31: +- ld [%o1], %g2 +- add %o1, 4, %o1 +- srl %g2, 24, %g3 +- and %o0, 7, %g5 +- stb %g3, [%o0] +- cmp %g5, 7 +- sll %g2, 8, %g1 +- add %o0, 4, %o0 +- be 41f +- and %o2, 0xffffffc0, %o3 +- ld [%o0 - 7], %o4 +-4: +- SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3) +- SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3) +- SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3) +- SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3) +- subcc %o3, 64, %o3 +- add %o1, 64, %o1 +- bne 4b +- add %o0, 64, %o0 +- +- andcc %o2, 0x30, %o3 +- be,a 1f +- srl %g1, 16, %g2 +-4: +- SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3) +- subcc %o3, 16, %o3 +- add %o1, 16, %o1 +- bne 4b +- add %o0, 16, %o0 +- +- srl %g1, 16, %g2 +-1: +- st %o4, [%o0 - 7] +- sth %g2, [%o0 - 3] +- srl %g1, 8, %g4 +- b 88f +- stb %g4, [%o0 - 1] +-32: +- ld [%o1], %g2 +- add %o1, 4, %o1 +- srl %g2, 16, %g3 +- and %o0, 7, %g5 +- sth %g3, [%o0] +- cmp %g5, 6 +- sll %g2, 16, %g1 +- add %o0, 4, %o0 +- be 42f +- and %o2, 0xffffffc0, %o3 +- ld [%o0 - 6], %o4 +-4: +- SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2) +- SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2) +- SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2) +- SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2) +- subcc %o3, 64, %o3 +- add %o1, 64, %o1 +- bne 4b +- add %o0, 64, %o0 +- +- andcc %o2, 0x30, %o3 +- be,a 1f +- srl %g1, 16, %g2 +-4: +- SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2) +- subcc %o3, 16, %o3 +- add %o1, 16, %o1 +- bne 4b +- add %o0, 16, %o0 +- +- srl %g1, 16, %g2 +-1: +- st %o4, [%o0 - 6] +- b 88f +- sth %g2, [%o0 - 2] +-33: +- ld [%o1], %g2 +- sub %o2, 4, %o2 +- srl %g2, 24, %g3 +- and %o0, 7, %g5 +- stb %g3, [%o0] +- cmp %g5, 5 +- srl %g2, 8, %g4 +- sll %g2, 24, %g1 +- sth %g4, [%o0 + 1] +- add %o1, 4, %o1 +- be 43f +- and %o2, 0xffffffc0, %o3 +- +- ld [%o0 - 1], %o4 +- add %o0, 4, %o0 +-4: +- SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1) +- SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1) +- SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1) +- SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1) +- subcc %o3, 64, %o3 +- add %o1, 64, %o1 +- bne 4b +- add %o0, 64, %o0 +- +- andcc %o2, 0x30, %o3 +- be,a 1f +- srl %g1, 24, %g2 +-4: +- SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1) +- subcc %o3, 16, %o3 +- add %o1, 16, %o1 +- bne 4b +- add %o0, 16, %o0 +- +- srl %g1, 24, %g2 +-1: +- st %o4, [%o0 - 5] +- b 88f +- stb %g2, [%o0 - 1] +-41: +- SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3) +- SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3) +- SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3) +- SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3) +- subcc %o3, 64, %o3 +- add %o1, 64, %o1 +- bne 41b +- add %o0, 64, %o0 +- +- andcc %o2, 0x30, %o3 +- be,a 1f +- srl %g1, 16, %g2 +-4: +- SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3) +- subcc %o3, 16, %o3 +- add %o1, 16, %o1 +- bne 4b +- add %o0, 16, %o0 +- +- srl %g1, 16, %g2 +-1: +- sth %g2, [%o0 - 3] +- srl %g1, 8, %g4 +- b 88f +- stb %g4, [%o0 - 1] +-43: +- SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3) +- SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3) +- SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3) +- SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3) +- subcc %o3, 64, %o3 +- add %o1, 64, %o1 +- bne 43b +- add %o0, 64, %o0 +- +- andcc %o2, 0x30, %o3 +- be,a 1f +- srl %g1, 24, %g2 +-4: +- SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3) +- subcc %o3, 16, %o3 +- add %o1, 16, %o1 +- bne 4b +- add %o0, 16, %o0 +- +- srl %g1, 24, %g2 +-1: +- stb %g2, [%o0 + 3] +- b 88f +- add %o0, 4, %o0 +-42: +- SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2) +- SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2) +- SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2) +- SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2) +- subcc %o3, 64, %o3 +- add %o1, 64, %o1 +- bne 42b +- add %o0, 64, %o0 +- +- andcc %o2, 0x30, %o3 +- be,a 1f +- srl %g1, 16, %g2 +-4: +- SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2) +- subcc %o3, 16, %o3 +- add %o1, 16, %o1 +- bne 4b +- add %o0, 16, %o0 +- +- srl %g1, 16, %g2 +-1: +- sth %g2, [%o0 - 2] +- +- /* Fall through */ +- +-#endif /* FASTER_NONALIGNED */ +- + 88: /* short_end */ + + and %o2, 0xe, %o3 diff --git a/queue-3.1/sparc32-remove-uses-of-g7-in-memcpy-implementation.patch b/queue-3.1/sparc32-remove-uses-of-g7-in-memcpy-implementation.patch new file mode 100644 index 00000000000..dad3da84658 --- /dev/null +++ b/queue-3.1/sparc32-remove-uses-of-g7-in-memcpy-implementation.patch @@ -0,0 +1,291 @@ +From 0a7316055e710cf551484615c0b1887e156ed972 Mon Sep 17 00:00:00 2001 +From: "David S. Miller" +Date: Wed, 19 Oct 2011 15:30:14 -0700 +Subject: sparc32: Remove uses of %g7 in memcpy implementation. + + +From: "David S. Miller" + +[ Upstream commit 21f74d361dfd6a7d0e47574e315f780d8172084a ] + +This is setting things up so that we can correct the return +value, so that it properly returns the original destination +buffer pointer. + +Signed-off-by: David S. Miller +Tested-by: Kjetil Oftedal +Signed-off-by: Greg Kroah-Hartman +--- + arch/sparc/lib/memcpy.S | 177 ++++++++++++++++++++++++------------------------ + 1 file changed, 91 insertions(+), 86 deletions(-) + +--- a/arch/sparc/lib/memcpy.S ++++ b/arch/sparc/lib/memcpy.S +@@ -235,7 +235,7 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len + add %o1, 4, %o1 + add %o0, 4, %o0 + 2: +- andcc %g1, 0xffffff80, %g7 ++ andcc %g1, 0xffffff80, %g0 + be 3f + andcc %o0, 4, %g0 + +@@ -245,22 +245,23 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len + MOVE_BIGCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5) + MOVE_BIGCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5) + MOVE_BIGCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5) +- subcc %g7, 128, %g7 ++ sub %g1, 128, %g1 + add %o1, 128, %o1 +- bne 5b ++ cmp %g1, 128 ++ bge 5b + add %o0, 128, %o0 + 3: +- andcc %g1, 0x70, %g7 ++ andcc %g1, 0x70, %g4 + be 80f + andcc %g1, 8, %g0 + + sethi %hi(80f), %o5 +- srl %g7, 1, %o4 +- add %g7, %o4, %o4 +- add %o1, %g7, %o1 ++ srl %g4, 1, %o4 ++ add %g4, %o4, %o4 ++ add %o1, %g4, %o1 + sub %o5, %o4, %o5 + jmpl %o5 + %lo(80f), %g0 +- add %o0, %g7, %o0 ++ add %o0, %g4, %o0 + + 79: /* memcpy_table */ + +@@ -314,20 +315,21 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len + MOVE_BIGALIGNCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5) + MOVE_BIGALIGNCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5) + MOVE_BIGALIGNCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5) +- subcc %g7, 128, %g7 ++ subcc %g1, 128, %g1 + add %o1, 128, %o1 +- bne 82b ++ cmp %g1, 128 ++ bge 82b + add %o0, 128, %o0 + +- andcc %g1, 0x70, %g7 ++ andcc %g1, 0x70, %g4 + be 84f + andcc %g1, 8, %g0 + + sethi %hi(84f), %o5 +- add %o1, %g7, %o1 +- sub %o5, %g7, %o5 ++ add %o1, %g4, %o1 ++ sub %o5, %g4, %o5 + jmpl %o5 + %lo(84f), %g0 +- add %o0, %g7, %o0 ++ add %o0, %g4, %o0 + + 83: /* amemcpy_table */ + +@@ -376,124 +378,127 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len + 86: /* non_aligned */ + cmp %o2, 6 + bleu 88f +- andcc %o0, 3, %g0 ++ nop ++ ++ save %sp, -96, %sp ++ andcc %i0, 3, %g0 + be 61f +- andcc %o0, 1, %g0 ++ andcc %i0, 1, %g0 + be 60f +- andcc %o0, 2, %g0 ++ andcc %i0, 2, %g0 + +- ldub [%o1], %g5 +- add %o1, 1, %o1 +- stb %g5, [%o0] +- sub %o2, 1, %o2 ++ ldub [%i1], %g5 ++ add %i1, 1, %i1 ++ stb %g5, [%i0] ++ sub %i2, 1, %i2 + bne 61f +- add %o0, 1, %o0 ++ add %i0, 1, %i0 + 60: +- ldub [%o1], %g3 +- add %o1, 2, %o1 +- stb %g3, [%o0] +- sub %o2, 2, %o2 +- ldub [%o1 - 1], %g3 +- add %o0, 2, %o0 +- stb %g3, [%o0 - 1] ++ ldub [%i1], %g3 ++ add %i1, 2, %i1 ++ stb %g3, [%i0] ++ sub %i2, 2, %i2 ++ ldub [%i1 - 1], %g3 ++ add %i0, 2, %i0 ++ stb %g3, [%i0 - 1] + 61: +- and %o1, 3, %g2 +- and %o2, 0xc, %g3 +- and %o1, -4, %o1 ++ and %i1, 3, %g2 ++ and %i2, 0xc, %g3 ++ and %i1, -4, %i1 + cmp %g3, 4 + sll %g2, 3, %g4 + mov 32, %g2 + be 4f +- sub %g2, %g4, %g7 ++ sub %g2, %g4, %l0 + + blu 3f + cmp %g3, 0x8 + + be 2f +- srl %o2, 2, %g3 ++ srl %i2, 2, %g3 + +- ld [%o1], %o3 +- add %o0, -8, %o0 +- ld [%o1 + 4], %o4 ++ ld [%i1], %i3 ++ add %i0, -8, %i0 ++ ld [%i1 + 4], %i4 + b 8f + add %g3, 1, %g3 + 2: +- ld [%o1], %o4 +- add %o0, -12, %o0 +- ld [%o1 + 4], %o5 ++ ld [%i1], %i4 ++ add %i0, -12, %i0 ++ ld [%i1 + 4], %i5 + add %g3, 2, %g3 + b 9f +- add %o1, -4, %o1 ++ add %i1, -4, %i1 + 3: +- ld [%o1], %g1 +- add %o0, -4, %o0 +- ld [%o1 + 4], %o3 +- srl %o2, 2, %g3 ++ ld [%i1], %g1 ++ add %i0, -4, %i0 ++ ld [%i1 + 4], %i3 ++ srl %i2, 2, %g3 + b 7f +- add %o1, 4, %o1 ++ add %i1, 4, %i1 + 4: +- ld [%o1], %o5 +- cmp %o2, 7 +- ld [%o1 + 4], %g1 +- srl %o2, 2, %g3 ++ ld [%i1], %i5 ++ cmp %i2, 7 ++ ld [%i1 + 4], %g1 ++ srl %i2, 2, %g3 + bleu 10f +- add %o1, 8, %o1 ++ add %i1, 8, %i1 + +- ld [%o1], %o3 ++ ld [%i1], %i3 + add %g3, -1, %g3 + 5: +- sll %o5, %g4, %g2 +- srl %g1, %g7, %g5 ++ sll %i5, %g4, %g2 ++ srl %g1, %l0, %g5 + or %g2, %g5, %g2 +- st %g2, [%o0] ++ st %g2, [%i0] + 7: +- ld [%o1 + 4], %o4 ++ ld [%i1 + 4], %i4 + sll %g1, %g4, %g2 +- srl %o3, %g7, %g5 ++ srl %i3, %l0, %g5 + or %g2, %g5, %g2 +- st %g2, [%o0 + 4] ++ st %g2, [%i0 + 4] + 8: +- ld [%o1 + 8], %o5 +- sll %o3, %g4, %g2 +- srl %o4, %g7, %g5 ++ ld [%i1 + 8], %i5 ++ sll %i3, %g4, %g2 ++ srl %i4, %l0, %g5 + or %g2, %g5, %g2 +- st %g2, [%o0 + 8] ++ st %g2, [%i0 + 8] + 9: +- ld [%o1 + 12], %g1 +- sll %o4, %g4, %g2 +- srl %o5, %g7, %g5 ++ ld [%i1 + 12], %g1 ++ sll %i4, %g4, %g2 ++ srl %i5, %l0, %g5 + addcc %g3, -4, %g3 + or %g2, %g5, %g2 +- add %o1, 16, %o1 +- st %g2, [%o0 + 12] +- add %o0, 16, %o0 ++ add %i1, 16, %i1 ++ st %g2, [%i0 + 12] ++ add %i0, 16, %i0 + bne,a 5b +- ld [%o1], %o3 ++ ld [%i1], %i3 + 10: +- sll %o5, %g4, %g2 +- srl %g1, %g7, %g5 +- srl %g7, 3, %g3 ++ sll %i5, %g4, %g2 ++ srl %g1, %l0, %g5 ++ srl %l0, 3, %g3 + or %g2, %g5, %g2 +- sub %o1, %g3, %o1 +- andcc %o2, 2, %g0 +- st %g2, [%o0] ++ sub %i1, %g3, %i1 ++ andcc %i2, 2, %g0 ++ st %g2, [%i0] + be 1f +- andcc %o2, 1, %g0 ++ andcc %i2, 1, %g0 + +- ldub [%o1], %g2 +- add %o1, 2, %o1 +- stb %g2, [%o0 + 4] +- add %o0, 2, %o0 +- ldub [%o1 - 1], %g2 +- stb %g2, [%o0 + 3] ++ ldub [%i1], %g2 ++ add %i1, 2, %i1 ++ stb %g2, [%i0 + 4] ++ add %i0, 2, %i0 ++ ldub [%i1 - 1], %g2 ++ stb %g2, [%i0 + 3] + 1: + be 1f + nop +- ldub [%o1], %g2 +- stb %g2, [%o0 + 4] ++ ldub [%i1], %g2 ++ stb %g2, [%i0 + 4] + 1: +- retl +- RETL_INSN ++ ret ++ restore %g0, %g0, %o0 + + 88: /* short_end */ + diff --git a/queue-3.1/sparc64-fix-masking-and-shifting-in-vis-fpcmp-emulation.patch b/queue-3.1/sparc64-fix-masking-and-shifting-in-vis-fpcmp-emulation.patch new file mode 100644 index 00000000000..4717d5996d4 --- /dev/null +++ b/queue-3.1/sparc64-fix-masking-and-shifting-in-vis-fpcmp-emulation.patch @@ -0,0 +1,106 @@ +From 612837c3502f6d1dd2d75b27778c6b8597ac4afc Mon Sep 17 00:00:00 2001 +From: "David S. Miller" +Date: Mon, 31 Oct 2011 01:05:49 -0700 +Subject: sparc64: Fix masking and shifting in VIS fpcmp emulation. + + +From: "David S. Miller" + +[ Upstream commit 2e8ecdc008a16b9a6c4b9628bb64d0d1c05f9f92 ] + +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + arch/sparc/kernel/visemul.c | 32 ++++++++++++++++---------------- + 1 file changed, 16 insertions(+), 16 deletions(-) + +--- a/arch/sparc/kernel/visemul.c ++++ b/arch/sparc/kernel/visemul.c +@@ -713,17 +713,17 @@ static void pcmp(struct pt_regs *regs, u + s16 b = (rs2 >> (i * 16)) & 0xffff; + + if (a > b) +- rd_val |= 1 << i; ++ rd_val |= 8 >> i; + } + break; + + case FCMPGT32_OPF: + for (i = 0; i < 2; i++) { +- s32 a = (rs1 >> (i * 32)) & 0xffff; +- s32 b = (rs2 >> (i * 32)) & 0xffff; ++ s32 a = (rs1 >> (i * 32)) & 0xffffffff; ++ s32 b = (rs2 >> (i * 32)) & 0xffffffff; + + if (a > b) +- rd_val |= 1 << i; ++ rd_val |= 2 >> i; + } + break; + +@@ -733,17 +733,17 @@ static void pcmp(struct pt_regs *regs, u + s16 b = (rs2 >> (i * 16)) & 0xffff; + + if (a <= b) +- rd_val |= 1 << i; ++ rd_val |= 8 >> i; + } + break; + + case FCMPLE32_OPF: + for (i = 0; i < 2; i++) { +- s32 a = (rs1 >> (i * 32)) & 0xffff; +- s32 b = (rs2 >> (i * 32)) & 0xffff; ++ s32 a = (rs1 >> (i * 32)) & 0xffffffff; ++ s32 b = (rs2 >> (i * 32)) & 0xffffffff; + + if (a <= b) +- rd_val |= 1 << i; ++ rd_val |= 2 >> i; + } + break; + +@@ -753,17 +753,17 @@ static void pcmp(struct pt_regs *regs, u + s16 b = (rs2 >> (i * 16)) & 0xffff; + + if (a != b) +- rd_val |= 1 << i; ++ rd_val |= 8 >> i; + } + break; + + case FCMPNE32_OPF: + for (i = 0; i < 2; i++) { +- s32 a = (rs1 >> (i * 32)) & 0xffff; +- s32 b = (rs2 >> (i * 32)) & 0xffff; ++ s32 a = (rs1 >> (i * 32)) & 0xffffffff; ++ s32 b = (rs2 >> (i * 32)) & 0xffffffff; + + if (a != b) +- rd_val |= 1 << i; ++ rd_val |= 2 >> i; + } + break; + +@@ -773,17 +773,17 @@ static void pcmp(struct pt_regs *regs, u + s16 b = (rs2 >> (i * 16)) & 0xffff; + + if (a == b) +- rd_val |= 1 << i; ++ rd_val |= 8 >> i; + } + break; + + case FCMPEQ32_OPF: + for (i = 0; i < 2; i++) { +- s32 a = (rs1 >> (i * 32)) & 0xffff; +- s32 b = (rs2 >> (i * 32)) & 0xffff; ++ s32 a = (rs1 >> (i * 32)) & 0xffffffff; ++ s32 b = (rs2 >> (i * 32)) & 0xffffffff; + + if (a == b) +- rd_val |= 1 << i; ++ rd_val |= 2 >> i; + } + break; + } diff --git a/queue-3.1/sparc64-fix-msiq-hv-call-ordering-in-pci_sun4v_msiq_build_irq.patch b/queue-3.1/sparc64-fix-msiq-hv-call-ordering-in-pci_sun4v_msiq_build_irq.patch new file mode 100644 index 00000000000..93c95be3cb1 --- /dev/null +++ b/queue-3.1/sparc64-fix-msiq-hv-call-ordering-in-pci_sun4v_msiq_build_irq.patch @@ -0,0 +1,44 @@ +From f852e0fd1bb963a325ffe943a6ad9ef7d9bfb88b Mon Sep 17 00:00:00 2001 +From: "David S. Miller" +Date: Thu, 22 Dec 2011 13:23:59 -0800 +Subject: sparc64: Fix MSIQ HV call ordering in pci_sun4v_msiq_build_irq(). + + +From: "David S. Miller" + +[ Upstream commit 7cc8583372a21d98a23b703ad96cab03180b5030 ] + +This silently was working for many years and stopped working on +Niagara-T3 machines. + +We need to set the MSIQ to VALID before we can set it's state to IDLE. + +On Niagara-T3, setting the state to IDLE first was causing HV_EINVAL +errors. The hypervisor documentation says, rather ambiguously, that +the MSIQ must be "initialized" before one can set the state. + +I previously understood this to mean merely that a successful setconf() +operation has been performed on the MSIQ, which we have done at this +point. But it seems to also mean that it has been set VALID too. + +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + arch/sparc/kernel/pci_sun4v.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/arch/sparc/kernel/pci_sun4v.c ++++ b/arch/sparc/kernel/pci_sun4v.c +@@ -848,10 +848,10 @@ static int pci_sun4v_msiq_build_irq(stru + if (!irq) + return -ENOMEM; + +- if (pci_sun4v_msiq_setstate(pbm->devhandle, msiqid, HV_MSIQSTATE_IDLE)) +- return -EINVAL; + if (pci_sun4v_msiq_setvalid(pbm->devhandle, msiqid, HV_MSIQ_VALID)) + return -EINVAL; ++ if (pci_sun4v_msiq_setstate(pbm->devhandle, msiqid, HV_MSIQSTATE_IDLE)) ++ return -EINVAL; + + return irq; + } diff --git a/queue-3.1/sparc64-patch-sun4v-code-sequences-properly-on-module-load.patch b/queue-3.1/sparc64-patch-sun4v-code-sequences-properly-on-module-load.patch new file mode 100644 index 00000000000..108f118fd27 --- /dev/null +++ b/queue-3.1/sparc64-patch-sun4v-code-sequences-properly-on-module-load.patch @@ -0,0 +1,168 @@ +From 6f47e53783de70866c46a35cfc2d52bb3a8ae394 Mon Sep 17 00:00:00 2001 +From: "David S. Miller" +Date: Thu, 17 Nov 2011 22:44:58 -0800 +Subject: sparc64: Patch sun4v code sequences properly on module load. + + +From: "David S. Miller" + +[ Upstream commit 0b64120cceb86e93cb1bda0dc055f13016646907 ] + +Some of the sun4v code patching occurs in inline functions visible +to, and usable by, modules. + +Therefore we have to patch them up during module load. + +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + arch/sparc/kernel/entry.h | 7 ++++++ + arch/sparc/kernel/module.c | 27 ++++++++++++++++++++++++ + arch/sparc/kernel/setup_64.c | 48 +++++++++++++++++++++++++------------------ + 3 files changed, 63 insertions(+), 19 deletions(-) + +--- a/arch/sparc/kernel/entry.h ++++ b/arch/sparc/kernel/entry.h +@@ -42,6 +42,9 @@ extern void fpsave(unsigned long *fpregs + extern void fpload(unsigned long *fpregs, unsigned long *fsr); + + #else /* CONFIG_SPARC32 */ ++ ++#include ++ + struct popc_3insn_patch_entry { + unsigned int addr; + unsigned int insns[3]; +@@ -57,6 +60,10 @@ extern struct popc_6insn_patch_entry __p + __popc_6insn_patch_end; + + extern void __init per_cpu_patch(void); ++extern void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *, ++ struct sun4v_1insn_patch_entry *); ++extern void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *, ++ struct sun4v_2insn_patch_entry *); + extern void __init sun4v_patch(void); + extern void __init boot_cpu_id_too_large(int cpu); + extern unsigned int dcache_parity_tl1_occurred; +--- a/arch/sparc/kernel/module.c ++++ b/arch/sparc/kernel/module.c +@@ -17,6 +17,8 @@ + #include + #include + ++#include "entry.h" ++ + #ifdef CONFIG_SPARC64 + + #include +@@ -203,6 +205,29 @@ int apply_relocate_add(Elf_Shdr *sechdrs + } + + #ifdef CONFIG_SPARC64 ++static void do_patch_sections(const Elf_Ehdr *hdr, ++ const Elf_Shdr *sechdrs) ++{ ++ const Elf_Shdr *s, *sun4v_1insn = NULL, *sun4v_2insn = NULL; ++ char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; ++ ++ for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) { ++ if (!strcmp(".sun4v_1insn_patch", secstrings + s->sh_name)) ++ sun4v_1insn = s; ++ if (!strcmp(".sun4v_2insn_patch", secstrings + s->sh_name)) ++ sun4v_2insn = s; ++ } ++ ++ if (sun4v_1insn && tlb_type == hypervisor) { ++ void *p = (void *) sun4v_1insn->sh_addr; ++ sun4v_patch_1insn_range(p, p + sun4v_1insn->sh_size); ++ } ++ if (sun4v_2insn && tlb_type == hypervisor) { ++ void *p = (void *) sun4v_2insn->sh_addr; ++ sun4v_patch_2insn_range(p, p + sun4v_2insn->sh_size); ++ } ++} ++ + int module_finalize(const Elf_Ehdr *hdr, + const Elf_Shdr *sechdrs, + struct module *me) +@@ -210,6 +235,8 @@ int module_finalize(const Elf_Ehdr *hdr, + /* make jump label nops */ + jump_label_apply_nops(me); + ++ do_patch_sections(hdr, sechdrs); ++ + /* Cheetah's I-cache is fully coherent. */ + if (tlb_type == spitfire) { + unsigned long va; +--- a/arch/sparc/kernel/setup_64.c ++++ b/arch/sparc/kernel/setup_64.c +@@ -234,40 +234,50 @@ void __init per_cpu_patch(void) + } + } + +-void __init sun4v_patch(void) ++void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *start, ++ struct sun4v_1insn_patch_entry *end) + { +- extern void sun4v_hvapi_init(void); +- struct sun4v_1insn_patch_entry *p1; +- struct sun4v_2insn_patch_entry *p2; +- +- if (tlb_type != hypervisor) +- return; ++ while (start < end) { ++ unsigned long addr = start->addr; + +- p1 = &__sun4v_1insn_patch; +- while (p1 < &__sun4v_1insn_patch_end) { +- unsigned long addr = p1->addr; +- +- *(unsigned int *) (addr + 0) = p1->insn; ++ *(unsigned int *) (addr + 0) = start->insn; + wmb(); + __asm__ __volatile__("flush %0" : : "r" (addr + 0)); + +- p1++; ++ start++; + } ++} + +- p2 = &__sun4v_2insn_patch; +- while (p2 < &__sun4v_2insn_patch_end) { +- unsigned long addr = p2->addr; ++void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *start, ++ struct sun4v_2insn_patch_entry *end) ++{ ++ while (start < end) { ++ unsigned long addr = start->addr; + +- *(unsigned int *) (addr + 0) = p2->insns[0]; ++ *(unsigned int *) (addr + 0) = start->insns[0]; + wmb(); + __asm__ __volatile__("flush %0" : : "r" (addr + 0)); + +- *(unsigned int *) (addr + 4) = p2->insns[1]; ++ *(unsigned int *) (addr + 4) = start->insns[1]; + wmb(); + __asm__ __volatile__("flush %0" : : "r" (addr + 4)); + +- p2++; ++ start++; + } ++} ++ ++void __init sun4v_patch(void) ++{ ++ extern void sun4v_hvapi_init(void); ++ ++ if (tlb_type != hypervisor) ++ return; ++ ++ sun4v_patch_1insn_range(&__sun4v_1insn_patch, ++ &__sun4v_1insn_patch_end); ++ ++ sun4v_patch_2insn_range(&__sun4v_2insn_patch, ++ &__sun4v_2insn_patch_end); + + sun4v_hvapi_init(); + }