Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

parisc: Use lpa instruction to load physical addresses in driver code

Most I/O in the kernel is done using the kernel offset mapping.
However, there is one API that uses aliased kernel address ranges:

> The final category of APIs is for I/O to deliberately aliased address
> ranges inside the kernel. Such aliases are set up by use of the
> vmap/vmalloc API. Since kernel I/O goes via physical pages, the I/O
> subsystem assumes that the user mapping and kernel offset mapping are
> the only aliases. This isn't true for vmap aliases, so anything in
> the kernel trying to do I/O to vmap areas must manually manage
> coherency. It must do this by flushing the vmap range before doing
> I/O and invalidating it after the I/O returns.

For this reason, we should use the hardware lpa instruction to load the
physical address of kernel virtual addresses in the driver code.

I believe we only use the vmap/vmalloc API with old PA 1.x processors
which don't have a sba, so we don't hit this problem.

Tested on c3750, c8000 and rp3440.

Signed-off-by: John David Anglin <dave.anglin@bell.net>
Signed-off-by: Helge Deller <deller@gmx.de>

authored by

John David Anglin and committed by
Helge Deller
116d7533 ec13c82d

+26 -2
+24
arch/parisc/include/asm/special_insns.h
··· 2 2 #ifndef __PARISC_SPECIAL_INSNS_H 3 3 #define __PARISC_SPECIAL_INSNS_H 4 4 5 + #define lpa(va) ({ \ 6 + unsigned long pa; \ 7 + __asm__ __volatile__( \ 8 + "copy %%r0,%0\n\t" \ 9 + "lpa %%r0(%1),%0" \ 10 + : "=r" (pa) \ 11 + : "r" (va) \ 12 + : "memory" \ 13 + ); \ 14 + pa; \ 15 + }) 16 + 17 + #define lpa_user(va) ({ \ 18 + unsigned long pa; \ 19 + __asm__ __volatile__( \ 20 + "copy %%r0,%0\n\t" \ 21 + "lpa %%r0(%%sr3,%1),%0" \ 22 + : "=r" (pa) \ 23 + : "r" (va) \ 24 + : "memory" \ 25 + ); \ 26 + pa; \ 27 + }) 28 + 5 29 #define mfctl(reg) ({ \ 6 30 unsigned long cr; \ 7 31 __asm__ __volatile__( \
+1 -1
drivers/parisc/ccio-dma.c
··· 570 570 ** "hints" parm includes the VALID bit! 571 571 ** "dep" clobbers the physical address offset bits as well. 572 572 */ 573 - pa = virt_to_phys(vba); 573 + pa = lpa(vba); 574 574 asm volatile("depw %1,31,12,%0" : "+r" (pa) : "r" (hints)); 575 575 ((u32 *)pdir_ptr)[1] = (u32) pa; 576 576
+1 -1
drivers/parisc/sba_iommu.c
··· 572 572 u64 pa; /* physical address */ 573 573 register unsigned ci; /* coherent index */ 574 574 575 - pa = virt_to_phys(vba); 575 + pa = lpa(vba); 576 576 pa &= IOVP_MASK; 577 577 578 578 asm("lci 0(%1), %0" : "=r" (ci) : "r" (vba));