Skip to content

Commit

Permalink
Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git…
Browse files Browse the repository at this point in the history
…/benh/powerpc

Pull powerpc updates from Ben Herrenschmidt:
 "Here is some powerpc goodness for -rc2.  Arguably -rc1 material more
  than -rc2 but I was travelling (again !)

  It's mostly bug fixes including regressions, but there are a couple of
  new things that I decided to drop-in.

  One is a straightforward patch from Michael to add a bunch of P8 cache
  events to perf.

  The other one is a patch by myself to add the direct DMA (iommu
  bypass) for PCIe on Power8 for 64-bit capable devices.  This has been
  around for a while, I had lost track of it.  However it's been in our
  internal kernels we use for testing P8 already and it affects only P8
  related code.  Since P8 is still unreleased the risk is pretty much
  nil at this point"

* 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc:
  powerpc/powernv: Add iommu DMA bypass support for IODA2
  powerpc: Fix endian issues in kexec and crash dump code
  powerpc/ppc32: Fix the bug in the init of non-base exception stack for UP
  powerpc/xmon: Don't signal we've entered until we're finished printing
  powerpc/xmon: Fix timeout loop in get_output_lock()
  powerpc/xmon: Don't loop forever in get_output_lock()
  powerpc/perf: Configure BHRB filter before enabling PMU interrupts
  crypto/nx/nx-842: Fix handling of vmalloc addresses
  powerpc/pseries: Select ARCH_RANDOM on pseries
  powerpc/perf: Add Power8 cache & TLB events
  powerpc/relocate fix relocate processing in LE mode
  powerpc: Fix kdump hang issue on p8 with relocation on exception enabled.
  powerpc/pseries: Disable relocation on exception while going down during crash.
  powerpc/eeh: Drop taken reference to driver on eeh_rmv_device
  powerpc: Fix build failure in sysdev/mpic.c for MPIC_WEIRD=y
  • Loading branch information
torvalds committed Feb 12, 2014
2 parents bbb1955 + cd15b04 commit 45f7fdc
Show file tree
Hide file tree
Showing 24 changed files with 398 additions and 55 deletions.
1 change: 1 addition & 0 deletions arch/powerpc/include/asm/dma-mapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ static inline int dma_supported(struct device *dev, u64 mask)
}

extern int dma_set_mask(struct device *dev, u64 dma_mask);
extern int __dma_set_mask(struct device *dev, u64 dma_mask);

#define dma_alloc_coherent(d,s,h,f) dma_alloc_attrs(d,s,h,f,NULL)

Expand Down
1 change: 1 addition & 0 deletions arch/powerpc/include/asm/iommu.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ struct iommu_table {
#ifdef CONFIG_IOMMU_API
struct iommu_group *it_group;
#endif
void (*set_bypass)(struct iommu_table *tbl, bool enable);
};

/* Pure 2^n version of get_order */
Expand Down
12 changes: 12 additions & 0 deletions arch/powerpc/include/asm/sections.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#ifdef __powerpc64__

extern char __start_interrupts[];
extern char __end_interrupts[];

extern char __prom_init_toc_start[];
Expand All @@ -21,6 +22,17 @@ static inline int in_kernel_text(unsigned long addr)
return 0;
}

static inline int overlaps_interrupt_vector_text(unsigned long start,
unsigned long end)
{
unsigned long real_start, real_end;
real_start = __start_interrupts - _stext;
real_end = __end_interrupts - _stext;

return start < (unsigned long)__va(real_end) &&
(unsigned long)__va(real_start) < end;
}

static inline int overlaps_kernel_text(unsigned long start, unsigned long end)
{
return start < (unsigned long)__init_end &&
Expand Down
10 changes: 7 additions & 3 deletions arch/powerpc/kernel/dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -191,19 +191,23 @@ EXPORT_SYMBOL(dma_direct_ops);

#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16)

int dma_set_mask(struct device *dev, u64 dma_mask)
int __dma_set_mask(struct device *dev, u64 dma_mask)
{
struct dma_map_ops *dma_ops = get_dma_ops(dev);

if (ppc_md.dma_set_mask)
return ppc_md.dma_set_mask(dev, dma_mask);
if ((dma_ops != NULL) && (dma_ops->set_dma_mask != NULL))
return dma_ops->set_dma_mask(dev, dma_mask);
if (!dev->dma_mask || !dma_supported(dev, dma_mask))
return -EIO;
*dev->dma_mask = dma_mask;
return 0;
}
int dma_set_mask(struct device *dev, u64 dma_mask)
{
if (ppc_md.dma_set_mask)
return ppc_md.dma_set_mask(dev, dma_mask);
return __dma_set_mask(dev, dma_mask);
}
EXPORT_SYMBOL(dma_set_mask);

u64 dma_get_required_mask(struct device *dev)
Expand Down
8 changes: 6 additions & 2 deletions arch/powerpc/kernel/eeh_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -362,9 +362,13 @@ static void *eeh_rmv_device(void *data, void *userdata)
*/
if (!dev || (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE))
return NULL;

driver = eeh_pcid_get(dev);
if (driver && driver->err_handler)
return NULL;
if (driver) {
eeh_pcid_put(dev);
if (driver->err_handler)
return NULL;
}

/* Remove it from PCI subsystem */
pr_debug("EEH: Removing %s without EEH sensitive driver\n",
Expand Down
12 changes: 12 additions & 0 deletions arch/powerpc/kernel/iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1088,6 +1088,14 @@ int iommu_take_ownership(struct iommu_table *tbl)
memset(tbl->it_map, 0xff, sz);
iommu_clear_tces_and_put_pages(tbl, tbl->it_offset, tbl->it_size);

/*
* Disable iommu bypass, otherwise the user can DMA to all of
* our physical memory via the bypass window instead of just
* the pages that has been explicitly mapped into the iommu
*/
if (tbl->set_bypass)
tbl->set_bypass(tbl, false);

return 0;
}
EXPORT_SYMBOL_GPL(iommu_take_ownership);
Expand All @@ -1102,6 +1110,10 @@ void iommu_release_ownership(struct iommu_table *tbl)
/* Restore bit#0 set by iommu_init_table() */
if (tbl->it_offset == 0)
set_bit(0, tbl->it_map);

/* The kernel owns the device now, we can restore the iommu bypass */
if (tbl->set_bypass)
tbl->set_bypass(tbl, true);
}
EXPORT_SYMBOL_GPL(iommu_release_ownership);

Expand Down
5 changes: 5 additions & 0 deletions arch/powerpc/kernel/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -559,8 +559,13 @@ void exc_lvl_ctx_init(void)
#ifdef CONFIG_PPC64
cpu_nr = i;
#else
#ifdef CONFIG_SMP
cpu_nr = get_hard_smp_processor_id(i);
#else
cpu_nr = 0;
#endif
#endif

memset((void *)critirq_ctx[cpu_nr], 0, THREAD_SIZE);
tp = critirq_ctx[cpu_nr];
tp->cpu = cpu_nr;
Expand Down
14 changes: 10 additions & 4 deletions arch/powerpc/kernel/machine_kexec.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,9 @@ int overlaps_crashkernel(unsigned long start, unsigned long size)

/* Values we need to export to the second kernel via the device tree. */
static phys_addr_t kernel_end;
static phys_addr_t crashk_base;
static phys_addr_t crashk_size;
static unsigned long long mem_limit;

static struct property kernel_end_prop = {
.name = "linux,kernel-end",
Expand All @@ -207,7 +209,7 @@ static struct property kernel_end_prop = {
static struct property crashk_base_prop = {
.name = "linux,crashkernel-base",
.length = sizeof(phys_addr_t),
.value = &crashk_res.start,
.value = &crashk_base
};

static struct property crashk_size_prop = {
Expand All @@ -219,9 +221,11 @@ static struct property crashk_size_prop = {
static struct property memory_limit_prop = {
.name = "linux,memory-limit",
.length = sizeof(unsigned long long),
.value = &memory_limit,
.value = &mem_limit,
};

#define cpu_to_be_ulong __PASTE(cpu_to_be, BITS_PER_LONG)

static void __init export_crashk_values(struct device_node *node)
{
struct property *prop;
Expand All @@ -237,15 +241,17 @@ static void __init export_crashk_values(struct device_node *node)
of_remove_property(node, prop);

if (crashk_res.start != 0) {
crashk_base = cpu_to_be_ulong(crashk_res.start),
of_add_property(node, &crashk_base_prop);
crashk_size = resource_size(&crashk_res);
crashk_size = cpu_to_be_ulong(resource_size(&crashk_res));
of_add_property(node, &crashk_size_prop);
}

/*
* memory_limit is required by the kexec-tools to limit the
* crash regions to the actual memory used.
*/
mem_limit = cpu_to_be_ulong(memory_limit);
of_update_property(node, &memory_limit_prop);
}

Expand All @@ -264,7 +270,7 @@ static int __init kexec_setup(void)
of_remove_property(node, prop);

/* information needed by userspace when using default_machine_kexec */
kernel_end = __pa(_end);
kernel_end = cpu_to_be_ulong(__pa(_end));
of_add_property(node, &kernel_end_prop);

export_crashk_values(node);
Expand Down
6 changes: 4 additions & 2 deletions arch/powerpc/kernel/machine_kexec_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,7 @@ void default_machine_kexec(struct kimage *image)

/* Values we need to export to the second kernel via the device tree. */
static unsigned long htab_base;
static unsigned long htab_size;

static struct property htab_base_prop = {
.name = "linux,htab-base",
Expand All @@ -379,7 +380,7 @@ static struct property htab_base_prop = {
static struct property htab_size_prop = {
.name = "linux,htab-size",
.length = sizeof(unsigned long),
.value = &htab_size_bytes,
.value = &htab_size,
};

static int __init export_htab_values(void)
Expand All @@ -403,8 +404,9 @@ static int __init export_htab_values(void)
if (prop)
of_remove_property(node, prop);

htab_base = __pa(htab_address);
htab_base = cpu_to_be64(__pa(htab_address));
of_add_property(node, &htab_base_prop);
htab_size = cpu_to_be64(htab_size_bytes);
of_add_property(node, &htab_size_prop);

of_node_put(node);
Expand Down
4 changes: 2 additions & 2 deletions arch/powerpc/kernel/reloc_64.S
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ _GLOBAL(relocate)
* R_PPC64_RELATIVE ones.
*/
mtctr r8
5: lwz r0,12(9) /* ELF64_R_TYPE(reloc->r_info) */
cmpwi r0,R_PPC64_RELATIVE
5: ld r0,8(9) /* ELF64_R_TYPE(reloc->r_info) */
cmpdi r0,R_PPC64_RELATIVE
bne 6f
ld r6,0(r9) /* reloc->r_offset */
ld r0,16(r9) /* reloc->r_addend */
Expand Down
5 changes: 5 additions & 0 deletions arch/powerpc/kernel/setup_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,12 @@ static void __init exc_lvl_early_init(void)
/* interrupt stacks must be in lowmem, we get that for free on ppc32
* as the memblock is limited to lowmem by MEMBLOCK_REAL_LIMIT */
for_each_possible_cpu(i) {
#ifdef CONFIG_SMP
hw_cpu = get_hard_smp_processor_id(i);
#else
hw_cpu = 0;
#endif

critirq_ctx[hw_cpu] = (struct thread_info *)
__va(memblock_alloc(THREAD_SIZE, THREAD_SIZE));
#ifdef CONFIG_BOOKE
Expand Down
14 changes: 14 additions & 0 deletions arch/powerpc/mm/hash_utils_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,20 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
if (overlaps_kernel_text(vaddr, vaddr + step))
tprot &= ~HPTE_R_N;

/*
* If relocatable, check if it overlaps interrupt vectors that
* are copied down to real 0. For relocatable kernel
* (e.g. kdump case) we copy interrupt vectors down to real
* address 0. Mark that region as executable. This is
* because on p8 system with relocation on exception feature
* enabled, exceptions are raised with MMU (IR=DR=1) ON. Hence
* in order to execute the interrupt handlers in virtual
* mode the vector region need to be marked as executable.
*/
if ((PHYSICAL_START > MEMORY_START) &&
overlaps_interrupt_vector_text(vaddr, vaddr + step))
tprot &= ~HPTE_R_N;

hash = hpt_hash(vpn, shift, ssize);
hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP);

Expand Down
5 changes: 3 additions & 2 deletions arch/powerpc/perf/core-book3s.c
Original file line number Diff line number Diff line change
Expand Up @@ -1147,6 +1147,9 @@ static void power_pmu_enable(struct pmu *pmu)
mmcr0 = ebb_switch_in(ebb, cpuhw->mmcr[0]);

mb();
if (cpuhw->bhrb_users)
ppmu->config_bhrb(cpuhw->bhrb_filter);

write_mmcr0(cpuhw, mmcr0);

/*
Expand All @@ -1158,8 +1161,6 @@ static void power_pmu_enable(struct pmu *pmu)
}

out:
if (cpuhw->bhrb_users)
ppmu->config_bhrb(cpuhw->bhrb_filter);

local_irq_restore(flags);
}
Expand Down
Loading

0 comments on commit 45f7fdc

Please sign in to comment.