Merge branch 'parisc-4.16-1' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux

Pull parisc fixes from Helge Deller:

 - a patch to change the ordering of cache and TLB flushes to hopefully
   fix the random segfaults we very rarely face (by Dave Anglin).

 - a patch to hide the virtual kernel memory layout due to security
   reasons.

 - two small patches to make the kernel run more smoothly under qemu.

* 'parisc-4.16-1' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux:
  parisc: Reduce irq overhead when run in qemu
  parisc: Use cr16 interval timers unconditionally on qemu
  parisc: Check if secondary CPUs want own PDC calls
  parisc: Hide virtual kernel memory layout
  parisc: Fix ordering of cache and TLB flushes
This commit is contained in:
Linus Torvalds 2018-03-02 13:05:20 -08:00
commit 5fbdefcf68
8 changed files with 86 additions and 39 deletions

View File

@ -26,6 +26,7 @@ void flush_user_icache_range_asm(unsigned long, unsigned long);
void flush_kernel_icache_range_asm(unsigned long, unsigned long);
void flush_user_dcache_range_asm(unsigned long, unsigned long);
void flush_kernel_dcache_range_asm(unsigned long, unsigned long);
void purge_kernel_dcache_range_asm(unsigned long, unsigned long);
void flush_kernel_dcache_page_asm(void *);
void flush_kernel_icache_page(void *);

View File

@ -316,6 +316,8 @@ extern int _parisc_requires_coherency;
#define parisc_requires_coherency() (0)
#endif
extern int running_on_qemu;
#endif /* __ASSEMBLY__ */
#endif /* __ASM_PARISC_PROCESSOR_H */

View File

@ -465,10 +465,10 @@ EXPORT_SYMBOL(copy_user_page);
int __flush_tlb_range(unsigned long sid, unsigned long start,
unsigned long end)
{
unsigned long flags, size;
unsigned long flags;
size = (end - start);
if (size >= parisc_tlb_flush_threshold) {
if ((!IS_ENABLED(CONFIG_SMP) || !arch_irqs_disabled()) &&
end - start >= parisc_tlb_flush_threshold) {
flush_tlb_all();
return 1;
}
@ -539,13 +539,11 @@ void flush_cache_mm(struct mm_struct *mm)
struct vm_area_struct *vma;
pgd_t *pgd;
/* Flush the TLB to avoid speculation if coherency is required. */
if (parisc_requires_coherency())
flush_tlb_all();
/* Flushing the whole cache on each cpu takes forever on
rp3440, etc. So, avoid it if the mm isn't too big. */
if (mm_total_size(mm) >= parisc_cache_flush_threshold) {
if ((!IS_ENABLED(CONFIG_SMP) || !arch_irqs_disabled()) &&
mm_total_size(mm) >= parisc_cache_flush_threshold) {
flush_tlb_all();
flush_cache_all();
return;
}
@ -553,9 +551,9 @@ void flush_cache_mm(struct mm_struct *mm)
if (mm->context == mfsp(3)) {
for (vma = mm->mmap; vma; vma = vma->vm_next) {
flush_user_dcache_range_asm(vma->vm_start, vma->vm_end);
if ((vma->vm_flags & VM_EXEC) == 0)
continue;
flush_user_icache_range_asm(vma->vm_start, vma->vm_end);
if (vma->vm_flags & VM_EXEC)
flush_user_icache_range_asm(vma->vm_start, vma->vm_end);
flush_tlb_range(vma, vma->vm_start, vma->vm_end);
}
return;
}
@ -581,14 +579,9 @@ void flush_cache_mm(struct mm_struct *mm)
void flush_cache_range(struct vm_area_struct *vma,
unsigned long start, unsigned long end)
{
BUG_ON(!vma->vm_mm->context);
/* Flush the TLB to avoid speculation if coherency is required. */
if (parisc_requires_coherency())
if ((!IS_ENABLED(CONFIG_SMP) || !arch_irqs_disabled()) &&
end - start >= parisc_cache_flush_threshold) {
flush_tlb_range(vma, start, end);
if ((end - start) >= parisc_cache_flush_threshold
|| vma->vm_mm->context != mfsp(3)) {
flush_cache_all();
return;
}
@ -596,6 +589,7 @@ void flush_cache_range(struct vm_area_struct *vma,
flush_user_dcache_range_asm(start, end);
if (vma->vm_flags & VM_EXEC)
flush_user_icache_range_asm(start, end);
flush_tlb_range(vma, start, end);
}
void
@ -604,8 +598,7 @@ flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long
BUG_ON(!vma->vm_mm->context);
if (pfn_valid(pfn)) {
if (parisc_requires_coherency())
flush_tlb_page(vma, vmaddr);
flush_tlb_page(vma, vmaddr);
__flush_cache_page(vma, vmaddr, PFN_PHYS(pfn));
}
}
@ -613,21 +606,33 @@ flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long
void flush_kernel_vmap_range(void *vaddr, int size)
{
unsigned long start = (unsigned long)vaddr;
unsigned long end = start + size;
if ((unsigned long)size > parisc_cache_flush_threshold)
if ((!IS_ENABLED(CONFIG_SMP) || !arch_irqs_disabled()) &&
(unsigned long)size >= parisc_cache_flush_threshold) {
flush_tlb_kernel_range(start, end);
flush_data_cache();
else
flush_kernel_dcache_range_asm(start, start + size);
return;
}
flush_kernel_dcache_range_asm(start, end);
flush_tlb_kernel_range(start, end);
}
EXPORT_SYMBOL(flush_kernel_vmap_range);
void invalidate_kernel_vmap_range(void *vaddr, int size)
{
unsigned long start = (unsigned long)vaddr;
unsigned long end = start + size;
if ((unsigned long)size > parisc_cache_flush_threshold)
if ((!IS_ENABLED(CONFIG_SMP) || !arch_irqs_disabled()) &&
(unsigned long)size >= parisc_cache_flush_threshold) {
flush_tlb_kernel_range(start, end);
flush_data_cache();
else
flush_kernel_dcache_range_asm(start, start + size);
return;
}
purge_kernel_dcache_range_asm(start, end);
flush_tlb_kernel_range(start, end);
}
EXPORT_SYMBOL(invalidate_kernel_vmap_range);

View File

@ -138,6 +138,16 @@ $pgt_fill_loop:
std %dp,0x18(%r10)
#endif
#ifdef CONFIG_64BIT
/* Get PDCE_PROC for monarch CPU. */
#define MEM_PDC_LO 0x388
#define MEM_PDC_HI 0x35C
ldw MEM_PDC_LO(%r0),%r3
ldw MEM_PDC_HI(%r0),%r10
depd %r10, 31, 32, %r3 /* move to upper word */
#endif
#ifdef CONFIG_SMP
/* Set the smp rendezvous address into page zero.
** It would be safer to do this in init_smp_config() but
@ -196,12 +206,6 @@ common_stext:
** Someday, palo might not do this for the Monarch either.
*/
2:
#define MEM_PDC_LO 0x388
#define MEM_PDC_HI 0x35C
ldw MEM_PDC_LO(%r0),%r3
ldw MEM_PDC_HI(%r0),%r6
depd %r6, 31, 32, %r3 /* move to upper word */
mfctl %cr30,%r6 /* PCX-W2 firmware bug */
ldo PDC_PSW(%r0),%arg0 /* 21 */
@ -268,6 +272,8 @@ $install_iva:
aligned_rfi:
pcxt_ssm_bug
copy %r3, %arg0 /* PDCE_PROC for smp_callin() */
rsm PSW_SM_QUIET,%r0 /* off troublesome PSW bits */
/* Don't need NOPs, have 8 compliant insn before rfi */

View File

@ -1110,6 +1110,28 @@ ENTRY_CFI(flush_kernel_dcache_range_asm)
.procend
ENDPROC_CFI(flush_kernel_dcache_range_asm)
ENTRY_CFI(purge_kernel_dcache_range_asm)
.proc
.callinfo NO_CALLS
.entry
ldil L%dcache_stride, %r1
ldw R%dcache_stride(%r1), %r23
ldo -1(%r23), %r21
ANDCM %r26, %r21, %r26
1: cmpb,COND(<<),n %r26, %r25,1b
pdc,m %r23(%r26)
sync
syncdma
bv %r0(%r2)
nop
.exit
.procend
ENDPROC_CFI(purge_kernel_dcache_range_asm)
ENTRY_CFI(flush_user_icache_range_asm)
.proc
.callinfo NO_CALLS

View File

@ -292,10 +292,15 @@ smp_cpu_init(int cpunum)
* Slaves start using C here. Indirectly called from smp_slave_stext.
* Do what start_kernel() and main() do for boot strap processor (aka monarch)
*/
void __init smp_callin(void)
void __init smp_callin(unsigned long pdce_proc)
{
int slave_id = cpu_now_booting;
#ifdef CONFIG_64BIT
WARN_ON(((unsigned long)(PAGE0->mem_pdc_hi) << 32
| PAGE0->mem_pdc) != pdce_proc);
#endif
smp_cpu_init(slave_id);
preempt_disable();

View File

@ -76,10 +76,10 @@ irqreturn_t __irq_entry timer_interrupt(int irq, void *dev_id)
next_tick = cpuinfo->it_value;
/* Calculate how many ticks have elapsed. */
now = mfctl(16);
do {
++ticks_elapsed;
next_tick += cpt;
now = mfctl(16);
} while (next_tick - now > cpt);
/* Store (in CR16 cycles) up to when we are accounting right now. */
@ -103,16 +103,17 @@ irqreturn_t __irq_entry timer_interrupt(int irq, void *dev_id)
* if one or the other wrapped. If "now" is "bigger" we'll end up
* with a very large unsigned number.
*/
while (next_tick - mfctl(16) > cpt)
now = mfctl(16);
while (next_tick - now > cpt)
next_tick += cpt;
/* Program the IT when to deliver the next interrupt.
* Only bottom 32-bits of next_tick are writable in CR16!
* Timer interrupt will be delivered at least a few hundred cycles
* after the IT fires, so if we are too close (<= 500 cycles) to the
* after the IT fires, so if we are too close (<= 8000 cycles) to the
* next cycle, simply skip it.
*/
if (next_tick - mfctl(16) <= 500)
if (next_tick - now <= 8000)
next_tick += cpt;
mtctl(next_tick, 16);
@ -248,7 +249,7 @@ static int __init init_cr16_clocksource(void)
* different sockets, so mark them unstable and lower rating on
* multi-socket SMP systems.
*/
if (num_online_cpus() > 1) {
if (num_online_cpus() > 1 && !running_on_qemu) {
int cpu;
unsigned long cpu0_loc;
cpu0_loc = per_cpu(cpu_data, 0).cpu_loc;

View File

@ -629,7 +629,12 @@ void __init mem_init(void)
#endif
mem_init_print_info(NULL);
#ifdef CONFIG_DEBUG_KERNEL /* double-sanity-check paranoia */
#if 0
/*
* Do not expose the virtual kernel memory layout to userspace.
* But keep code for debugging purposes.
*/
printk("virtual kernel memory layout:\n"
" vmalloc : 0x%px - 0x%px (%4ld MB)\n"
" memory : 0x%px - 0x%px (%4ld MB)\n"