From: Greg Kroah-Hartman Date: Sun, 27 May 2012 00:20:42 +0000 (+0900) Subject: 3.3-stable patches X-Git-Tag: v3.0.33~6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4706c5bc070d002eaeb663c51149d055d7cbebe9;p=thirdparty%2Fkernel%2Fstable-queue.git 3.3-stable patches added patches: arm-7365-1-drop-unused-parameter-from-flush_cache_user_range.patch arm-7409-1-do-not-call-flush_cache_user_range-with-mmap_sem-held.patch i2c-davinci-free-requested-irq-in-remove.patch i2c-tegra-notify-transfer-complete-after-clearing-status.patch intel-iommu-add-device-info-into-list-before-doing-context-mapping.patch iommu-fix-off-by-one-in-dmar_get_fault_reason.patch mce-fix-vm86-handling-for-32bit-mce-handler.patch mmc-cd-gpio-protect-against-null-context-in-mmc_cd_gpio_free.patch mmc-omap_hsmmc-pass-irqf_oneshot-to-request_threaded_irq.patch mmc-sdio-avoid-spurious-calls-to-interrupt-handlers.patch rtlwifi-fix-for-race-condition-when-firmware-is-cached.patch tile-fix-bug-where-fls-0-was-not-returning-0.patch x86-32-relocs-whitelist-more-symbols-for-ld-bug-workaround.patch x86-mce-fix-check-for-processor-context-when-machine-check-was-taken.patch x86-realmode-16-bit-real-mode-code-support-for-relocs-tool.patch x86-relocs-add-jiffies-and-jiffies_64-to-the-relative-whitelist.patch x86-relocs-build-clean-fix.patch x86-relocs-when-printing-an-error-say-relative-or-absolute.patch x86-relocs-workaround-for-binutils-2.22.52.0.1-section-bug.patch --- diff --git a/queue-3.3/arm-7365-1-drop-unused-parameter-from-flush_cache_user_range.patch b/queue-3.3/arm-7365-1-drop-unused-parameter-from-flush_cache_user_range.patch new file mode 100644 index 00000000000..c5708fd0985 --- /dev/null +++ b/queue-3.3/arm-7365-1-drop-unused-parameter-from-flush_cache_user_range.patch @@ -0,0 +1,56 @@ +From 4542b6a0fa6b48d9ae6b41c1efeb618b7a221b2a Mon Sep 17 00:00:00 2001 +From: Dima Zavin +Date: Thu, 29 Mar 2012 20:44:06 +0100 +Subject: ARM: 7365/1: drop unused parameter from flush_cache_user_range +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Dima Zavin + +commit 4542b6a0fa6b48d9ae6b41c1efeb618b7a221b2a upstream. + +vma isn't used and flush_cache_user_range isn't a standard macro that +is used on several archs with the same prototype. In fact only unicore32 +has a macro with the same name (with an identical implementation and no +in-tree users). + +This is a part of a patch proposed by Dima Zavin (with Message-id: +1272439931-12795-1-git-send-email-dima@android.com) that didn't get +accepted. + +Cc: Dima Zavin +Acked-by: Catalin Marinas +Signed-off-by: Uwe Kleine-König +Signed-off-by: Russell King +Cc: Will Deacon +Signed-off-by: Greg Kroah-Hartman + + +--- + arch/arm/include/asm/cacheflush.h | 2 +- + arch/arm/kernel/traps.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +--- a/arch/arm/include/asm/cacheflush.h ++++ b/arch/arm/include/asm/cacheflush.h +@@ -249,7 +249,7 @@ extern void flush_cache_page(struct vm_a + * Harvard caches are synchronised for the user space address range. + * This is used for the ARM private sys_cacheflush system call. + */ +-#define flush_cache_user_range(vma,start,end) \ ++#define flush_cache_user_range(start,end) \ + __cpuc_coherent_user_range((start) & PAGE_MASK, PAGE_ALIGN(end)) + + /* +--- a/arch/arm/kernel/traps.c ++++ b/arch/arm/kernel/traps.c +@@ -491,7 +491,7 @@ do_cache_op(unsigned long start, unsigne + if (end > vma->vm_end) + end = vma->vm_end; + +- flush_cache_user_range(vma, start, end); ++ flush_cache_user_range(start, end); + } + up_read(&mm->mmap_sem); + } diff --git a/queue-3.3/arm-7409-1-do-not-call-flush_cache_user_range-with-mmap_sem-held.patch b/queue-3.3/arm-7409-1-do-not-call-flush_cache_user_range-with-mmap_sem-held.patch new file mode 100644 index 00000000000..03bb8641e07 --- /dev/null +++ b/queue-3.3/arm-7409-1-do-not-call-flush_cache_user_range-with-mmap_sem-held.patch @@ -0,0 +1,42 @@ +From 435a7ef52db7d86e67a009b36cac1457f8972391 Mon Sep 17 00:00:00 2001 +From: Dima Zavin +Date: Mon, 30 Apr 2012 10:26:14 +0100 +Subject: ARM: 7409/1: Do not call flush_cache_user_range with mmap_sem held + +From: Dima Zavin + +commit 435a7ef52db7d86e67a009b36cac1457f8972391 upstream. + +We can't be holding the mmap_sem while calling flush_cache_user_range +because the flush can fault. If we fault on a user address, the +page fault handler will try to take mmap_sem again. Since both places +acquire the read lock, most of the time it succeeds. However, if another +thread tries to acquire the write lock on the mmap_sem (e.g. mmap) in +between the call to flush_cache_user_range and the fault, the down_read +in do_page_fault will deadlock. + +[will: removed drop of vma parameter as already queued by rmk (7365/1)] + +Acked-by: Catalin Marinas +Signed-off-by: Dima Zavin +Signed-off-by: John Stultz +Signed-off-by: Will Deacon +Signed-off-by: Russell King +Signed-off-by: Greg Kroah-Hartman + +--- + arch/arm/kernel/traps.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/arm/kernel/traps.c ++++ b/arch/arm/kernel/traps.c +@@ -491,7 +491,9 @@ do_cache_op(unsigned long start, unsigne + if (end > vma->vm_end) + end = vma->vm_end; + ++ up_read(&mm->mmap_sem); + flush_cache_user_range(start, end); ++ return; + } + up_read(&mm->mmap_sem); + } diff --git a/queue-3.3/i2c-davinci-free-requested-irq-in-remove.patch b/queue-3.3/i2c-davinci-free-requested-irq-in-remove.patch new file mode 100644 index 00000000000..974db2f256c --- /dev/null +++ b/queue-3.3/i2c-davinci-free-requested-irq-in-remove.patch @@ -0,0 +1,31 @@ +From 9868a060ccf769c08ec378a9829137e272e9a92c Mon Sep 17 00:00:00 2001 +From: Marcus Folkesson +Date: Thu, 3 May 2012 15:56:36 +0200 +Subject: i2c: davinci: Free requested IRQ in remove + +From: Marcus Folkesson + +commit 9868a060ccf769c08ec378a9829137e272e9a92c upstream. + +The freed IRQ is not necessary the one requested in probe. +Even if it was, with two or more i2c-controllers it will fails anyway. + +Signed-off-by: Marcus Folkesson +Signed-off-by: Wolfram Sang +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/i2c/busses/i2c-davinci.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/i2c/busses/i2c-davinci.c ++++ b/drivers/i2c/busses/i2c-davinci.c +@@ -755,7 +755,7 @@ static int davinci_i2c_remove(struct pla + dev->clk = NULL; + + davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, 0); +- free_irq(IRQ_I2C, dev); ++ free_irq(dev->irq, dev); + iounmap(dev->base); + kfree(dev); + diff --git a/queue-3.3/i2c-tegra-notify-transfer-complete-after-clearing-status.patch b/queue-3.3/i2c-tegra-notify-transfer-complete-after-clearing-status.patch new file mode 100644 index 00000000000..c4f20145fb2 --- /dev/null +++ b/queue-3.3/i2c-tegra-notify-transfer-complete-after-clearing-status.patch @@ -0,0 +1,70 @@ +From c889e91d2cc22123f20f40dde0c0a91856a20eea Mon Sep 17 00:00:00 2001 +From: Laxman Dewangan +Date: Mon, 7 May 2012 12:16:19 +0530 +Subject: i2c: tegra: notify transfer-complete after clearing status. + +From: Laxman Dewangan + +commit c889e91d2cc22123f20f40dde0c0a91856a20eea upstream. + +The notification of the transfer complete by calling complete() +should be done after clearing all interrupt status. +This avoids the race condition of misconfigure the i2c controller +in multi-core environment. + +Signed-off-by: Laxman Dewangan +Acked-by: Stephen Warren +Signed-off-by: Wolfram Sang +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/i2c/busses/i2c-tegra.c | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +--- a/drivers/i2c/busses/i2c-tegra.c ++++ b/drivers/i2c/busses/i2c-tegra.c +@@ -401,8 +401,6 @@ static irqreturn_t tegra_i2c_isr(int irq + disable_irq_nosync(i2c_dev->irq); + i2c_dev->irq_disabled = 1; + } +- +- complete(&i2c_dev->msg_complete); + goto err; + } + +@@ -411,7 +409,6 @@ static irqreturn_t tegra_i2c_isr(int irq + i2c_dev->msg_err |= I2C_ERR_NO_ACK; + if (status & I2C_INT_ARBITRATION_LOST) + i2c_dev->msg_err |= I2C_ERR_ARBITRATION_LOST; +- complete(&i2c_dev->msg_complete); + goto err; + } + +@@ -429,14 +426,14 @@ static irqreturn_t tegra_i2c_isr(int irq + tegra_i2c_mask_irq(i2c_dev, I2C_INT_TX_FIFO_DATA_REQ); + } + ++ i2c_writel(i2c_dev, status, I2C_INT_STATUS); ++ if (i2c_dev->is_dvc) ++ dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS); ++ + if (status & I2C_INT_PACKET_XFER_COMPLETE) { + BUG_ON(i2c_dev->msg_buf_remaining); + complete(&i2c_dev->msg_complete); + } +- +- i2c_writel(i2c_dev, status, I2C_INT_STATUS); +- if (i2c_dev->is_dvc) +- dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS); + return IRQ_HANDLED; + err: + /* An error occurred, mask all interrupts */ +@@ -446,6 +443,8 @@ err: + i2c_writel(i2c_dev, status, I2C_INT_STATUS); + if (i2c_dev->is_dvc) + dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS); ++ ++ complete(&i2c_dev->msg_complete); + return IRQ_HANDLED; + } + diff --git a/queue-3.3/intel-iommu-add-device-info-into-list-before-doing-context-mapping.patch b/queue-3.3/intel-iommu-add-device-info-into-list-before-doing-context-mapping.patch new file mode 100644 index 00000000000..4f683da6931 --- /dev/null +++ b/queue-3.3/intel-iommu-add-device-info-into-list-before-doing-context-mapping.patch @@ -0,0 +1,60 @@ +From e2ad23d04c1304431ab5176c89b7b476ded2d995 Mon Sep 17 00:00:00 2001 +From: David Woodhouse +Date: Fri, 25 May 2012 17:42:54 +0100 +Subject: intel-iommu: Add device info into list before doing context mapping + +From: David Woodhouse + +commit e2ad23d04c1304431ab5176c89b7b476ded2d995 upstream. + +Add device info into list before doing context mapping, because device +info will be used by iommu_enable_dev_iotlb(). Without it, ATS won't get +enabled as it should be. + +ATS, while a dubious decision from a security point of view, can be very +important for performance. + +Signed-off-by: Xudong Hao +Signed-off-by: Xiantao Zhang +Acked-by: Chris Wright +Signed-off-by: David Woodhouse +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/iommu/intel-iommu.c | 17 +++++++++++------ + 1 file changed, 11 insertions(+), 6 deletions(-) + +--- a/drivers/iommu/intel-iommu.c ++++ b/drivers/iommu/intel-iommu.c +@@ -2280,12 +2280,6 @@ static int domain_add_dev_info(struct dm + if (!info) + return -ENOMEM; + +- ret = domain_context_mapping(domain, pdev, translation); +- if (ret) { +- free_devinfo_mem(info); +- return ret; +- } +- + info->segment = pci_domain_nr(pdev->bus); + info->bus = pdev->bus->number; + info->devfn = pdev->devfn; +@@ -2298,6 +2292,17 @@ static int domain_add_dev_info(struct dm + pdev->dev.archdata.iommu = info; + spin_unlock_irqrestore(&device_domain_lock, flags); + ++ ret = domain_context_mapping(domain, pdev, translation); ++ if (ret) { ++ spin_lock_irqsave(&device_domain_lock, flags); ++ list_del(&info->link); ++ list_del(&info->global); ++ pdev->dev.archdata.iommu = NULL; ++ spin_unlock_irqrestore(&device_domain_lock, flags); ++ free_devinfo_mem(info); ++ return ret; ++ } ++ + return 0; + } + diff --git a/queue-3.3/iommu-fix-off-by-one-in-dmar_get_fault_reason.patch b/queue-3.3/iommu-fix-off-by-one-in-dmar_get_fault_reason.patch new file mode 100644 index 00000000000..3c790c28eff --- /dev/null +++ b/queue-3.3/iommu-fix-off-by-one-in-dmar_get_fault_reason.patch @@ -0,0 +1,38 @@ +From: Dan Carpenter +Date: Sun, 13 May 2012 20:09:38 +0300 +Subject: iommu: Fix off by one in dmar_get_fault_reason() + +From: Dan Carpenter + +commit fefe1ed1398b81e3fadc92d11d91162d343c8836 upstream. + +fault_reason - 0x20 == ARRAY_SIZE(irq_remap_fault_reasons) is +one past the end of the array. + +Signed-off-by: Dan Carpenter +Cc: Joerg Roedel +Cc: Youquan Song +Cc: walter harms +Cc: Suresh Siddha +Link: http://lkml.kernel.org/r/20120513170938.GA4280@elgon.mountain +Signed-off-by: Ingo Molnar +[bwh: Backported to 3.2: s/irq_remap_fault_reasons/intr_remap_fault_reasons/] +Signed-off-by: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iommu/dmar.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/iommu/dmar.c ++++ b/drivers/iommu/dmar.c +@@ -1056,8 +1056,8 @@ static const char *intr_remap_fault_reas + + const char *dmar_get_fault_reason(u8 fault_reason, int *fault_type) + { +- if (fault_reason >= 0x20 && (fault_reason <= 0x20 + +- ARRAY_SIZE(intr_remap_fault_reasons))) { ++ if (fault_reason >= 0x20 && (fault_reason - 0x20 < ++ ARRAY_SIZE(intr_remap_fault_reasons))) { + *fault_type = INTR_REMAP; + return intr_remap_fault_reasons[fault_reason - 0x20]; + } else if (fault_reason < ARRAY_SIZE(dma_remap_fault_reasons)) { diff --git a/queue-3.3/mce-fix-vm86-handling-for-32bit-mce-handler.patch b/queue-3.3/mce-fix-vm86-handling-for-32bit-mce-handler.patch new file mode 100644 index 00000000000..fda5bb4b411 --- /dev/null +++ b/queue-3.3/mce-fix-vm86-handling-for-32bit-mce-handler.patch @@ -0,0 +1,41 @@ +From a129a7c84582629741e5fa6f40026efcd7a65bd4 Mon Sep 17 00:00:00 2001 +From: Andi Kleen +Date: Fri, 19 Nov 2010 13:16:22 +0100 +Subject: MCE: Fix vm86 handling for 32bit mce handler + +From: Andi Kleen + +commit a129a7c84582629741e5fa6f40026efcd7a65bd4 upstream. + +When running on 32bit the mce handler could misinterpret +vm86 mode as ring 0. This can affect whether it does recovery +or not; it was possible to panic when recovery was actually +possible. + +Fix this by always forcing vm86 to look like ring 3. + +Signed-off-by: Andi Kleen +Signed-off-by: Tony Luck +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/kernel/cpu/mcheck/mce.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/arch/x86/kernel/cpu/mcheck/mce.c ++++ b/arch/x86/kernel/cpu/mcheck/mce.c +@@ -437,6 +437,14 @@ static inline void mce_gather_info(struc + if (m->mcgstatus & (MCG_STATUS_RIPV|MCG_STATUS_EIPV)) { + m->ip = regs->ip; + m->cs = regs->cs; ++ ++ /* ++ * When in VM86 mode make the cs look like ring 3 ++ * always. This is a lie, but it's better than passing ++ * the additional vm86 bit around everywhere. ++ */ ++ if (v8086_mode(regs)) ++ m->cs |= 3; + } + /* Use accurate RIP reporting if available. */ + if (rip_msr) diff --git a/queue-3.3/mmc-cd-gpio-protect-against-null-context-in-mmc_cd_gpio_free.patch b/queue-3.3/mmc-cd-gpio-protect-against-null-context-in-mmc_cd_gpio_free.patch new file mode 100644 index 00000000000..ffbeec6206a --- /dev/null +++ b/queue-3.3/mmc-cd-gpio-protect-against-null-context-in-mmc_cd_gpio_free.patch @@ -0,0 +1,33 @@ +From 0e9f480bb553d39ee06ccd45639ba7a5446a7b81 Mon Sep 17 00:00:00 2001 +From: Guennadi Liakhovetski +Date: Tue, 24 Apr 2012 17:56:29 +0200 +Subject: mmc: cd-gpio: protect against NULL context in mmc_cd_gpio_free() + +From: Guennadi Liakhovetski + +commit 0e9f480bb553d39ee06ccd45639ba7a5446a7b81 upstream. + +Do not oops, even if mmc_cd_gpio_free() is mistakenly called on a driver +cleanup path, even though a previous call to mmc_cd_gpio_request() failed. + +Signed-off-by: Guennadi Liakhovetski +[stable@: please apply to 3.3-stable] +Signed-off-by: Chris Ball +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/mmc/core/cd-gpio.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/mmc/core/cd-gpio.c ++++ b/drivers/mmc/core/cd-gpio.c +@@ -67,6 +67,9 @@ void mmc_cd_gpio_free(struct mmc_host *h + { + struct mmc_cd_gpio *cd = host->hotplug.handler_priv; + ++ if (!cd) ++ return; ++ + free_irq(host->hotplug.irq, host); + gpio_free(cd->gpio); + kfree(cd); diff --git a/queue-3.3/mmc-omap_hsmmc-pass-irqf_oneshot-to-request_threaded_irq.patch b/queue-3.3/mmc-omap_hsmmc-pass-irqf_oneshot-to-request_threaded_irq.patch new file mode 100644 index 00000000000..0c3d7192ba3 --- /dev/null +++ b/queue-3.3/mmc-omap_hsmmc-pass-irqf_oneshot-to-request_threaded_irq.patch @@ -0,0 +1,40 @@ +From db35f83ef47b5f180f2670d11f5f93992314ea09 Mon Sep 17 00:00:00 2001 +From: Ming Lei +Date: Thu, 17 May 2012 10:27:12 +0800 +Subject: mmc: omap_hsmmc: pass IRQF_ONESHOT to request_threaded_irq + +From: Ming Lei + +commit db35f83ef47b5f180f2670d11f5f93992314ea09 upstream. + +The flag of IRQF_ONESHOT should be passed to request_threaded_irq, +otherwise the following failure message should be dumped because +hardware handler is defined as NULL: + +[ 3.383483] genirq: Threaded irq requested with handler=NULL and +!ONESHOT for irq 368 +[ 3.392730] omap_hsmmc: probe of omap_hsmmc.0 failed with error -22 + +The patch fixes one kernel hang bug which is caused by mmc card +probe failure and root device can't be brought up. + +Signed-off-by: Ming Lei +Acked-by: Venkatraman S +Signed-off-by: Chris Ball +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/mmc/host/omap_hsmmc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/mmc/host/omap_hsmmc.c ++++ b/drivers/mmc/host/omap_hsmmc.c +@@ -2034,7 +2034,7 @@ static int __init omap_hsmmc_probe(struc + ret = request_threaded_irq(mmc_slot(host).card_detect_irq, + NULL, + omap_hsmmc_detect, +- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, ++ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + mmc_hostname(mmc), host); + if (ret) { + dev_dbg(mmc_dev(host->mmc), diff --git a/queue-3.3/mmc-sdio-avoid-spurious-calls-to-interrupt-handlers.patch b/queue-3.3/mmc-sdio-avoid-spurious-calls-to-interrupt-handlers.patch new file mode 100644 index 00000000000..03943b8652a --- /dev/null +++ b/queue-3.3/mmc-sdio-avoid-spurious-calls-to-interrupt-handlers.patch @@ -0,0 +1,92 @@ +From bbbc4c4d8c5face097d695f9bf3a39647ba6b7e7 Mon Sep 17 00:00:00 2001 +From: Nicolas Pitre +Date: Mon, 16 Apr 2012 19:16:54 -0400 +Subject: mmc: sdio: avoid spurious calls to interrupt handlers + +From: Nicolas Pitre + +commit bbbc4c4d8c5face097d695f9bf3a39647ba6b7e7 upstream. + +Commit 06e8935feb ("optimized SDIO IRQ handling for single irq") +introduced some spurious calls to SDIO function interrupt handlers, +such as when the SDIO IRQ thread is started, or the safety check +performed upon a system resume. Let's add a flag to perform the +optimization only when a real interrupt is signaled by the host +driver and we know there is no point confirming it. + +Reported-by: Sujit Reddy Thumma +Signed-off-by: Nicolas Pitre +Signed-off-by: Chris Ball +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/mmc/core/sdio.c | 2 +- + drivers/mmc/core/sdio_irq.c | 11 +++++++---- + include/linux/mmc/host.h | 2 ++ + 3 files changed, 10 insertions(+), 5 deletions(-) + +--- a/drivers/mmc/core/sdio.c ++++ b/drivers/mmc/core/sdio.c +@@ -947,7 +947,7 @@ static int mmc_sdio_resume(struct mmc_ho + } + + if (!err && host->sdio_irqs) +- mmc_signal_sdio_irq(host); ++ wake_up_process(host->sdio_irq_thread); + mmc_release_host(host); + + /* +--- a/drivers/mmc/core/sdio_irq.c ++++ b/drivers/mmc/core/sdio_irq.c +@@ -28,18 +28,20 @@ + + #include "sdio_ops.h" + +-static int process_sdio_pending_irqs(struct mmc_card *card) ++static int process_sdio_pending_irqs(struct mmc_host *host) + { ++ struct mmc_card *card = host->card; + int i, ret, count; + unsigned char pending; + struct sdio_func *func; + + /* + * Optimization, if there is only 1 function interrupt registered +- * call irq handler directly ++ * and we know an IRQ was signaled then call irq handler directly. ++ * Otherwise do the full probe. + */ + func = card->sdio_single_irq; +- if (func) { ++ if (func && host->sdio_irq_pending) { + func->irq_handler(func); + return 1; + } +@@ -116,7 +118,8 @@ static int sdio_irq_thread(void *_host) + ret = __mmc_claim_host(host, &host->sdio_irq_thread_abort); + if (ret) + break; +- ret = process_sdio_pending_irqs(host->card); ++ ret = process_sdio_pending_irqs(host); ++ host->sdio_irq_pending = false; + mmc_release_host(host); + + /* +--- a/include/linux/mmc/host.h ++++ b/include/linux/mmc/host.h +@@ -323,6 +323,7 @@ struct mmc_host { + + unsigned int sdio_irqs; + struct task_struct *sdio_irq_thread; ++ bool sdio_irq_pending; + atomic_t sdio_irq_thread_abort; + + mmc_pm_flag_t pm_flags; /* requested pm features */ +@@ -378,6 +379,7 @@ extern int mmc_cache_ctrl(struct mmc_hos + static inline void mmc_signal_sdio_irq(struct mmc_host *host) + { + host->ops->enable_sdio_irq(host, 0); ++ host->sdio_irq_pending = true; + wake_up_process(host->sdio_irq_thread); + } + diff --git a/queue-3.3/rtlwifi-fix-for-race-condition-when-firmware-is-cached.patch b/queue-3.3/rtlwifi-fix-for-race-condition-when-firmware-is-cached.patch new file mode 100644 index 00000000000..14970d1af55 --- /dev/null +++ b/queue-3.3/rtlwifi-fix-for-race-condition-when-firmware-is-cached.patch @@ -0,0 +1,88 @@ +From 574e02abaf816b582685805f0c1150ca9f1f18ee Mon Sep 17 00:00:00 2001 +From: Larry Finger +Date: Fri, 4 May 2012 08:27:43 -0500 +Subject: rtlwifi: fix for race condition when firmware is cached + +From: Larry Finger + +commit 574e02abaf816b582685805f0c1150ca9f1f18ee upstream. + +In commit b0302ab, the rtlwifi family of drivers was converted to use +asynchronous firmware loading. Unfortumately, the implementation was +racy, and the ieee80211 routines could be started before rtl_init_core() +was called to setup the data. + +This patch fixes the bug noted in https://bugzilla.kernel.org/show_bug.cgi?id=43187. + +Reported-by: Joshua Roys +Tested-by: Neptune Ning +Signed-off-by: Larry Finger +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/rtlwifi/pci.c | 17 +++++++++-------- + drivers/net/wireless/rtlwifi/usb.c | 12 ++++++------ + 2 files changed, 15 insertions(+), 14 deletions(-) + +--- a/drivers/net/wireless/rtlwifi/pci.c ++++ b/drivers/net/wireless/rtlwifi/pci.c +@@ -1865,14 +1865,6 @@ int __devinit rtl_pci_probe(struct pci_d + /*like read eeprom and so on */ + rtlpriv->cfg->ops->read_eeprom_info(hw); + +- if (rtlpriv->cfg->ops->init_sw_vars(hw)) { +- RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +- ("Can't init_sw_vars.\n")); +- goto fail3; +- } +- +- rtlpriv->cfg->ops->init_sw_leds(hw); +- + /*aspm */ + rtl_pci_init_aspm(hw); + +@@ -1892,6 +1884,15 @@ int __devinit rtl_pci_probe(struct pci_d + goto fail3; + } + ++ if (rtlpriv->cfg->ops->init_sw_vars(hw)) { ++ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ++ ("Can't init_sw_vars.\n")); ++ err = -ENODEV; ++ goto fail3; ++ } ++ ++ rtlpriv->cfg->ops->init_sw_leds(hw); ++ + err = sysfs_create_group(&pdev->dev.kobj, &rtl_attribute_group); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +--- a/drivers/net/wireless/rtlwifi/usb.c ++++ b/drivers/net/wireless/rtlwifi/usb.c +@@ -970,12 +970,6 @@ int __devinit rtl_usb_probe(struct usb_i + rtlpriv->cfg->ops->read_chip_version(hw); + /*like read eeprom and so on */ + rtlpriv->cfg->ops->read_eeprom_info(hw); +- if (rtlpriv->cfg->ops->init_sw_vars(hw)) { +- RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +- ("Can't init_sw_vars.\n")); +- goto error_out; +- } +- rtlpriv->cfg->ops->init_sw_leds(hw); + err = _rtl_usb_init(hw); + err = _rtl_usb_init_sw(hw); + /* Init mac80211 sw */ +@@ -985,6 +979,12 @@ int __devinit rtl_usb_probe(struct usb_i + ("Can't allocate sw for mac80211.\n")); + goto error_out; + } ++ if (rtlpriv->cfg->ops->init_sw_vars(hw)) { ++ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ++ ("Can't init_sw_vars.\n")); ++ goto error_out; ++ } ++ rtlpriv->cfg->ops->init_sw_leds(hw); + + return 0; + error_out: diff --git a/queue-3.3/series b/queue-3.3/series index e7dce2a3d9b..31b894d7a2c 100644 --- a/queue-3.3/series +++ b/queue-3.3/series @@ -73,3 +73,22 @@ xen-do-not-map-the-same-gsi-twice-in-pvhvm-guests.patch nouveau-nouveau_set_bo_placement-takes-ttm-flags.patch smsusb-add-autodetection-support-for-usb-id-2040-c0a0.patch media-uvcvideo-fix-enuminput-handling.patch +x86-realmode-16-bit-real-mode-code-support-for-relocs-tool.patch +x86-relocs-workaround-for-binutils-2.22.52.0.1-section-bug.patch +x86-relocs-when-printing-an-error-say-relative-or-absolute.patch +x86-relocs-build-clean-fix.patch +x86-32-relocs-whitelist-more-symbols-for-ld-bug-workaround.patch +x86-relocs-add-jiffies-and-jiffies_64-to-the-relative-whitelist.patch +x86-mce-fix-check-for-processor-context-when-machine-check-was-taken.patch +mmc-sdio-avoid-spurious-calls-to-interrupt-handlers.patch +mmc-cd-gpio-protect-against-null-context-in-mmc_cd_gpio_free.patch +mmc-omap_hsmmc-pass-irqf_oneshot-to-request_threaded_irq.patch +tile-fix-bug-where-fls-0-was-not-returning-0.patch +intel-iommu-add-device-info-into-list-before-doing-context-mapping.patch +iommu-fix-off-by-one-in-dmar_get_fault_reason.patch +rtlwifi-fix-for-race-condition-when-firmware-is-cached.patch +arm-7365-1-drop-unused-parameter-from-flush_cache_user_range.patch +arm-7409-1-do-not-call-flush_cache_user_range-with-mmap_sem-held.patch +mce-fix-vm86-handling-for-32bit-mce-handler.patch +i2c-davinci-free-requested-irq-in-remove.patch +i2c-tegra-notify-transfer-complete-after-clearing-status.patch diff --git a/queue-3.3/tile-fix-bug-where-fls-0-was-not-returning-0.patch b/queue-3.3/tile-fix-bug-where-fls-0-was-not-returning-0.patch new file mode 100644 index 00000000000..3b41aab130d --- /dev/null +++ b/queue-3.3/tile-fix-bug-where-fls-0-was-not-returning-0.patch @@ -0,0 +1,48 @@ +From 9f1d62bed7f015d11b9164078b7fea433b474114 Mon Sep 17 00:00:00 2001 +From: Chris Metcalf +Date: Fri, 25 May 2012 12:32:09 -0400 +Subject: tile: fix bug where fls(0) was not returning 0 + +From: Chris Metcalf + +commit 9f1d62bed7f015d11b9164078b7fea433b474114 upstream. + +This is because __builtin_clz(0) returns 64 for the "undefined" case +of 0, since the builtin just does a right-shift 32 and "clz" instruction. +So, use the alpha approach of casting to u32 and using __builtin_clzll(). + +Signed-off-by: Chris Metcalf +Signed-off-by: Greg Kroah-Hartman + +--- + arch/tile/include/asm/bitops.h | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +--- a/arch/tile/include/asm/bitops.h ++++ b/arch/tile/include/asm/bitops.h +@@ -77,6 +77,11 @@ static inline int ffs(int x) + return __builtin_ffs(x); + } + ++static inline int fls64(__u64 w) ++{ ++ return (sizeof(__u64) * 8) - __builtin_clzll(w); ++} ++ + /** + * fls - find last set bit in word + * @x: the word to search +@@ -90,12 +95,7 @@ static inline int ffs(int x) + */ + static inline int fls(int x) + { +- return (sizeof(int) * 8) - __builtin_clz(x); +-} +- +-static inline int fls64(__u64 w) +-{ +- return (sizeof(__u64) * 8) - __builtin_clzll(w); ++ return fls64((unsigned int) x); + } + + static inline unsigned int __arch_hweight32(unsigned int w) diff --git a/queue-3.3/x86-32-relocs-whitelist-more-symbols-for-ld-bug-workaround.patch b/queue-3.3/x86-32-relocs-whitelist-more-symbols-for-ld-bug-workaround.patch new file mode 100644 index 00000000000..722328f822d --- /dev/null +++ b/queue-3.3/x86-32-relocs-whitelist-more-symbols-for-ld-bug-workaround.patch @@ -0,0 +1,70 @@ +From fd952815307f0f272bf49fd364a7fd2f9992bc42 Mon Sep 17 00:00:00 2001 +From: "H. Peter Anvin" +Date: Wed, 23 May 2012 14:02:34 -0700 +Subject: x86-32, relocs: Whitelist more symbols for ld bug workaround + +From: "H. Peter Anvin" + +commit fd952815307f0f272bf49fd364a7fd2f9992bc42 upstream. + +As noted in checkin: + +a3e854d95 x86, relocs: Workaround for binutils 2.22.52.0.1 section bug + +ld version 2.22.52.0.[12] can incorrectly promote relative symbols to +absolute, if the output section they appear in is otherwise empty. + +Since checkin: + +6520fe55 x86, realmode: 16-bit real-mode code support for relocs tool + +we actually check for this and error out rather than silently creating +a kernel which will malfunction if relocated. + +Ingo found a configuration in which __start_builtin_fw triggered the +warning. + +Go through the linker script sources and look for more symbols that +could plausibly get bogusly promoted to absolute, and add them to the +whitelist. + +In general, if the following error triggers: + + Invalid absolute R_386_32 relocation: + +... then we should verify that is really meant to be +relocated, and add it and any related symbols manually to the S_REL +regexp. + +Please note that 6520fe55 does not introduce the error, only the check +for the error -- without 6520fe55 this version of ld will simply +produce a corrupt kernel if CONFIG_RELOCATABLE is set on x86-32. + +Reported-by: Ingo Molnar +Signed-off-by: H. Peter Anvin +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/tools/relocs.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +--- a/arch/x86/tools/relocs.c ++++ b/arch/x86/tools/relocs.c +@@ -60,6 +60,17 @@ static const char * const sym_regex_kern + "__x86_cpu_dev_(start|end)|" + "(__parainstructions|__alt_instructions)(|_end)|" + "(__iommu_table|__apicdrivers|__smp_locks)(|_end)|" ++ "__(start|end)_pci_.*|" ++ "__(start|end)_builtin_fw|" ++ "__(start|stop)___ksymtab(|_gpl|_unused|_unused_gpl|_gpl_future)|" ++ "__(start|stop)___kcrctab(|_gpl|_unused|_unused_gpl|_gpl_future)|" ++ "__(start|stop)___param|" ++ "__(start|stop)___modver|" ++ "__(start|stop)___bug_table|" ++ "__tracedata_(start|end)|" ++ "__(start|stop)_notes|" ++ "__end_rodata|" ++ "__initramfs_start|" + "_end)$" + }; + diff --git a/queue-3.3/x86-mce-fix-check-for-processor-context-when-machine-check-was-taken.patch b/queue-3.3/x86-mce-fix-check-for-processor-context-when-machine-check-was-taken.patch new file mode 100644 index 00000000000..6d9f3707ccf --- /dev/null +++ b/queue-3.3/x86-mce-fix-check-for-processor-context-when-machine-check-was-taken.patch @@ -0,0 +1,50 @@ +From 875e26648cf9b6db9d8dc07b7959d7c61fb3f49c Mon Sep 17 00:00:00 2001 +From: Tony Luck +Date: Wed, 23 May 2012 14:14:22 -0700 +Subject: x86/mce: Fix check for processor context when machine check was taken. + +From: Tony Luck + +commit 875e26648cf9b6db9d8dc07b7959d7c61fb3f49c upstream. + +Linus pointed out that there was no value is checking whether m->ip +was zero - because zero is a legimate value. If we have a reliable +(or faked in the VM86 case) "m->cs" we can use it to tell whether we +were in user mode or kernelwhen the machine check hit. + +Reported-by: Linus Torvalds +Signed-off-by: Tony Luck +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/kernel/cpu/mcheck/mce-severity.c | 16 ++++++++++------ + 1 file changed, 10 insertions(+), 6 deletions(-) + +--- a/arch/x86/kernel/cpu/mcheck/mce-severity.c ++++ b/arch/x86/kernel/cpu/mcheck/mce-severity.c +@@ -145,15 +145,19 @@ static struct severity { + }; + + /* +- * If the EIPV bit is set, it means the saved IP is the +- * instruction which caused the MCE. ++ * If mcgstatus indicated that ip/cs on the stack were ++ * no good, then "m->cs" will be zero and we will have ++ * to assume the worst case (IN_KERNEL) as we actually ++ * have no idea what we were executing when the machine ++ * check hit. ++ * If we do have a good "m->cs" (or a faked one in the ++ * case we were executing in VM86 mode) we can use it to ++ * distinguish an exception taken in user from from one ++ * taken in the kernel. + */ + static int error_context(struct mce *m) + { +- if (m->mcgstatus & MCG_STATUS_EIPV) +- return (m->ip && (m->cs & 3) == 3) ? IN_USER : IN_KERNEL; +- /* Unknown, assume kernel */ +- return IN_KERNEL; ++ return ((m->cs & 3) == 3) ? IN_USER : IN_KERNEL; + } + + int mce_severity(struct mce *m, int tolerant, char **msg) diff --git a/queue-3.3/x86-realmode-16-bit-real-mode-code-support-for-relocs-tool.patch b/queue-3.3/x86-realmode-16-bit-real-mode-code-support-for-relocs-tool.patch new file mode 100644 index 00000000000..fc9954fba64 --- /dev/null +++ b/queue-3.3/x86-realmode-16-bit-real-mode-code-support-for-relocs-tool.patch @@ -0,0 +1,1628 @@ +From 6520fe5564acf07ade7b18a1272db1184835c487 Mon Sep 17 00:00:00 2001 +From: "H. Peter Anvin" +Date: Tue, 8 May 2012 21:22:24 +0300 +Subject: x86, realmode: 16-bit real-mode code support for relocs tool + +From: "H. Peter Anvin" + +commit 6520fe5564acf07ade7b18a1272db1184835c487 upstream. + +A new option is added to the relocs tool called '--realmode'. +This option causes the generation of 16-bit segment relocations +and 32-bit linear relocations for the real-mode code. When +the real-mode code is moved to the low-memory during kernel +initialization, these relocation entries can be used to +relocate the code properly. + +In the assembly code 16-bit segment relocations must be relative +to the 'real_mode_seg' absolute symbol. Linear relocations must be +relative to a symbol prefixed with 'pa_'. + +16-bit segment relocation is used to load cs:ip in 16-bit code. +Linear relocations are used in the 32-bit code for relocatable +data references. They are declared in the linker script of the +real-mode code. + +The relocs tool is moved to arch/x86/tools/relocs.c, and added new +target archscripts that can be used to build scripts needed building +an architecture. be compiled before building the arch/x86 tree. + +[ hpa: accelerating this because it detects invalid absolute + relocations, a serious bug in binutils 2.22.52.0.x which currently + produces bad kernels. ] + +[ jsakkine: applied against 3.3.7 ] + +Signed-off-by: H. Peter Anvin +Link: http://lkml.kernel.org/r/1336501366-28617-2-git-send-email-jarkko.sakkinen@intel.com +Signed-off-by: Jarkko Sakkinen +Signed-off-by: H. Peter Anvin +Signed-off-by: Jarkko Sakkinen +Signed-off-by: Greg Kroah-Hartman +--- + Makefile | 9 + arch/x86/Makefile | 3 + arch/x86/boot/compressed/Makefile | 9 + arch/x86/boot/compressed/relocs.c | 680 -------------------------------- + arch/x86/tools/.gitignore | 1 + arch/x86/tools/Makefile | 4 + arch/x86/tools/relocs.c | 797 ++++++++++++++++++++++++++++++++++++++ + scripts/Makefile | 2 + 8 files changed, 817 insertions(+), 688 deletions(-) + delete mode 100644 arch/x86/boot/compressed/relocs.c + create mode 100644 arch/x86/tools/.gitignore + create mode 100644 arch/x86/tools/relocs.c + +--- a/Makefile ++++ b/Makefile +@@ -442,7 +442,7 @@ asm-generic: + + no-dot-config-targets := clean mrproper distclean \ + cscope gtags TAGS tags help %docs check% coccicheck \ +- include/linux/version.h headers_% archheaders \ ++ include/linux/version.h headers_% archheaders archscripts \ + kernelversion %src-pkg + + config-targets := 0 +@@ -979,7 +979,7 @@ prepare1: prepare2 include/linux/version + include/config/auto.conf + $(cmd_crmodverdir) + +-archprepare: archheaders prepare1 scripts_basic ++archprepare: archheaders archscripts prepare1 scripts_basic + + prepare0: archprepare FORCE + $(Q)$(MAKE) $(build)=. +@@ -1049,8 +1049,11 @@ hdr-dst = $(if $(KBUILD_HEADERS), dst=in + PHONY += archheaders + archheaders: + ++PHONY += archscripts ++archscripts: ++ + PHONY += __headers +-__headers: include/linux/version.h scripts_basic asm-generic archheaders FORCE ++__headers: include/linux/version.h scripts_basic asm-generic archheaders archscripts FORCE + $(Q)$(MAKE) $(build)=scripts build_unifdef + + PHONY += headers_install_all +--- a/arch/x86/Makefile ++++ b/arch/x86/Makefile +@@ -117,6 +117,9 @@ KBUILD_CFLAGS += $(call cc-option,-mno-s + KBUILD_CFLAGS += $(mflags-y) + KBUILD_AFLAGS += $(mflags-y) + ++archscripts: ++ $(Q)$(MAKE) $(build)=arch/x86/tools relocs ++ + ### + # Syscall table generation + +--- a/arch/x86/boot/compressed/Makefile ++++ b/arch/x86/boot/compressed/Makefile +@@ -40,13 +40,12 @@ OBJCOPYFLAGS_vmlinux.bin := -R .comment + $(obj)/vmlinux.bin: vmlinux FORCE + $(call if_changed,objcopy) + ++targets += vmlinux.bin.all vmlinux.relocs + +-targets += vmlinux.bin.all vmlinux.relocs relocs +-hostprogs-$(CONFIG_X86_NEED_RELOCS) += relocs +- ++CMD_RELOCS = arch/x86/tools/relocs + quiet_cmd_relocs = RELOCS $@ +- cmd_relocs = $(obj)/relocs $< > $@;$(obj)/relocs --abs-relocs $< +-$(obj)/vmlinux.relocs: vmlinux $(obj)/relocs FORCE ++ cmd_relocs = $(CMD_RELOCS) $< > $@;$(CMD_RELOCS) --abs-relocs $< ++$(obj)/vmlinux.relocs: vmlinux FORCE + $(call if_changed,relocs) + + vmlinux.bin.all-y := $(obj)/vmlinux.bin +--- a/arch/x86/boot/compressed/relocs.c ++++ /dev/null +@@ -1,680 +0,0 @@ +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#define USE_BSD +-#include +-#include +- +-static void die(char *fmt, ...); +- +-#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +-static Elf32_Ehdr ehdr; +-static unsigned long reloc_count, reloc_idx; +-static unsigned long *relocs; +- +-struct section { +- Elf32_Shdr shdr; +- struct section *link; +- Elf32_Sym *symtab; +- Elf32_Rel *reltab; +- char *strtab; +-}; +-static struct section *secs; +- +-/* +- * Following symbols have been audited. There values are constant and do +- * not change if bzImage is loaded at a different physical address than +- * the address for which it has been compiled. Don't warn user about +- * absolute relocations present w.r.t these symbols. +- */ +-static const char abs_sym_regex[] = +- "^(xen_irq_disable_direct_reloc$|" +- "xen_save_fl_direct_reloc$|" +- "VDSO|" +- "__crc_)"; +-static regex_t abs_sym_regex_c; +-static int is_abs_reloc(const char *sym_name) +-{ +- return !regexec(&abs_sym_regex_c, sym_name, 0, NULL, 0); +-} +- +-/* +- * These symbols are known to be relative, even if the linker marks them +- * as absolute (typically defined outside any section in the linker script.) +- */ +-static const char rel_sym_regex[] = +- "^_end$"; +-static regex_t rel_sym_regex_c; +-static int is_rel_reloc(const char *sym_name) +-{ +- return !regexec(&rel_sym_regex_c, sym_name, 0, NULL, 0); +-} +- +-static void regex_init(void) +-{ +- char errbuf[128]; +- int err; +- +- err = regcomp(&abs_sym_regex_c, abs_sym_regex, +- REG_EXTENDED|REG_NOSUB); +- if (err) { +- regerror(err, &abs_sym_regex_c, errbuf, sizeof errbuf); +- die("%s", errbuf); +- } +- +- err = regcomp(&rel_sym_regex_c, rel_sym_regex, +- REG_EXTENDED|REG_NOSUB); +- if (err) { +- regerror(err, &rel_sym_regex_c, errbuf, sizeof errbuf); +- die("%s", errbuf); +- } +-} +- +-static void die(char *fmt, ...) +-{ +- va_list ap; +- va_start(ap, fmt); +- vfprintf(stderr, fmt, ap); +- va_end(ap); +- exit(1); +-} +- +-static const char *sym_type(unsigned type) +-{ +- static const char *type_name[] = { +-#define SYM_TYPE(X) [X] = #X +- SYM_TYPE(STT_NOTYPE), +- SYM_TYPE(STT_OBJECT), +- SYM_TYPE(STT_FUNC), +- SYM_TYPE(STT_SECTION), +- SYM_TYPE(STT_FILE), +- SYM_TYPE(STT_COMMON), +- SYM_TYPE(STT_TLS), +-#undef SYM_TYPE +- }; +- const char *name = "unknown sym type name"; +- if (type < ARRAY_SIZE(type_name)) { +- name = type_name[type]; +- } +- return name; +-} +- +-static const char *sym_bind(unsigned bind) +-{ +- static const char *bind_name[] = { +-#define SYM_BIND(X) [X] = #X +- SYM_BIND(STB_LOCAL), +- SYM_BIND(STB_GLOBAL), +- SYM_BIND(STB_WEAK), +-#undef SYM_BIND +- }; +- const char *name = "unknown sym bind name"; +- if (bind < ARRAY_SIZE(bind_name)) { +- name = bind_name[bind]; +- } +- return name; +-} +- +-static const char *sym_visibility(unsigned visibility) +-{ +- static const char *visibility_name[] = { +-#define SYM_VISIBILITY(X) [X] = #X +- SYM_VISIBILITY(STV_DEFAULT), +- SYM_VISIBILITY(STV_INTERNAL), +- SYM_VISIBILITY(STV_HIDDEN), +- SYM_VISIBILITY(STV_PROTECTED), +-#undef SYM_VISIBILITY +- }; +- const char *name = "unknown sym visibility name"; +- if (visibility < ARRAY_SIZE(visibility_name)) { +- name = visibility_name[visibility]; +- } +- return name; +-} +- +-static const char *rel_type(unsigned type) +-{ +- static const char *type_name[] = { +-#define REL_TYPE(X) [X] = #X +- REL_TYPE(R_386_NONE), +- REL_TYPE(R_386_32), +- REL_TYPE(R_386_PC32), +- REL_TYPE(R_386_GOT32), +- REL_TYPE(R_386_PLT32), +- REL_TYPE(R_386_COPY), +- REL_TYPE(R_386_GLOB_DAT), +- REL_TYPE(R_386_JMP_SLOT), +- REL_TYPE(R_386_RELATIVE), +- REL_TYPE(R_386_GOTOFF), +- REL_TYPE(R_386_GOTPC), +-#undef REL_TYPE +- }; +- const char *name = "unknown type rel type name"; +- if (type < ARRAY_SIZE(type_name) && type_name[type]) { +- name = type_name[type]; +- } +- return name; +-} +- +-static const char *sec_name(unsigned shndx) +-{ +- const char *sec_strtab; +- const char *name; +- sec_strtab = secs[ehdr.e_shstrndx].strtab; +- name = ""; +- if (shndx < ehdr.e_shnum) { +- name = sec_strtab + secs[shndx].shdr.sh_name; +- } +- else if (shndx == SHN_ABS) { +- name = "ABSOLUTE"; +- } +- else if (shndx == SHN_COMMON) { +- name = "COMMON"; +- } +- return name; +-} +- +-static const char *sym_name(const char *sym_strtab, Elf32_Sym *sym) +-{ +- const char *name; +- name = ""; +- if (sym->st_name) { +- name = sym_strtab + sym->st_name; +- } +- else { +- name = sec_name(secs[sym->st_shndx].shdr.sh_name); +- } +- return name; +-} +- +- +- +-#if BYTE_ORDER == LITTLE_ENDIAN +-#define le16_to_cpu(val) (val) +-#define le32_to_cpu(val) (val) +-#endif +-#if BYTE_ORDER == BIG_ENDIAN +-#define le16_to_cpu(val) bswap_16(val) +-#define le32_to_cpu(val) bswap_32(val) +-#endif +- +-static uint16_t elf16_to_cpu(uint16_t val) +-{ +- return le16_to_cpu(val); +-} +- +-static uint32_t elf32_to_cpu(uint32_t val) +-{ +- return le32_to_cpu(val); +-} +- +-static void read_ehdr(FILE *fp) +-{ +- if (fread(&ehdr, sizeof(ehdr), 1, fp) != 1) { +- die("Cannot read ELF header: %s\n", +- strerror(errno)); +- } +- if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0) { +- die("No ELF magic\n"); +- } +- if (ehdr.e_ident[EI_CLASS] != ELFCLASS32) { +- die("Not a 32 bit executable\n"); +- } +- if (ehdr.e_ident[EI_DATA] != ELFDATA2LSB) { +- die("Not a LSB ELF executable\n"); +- } +- if (ehdr.e_ident[EI_VERSION] != EV_CURRENT) { +- die("Unknown ELF version\n"); +- } +- /* Convert the fields to native endian */ +- ehdr.e_type = elf16_to_cpu(ehdr.e_type); +- ehdr.e_machine = elf16_to_cpu(ehdr.e_machine); +- ehdr.e_version = elf32_to_cpu(ehdr.e_version); +- ehdr.e_entry = elf32_to_cpu(ehdr.e_entry); +- ehdr.e_phoff = elf32_to_cpu(ehdr.e_phoff); +- ehdr.e_shoff = elf32_to_cpu(ehdr.e_shoff); +- ehdr.e_flags = elf32_to_cpu(ehdr.e_flags); +- ehdr.e_ehsize = elf16_to_cpu(ehdr.e_ehsize); +- ehdr.e_phentsize = elf16_to_cpu(ehdr.e_phentsize); +- ehdr.e_phnum = elf16_to_cpu(ehdr.e_phnum); +- ehdr.e_shentsize = elf16_to_cpu(ehdr.e_shentsize); +- ehdr.e_shnum = elf16_to_cpu(ehdr.e_shnum); +- ehdr.e_shstrndx = elf16_to_cpu(ehdr.e_shstrndx); +- +- if ((ehdr.e_type != ET_EXEC) && (ehdr.e_type != ET_DYN)) { +- die("Unsupported ELF header type\n"); +- } +- if (ehdr.e_machine != EM_386) { +- die("Not for x86\n"); +- } +- if (ehdr.e_version != EV_CURRENT) { +- die("Unknown ELF version\n"); +- } +- if (ehdr.e_ehsize != sizeof(Elf32_Ehdr)) { +- die("Bad Elf header size\n"); +- } +- if (ehdr.e_phentsize != sizeof(Elf32_Phdr)) { +- die("Bad program header entry\n"); +- } +- if (ehdr.e_shentsize != sizeof(Elf32_Shdr)) { +- die("Bad section header entry\n"); +- } +- if (ehdr.e_shstrndx >= ehdr.e_shnum) { +- die("String table index out of bounds\n"); +- } +-} +- +-static void read_shdrs(FILE *fp) +-{ +- int i; +- Elf32_Shdr shdr; +- +- secs = calloc(ehdr.e_shnum, sizeof(struct section)); +- if (!secs) { +- die("Unable to allocate %d section headers\n", +- ehdr.e_shnum); +- } +- if (fseek(fp, ehdr.e_shoff, SEEK_SET) < 0) { +- die("Seek to %d failed: %s\n", +- ehdr.e_shoff, strerror(errno)); +- } +- for (i = 0; i < ehdr.e_shnum; i++) { +- struct section *sec = &secs[i]; +- if (fread(&shdr, sizeof shdr, 1, fp) != 1) +- die("Cannot read ELF section headers %d/%d: %s\n", +- i, ehdr.e_shnum, strerror(errno)); +- sec->shdr.sh_name = elf32_to_cpu(shdr.sh_name); +- sec->shdr.sh_type = elf32_to_cpu(shdr.sh_type); +- sec->shdr.sh_flags = elf32_to_cpu(shdr.sh_flags); +- sec->shdr.sh_addr = elf32_to_cpu(shdr.sh_addr); +- sec->shdr.sh_offset = elf32_to_cpu(shdr.sh_offset); +- sec->shdr.sh_size = elf32_to_cpu(shdr.sh_size); +- sec->shdr.sh_link = elf32_to_cpu(shdr.sh_link); +- sec->shdr.sh_info = elf32_to_cpu(shdr.sh_info); +- sec->shdr.sh_addralign = elf32_to_cpu(shdr.sh_addralign); +- sec->shdr.sh_entsize = elf32_to_cpu(shdr.sh_entsize); +- if (sec->shdr.sh_link < ehdr.e_shnum) +- sec->link = &secs[sec->shdr.sh_link]; +- } +- +-} +- +-static void read_strtabs(FILE *fp) +-{ +- int i; +- for (i = 0; i < ehdr.e_shnum; i++) { +- struct section *sec = &secs[i]; +- if (sec->shdr.sh_type != SHT_STRTAB) { +- continue; +- } +- sec->strtab = malloc(sec->shdr.sh_size); +- if (!sec->strtab) { +- die("malloc of %d bytes for strtab failed\n", +- sec->shdr.sh_size); +- } +- if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) { +- die("Seek to %d failed: %s\n", +- sec->shdr.sh_offset, strerror(errno)); +- } +- if (fread(sec->strtab, 1, sec->shdr.sh_size, fp) +- != sec->shdr.sh_size) { +- die("Cannot read symbol table: %s\n", +- strerror(errno)); +- } +- } +-} +- +-static void read_symtabs(FILE *fp) +-{ +- int i,j; +- for (i = 0; i < ehdr.e_shnum; i++) { +- struct section *sec = &secs[i]; +- if (sec->shdr.sh_type != SHT_SYMTAB) { +- continue; +- } +- sec->symtab = malloc(sec->shdr.sh_size); +- if (!sec->symtab) { +- die("malloc of %d bytes for symtab failed\n", +- sec->shdr.sh_size); +- } +- if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) { +- die("Seek to %d failed: %s\n", +- sec->shdr.sh_offset, strerror(errno)); +- } +- if (fread(sec->symtab, 1, sec->shdr.sh_size, fp) +- != sec->shdr.sh_size) { +- die("Cannot read symbol table: %s\n", +- strerror(errno)); +- } +- for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Sym); j++) { +- Elf32_Sym *sym = &sec->symtab[j]; +- sym->st_name = elf32_to_cpu(sym->st_name); +- sym->st_value = elf32_to_cpu(sym->st_value); +- sym->st_size = elf32_to_cpu(sym->st_size); +- sym->st_shndx = elf16_to_cpu(sym->st_shndx); +- } +- } +-} +- +- +-static void read_relocs(FILE *fp) +-{ +- int i,j; +- for (i = 0; i < ehdr.e_shnum; i++) { +- struct section *sec = &secs[i]; +- if (sec->shdr.sh_type != SHT_REL) { +- continue; +- } +- sec->reltab = malloc(sec->shdr.sh_size); +- if (!sec->reltab) { +- die("malloc of %d bytes for relocs failed\n", +- sec->shdr.sh_size); +- } +- if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) { +- die("Seek to %d failed: %s\n", +- sec->shdr.sh_offset, strerror(errno)); +- } +- if (fread(sec->reltab, 1, sec->shdr.sh_size, fp) +- != sec->shdr.sh_size) { +- die("Cannot read symbol table: %s\n", +- strerror(errno)); +- } +- for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) { +- Elf32_Rel *rel = &sec->reltab[j]; +- rel->r_offset = elf32_to_cpu(rel->r_offset); +- rel->r_info = elf32_to_cpu(rel->r_info); +- } +- } +-} +- +- +-static void print_absolute_symbols(void) +-{ +- int i; +- printf("Absolute symbols\n"); +- printf(" Num: Value Size Type Bind Visibility Name\n"); +- for (i = 0; i < ehdr.e_shnum; i++) { +- struct section *sec = &secs[i]; +- char *sym_strtab; +- int j; +- +- if (sec->shdr.sh_type != SHT_SYMTAB) { +- continue; +- } +- sym_strtab = sec->link->strtab; +- for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Sym); j++) { +- Elf32_Sym *sym; +- const char *name; +- sym = &sec->symtab[j]; +- name = sym_name(sym_strtab, sym); +- if (sym->st_shndx != SHN_ABS) { +- continue; +- } +- printf("%5d %08x %5d %10s %10s %12s %s\n", +- j, sym->st_value, sym->st_size, +- sym_type(ELF32_ST_TYPE(sym->st_info)), +- sym_bind(ELF32_ST_BIND(sym->st_info)), +- sym_visibility(ELF32_ST_VISIBILITY(sym->st_other)), +- name); +- } +- } +- printf("\n"); +-} +- +-static void print_absolute_relocs(void) +-{ +- int i, printed = 0; +- +- for (i = 0; i < ehdr.e_shnum; i++) { +- struct section *sec = &secs[i]; +- struct section *sec_applies, *sec_symtab; +- char *sym_strtab; +- Elf32_Sym *sh_symtab; +- int j; +- if (sec->shdr.sh_type != SHT_REL) { +- continue; +- } +- sec_symtab = sec->link; +- sec_applies = &secs[sec->shdr.sh_info]; +- if (!(sec_applies->shdr.sh_flags & SHF_ALLOC)) { +- continue; +- } +- sh_symtab = sec_symtab->symtab; +- sym_strtab = sec_symtab->link->strtab; +- for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) { +- Elf32_Rel *rel; +- Elf32_Sym *sym; +- const char *name; +- rel = &sec->reltab[j]; +- sym = &sh_symtab[ELF32_R_SYM(rel->r_info)]; +- name = sym_name(sym_strtab, sym); +- if (sym->st_shndx != SHN_ABS) { +- continue; +- } +- +- /* Absolute symbols are not relocated if bzImage is +- * loaded at a non-compiled address. Display a warning +- * to user at compile time about the absolute +- * relocations present. +- * +- * User need to audit the code to make sure +- * some symbols which should have been section +- * relative have not become absolute because of some +- * linker optimization or wrong programming usage. +- * +- * Before warning check if this absolute symbol +- * relocation is harmless. +- */ +- if (is_abs_reloc(name) || is_rel_reloc(name)) +- continue; +- +- if (!printed) { +- printf("WARNING: Absolute relocations" +- " present\n"); +- printf("Offset Info Type Sym.Value " +- "Sym.Name\n"); +- printed = 1; +- } +- +- printf("%08x %08x %10s %08x %s\n", +- rel->r_offset, +- rel->r_info, +- rel_type(ELF32_R_TYPE(rel->r_info)), +- sym->st_value, +- name); +- } +- } +- +- if (printed) +- printf("\n"); +-} +- +-static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym)) +-{ +- int i; +- /* Walk through the relocations */ +- for (i = 0; i < ehdr.e_shnum; i++) { +- char *sym_strtab; +- Elf32_Sym *sh_symtab; +- struct section *sec_applies, *sec_symtab; +- int j; +- struct section *sec = &secs[i]; +- +- if (sec->shdr.sh_type != SHT_REL) { +- continue; +- } +- sec_symtab = sec->link; +- sec_applies = &secs[sec->shdr.sh_info]; +- if (!(sec_applies->shdr.sh_flags & SHF_ALLOC)) { +- continue; +- } +- sh_symtab = sec_symtab->symtab; +- sym_strtab = sec_symtab->link->strtab; +- for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) { +- Elf32_Rel *rel; +- Elf32_Sym *sym; +- unsigned r_type; +- rel = &sec->reltab[j]; +- sym = &sh_symtab[ELF32_R_SYM(rel->r_info)]; +- r_type = ELF32_R_TYPE(rel->r_info); +- /* Don't visit relocations to absolute symbols */ +- if (sym->st_shndx == SHN_ABS && +- !is_rel_reloc(sym_name(sym_strtab, sym))) { +- continue; +- } +- switch (r_type) { +- case R_386_NONE: +- case R_386_PC32: +- /* +- * NONE can be ignored and and PC relative +- * relocations don't need to be adjusted. +- */ +- break; +- case R_386_32: +- /* Visit relocations that need to be adjusted */ +- visit(rel, sym); +- break; +- default: +- die("Unsupported relocation type: %s (%d)\n", +- rel_type(r_type), r_type); +- break; +- } +- } +- } +-} +- +-static void count_reloc(Elf32_Rel *rel, Elf32_Sym *sym) +-{ +- reloc_count += 1; +-} +- +-static void collect_reloc(Elf32_Rel *rel, Elf32_Sym *sym) +-{ +- /* Remember the address that needs to be adjusted. */ +- relocs[reloc_idx++] = rel->r_offset; +-} +- +-static int cmp_relocs(const void *va, const void *vb) +-{ +- const unsigned long *a, *b; +- a = va; b = vb; +- return (*a == *b)? 0 : (*a > *b)? 1 : -1; +-} +- +-static void emit_relocs(int as_text) +-{ +- int i; +- /* Count how many relocations I have and allocate space for them. */ +- reloc_count = 0; +- walk_relocs(count_reloc); +- relocs = malloc(reloc_count * sizeof(relocs[0])); +- if (!relocs) { +- die("malloc of %d entries for relocs failed\n", +- reloc_count); +- } +- /* Collect up the relocations */ +- reloc_idx = 0; +- walk_relocs(collect_reloc); +- +- /* Order the relocations for more efficient processing */ +- qsort(relocs, reloc_count, sizeof(relocs[0]), cmp_relocs); +- +- /* Print the relocations */ +- if (as_text) { +- /* Print the relocations in a form suitable that +- * gas will like. +- */ +- printf(".section \".data.reloc\",\"a\"\n"); +- printf(".balign 4\n"); +- for (i = 0; i < reloc_count; i++) { +- printf("\t .long 0x%08lx\n", relocs[i]); +- } +- printf("\n"); +- } +- else { +- unsigned char buf[4]; +- /* Print a stop */ +- fwrite("\0\0\0\0", 4, 1, stdout); +- /* Now print each relocation */ +- for (i = 0; i < reloc_count; i++) { +- buf[0] = (relocs[i] >> 0) & 0xff; +- buf[1] = (relocs[i] >> 8) & 0xff; +- buf[2] = (relocs[i] >> 16) & 0xff; +- buf[3] = (relocs[i] >> 24) & 0xff; +- fwrite(buf, 4, 1, stdout); +- } +- } +-} +- +-static void usage(void) +-{ +- die("relocs [--abs-syms |--abs-relocs | --text] vmlinux\n"); +-} +- +-int main(int argc, char **argv) +-{ +- int show_absolute_syms, show_absolute_relocs; +- int as_text; +- const char *fname; +- FILE *fp; +- int i; +- +- regex_init(); +- +- show_absolute_syms = 0; +- show_absolute_relocs = 0; +- as_text = 0; +- fname = NULL; +- for (i = 1; i < argc; i++) { +- char *arg = argv[i]; +- if (*arg == '-') { +- if (strcmp(argv[1], "--abs-syms") == 0) { +- show_absolute_syms = 1; +- continue; +- } +- +- if (strcmp(argv[1], "--abs-relocs") == 0) { +- show_absolute_relocs = 1; +- continue; +- } +- else if (strcmp(argv[1], "--text") == 0) { +- as_text = 1; +- continue; +- } +- } +- else if (!fname) { +- fname = arg; +- continue; +- } +- usage(); +- } +- if (!fname) { +- usage(); +- } +- fp = fopen(fname, "r"); +- if (!fp) { +- die("Cannot open %s: %s\n", +- fname, strerror(errno)); +- } +- read_ehdr(fp); +- read_shdrs(fp); +- read_strtabs(fp); +- read_symtabs(fp); +- read_relocs(fp); +- if (show_absolute_syms) { +- print_absolute_symbols(); +- return 0; +- } +- if (show_absolute_relocs) { +- print_absolute_relocs(); +- return 0; +- } +- emit_relocs(as_text); +- return 0; +-} +--- /dev/null ++++ b/arch/x86/tools/.gitignore +@@ -0,0 +1 @@ ++relocs +--- a/arch/x86/tools/Makefile ++++ b/arch/x86/tools/Makefile +@@ -36,3 +36,7 @@ HOSTCFLAGS_insn_sanity.o := -Wall -I$(ob + $(obj)/test_get_len.o: $(srctree)/arch/x86/lib/insn.c $(srctree)/arch/x86/lib/inat.c $(srctree)/arch/x86/include/asm/inat_types.h $(srctree)/arch/x86/include/asm/inat.h $(srctree)/arch/x86/include/asm/insn.h $(objtree)/arch/x86/lib/inat-tables.c + + $(obj)/insn_sanity.o: $(srctree)/arch/x86/lib/insn.c $(srctree)/arch/x86/lib/inat.c $(srctree)/arch/x86/include/asm/inat_types.h $(srctree)/arch/x86/include/asm/inat.h $(srctree)/arch/x86/include/asm/insn.h $(objtree)/arch/x86/lib/inat-tables.c ++ ++HOST_EXTRACFLAGS += -I$(srctree)/tools/include ++hostprogs-y += relocs ++relocs: $(obj)/relocs +--- /dev/null ++++ b/arch/x86/tools/relocs.c +@@ -0,0 +1,797 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#define USE_BSD ++#include ++#include ++#include ++ ++static void die(char *fmt, ...); ++ ++#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) ++static Elf32_Ehdr ehdr; ++static unsigned long reloc_count, reloc_idx; ++static unsigned long *relocs; ++static unsigned long reloc16_count, reloc16_idx; ++static unsigned long *relocs16; ++ ++struct section { ++ Elf32_Shdr shdr; ++ struct section *link; ++ Elf32_Sym *symtab; ++ Elf32_Rel *reltab; ++ char *strtab; ++}; ++static struct section *secs; ++ ++enum symtype { ++ S_ABS, ++ S_REL, ++ S_SEG, ++ S_LIN, ++ S_NSYMTYPES ++}; ++ ++static const char * const sym_regex_kernel[S_NSYMTYPES] = { ++/* ++ * Following symbols have been audited. There values are constant and do ++ * not change if bzImage is loaded at a different physical address than ++ * the address for which it has been compiled. Don't warn user about ++ * absolute relocations present w.r.t these symbols. ++ */ ++ [S_ABS] = ++ "^(xen_irq_disable_direct_reloc$|" ++ "xen_save_fl_direct_reloc$|" ++ "VDSO|" ++ "__crc_)", ++ ++/* ++ * These symbols are known to be relative, even if the linker marks them ++ * as absolute (typically defined outside any section in the linker script.) ++ */ ++ [S_REL] = ++ "^_end$", ++}; ++ ++ ++static const char * const sym_regex_realmode[S_NSYMTYPES] = { ++/* ++ * These are 16-bit segment symbols when compiling 16-bit code. ++ */ ++ [S_SEG] = ++ "^real_mode_seg$", ++ ++/* ++ * These are offsets belonging to segments, as opposed to linear addresses, ++ * when compiling 16-bit code. ++ */ ++ [S_LIN] = ++ "^pa_", ++}; ++ ++static const char * const *sym_regex; ++ ++static regex_t sym_regex_c[S_NSYMTYPES]; ++static int is_reloc(enum symtype type, const char *sym_name) ++{ ++ return sym_regex[type] && ++ !regexec(&sym_regex_c[type], sym_name, 0, NULL, 0); ++} ++ ++static void regex_init(int use_real_mode) ++{ ++ char errbuf[128]; ++ int err; ++ int i; ++ ++ if (use_real_mode) ++ sym_regex = sym_regex_realmode; ++ else ++ sym_regex = sym_regex_kernel; ++ ++ for (i = 0; i < S_NSYMTYPES; i++) { ++ if (!sym_regex[i]) ++ continue; ++ ++ err = regcomp(&sym_regex_c[i], sym_regex[i], ++ REG_EXTENDED|REG_NOSUB); ++ ++ if (err) { ++ regerror(err, &sym_regex_c[i], errbuf, sizeof errbuf); ++ die("%s", errbuf); ++ } ++ } ++} ++ ++static void die(char *fmt, ...) ++{ ++ va_list ap; ++ va_start(ap, fmt); ++ vfprintf(stderr, fmt, ap); ++ va_end(ap); ++ exit(1); ++} ++ ++static const char *sym_type(unsigned type) ++{ ++ static const char *type_name[] = { ++#define SYM_TYPE(X) [X] = #X ++ SYM_TYPE(STT_NOTYPE), ++ SYM_TYPE(STT_OBJECT), ++ SYM_TYPE(STT_FUNC), ++ SYM_TYPE(STT_SECTION), ++ SYM_TYPE(STT_FILE), ++ SYM_TYPE(STT_COMMON), ++ SYM_TYPE(STT_TLS), ++#undef SYM_TYPE ++ }; ++ const char *name = "unknown sym type name"; ++ if (type < ARRAY_SIZE(type_name)) { ++ name = type_name[type]; ++ } ++ return name; ++} ++ ++static const char *sym_bind(unsigned bind) ++{ ++ static const char *bind_name[] = { ++#define SYM_BIND(X) [X] = #X ++ SYM_BIND(STB_LOCAL), ++ SYM_BIND(STB_GLOBAL), ++ SYM_BIND(STB_WEAK), ++#undef SYM_BIND ++ }; ++ const char *name = "unknown sym bind name"; ++ if (bind < ARRAY_SIZE(bind_name)) { ++ name = bind_name[bind]; ++ } ++ return name; ++} ++ ++static const char *sym_visibility(unsigned visibility) ++{ ++ static const char *visibility_name[] = { ++#define SYM_VISIBILITY(X) [X] = #X ++ SYM_VISIBILITY(STV_DEFAULT), ++ SYM_VISIBILITY(STV_INTERNAL), ++ SYM_VISIBILITY(STV_HIDDEN), ++ SYM_VISIBILITY(STV_PROTECTED), ++#undef SYM_VISIBILITY ++ }; ++ const char *name = "unknown sym visibility name"; ++ if (visibility < ARRAY_SIZE(visibility_name)) { ++ name = visibility_name[visibility]; ++ } ++ return name; ++} ++ ++static const char *rel_type(unsigned type) ++{ ++ static const char *type_name[] = { ++#define REL_TYPE(X) [X] = #X ++ REL_TYPE(R_386_NONE), ++ REL_TYPE(R_386_32), ++ REL_TYPE(R_386_PC32), ++ REL_TYPE(R_386_GOT32), ++ REL_TYPE(R_386_PLT32), ++ REL_TYPE(R_386_COPY), ++ REL_TYPE(R_386_GLOB_DAT), ++ REL_TYPE(R_386_JMP_SLOT), ++ REL_TYPE(R_386_RELATIVE), ++ REL_TYPE(R_386_GOTOFF), ++ REL_TYPE(R_386_GOTPC), ++ REL_TYPE(R_386_8), ++ REL_TYPE(R_386_PC8), ++ REL_TYPE(R_386_16), ++ REL_TYPE(R_386_PC16), ++#undef REL_TYPE ++ }; ++ const char *name = "unknown type rel type name"; ++ if (type < ARRAY_SIZE(type_name) && type_name[type]) { ++ name = type_name[type]; ++ } ++ return name; ++} ++ ++static const char *sec_name(unsigned shndx) ++{ ++ const char *sec_strtab; ++ const char *name; ++ sec_strtab = secs[ehdr.e_shstrndx].strtab; ++ name = ""; ++ if (shndx < ehdr.e_shnum) { ++ name = sec_strtab + secs[shndx].shdr.sh_name; ++ } ++ else if (shndx == SHN_ABS) { ++ name = "ABSOLUTE"; ++ } ++ else if (shndx == SHN_COMMON) { ++ name = "COMMON"; ++ } ++ return name; ++} ++ ++static const char *sym_name(const char *sym_strtab, Elf32_Sym *sym) ++{ ++ const char *name; ++ name = ""; ++ if (sym->st_name) { ++ name = sym_strtab + sym->st_name; ++ } ++ else { ++ name = sec_name(sym->st_shndx); ++ } ++ return name; ++} ++ ++ ++ ++#if BYTE_ORDER == LITTLE_ENDIAN ++#define le16_to_cpu(val) (val) ++#define le32_to_cpu(val) (val) ++#endif ++#if BYTE_ORDER == BIG_ENDIAN ++#define le16_to_cpu(val) bswap_16(val) ++#define le32_to_cpu(val) bswap_32(val) ++#endif ++ ++static uint16_t elf16_to_cpu(uint16_t val) ++{ ++ return le16_to_cpu(val); ++} ++ ++static uint32_t elf32_to_cpu(uint32_t val) ++{ ++ return le32_to_cpu(val); ++} ++ ++static void read_ehdr(FILE *fp) ++{ ++ if (fread(&ehdr, sizeof(ehdr), 1, fp) != 1) { ++ die("Cannot read ELF header: %s\n", ++ strerror(errno)); ++ } ++ if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0) { ++ die("No ELF magic\n"); ++ } ++ if (ehdr.e_ident[EI_CLASS] != ELFCLASS32) { ++ die("Not a 32 bit executable\n"); ++ } ++ if (ehdr.e_ident[EI_DATA] != ELFDATA2LSB) { ++ die("Not a LSB ELF executable\n"); ++ } ++ if (ehdr.e_ident[EI_VERSION] != EV_CURRENT) { ++ die("Unknown ELF version\n"); ++ } ++ /* Convert the fields to native endian */ ++ ehdr.e_type = elf16_to_cpu(ehdr.e_type); ++ ehdr.e_machine = elf16_to_cpu(ehdr.e_machine); ++ ehdr.e_version = elf32_to_cpu(ehdr.e_version); ++ ehdr.e_entry = elf32_to_cpu(ehdr.e_entry); ++ ehdr.e_phoff = elf32_to_cpu(ehdr.e_phoff); ++ ehdr.e_shoff = elf32_to_cpu(ehdr.e_shoff); ++ ehdr.e_flags = elf32_to_cpu(ehdr.e_flags); ++ ehdr.e_ehsize = elf16_to_cpu(ehdr.e_ehsize); ++ ehdr.e_phentsize = elf16_to_cpu(ehdr.e_phentsize); ++ ehdr.e_phnum = elf16_to_cpu(ehdr.e_phnum); ++ ehdr.e_shentsize = elf16_to_cpu(ehdr.e_shentsize); ++ ehdr.e_shnum = elf16_to_cpu(ehdr.e_shnum); ++ ehdr.e_shstrndx = elf16_to_cpu(ehdr.e_shstrndx); ++ ++ if ((ehdr.e_type != ET_EXEC) && (ehdr.e_type != ET_DYN)) { ++ die("Unsupported ELF header type\n"); ++ } ++ if (ehdr.e_machine != EM_386) { ++ die("Not for x86\n"); ++ } ++ if (ehdr.e_version != EV_CURRENT) { ++ die("Unknown ELF version\n"); ++ } ++ if (ehdr.e_ehsize != sizeof(Elf32_Ehdr)) { ++ die("Bad Elf header size\n"); ++ } ++ if (ehdr.e_phentsize != sizeof(Elf32_Phdr)) { ++ die("Bad program header entry\n"); ++ } ++ if (ehdr.e_shentsize != sizeof(Elf32_Shdr)) { ++ die("Bad section header entry\n"); ++ } ++ if (ehdr.e_shstrndx >= ehdr.e_shnum) { ++ die("String table index out of bounds\n"); ++ } ++} ++ ++static void read_shdrs(FILE *fp) ++{ ++ int i; ++ Elf32_Shdr shdr; ++ ++ secs = calloc(ehdr.e_shnum, sizeof(struct section)); ++ if (!secs) { ++ die("Unable to allocate %d section headers\n", ++ ehdr.e_shnum); ++ } ++ if (fseek(fp, ehdr.e_shoff, SEEK_SET) < 0) { ++ die("Seek to %d failed: %s\n", ++ ehdr.e_shoff, strerror(errno)); ++ } ++ for (i = 0; i < ehdr.e_shnum; i++) { ++ struct section *sec = &secs[i]; ++ if (fread(&shdr, sizeof shdr, 1, fp) != 1) ++ die("Cannot read ELF section headers %d/%d: %s\n", ++ i, ehdr.e_shnum, strerror(errno)); ++ sec->shdr.sh_name = elf32_to_cpu(shdr.sh_name); ++ sec->shdr.sh_type = elf32_to_cpu(shdr.sh_type); ++ sec->shdr.sh_flags = elf32_to_cpu(shdr.sh_flags); ++ sec->shdr.sh_addr = elf32_to_cpu(shdr.sh_addr); ++ sec->shdr.sh_offset = elf32_to_cpu(shdr.sh_offset); ++ sec->shdr.sh_size = elf32_to_cpu(shdr.sh_size); ++ sec->shdr.sh_link = elf32_to_cpu(shdr.sh_link); ++ sec->shdr.sh_info = elf32_to_cpu(shdr.sh_info); ++ sec->shdr.sh_addralign = elf32_to_cpu(shdr.sh_addralign); ++ sec->shdr.sh_entsize = elf32_to_cpu(shdr.sh_entsize); ++ if (sec->shdr.sh_link < ehdr.e_shnum) ++ sec->link = &secs[sec->shdr.sh_link]; ++ } ++ ++} ++ ++static void read_strtabs(FILE *fp) ++{ ++ int i; ++ for (i = 0; i < ehdr.e_shnum; i++) { ++ struct section *sec = &secs[i]; ++ if (sec->shdr.sh_type != SHT_STRTAB) { ++ continue; ++ } ++ sec->strtab = malloc(sec->shdr.sh_size); ++ if (!sec->strtab) { ++ die("malloc of %d bytes for strtab failed\n", ++ sec->shdr.sh_size); ++ } ++ if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) { ++ die("Seek to %d failed: %s\n", ++ sec->shdr.sh_offset, strerror(errno)); ++ } ++ if (fread(sec->strtab, 1, sec->shdr.sh_size, fp) ++ != sec->shdr.sh_size) { ++ die("Cannot read symbol table: %s\n", ++ strerror(errno)); ++ } ++ } ++} ++ ++static void read_symtabs(FILE *fp) ++{ ++ int i,j; ++ for (i = 0; i < ehdr.e_shnum; i++) { ++ struct section *sec = &secs[i]; ++ if (sec->shdr.sh_type != SHT_SYMTAB) { ++ continue; ++ } ++ sec->symtab = malloc(sec->shdr.sh_size); ++ if (!sec->symtab) { ++ die("malloc of %d bytes for symtab failed\n", ++ sec->shdr.sh_size); ++ } ++ if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) { ++ die("Seek to %d failed: %s\n", ++ sec->shdr.sh_offset, strerror(errno)); ++ } ++ if (fread(sec->symtab, 1, sec->shdr.sh_size, fp) ++ != sec->shdr.sh_size) { ++ die("Cannot read symbol table: %s\n", ++ strerror(errno)); ++ } ++ for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Sym); j++) { ++ Elf32_Sym *sym = &sec->symtab[j]; ++ sym->st_name = elf32_to_cpu(sym->st_name); ++ sym->st_value = elf32_to_cpu(sym->st_value); ++ sym->st_size = elf32_to_cpu(sym->st_size); ++ sym->st_shndx = elf16_to_cpu(sym->st_shndx); ++ } ++ } ++} ++ ++ ++static void read_relocs(FILE *fp) ++{ ++ int i,j; ++ for (i = 0; i < ehdr.e_shnum; i++) { ++ struct section *sec = &secs[i]; ++ if (sec->shdr.sh_type != SHT_REL) { ++ continue; ++ } ++ sec->reltab = malloc(sec->shdr.sh_size); ++ if (!sec->reltab) { ++ die("malloc of %d bytes for relocs failed\n", ++ sec->shdr.sh_size); ++ } ++ if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) { ++ die("Seek to %d failed: %s\n", ++ sec->shdr.sh_offset, strerror(errno)); ++ } ++ if (fread(sec->reltab, 1, sec->shdr.sh_size, fp) ++ != sec->shdr.sh_size) { ++ die("Cannot read symbol table: %s\n", ++ strerror(errno)); ++ } ++ for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) { ++ Elf32_Rel *rel = &sec->reltab[j]; ++ rel->r_offset = elf32_to_cpu(rel->r_offset); ++ rel->r_info = elf32_to_cpu(rel->r_info); ++ } ++ } ++} ++ ++ ++static void print_absolute_symbols(void) ++{ ++ int i; ++ printf("Absolute symbols\n"); ++ printf(" Num: Value Size Type Bind Visibility Name\n"); ++ for (i = 0; i < ehdr.e_shnum; i++) { ++ struct section *sec = &secs[i]; ++ char *sym_strtab; ++ int j; ++ ++ if (sec->shdr.sh_type != SHT_SYMTAB) { ++ continue; ++ } ++ sym_strtab = sec->link->strtab; ++ for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Sym); j++) { ++ Elf32_Sym *sym; ++ const char *name; ++ sym = &sec->symtab[j]; ++ name = sym_name(sym_strtab, sym); ++ if (sym->st_shndx != SHN_ABS) { ++ continue; ++ } ++ printf("%5d %08x %5d %10s %10s %12s %s\n", ++ j, sym->st_value, sym->st_size, ++ sym_type(ELF32_ST_TYPE(sym->st_info)), ++ sym_bind(ELF32_ST_BIND(sym->st_info)), ++ sym_visibility(ELF32_ST_VISIBILITY(sym->st_other)), ++ name); ++ } ++ } ++ printf("\n"); ++} ++ ++static void print_absolute_relocs(void) ++{ ++ int i, printed = 0; ++ ++ for (i = 0; i < ehdr.e_shnum; i++) { ++ struct section *sec = &secs[i]; ++ struct section *sec_applies, *sec_symtab; ++ char *sym_strtab; ++ Elf32_Sym *sh_symtab; ++ int j; ++ if (sec->shdr.sh_type != SHT_REL) { ++ continue; ++ } ++ sec_symtab = sec->link; ++ sec_applies = &secs[sec->shdr.sh_info]; ++ if (!(sec_applies->shdr.sh_flags & SHF_ALLOC)) { ++ continue; ++ } ++ sh_symtab = sec_symtab->symtab; ++ sym_strtab = sec_symtab->link->strtab; ++ for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) { ++ Elf32_Rel *rel; ++ Elf32_Sym *sym; ++ const char *name; ++ rel = &sec->reltab[j]; ++ sym = &sh_symtab[ELF32_R_SYM(rel->r_info)]; ++ name = sym_name(sym_strtab, sym); ++ if (sym->st_shndx != SHN_ABS) { ++ continue; ++ } ++ ++ /* Absolute symbols are not relocated if bzImage is ++ * loaded at a non-compiled address. Display a warning ++ * to user at compile time about the absolute ++ * relocations present. ++ * ++ * User need to audit the code to make sure ++ * some symbols which should have been section ++ * relative have not become absolute because of some ++ * linker optimization or wrong programming usage. ++ * ++ * Before warning check if this absolute symbol ++ * relocation is harmless. ++ */ ++ if (is_reloc(S_ABS, name) || is_reloc(S_REL, name)) ++ continue; ++ ++ if (!printed) { ++ printf("WARNING: Absolute relocations" ++ " present\n"); ++ printf("Offset Info Type Sym.Value " ++ "Sym.Name\n"); ++ printed = 1; ++ } ++ ++ printf("%08x %08x %10s %08x %s\n", ++ rel->r_offset, ++ rel->r_info, ++ rel_type(ELF32_R_TYPE(rel->r_info)), ++ sym->st_value, ++ name); ++ } ++ } ++ ++ if (printed) ++ printf("\n"); ++} ++ ++static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym), ++ int use_real_mode) ++{ ++ int i; ++ /* Walk through the relocations */ ++ for (i = 0; i < ehdr.e_shnum; i++) { ++ char *sym_strtab; ++ Elf32_Sym *sh_symtab; ++ struct section *sec_applies, *sec_symtab; ++ int j; ++ struct section *sec = &secs[i]; ++ ++ if (sec->shdr.sh_type != SHT_REL) { ++ continue; ++ } ++ sec_symtab = sec->link; ++ sec_applies = &secs[sec->shdr.sh_info]; ++ if (!(sec_applies->shdr.sh_flags & SHF_ALLOC)) { ++ continue; ++ } ++ sh_symtab = sec_symtab->symtab; ++ sym_strtab = sec_symtab->link->strtab; ++ for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) { ++ Elf32_Rel *rel; ++ Elf32_Sym *sym; ++ unsigned r_type; ++ const char *symname; ++ rel = &sec->reltab[j]; ++ sym = &sh_symtab[ELF32_R_SYM(rel->r_info)]; ++ r_type = ELF32_R_TYPE(rel->r_info); ++ ++ switch (r_type) { ++ case R_386_NONE: ++ case R_386_PC32: ++ case R_386_PC16: ++ case R_386_PC8: ++ /* ++ * NONE can be ignored and and PC relative ++ * relocations don't need to be adjusted. ++ */ ++ break; ++ ++ case R_386_16: ++ symname = sym_name(sym_strtab, sym); ++ if (!use_real_mode) ++ goto bad; ++ if (sym->st_shndx == SHN_ABS) { ++ if (is_reloc(S_ABS, symname)) ++ break; ++ else if (!is_reloc(S_SEG, symname)) ++ goto bad; ++ } else { ++ if (is_reloc(S_LIN, symname)) ++ goto bad; ++ else ++ break; ++ } ++ visit(rel, sym); ++ break; ++ ++ case R_386_32: ++ symname = sym_name(sym_strtab, sym); ++ if (sym->st_shndx == SHN_ABS) { ++ if (is_reloc(S_ABS, symname)) ++ break; ++ else if (!is_reloc(S_REL, symname)) ++ goto bad; ++ } else { ++ if (use_real_mode && ++ !is_reloc(S_LIN, symname)) ++ break; ++ } ++ visit(rel, sym); ++ break; ++ default: ++ die("Unsupported relocation type: %s (%d)\n", ++ rel_type(r_type), r_type); ++ break; ++ bad: ++ symname = sym_name(sym_strtab, sym); ++ die("Invalid %s relocation: %s\n", ++ rel_type(r_type), symname); ++ } ++ } ++ } ++} ++ ++static void count_reloc(Elf32_Rel *rel, Elf32_Sym *sym) ++{ ++ if (ELF32_R_TYPE(rel->r_info) == R_386_16) ++ reloc16_count++; ++ else ++ reloc_count++; ++} ++ ++static void collect_reloc(Elf32_Rel *rel, Elf32_Sym *sym) ++{ ++ /* Remember the address that needs to be adjusted. */ ++ if (ELF32_R_TYPE(rel->r_info) == R_386_16) ++ relocs16[reloc16_idx++] = rel->r_offset; ++ else ++ relocs[reloc_idx++] = rel->r_offset; ++} ++ ++static int cmp_relocs(const void *va, const void *vb) ++{ ++ const unsigned long *a, *b; ++ a = va; b = vb; ++ return (*a == *b)? 0 : (*a > *b)? 1 : -1; ++} ++ ++static int write32(unsigned int v, FILE *f) ++{ ++ unsigned char buf[4]; ++ ++ put_unaligned_le32(v, buf); ++ return fwrite(buf, 1, 4, f) == 4 ? 0 : -1; ++} ++ ++static void emit_relocs(int as_text, int use_real_mode) ++{ ++ int i; ++ /* Count how many relocations I have and allocate space for them. */ ++ reloc_count = 0; ++ walk_relocs(count_reloc, use_real_mode); ++ relocs = malloc(reloc_count * sizeof(relocs[0])); ++ if (!relocs) { ++ die("malloc of %d entries for relocs failed\n", ++ reloc_count); ++ } ++ ++ relocs16 = malloc(reloc16_count * sizeof(relocs[0])); ++ if (!relocs16) { ++ die("malloc of %d entries for relocs16 failed\n", ++ reloc16_count); ++ } ++ /* Collect up the relocations */ ++ reloc_idx = 0; ++ walk_relocs(collect_reloc, use_real_mode); ++ ++ if (reloc16_count && !use_real_mode) ++ die("Segment relocations found but --realmode not specified\n"); ++ ++ /* Order the relocations for more efficient processing */ ++ qsort(relocs, reloc_count, sizeof(relocs[0]), cmp_relocs); ++ qsort(relocs16, reloc16_count, sizeof(relocs16[0]), cmp_relocs); ++ ++ /* Print the relocations */ ++ if (as_text) { ++ /* Print the relocations in a form suitable that ++ * gas will like. ++ */ ++ printf(".section \".data.reloc\",\"a\"\n"); ++ printf(".balign 4\n"); ++ if (use_real_mode) { ++ printf("\t.long %lu\n", reloc16_count); ++ for (i = 0; i < reloc16_count; i++) ++ printf("\t.long 0x%08lx\n", relocs16[i]); ++ printf("\t.long %lu\n", reloc_count); ++ for (i = 0; i < reloc_count; i++) { ++ printf("\t.long 0x%08lx\n", relocs[i]); ++ } ++ } else { ++ /* Print a stop */ ++ printf("\t.long 0x%08lx\n", (unsigned long)0); ++ for (i = 0; i < reloc_count; i++) { ++ printf("\t.long 0x%08lx\n", relocs[i]); ++ } ++ } ++ ++ printf("\n"); ++ } ++ else { ++ if (use_real_mode) { ++ write32(reloc16_count, stdout); ++ for (i = 0; i < reloc16_count; i++) ++ write32(relocs16[i], stdout); ++ write32(reloc_count, stdout); ++ ++ /* Now print each relocation */ ++ for (i = 0; i < reloc_count; i++) ++ write32(relocs[i], stdout); ++ } else { ++ /* Print a stop */ ++ write32(0, stdout); ++ ++ /* Now print each relocation */ ++ for (i = 0; i < reloc_count; i++) { ++ write32(relocs[i], stdout); ++ } ++ } ++ } ++} ++ ++static void usage(void) ++{ ++ die("relocs [--abs-syms|--abs-relocs|--text|--realmode] vmlinux\n"); ++} ++ ++int main(int argc, char **argv) ++{ ++ int show_absolute_syms, show_absolute_relocs; ++ int as_text, use_real_mode; ++ const char *fname; ++ FILE *fp; ++ int i; ++ ++ show_absolute_syms = 0; ++ show_absolute_relocs = 0; ++ as_text = 0; ++ use_real_mode = 0; ++ fname = NULL; ++ for (i = 1; i < argc; i++) { ++ char *arg = argv[i]; ++ if (*arg == '-') { ++ if (strcmp(arg, "--abs-syms") == 0) { ++ show_absolute_syms = 1; ++ continue; ++ } ++ if (strcmp(arg, "--abs-relocs") == 0) { ++ show_absolute_relocs = 1; ++ continue; ++ } ++ if (strcmp(arg, "--text") == 0) { ++ as_text = 1; ++ continue; ++ } ++ if (strcmp(arg, "--realmode") == 0) { ++ use_real_mode = 1; ++ continue; ++ } ++ } ++ else if (!fname) { ++ fname = arg; ++ continue; ++ } ++ usage(); ++ } ++ if (!fname) { ++ usage(); ++ } ++ regex_init(use_real_mode); ++ fp = fopen(fname, "r"); ++ if (!fp) { ++ die("Cannot open %s: %s\n", ++ fname, strerror(errno)); ++ } ++ read_ehdr(fp); ++ read_shdrs(fp); ++ read_strtabs(fp); ++ read_symtabs(fp); ++ read_relocs(fp); ++ if (show_absolute_syms) { ++ print_absolute_symbols(); ++ return 0; ++ } ++ if (show_absolute_relocs) { ++ print_absolute_relocs(); ++ return 0; ++ } ++ emit_relocs(as_text, use_real_mode); ++ return 0; ++} +--- a/scripts/Makefile ++++ b/scripts/Makefile +@@ -8,6 +8,8 @@ + # conmakehash: Create arrays for initializing the kernel console tables + # docproc: Used in Documentation/DocBook + ++HOST_EXTRACFLAGS += -I$(srctree)/tools/include ++ + hostprogs-$(CONFIG_KALLSYMS) += kallsyms + hostprogs-$(CONFIG_LOGO) += pnmtologo + hostprogs-$(CONFIG_VT) += conmakehash diff --git a/queue-3.3/x86-relocs-add-jiffies-and-jiffies_64-to-the-relative-whitelist.patch b/queue-3.3/x86-relocs-add-jiffies-and-jiffies_64-to-the-relative-whitelist.patch new file mode 100644 index 00000000000..dbc5849d1ba --- /dev/null +++ b/queue-3.3/x86-relocs-add-jiffies-and-jiffies_64-to-the-relative-whitelist.patch @@ -0,0 +1,39 @@ +From ea17e7414bc62e8d3bde8d08e3df1d921c518c17 Mon Sep 17 00:00:00 2001 +From: "H. Peter Anvin" +Date: Thu, 24 May 2012 07:01:38 -0700 +Subject: x86, relocs: Add jiffies and jiffies_64 to the relative whitelist + +From: "H. Peter Anvin" + +commit ea17e7414bc62e8d3bde8d08e3df1d921c518c17 upstream. + +The symbol jiffies is created in the linker script as an alias to +jiffies_64. Unfortunately this is done outside any section, and +apparently GNU ld 2.21 doesn't carry the section with it, so we end up +with an absolute symbol and therefore a broken kernel. + +Add jiffies and jiffies_64 to the whitelist. + +The most disturbing bit with this discovery is that it shows that we +have had multiple linker bugs in this area crossing multiple +generations, and have been silently building bad kernels for some time. + +Link: http://lkml.kernel.org/r/20120524171604.0d98284f3affc643e9714470@canb.auug.org.au +Reported-by: Stephen Rothwell +Signed-off-by: H. Peter Anvin +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/tools/relocs.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/x86/tools/relocs.c ++++ b/arch/x86/tools/relocs.c +@@ -71,6 +71,7 @@ static const char * const sym_regex_kern + "__(start|stop)_notes|" + "__end_rodata|" + "__initramfs_start|" ++ "(jiffies|jiffies_64)|" + "_end)$" + }; + diff --git a/queue-3.3/x86-relocs-build-clean-fix.patch b/queue-3.3/x86-relocs-build-clean-fix.patch new file mode 100644 index 00000000000..63369bf8b9e --- /dev/null +++ b/queue-3.3/x86-relocs-build-clean-fix.patch @@ -0,0 +1,31 @@ +From b2d668da9307c4c163dd603d2bb3cadb10f9fd37 Mon Sep 17 00:00:00 2001 +From: Jarkko Sakkinen +Date: Mon, 21 May 2012 20:51:24 +0300 +Subject: x86, relocs: Build clean fix + +From: Jarkko Sakkinen + +commit b2d668da9307c4c163dd603d2bb3cadb10f9fd37 upstream. + +relocs was not cleaned up when "make clean" is issued. This +patch fixes the issue. + +Signed-off-by: Jarkko Sakkinen +Link: http://lkml.kernel.org/r/1337622684-6834-1-git-send-email-jarkko.sakkinen@intel.com +Signed-off-by: H. Peter Anvin +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/Makefile | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/x86/Makefile ++++ b/arch/x86/Makefile +@@ -189,6 +189,7 @@ archclean: + $(Q)rm -rf $(objtree)/arch/i386 + $(Q)rm -rf $(objtree)/arch/x86_64 + $(Q)$(MAKE) $(clean)=$(boot) ++ $(Q)$(MAKE) $(clean)=arch/x86/tools + + define archhelp + echo '* bzImage - Compressed kernel image (arch/x86/boot/bzImage)' diff --git a/queue-3.3/x86-relocs-when-printing-an-error-say-relative-or-absolute.patch b/queue-3.3/x86-relocs-when-printing-an-error-say-relative-or-absolute.patch new file mode 100644 index 00000000000..48104aac9a9 --- /dev/null +++ b/queue-3.3/x86-relocs-when-printing-an-error-say-relative-or-absolute.patch @@ -0,0 +1,66 @@ +From 24ab82bd9bf18f3efc69a131d73577940941e1b7 Mon Sep 17 00:00:00 2001 +From: "H. Peter Anvin" +Date: Fri, 18 May 2012 09:52:01 -0700 +Subject: x86, relocs: When printing an error, say relative or absolute + +From: "H. Peter Anvin" + +commit 24ab82bd9bf18f3efc69a131d73577940941e1b7 upstream. + +When the relocs tool throws an error, let the error message say if it +is an absolute or relative symbol. This should make it a lot more +clear what action the programmer needs to take and should help us find +the reason if additional symbol bugs show up. + +Signed-off-by: H. Peter Anvin +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/tools/relocs.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +--- a/arch/x86/tools/relocs.c ++++ b/arch/x86/tools/relocs.c +@@ -563,10 +563,14 @@ static void walk_relocs(void (*visit)(El + Elf32_Sym *sym; + unsigned r_type; + const char *symname; ++ int shn_abs; ++ + rel = &sec->reltab[j]; + sym = &sh_symtab[ELF32_R_SYM(rel->r_info)]; + r_type = ELF32_R_TYPE(rel->r_info); + ++ shn_abs = sym->st_shndx == SHN_ABS; ++ + switch (r_type) { + case R_386_NONE: + case R_386_PC32: +@@ -582,7 +586,7 @@ static void walk_relocs(void (*visit)(El + symname = sym_name(sym_strtab, sym); + if (!use_real_mode) + goto bad; +- if (sym->st_shndx == SHN_ABS) { ++ if (shn_abs) { + if (is_reloc(S_ABS, symname)) + break; + else if (!is_reloc(S_SEG, symname)) +@@ -598,7 +602,7 @@ static void walk_relocs(void (*visit)(El + + case R_386_32: + symname = sym_name(sym_strtab, sym); +- if (sym->st_shndx == SHN_ABS) { ++ if (shn_abs) { + if (is_reloc(S_ABS, symname)) + break; + else if (!is_reloc(S_REL, symname)) +@@ -616,7 +620,8 @@ static void walk_relocs(void (*visit)(El + break; + bad: + symname = sym_name(sym_strtab, sym); +- die("Invalid %s relocation: %s\n", ++ die("Invalid %s %s relocation: %s\n", ++ shn_abs ? "absolute" : "relative", + rel_type(r_type), symname); + } + } diff --git a/queue-3.3/x86-relocs-workaround-for-binutils-2.22.52.0.1-section-bug.patch b/queue-3.3/x86-relocs-workaround-for-binutils-2.22.52.0.1-section-bug.patch new file mode 100644 index 00000000000..35a0f887d67 --- /dev/null +++ b/queue-3.3/x86-relocs-workaround-for-binutils-2.22.52.0.1-section-bug.patch @@ -0,0 +1,40 @@ +From a3e854d95a76862cd37937e0b0438f540536771a Mon Sep 17 00:00:00 2001 +From: "H. Peter Anvin" +Date: Fri, 18 May 2012 00:24:09 -0700 +Subject: x86, relocs: Workaround for binutils 2.22.52.0.1 section bug + +From: "H. Peter Anvin" + +commit a3e854d95a76862cd37937e0b0438f540536771a upstream. + +GNU ld 2.22.52.0.1 has a bug that it blindly changes symbols from +section-relative to absolute if they are in a section of zero length. +This turns the symbols __init_begin and __init_end into absolute +symbols. Let the relocs program know that those should be treated as +relative symbols. + +Reported-by: Ingo Molnar +Signed-off-by: H. Peter Anvin +Cc: H.J. Lu +Cc: Jarkko Sakkinen +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/tools/relocs.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/arch/x86/tools/relocs.c ++++ b/arch/x86/tools/relocs.c +@@ -56,7 +56,11 @@ static const char * const sym_regex_kern + * as absolute (typically defined outside any section in the linker script.) + */ + [S_REL] = +- "^_end$", ++ "^(__init_(begin|end)|" ++ "__x86_cpu_dev_(start|end)|" ++ "(__parainstructions|__alt_instructions)(|_end)|" ++ "(__iommu_table|__apicdrivers|__smp_locks)(|_end)|" ++ "_end)$" + }; + +