1. 27 Aug, 2019 5 commits
    • Will Deacon's avatar
      arm64: mm: Ignore spurious translation faults taken from the kernel · 42f91093
      Will Deacon authored
      Thanks to address translation being performed out of order with respect to
      loads and stores, it is possible for a CPU to take a translation fault when
      accessing a page that was mapped by a different CPU.
      
      For example, in the case that one CPU maps a page and then sets a flag to
      tell another CPU:
      
      	CPU 0
      	-----
      
      	MOV	X0, <valid pte>
      	STR	X0, [Xptep]	// Store new PTE to page table
      	DSB	ISHST
      	ISB
      	MOV	X1, #1
      	STR	X1, [Xflag]	// Set the flag
      
      	CPU 1
      	-----
      
      loop:	LDAR	X0, [Xflag]	// Poll flag with Acquire semantics
      	CBZ	X0, loop
      	LDR	X1, [X2]	// Translates using the new PTE
      
      then the final load on CPU 1 can raise a translation fault because the
      translation can be performed speculatively before the read of the flag and
      marked as "faulting" by the CPU. This isn't quite as bad as it sounds
      since, in reality, code such as:
      
      	CPU 0				CPU 1
      	-----				-----
      	spin_lock(&lock);		spin_lock(&lock);
      	*ptr = vmalloc(size);		if (*ptr)
      	spin_unlock(&lock);			foo = **ptr;
      					spin_unlock(&lock);
      
      will not trigger the fault because there is an address dependency on CPU 1
      which prevents the speculative translation. However, more exotic code where
      the virtual address is known ahead of time, such as:
      
      	CPU 0				CPU 1
      	-----				-----
      	spin_lock(&lock);		spin_lock(&lock);
      	set_fixmap(0, paddr, prot);	if (mapped)
      	mapped = true;				foo = *fix_to_virt(0);
      	spin_unlock(&lock);		spin_unlock(&lock);
      
      could fault. This can be avoided by any of:
      
      	* Introducing broadcast TLB maintenance on the map path
      	* Adding a DSB;ISB sequence after checking a flag which indicates
      	  that a virtual address is now mapped
      	* Handling the spurious fault
      
      Given that we have never observed a problem due to this under Linux and
      future revisions of the architecture are being tightened so that
      translation table walks are effectively ordered in the same way as explicit
      memory accesses, we no longer treat spurious kernel faults as fatal if an
      AT instruction indicates that the access does not trigger a translation
      fault.
      Reviewed-by: default avatarMark Rutland <mark.rutland@arm.com>
      Signed-off-by: default avatarWill Deacon <will@kernel.org>
      42f91093
    • Will Deacon's avatar
      arm64: sysreg: Add some field definitions for PAR_EL1 · e8620cff
      Will Deacon authored
      PAR_EL1 is a mysterious creature, but sometimes it's necessary to read
      it when translating addresses in situations where we cannot walk the
      page table directly.
      
      Add a couple of system register definitions for the fault indication
      field ('F') and the fault status code ('FST').
      Reviewed-by: default avatarMark Rutland <mark.rutland@arm.com>
      Signed-off-by: default avatarWill Deacon <will@kernel.org>
      e8620cff
    • Will Deacon's avatar
      arm64: mm: Add ISB instruction to set_pgd() · eb6a4dcc
      Will Deacon authored
      Commit 6a4cbd63c25a ("Revert "arm64: Remove unnecessary ISBs from
      set_{pte,pmd,pud}"") reintroduced ISB instructions to some of our
      page table setter functions in light of a recent clarification to the
      Armv8 architecture. Although 'set_pgd()' isn't currently used to update
      a live page table, add the ISB instruction there too for consistency
      with the other macros and to provide some future-proofing if we use it
      on live tables in the future.
      Reported-by: default avatarMark Rutland <mark.rutland@arm.com>
      Reviewed-by: default avatarMark Rutland <mark.rutland@arm.com>
      Signed-off-by: default avatarWill Deacon <will@kernel.org>
      eb6a4dcc
    • Will Deacon's avatar
      arm64: tlb: Ensure we execute an ISB following walk cache invalidation · 51696d34
      Will Deacon authored
      05f2d2f8 ("arm64: tlbflush: Introduce __flush_tlb_kernel_pgtable")
      added a new TLB invalidation helper which is used when freeing
      intermediate levels of page table used for kernel mappings, but is
      missing the required ISB instruction after completion of the TLBI
      instruction.
      
      Add the missing barrier.
      
      Cc: <stable@vger.kernel.org>
      Fixes: 05f2d2f8 ("arm64: tlbflush: Introduce __flush_tlb_kernel_pgtable")
      Reviewed-by: default avatarMark Rutland <mark.rutland@arm.com>
      Signed-off-by: default avatarWill Deacon <will@kernel.org>
      51696d34
    • Will Deacon's avatar
      Revert "arm64: Remove unnecessary ISBs from set_{pte,pmd,pud}" · d0b7a302
      Will Deacon authored
      This reverts commit 24fe1b0e.
      
      Commit 24fe1b0e ("arm64: Remove unnecessary ISBs from
      set_{pte,pmd,pud}") removed ISB instructions immediately following updates
      to the page table, on the grounds that they are not required by the
      architecture and a DSB alone is sufficient to ensure that subsequent data
      accesses use the new translation:
      
        DDI0487E_a, B2-128:
      
        | ... no instruction that appears in program order after the DSB
        | instruction can alter any state of the system or perform any part of
        | its functionality until the DSB completes other than:
        |
        | * Being fetched from memory and decoded
        | * Reading the general-purpose, SIMD and floating-point,
        |   Special-purpose, or System registers that are directly or indirectly
        |   read without causing side-effects.
      
      However, the same document also states the following:
      
        DDI0487E_a, B2-125:
      
        | DMB and DSB instructions affect reads and writes to the memory system
        | generated by Load/Store instructions and data or unified cache
        | maintenance instructions being executed by the PE. Instruction fetches
        | or accesses caused by a hardware translation table access are not
        | explicit accesses.
      
      which appears to claim that the DSB alone is insufficient.  Unfortunately,
      some CPU designers have followed the second clause above, whereas in Linux
      we've been relying on the first. This means that our mapping sequence:
      
      	MOV	X0, <valid pte>
      	STR	X0, [Xptep]	// Store new PTE to page table
      	DSB	ISHST
      	LDR	X1, [X2]	// Translates using the new PTE
      
      can actually raise a translation fault on the load instruction because the
      translation can be performed speculatively before the page table update and
      then marked as "faulting" by the CPU. For user PTEs, this is ok because we
      can handle the spurious fault, but for kernel PTEs and intermediate table
      entries this results in a panic().
      
      Revert the offending commit to reintroduce the missing barriers.
      
      Cc: <stable@vger.kernel.org>
      Fixes: 24fe1b0e ("arm64: Remove unnecessary ISBs from set_{pte,pmd,pud}")
      Reviewed-by: default avatarMark Rutland <mark.rutland@arm.com>
      Signed-off-by: default avatarWill Deacon <will@kernel.org>
      d0b7a302
  2. 05 Aug, 2019 1 commit
  3. 04 Aug, 2019 10 commits
  4. 03 Aug, 2019 24 commits