From e1ddb026d12d19337c3a79ead6dd4cc449da50e1 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 7 Dec 2010 14:04:13 -0800 Subject: [PATCH] .32 patches --- queue-2.6.32/act_nat-use-stack-variable.patch | 75 ++++++ ...t-sched-fix-some-kernel-memory-leaks.patch | 165 +++++++++++++ ...mi-fix-clock-comparator-revalidation.patch | 93 ++++++++ queue-2.6.32/series | 9 + ...d-of-nid-to-gru_create_message_queue.patch | 45 ++++ ...xpc-to-handle-updated-bios-interface.patch | 219 ++++++++++++++++++ ...to-provide-an-abstraction-for-uv_gpa.patch | 100 ++++++++ ...c-null-deref-when-mesq-becomes-empty.patch | 43 ++++ ...essage-reuse-triggers-invalid-bug_on.patch | 63 +++++ ...ng-due-to-not-accepting-active-state.patch | 41 ++++ 10 files changed, 853 insertions(+) create mode 100644 queue-2.6.32/act_nat-use-stack-variable.patch create mode 100644 queue-2.6.32/net-sched-fix-some-kernel-memory-leaks.patch create mode 100644 queue-2.6.32/nmi-fix-clock-comparator-revalidation.patch create mode 100644 queue-2.6.32/uv-xpc-pass-nasid-instead-of-nid-to-gru_create_message_queue.patch create mode 100644 queue-2.6.32/x86-uv-update-xpc-to-handle-updated-bios-interface.patch create mode 100644 queue-2.6.32/x86-uv-xpc-needs-to-provide-an-abstraction-for-uv_gpa.patch create mode 100644 queue-2.6.32/x86-uv-xpc-null-deref-when-mesq-becomes-empty.patch create mode 100644 queue-2.6.32/x86-uv-xpc-receive-message-reuse-triggers-invalid-bug_on.patch create mode 100644 queue-2.6.32/x86-uv-xpc_make_first_contact-hang-due-to-not-accepting-active-state.patch diff --git a/queue-2.6.32/act_nat-use-stack-variable.patch b/queue-2.6.32/act_nat-use-stack-variable.patch new file mode 100644 index 00000000000..34e2b6aebbe --- /dev/null +++ b/queue-2.6.32/act_nat-use-stack-variable.patch @@ -0,0 +1,75 @@ +From 504f85c9d05f7c605306e808f0d835fe11bfd18d Mon Sep 17 00:00:00 2001 +From: Changli Gao +Date: Tue, 29 Jun 2010 23:07:09 +0000 +Subject: act_nat: use stack variable + +From: Changli Gao + +commit 504f85c9d05f7c605306e808f0d835fe11bfd18d upstream. + +act_nat: use stack variable + +structure tc_nat isn't too big for stack, so we can put it in stack. + +Signed-off-by: Changli Gao +Cc: dann frazier +Signed-off-by: Greg Kroah-Hartman + +--- + net/sched/act_nat.c | 33 +++++++++++---------------------- + 1 file changed, 11 insertions(+), 22 deletions(-) + +--- a/net/sched/act_nat.c ++++ b/net/sched/act_nat.c +@@ -261,40 +261,29 @@ static int tcf_nat_dump(struct sk_buff * + { + unsigned char *b = skb_tail_pointer(skb); + struct tcf_nat *p = a->priv; +- struct tc_nat *opt; ++ struct tc_nat opt; + struct tcf_t t; +- int s; + +- s = sizeof(*opt); ++ opt.old_addr = p->old_addr; ++ opt.new_addr = p->new_addr; ++ opt.mask = p->mask; ++ opt.flags = p->flags; ++ ++ opt.index = p->tcf_index; ++ opt.action = p->tcf_action; ++ opt.refcnt = p->tcf_refcnt - ref; ++ opt.bindcnt = p->tcf_bindcnt - bind; + +- /* netlink spinlocks held above us - must use ATOMIC */ +- opt = kzalloc(s, GFP_ATOMIC); +- if (unlikely(!opt)) +- return -ENOBUFS; +- +- opt->old_addr = p->old_addr; +- opt->new_addr = p->new_addr; +- opt->mask = p->mask; +- opt->flags = p->flags; +- +- opt->index = p->tcf_index; +- opt->action = p->tcf_action; +- opt->refcnt = p->tcf_refcnt - ref; +- opt->bindcnt = p->tcf_bindcnt - bind; +- +- NLA_PUT(skb, TCA_NAT_PARMS, s, opt); ++ NLA_PUT(skb, TCA_NAT_PARMS, sizeof(opt), &opt); + t.install = jiffies_to_clock_t(jiffies - p->tcf_tm.install); + t.lastuse = jiffies_to_clock_t(jiffies - p->tcf_tm.lastuse); + t.expires = jiffies_to_clock_t(p->tcf_tm.expires); + NLA_PUT(skb, TCA_NAT_TM, sizeof(t), &t); + +- kfree(opt); +- + return skb->len; + + nla_put_failure: + nlmsg_trim(skb, b); +- kfree(opt); + return -1; + } + diff --git a/queue-2.6.32/net-sched-fix-some-kernel-memory-leaks.patch b/queue-2.6.32/net-sched-fix-some-kernel-memory-leaks.patch new file mode 100644 index 00000000000..7e225379a21 --- /dev/null +++ b/queue-2.6.32/net-sched-fix-some-kernel-memory-leaks.patch @@ -0,0 +1,165 @@ +From 1c40be12f7d8ca1d387510d39787b12e512a7ce8 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Mon, 16 Aug 2010 20:04:22 +0000 +Subject: net sched: fix some kernel memory leaks + +From: Eric Dumazet + +commit 1c40be12f7d8ca1d387510d39787b12e512a7ce8 upstream. + +We leak at least 32bits of kernel memory to user land in tc dump, +because we dont init all fields (capab ?) of the dumped structure. + +Use C99 initializers so that holes and non explicit fields are zeroed. + +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +Cc: dann frazier +Signed-off-by: Greg Kroah-Hartman + +--- + net/sched/act_gact.c | 21 ++++++++++++--------- + net/sched/act_mirred.c | 15 ++++++++------- + net/sched/act_nat.c | 22 +++++++++++----------- + net/sched/act_simple.c | 11 ++++++----- + net/sched/act_skbedit.c | 11 ++++++----- + 5 files changed, 43 insertions(+), 37 deletions(-) + +--- a/net/sched/act_gact.c ++++ b/net/sched/act_gact.c +@@ -152,21 +152,24 @@ static int tcf_gact(struct sk_buff *skb, + static int tcf_gact_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) + { + unsigned char *b = skb_tail_pointer(skb); +- struct tc_gact opt; + struct tcf_gact *gact = a->priv; ++ struct tc_gact opt = { ++ .index = gact->tcf_index, ++ .refcnt = gact->tcf_refcnt - ref, ++ .bindcnt = gact->tcf_bindcnt - bind, ++ .action = gact->tcf_action, ++ }; + struct tcf_t t; + +- opt.index = gact->tcf_index; +- opt.refcnt = gact->tcf_refcnt - ref; +- opt.bindcnt = gact->tcf_bindcnt - bind; +- opt.action = gact->tcf_action; + NLA_PUT(skb, TCA_GACT_PARMS, sizeof(opt), &opt); + #ifdef CONFIG_GACT_PROB + if (gact->tcfg_ptype) { +- struct tc_gact_p p_opt; +- p_opt.paction = gact->tcfg_paction; +- p_opt.pval = gact->tcfg_pval; +- p_opt.ptype = gact->tcfg_ptype; ++ struct tc_gact_p p_opt = { ++ .paction = gact->tcfg_paction, ++ .pval = gact->tcfg_pval, ++ .ptype = gact->tcfg_ptype, ++ }; ++ + NLA_PUT(skb, TCA_GACT_PROB, sizeof(p_opt), &p_opt); + } + #endif +--- a/net/sched/act_mirred.c ++++ b/net/sched/act_mirred.c +@@ -205,15 +205,16 @@ static int tcf_mirred_dump(struct sk_buf + { + unsigned char *b = skb_tail_pointer(skb); + struct tcf_mirred *m = a->priv; +- struct tc_mirred opt; ++ struct tc_mirred opt = { ++ .index = m->tcf_index, ++ .action = m->tcf_action, ++ .refcnt = m->tcf_refcnt - ref, ++ .bindcnt = m->tcf_bindcnt - bind, ++ .eaction = m->tcfm_eaction, ++ .ifindex = m->tcfm_ifindex, ++ }; + struct tcf_t t; + +- opt.index = m->tcf_index; +- opt.action = m->tcf_action; +- opt.refcnt = m->tcf_refcnt - ref; +- opt.bindcnt = m->tcf_bindcnt - bind; +- opt.eaction = m->tcfm_eaction; +- opt.ifindex = m->tcfm_ifindex; + NLA_PUT(skb, TCA_MIRRED_PARMS, sizeof(opt), &opt); + t.install = jiffies_to_clock_t(jiffies - m->tcf_tm.install); + t.lastuse = jiffies_to_clock_t(jiffies - m->tcf_tm.lastuse); +--- a/net/sched/act_nat.c ++++ b/net/sched/act_nat.c +@@ -261,18 +261,18 @@ static int tcf_nat_dump(struct sk_buff * + { + unsigned char *b = skb_tail_pointer(skb); + struct tcf_nat *p = a->priv; +- struct tc_nat opt; +- struct tcf_t t; +- +- opt.old_addr = p->old_addr; +- opt.new_addr = p->new_addr; +- opt.mask = p->mask; +- opt.flags = p->flags; ++ struct tc_nat opt = { ++ .old_addr = p->old_addr, ++ .new_addr = p->new_addr, ++ .mask = p->mask, ++ .flags = p->flags, + +- opt.index = p->tcf_index; +- opt.action = p->tcf_action; +- opt.refcnt = p->tcf_refcnt - ref; +- opt.bindcnt = p->tcf_bindcnt - bind; ++ .index = p->tcf_index, ++ .action = p->tcf_action, ++ .refcnt = p->tcf_refcnt - ref, ++ .bindcnt = p->tcf_bindcnt - bind, ++ }; ++ struct tcf_t t; + + NLA_PUT(skb, TCA_NAT_PARMS, sizeof(opt), &opt); + t.install = jiffies_to_clock_t(jiffies - p->tcf_tm.install); +--- a/net/sched/act_simple.c ++++ b/net/sched/act_simple.c +@@ -163,13 +163,14 @@ static inline int tcf_simp_dump(struct s + { + unsigned char *b = skb_tail_pointer(skb); + struct tcf_defact *d = a->priv; +- struct tc_defact opt; ++ struct tc_defact opt = { ++ .index = d->tcf_index, ++ .refcnt = d->tcf_refcnt - ref, ++ .bindcnt = d->tcf_bindcnt - bind, ++ .action = d->tcf_action, ++ }; + struct tcf_t t; + +- opt.index = d->tcf_index; +- opt.refcnt = d->tcf_refcnt - ref; +- opt.bindcnt = d->tcf_bindcnt - bind; +- opt.action = d->tcf_action; + NLA_PUT(skb, TCA_DEF_PARMS, sizeof(opt), &opt); + NLA_PUT_STRING(skb, TCA_DEF_DATA, d->tcfd_defdata); + t.install = jiffies_to_clock_t(jiffies - d->tcf_tm.install); +--- a/net/sched/act_skbedit.c ++++ b/net/sched/act_skbedit.c +@@ -147,13 +147,14 @@ static inline int tcf_skbedit_dump(struc + { + unsigned char *b = skb_tail_pointer(skb); + struct tcf_skbedit *d = a->priv; +- struct tc_skbedit opt; ++ struct tc_skbedit opt = { ++ .index = d->tcf_index, ++ .refcnt = d->tcf_refcnt - ref, ++ .bindcnt = d->tcf_bindcnt - bind, ++ .action = d->tcf_action, ++ }; + struct tcf_t t; + +- opt.index = d->tcf_index; +- opt.refcnt = d->tcf_refcnt - ref; +- opt.bindcnt = d->tcf_bindcnt - bind; +- opt.action = d->tcf_action; + NLA_PUT(skb, TCA_SKBEDIT_PARMS, sizeof(opt), &opt); + if (d->flags & SKBEDIT_F_PRIORITY) + NLA_PUT(skb, TCA_SKBEDIT_PRIORITY, sizeof(d->priority), diff --git a/queue-2.6.32/nmi-fix-clock-comparator-revalidation.patch b/queue-2.6.32/nmi-fix-clock-comparator-revalidation.patch new file mode 100644 index 00000000000..e2a14fcd523 --- /dev/null +++ b/queue-2.6.32/nmi-fix-clock-comparator-revalidation.patch @@ -0,0 +1,93 @@ +From e8129c642155616d9e2160a75f103e127c8c3708 Mon Sep 17 00:00:00 2001 +From: Heiko Carstens +Date: Thu, 25 Nov 2010 09:52:45 +0100 +Subject: [S390] nmi: fix clock comparator revalidation + +From: Heiko Carstens + +commit e8129c642155616d9e2160a75f103e127c8c3708 upstream. + +On each machine check all registers are revalidated. The save area for +the clock comparator however only contains the upper most seven bytes +of the former contents, if valid. +Therefore the machine check handler uses a store clock instruction to +get the current time and writes that to the clock comparator register +which in turn will generate an immediate timer interrupt. +However within the lowcore the expected time of the next timer +interrupt is stored. If the interrupt happens before that time the +handler won't be called. In turn the clock comparator won't be +reprogrammed and therefore the interrupt condition stays pending which +causes an interrupt loop until the expected time is reached. + +On NOHZ machines this can result in unresponsive machines since the +time of the next expected interrupted can be a couple of days in the +future. + +To fix this just revalidate the clock comparator register with the +expected value. +In addition the special handling for udelay must be changed as well. + +Signed-off-by: Heiko Carstens +Signed-off-by: Martin Schwidefsky +Signed-off-by: Greg Kroah-Hartman + +--- + arch/s390/kernel/nmi.c | 10 ++++------ + arch/s390/lib/delay.c | 14 +++++++++----- + 2 files changed, 13 insertions(+), 11 deletions(-) + +--- a/arch/s390/kernel/nmi.c ++++ b/arch/s390/kernel/nmi.c +@@ -95,7 +95,6 @@ EXPORT_SYMBOL_GPL(s390_handle_mcck); + static int notrace s390_revalidate_registers(struct mci *mci) + { + int kill_task; +- u64 tmpclock; + u64 zero; + void *fpt_save_area, *fpt_creg_save_area; + +@@ -214,11 +213,10 @@ static int notrace s390_revalidate_regis + : "0", "cc"); + #endif + /* Revalidate clock comparator register */ +- asm volatile( +- " stck 0(%1)\n" +- " sckc 0(%1)" +- : "=m" (tmpclock) : "a" (&(tmpclock)) : "cc", "memory"); +- ++ if (S390_lowcore.clock_comparator == -1) ++ set_clock_comparator(S390_lowcore.mcck_clock); ++ else ++ set_clock_comparator(S390_lowcore.clock_comparator); + /* Check if old PSW is valid */ + if (!mci->wp) + /* +--- a/arch/s390/lib/delay.c ++++ b/arch/s390/lib/delay.c +@@ -29,17 +29,21 @@ static void __udelay_disabled(unsigned l + { + unsigned long mask, cr0, cr0_saved; + u64 clock_saved; ++ u64 end; + ++ mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT; ++ end = get_clock() + (usecs << 12); + clock_saved = local_tick_disable(); +- set_clock_comparator(get_clock() + (usecs << 12)); + __ctl_store(cr0_saved, 0, 0); + cr0 = (cr0_saved & 0xffff00e0) | 0x00000800; + __ctl_load(cr0 , 0, 0); +- mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT; + lockdep_off(); +- trace_hardirqs_on(); +- __load_psw_mask(mask); +- local_irq_disable(); ++ do { ++ set_clock_comparator(end); ++ trace_hardirqs_on(); ++ __load_psw_mask(mask); ++ local_irq_disable(); ++ } while (get_clock() < end); + lockdep_on(); + __ctl_load(cr0_saved, 0, 0); + local_tick_enable(clock_saved); diff --git a/queue-2.6.32/series b/queue-2.6.32/series index 94a3d190c4c..58e34bd1cd4 100644 --- a/queue-2.6.32/series +++ b/queue-2.6.32/series @@ -118,3 +118,12 @@ econet-fix-cve-2010-3850.patch rds-integer-overflow-in-rds-cmsg-handling.patch net-truncate-recvfrom-and-sendto-length-to-int_max.patch net-limit-socket-i-o-iovec-total-length-to-int_max.patch +nmi-fix-clock-comparator-revalidation.patch +act_nat-use-stack-variable.patch +net-sched-fix-some-kernel-memory-leaks.patch +uv-xpc-pass-nasid-instead-of-nid-to-gru_create_message_queue.patch +x86-uv-xpc-receive-message-reuse-triggers-invalid-bug_on.patch +x86-uv-xpc_make_first_contact-hang-due-to-not-accepting-active-state.patch +x86-uv-xpc-null-deref-when-mesq-becomes-empty.patch +x86-uv-update-xpc-to-handle-updated-bios-interface.patch +x86-uv-xpc-needs-to-provide-an-abstraction-for-uv_gpa.patch diff --git a/queue-2.6.32/uv-xpc-pass-nasid-instead-of-nid-to-gru_create_message_queue.patch b/queue-2.6.32/uv-xpc-pass-nasid-instead-of-nid-to-gru_create_message_queue.patch new file mode 100644 index 00000000000..747329a5066 --- /dev/null +++ b/queue-2.6.32/uv-xpc-pass-nasid-instead-of-nid-to-gru_create_message_queue.patch @@ -0,0 +1,45 @@ +From 57e6d258b1e41cd7ceb26fa43ce116939d8440b1 Mon Sep 17 00:00:00 2001 +From: Robin Holt +Date: Tue, 15 Dec 2009 16:48:00 -0800 +Subject: UV - XPC: pass nasid instead of nid to gru_create_message_queue + +From: Robin Holt + +commit 57e6d258b1e41cd7ceb26fa43ce116939d8440b1 upstream. + +Currently, the UV xpc code is passing nid to the gru_create_message_queue +instead of nasid as it expects. + +Signed-off-by: Robin Holt +Signed-off-by: Jack Steiner +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/misc/sgi-xp/xpc_uv.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/misc/sgi-xp/xpc_uv.c ++++ b/drivers/misc/sgi-xp/xpc_uv.c +@@ -203,6 +203,7 @@ xpc_create_gru_mq_uv(unsigned int mq_siz + enum xp_retval xp_ret; + int ret; + int nid; ++ int nasid; + int pg_order; + struct page *page; + struct xpc_gru_mq_uv *mq; +@@ -258,9 +259,11 @@ xpc_create_gru_mq_uv(unsigned int mq_siz + goto out_5; + } + ++ nasid = UV_PNODE_TO_NASID(uv_cpu_to_pnode(cpu)); ++ + mmr_value = (struct uv_IO_APIC_route_entry *)&mq->mmr_value; + ret = gru_create_message_queue(mq->gru_mq_desc, mq->address, mq_size, +- nid, mmr_value->vector, mmr_value->dest); ++ nasid, mmr_value->vector, mmr_value->dest); + if (ret != 0) { + dev_err(xpc_part, "gru_create_message_queue() returned " + "error=%d\n", ret); diff --git a/queue-2.6.32/x86-uv-update-xpc-to-handle-updated-bios-interface.patch b/queue-2.6.32/x86-uv-update-xpc-to-handle-updated-bios-interface.patch new file mode 100644 index 00000000000..bf9ee1cf89c --- /dev/null +++ b/queue-2.6.32/x86-uv-update-xpc-to-handle-updated-bios-interface.patch @@ -0,0 +1,219 @@ +From c2c9f115741453715d6b4da1cd2de65af8c7ad86 Mon Sep 17 00:00:00 2001 +From: Robin Holt +Date: Tue, 15 Dec 2009 16:47:56 -0800 +Subject: x86: uv: update XPC to handle updated BIOS interface + +From: Robin Holt + +commit c2c9f115741453715d6b4da1cd2de65af8c7ad86 upstream. + +The UV BIOS has moved the location of some of their pointers to the +"partition reserved page" from memory into a uv hub MMR. The GRU does not +support bcopy operations from MMR space so we need to special case the MMR +addresses using VLOAD operations. + +Additionally, the BIOS call for registering a message queue watchlist has +removed the 'blade' value and eliminated the structure that was being +passed in. This is also reflected in this patch. + +Signed-off-by: Robin Holt +Cc: Jack Steiner +Cc: Ingo Molnar +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/include/asm/uv/bios.h | 11 +---------- + arch/x86/kernel/bios_uv.c | 8 ++------ + drivers/misc/sgi-xp/xp_uv.c | 23 +++++++++++++++++++++++ + drivers/misc/sgi-xp/xpc_partition.c | 13 +++++++++---- + drivers/misc/sgi-xp/xpc_uv.c | 27 +++++++++++++++------------ + 5 files changed, 50 insertions(+), 32 deletions(-) + +--- a/arch/x86/include/asm/uv/bios.h ++++ b/arch/x86/include/asm/uv/bios.h +@@ -76,15 +76,6 @@ union partition_info_u { + }; + }; + +-union uv_watchlist_u { +- u64 val; +- struct { +- u64 blade : 16, +- size : 32, +- filler : 16; +- }; +-}; +- + enum uv_memprotect { + UV_MEMPROT_RESTRICT_ACCESS, + UV_MEMPROT_ALLOW_AMO, +@@ -100,7 +91,7 @@ extern s64 uv_bios_call_reentrant(enum u + + extern s64 uv_bios_get_sn_info(int, int *, long *, long *, long *); + extern s64 uv_bios_freq_base(u64, u64 *); +-extern int uv_bios_mq_watchlist_alloc(int, unsigned long, unsigned int, ++extern int uv_bios_mq_watchlist_alloc(unsigned long, unsigned int, + unsigned long *); + extern int uv_bios_mq_watchlist_free(int, int); + extern s64 uv_bios_change_memprotect(u64, u64, enum uv_memprotect); +--- a/arch/x86/kernel/bios_uv.c ++++ b/arch/x86/kernel/bios_uv.c +@@ -101,21 +101,17 @@ s64 uv_bios_get_sn_info(int fc, int *uvt + } + + int +-uv_bios_mq_watchlist_alloc(int blade, unsigned long addr, unsigned int mq_size, ++uv_bios_mq_watchlist_alloc(unsigned long addr, unsigned int mq_size, + unsigned long *intr_mmr_offset) + { +- union uv_watchlist_u size_blade; + u64 watchlist; + s64 ret; + +- size_blade.size = mq_size; +- size_blade.blade = blade; +- + /* + * bios returns watchlist number or negative error number. + */ + ret = (int)uv_bios_call_irqsave(UV_BIOS_WATCHLIST_ALLOC, addr, +- size_blade.val, (u64)intr_mmr_offset, ++ mq_size, (u64)intr_mmr_offset, + (u64)&watchlist, 0); + if (ret < BIOS_STATUS_SUCCESS) + return ret; +--- a/drivers/misc/sgi-xp/xp_uv.c ++++ b/drivers/misc/sgi-xp/xp_uv.c +@@ -33,11 +33,34 @@ xp_pa_uv(void *addr) + } + + static enum xp_retval ++xp_remote_mmr_read(unsigned long dst_gpa, const unsigned long src_gpa, ++ size_t len) ++{ ++ int ret; ++ unsigned long *dst_va = __va(uv_gpa_to_soc_phys_ram(dst_gpa)); ++ ++ BUG_ON(!uv_gpa_in_mmr_space(src_gpa)); ++ BUG_ON(len != 8); ++ ++ ret = gru_read_gpa(dst_va, src_gpa); ++ if (ret == 0) ++ return xpSuccess; ++ ++ dev_err(xp, "gru_read_gpa() failed, dst_gpa=0x%016lx src_gpa=0x%016lx " ++ "len=%ld\n", dst_gpa, src_gpa, len); ++ return xpGruCopyError; ++} ++ ++ ++static enum xp_retval + xp_remote_memcpy_uv(unsigned long dst_gpa, const unsigned long src_gpa, + size_t len) + { + int ret; + ++ if (uv_gpa_in_mmr_space(src_gpa)) ++ return xp_remote_mmr_read(dst_gpa, src_gpa, len); ++ + ret = gru_copy_gpa(dst_gpa, src_gpa, len); + if (ret == 0) + return xpSuccess; +--- a/drivers/misc/sgi-xp/xpc_partition.c ++++ b/drivers/misc/sgi-xp/xpc_partition.c +@@ -18,6 +18,7 @@ + #include + #include + #include "xpc.h" ++#include + + /* XPC is exiting flag */ + int xpc_exiting; +@@ -92,8 +93,12 @@ xpc_get_rsvd_page_pa(int nasid) + break; + + /* !!! L1_CACHE_ALIGN() is only a sn2-bte_copy requirement */ +- if (L1_CACHE_ALIGN(len) > buf_len) { +- kfree(buf_base); ++ if (is_shub()) ++ len = L1_CACHE_ALIGN(len); ++ ++ if (len > buf_len) { ++ if (buf_base != NULL) ++ kfree(buf_base); + buf_len = L1_CACHE_ALIGN(len); + buf = xpc_kmalloc_cacheline_aligned(buf_len, GFP_KERNEL, + &buf_base); +@@ -105,7 +110,7 @@ xpc_get_rsvd_page_pa(int nasid) + } + } + +- ret = xp_remote_memcpy(xp_pa(buf), rp_pa, buf_len); ++ ret = xp_remote_memcpy(xp_pa(buf), rp_pa, len); + if (ret != xpSuccess) { + dev_dbg(xpc_part, "xp_remote_memcpy failed %d\n", ret); + break; +@@ -143,7 +148,7 @@ xpc_setup_rsvd_page(void) + dev_err(xpc_part, "SAL failed to locate the reserved page\n"); + return -ESRCH; + } +- rp = (struct xpc_rsvd_page *)__va(rp_pa); ++ rp = (struct xpc_rsvd_page *)__va(xp_socket_pa(rp_pa)); + + if (rp->SAL_version < 3) { + /* SAL_versions < 3 had a SAL_partid defined as a u8 */ +--- a/drivers/misc/sgi-xp/xpc_uv.c ++++ b/drivers/misc/sgi-xp/xpc_uv.c +@@ -156,22 +156,24 @@ xpc_gru_mq_watchlist_alloc_uv(struct xpc + { + int ret; + +-#if defined CONFIG_X86_64 +- ret = uv_bios_mq_watchlist_alloc(mq->mmr_blade, uv_gpa(mq->address), +- mq->order, &mq->mmr_offset); +- if (ret < 0) { +- dev_err(xpc_part, "uv_bios_mq_watchlist_alloc() failed, " +- "ret=%d\n", ret); +- return ret; +- } +-#elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV +- ret = sn_mq_watchlist_alloc(mq->mmr_blade, (void *)uv_gpa(mq->address), ++#if defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV ++ int mmr_pnode = uv_blade_to_pnode(mq->mmr_blade); ++ ++ ret = sn_mq_watchlist_alloc(mmr_pnode, (void *)uv_gpa(mq->address), + mq->order, &mq->mmr_offset); + if (ret < 0) { + dev_err(xpc_part, "sn_mq_watchlist_alloc() failed, ret=%d\n", + ret); + return -EBUSY; + } ++#elif defined CONFIG_X86_64 ++ ret = uv_bios_mq_watchlist_alloc(uv_gpa(mq->address), ++ mq->order, &mq->mmr_offset); ++ if (ret < 0) { ++ dev_err(xpc_part, "uv_bios_mq_watchlist_alloc() failed, " ++ "ret=%d\n", ret); ++ return ret; ++ } + #else + #error not a supported configuration + #endif +@@ -184,12 +186,13 @@ static void + xpc_gru_mq_watchlist_free_uv(struct xpc_gru_mq_uv *mq) + { + int ret; ++ int mmr_pnode = uv_blade_to_pnode(mq->mmr_blade); + + #if defined CONFIG_X86_64 +- ret = uv_bios_mq_watchlist_free(mq->mmr_blade, mq->watchlist_num); ++ ret = uv_bios_mq_watchlist_free(mmr_pnode, mq->watchlist_num); + BUG_ON(ret != BIOS_STATUS_SUCCESS); + #elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV +- ret = sn_mq_watchlist_free(mq->mmr_blade, mq->watchlist_num); ++ ret = sn_mq_watchlist_free(mmr_pnode, mq->watchlist_num); + BUG_ON(ret != SALRET_OK); + #else + #error not a supported configuration diff --git a/queue-2.6.32/x86-uv-xpc-needs-to-provide-an-abstraction-for-uv_gpa.patch b/queue-2.6.32/x86-uv-xpc-needs-to-provide-an-abstraction-for-uv_gpa.patch new file mode 100644 index 00000000000..47b6735bca0 --- /dev/null +++ b/queue-2.6.32/x86-uv-xpc-needs-to-provide-an-abstraction-for-uv_gpa.patch @@ -0,0 +1,100 @@ +From 682128939f546e3a9cdd9fef392b932dd9c41a65 Mon Sep 17 00:00:00 2001 +From: Robin Holt +Date: Tue, 15 Dec 2009 16:47:53 -0800 +Subject: x86: uv: xpc needs to provide an abstraction for uv_gpa + +From: Robin Holt + +commit 682128939f546e3a9cdd9fef392b932dd9c41a65 upstream. + +Provide an SGI SN2/UV agnositic method for converting a global physical +address into a socket physical address. + +Signed-off-by: Robin Holt +Cc: Jack Steiner +Cc: Ingo Molnar +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/misc/sgi-xp/xp.h | 1 + + drivers/misc/sgi-xp/xp_main.c | 3 +++ + drivers/misc/sgi-xp/xp_sn2.c | 10 ++++++++++ + drivers/misc/sgi-xp/xp_uv.c | 10 ++++++++++ + 4 files changed, 24 insertions(+) + +--- a/drivers/misc/sgi-xp/xp.h ++++ b/drivers/misc/sgi-xp/xp.h +@@ -339,6 +339,7 @@ extern short xp_partition_id; + extern u8 xp_region_size; + + extern unsigned long (*xp_pa) (void *); ++extern unsigned long (*xp_socket_pa) (unsigned long); + extern enum xp_retval (*xp_remote_memcpy) (unsigned long, const unsigned long, + size_t); + extern int (*xp_cpu_to_nasid) (int); +--- a/drivers/misc/sgi-xp/xp_main.c ++++ b/drivers/misc/sgi-xp/xp_main.c +@@ -44,6 +44,9 @@ EXPORT_SYMBOL_GPL(xp_region_size); + unsigned long (*xp_pa) (void *addr); + EXPORT_SYMBOL_GPL(xp_pa); + ++unsigned long (*xp_socket_pa) (unsigned long gpa); ++EXPORT_SYMBOL_GPL(xp_socket_pa); ++ + enum xp_retval (*xp_remote_memcpy) (unsigned long dst_gpa, + const unsigned long src_gpa, size_t len); + EXPORT_SYMBOL_GPL(xp_remote_memcpy); +--- a/drivers/misc/sgi-xp/xp_sn2.c ++++ b/drivers/misc/sgi-xp/xp_sn2.c +@@ -84,6 +84,15 @@ xp_pa_sn2(void *addr) + } + + /* ++ * Convert a global physical to a socket physical address. ++ */ ++static unsigned long ++xp_socket_pa_sn2(unsigned long gpa) ++{ ++ return gpa; ++} ++ ++/* + * Wrapper for bte_copy(). + * + * dst_pa - physical address of the destination of the transfer. +@@ -162,6 +171,7 @@ xp_init_sn2(void) + xp_region_size = sn_region_size; + + xp_pa = xp_pa_sn2; ++ xp_socket_pa = xp_socket_pa_sn2; + xp_remote_memcpy = xp_remote_memcpy_sn2; + xp_cpu_to_nasid = xp_cpu_to_nasid_sn2; + xp_expand_memprotect = xp_expand_memprotect_sn2; +--- a/drivers/misc/sgi-xp/xp_uv.c ++++ b/drivers/misc/sgi-xp/xp_uv.c +@@ -32,6 +32,15 @@ xp_pa_uv(void *addr) + return uv_gpa(addr); + } + ++/* ++ * Convert a global physical to socket physical address. ++ */ ++static unsigned long ++xp_socket_pa_uv(unsigned long gpa) ++{ ++ return uv_gpa_to_soc_phys_ram(gpa); ++} ++ + static enum xp_retval + xp_remote_mmr_read(unsigned long dst_gpa, const unsigned long src_gpa, + size_t len) +@@ -146,6 +155,7 @@ xp_init_uv(void) + xp_region_size = sn_region_size; + + xp_pa = xp_pa_uv; ++ xp_socket_pa = xp_socket_pa_uv; + xp_remote_memcpy = xp_remote_memcpy_uv; + xp_cpu_to_nasid = xp_cpu_to_nasid_uv; + xp_expand_memprotect = xp_expand_memprotect_uv; diff --git a/queue-2.6.32/x86-uv-xpc-null-deref-when-mesq-becomes-empty.patch b/queue-2.6.32/x86-uv-xpc-null-deref-when-mesq-becomes-empty.patch new file mode 100644 index 00000000000..12df048e319 --- /dev/null +++ b/queue-2.6.32/x86-uv-xpc-null-deref-when-mesq-becomes-empty.patch @@ -0,0 +1,43 @@ +From 15b87d67ff3dc042bee42f991858d6b121b3b3ca Mon Sep 17 00:00:00 2001 +From: Robin Holt +Date: Tue, 15 Dec 2009 16:47:57 -0800 +Subject: x86: uv: xpc NULL deref when mesq becomes empty + +From: Robin Holt + +commit 15b87d67ff3dc042bee42f991858d6b121b3b3ca upstream. + +Under heavy load conditions, our set of xpc messages may become exhausted. + The code handles this correctly with the exception of the management code +which hits a NULL pointer dereference. + +Signed-off-by: Robin Holt +Cc: Jack Steiner +Cc: Ingo Molnar +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/misc/sgi-xp/xpc_uv.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +--- a/drivers/misc/sgi-xp/xpc_uv.c ++++ b/drivers/misc/sgi-xp/xpc_uv.c +@@ -965,11 +965,13 @@ xpc_get_fifo_entry_uv(struct xpc_fifo_he + head->first = first->next; + if (head->first == NULL) + head->last = NULL; ++ ++ head->n_entries--; ++ BUG_ON(head->n_entries < 0); ++ ++ first->next = NULL; + } +- head->n_entries--; +- BUG_ON(head->n_entries < 0); + spin_unlock_irqrestore(&head->lock, irq_flags); +- first->next = NULL; + return first; + } + diff --git a/queue-2.6.32/x86-uv-xpc-receive-message-reuse-triggers-invalid-bug_on.patch b/queue-2.6.32/x86-uv-xpc-receive-message-reuse-triggers-invalid-bug_on.patch new file mode 100644 index 00000000000..c989ec5fee5 --- /dev/null +++ b/queue-2.6.32/x86-uv-xpc-receive-message-reuse-triggers-invalid-bug_on.patch @@ -0,0 +1,63 @@ +From 046d6c563b1c6226bbf0f84e5b2413ad8ab921a1 Mon Sep 17 00:00:00 2001 +From: Robin Holt +Date: Tue, 15 Dec 2009 16:47:59 -0800 +Subject: x86: uv: XPC receive message reuse triggers invalid BUG_ON() + +From: Robin Holt + +commit 046d6c563b1c6226bbf0f84e5b2413ad8ab921a1 upstream. + +This was a difficult bug to trip. XPC was in the middle of sending an +acknowledgement for a received message. + +In xpc_received_payload_uv(): +. + ret = xpc_send_gru_msg(ch->sn.uv.cached_notify_gru_mq_desc, msg, + sizeof(struct xpc_notify_mq_msghdr_uv)); + if (ret != xpSuccess) + XPC_DEACTIVATE_PARTITION(&xpc_partitions[ch->partid], ret); + + msg->hdr.msg_slot_number += ch->remote_nentries; + +at the point in xpc_send_gru_msg() where the hardware has dispatched the +acknowledgement, the remote side is able to reuse the message structure +and send a message with a different slot number. This problem is made +worse by interrupts. + +The adjustment of msg_slot_number and the BUG_ON in +xpc_handle_notify_mq_msg_uv() which verifies the msg_slot_number is +consistent are only used for debug purposes. Since a fix for this that +preserves the debug functionality would either have to infringe upon the +payload or allocate another structure just for debug, I decided to remove +it entirely. + +Signed-off-by: Robin Holt +Cc: Jack Steiner +Cc: Ingo Molnar +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/misc/sgi-xp/xpc_uv.c | 3 --- + 1 file changed, 3 deletions(-) + +--- a/drivers/misc/sgi-xp/xpc_uv.c ++++ b/drivers/misc/sgi-xp/xpc_uv.c +@@ -1441,7 +1441,6 @@ xpc_handle_notify_mq_msg_uv(struct xpc_p + msg_slot = ch_uv->recv_msg_slots + + (msg->hdr.msg_slot_number % ch->remote_nentries) * ch->entry_size; + +- BUG_ON(msg->hdr.msg_slot_number != msg_slot->hdr.msg_slot_number); + BUG_ON(msg_slot->hdr.size != 0); + + memcpy(msg_slot, msg, msg->hdr.size); +@@ -1665,8 +1664,6 @@ xpc_received_payload_uv(struct xpc_chann + sizeof(struct xpc_notify_mq_msghdr_uv)); + if (ret != xpSuccess) + XPC_DEACTIVATE_PARTITION(&xpc_partitions[ch->partid], ret); +- +- msg->hdr.msg_slot_number += ch->remote_nentries; + } + + static struct xpc_arch_operations xpc_arch_ops_uv = { diff --git a/queue-2.6.32/x86-uv-xpc_make_first_contact-hang-due-to-not-accepting-active-state.patch b/queue-2.6.32/x86-uv-xpc_make_first_contact-hang-due-to-not-accepting-active-state.patch new file mode 100644 index 00000000000..279471faf33 --- /dev/null +++ b/queue-2.6.32/x86-uv-xpc_make_first_contact-hang-due-to-not-accepting-active-state.patch @@ -0,0 +1,41 @@ +From dbd2918ec65c35f36bb102c88eafe87be0552f6f Mon Sep 17 00:00:00 2001 +From: Robin Holt +Date: Tue, 15 Dec 2009 16:47:58 -0800 +Subject: X86: uv: xpc_make_first_contact hang due to not accepting ACTIVE state + +From: Robin Holt + +commit dbd2918ec65c35f36bb102c88eafe87be0552f6f upstream. + +Many times while the initial connection is being made, the contacted +partition will send back both the ACTIVATING and the ACTIVE +remote_act_state changes in very close succescion. The 1/4 second delay +in the make first contact loop is large enough to nearly always miss the +ACTIVATING state change. + +Since either state indicates the remote partition has acknowledged our +state change, accept either. + +Signed-off-by: Robin Holt +Cc: Jack Steiner +Cc: Ingo Molnar +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/misc/sgi-xp/xpc_uv.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/misc/sgi-xp/xpc_uv.c ++++ b/drivers/misc/sgi-xp/xpc_uv.c +@@ -1038,7 +1038,8 @@ xpc_make_first_contact_uv(struct xpc_par + xpc_send_activate_IRQ_part_uv(part, &msg, sizeof(msg), + XPC_ACTIVATE_MQ_MSG_SYNC_ACT_STATE_UV); + +- while (part->sn.uv.remote_act_state != XPC_P_AS_ACTIVATING) { ++ while (!((part->sn.uv.remote_act_state == XPC_P_AS_ACTIVATING) || ++ (part->sn.uv.remote_act_state == XPC_P_AS_ACTIVE))) { + + dev_dbg(xpc_part, "waiting to make first contact with " + "partition %d\n", XPC_PARTID(part)); -- 2.47.3