account_process_vtime(current);
calculate_steal_time();
+ /*
+ * We can't take a PMU exception inside _switch() since there is a
+ * window where the kernel stack SLB and the kernel stack are out
+ * of sync. Hard disable here.
+ */
+ hard_irq_disable();
last = _switch(old_thread, new_thread);
local_irq_restore(flags);
flush_spe_to_thread(current);
error = do_execve(filename, (char __user * __user *) a1,
(char __user * __user *) a2, regs);
- if (error == 0) {
- task_lock(current);
- current->ptrace &= ~PT_DTRACE;
- task_unlock(current);
- }
putname(filename);
out:
return error;
#include <linux/cache.h>
#include <linux/init.h>
#include <linux/signal.h>
+#include <linux/lmb.h>
#include <asm/processor.h>
#include <asm/pgtable.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/machdep.h>
-#include <asm/lmb.h>
+#include <asm/prom.h>
#include <asm/abs_addr.h>
#include <asm/tlbflush.h>
#include <asm/io.h>
return ret < 0 ? ret : 0;
}
+static void htab_remove_mapping(unsigned long vstart, unsigned long vend,
+ int psize, int ssize)
+{
+ unsigned long vaddr;
+ unsigned int step, shift;
+
+ shift = mmu_psize_defs[psize].shift;
+ step = 1 << shift;
+
+ if (!ppc_md.hpte_removebolted) {
+ printk("Sub-arch doesn't implement hpte_removebolted\n");
+ return;
+ }
+
+ for (vaddr = vstart; vaddr < vend; vaddr += step)
+ ppc_md.hpte_removebolted(vaddr, psize, ssize);
+}
+
static int __init htab_dt_scan_seg_sizes(unsigned long node,
const char *uname, int depth,
void *data)
mmu_vmalloc_psize = MMU_PAGE_64K;
if (mmu_linear_psize == MMU_PAGE_4K)
mmu_linear_psize = MMU_PAGE_64K;
- if (cpu_has_feature(CPU_FTR_CI_LARGE_PAGE))
- mmu_io_psize = MMU_PAGE_64K;
- else
+ if (cpu_has_feature(CPU_FTR_CI_LARGE_PAGE)) {
+ /*
+ * Don't use 64k pages for ioremap on pSeries, since
+ * that would stop us accessing the HEA ethernet.
+ */
+ if (!machine_is(pseries))
+ mmu_io_psize = MMU_PAGE_64K;
+ } else
mmu_ci_restrictions = 1;
}
#endif /* CONFIG_PPC_64K_PAGES */
_PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX,
mmu_linear_psize, mmu_kernel_ssize));
}
+
+void remove_section_mapping(unsigned long start, unsigned long end)
+{
+ htab_remove_mapping(start, end, mmu_linear_psize, mmu_kernel_ssize);
+}
#endif /* CONFIG_MEMORY_HOTPLUG */
static inline void make_bl(unsigned int *insn_addr, void *func)
#include <linux/notifier.h>
#include <linux/of.h>
#include <linux/of_platform.h>
+#include <linux/lmb.h>
#include <asm/prom.h>
#include <asm/iommu.h>
#include <asm/machdep.h>
#include <asm/pci-bridge.h>
#include <asm/udbg.h>
-#include <asm/lmb.h>
#include <asm/firmware.h>
#include <asm/cell-regs.h>
static u64 cell_iommu_get_fixed_address(struct device *dev)
{
- u64 cpu_addr, size, best_size, pci_addr = OF_BAD_ADDR;
+ u64 cpu_addr, size, best_size, dev_addr = OF_BAD_ADDR;
struct device_node *np;
const u32 *ranges = NULL;
- int i, len, best;
+ int i, len, best, naddr, nsize, pna, range_size;
np = of_node_get(dev->archdata.of_node);
- while (np) {
+ while (1) {
+ naddr = of_n_addr_cells(np);
+ nsize = of_n_size_cells(np);
+ np = of_get_next_parent(np);
+ if (!np)
+ break;
+
ranges = of_get_property(np, "dma-ranges", &len);
- if (ranges)
+
+ /* Ignore empty ranges, they imply no translation required */
+ if (ranges && len > 0)
break;
- np = of_get_next_parent(np);
}
if (!ranges) {
len /= sizeof(u32);
+ pna = of_n_addr_cells(np);
+ range_size = naddr + nsize + pna;
+
/* dma-ranges format:
- * 1 cell: pci space
- * 2 cells: pci address
- * 2 cells: parent address
- * 2 cells: size
+ * child addr : naddr cells
+ * parent addr : pna cells
+ * size : nsize cells
*/
- for (i = 0, best = -1, best_size = 0; i < len; i += 7) {
- cpu_addr = of_translate_dma_address(np, ranges +i + 3);
- size = of_read_number(ranges + i + 5, 2);
+ for (i = 0, best = -1, best_size = 0; i < len; i += range_size) {
+ cpu_addr = of_translate_dma_address(np, ranges + i + naddr);
+ size = of_read_number(ranges + i + naddr + pna, nsize);
if (cpu_addr == 0 && size > best_size) {
best = i;
}
}
- if (best >= 0)
- pci_addr = of_read_number(ranges + best + 1, 2);
- else
+ if (best >= 0) {
+ dev_addr = of_read_number(ranges + best, naddr);
+ } else
dev_dbg(dev, "iommu: no suitable range found!\n");
out:
of_node_put(np);
- return pci_addr;
+ return dev_addr;
}
static int dma_set_mask_and_switch(struct device *dev, u64 dma_mask)