mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 10:58:48 +09:00
Merge 8a5be36b93 ("Merge tag 'powerpc-5.11-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux") into android-mainline
Steps on the way to 5.11-rc1 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: I251afb735caf9b4382a169be56978964380c194d
This commit is contained in:
@@ -66,7 +66,7 @@ config NEED_PER_CPU_PAGE_FIRST_CHUNK
|
||||
|
||||
config NR_IRQS
|
||||
int "Number of virtual interrupt numbers"
|
||||
range 32 32768
|
||||
range 32 1048576
|
||||
default "512"
|
||||
help
|
||||
This defines the number of virtual interrupt numbers the kernel
|
||||
@@ -87,7 +87,7 @@ config PPC_WATCHDOG
|
||||
help
|
||||
This is a placeholder when the powerpc hardlockup detector
|
||||
watchdog is selected (arch/powerpc/kernel/watchdog.c). It is
|
||||
seleted via the generic lockup detector menu which is why we
|
||||
selected via the generic lockup detector menu which is why we
|
||||
have no standalone config option for it here.
|
||||
|
||||
config STACKTRACE_SUPPORT
|
||||
@@ -177,6 +177,7 @@ config PPC
|
||||
select GENERIC_STRNCPY_FROM_USER
|
||||
select GENERIC_STRNLEN_USER
|
||||
select GENERIC_TIME_VSYSCALL
|
||||
select GENERIC_GETTIMEOFDAY
|
||||
select HAVE_ARCH_AUDITSYSCALL
|
||||
select HAVE_ARCH_HUGE_VMAP if PPC_BOOK3S_64 && PPC_RADIX_MMU
|
||||
select HAVE_ARCH_JUMP_LABEL
|
||||
@@ -207,6 +208,7 @@ config PPC
|
||||
select HAVE_FUNCTION_GRAPH_TRACER
|
||||
select HAVE_FUNCTION_TRACER
|
||||
select HAVE_GCC_PLUGINS if GCC_VERSION >= 50200 # plugin support on gcc <= 5.1 is buggy on PPC
|
||||
select HAVE_GENERIC_VDSO
|
||||
select HAVE_HW_BREAKPOINT if PERF_EVENTS && (PPC_BOOK3S || PPC_8xx)
|
||||
select HAVE_IDE
|
||||
select HAVE_IOREMAP_PROT
|
||||
@@ -312,6 +314,10 @@ config GENERIC_BUG
|
||||
default y
|
||||
depends on BUG
|
||||
|
||||
config GENERIC_BUG_RELATIVE_POINTERS
|
||||
def_bool y
|
||||
depends on GENERIC_BUG
|
||||
|
||||
config SYS_SUPPORTS_APM_EMULATION
|
||||
default y if PMAC_APM_EMU
|
||||
bool
|
||||
@@ -418,6 +424,7 @@ config HUGETLB_PAGE_SIZE_VARIABLE
|
||||
config MATH_EMULATION
|
||||
bool "Math emulation"
|
||||
depends on 4xx || PPC_8xx || PPC_MPC832x || BOOKE
|
||||
select PPC_FPU_REGS
|
||||
help
|
||||
Some PowerPC chips designed for embedded applications do not have
|
||||
a floating-point unit and therefore do not implement the
|
||||
@@ -657,9 +664,15 @@ config IRQ_ALL_CPUS
|
||||
reported with SMP Power Macintoshes with this option enabled.
|
||||
|
||||
config NUMA
|
||||
bool "NUMA support"
|
||||
depends on PPC64
|
||||
default y if SMP && PPC_PSERIES
|
||||
bool "NUMA Memory Allocation and Scheduler Support"
|
||||
depends on PPC64 && SMP
|
||||
default y if PPC_PSERIES || PPC_POWERNV
|
||||
help
|
||||
Enable NUMA (Non-Uniform Memory Access) support.
|
||||
|
||||
The kernel will try to allocate memory used by a CPU on the
|
||||
local memory controller of the CPU and add some more
|
||||
NUMA awareness to the kernel.
|
||||
|
||||
config NODES_SHIFT
|
||||
int
|
||||
@@ -793,8 +806,7 @@ config DATA_SHIFT_BOOL
|
||||
bool "Set custom data alignment"
|
||||
depends on ADVANCED_OPTIONS
|
||||
depends on STRICT_KERNEL_RWX || DEBUG_PAGEALLOC
|
||||
depends on PPC_BOOK3S_32 || (PPC_8xx && !PIN_TLB_DATA && \
|
||||
(!PIN_TLB_TEXT || !STRICT_KERNEL_RWX))
|
||||
depends on PPC_BOOK3S_32 || (PPC_8xx && !PIN_TLB_DATA && !STRICT_KERNEL_RWX)
|
||||
help
|
||||
This option allows you to set the kernel data alignment. When
|
||||
RAM is mapped by blocks, the alignment needs to fit the size and
|
||||
|
||||
@@ -374,6 +374,11 @@ ppc64le_allmodconfig:
|
||||
$(Q)$(MAKE) KCONFIG_ALLCONFIG=$(srctree)/arch/powerpc/configs/le.config \
|
||||
-f $(srctree)/Makefile allmodconfig
|
||||
|
||||
PHONY += ppc64le_allnoconfig
|
||||
ppc64le_allnoconfig:
|
||||
$(Q)$(MAKE) KCONFIG_ALLCONFIG=$(srctree)/arch/powerpc/configs/ppc64le.config \
|
||||
-f $(srctree)/Makefile allnoconfig
|
||||
|
||||
PHONY += ppc64_book3e_allmodconfig
|
||||
ppc64_book3e_allmodconfig:
|
||||
$(Q)$(MAKE) KCONFIG_ALLCONFIG=$(srctree)/arch/powerpc/configs/85xx-64bit.config \
|
||||
@@ -405,18 +410,24 @@ PHONY += install
|
||||
install:
|
||||
$(Q)$(MAKE) $(build)=$(boot) install
|
||||
|
||||
PHONY += vdso_install
|
||||
vdso_install:
|
||||
ifdef CONFIG_PPC64
|
||||
$(Q)$(MAKE) $(build)=arch/$(ARCH)/kernel/vdso64 $@
|
||||
endif
|
||||
ifdef CONFIG_VDSO32
|
||||
$(Q)$(MAKE) $(build)=arch/$(ARCH)/kernel/vdso32 $@
|
||||
endif
|
||||
|
||||
archclean:
|
||||
$(Q)$(MAKE) $(clean)=$(boot)
|
||||
|
||||
ifeq ($(KBUILD_EXTMOD),)
|
||||
# We need to generate vdso-offsets.h before compiling certain files in kernel/.
|
||||
# In order to do that, we should use the archprepare target, but we can't since
|
||||
# asm-offsets.h is included in some files used to generate vdso-offsets.h, and
|
||||
# asm-offsets.h is built in prepare0, for which archprepare is a dependency.
|
||||
# Therefore we need to generate the header after prepare0 has been made, hence
|
||||
# this hack.
|
||||
prepare: vdso_prepare
|
||||
vdso_prepare: prepare0
|
||||
$(if $(CONFIG_VDSO32),$(Q)$(MAKE) \
|
||||
$(build)=arch/powerpc/kernel/vdso32 include/generated/vdso32-offsets.h)
|
||||
$(if $(CONFIG_PPC64),$(Q)$(MAKE) \
|
||||
$(build)=arch/powerpc/kernel/vdso64 include/generated/vdso64-offsets.h)
|
||||
endif
|
||||
|
||||
archprepare: checkbin
|
||||
|
||||
archheaders:
|
||||
|
||||
@@ -21,7 +21,11 @@
|
||||
all: $(obj)/zImage
|
||||
|
||||
ifdef CROSS32_COMPILE
|
||||
ifdef CONFIG_CC_IS_CLANG
|
||||
BOOTCC := $(CROSS32_COMPILE)clang
|
||||
else
|
||||
BOOTCC := $(CROSS32_COMPILE)gcc
|
||||
endif
|
||||
BOOTAR := $(CROSS32_COMPILE)ar
|
||||
else
|
||||
BOOTCC := $(CC)
|
||||
|
||||
@@ -21,13 +21,6 @@ extern int lv1_get_logical_ppe_id(u64 *out_1);
|
||||
extern int lv1_get_repository_node_value(u64 in_1, u64 in_2, u64 in_3,
|
||||
u64 in_4, u64 in_5, u64 *out_1, u64 *out_2);
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DBG(fmt...) printf(fmt)
|
||||
#else
|
||||
static inline int __attribute__ ((format (printf, 1, 2))) DBG(
|
||||
const char *fmt, ...) {return 0;}
|
||||
#endif
|
||||
|
||||
BSS_STACK(4096);
|
||||
|
||||
/* A buffer that may be edited by tools operating on a zImage binary so as to
|
||||
|
||||
@@ -42,14 +42,11 @@ udelay:
|
||||
* (nanoseconds + (timebase_period_ns - 1 )) / timebase_period_ns
|
||||
* timebase_period_ns defaults to 60 (16.6MHz) */
|
||||
mflr r5
|
||||
bl 0f
|
||||
bcl 20,31,0f
|
||||
0: mflr r6
|
||||
mtlr r5
|
||||
lis r5,0b@ha
|
||||
addi r5,r5,0b@l
|
||||
subf r5,r5,r6 /* In case we're relocated */
|
||||
addis r5,r5,timebase_period_ns@ha
|
||||
lwz r5,timebase_period_ns@l(r5)
|
||||
addis r5,r6,(timebase_period_ns-0b)@ha
|
||||
lwz r5,(timebase_period_ns-0b)@l(r5)
|
||||
add r4,r4,r5
|
||||
addi r4,r4,-1
|
||||
divw r4,r4,r5 /* BUS ticks */
|
||||
|
||||
@@ -46,6 +46,8 @@ compression=.gz
|
||||
uboot_comp=gzip
|
||||
pie=
|
||||
format=
|
||||
notext=
|
||||
rodynamic=
|
||||
|
||||
# cross-compilation prefix
|
||||
CROSS=
|
||||
@@ -353,6 +355,8 @@ epapr)
|
||||
platformo="$object/pseries-head.o $object/epapr.o $object/epapr-wrapper.o"
|
||||
link_address='0x20000000'
|
||||
pie=-pie
|
||||
notext='-z notext'
|
||||
rodynamic=$(if ${CROSS}ld -V 2>&1 | grep -q LLD ; then echo "-z rodynamic"; fi)
|
||||
;;
|
||||
mvme5100)
|
||||
platformo="$object/fixed-head.o $object/mvme5100.o"
|
||||
@@ -493,7 +497,7 @@ if [ "$platform" != "miboot" ]; then
|
||||
text_start="-Ttext $link_address"
|
||||
fi
|
||||
#link everything
|
||||
${CROSS}ld -m $format -T $lds $text_start $pie $nodl -o "$ofile" $map \
|
||||
${CROSS}ld -m $format -T $lds $text_start $pie $nodl $rodynamic $notext -o "$ofile" $map \
|
||||
$platformo $tmp $object/wrapper.a
|
||||
rm $tmp
|
||||
fi
|
||||
|
||||
@@ -34,6 +34,17 @@ SECTIONS
|
||||
__dynamic_start = .;
|
||||
*(.dynamic)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC64_BOOT_WRAPPER
|
||||
. = ALIGN(256);
|
||||
.got :
|
||||
{
|
||||
__toc_start = .;
|
||||
*(.got)
|
||||
*(.toc)
|
||||
}
|
||||
#endif
|
||||
|
||||
.hash : { *(.hash) }
|
||||
.interp : { *(.interp) }
|
||||
.rela.dyn :
|
||||
@@ -76,16 +87,6 @@ SECTIONS
|
||||
_esm_blob_end = .;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC64_BOOT_WRAPPER
|
||||
. = ALIGN(256);
|
||||
.got :
|
||||
{
|
||||
__toc_start = .;
|
||||
*(.got)
|
||||
*(.toc)
|
||||
}
|
||||
#endif
|
||||
|
||||
. = ALIGN(4096);
|
||||
.bss :
|
||||
{
|
||||
|
||||
1
arch/powerpc/configs/disable-werror.config
Normal file
1
arch/powerpc/configs/disable-werror.config
Normal file
@@ -0,0 +1 @@
|
||||
CONFIG_PPC_DISABLE_WERROR=y
|
||||
2
arch/powerpc/configs/ppc64le.config
Normal file
2
arch/powerpc/configs/ppc64le.config
Normal file
@@ -0,0 +1,2 @@
|
||||
CONFIG_PPC64=y
|
||||
CONFIG_CPU_LITTLE_ENDIAN=y
|
||||
15
arch/powerpc/configs/security.config
Normal file
15
arch/powerpc/configs/security.config
Normal file
@@ -0,0 +1,15 @@
|
||||
# This is the equivalent of booting with lockdown=integrity
|
||||
CONFIG_SECURITY=y
|
||||
CONFIG_SECURITYFS=y
|
||||
CONFIG_SECURITY_LOCKDOWN_LSM=y
|
||||
CONFIG_SECURITY_LOCKDOWN_LSM_EARLY=y
|
||||
CONFIG_LOCK_DOWN_KERNEL_FORCE_INTEGRITY=y
|
||||
|
||||
# These are some general, reasonably inexpensive hardening options
|
||||
CONFIG_HARDENED_USERCOPY=y
|
||||
CONFIG_FORTIFY_SOURCE=y
|
||||
CONFIG_INIT_ON_ALLOC_DEFAULT_ON=y
|
||||
|
||||
# UBSAN bounds checking is very cheap and good for hardening
|
||||
CONFIG_UBSAN=y
|
||||
# CONFIG_UBSAN_MISC is not set
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <linux/types.h>
|
||||
#include <asm/cmpxchg.h>
|
||||
#include <asm/barrier.h>
|
||||
#include <asm/asm-const.h>
|
||||
|
||||
/*
|
||||
* Since *_return_relaxed and {cmp}xchg_relaxed are implemented with
|
||||
@@ -26,14 +27,14 @@ static __inline__ int atomic_read(const atomic_t *v)
|
||||
{
|
||||
int t;
|
||||
|
||||
__asm__ __volatile__("lwz%U1%X1 %0,%1" : "=r"(t) : "m"(v->counter));
|
||||
__asm__ __volatile__("lwz%U1%X1 %0,%1" : "=r"(t) : "m"UPD_CONSTR(v->counter));
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
static __inline__ void atomic_set(atomic_t *v, int i)
|
||||
{
|
||||
__asm__ __volatile__("stw%U0%X0 %1,%0" : "=m"(v->counter) : "r"(i));
|
||||
__asm__ __volatile__("stw%U0%X0 %1,%0" : "=m"UPD_CONSTR(v->counter) : "r"(i));
|
||||
}
|
||||
|
||||
#define ATOMIC_OP(op, asm_op) \
|
||||
@@ -316,14 +317,14 @@ static __inline__ s64 atomic64_read(const atomic64_t *v)
|
||||
{
|
||||
s64 t;
|
||||
|
||||
__asm__ __volatile__("ld%U1%X1 %0,%1" : "=r"(t) : "m"(v->counter));
|
||||
__asm__ __volatile__("ld%U1%X1 %0,%1" : "=r"(t) : "m"UPD_CONSTR(v->counter));
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
static __inline__ void atomic64_set(atomic64_t *v, s64 i)
|
||||
{
|
||||
__asm__ __volatile__("std%U0%X0 %1,%0" : "=m"(v->counter) : "r"(i));
|
||||
__asm__ __volatile__("std%U0%X0 %1,%0" : "=m"UPD_CONSTR(v->counter) : "r"(i));
|
||||
}
|
||||
|
||||
#define ATOMIC64_OP(op, asm_op) \
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
#define wmb() __asm__ __volatile__ ("sync" : : : "memory")
|
||||
|
||||
/* The sub-arch has lwsync */
|
||||
#if defined(__powerpc64__) || defined(CONFIG_PPC_E500MC)
|
||||
#if defined(CONFIG_PPC64) || defined(CONFIG_PPC_E500MC)
|
||||
# define SMPWMB LWSYNC
|
||||
#else
|
||||
# define SMPWMB eieio
|
||||
|
||||
@@ -216,15 +216,34 @@ static inline void arch___clear_bit_unlock(int nr, volatile unsigned long *addr)
|
||||
*/
|
||||
static inline int fls(unsigned int x)
|
||||
{
|
||||
return 32 - __builtin_clz(x);
|
||||
int lz;
|
||||
|
||||
if (__builtin_constant_p(x))
|
||||
return x ? 32 - __builtin_clz(x) : 0;
|
||||
asm("cntlzw %0,%1" : "=r" (lz) : "r" (x));
|
||||
return 32 - lz;
|
||||
}
|
||||
|
||||
#include <asm-generic/bitops/builtin-__fls.h>
|
||||
|
||||
/*
|
||||
* 64-bit can do this using one cntlzd (count leading zeroes doubleword)
|
||||
* instruction; for 32-bit we use the generic version, which does two
|
||||
* 32-bit fls calls.
|
||||
*/
|
||||
#ifdef CONFIG_PPC64
|
||||
static inline int fls64(__u64 x)
|
||||
{
|
||||
return 64 - __builtin_clzll(x);
|
||||
int lz;
|
||||
|
||||
if (__builtin_constant_p(x))
|
||||
return x ? 64 - __builtin_clzll(x) : 0;
|
||||
asm("cntlzd %0,%1" : "=r" (lz) : "r" (x));
|
||||
return 64 - lz;
|
||||
}
|
||||
#else
|
||||
#include <asm-generic/bitops/fls64.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
unsigned int __arch_hweight8(unsigned int w);
|
||||
|
||||
@@ -183,11 +183,7 @@ bad_kuap_fault(struct pt_regs *regs, unsigned long address, bool is_write)
|
||||
unsigned long begin = regs->kuap & 0xf0000000;
|
||||
unsigned long end = regs->kuap << 28;
|
||||
|
||||
if (!is_write)
|
||||
return false;
|
||||
|
||||
return WARN(address < begin || address >= end,
|
||||
"Bug: write fault blocked by segment registers !");
|
||||
return is_write && (address < begin || address >= end);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PPC_KUAP */
|
||||
|
||||
@@ -90,10 +90,11 @@ struct hash_pte {
|
||||
|
||||
typedef struct {
|
||||
unsigned long id;
|
||||
unsigned long vdso_base;
|
||||
void __user *vdso;
|
||||
} mm_context_t;
|
||||
|
||||
void update_bats(void);
|
||||
static inline void cleanup_cpu_mmu_context(void) { };
|
||||
|
||||
/* patch sites */
|
||||
extern s32 patch__hash_page_A0, patch__hash_page_A1, patch__hash_page_A2;
|
||||
|
||||
@@ -240,8 +240,14 @@ extern void add_hash_page(unsigned context, unsigned long va,
|
||||
unsigned long pmdval);
|
||||
|
||||
/* Flush an entry from the TLB/hash table */
|
||||
extern void flush_hash_entry(struct mm_struct *mm, pte_t *ptep,
|
||||
unsigned long address);
|
||||
static inline void flush_hash_entry(struct mm_struct *mm, pte_t *ptep, unsigned long addr)
|
||||
{
|
||||
if (mmu_has_feature(MMU_FTR_HPTE_TABLE)) {
|
||||
unsigned long ptephys = __pa(ptep) & PAGE_MASK;
|
||||
|
||||
flush_hash_pages(mm->context.id, addr, ptephys, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* PTE updates. This function is called whenever an existing
|
||||
@@ -293,10 +299,9 @@ static inline int __ptep_test_and_clear_young(struct mm_struct *mm,
|
||||
{
|
||||
unsigned long old;
|
||||
old = pte_update(mm, addr, ptep, _PAGE_ACCESSED, 0, 0);
|
||||
if (old & _PAGE_HASHPTE) {
|
||||
unsigned long ptephys = __pa(ptep) & PAGE_MASK;
|
||||
flush_hash_pages(mm->context.id, addr, ptephys, 1);
|
||||
}
|
||||
if (old & _PAGE_HASHPTE)
|
||||
flush_hash_entry(mm, ptep, addr);
|
||||
|
||||
return (old & _PAGE_ACCESSED) != 0;
|
||||
}
|
||||
#define ptep_test_and_clear_young(__vma, __addr, __ptep) \
|
||||
@@ -524,9 +529,9 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
|
||||
if (pte_val(*ptep) & _PAGE_HASHPTE)
|
||||
flush_hash_entry(mm, ptep, addr);
|
||||
__asm__ __volatile__("\
|
||||
stw%U0%X0 %2,%0\n\
|
||||
stw%X0 %2,%0\n\
|
||||
eieio\n\
|
||||
stw%U0%X0 %L2,%1"
|
||||
stw%X1 %L2,%1"
|
||||
: "=m" (*ptep), "=m" (*((unsigned char *)ptep+4))
|
||||
: "r" (pte) : "memory");
|
||||
|
||||
|
||||
@@ -6,12 +6,69 @@
|
||||
/*
|
||||
* TLB flushing for "classic" hash-MMU 32-bit CPUs, 6xx, 7xx, 7xxx
|
||||
*/
|
||||
extern void flush_tlb_mm(struct mm_struct *mm);
|
||||
extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
|
||||
extern void flush_tlb_page_nohash(struct vm_area_struct *vma, unsigned long addr);
|
||||
extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
|
||||
unsigned long end);
|
||||
extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
|
||||
void hash__flush_tlb_mm(struct mm_struct *mm);
|
||||
void hash__flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
|
||||
void hash__flush_range(struct mm_struct *mm, unsigned long start, unsigned long end);
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
void _tlbie(unsigned long address);
|
||||
#else
|
||||
static inline void _tlbie(unsigned long address)
|
||||
{
|
||||
asm volatile ("tlbie %0; sync" : : "r" (address) : "memory");
|
||||
}
|
||||
#endif
|
||||
void _tlbia(void);
|
||||
|
||||
/*
|
||||
* Called at the end of a mmu_gather operation to make sure the
|
||||
* TLB flush is completely done.
|
||||
*/
|
||||
static inline void tlb_flush(struct mmu_gather *tlb)
|
||||
{
|
||||
/* 603 needs to flush the whole TLB here since it doesn't use a hash table. */
|
||||
if (!mmu_has_feature(MMU_FTR_HPTE_TABLE))
|
||||
_tlbia();
|
||||
}
|
||||
|
||||
static inline void flush_range(struct mm_struct *mm, unsigned long start, unsigned long end)
|
||||
{
|
||||
start &= PAGE_MASK;
|
||||
if (mmu_has_feature(MMU_FTR_HPTE_TABLE))
|
||||
hash__flush_range(mm, start, end);
|
||||
else if (end - start <= PAGE_SIZE)
|
||||
_tlbie(start);
|
||||
else
|
||||
_tlbia();
|
||||
}
|
||||
|
||||
static inline void flush_tlb_mm(struct mm_struct *mm)
|
||||
{
|
||||
if (mmu_has_feature(MMU_FTR_HPTE_TABLE))
|
||||
hash__flush_tlb_mm(mm);
|
||||
else
|
||||
_tlbia();
|
||||
}
|
||||
|
||||
static inline void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
|
||||
{
|
||||
if (mmu_has_feature(MMU_FTR_HPTE_TABLE))
|
||||
hash__flush_tlb_page(vma, vmaddr);
|
||||
else
|
||||
_tlbie(vmaddr);
|
||||
}
|
||||
|
||||
static inline void
|
||||
flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end)
|
||||
{
|
||||
flush_range(vma->vm_mm, start, end);
|
||||
}
|
||||
|
||||
static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end)
|
||||
{
|
||||
flush_range(&init_mm, start, end);
|
||||
}
|
||||
|
||||
static inline void local_flush_tlb_page(struct vm_area_struct *vma,
|
||||
unsigned long vmaddr)
|
||||
{
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
#ifndef _ASM_POWERPC_BOOK3S_64_HASH_PKEY_H
|
||||
#define _ASM_POWERPC_BOOK3S_64_HASH_PKEY_H
|
||||
|
||||
/* We use key 3 for KERNEL */
|
||||
#define HASH_DEFAULT_KERNEL_KEY (HPTE_R_KEY_BIT0 | HPTE_R_KEY_BIT1)
|
||||
|
||||
static inline u64 hash__vmflag_to_pte_pkey_bits(u64 vm_flags)
|
||||
{
|
||||
return (((vm_flags & VM_PKEY_BIT0) ? H_PTE_PKEY_BIT0 : 0x0UL) |
|
||||
@@ -11,13 +14,23 @@ static inline u64 hash__vmflag_to_pte_pkey_bits(u64 vm_flags)
|
||||
((vm_flags & VM_PKEY_BIT4) ? H_PTE_PKEY_BIT4 : 0x0UL));
|
||||
}
|
||||
|
||||
static inline u64 pte_to_hpte_pkey_bits(u64 pteflags)
|
||||
static inline u64 pte_to_hpte_pkey_bits(u64 pteflags, unsigned long flags)
|
||||
{
|
||||
return (((pteflags & H_PTE_PKEY_BIT4) ? HPTE_R_KEY_BIT4 : 0x0UL) |
|
||||
((pteflags & H_PTE_PKEY_BIT3) ? HPTE_R_KEY_BIT3 : 0x0UL) |
|
||||
((pteflags & H_PTE_PKEY_BIT2) ? HPTE_R_KEY_BIT2 : 0x0UL) |
|
||||
((pteflags & H_PTE_PKEY_BIT1) ? HPTE_R_KEY_BIT1 : 0x0UL) |
|
||||
((pteflags & H_PTE_PKEY_BIT0) ? HPTE_R_KEY_BIT0 : 0x0UL));
|
||||
unsigned long pte_pkey;
|
||||
|
||||
pte_pkey = (((pteflags & H_PTE_PKEY_BIT4) ? HPTE_R_KEY_BIT4 : 0x0UL) |
|
||||
((pteflags & H_PTE_PKEY_BIT3) ? HPTE_R_KEY_BIT3 : 0x0UL) |
|
||||
((pteflags & H_PTE_PKEY_BIT2) ? HPTE_R_KEY_BIT2 : 0x0UL) |
|
||||
((pteflags & H_PTE_PKEY_BIT1) ? HPTE_R_KEY_BIT1 : 0x0UL) |
|
||||
((pteflags & H_PTE_PKEY_BIT0) ? HPTE_R_KEY_BIT0 : 0x0UL));
|
||||
|
||||
if (mmu_has_feature(MMU_FTR_BOOK3S_KUAP) ||
|
||||
mmu_has_feature(MMU_FTR_BOOK3S_KUEP)) {
|
||||
if ((pte_pkey == 0) && (flags & HPTE_USE_KERNEL_KEY))
|
||||
return HASH_DEFAULT_KERNEL_KEY;
|
||||
}
|
||||
|
||||
return pte_pkey;
|
||||
}
|
||||
|
||||
static inline u16 hash__pte_to_pkey_bits(u64 pteflags)
|
||||
|
||||
@@ -145,7 +145,7 @@ extern void hash__mark_initmem_nx(void);
|
||||
|
||||
extern void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
|
||||
pte_t *ptep, unsigned long pte, int huge);
|
||||
extern unsigned long htab_convert_pte_flags(unsigned long pteflags);
|
||||
unsigned long htab_convert_pte_flags(unsigned long pteflags, unsigned long flags);
|
||||
/* Atomic PTE updates */
|
||||
static inline unsigned long hash__pte_update(struct mm_struct *mm,
|
||||
unsigned long addr,
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#ifndef _ASM_POWERPC_BOOK3S_64_KEXEC_H_
|
||||
#define _ASM_POWERPC_BOOK3S_64_KEXEC_H_
|
||||
|
||||
#include <asm/plpar_wrappers.h>
|
||||
|
||||
#define reset_sprs reset_sprs
|
||||
static inline void reset_sprs(void)
|
||||
@@ -14,6 +15,10 @@ static inline void reset_sprs(void)
|
||||
|
||||
if (cpu_has_feature(CPU_FTR_ARCH_207S)) {
|
||||
mtspr(SPRN_IAMR, 0);
|
||||
if (cpu_has_feature(CPU_FTR_HVMODE))
|
||||
mtspr(SPRN_CIABR, 0);
|
||||
else
|
||||
plpar_set_ciabr(0);
|
||||
}
|
||||
|
||||
/* Do we need isync()? We are going via a kexec reset */
|
||||
|
||||
@@ -1,205 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _ASM_POWERPC_BOOK3S_64_KUP_RADIX_H
|
||||
#define _ASM_POWERPC_BOOK3S_64_KUP_RADIX_H
|
||||
|
||||
#include <linux/const.h>
|
||||
#include <asm/reg.h>
|
||||
|
||||
#define AMR_KUAP_BLOCK_READ UL(0x4000000000000000)
|
||||
#define AMR_KUAP_BLOCK_WRITE UL(0x8000000000000000)
|
||||
#define AMR_KUAP_BLOCKED (AMR_KUAP_BLOCK_READ | AMR_KUAP_BLOCK_WRITE)
|
||||
#define AMR_KUAP_SHIFT 62
|
||||
|
||||
#ifdef __ASSEMBLY__
|
||||
|
||||
.macro kuap_restore_amr gpr1, gpr2
|
||||
#ifdef CONFIG_PPC_KUAP
|
||||
BEGIN_MMU_FTR_SECTION_NESTED(67)
|
||||
mfspr \gpr1, SPRN_AMR
|
||||
ld \gpr2, STACK_REGS_KUAP(r1)
|
||||
cmpd \gpr1, \gpr2
|
||||
beq 998f
|
||||
isync
|
||||
mtspr SPRN_AMR, \gpr2
|
||||
/* No isync required, see kuap_restore_amr() */
|
||||
998:
|
||||
END_MMU_FTR_SECTION_NESTED_IFSET(MMU_FTR_RADIX_KUAP, 67)
|
||||
#endif
|
||||
.endm
|
||||
|
||||
#ifdef CONFIG_PPC_KUAP
|
||||
.macro kuap_check_amr gpr1, gpr2
|
||||
#ifdef CONFIG_PPC_KUAP_DEBUG
|
||||
BEGIN_MMU_FTR_SECTION_NESTED(67)
|
||||
mfspr \gpr1, SPRN_AMR
|
||||
li \gpr2, (AMR_KUAP_BLOCKED >> AMR_KUAP_SHIFT)
|
||||
sldi \gpr2, \gpr2, AMR_KUAP_SHIFT
|
||||
999: tdne \gpr1, \gpr2
|
||||
EMIT_BUG_ENTRY 999b, __FILE__, __LINE__, (BUGFLAG_WARNING | BUGFLAG_ONCE)
|
||||
END_MMU_FTR_SECTION_NESTED_IFSET(MMU_FTR_RADIX_KUAP, 67)
|
||||
#endif
|
||||
.endm
|
||||
#endif
|
||||
|
||||
.macro kuap_save_amr_and_lock gpr1, gpr2, use_cr, msr_pr_cr
|
||||
#ifdef CONFIG_PPC_KUAP
|
||||
BEGIN_MMU_FTR_SECTION_NESTED(67)
|
||||
.ifnb \msr_pr_cr
|
||||
bne \msr_pr_cr, 99f
|
||||
.endif
|
||||
mfspr \gpr1, SPRN_AMR
|
||||
std \gpr1, STACK_REGS_KUAP(r1)
|
||||
li \gpr2, (AMR_KUAP_BLOCKED >> AMR_KUAP_SHIFT)
|
||||
sldi \gpr2, \gpr2, AMR_KUAP_SHIFT
|
||||
cmpd \use_cr, \gpr1, \gpr2
|
||||
beq \use_cr, 99f
|
||||
// We don't isync here because we very recently entered via rfid
|
||||
mtspr SPRN_AMR, \gpr2
|
||||
isync
|
||||
99:
|
||||
END_MMU_FTR_SECTION_NESTED_IFSET(MMU_FTR_RADIX_KUAP, 67)
|
||||
#endif
|
||||
.endm
|
||||
|
||||
#else /* !__ASSEMBLY__ */
|
||||
|
||||
#include <linux/jump_label.h>
|
||||
|
||||
DECLARE_STATIC_KEY_FALSE(uaccess_flush_key);
|
||||
|
||||
#ifdef CONFIG_PPC_KUAP
|
||||
|
||||
#include <asm/mmu.h>
|
||||
#include <asm/ptrace.h>
|
||||
|
||||
static inline void kuap_restore_amr(struct pt_regs *regs, unsigned long amr)
|
||||
{
|
||||
if (mmu_has_feature(MMU_FTR_RADIX_KUAP) && unlikely(regs->kuap != amr)) {
|
||||
isync();
|
||||
mtspr(SPRN_AMR, regs->kuap);
|
||||
/*
|
||||
* No isync required here because we are about to RFI back to
|
||||
* previous context before any user accesses would be made,
|
||||
* which is a CSI.
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
static inline unsigned long kuap_get_and_check_amr(void)
|
||||
{
|
||||
if (mmu_has_feature(MMU_FTR_RADIX_KUAP)) {
|
||||
unsigned long amr = mfspr(SPRN_AMR);
|
||||
if (IS_ENABLED(CONFIG_PPC_KUAP_DEBUG)) /* kuap_check_amr() */
|
||||
WARN_ON_ONCE(amr != AMR_KUAP_BLOCKED);
|
||||
return amr;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void kuap_check_amr(void)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_PPC_KUAP_DEBUG) && mmu_has_feature(MMU_FTR_RADIX_KUAP))
|
||||
WARN_ON_ONCE(mfspr(SPRN_AMR) != AMR_KUAP_BLOCKED);
|
||||
}
|
||||
|
||||
/*
|
||||
* We support individually allowing read or write, but we don't support nesting
|
||||
* because that would require an expensive read/modify write of the AMR.
|
||||
*/
|
||||
|
||||
static inline unsigned long get_kuap(void)
|
||||
{
|
||||
/*
|
||||
* We return AMR_KUAP_BLOCKED when we don't support KUAP because
|
||||
* prevent_user_access_return needs to return AMR_KUAP_BLOCKED to
|
||||
* cause restore_user_access to do a flush.
|
||||
*
|
||||
* This has no effect in terms of actually blocking things on hash,
|
||||
* so it doesn't break anything.
|
||||
*/
|
||||
if (!early_mmu_has_feature(MMU_FTR_RADIX_KUAP))
|
||||
return AMR_KUAP_BLOCKED;
|
||||
|
||||
return mfspr(SPRN_AMR);
|
||||
}
|
||||
|
||||
static inline void set_kuap(unsigned long value)
|
||||
{
|
||||
if (!early_mmu_has_feature(MMU_FTR_RADIX_KUAP))
|
||||
return;
|
||||
|
||||
/*
|
||||
* ISA v3.0B says we need a CSI (Context Synchronising Instruction) both
|
||||
* before and after the move to AMR. See table 6 on page 1134.
|
||||
*/
|
||||
isync();
|
||||
mtspr(SPRN_AMR, value);
|
||||
isync();
|
||||
}
|
||||
|
||||
static inline bool
|
||||
bad_kuap_fault(struct pt_regs *regs, unsigned long address, bool is_write)
|
||||
{
|
||||
return WARN(mmu_has_feature(MMU_FTR_RADIX_KUAP) &&
|
||||
(regs->kuap & (is_write ? AMR_KUAP_BLOCK_WRITE : AMR_KUAP_BLOCK_READ)),
|
||||
"Bug: %s fault blocked by AMR!", is_write ? "Write" : "Read");
|
||||
}
|
||||
#else /* CONFIG_PPC_KUAP */
|
||||
static inline void kuap_restore_amr(struct pt_regs *regs, unsigned long amr) { }
|
||||
|
||||
static inline unsigned long kuap_get_and_check_amr(void)
|
||||
{
|
||||
return 0UL;
|
||||
}
|
||||
|
||||
static inline unsigned long get_kuap(void)
|
||||
{
|
||||
return AMR_KUAP_BLOCKED;
|
||||
}
|
||||
|
||||
static inline void set_kuap(unsigned long value) { }
|
||||
#endif /* !CONFIG_PPC_KUAP */
|
||||
|
||||
static __always_inline void allow_user_access(void __user *to, const void __user *from,
|
||||
unsigned long size, unsigned long dir)
|
||||
{
|
||||
// This is written so we can resolve to a single case at build time
|
||||
BUILD_BUG_ON(!__builtin_constant_p(dir));
|
||||
if (dir == KUAP_READ)
|
||||
set_kuap(AMR_KUAP_BLOCK_WRITE);
|
||||
else if (dir == KUAP_WRITE)
|
||||
set_kuap(AMR_KUAP_BLOCK_READ);
|
||||
else if (dir == KUAP_READ_WRITE)
|
||||
set_kuap(0);
|
||||
else
|
||||
BUILD_BUG();
|
||||
}
|
||||
|
||||
static inline void prevent_user_access(void __user *to, const void __user *from,
|
||||
unsigned long size, unsigned long dir)
|
||||
{
|
||||
set_kuap(AMR_KUAP_BLOCKED);
|
||||
if (static_branch_unlikely(&uaccess_flush_key))
|
||||
do_uaccess_flush();
|
||||
}
|
||||
|
||||
static inline unsigned long prevent_user_access_return(void)
|
||||
{
|
||||
unsigned long flags = get_kuap();
|
||||
|
||||
set_kuap(AMR_KUAP_BLOCKED);
|
||||
if (static_branch_unlikely(&uaccess_flush_key))
|
||||
do_uaccess_flush();
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
static inline void restore_user_access(unsigned long flags)
|
||||
{
|
||||
set_kuap(flags);
|
||||
if (static_branch_unlikely(&uaccess_flush_key) && flags == AMR_KUAP_BLOCKED)
|
||||
do_uaccess_flush();
|
||||
}
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* _ASM_POWERPC_BOOK3S_64_KUP_RADIX_H */
|
||||
442
arch/powerpc/include/asm/book3s/64/kup.h
Normal file
442
arch/powerpc/include/asm/book3s/64/kup.h
Normal file
@@ -0,0 +1,442 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _ASM_POWERPC_BOOK3S_64_KUP_H
|
||||
#define _ASM_POWERPC_BOOK3S_64_KUP_H
|
||||
|
||||
#include <linux/const.h>
|
||||
#include <asm/reg.h>
|
||||
|
||||
#define AMR_KUAP_BLOCK_READ UL(0x5455555555555555)
|
||||
#define AMR_KUAP_BLOCK_WRITE UL(0xa8aaaaaaaaaaaaaa)
|
||||
#define AMR_KUEP_BLOCKED UL(0x5455555555555555)
|
||||
#define AMR_KUAP_BLOCKED (AMR_KUAP_BLOCK_READ | AMR_KUAP_BLOCK_WRITE)
|
||||
|
||||
#ifdef __ASSEMBLY__
|
||||
|
||||
.macro kuap_user_restore gpr1, gpr2
|
||||
#if defined(CONFIG_PPC_PKEY)
|
||||
BEGIN_MMU_FTR_SECTION_NESTED(67)
|
||||
b 100f // skip_restore_amr
|
||||
END_MMU_FTR_SECTION_NESTED_IFCLR(MMU_FTR_PKEY, 67)
|
||||
/*
|
||||
* AMR and IAMR are going to be different when
|
||||
* returning to userspace.
|
||||
*/
|
||||
ld \gpr1, STACK_REGS_AMR(r1)
|
||||
|
||||
/*
|
||||
* If kuap feature is not enabled, do the mtspr
|
||||
* only if AMR value is different.
|
||||
*/
|
||||
BEGIN_MMU_FTR_SECTION_NESTED(68)
|
||||
mfspr \gpr2, SPRN_AMR
|
||||
cmpd \gpr1, \gpr2
|
||||
beq 99f
|
||||
END_MMU_FTR_SECTION_NESTED_IFCLR(MMU_FTR_BOOK3S_KUAP, 68)
|
||||
|
||||
isync
|
||||
mtspr SPRN_AMR, \gpr1
|
||||
99:
|
||||
/*
|
||||
* Restore IAMR only when returning to userspace
|
||||
*/
|
||||
ld \gpr1, STACK_REGS_IAMR(r1)
|
||||
|
||||
/*
|
||||
* If kuep feature is not enabled, do the mtspr
|
||||
* only if IAMR value is different.
|
||||
*/
|
||||
BEGIN_MMU_FTR_SECTION_NESTED(69)
|
||||
mfspr \gpr2, SPRN_IAMR
|
||||
cmpd \gpr1, \gpr2
|
||||
beq 100f
|
||||
END_MMU_FTR_SECTION_NESTED_IFCLR(MMU_FTR_BOOK3S_KUEP, 69)
|
||||
|
||||
isync
|
||||
mtspr SPRN_IAMR, \gpr1
|
||||
|
||||
100: //skip_restore_amr
|
||||
/* No isync required, see kuap_user_restore() */
|
||||
#endif
|
||||
.endm
|
||||
|
||||
.macro kuap_kernel_restore gpr1, gpr2
|
||||
#if defined(CONFIG_PPC_PKEY)
|
||||
|
||||
BEGIN_MMU_FTR_SECTION_NESTED(67)
|
||||
/*
|
||||
* AMR is going to be mostly the same since we are
|
||||
* returning to the kernel. Compare and do a mtspr.
|
||||
*/
|
||||
ld \gpr2, STACK_REGS_AMR(r1)
|
||||
mfspr \gpr1, SPRN_AMR
|
||||
cmpd \gpr1, \gpr2
|
||||
beq 100f
|
||||
isync
|
||||
mtspr SPRN_AMR, \gpr2
|
||||
/*
|
||||
* No isync required, see kuap_restore_amr()
|
||||
* No need to restore IAMR when returning to kernel space.
|
||||
*/
|
||||
100:
|
||||
END_MMU_FTR_SECTION_NESTED_IFSET(MMU_FTR_BOOK3S_KUAP, 67)
|
||||
#endif
|
||||
.endm
|
||||
|
||||
#ifdef CONFIG_PPC_KUAP
|
||||
.macro kuap_check_amr gpr1, gpr2
|
||||
#ifdef CONFIG_PPC_KUAP_DEBUG
|
||||
BEGIN_MMU_FTR_SECTION_NESTED(67)
|
||||
mfspr \gpr1, SPRN_AMR
|
||||
/* Prevent access to userspace using any key values */
|
||||
LOAD_REG_IMMEDIATE(\gpr2, AMR_KUAP_BLOCKED)
|
||||
999: tdne \gpr1, \gpr2
|
||||
EMIT_BUG_ENTRY 999b, __FILE__, __LINE__, (BUGFLAG_WARNING | BUGFLAG_ONCE)
|
||||
END_MMU_FTR_SECTION_NESTED_IFSET(MMU_FTR_BOOK3S_KUAP, 67)
|
||||
#endif
|
||||
.endm
|
||||
#endif
|
||||
|
||||
/*
|
||||
* if (pkey) {
|
||||
*
|
||||
* save AMR -> stack;
|
||||
* if (kuap) {
|
||||
* if (AMR != BLOCKED)
|
||||
* KUAP_BLOCKED -> AMR;
|
||||
* }
|
||||
* if (from_user) {
|
||||
* save IAMR -> stack;
|
||||
* if (kuep) {
|
||||
* KUEP_BLOCKED ->IAMR
|
||||
* }
|
||||
* }
|
||||
* return;
|
||||
* }
|
||||
*
|
||||
* if (kuap) {
|
||||
* if (from_kernel) {
|
||||
* save AMR -> stack;
|
||||
* if (AMR != BLOCKED)
|
||||
* KUAP_BLOCKED -> AMR;
|
||||
* }
|
||||
*
|
||||
* }
|
||||
*/
|
||||
.macro kuap_save_amr_and_lock gpr1, gpr2, use_cr, msr_pr_cr
|
||||
#if defined(CONFIG_PPC_PKEY)
|
||||
|
||||
/*
|
||||
* if both pkey and kuap is disabled, nothing to do
|
||||
*/
|
||||
BEGIN_MMU_FTR_SECTION_NESTED(68)
|
||||
b 100f // skip_save_amr
|
||||
END_MMU_FTR_SECTION_NESTED_IFCLR(MMU_FTR_PKEY | MMU_FTR_BOOK3S_KUAP, 68)
|
||||
|
||||
/*
|
||||
* if pkey is disabled and we are entering from userspace
|
||||
* don't do anything.
|
||||
*/
|
||||
BEGIN_MMU_FTR_SECTION_NESTED(67)
|
||||
.ifnb \msr_pr_cr
|
||||
/*
|
||||
* Without pkey we are not changing AMR outside the kernel
|
||||
* hence skip this completely.
|
||||
*/
|
||||
bne \msr_pr_cr, 100f // from userspace
|
||||
.endif
|
||||
END_MMU_FTR_SECTION_NESTED_IFCLR(MMU_FTR_PKEY, 67)
|
||||
|
||||
/*
|
||||
* pkey is enabled or pkey is disabled but entering from kernel
|
||||
*/
|
||||
mfspr \gpr1, SPRN_AMR
|
||||
std \gpr1, STACK_REGS_AMR(r1)
|
||||
|
||||
/*
|
||||
* update kernel AMR with AMR_KUAP_BLOCKED only
|
||||
* if KUAP feature is enabled
|
||||
*/
|
||||
BEGIN_MMU_FTR_SECTION_NESTED(69)
|
||||
LOAD_REG_IMMEDIATE(\gpr2, AMR_KUAP_BLOCKED)
|
||||
cmpd \use_cr, \gpr1, \gpr2
|
||||
beq \use_cr, 102f
|
||||
/*
|
||||
* We don't isync here because we very recently entered via an interrupt
|
||||
*/
|
||||
mtspr SPRN_AMR, \gpr2
|
||||
isync
|
||||
102:
|
||||
END_MMU_FTR_SECTION_NESTED_IFSET(MMU_FTR_BOOK3S_KUAP, 69)
|
||||
|
||||
/*
|
||||
* if entering from kernel we don't need save IAMR
|
||||
*/
|
||||
.ifnb \msr_pr_cr
|
||||
beq \msr_pr_cr, 100f // from kernel space
|
||||
mfspr \gpr1, SPRN_IAMR
|
||||
std \gpr1, STACK_REGS_IAMR(r1)
|
||||
|
||||
/*
|
||||
* update kernel IAMR with AMR_KUEP_BLOCKED only
|
||||
* if KUEP feature is enabled
|
||||
*/
|
||||
BEGIN_MMU_FTR_SECTION_NESTED(70)
|
||||
LOAD_REG_IMMEDIATE(\gpr2, AMR_KUEP_BLOCKED)
|
||||
mtspr SPRN_IAMR, \gpr2
|
||||
isync
|
||||
END_MMU_FTR_SECTION_NESTED_IFSET(MMU_FTR_BOOK3S_KUEP, 70)
|
||||
.endif
|
||||
|
||||
100: // skip_save_amr
|
||||
#endif
|
||||
.endm
|
||||
|
||||
#else /* !__ASSEMBLY__ */
|
||||
|
||||
#include <linux/jump_label.h>
|
||||
|
||||
DECLARE_STATIC_KEY_FALSE(uaccess_flush_key);
|
||||
|
||||
#ifdef CONFIG_PPC_PKEY
|
||||
|
||||
#include <asm/mmu.h>
|
||||
#include <asm/ptrace.h>
|
||||
|
||||
/*
|
||||
* For kernel thread that doesn't have thread.regs return
|
||||
* default AMR/IAMR values.
|
||||
*/
|
||||
static inline u64 current_thread_amr(void)
|
||||
{
|
||||
if (current->thread.regs)
|
||||
return current->thread.regs->amr;
|
||||
return AMR_KUAP_BLOCKED;
|
||||
}
|
||||
|
||||
static inline u64 current_thread_iamr(void)
|
||||
{
|
||||
if (current->thread.regs)
|
||||
return current->thread.regs->iamr;
|
||||
return AMR_KUEP_BLOCKED;
|
||||
}
|
||||
#endif /* CONFIG_PPC_PKEY */
|
||||
|
||||
#ifdef CONFIG_PPC_KUAP
|
||||
|
||||
static inline void kuap_user_restore(struct pt_regs *regs)
|
||||
{
|
||||
bool restore_amr = false, restore_iamr = false;
|
||||
unsigned long amr, iamr;
|
||||
|
||||
if (!mmu_has_feature(MMU_FTR_PKEY))
|
||||
return;
|
||||
|
||||
if (!mmu_has_feature(MMU_FTR_BOOK3S_KUAP)) {
|
||||
amr = mfspr(SPRN_AMR);
|
||||
if (amr != regs->amr)
|
||||
restore_amr = true;
|
||||
} else {
|
||||
restore_amr = true;
|
||||
}
|
||||
|
||||
if (!mmu_has_feature(MMU_FTR_BOOK3S_KUEP)) {
|
||||
iamr = mfspr(SPRN_IAMR);
|
||||
if (iamr != regs->iamr)
|
||||
restore_iamr = true;
|
||||
} else {
|
||||
restore_iamr = true;
|
||||
}
|
||||
|
||||
|
||||
if (restore_amr || restore_iamr) {
|
||||
isync();
|
||||
if (restore_amr)
|
||||
mtspr(SPRN_AMR, regs->amr);
|
||||
if (restore_iamr)
|
||||
mtspr(SPRN_IAMR, regs->iamr);
|
||||
}
|
||||
/*
|
||||
* No isync required here because we are about to rfi
|
||||
* back to previous context before any user accesses
|
||||
* would be made, which is a CSI.
|
||||
*/
|
||||
}
|
||||
|
||||
static inline void kuap_kernel_restore(struct pt_regs *regs,
|
||||
unsigned long amr)
|
||||
{
|
||||
if (mmu_has_feature(MMU_FTR_BOOK3S_KUAP)) {
|
||||
if (unlikely(regs->amr != amr)) {
|
||||
isync();
|
||||
mtspr(SPRN_AMR, regs->amr);
|
||||
/*
|
||||
* No isync required here because we are about to rfi
|
||||
* back to previous context before any user accesses
|
||||
* would be made, which is a CSI.
|
||||
*/
|
||||
}
|
||||
}
|
||||
/*
|
||||
* No need to restore IAMR when returning to kernel space.
|
||||
*/
|
||||
}
|
||||
|
||||
static inline unsigned long kuap_get_and_check_amr(void)
|
||||
{
|
||||
if (mmu_has_feature(MMU_FTR_BOOK3S_KUAP)) {
|
||||
unsigned long amr = mfspr(SPRN_AMR);
|
||||
if (IS_ENABLED(CONFIG_PPC_KUAP_DEBUG)) /* kuap_check_amr() */
|
||||
WARN_ON_ONCE(amr != AMR_KUAP_BLOCKED);
|
||||
return amr;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* CONFIG_PPC_PKEY */
|
||||
|
||||
static inline void kuap_user_restore(struct pt_regs *regs)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void kuap_kernel_restore(struct pt_regs *regs, unsigned long amr)
|
||||
{
|
||||
}
|
||||
|
||||
static inline unsigned long kuap_get_and_check_amr(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PPC_PKEY */
|
||||
|
||||
|
||||
#ifdef CONFIG_PPC_KUAP
|
||||
|
||||
static inline void kuap_check_amr(void)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_PPC_KUAP_DEBUG) && mmu_has_feature(MMU_FTR_BOOK3S_KUAP))
|
||||
WARN_ON_ONCE(mfspr(SPRN_AMR) != AMR_KUAP_BLOCKED);
|
||||
}
|
||||
|
||||
/*
|
||||
* We support individually allowing read or write, but we don't support nesting
|
||||
* because that would require an expensive read/modify write of the AMR.
|
||||
*/
|
||||
|
||||
static inline unsigned long get_kuap(void)
|
||||
{
|
||||
/*
|
||||
* We return AMR_KUAP_BLOCKED when we don't support KUAP because
|
||||
* prevent_user_access_return needs to return AMR_KUAP_BLOCKED to
|
||||
* cause restore_user_access to do a flush.
|
||||
*
|
||||
* This has no effect in terms of actually blocking things on hash,
|
||||
* so it doesn't break anything.
|
||||
*/
|
||||
if (!early_mmu_has_feature(MMU_FTR_BOOK3S_KUAP))
|
||||
return AMR_KUAP_BLOCKED;
|
||||
|
||||
return mfspr(SPRN_AMR);
|
||||
}
|
||||
|
||||
static inline void set_kuap(unsigned long value)
|
||||
{
|
||||
if (!early_mmu_has_feature(MMU_FTR_BOOK3S_KUAP))
|
||||
return;
|
||||
|
||||
/*
|
||||
* ISA v3.0B says we need a CSI (Context Synchronising Instruction) both
|
||||
* before and after the move to AMR. See table 6 on page 1134.
|
||||
*/
|
||||
isync();
|
||||
mtspr(SPRN_AMR, value);
|
||||
isync();
|
||||
}
|
||||
|
||||
static inline bool bad_kuap_fault(struct pt_regs *regs, unsigned long address,
|
||||
bool is_write)
|
||||
{
|
||||
if (!mmu_has_feature(MMU_FTR_BOOK3S_KUAP))
|
||||
return false;
|
||||
/*
|
||||
* For radix this will be a storage protection fault (DSISR_PROTFAULT).
|
||||
* For hash this will be a key fault (DSISR_KEYFAULT)
|
||||
*/
|
||||
/*
|
||||
* We do have exception table entry, but accessing the
|
||||
* userspace results in fault. This could be because we
|
||||
* didn't unlock the AMR or access is denied by userspace
|
||||
* using a key value that blocks access. We are only interested
|
||||
* in catching the use case of accessing without unlocking
|
||||
* the AMR. Hence check for BLOCK_WRITE/READ against AMR.
|
||||
*/
|
||||
if (is_write) {
|
||||
return (regs->amr & AMR_KUAP_BLOCK_WRITE) == AMR_KUAP_BLOCK_WRITE;
|
||||
}
|
||||
return (regs->amr & AMR_KUAP_BLOCK_READ) == AMR_KUAP_BLOCK_READ;
|
||||
}
|
||||
|
||||
static __always_inline void allow_user_access(void __user *to, const void __user *from,
|
||||
unsigned long size, unsigned long dir)
|
||||
{
|
||||
unsigned long thread_amr = 0;
|
||||
|
||||
// This is written so we can resolve to a single case at build time
|
||||
BUILD_BUG_ON(!__builtin_constant_p(dir));
|
||||
|
||||
if (mmu_has_feature(MMU_FTR_PKEY))
|
||||
thread_amr = current_thread_amr();
|
||||
|
||||
if (dir == KUAP_READ)
|
||||
set_kuap(thread_amr | AMR_KUAP_BLOCK_WRITE);
|
||||
else if (dir == KUAP_WRITE)
|
||||
set_kuap(thread_amr | AMR_KUAP_BLOCK_READ);
|
||||
else if (dir == KUAP_READ_WRITE)
|
||||
set_kuap(thread_amr);
|
||||
else
|
||||
BUILD_BUG();
|
||||
}
|
||||
|
||||
#else /* CONFIG_PPC_KUAP */
|
||||
|
||||
static inline unsigned long get_kuap(void)
|
||||
{
|
||||
return AMR_KUAP_BLOCKED;
|
||||
}
|
||||
|
||||
static inline void set_kuap(unsigned long value) { }
|
||||
|
||||
static __always_inline void allow_user_access(void __user *to, const void __user *from,
|
||||
unsigned long size, unsigned long dir)
|
||||
{ }
|
||||
|
||||
#endif /* !CONFIG_PPC_KUAP */
|
||||
|
||||
static inline void prevent_user_access(void __user *to, const void __user *from,
|
||||
unsigned long size, unsigned long dir)
|
||||
{
|
||||
set_kuap(AMR_KUAP_BLOCKED);
|
||||
if (static_branch_unlikely(&uaccess_flush_key))
|
||||
do_uaccess_flush();
|
||||
}
|
||||
|
||||
static inline unsigned long prevent_user_access_return(void)
|
||||
{
|
||||
unsigned long flags = get_kuap();
|
||||
|
||||
set_kuap(AMR_KUAP_BLOCKED);
|
||||
if (static_branch_unlikely(&uaccess_flush_key))
|
||||
do_uaccess_flush();
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
static inline void restore_user_access(unsigned long flags)
|
||||
{
|
||||
set_kuap(flags);
|
||||
if (static_branch_unlikely(&uaccess_flush_key) && flags == AMR_KUAP_BLOCKED)
|
||||
do_uaccess_flush();
|
||||
}
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* _ASM_POWERPC_BOOK3S_64_KUP_H */
|
||||
@@ -452,6 +452,7 @@ static inline unsigned long hpt_hash(unsigned long vpn,
|
||||
|
||||
#define HPTE_LOCAL_UPDATE 0x1
|
||||
#define HPTE_NOHPTE_UPDATE 0x2
|
||||
#define HPTE_USE_KERNEL_KEY 0x4
|
||||
|
||||
extern int __hash_page_4K(unsigned long ea, unsigned long access,
|
||||
unsigned long vsid, pte_t *ptep, unsigned long trap,
|
||||
@@ -842,6 +843,32 @@ static inline unsigned long get_kernel_vsid(unsigned long ea, int ssize)
|
||||
|
||||
unsigned htab_shift_for_mem_size(unsigned long mem_size);
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
enum slb_index {
|
||||
LINEAR_INDEX = 0, /* Kernel linear map (0xc000000000000000) */
|
||||
KSTACK_INDEX = 1, /* Kernel stack map */
|
||||
};
|
||||
|
||||
#define slb_esid_mask(ssize) \
|
||||
(((ssize) == MMU_SEGSIZE_256M) ? ESID_MASK : ESID_MASK_1T)
|
||||
|
||||
static inline unsigned long mk_esid_data(unsigned long ea, int ssize,
|
||||
enum slb_index index)
|
||||
{
|
||||
return (ea & slb_esid_mask(ssize)) | SLB_ESID_V | index;
|
||||
}
|
||||
|
||||
static inline unsigned long __mk_vsid_data(unsigned long vsid, int ssize,
|
||||
unsigned long flags)
|
||||
{
|
||||
return (vsid << slb_vsid_shift(ssize)) | flags |
|
||||
((unsigned long)ssize << SLB_VSID_SSIZE_SHIFT);
|
||||
}
|
||||
|
||||
static inline unsigned long mk_vsid_data(unsigned long ea, int ssize,
|
||||
unsigned long flags)
|
||||
{
|
||||
return __mk_vsid_data(get_kernel_vsid(ea, ssize), ssize, flags);
|
||||
}
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* _ASM_POWERPC_BOOK3S_64_MMU_HASH_H_ */
|
||||
|
||||
@@ -111,7 +111,7 @@ typedef struct {
|
||||
|
||||
struct hash_mm_context *hash_context;
|
||||
|
||||
unsigned long vdso_base;
|
||||
void __user *vdso;
|
||||
/*
|
||||
* pagetable fragment support
|
||||
*/
|
||||
@@ -199,7 +199,7 @@ extern int mmu_io_psize;
|
||||
void mmu_early_init_devtree(void);
|
||||
void hash__early_init_devtree(void);
|
||||
void radix__early_init_devtree(void);
|
||||
#ifdef CONFIG_PPC_MEM_KEYS
|
||||
#ifdef CONFIG_PPC_PKEY
|
||||
void pkey_early_init_devtree(void);
|
||||
#else
|
||||
static inline void pkey_early_init_devtree(void) {}
|
||||
|
||||
@@ -1231,13 +1231,28 @@ static inline int pmd_same(pmd_t pmd_a, pmd_t pmd_b)
|
||||
return hash__pmd_same(pmd_a, pmd_b);
|
||||
}
|
||||
|
||||
static inline pmd_t pmd_mkhuge(pmd_t pmd)
|
||||
static inline pmd_t __pmd_mkhuge(pmd_t pmd)
|
||||
{
|
||||
if (radix_enabled())
|
||||
return radix__pmd_mkhuge(pmd);
|
||||
return hash__pmd_mkhuge(pmd);
|
||||
}
|
||||
|
||||
/*
|
||||
* pfn_pmd return a pmd_t that can be used as pmd pte entry.
|
||||
*/
|
||||
static inline pmd_t pmd_mkhuge(pmd_t pmd)
|
||||
{
|
||||
#ifdef CONFIG_DEBUG_VM
|
||||
if (radix_enabled())
|
||||
WARN_ON((pmd_raw(pmd) & cpu_to_be64(_PAGE_PTE)) == 0);
|
||||
else
|
||||
WARN_ON((pmd_raw(pmd) & cpu_to_be64(_PAGE_PTE | H_PAGE_THP_HUGE)) !=
|
||||
cpu_to_be64(_PAGE_PTE | H_PAGE_THP_HUGE));
|
||||
#endif
|
||||
return pmd;
|
||||
}
|
||||
|
||||
#define __HAVE_ARCH_PMDP_SET_ACCESS_FLAGS
|
||||
extern int pmdp_set_access_flags(struct vm_area_struct *vma,
|
||||
unsigned long address, pmd_t *pmdp,
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include <asm/book3s/64/hash-pkey.h>
|
||||
|
||||
extern u64 __ro_after_init default_uamor;
|
||||
extern u64 __ro_after_init default_amr;
|
||||
extern u64 __ro_after_init default_iamr;
|
||||
|
||||
static inline u64 vmflag_to_pte_pkey_bits(u64 vm_flags)
|
||||
{
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#ifdef CONFIG_DEBUG_BUGVERBOSE
|
||||
.macro EMIT_BUG_ENTRY addr,file,line,flags
|
||||
.section __bug_table,"aw"
|
||||
5001: PPC_LONG \addr, 5002f
|
||||
5001: .4byte \addr - 5001b, 5002f - 5001b
|
||||
.short \line, \flags
|
||||
.org 5001b+BUG_ENTRY_SIZE
|
||||
.previous
|
||||
@@ -23,7 +23,7 @@
|
||||
#else
|
||||
.macro EMIT_BUG_ENTRY addr,file,line,flags
|
||||
.section __bug_table,"aw"
|
||||
5001: PPC_LONG \addr
|
||||
5001: .4byte \addr - 5001b
|
||||
.short \flags
|
||||
.org 5001b+BUG_ENTRY_SIZE
|
||||
.previous
|
||||
@@ -36,14 +36,14 @@
|
||||
#ifdef CONFIG_DEBUG_BUGVERBOSE
|
||||
#define _EMIT_BUG_ENTRY \
|
||||
".section __bug_table,\"aw\"\n" \
|
||||
"2:\t" PPC_LONG "1b, %0\n" \
|
||||
"2:\t.4byte 1b - 2b, %0 - 2b\n" \
|
||||
"\t.short %1, %2\n" \
|
||||
".org 2b+%3\n" \
|
||||
".previous\n"
|
||||
#else
|
||||
#define _EMIT_BUG_ENTRY \
|
||||
".section __bug_table,\"aw\"\n" \
|
||||
"2:\t" PPC_LONG "1b\n" \
|
||||
"2:\t.4byte 1b - 2b\n" \
|
||||
"\t.short %2\n" \
|
||||
".org 2b+%3\n" \
|
||||
".previous\n"
|
||||
@@ -113,6 +113,7 @@
|
||||
struct pt_regs;
|
||||
extern int do_page_fault(struct pt_regs *, unsigned long, unsigned long);
|
||||
extern void bad_page_fault(struct pt_regs *, unsigned long, int);
|
||||
void __bad_page_fault(struct pt_regs *regs, unsigned long address, int sig);
|
||||
extern void _exception(int, struct pt_regs *, int, unsigned long);
|
||||
extern void _exception_pkey(struct pt_regs *, unsigned long, int);
|
||||
extern void die(const char *, struct pt_regs *, long);
|
||||
|
||||
@@ -163,7 +163,7 @@ static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
|
||||
*/
|
||||
__wsum __csum_partial(const void *buff, int len, __wsum sum);
|
||||
|
||||
static inline __wsum csum_partial(const void *buff, int len, __wsum sum)
|
||||
static __always_inline __wsum csum_partial(const void *buff, int len, __wsum sum)
|
||||
{
|
||||
if (__builtin_constant_p(len) && len <= 16 && (len & 1) == 0) {
|
||||
if (len == 2)
|
||||
|
||||
7
arch/powerpc/include/asm/clocksource.h
Normal file
7
arch/powerpc/include/asm/clocksource.h
Normal file
@@ -0,0 +1,7 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _ASM_POWERPC_CLOCKSOURCE_H
|
||||
#define _ASM_POWERPC_CLOCKSOURCE_H
|
||||
|
||||
#include <asm/vdso/clocksource.h>
|
||||
|
||||
#endif /* _ASM_POWERPC_CLOCKSOURCE_H */
|
||||
@@ -68,6 +68,7 @@ extern void cpm_reset(void);
|
||||
#define PROFF_SPI ((uint)0x0180)
|
||||
#define PROFF_SCC3 ((uint)0x0200)
|
||||
#define PROFF_SMC1 ((uint)0x0280)
|
||||
#define PROFF_DSP1 ((uint)0x02c0)
|
||||
#define PROFF_SCC4 ((uint)0x0300)
|
||||
#define PROFF_SMC2 ((uint)0x0380)
|
||||
|
||||
|
||||
12
arch/powerpc/include/asm/cpu_setup_power.h
Normal file
12
arch/powerpc/include/asm/cpu_setup_power.h
Normal file
@@ -0,0 +1,12 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (C) 2020 IBM Corporation
|
||||
*/
|
||||
void __setup_cpu_power7(unsigned long offset, struct cpu_spec *spec);
|
||||
void __restore_cpu_power7(void);
|
||||
void __setup_cpu_power8(unsigned long offset, struct cpu_spec *spec);
|
||||
void __restore_cpu_power8(void);
|
||||
void __setup_cpu_power9(unsigned long offset, struct cpu_spec *spec);
|
||||
void __restore_cpu_power9(void);
|
||||
void __setup_cpu_power10(unsigned long offset, struct cpu_spec *spec);
|
||||
void __restore_cpu_power10(void);
|
||||
@@ -41,7 +41,6 @@ extern int machine_check_4xx(struct pt_regs *regs);
|
||||
extern int machine_check_440A(struct pt_regs *regs);
|
||||
extern int machine_check_e500mc(struct pt_regs *regs);
|
||||
extern int machine_check_e500(struct pt_regs *regs);
|
||||
extern int machine_check_e200(struct pt_regs *regs);
|
||||
extern int machine_check_47x(struct pt_regs *regs);
|
||||
int machine_check_8xx(struct pt_regs *regs);
|
||||
int machine_check_83xx(struct pt_regs *regs);
|
||||
@@ -137,7 +136,7 @@ static inline void cpu_feature_keys_init(void) { }
|
||||
#define CPU_FTR_DBELL ASM_CONST(0x00000004)
|
||||
#define CPU_FTR_CAN_NAP ASM_CONST(0x00000008)
|
||||
#define CPU_FTR_DEBUG_LVL_EXC ASM_CONST(0x00000010)
|
||||
#define CPU_FTR_NODSISRALIGN ASM_CONST(0x00000020)
|
||||
// ASM_CONST(0x00000020) Free
|
||||
#define CPU_FTR_FPU_UNAVAILABLE ASM_CONST(0x00000040)
|
||||
#define CPU_FTR_LWSYNC ASM_CONST(0x00000080)
|
||||
#define CPU_FTR_NOEXECUTE ASM_CONST(0x00000100)
|
||||
@@ -219,9 +218,7 @@ static inline void cpu_feature_keys_init(void) { }
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#define CPU_FTR_PPCAS_ARCH_V2 (CPU_FTR_NOEXECUTE | CPU_FTR_NODSISRALIGN)
|
||||
|
||||
#define MMU_FTR_PPCAS_ARCH_V2 (MMU_FTR_TLBIEL | MMU_FTR_16M_PAGE)
|
||||
#define CPU_FTR_PPCAS_ARCH_V2 (CPU_FTR_NOEXECUTE)
|
||||
|
||||
/* We only set the altivec features if the kernel was compiled with altivec
|
||||
* support
|
||||
@@ -369,7 +366,7 @@ static inline void cpu_feature_keys_init(void) { }
|
||||
CPU_FTR_PPC_LE | CPU_FTR_NEED_PAIRED_STWCX)
|
||||
#define CPU_FTRS_82XX (CPU_FTR_COMMON | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_NOEXECUTE)
|
||||
#define CPU_FTRS_G2_LE (CPU_FTR_COMMON | CPU_FTR_MAYBE_CAN_DOZE | \
|
||||
CPU_FTR_MAYBE_CAN_NAP)
|
||||
CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_NOEXECUTE)
|
||||
#define CPU_FTRS_E300 (CPU_FTR_MAYBE_CAN_DOZE | \
|
||||
CPU_FTR_MAYBE_CAN_NAP | \
|
||||
CPU_FTR_COMMON | CPU_FTR_NOEXECUTE)
|
||||
@@ -378,38 +375,33 @@ static inline void cpu_feature_keys_init(void) { }
|
||||
CPU_FTR_COMMON | CPU_FTR_FPU_UNAVAILABLE | CPU_FTR_NOEXECUTE)
|
||||
#define CPU_FTRS_CLASSIC32 (CPU_FTR_COMMON)
|
||||
#define CPU_FTRS_8XX (CPU_FTR_NOEXECUTE)
|
||||
#define CPU_FTRS_40X (CPU_FTR_NODSISRALIGN | CPU_FTR_NOEXECUTE)
|
||||
#define CPU_FTRS_44X (CPU_FTR_NODSISRALIGN | CPU_FTR_NOEXECUTE)
|
||||
#define CPU_FTRS_440x6 (CPU_FTR_NODSISRALIGN | CPU_FTR_NOEXECUTE | \
|
||||
#define CPU_FTRS_40X (CPU_FTR_NOEXECUTE)
|
||||
#define CPU_FTRS_44X (CPU_FTR_NOEXECUTE)
|
||||
#define CPU_FTRS_440x6 (CPU_FTR_NOEXECUTE | \
|
||||
CPU_FTR_INDEXED_DCR)
|
||||
#define CPU_FTRS_47X (CPU_FTRS_440x6)
|
||||
#define CPU_FTRS_E200 (CPU_FTR_SPE_COMP | \
|
||||
CPU_FTR_NODSISRALIGN | CPU_FTR_COHERENT_ICACHE | \
|
||||
CPU_FTR_NOEXECUTE | \
|
||||
CPU_FTR_DEBUG_LVL_EXC)
|
||||
#define CPU_FTRS_E500 (CPU_FTR_MAYBE_CAN_DOZE | \
|
||||
CPU_FTR_SPE_COMP | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_NODSISRALIGN | \
|
||||
CPU_FTR_SPE_COMP | CPU_FTR_MAYBE_CAN_NAP | \
|
||||
CPU_FTR_NOEXECUTE)
|
||||
#define CPU_FTRS_E500_2 (CPU_FTR_MAYBE_CAN_DOZE | \
|
||||
CPU_FTR_SPE_COMP | CPU_FTR_MAYBE_CAN_NAP | \
|
||||
CPU_FTR_NODSISRALIGN | CPU_FTR_NOEXECUTE)
|
||||
#define CPU_FTRS_E500MC (CPU_FTR_NODSISRALIGN | \
|
||||
CPU_FTR_NOEXECUTE)
|
||||
#define CPU_FTRS_E500MC ( \
|
||||
CPU_FTR_LWSYNC | CPU_FTR_NOEXECUTE | \
|
||||
CPU_FTR_DBELL | CPU_FTR_DEBUG_LVL_EXC | CPU_FTR_EMB_HV)
|
||||
/*
|
||||
* e5500/e6500 erratum A-006958 is a timebase bug that can use the
|
||||
* same workaround as CPU_FTR_CELL_TB_BUG.
|
||||
*/
|
||||
#define CPU_FTRS_E5500 (CPU_FTR_NODSISRALIGN | \
|
||||
#define CPU_FTRS_E5500 ( \
|
||||
CPU_FTR_LWSYNC | CPU_FTR_NOEXECUTE | \
|
||||
CPU_FTR_DBELL | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \
|
||||
CPU_FTR_DEBUG_LVL_EXC | CPU_FTR_EMB_HV | CPU_FTR_CELL_TB_BUG)
|
||||
#define CPU_FTRS_E6500 (CPU_FTR_NODSISRALIGN | \
|
||||
#define CPU_FTRS_E6500 ( \
|
||||
CPU_FTR_LWSYNC | CPU_FTR_NOEXECUTE | \
|
||||
CPU_FTR_DBELL | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \
|
||||
CPU_FTR_DEBUG_LVL_EXC | CPU_FTR_EMB_HV | CPU_FTR_ALTIVEC_COMP | \
|
||||
CPU_FTR_CELL_TB_BUG | CPU_FTR_SMT)
|
||||
#define CPU_FTRS_GENERIC_32 (CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN)
|
||||
|
||||
/* 64-bit CPUs */
|
||||
#define CPU_FTRS_PPC970 (CPU_FTR_LWSYNC | \
|
||||
@@ -489,7 +481,7 @@ static inline void cpu_feature_keys_init(void) { }
|
||||
CPU_FTR_PURR | CPU_FTR_REAL_LE | CPU_FTR_DABRX)
|
||||
#define CPU_FTRS_COMPATIBLE (CPU_FTR_PPCAS_ARCH_V2)
|
||||
|
||||
#ifdef __powerpc64__
|
||||
#ifdef CONFIG_PPC64
|
||||
#ifdef CONFIG_PPC_BOOK3E
|
||||
#define CPU_FTRS_POSSIBLE (CPU_FTRS_E6500 | CPU_FTRS_E5500)
|
||||
#else
|
||||
@@ -510,18 +502,19 @@ static inline void cpu_feature_keys_init(void) { }
|
||||
#else
|
||||
enum {
|
||||
CPU_FTRS_POSSIBLE =
|
||||
#ifdef CONFIG_PPC_BOOK3S_32
|
||||
CPU_FTRS_603 | CPU_FTRS_604 | CPU_FTRS_740_NOTAU |
|
||||
#ifdef CONFIG_PPC_BOOK3S_604
|
||||
CPU_FTRS_604 | CPU_FTRS_740_NOTAU |
|
||||
CPU_FTRS_740 | CPU_FTRS_750 | CPU_FTRS_750FX1 |
|
||||
CPU_FTRS_750FX2 | CPU_FTRS_750FX | CPU_FTRS_750GX |
|
||||
CPU_FTRS_7400_NOTAU | CPU_FTRS_7400 | CPU_FTRS_7450_20 |
|
||||
CPU_FTRS_7450_21 | CPU_FTRS_7450_23 | CPU_FTRS_7455_1 |
|
||||
CPU_FTRS_7455_20 | CPU_FTRS_7455 | CPU_FTRS_7447_10 |
|
||||
CPU_FTRS_7447 | CPU_FTRS_7447A | CPU_FTRS_82XX |
|
||||
CPU_FTRS_G2_LE | CPU_FTRS_E300 | CPU_FTRS_E300C2 |
|
||||
CPU_FTRS_7447 | CPU_FTRS_7447A |
|
||||
CPU_FTRS_CLASSIC32 |
|
||||
#else
|
||||
CPU_FTRS_GENERIC_32 |
|
||||
#endif
|
||||
#ifdef CONFIG_PPC_BOOK3S_603
|
||||
CPU_FTRS_603 | CPU_FTRS_82XX |
|
||||
CPU_FTRS_G2_LE | CPU_FTRS_E300 | CPU_FTRS_E300C2 |
|
||||
#endif
|
||||
#ifdef CONFIG_PPC_8xx
|
||||
CPU_FTRS_8XX |
|
||||
@@ -529,14 +522,10 @@ enum {
|
||||
#ifdef CONFIG_40x
|
||||
CPU_FTRS_40X |
|
||||
#endif
|
||||
#ifdef CONFIG_44x
|
||||
CPU_FTRS_44X | CPU_FTRS_440x6 |
|
||||
#endif
|
||||
#ifdef CONFIG_PPC_47x
|
||||
CPU_FTRS_47X | CPU_FTR_476_DD2 |
|
||||
#endif
|
||||
#ifdef CONFIG_E200
|
||||
CPU_FTRS_E200 |
|
||||
#elif defined(CONFIG_44x)
|
||||
CPU_FTRS_44X | CPU_FTRS_440x6 |
|
||||
#endif
|
||||
#ifdef CONFIG_E500
|
||||
CPU_FTRS_E500 | CPU_FTRS_E500_2 |
|
||||
@@ -548,7 +537,7 @@ enum {
|
||||
};
|
||||
#endif /* __powerpc64__ */
|
||||
|
||||
#ifdef __powerpc64__
|
||||
#ifdef CONFIG_PPC64
|
||||
#ifdef CONFIG_PPC_BOOK3E
|
||||
#define CPU_FTRS_ALWAYS (CPU_FTRS_E6500 & CPU_FTRS_E5500)
|
||||
#else
|
||||
@@ -557,7 +546,6 @@ enum {
|
||||
#define CPU_FTRS_DT_CPU_BASE \
|
||||
(CPU_FTR_LWSYNC | \
|
||||
CPU_FTR_FPU_UNAVAILABLE | \
|
||||
CPU_FTR_NODSISRALIGN | \
|
||||
CPU_FTR_NOEXECUTE | \
|
||||
CPU_FTR_COHERENT_ICACHE | \
|
||||
CPU_FTR_STCX_CHECKS_ADDRESS | \
|
||||
@@ -586,18 +574,19 @@ enum {
|
||||
#else
|
||||
enum {
|
||||
CPU_FTRS_ALWAYS =
|
||||
#ifdef CONFIG_PPC_BOOK3S_32
|
||||
CPU_FTRS_603 & CPU_FTRS_604 & CPU_FTRS_740_NOTAU &
|
||||
#ifdef CONFIG_PPC_BOOK3S_604
|
||||
CPU_FTRS_604 & CPU_FTRS_740_NOTAU &
|
||||
CPU_FTRS_740 & CPU_FTRS_750 & CPU_FTRS_750FX1 &
|
||||
CPU_FTRS_750FX2 & CPU_FTRS_750FX & CPU_FTRS_750GX &
|
||||
CPU_FTRS_7400_NOTAU & CPU_FTRS_7400 & CPU_FTRS_7450_20 &
|
||||
CPU_FTRS_7450_21 & CPU_FTRS_7450_23 & CPU_FTRS_7455_1 &
|
||||
CPU_FTRS_7455_20 & CPU_FTRS_7455 & CPU_FTRS_7447_10 &
|
||||
CPU_FTRS_7447 & CPU_FTRS_7447A & CPU_FTRS_82XX &
|
||||
CPU_FTRS_G2_LE & CPU_FTRS_E300 & CPU_FTRS_E300C2 &
|
||||
CPU_FTRS_7447 & CPU_FTRS_7447A &
|
||||
CPU_FTRS_CLASSIC32 &
|
||||
#else
|
||||
CPU_FTRS_GENERIC_32 &
|
||||
#endif
|
||||
#ifdef CONFIG_PPC_BOOK3S_603
|
||||
CPU_FTRS_603 & CPU_FTRS_82XX &
|
||||
CPU_FTRS_G2_LE & CPU_FTRS_E300 & CPU_FTRS_E300C2 &
|
||||
#endif
|
||||
#ifdef CONFIG_PPC_8xx
|
||||
CPU_FTRS_8XX &
|
||||
@@ -605,12 +594,11 @@ enum {
|
||||
#ifdef CONFIG_40x
|
||||
CPU_FTRS_40X &
|
||||
#endif
|
||||
#ifdef CONFIG_44x
|
||||
#ifdef CONFIG_PPC_47x
|
||||
CPU_FTRS_47X &
|
||||
#elif defined(CONFIG_44x)
|
||||
CPU_FTRS_44X & CPU_FTRS_440x6 &
|
||||
#endif
|
||||
#ifdef CONFIG_E200
|
||||
CPU_FTRS_E200 &
|
||||
#endif
|
||||
#ifdef CONFIG_E500
|
||||
CPU_FTRS_E500 & CPU_FTRS_E500_2 &
|
||||
#endif
|
||||
|
||||
@@ -168,8 +168,8 @@ do { \
|
||||
/* Cache size items */ \
|
||||
NEW_AUX_ENT(AT_DCACHEBSIZE, dcache_bsize); \
|
||||
NEW_AUX_ENT(AT_ICACHEBSIZE, icache_bsize); \
|
||||
NEW_AUX_ENT(AT_UCACHEBSIZE, ucache_bsize); \
|
||||
VDSO_AUX_ENT(AT_SYSINFO_EHDR, current->mm->context.vdso_base); \
|
||||
NEW_AUX_ENT(AT_UCACHEBSIZE, 0); \
|
||||
VDSO_AUX_ENT(AT_SYSINFO_EHDR, (unsigned long)current->mm->context.vdso);\
|
||||
ARCH_DLINFO_CACHE_GEOMETRY; \
|
||||
} while (0)
|
||||
|
||||
|
||||
@@ -36,6 +36,24 @@ label##2: \
|
||||
.align 2; \
|
||||
label##3:
|
||||
|
||||
|
||||
#ifndef CONFIG_CC_IS_CLANG
|
||||
#define CHECK_ALT_SIZE(else_size, body_size) \
|
||||
.ifgt (else_size) - (body_size); \
|
||||
.error "Feature section else case larger than body"; \
|
||||
.endif;
|
||||
#else
|
||||
/*
|
||||
* If we use the ifgt syntax above, clang's assembler complains about the
|
||||
* expression being non-absolute when the code appears in an inline assembly
|
||||
* statement.
|
||||
* As a workaround use an .org directive that has no effect if the else case
|
||||
* instructions are smaller than the body, but fails otherwise.
|
||||
*/
|
||||
#define CHECK_ALT_SIZE(else_size, body_size) \
|
||||
.org . + ((else_size) > (body_size));
|
||||
#endif
|
||||
|
||||
#define MAKE_FTR_SECTION_ENTRY(msk, val, label, sect) \
|
||||
label##4: \
|
||||
.popsection; \
|
||||
@@ -48,9 +66,7 @@ label##5: \
|
||||
FTR_ENTRY_OFFSET label##2b-label##5b; \
|
||||
FTR_ENTRY_OFFSET label##3b-label##5b; \
|
||||
FTR_ENTRY_OFFSET label##4b-label##5b; \
|
||||
.ifgt (label##4b- label##3b)-(label##2b- label##1b); \
|
||||
.error "Feature section else case larger than body"; \
|
||||
.endif; \
|
||||
CHECK_ALT_SIZE((label##4b-label##3b), (label##2b-label##1b)); \
|
||||
.popsection;
|
||||
|
||||
|
||||
@@ -100,6 +116,9 @@ label##5: \
|
||||
#define END_MMU_FTR_SECTION_NESTED_IFSET(msk, label) \
|
||||
END_MMU_FTR_SECTION_NESTED((msk), (msk), label)
|
||||
|
||||
#define END_MMU_FTR_SECTION_NESTED_IFCLR(msk, label) \
|
||||
END_MMU_FTR_SECTION_NESTED((msk), 0, label)
|
||||
|
||||
#define END_MMU_FTR_SECTION_IFSET(msk) END_MMU_FTR_SECTION((msk), (msk))
|
||||
#define END_MMU_FTR_SECTION_IFCLR(msk) END_MMU_FTR_SECTION((msk), 0)
|
||||
|
||||
|
||||
@@ -134,12 +134,6 @@ extern int ibm_nmi_interlock_token;
|
||||
|
||||
extern unsigned int __start___fw_ftr_fixup, __stop___fw_ftr_fixup;
|
||||
|
||||
#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_KVM_GUEST)
|
||||
bool is_kvm_guest(void);
|
||||
#else
|
||||
static inline bool is_kvm_guest(void) { return false; }
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PPC_PSERIES
|
||||
void pseries_probe_fw_features(void);
|
||||
#else
|
||||
|
||||
@@ -155,6 +155,14 @@
|
||||
#define H_VASI_RESUMED 5
|
||||
#define H_VASI_COMPLETED 6
|
||||
|
||||
/* VASI signal codes. Only the Cancel code is valid for H_VASI_SIGNAL. */
|
||||
#define H_VASI_SIGNAL_CANCEL 1
|
||||
#define H_VASI_SIGNAL_ABORT 2
|
||||
#define H_VASI_SIGNAL_SUSPEND 3
|
||||
#define H_VASI_SIGNAL_COMPLETE 4
|
||||
#define H_VASI_SIGNAL_ENABLE 5
|
||||
#define H_VASI_SIGNAL_FAILOVER 6
|
||||
|
||||
/* Each control block has to be on a 4K boundary */
|
||||
#define H_CB_ALIGNMENT 4096
|
||||
|
||||
@@ -261,6 +269,7 @@
|
||||
#define H_ADD_CONN 0x284
|
||||
#define H_DEL_CONN 0x288
|
||||
#define H_JOIN 0x298
|
||||
#define H_VASI_SIGNAL 0x2A0
|
||||
#define H_VASI_STATE 0x2A4
|
||||
#define H_VIOCTL 0x2A8
|
||||
#define H_ENABLE_CRQ 0x2B0
|
||||
|
||||
@@ -122,7 +122,7 @@ static inline u##size name(const volatile u##size __iomem *addr) \
|
||||
{ \
|
||||
u##size ret; \
|
||||
__asm__ __volatile__("sync;"#insn"%U1%X1 %0,%1;twi 0,%0,0;isync"\
|
||||
: "=r" (ret) : "m" (*addr) : "memory"); \
|
||||
: "=r" (ret) : "m"UPD_CONSTR (*addr) : "memory"); \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ static inline u##size name(const volatile u##size __iomem *addr) \
|
||||
static inline void name(volatile u##size __iomem *addr, u##size val) \
|
||||
{ \
|
||||
__asm__ __volatile__("sync;"#insn"%U0%X0 %1,%0" \
|
||||
: "=m" (*addr) : "r" (val) : "memory"); \
|
||||
: "=m"UPD_CONSTR (*addr) : "r" (val) : "memory"); \
|
||||
mmiowb_set_pending(); \
|
||||
}
|
||||
|
||||
@@ -302,41 +302,56 @@ static inline unsigned char __raw_readb(const volatile void __iomem *addr)
|
||||
{
|
||||
return *(volatile unsigned char __force *)PCI_FIX_ADDR(addr);
|
||||
}
|
||||
#define __raw_readb __raw_readb
|
||||
|
||||
static inline unsigned short __raw_readw(const volatile void __iomem *addr)
|
||||
{
|
||||
return *(volatile unsigned short __force *)PCI_FIX_ADDR(addr);
|
||||
}
|
||||
#define __raw_readw __raw_readw
|
||||
|
||||
static inline unsigned int __raw_readl(const volatile void __iomem *addr)
|
||||
{
|
||||
return *(volatile unsigned int __force *)PCI_FIX_ADDR(addr);
|
||||
}
|
||||
#define __raw_readl __raw_readl
|
||||
|
||||
static inline void __raw_writeb(unsigned char v, volatile void __iomem *addr)
|
||||
{
|
||||
*(volatile unsigned char __force *)PCI_FIX_ADDR(addr) = v;
|
||||
}
|
||||
#define __raw_writeb __raw_writeb
|
||||
|
||||
static inline void __raw_writew(unsigned short v, volatile void __iomem *addr)
|
||||
{
|
||||
*(volatile unsigned short __force *)PCI_FIX_ADDR(addr) = v;
|
||||
}
|
||||
#define __raw_writew __raw_writew
|
||||
|
||||
static inline void __raw_writel(unsigned int v, volatile void __iomem *addr)
|
||||
{
|
||||
*(volatile unsigned int __force *)PCI_FIX_ADDR(addr) = v;
|
||||
}
|
||||
#define __raw_writel __raw_writel
|
||||
|
||||
#ifdef __powerpc64__
|
||||
static inline unsigned long __raw_readq(const volatile void __iomem *addr)
|
||||
{
|
||||
return *(volatile unsigned long __force *)PCI_FIX_ADDR(addr);
|
||||
}
|
||||
#define __raw_readq __raw_readq
|
||||
|
||||
static inline void __raw_writeq(unsigned long v, volatile void __iomem *addr)
|
||||
{
|
||||
*(volatile unsigned long __force *)PCI_FIX_ADDR(addr) = v;
|
||||
}
|
||||
#define __raw_writeq __raw_writeq
|
||||
|
||||
static inline void __raw_writeq_be(unsigned long v, volatile void __iomem *addr)
|
||||
{
|
||||
__raw_writeq((__force unsigned long)cpu_to_be64(v), addr);
|
||||
}
|
||||
#define __raw_writeq_be __raw_writeq_be
|
||||
|
||||
/*
|
||||
* Real mode versions of the above. Those instructions are only supposed
|
||||
@@ -609,10 +624,37 @@ static inline void name at \
|
||||
/* Some drivers check for the presence of readq & writeq with
|
||||
* a #ifdef, so we make them happy here.
|
||||
*/
|
||||
#define readb readb
|
||||
#define readw readw
|
||||
#define readl readl
|
||||
#define writeb writeb
|
||||
#define writew writew
|
||||
#define writel writel
|
||||
#define readsb readsb
|
||||
#define readsw readsw
|
||||
#define readsl readsl
|
||||
#define writesb writesb
|
||||
#define writesw writesw
|
||||
#define writesl writesl
|
||||
#define inb inb
|
||||
#define inw inw
|
||||
#define inl inl
|
||||
#define outb outb
|
||||
#define outw outw
|
||||
#define outl outl
|
||||
#define insb insb
|
||||
#define insw insw
|
||||
#define insl insl
|
||||
#define outsb outsb
|
||||
#define outsw outsw
|
||||
#define outsl outsl
|
||||
#ifdef __powerpc64__
|
||||
#define readq readq
|
||||
#define writeq writeq
|
||||
#endif
|
||||
#define memset_io memset_io
|
||||
#define memcpy_fromio memcpy_fromio
|
||||
#define memcpy_toio memcpy_toio
|
||||
|
||||
/*
|
||||
* Convert a physical pointer to a virtual kernel pointer for /dev/mem
|
||||
@@ -637,7 +679,106 @@ static inline void name at \
|
||||
#define writel_relaxed(v, addr) writel(v, addr)
|
||||
#define writeq_relaxed(v, addr) writeq(v, addr)
|
||||
|
||||
#ifdef CONFIG_GENERIC_IOMAP
|
||||
#include <asm-generic/iomap.h>
|
||||
#else
|
||||
/*
|
||||
* Here comes the implementation of the IOMAP interfaces.
|
||||
*/
|
||||
static inline unsigned int ioread16be(const void __iomem *addr)
|
||||
{
|
||||
return readw_be(addr);
|
||||
}
|
||||
#define ioread16be ioread16be
|
||||
|
||||
static inline unsigned int ioread32be(const void __iomem *addr)
|
||||
{
|
||||
return readl_be(addr);
|
||||
}
|
||||
#define ioread32be ioread32be
|
||||
|
||||
#ifdef __powerpc64__
|
||||
static inline u64 ioread64_lo_hi(const void __iomem *addr)
|
||||
{
|
||||
return readq(addr);
|
||||
}
|
||||
#define ioread64_lo_hi ioread64_lo_hi
|
||||
|
||||
static inline u64 ioread64_hi_lo(const void __iomem *addr)
|
||||
{
|
||||
return readq(addr);
|
||||
}
|
||||
#define ioread64_hi_lo ioread64_hi_lo
|
||||
|
||||
static inline u64 ioread64be(const void __iomem *addr)
|
||||
{
|
||||
return readq_be(addr);
|
||||
}
|
||||
#define ioread64be ioread64be
|
||||
|
||||
static inline u64 ioread64be_lo_hi(const void __iomem *addr)
|
||||
{
|
||||
return readq_be(addr);
|
||||
}
|
||||
#define ioread64be_lo_hi ioread64be_lo_hi
|
||||
|
||||
static inline u64 ioread64be_hi_lo(const void __iomem *addr)
|
||||
{
|
||||
return readq_be(addr);
|
||||
}
|
||||
#define ioread64be_hi_lo ioread64be_hi_lo
|
||||
#endif /* __powerpc64__ */
|
||||
|
||||
static inline void iowrite16be(u16 val, void __iomem *addr)
|
||||
{
|
||||
writew_be(val, addr);
|
||||
}
|
||||
#define iowrite16be iowrite16be
|
||||
|
||||
static inline void iowrite32be(u32 val, void __iomem *addr)
|
||||
{
|
||||
writel_be(val, addr);
|
||||
}
|
||||
#define iowrite32be iowrite32be
|
||||
|
||||
#ifdef __powerpc64__
|
||||
static inline void iowrite64_lo_hi(u64 val, void __iomem *addr)
|
||||
{
|
||||
writeq(val, addr);
|
||||
}
|
||||
#define iowrite64_lo_hi iowrite64_lo_hi
|
||||
|
||||
static inline void iowrite64_hi_lo(u64 val, void __iomem *addr)
|
||||
{
|
||||
writeq(val, addr);
|
||||
}
|
||||
#define iowrite64_hi_lo iowrite64_hi_lo
|
||||
|
||||
static inline void iowrite64be(u64 val, void __iomem *addr)
|
||||
{
|
||||
writeq_be(val, addr);
|
||||
}
|
||||
#define iowrite64be iowrite64be
|
||||
|
||||
static inline void iowrite64be_lo_hi(u64 val, void __iomem *addr)
|
||||
{
|
||||
writeq_be(val, addr);
|
||||
}
|
||||
#define iowrite64be_lo_hi iowrite64be_lo_hi
|
||||
|
||||
static inline void iowrite64be_hi_lo(u64 val, void __iomem *addr)
|
||||
{
|
||||
writeq_be(val, addr);
|
||||
}
|
||||
#define iowrite64be_hi_lo iowrite64be_hi_lo
|
||||
#endif /* __powerpc64__ */
|
||||
|
||||
struct pci_dev;
|
||||
void pci_iounmap(struct pci_dev *dev, void __iomem *addr);
|
||||
#define pci_iounmap pci_iounmap
|
||||
void __iomem *ioport_map(unsigned long port, unsigned int len);
|
||||
#define ioport_map ioport_map
|
||||
#endif
|
||||
|
||||
static inline void iosync(void)
|
||||
{
|
||||
@@ -670,7 +811,6 @@ static inline void iosync(void)
|
||||
|
||||
#define IO_SPACE_LIMIT ~(0UL)
|
||||
|
||||
|
||||
/**
|
||||
* ioremap - map bus memory into CPU space
|
||||
* @address: bus address of the memory
|
||||
@@ -706,7 +846,13 @@ extern void __iomem *ioremap(phys_addr_t address, unsigned long size);
|
||||
extern void __iomem *ioremap_prot(phys_addr_t address, unsigned long size,
|
||||
unsigned long flags);
|
||||
extern void __iomem *ioremap_wc(phys_addr_t address, unsigned long size);
|
||||
#define ioremap_wc ioremap_wc
|
||||
|
||||
#ifdef CONFIG_PPC32
|
||||
void __iomem *ioremap_wt(phys_addr_t address, unsigned long size);
|
||||
#define ioremap_wt ioremap_wt
|
||||
#endif
|
||||
|
||||
void __iomem *ioremap_coherent(phys_addr_t address, unsigned long size);
|
||||
#define ioremap_uc(addr, size) ioremap((addr), (size))
|
||||
#define ioremap_cache(addr, size) \
|
||||
@@ -766,6 +912,7 @@ static inline unsigned long virt_to_phys(volatile void * address)
|
||||
|
||||
return __pa((unsigned long)address);
|
||||
}
|
||||
#define virt_to_phys virt_to_phys
|
||||
|
||||
/**
|
||||
* phys_to_virt - map physical address to virtual
|
||||
@@ -783,6 +930,7 @@ static inline void * phys_to_virt(unsigned long address)
|
||||
{
|
||||
return (void *)__va(address);
|
||||
}
|
||||
#define phys_to_virt phys_to_virt
|
||||
|
||||
/*
|
||||
* Change "struct page" to physical address.
|
||||
@@ -810,6 +958,7 @@ static inline unsigned long virt_to_bus(volatile void * address)
|
||||
return 0;
|
||||
return __pa(address) + PCI_DRAM_OFFSET;
|
||||
}
|
||||
#define virt_to_bus virt_to_bus
|
||||
|
||||
static inline void * bus_to_virt(unsigned long address)
|
||||
{
|
||||
@@ -817,6 +966,7 @@ static inline void * bus_to_virt(unsigned long address)
|
||||
return NULL;
|
||||
return __va(address - PCI_DRAM_OFFSET);
|
||||
}
|
||||
#define bus_to_virt bus_to_virt
|
||||
|
||||
#define page_to_bus(page) (page_to_phys(page) + PCI_DRAM_OFFSET)
|
||||
|
||||
@@ -855,6 +1005,8 @@ static inline void * bus_to_virt(unsigned long address)
|
||||
|
||||
#define clrsetbits_8(addr, clear, set) clrsetbits(8, addr, clear, set)
|
||||
|
||||
#include <asm-generic/io.h>
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* _ASM_POWERPC_IO_H */
|
||||
|
||||
@@ -15,11 +15,13 @@
|
||||
#define KUAP_CURRENT (KUAP_CURRENT_READ | KUAP_CURRENT_WRITE)
|
||||
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
#include <asm/book3s/64/kup-radix.h>
|
||||
#include <asm/book3s/64/kup.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PPC_8xx
|
||||
#include <asm/nohash/32/kup-8xx.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PPC_BOOK3S_32
|
||||
#include <asm/book3s/32/kup.h>
|
||||
#endif
|
||||
@@ -42,9 +44,10 @@
|
||||
|
||||
#else /* !__ASSEMBLY__ */
|
||||
|
||||
#include <linux/pgtable.h>
|
||||
extern bool disable_kuep;
|
||||
extern bool disable_kuap;
|
||||
|
||||
void setup_kup(void);
|
||||
#include <linux/pgtable.h>
|
||||
|
||||
#ifdef CONFIG_PPC_KUEP
|
||||
void setup_kuep(bool disabled);
|
||||
@@ -80,6 +83,12 @@ static inline void restore_user_access(unsigned long flags) { }
|
||||
#endif /* CONFIG_PPC_BOOK3S_64 */
|
||||
#endif /* CONFIG_PPC_KUAP */
|
||||
|
||||
static __always_inline void setup_kup(void)
|
||||
{
|
||||
setup_kuep(disable_kuep);
|
||||
setup_kuap(disable_kuap);
|
||||
}
|
||||
|
||||
static inline void allow_read_from_user(const void __user *from, unsigned long size)
|
||||
{
|
||||
allow_user_access(NULL, from, size, KUAP_READ);
|
||||
|
||||
25
arch/powerpc/include/asm/kvm_guest.h
Normal file
25
arch/powerpc/include/asm/kvm_guest.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (C) 2020 IBM Corporation
|
||||
*/
|
||||
|
||||
#ifndef _ASM_POWERPC_KVM_GUEST_H_
|
||||
#define _ASM_POWERPC_KVM_GUEST_H_
|
||||
|
||||
#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_KVM_GUEST)
|
||||
#include <linux/jump_label.h>
|
||||
|
||||
DECLARE_STATIC_KEY_FALSE(kvm_guest);
|
||||
|
||||
static inline bool is_kvm_guest(void)
|
||||
{
|
||||
return static_branch_unlikely(&kvm_guest);
|
||||
}
|
||||
|
||||
bool check_kvm_guest(void);
|
||||
#else
|
||||
static inline bool is_kvm_guest(void) { return false; }
|
||||
static inline bool check_kvm_guest(void) { return false; }
|
||||
#endif
|
||||
|
||||
#endif /* _ASM_POWERPC_KVM_GUEST_H_ */
|
||||
@@ -8,7 +8,7 @@
|
||||
#ifndef __POWERPC_KVM_PARA_H__
|
||||
#define __POWERPC_KVM_PARA_H__
|
||||
|
||||
#include <asm/firmware.h>
|
||||
#include <asm/kvm_guest.h>
|
||||
|
||||
#include <uapi/asm/kvm_para.h>
|
||||
|
||||
|
||||
@@ -207,7 +207,6 @@ struct machdep_calls {
|
||||
void (*suspend_disable_irqs)(void);
|
||||
void (*suspend_enable_irqs)(void);
|
||||
#endif
|
||||
int (*suspend_disable_cpu)(void);
|
||||
|
||||
#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
|
||||
ssize_t (*cpu_probe)(const char *, size_t);
|
||||
|
||||
@@ -228,6 +228,7 @@ int mce_register_notifier(struct notifier_block *nb);
|
||||
int mce_unregister_notifier(struct notifier_block *nb);
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
void flush_and_reload_slb(void);
|
||||
void flush_erat(void);
|
||||
long __machine_check_early_realmode_p7(struct pt_regs *regs);
|
||||
long __machine_check_early_realmode_p8(struct pt_regs *regs);
|
||||
long __machine_check_early_realmode_p9(struct pt_regs *regs);
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Architecture specific mm hooks
|
||||
*
|
||||
* Copyright (C) 2015, IBM Corporation
|
||||
* Author: Laurent Dufour <ldufour@linux.vnet.ibm.com>
|
||||
*/
|
||||
|
||||
#ifndef _ASM_POWERPC_MM_ARCH_HOOKS_H
|
||||
#define _ASM_POWERPC_MM_ARCH_HOOKS_H
|
||||
|
||||
static inline void arch_remap(struct mm_struct *mm,
|
||||
unsigned long old_start, unsigned long old_end,
|
||||
unsigned long new_start, unsigned long new_end)
|
||||
{
|
||||
/*
|
||||
* mremap() doesn't allow moving multiple vmas so we can limit the
|
||||
* check to old_start == vdso_base.
|
||||
*/
|
||||
if (old_start == mm->context.vdso_base)
|
||||
mm->context.vdso_base = new_start;
|
||||
}
|
||||
#define arch_remap arch_remap
|
||||
|
||||
#endif /* _ASM_POWERPC_MM_ARCH_HOOKS_H */
|
||||
@@ -29,9 +29,18 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Support for KUEP feature.
|
||||
* Supports KUAP feature
|
||||
* key 0 controlling userspace addresses on radix
|
||||
* Key 3 on hash
|
||||
*/
|
||||
#define MMU_FTR_KUEP ASM_CONST(0x00000400)
|
||||
#define MMU_FTR_BOOK3S_KUAP ASM_CONST(0x00000200)
|
||||
|
||||
/*
|
||||
* Supports KUEP feature
|
||||
* key 0 controlling userspace addresses on radix
|
||||
* Key 3 on hash
|
||||
*/
|
||||
#define MMU_FTR_BOOK3S_KUEP ASM_CONST(0x00000400)
|
||||
|
||||
/*
|
||||
* Support for memory protection keys.
|
||||
@@ -120,14 +129,8 @@
|
||||
*/
|
||||
#define MMU_FTR_1T_SEGMENT ASM_CONST(0x40000000)
|
||||
|
||||
/*
|
||||
* Supports KUAP (key 0 controlling userspace addresses) on radix
|
||||
*/
|
||||
#define MMU_FTR_RADIX_KUAP ASM_CONST(0x80000000)
|
||||
|
||||
/* MMU feature bit sets for various CPUs */
|
||||
#define MMU_FTRS_DEFAULT_HPTE_ARCH_V2 \
|
||||
MMU_FTR_HPTE_TABLE | MMU_FTR_PPCAS_ARCH_V2
|
||||
#define MMU_FTRS_DEFAULT_HPTE_ARCH_V2 (MMU_FTR_HPTE_TABLE | MMU_FTR_TLBIEL | MMU_FTR_16M_PAGE)
|
||||
#define MMU_FTRS_POWER MMU_FTRS_DEFAULT_HPTE_ARCH_V2
|
||||
#define MMU_FTRS_PPC970 MMU_FTRS_POWER | MMU_FTR_TLBIE_CROP_VA
|
||||
#define MMU_FTRS_POWER5 MMU_FTRS_POWER | MMU_FTR_LOCKLESS_TLBIE
|
||||
@@ -154,7 +157,7 @@ DECLARE_PER_CPU(int, next_tlbcam_idx);
|
||||
|
||||
enum {
|
||||
MMU_FTRS_POSSIBLE =
|
||||
#ifdef CONFIG_PPC_BOOK3S
|
||||
#if defined(CONFIG_PPC_BOOK3S_64) || defined(CONFIG_PPC_BOOK3S_604)
|
||||
MMU_FTR_HPTE_TABLE |
|
||||
#endif
|
||||
#ifdef CONFIG_PPC_8xx
|
||||
@@ -163,17 +166,19 @@ enum {
|
||||
#ifdef CONFIG_40x
|
||||
MMU_FTR_TYPE_40x |
|
||||
#endif
|
||||
#ifdef CONFIG_44x
|
||||
MMU_FTR_TYPE_44x |
|
||||
#endif
|
||||
#if defined(CONFIG_E200) || defined(CONFIG_E500)
|
||||
MMU_FTR_TYPE_FSL_E | MMU_FTR_BIG_PHYS | MMU_FTR_USE_TLBILX |
|
||||
#endif
|
||||
#ifdef CONFIG_PPC_47x
|
||||
MMU_FTR_TYPE_47x | MMU_FTR_USE_TLBIVAX_BCAST | MMU_FTR_LOCK_BCAST_INVAL |
|
||||
#elif defined(CONFIG_44x)
|
||||
MMU_FTR_TYPE_44x |
|
||||
#endif
|
||||
#ifdef CONFIG_E500
|
||||
MMU_FTR_TYPE_FSL_E | MMU_FTR_BIG_PHYS | MMU_FTR_USE_TLBILX |
|
||||
#endif
|
||||
#ifdef CONFIG_PPC_BOOK3S_32
|
||||
MMU_FTR_USE_HIGH_BATS | MMU_FTR_NEED_DTLB_SW_LRU |
|
||||
MMU_FTR_USE_HIGH_BATS |
|
||||
#endif
|
||||
#ifdef CONFIG_PPC_83xx
|
||||
MMU_FTR_NEED_DTLB_SW_LRU |
|
||||
#endif
|
||||
#ifdef CONFIG_PPC_BOOK3E_64
|
||||
MMU_FTR_USE_TLBRSRV | MMU_FTR_USE_PAIRED_MAS |
|
||||
@@ -187,22 +192,47 @@ enum {
|
||||
#ifdef CONFIG_PPC_RADIX_MMU
|
||||
MMU_FTR_TYPE_RADIX |
|
||||
MMU_FTR_GTSE |
|
||||
#ifdef CONFIG_PPC_KUAP
|
||||
MMU_FTR_RADIX_KUAP |
|
||||
#endif /* CONFIG_PPC_KUAP */
|
||||
#endif /* CONFIG_PPC_RADIX_MMU */
|
||||
#ifdef CONFIG_PPC_KUAP
|
||||
MMU_FTR_BOOK3S_KUAP |
|
||||
#endif /* CONFIG_PPC_KUAP */
|
||||
#ifdef CONFIG_PPC_MEM_KEYS
|
||||
MMU_FTR_PKEY |
|
||||
#endif
|
||||
#ifdef CONFIG_PPC_KUEP
|
||||
MMU_FTR_KUEP |
|
||||
MMU_FTR_BOOK3S_KUEP |
|
||||
#endif /* CONFIG_PPC_KUAP */
|
||||
|
||||
0,
|
||||
};
|
||||
|
||||
#if defined(CONFIG_PPC_BOOK3S_604) && !defined(CONFIG_PPC_BOOK3S_603)
|
||||
#define MMU_FTRS_ALWAYS MMU_FTR_HPTE_TABLE
|
||||
#endif
|
||||
#ifdef CONFIG_PPC_8xx
|
||||
#define MMU_FTRS_ALWAYS MMU_FTR_TYPE_8xx
|
||||
#endif
|
||||
#ifdef CONFIG_40x
|
||||
#define MMU_FTRS_ALWAYS MMU_FTR_TYPE_40x
|
||||
#endif
|
||||
#ifdef CONFIG_PPC_47x
|
||||
#define MMU_FTRS_ALWAYS MMU_FTR_TYPE_47x
|
||||
#elif defined(CONFIG_44x)
|
||||
#define MMU_FTRS_ALWAYS MMU_FTR_TYPE_44x
|
||||
#endif
|
||||
#if defined(CONFIG_E200) || defined(CONFIG_E500)
|
||||
#define MMU_FTRS_ALWAYS MMU_FTR_TYPE_FSL_E
|
||||
#endif
|
||||
|
||||
#ifndef MMU_FTRS_ALWAYS
|
||||
#define MMU_FTRS_ALWAYS 0
|
||||
#endif
|
||||
|
||||
static inline bool early_mmu_has_feature(unsigned long feature)
|
||||
{
|
||||
if (MMU_FTRS_ALWAYS & feature)
|
||||
return true;
|
||||
|
||||
return !!(MMU_FTRS_POSSIBLE & cur_cpu_spec->mmu_features & feature);
|
||||
}
|
||||
|
||||
@@ -231,6 +261,9 @@ static __always_inline bool mmu_has_feature(unsigned long feature)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (MMU_FTRS_ALWAYS & feature)
|
||||
return true;
|
||||
|
||||
if (!(MMU_FTRS_POSSIBLE & feature))
|
||||
return false;
|
||||
|
||||
|
||||
@@ -263,8 +263,10 @@ extern void arch_exit_mmap(struct mm_struct *mm);
|
||||
static inline void arch_unmap(struct mm_struct *mm,
|
||||
unsigned long start, unsigned long end)
|
||||
{
|
||||
if (start <= mm->context.vdso_base && mm->context.vdso_base < end)
|
||||
mm->context.vdso_base = 0;
|
||||
unsigned long vdso_base = (unsigned long)mm->context.vdso - PAGE_SIZE;
|
||||
|
||||
if (start <= vdso_base && vdso_base < end)
|
||||
mm->context.vdso = NULL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC_MEM_KEYS
|
||||
@@ -285,7 +287,7 @@ static inline bool arch_vma_access_permitted(struct vm_area_struct *vma,
|
||||
#define thread_pkey_regs_init(thread)
|
||||
#define arch_dup_pkeys(oldmm, mm)
|
||||
|
||||
static inline u64 pte_to_hpte_pkey_bits(u64 pteflags)
|
||||
static inline u64 pte_to_hpte_pkey_bits(u64 pteflags, unsigned long flags)
|
||||
{
|
||||
return 0x0UL;
|
||||
}
|
||||
|
||||
@@ -63,8 +63,7 @@ static inline void restore_user_access(unsigned long flags)
|
||||
static inline bool
|
||||
bad_kuap_fault(struct pt_regs *regs, unsigned long address, bool is_write)
|
||||
{
|
||||
return WARN(!((regs->kuap ^ MD_APG_KUAP) & 0xff000000),
|
||||
"Bug: fault blocked by AP register !");
|
||||
return !((regs->kuap ^ MD_APG_KUAP) & 0xff000000);
|
||||
}
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
typedef struct {
|
||||
unsigned int id;
|
||||
unsigned int active;
|
||||
unsigned long vdso_base;
|
||||
void __user *vdso;
|
||||
} mm_context_t;
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
@@ -108,7 +108,7 @@ extern unsigned int tlb_44x_index;
|
||||
typedef struct {
|
||||
unsigned int id;
|
||||
unsigned int active;
|
||||
unsigned long vdso_base;
|
||||
void __user *vdso;
|
||||
} mm_context_t;
|
||||
|
||||
/* patch sites */
|
||||
|
||||
@@ -181,7 +181,7 @@ void mmu_pin_tlb(unsigned long top, bool readonly);
|
||||
typedef struct {
|
||||
unsigned int id;
|
||||
unsigned int active;
|
||||
unsigned long vdso_base;
|
||||
void __user *vdso;
|
||||
void *pte_frag;
|
||||
} mm_context_t;
|
||||
|
||||
|
||||
@@ -238,7 +238,7 @@ extern unsigned int tlbcam_index;
|
||||
typedef struct {
|
||||
unsigned int id;
|
||||
unsigned int active;
|
||||
unsigned long vdso_base;
|
||||
void __user *vdso;
|
||||
} mm_context_t;
|
||||
|
||||
/* Page size definitions, common between 32 and 64-bit
|
||||
|
||||
@@ -192,9 +192,9 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_PPC32) && IS_ENABLED(CONFIG_PTE_64BIT) && !percpu) {
|
||||
__asm__ __volatile__("\
|
||||
stw%U0%X0 %2,%0\n\
|
||||
stw%X0 %2,%0\n\
|
||||
eieio\n\
|
||||
stw%U0%X0 %L2,%1"
|
||||
stw%X1 %L2,%1"
|
||||
: "=m" (*ptep), "=m" (*((unsigned char *)ptep+4))
|
||||
: "r" (pte) : "memory");
|
||||
return;
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
* - local_flush_tlb_mm(mm, full) flushes the specified mm context on
|
||||
* the local processor
|
||||
* - local_flush_tlb_page(vma, vmaddr) flushes one page on the local processor
|
||||
* - flush_tlb_page_nohash(vma, vmaddr) flushes one page if SW loaded TLB
|
||||
* - flush_tlb_range(vma, start, end) flushes a range of pages
|
||||
* - flush_tlb_kernel_range(start, end) flushes a range of kernel pages
|
||||
*
|
||||
|
||||
@@ -1091,9 +1091,9 @@ enum {
|
||||
OPAL_XIVE_IRQ_TRIGGER_PAGE = 0x00000001,
|
||||
OPAL_XIVE_IRQ_STORE_EOI = 0x00000002,
|
||||
OPAL_XIVE_IRQ_LSI = 0x00000004,
|
||||
OPAL_XIVE_IRQ_SHIFT_BUG = 0x00000008,
|
||||
OPAL_XIVE_IRQ_MASK_VIA_FW = 0x00000010,
|
||||
OPAL_XIVE_IRQ_EOI_VIA_FW = 0x00000020,
|
||||
OPAL_XIVE_IRQ_SHIFT_BUG = 0x00000008, /* P9 DD1.0 workaround */
|
||||
OPAL_XIVE_IRQ_MASK_VIA_FW = 0x00000010, /* P9 DD1.0 workaround */
|
||||
OPAL_XIVE_IRQ_EOI_VIA_FW = 0x00000020, /* P9 DD1.0 workaround */
|
||||
};
|
||||
|
||||
/* Flags for OPAL_XIVE_GET/SET_QUEUE_INFO */
|
||||
|
||||
@@ -16,12 +16,6 @@
|
||||
#define ARCH_DMA_MINALIGN L1_CACHE_BYTES
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PTE_64BIT
|
||||
#define PTE_FLAGS_OFFSET 4 /* offset of PTE flags, in bytes */
|
||||
#else
|
||||
#define PTE_FLAGS_OFFSET 0
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_PPC_256K_PAGES) || \
|
||||
(defined(CONFIG_PPC_8xx) && defined(CONFIG_PPC_16K_PAGES))
|
||||
#define PTE_SHIFT (PAGE_SHIFT - PTE_T_LOG2 - 2) /* 1/4 of a page */
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PPC_SPLPAR
|
||||
#include <asm/kvm_guest.h>
|
||||
#include <asm/cputhreads.h>
|
||||
|
||||
DECLARE_STATIC_KEY_FALSE(shared_processor);
|
||||
|
||||
static inline bool is_shared_processor(void)
|
||||
@@ -74,6 +77,21 @@ static inline bool vcpu_is_preempted(int cpu)
|
||||
{
|
||||
if (!is_shared_processor())
|
||||
return false;
|
||||
|
||||
#ifdef CONFIG_PPC_SPLPAR
|
||||
if (!is_kvm_guest()) {
|
||||
int first_cpu = cpu_first_thread_sibling(smp_processor_id());
|
||||
|
||||
/*
|
||||
* Preemption can only happen at core granularity. This CPU
|
||||
* is not preempted if one of the CPU of this core is not
|
||||
* preempted.
|
||||
*/
|
||||
if (cpu_first_thread_sibling(cpu) == first_cpu)
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (yield_count_of(cpu) & 1)
|
||||
return true;
|
||||
return false;
|
||||
|
||||
@@ -82,6 +82,7 @@ struct power_pmu {
|
||||
#define PPMU_ARCH_207S 0x00000080 /* PMC is architecture v2.07S */
|
||||
#define PPMU_NO_SIAR 0x00000100 /* Do not use SIAR */
|
||||
#define PPMU_ARCH_31 0x00000200 /* Has MMCR3, SIER2 and SIER3 */
|
||||
#define PPMU_P10_DD1 0x00000400 /* Is power10 DD1 processor version */
|
||||
|
||||
/*
|
||||
* Values for flags to get_alternatives()
|
||||
|
||||
@@ -3,12 +3,59 @@
|
||||
#ifndef _ASM_PNV_OCXL_H
|
||||
#define _ASM_PNV_OCXL_H
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#define PNV_OCXL_TL_MAX_TEMPLATE 63
|
||||
#define PNV_OCXL_TL_BITS_PER_RATE 4
|
||||
#define PNV_OCXL_TL_RATE_BUF_SIZE ((PNV_OCXL_TL_MAX_TEMPLATE+1) * PNV_OCXL_TL_BITS_PER_RATE / 8)
|
||||
|
||||
#define PNV_OCXL_ATSD_TIMEOUT 1
|
||||
|
||||
/* TLB Management Instructions */
|
||||
#define PNV_OCXL_ATSD_LNCH 0x00
|
||||
/* Radix Invalidate */
|
||||
#define PNV_OCXL_ATSD_LNCH_R PPC_BIT(0)
|
||||
/* Radix Invalidation Control
|
||||
* 0b00 Just invalidate TLB.
|
||||
* 0b01 Invalidate just Page Walk Cache.
|
||||
* 0b10 Invalidate TLB, Page Walk Cache, and any
|
||||
* caching of Partition and Process Table Entries.
|
||||
*/
|
||||
#define PNV_OCXL_ATSD_LNCH_RIC PPC_BITMASK(1, 2)
|
||||
/* Number and Page Size of translations to be invalidated */
|
||||
#define PNV_OCXL_ATSD_LNCH_LP PPC_BITMASK(3, 10)
|
||||
/* Invalidation Criteria
|
||||
* 0b00 Invalidate just the target VA.
|
||||
* 0b01 Invalidate matching PID.
|
||||
*/
|
||||
#define PNV_OCXL_ATSD_LNCH_IS PPC_BITMASK(11, 12)
|
||||
/* 0b1: Process Scope, 0b0: Partition Scope */
|
||||
#define PNV_OCXL_ATSD_LNCH_PRS PPC_BIT(13)
|
||||
/* Invalidation Flag */
|
||||
#define PNV_OCXL_ATSD_LNCH_B PPC_BIT(14)
|
||||
/* Actual Page Size to be invalidated
|
||||
* 000 4KB
|
||||
* 101 64KB
|
||||
* 001 2MB
|
||||
* 010 1GB
|
||||
*/
|
||||
#define PNV_OCXL_ATSD_LNCH_AP PPC_BITMASK(15, 17)
|
||||
/* Defines the large page select
|
||||
* L=0b0 for 4KB pages
|
||||
* L=0b1 for large pages)
|
||||
*/
|
||||
#define PNV_OCXL_ATSD_LNCH_L PPC_BIT(18)
|
||||
/* Process ID */
|
||||
#define PNV_OCXL_ATSD_LNCH_PID PPC_BITMASK(19, 38)
|
||||
/* NoFlush – Assumed to be 0b0 */
|
||||
#define PNV_OCXL_ATSD_LNCH_F PPC_BIT(39)
|
||||
#define PNV_OCXL_ATSD_LNCH_OCAPI_SLBI PPC_BIT(40)
|
||||
#define PNV_OCXL_ATSD_LNCH_OCAPI_SINGLETON PPC_BIT(41)
|
||||
#define PNV_OCXL_ATSD_AVA 0x08
|
||||
#define PNV_OCXL_ATSD_AVA_AVA PPC_BITMASK(0, 51)
|
||||
#define PNV_OCXL_ATSD_STAT 0x10
|
||||
|
||||
int pnv_ocxl_get_actag(struct pci_dev *dev, u16 *base, u16 *enabled, u16 *supported);
|
||||
int pnv_ocxl_get_pasid_count(struct pci_dev *dev, int *count);
|
||||
|
||||
@@ -28,4 +75,11 @@ int pnv_ocxl_spa_setup(struct pci_dev *dev, void *spa_mem, int PE_mask, void **p
|
||||
void pnv_ocxl_spa_release(void *platform_data);
|
||||
int pnv_ocxl_spa_remove_pe_from_cache(void *platform_data, int pe_handle);
|
||||
|
||||
int pnv_ocxl_map_lpar(struct pci_dev *dev, uint64_t lparid,
|
||||
uint64_t lpcr, void __iomem **arva);
|
||||
void pnv_ocxl_unmap_lpar(void __iomem *arva);
|
||||
void pnv_ocxl_tlb_invalidate(void __iomem *arva,
|
||||
unsigned long pid,
|
||||
unsigned long addr,
|
||||
unsigned long page_size);
|
||||
#endif /* _ASM_PNV_OCXL_H */
|
||||
|
||||
@@ -78,6 +78,9 @@
|
||||
|
||||
#define IMM_L(i) ((uintptr_t)(i) & 0xffff)
|
||||
#define IMM_DS(i) ((uintptr_t)(i) & 0xfffc)
|
||||
#define IMM_DQ(i) ((uintptr_t)(i) & 0xfff0)
|
||||
#define IMM_D0(i) (((uintptr_t)(i) >> 16) & 0x3ffff)
|
||||
#define IMM_D1(i) IMM_L(i)
|
||||
|
||||
/*
|
||||
* 16-bit immediate helper macros: HA() is for use with sign-extending instrs
|
||||
@@ -230,7 +233,6 @@
|
||||
#define PPC_INST_POPCNTB_MASK 0xfc0007fe
|
||||
#define PPC_INST_RFEBB 0x4c000124
|
||||
#define PPC_INST_RFID 0x4c000024
|
||||
#define PPC_INST_MFSPR 0x7c0002a6
|
||||
#define PPC_INST_MFSPR_DSCR 0x7c1102a6
|
||||
#define PPC_INST_MFSPR_DSCR_MASK 0xfc1ffffe
|
||||
#define PPC_INST_MTSPR_DSCR 0x7c1103a6
|
||||
@@ -295,6 +297,8 @@
|
||||
#define __PPC_XB(b) ((((b) & 0x1f) << 11) | (((b) & 0x20) >> 4))
|
||||
#define __PPC_XS(s) ((((s) & 0x1f) << 21) | (((s) & 0x20) >> 5))
|
||||
#define __PPC_XT(s) __PPC_XS(s)
|
||||
#define __PPC_XSP(s) ((((s) & 0x1e) | (((s) >> 5) & 0x1)) << 21)
|
||||
#define __PPC_XTP(s) __PPC_XSP(s)
|
||||
#define __PPC_T_TLB(t) (((t) & 0x3) << 21)
|
||||
#define __PPC_WC(w) (((w) & 0x3) << 21)
|
||||
#define __PPC_WS(w) (((w) & 0x1f) << 11)
|
||||
@@ -395,6 +399,14 @@
|
||||
#define PPC_RAW_XVCPSGNDP(t, a, b) ((0xf0000780 | VSX_XX3((t), (a), (b))))
|
||||
#define PPC_RAW_VPERMXOR(vrt, vra, vrb, vrc) \
|
||||
((0x1000002d | ___PPC_RT(vrt) | ___PPC_RA(vra) | ___PPC_RB(vrb) | (((vrc) & 0x1f) << 6)))
|
||||
#define PPC_RAW_LXVP(xtp, a, i) (0x18000000 | __PPC_XTP(xtp) | ___PPC_RA(a) | IMM_DQ(i))
|
||||
#define PPC_RAW_STXVP(xsp, a, i) (0x18000001 | __PPC_XSP(xsp) | ___PPC_RA(a) | IMM_DQ(i))
|
||||
#define PPC_RAW_LXVPX(xtp, a, b) (0x7c00029a | __PPC_XTP(xtp) | ___PPC_RA(a) | ___PPC_RB(b))
|
||||
#define PPC_RAW_STXVPX(xsp, a, b) (0x7c00039a | __PPC_XSP(xsp) | ___PPC_RA(a) | ___PPC_RB(b))
|
||||
#define PPC_RAW_PLXVP(xtp, i, a, pr) \
|
||||
((PPC_PREFIX_8LS | __PPC_PRFX_R(pr) | IMM_D0(i)) << 32 | (0xe8000000 | __PPC_XTP(xtp) | ___PPC_RA(a) | IMM_D1(i)))
|
||||
#define PPC_RAW_PSTXVP(xsp, i, a, pr) \
|
||||
((PPC_PREFIX_8LS | __PPC_PRFX_R(pr) | IMM_D0(i)) << 32 | (0xf8000000 | __PPC_XSP(xsp) | ___PPC_RA(a) | IMM_D1(i)))
|
||||
#define PPC_RAW_NAP (0x4c000364)
|
||||
#define PPC_RAW_SLEEP (0x4c0003a4)
|
||||
#define PPC_RAW_WINKLE (0x4c0003e4)
|
||||
@@ -507,6 +519,8 @@
|
||||
|
||||
#define PPC_RAW_NEG(d, a) (0x7c0000d0 | ___PPC_RT(d) | ___PPC_RA(a))
|
||||
|
||||
#define PPC_RAW_MFSPR(d, spr) (0x7c0002a6 | ___PPC_RT(d) | __PPC_SPR(spr))
|
||||
|
||||
/* Deal with instructions that older assemblers aren't aware of */
|
||||
#define PPC_BCCTR_FLUSH stringify_in_c(.long PPC_INST_BCCTR_FLUSH)
|
||||
#define PPC_CP_ABORT stringify_in_c(.long PPC_RAW_CP_ABORT)
|
||||
|
||||
@@ -251,6 +251,8 @@ n:
|
||||
|
||||
#define _GLOBAL_TOC(name) _GLOBAL(name)
|
||||
|
||||
#define DOTSYM(a) a
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -495,15 +497,9 @@ END_FTR_SECTION_NESTED(CPU_FTR_CELL_TB_BUG, CPU_FTR_CELL_TB_BUG, 96)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
#define RFI rfid
|
||||
#define MTMSRD(r) mtmsrd r
|
||||
#define MTMSR_EERI(reg) mtmsrd reg,1
|
||||
#else
|
||||
#ifndef CONFIG_40x
|
||||
#define RFI rfi
|
||||
#else
|
||||
#define RFI rfi; b . /* Prevent prefetch past rfi */
|
||||
#endif
|
||||
#define MTMSRD(r) mtmsr r
|
||||
#define MTMSR_EERI(reg) mtmsr reg
|
||||
#endif
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
* Copyright (C) 2001 PPC 64 Team, IBM Corp
|
||||
*/
|
||||
|
||||
#include <vdso/processor.h>
|
||||
|
||||
#include <asm/reg.h>
|
||||
|
||||
#ifdef CONFIG_VSX
|
||||
@@ -63,14 +65,6 @@ extern int _chrp_type;
|
||||
|
||||
#endif /* defined(__KERNEL__) && defined(CONFIG_PPC32) */
|
||||
|
||||
/* Macros for adjusting thread priority (hardware multi-threading) */
|
||||
#define HMT_very_low() asm volatile("or 31,31,31 # very low priority")
|
||||
#define HMT_low() asm volatile("or 1,1,1 # low priority")
|
||||
#define HMT_medium_low() asm volatile("or 6,6,6 # medium low priority")
|
||||
#define HMT_medium() asm volatile("or 2,2,2 # medium priority")
|
||||
#define HMT_medium_high() asm volatile("or 5,5,5 # medium high priority")
|
||||
#define HMT_high() asm volatile("or 3,3,3 # high priority")
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
@@ -170,8 +164,10 @@ struct thread_struct {
|
||||
#endif
|
||||
/* Debug Registers */
|
||||
struct debug_reg debug;
|
||||
#ifdef CONFIG_PPC_FPU_REGS
|
||||
struct thread_fp_state fp_state;
|
||||
struct thread_fp_state *fp_save_area;
|
||||
#endif
|
||||
int fpexc_mode; /* floating-point exception mode */
|
||||
unsigned int align_ctl; /* alignment handling control */
|
||||
#ifdef CONFIG_HAVE_HW_BREAKPOINT
|
||||
@@ -230,10 +226,6 @@ struct thread_struct {
|
||||
struct thread_vr_state ckvr_state; /* Checkpointed VR state */
|
||||
unsigned long ckvrsave; /* Checkpointed VRSAVE */
|
||||
#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
|
||||
#ifdef CONFIG_PPC_MEM_KEYS
|
||||
unsigned long amr;
|
||||
unsigned long iamr;
|
||||
#endif
|
||||
#ifdef CONFIG_KVM_BOOK3S_32_HANDLER
|
||||
void* kvm_shadow_vcpu; /* KVM internal data */
|
||||
#endif /* CONFIG_KVM_BOOK3S_32_HANDLER */
|
||||
@@ -344,7 +336,6 @@ static inline unsigned long __pack_fe01(unsigned int fpmode)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
#define cpu_relax() do { HMT_low(); HMT_medium(); barrier(); } while (0)
|
||||
|
||||
#define spin_begin() HMT_low()
|
||||
|
||||
@@ -363,8 +354,6 @@ do { \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
#define cpu_relax() barrier()
|
||||
#endif
|
||||
|
||||
/* Check that a certain kernel stack pointer is valid in task_struct p */
|
||||
@@ -398,20 +387,6 @@ static inline void prefetchw(const void *x)
|
||||
|
||||
#define HAVE_ARCH_PICK_MMAP_LAYOUT
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
static inline unsigned long get_clean_sp(unsigned long sp, int is_32)
|
||||
{
|
||||
if (is_32)
|
||||
return sp & 0x0ffffffffUL;
|
||||
return sp;
|
||||
}
|
||||
#else
|
||||
static inline unsigned long get_clean_sp(unsigned long sp, int is_32)
|
||||
{
|
||||
return sp;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* asm stubs */
|
||||
extern unsigned long isa300_idle_stop_noloss(unsigned long psscr_val);
|
||||
extern unsigned long isa300_idle_stop_mayloss(unsigned long psscr_val);
|
||||
|
||||
@@ -378,8 +378,8 @@ struct ps3_system_bus_driver {
|
||||
enum ps3_match_sub_id match_sub_id;
|
||||
struct device_driver core;
|
||||
int (*probe)(struct ps3_system_bus_device *);
|
||||
int (*remove)(struct ps3_system_bus_device *);
|
||||
int (*shutdown)(struct ps3_system_bus_device *);
|
||||
void (*remove)(struct ps3_system_bus_device *);
|
||||
void (*shutdown)(struct ps3_system_bus_device *);
|
||||
/* int (*suspend)(struct ps3_system_bus_device *, pm_message_t); */
|
||||
/* int (*resume)(struct ps3_system_bus_device *); */
|
||||
};
|
||||
|
||||
@@ -53,11 +53,19 @@ struct pt_regs
|
||||
#ifdef CONFIG_PPC64
|
||||
unsigned long ppr;
|
||||
#endif
|
||||
union {
|
||||
#ifdef CONFIG_PPC_KUAP
|
||||
unsigned long kuap;
|
||||
unsigned long kuap;
|
||||
#endif
|
||||
#ifdef CONFIG_PPC_PKEY
|
||||
unsigned long amr;
|
||||
#endif
|
||||
};
|
||||
#ifdef CONFIG_PPC_PKEY
|
||||
unsigned long iamr;
|
||||
#endif
|
||||
};
|
||||
unsigned long __pad[2]; /* Maintain 16 byte interrupt stack alignment */
|
||||
unsigned long __pad[4]; /* Maintain 16 byte interrupt stack alignment */
|
||||
};
|
||||
};
|
||||
#endif
|
||||
@@ -171,12 +179,6 @@ static inline void regs_set_return_value(struct pt_regs *regs, unsigned long rc)
|
||||
set_thread_flag(TIF_NOERROR); \
|
||||
} while(0)
|
||||
|
||||
struct task_struct;
|
||||
extern int ptrace_get_reg(struct task_struct *task, int regno,
|
||||
unsigned long *data);
|
||||
extern int ptrace_put_reg(struct task_struct *task, int regno,
|
||||
unsigned long data);
|
||||
|
||||
#define current_pt_regs() \
|
||||
((struct pt_regs *)((unsigned long)task_stack_page(current) + THREAD_SIZE) - 1)
|
||||
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#include <asm/reg_8xx.h>
|
||||
|
||||
#define MSR_SF_LG 63 /* Enable 64 bit mode */
|
||||
#define MSR_ISF_LG 61 /* Interrupt 64b mode valid on 630 */
|
||||
#define MSR_HV_LG 60 /* Hypervisor state */
|
||||
#define MSR_TS_T_LG 34 /* Trans Mem state: Transactional */
|
||||
#define MSR_TS_S_LG 33 /* Trans Mem state: Suspended */
|
||||
@@ -69,13 +68,11 @@
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
#define MSR_SF __MASK(MSR_SF_LG) /* Enable 64 bit mode */
|
||||
#define MSR_ISF __MASK(MSR_ISF_LG) /* Interrupt 64b mode valid on 630 */
|
||||
#define MSR_HV __MASK(MSR_HV_LG) /* Hypervisor state */
|
||||
#define MSR_S __MASK(MSR_S_LG) /* Secure state */
|
||||
#else
|
||||
/* so tests for these bits fail on 32-bit */
|
||||
#define MSR_SF 0
|
||||
#define MSR_ISF 0
|
||||
#define MSR_HV 0
|
||||
#define MSR_S 0
|
||||
#endif
|
||||
@@ -134,7 +131,7 @@
|
||||
#define MSR_64BIT MSR_SF
|
||||
|
||||
/* Server variant */
|
||||
#define __MSR (MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_ISF |MSR_HV)
|
||||
#define __MSR (MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_HV)
|
||||
#ifdef __BIG_ENDIAN__
|
||||
#define MSR_ __MSR
|
||||
#define MSR_IDLE (MSR_ME | MSR_SF | MSR_HV)
|
||||
@@ -864,6 +861,7 @@
|
||||
#define MMCR0_BHRBA 0x00200000UL /* BHRB Access allowed in userspace */
|
||||
#define MMCR0_EBE 0x00100000UL /* Event based branch enable */
|
||||
#define MMCR0_PMCC 0x000c0000UL /* PMC control */
|
||||
#define MMCR0_PMCCEXT ASM_CONST(0x00000200) /* PMCCEXT control */
|
||||
#define MMCR0_PMCC_U6 0x00080000UL /* PMC1-6 are R/W by user (PR) */
|
||||
#define MMCR0_PMC1CE 0x00008000UL /* PMC1 count enable*/
|
||||
#define MMCR0_PMCjCE ASM_CONST(0x00004000) /* PMCj count enable*/
|
||||
@@ -1203,7 +1201,7 @@
|
||||
#ifdef CONFIG_PPC_BOOK3S_32
|
||||
#define SPRN_SPRG_SCRATCH0 SPRN_SPRG0
|
||||
#define SPRN_SPRG_SCRATCH1 SPRN_SPRG1
|
||||
#define SPRN_SPRG_PGDIR SPRN_SPRG2
|
||||
#define SPRN_SPRG_SCRATCH2 SPRN_SPRG2
|
||||
#define SPRN_SPRG_603_LRU SPRN_SPRG4
|
||||
#endif
|
||||
|
||||
@@ -1232,14 +1230,9 @@
|
||||
#define SPRN_SPRG_WSCRATCH_MC SPRN_SPRG1
|
||||
#define SPRN_SPRG_RSCRATCH4 SPRN_SPRG7R
|
||||
#define SPRN_SPRG_WSCRATCH4 SPRN_SPRG7W
|
||||
#ifdef CONFIG_E200
|
||||
#define SPRN_SPRG_RSCRATCH_DBG SPRN_SPRG6R
|
||||
#define SPRN_SPRG_WSCRATCH_DBG SPRN_SPRG6W
|
||||
#else
|
||||
#define SPRN_SPRG_RSCRATCH_DBG SPRN_SPRG9
|
||||
#define SPRN_SPRG_WSCRATCH_DBG SPRN_SPRG9
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PPC_8xx
|
||||
#define SPRN_SPRG_SCRATCH0 SPRN_SPRG0
|
||||
@@ -1419,37 +1412,6 @@ static inline void msr_check_and_clear(unsigned long bits)
|
||||
__msr_check_and_clear(bits);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_PPC_CELL) || defined(CONFIG_E500)
|
||||
#define mftb() ({unsigned long rval; \
|
||||
asm volatile( \
|
||||
"90: mfspr %0, %2;\n" \
|
||||
ASM_FTR_IFSET( \
|
||||
"97: cmpwi %0,0;\n" \
|
||||
" beq- 90b;\n", "", %1) \
|
||||
: "=r" (rval) \
|
||||
: "i" (CPU_FTR_CELL_TB_BUG), "i" (SPRN_TBRL) : "cr0"); \
|
||||
rval;})
|
||||
#elif defined(CONFIG_PPC_8xx)
|
||||
#define mftb() ({unsigned long rval; \
|
||||
asm volatile("mftbl %0" : "=r" (rval)); rval;})
|
||||
#else
|
||||
#define mftb() ({unsigned long rval; \
|
||||
asm volatile("mfspr %0, %1" : \
|
||||
"=r" (rval) : "i" (SPRN_TBRL)); rval;})
|
||||
#endif /* !CONFIG_PPC_CELL */
|
||||
|
||||
#if defined(CONFIG_PPC_8xx)
|
||||
#define mftbu() ({unsigned long rval; \
|
||||
asm volatile("mftbu %0" : "=r" (rval)); rval;})
|
||||
#else
|
||||
#define mftbu() ({unsigned long rval; \
|
||||
asm volatile("mfspr %0, %1" : "=r" (rval) : \
|
||||
"i" (SPRN_TBRU)); rval;})
|
||||
#endif
|
||||
|
||||
#define mttbl(v) asm volatile("mttbl %0":: "r"(v))
|
||||
#define mttbu(v) asm volatile("mttbu %0":: "r"(v))
|
||||
|
||||
#ifdef CONFIG_PPC32
|
||||
#define mfsrin(v) ({unsigned int rval; \
|
||||
asm volatile("mfsrin %0,%1" : "=r" (rval) : "r" (v)); \
|
||||
|
||||
@@ -281,18 +281,6 @@
|
||||
#define MSRP_PMMP 0x00000004 /* Protect MSR[PMM] */
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_E200
|
||||
#define MCSR_MCP 0x80000000UL /* Machine Check Input Pin */
|
||||
#define MCSR_CP_PERR 0x20000000UL /* Cache Push Parity Error */
|
||||
#define MCSR_CPERR 0x10000000UL /* Cache Parity Error */
|
||||
#define MCSR_EXCP_ERR 0x08000000UL /* ISI, ITLB, or Bus Error on 1st insn
|
||||
fetch for an exception handler */
|
||||
#define MCSR_BUS_IRERR 0x00000010UL /* Read Bus Error on instruction fetch*/
|
||||
#define MCSR_BUS_DRERR 0x00000008UL /* Read Bus Error on data load */
|
||||
#define MCSR_BUS_WRERR 0x00000004UL /* Write Bus Error on buffered
|
||||
store or cache line push */
|
||||
#endif
|
||||
|
||||
/* Bit definitions for the HID1 */
|
||||
#ifdef CONFIG_E500
|
||||
/* e500v1/v2 */
|
||||
|
||||
@@ -23,14 +23,6 @@ struct rtas_t {
|
||||
struct device_node *dev; /* virtual address pointer */
|
||||
};
|
||||
|
||||
struct rtas_suspend_me_data {
|
||||
atomic_t working; /* number of cpus accessing this struct */
|
||||
atomic_t done;
|
||||
int token; /* ibm,suspend-me */
|
||||
atomic_t error;
|
||||
struct completion *complete; /* wait on this until working == 0 */
|
||||
};
|
||||
|
||||
struct rtas_error_log {
|
||||
/* Byte 0 */
|
||||
u8 byte0; /* Architectural version */
|
||||
|
||||
@@ -23,11 +23,16 @@
|
||||
#define RTAS_RMOBUF_MAX (64 * 1024)
|
||||
|
||||
/* RTAS return status codes */
|
||||
#define RTAS_NOT_SUSPENDABLE -9004
|
||||
#define RTAS_BUSY -2 /* RTAS Busy */
|
||||
#define RTAS_EXTENDED_DELAY_MIN 9900
|
||||
#define RTAS_EXTENDED_DELAY_MAX 9905
|
||||
|
||||
/* statuses specific to ibm,suspend-me */
|
||||
#define RTAS_SUSPEND_ABORTED 9000 /* Suspension aborted */
|
||||
#define RTAS_NOT_SUSPENDABLE -9004 /* Partition not suspendable */
|
||||
#define RTAS_THREADS_ACTIVE -9005 /* Multiple processor threads active */
|
||||
#define RTAS_OUTSTANDING_COPROC -9006 /* Outstanding coprocessor operations */
|
||||
|
||||
/*
|
||||
* In general to call RTAS use rtas_token("string") to lookup
|
||||
* an RTAS token for the given string (e.g. "event-scan").
|
||||
@@ -242,6 +247,7 @@ extern void __noreturn rtas_restart(char *cmd);
|
||||
extern void rtas_power_off(void);
|
||||
extern void __noreturn rtas_halt(void);
|
||||
extern void rtas_os_term(char *str);
|
||||
void rtas_activate_firmware(void);
|
||||
extern int rtas_get_sensor(int sensor, int index, int *state);
|
||||
extern int rtas_get_sensor_fast(int sensor, int index, int *state);
|
||||
extern int rtas_get_power_level(int powerdomain, int *level);
|
||||
@@ -250,9 +256,7 @@ extern bool rtas_indicator_present(int token, int *maxindex);
|
||||
extern int rtas_set_indicator(int indicator, int index, int new_value);
|
||||
extern int rtas_set_indicator_fast(int indicator, int index, int new_value);
|
||||
extern void rtas_progress(char *s, unsigned short hex);
|
||||
extern int rtas_suspend_cpu(struct rtas_suspend_me_data *data);
|
||||
extern int rtas_suspend_last_cpu(struct rtas_suspend_me_data *data);
|
||||
extern int rtas_ibm_suspend_me(u64 handle);
|
||||
int rtas_ibm_suspend_me(int *fw_status);
|
||||
|
||||
struct rtc_time;
|
||||
extern time64_t rtas_get_boot_time(void);
|
||||
@@ -272,8 +276,13 @@ extern time64_t last_rtas_event;
|
||||
extern int clobbering_unread_rtas_event(void);
|
||||
extern int pseries_devicetree_update(s32 scope);
|
||||
extern void post_mobility_fixup(void);
|
||||
int rtas_syscall_dispatch_ibm_suspend_me(u64 handle);
|
||||
#else
|
||||
static inline int clobbering_unread_rtas_event(void) { return 0; }
|
||||
static inline int rtas_syscall_dispatch_ibm_suspend_me(u64 handle)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PPC_RTAS_DAEMON
|
||||
|
||||
@@ -134,6 +134,7 @@ static inline struct cpumask *cpu_smallcore_mask(int cpu)
|
||||
extern int cpu_to_core_id(int cpu);
|
||||
|
||||
extern bool has_big_cores;
|
||||
extern bool thread_group_shares_l2;
|
||||
|
||||
#define cpu_smt_mask cpu_smt_mask
|
||||
#ifdef CONFIG_SCHED_SMT
|
||||
@@ -187,6 +188,7 @@ extern void __cpu_die(unsigned int cpu);
|
||||
/* for UP */
|
||||
#define hard_smp_processor_id() get_hard_smp_processor_id(0)
|
||||
#define smp_setup_cpu_maps()
|
||||
#define thread_group_shares_l2 0
|
||||
static inline void inhibit_secondary_onlining(void) {}
|
||||
static inline void uninhibit_secondary_onlining(void) {}
|
||||
static inline const struct cpumask *cpu_sibling_mask(int cpu)
|
||||
@@ -199,6 +201,10 @@ static inline const struct cpumask *cpu_smallcore_mask(int cpu)
|
||||
return cpumask_of(cpu);
|
||||
}
|
||||
|
||||
static inline const struct cpumask *cpu_l2_cache_mask(int cpu)
|
||||
{
|
||||
return cpumask_of(cpu);
|
||||
}
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
|
||||
@@ -77,10 +77,8 @@ struct thread_info {
|
||||
/* how to get the thread information struct from C */
|
||||
extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src);
|
||||
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
void arch_setup_new_exec(void);
|
||||
#define arch_setup_new_exec arch_setup_new_exec
|
||||
#endif
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
#include <asm/processor.h>
|
||||
#include <asm/cpu_has_feature.h>
|
||||
#include <asm/vdso/timebase.h>
|
||||
|
||||
/* time.c */
|
||||
extern unsigned long tb_ticks_per_jiffy;
|
||||
@@ -38,44 +39,14 @@ struct div_result {
|
||||
u64 result_low;
|
||||
};
|
||||
|
||||
/* For compatibility, get_tbl() is defined as get_tb() on ppc64 */
|
||||
static inline unsigned long get_tbl(void)
|
||||
{
|
||||
return mftb();
|
||||
}
|
||||
|
||||
static inline u64 get_vtb(void)
|
||||
{
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
if (cpu_has_feature(CPU_FTR_ARCH_207S))
|
||||
return mfspr(SPRN_VTB);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline u64 get_tb(void)
|
||||
{
|
||||
unsigned int tbhi, tblo, tbhi2;
|
||||
|
||||
if (IS_ENABLED(CONFIG_PPC64))
|
||||
return mftb();
|
||||
|
||||
do {
|
||||
tbhi = mftbu();
|
||||
tblo = mftb();
|
||||
tbhi2 = mftbu();
|
||||
} while (tbhi != tbhi2);
|
||||
|
||||
return ((u64)tbhi << 32) | tblo;
|
||||
}
|
||||
|
||||
static inline void set_tb(unsigned int upper, unsigned int lower)
|
||||
{
|
||||
mtspr(SPRN_TBWL, 0);
|
||||
mtspr(SPRN_TBWU, upper);
|
||||
mtspr(SPRN_TBWL, lower);
|
||||
}
|
||||
|
||||
/* Accessor functions for the decrementer register.
|
||||
* The 4xx doesn't even have a decrementer. I tried to use the
|
||||
* generic timer interrupt code, which seems OK, with the 4xx PIT
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*/
|
||||
|
||||
#include <asm/cputable.h>
|
||||
#include <asm/reg.h>
|
||||
#include <asm/vdso/timebase.h>
|
||||
|
||||
#define CLOCK_TICK_RATE 1024000 /* Underlying HZ */
|
||||
|
||||
|
||||
@@ -40,9 +40,6 @@ extern void tlb_flush(struct mmu_gather *tlb);
|
||||
/* Get the generic bits... */
|
||||
#include <asm-generic/tlb.h>
|
||||
|
||||
extern void flush_hash_entry(struct mm_struct *mm, pte_t *ptep,
|
||||
unsigned long address);
|
||||
|
||||
static inline void __tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep,
|
||||
unsigned long address)
|
||||
{
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __PPC64_VDSO_H__
|
||||
#define __PPC64_VDSO_H__
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
/* Default link addresses for the vDSOs */
|
||||
#define VDSO32_LBASE 0x0
|
||||
#define VDSO64_LBASE 0x0
|
||||
#ifndef _ASM_POWERPC_VDSO_H
|
||||
#define _ASM_POWERPC_VDSO_H
|
||||
|
||||
/* Default map addresses for 32bit vDSO */
|
||||
#define VDSO32_MBASE 0x100000
|
||||
@@ -15,10 +9,17 @@
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
/* Offsets relative to thread->vdso_base */
|
||||
extern unsigned long vdso64_rt_sigtramp;
|
||||
extern unsigned long vdso32_sigtramp;
|
||||
extern unsigned long vdso32_rt_sigtramp;
|
||||
#ifdef CONFIG_PPC64
|
||||
#include <generated/vdso64-offsets.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_VDSO32
|
||||
#include <generated/vdso32-offsets.h>
|
||||
#endif
|
||||
|
||||
#define VDSO64_SYMBOL(base, name) ((unsigned long)(base) + (vdso64_offset_##name))
|
||||
|
||||
#define VDSO32_SYMBOL(base, name) ((unsigned long)(base) + (vdso32_offset_##name))
|
||||
|
||||
int vdso_getcpu_init(void);
|
||||
|
||||
@@ -51,6 +52,4 @@ int vdso_getcpu_init(void);
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* __PPC64_VDSO_H__ */
|
||||
#endif /* _ASM_POWERPC_VDSO_H */
|
||||
|
||||
7
arch/powerpc/include/asm/vdso/clocksource.h
Normal file
7
arch/powerpc/include/asm/vdso/clocksource.h
Normal file
@@ -0,0 +1,7 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _ASM_POWERPC_VDSO_CLOCKSOURCE_H
|
||||
#define _ASM_POWERPC_VDSO_CLOCKSOURCE_H
|
||||
|
||||
#define VDSO_ARCH_CLOCKMODES VDSO_CLOCKMODE_ARCHTIMER
|
||||
|
||||
#endif
|
||||
201
arch/powerpc/include/asm/vdso/gettimeofday.h
Normal file
201
arch/powerpc/include/asm/vdso/gettimeofday.h
Normal file
@@ -0,0 +1,201 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _ASM_POWERPC_VDSO_GETTIMEOFDAY_H
|
||||
#define _ASM_POWERPC_VDSO_GETTIMEOFDAY_H
|
||||
|
||||
#ifdef __ASSEMBLY__
|
||||
|
||||
#include <asm/ppc_asm.h>
|
||||
|
||||
/*
|
||||
* The macros sets two stack frames, one for the caller and one for the callee
|
||||
* because there are no requirement for the caller to set a stack frame when
|
||||
* calling VDSO so it may have omitted to set one, especially on PPC64
|
||||
*/
|
||||
|
||||
.macro cvdso_call funct
|
||||
.cfi_startproc
|
||||
PPC_STLU r1, -PPC_MIN_STKFRM(r1)
|
||||
mflr r0
|
||||
.cfi_register lr, r0
|
||||
PPC_STLU r1, -PPC_MIN_STKFRM(r1)
|
||||
PPC_STL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1)
|
||||
#ifdef __powerpc64__
|
||||
PPC_STL r2, PPC_MIN_STKFRM + STK_GOT(r1)
|
||||
#endif
|
||||
get_datapage r5
|
||||
addi r5, r5, VDSO_DATA_OFFSET
|
||||
bl DOTSYM(\funct)
|
||||
PPC_LL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1)
|
||||
#ifdef __powerpc64__
|
||||
PPC_LL r2, PPC_MIN_STKFRM + STK_GOT(r1)
|
||||
#endif
|
||||
cmpwi r3, 0
|
||||
mtlr r0
|
||||
.cfi_restore lr
|
||||
addi r1, r1, 2 * PPC_MIN_STKFRM
|
||||
crclr so
|
||||
beqlr+
|
||||
crset so
|
||||
neg r3, r3
|
||||
blr
|
||||
.cfi_endproc
|
||||
.endm
|
||||
|
||||
.macro cvdso_call_time funct
|
||||
.cfi_startproc
|
||||
PPC_STLU r1, -PPC_MIN_STKFRM(r1)
|
||||
mflr r0
|
||||
.cfi_register lr, r0
|
||||
PPC_STLU r1, -PPC_MIN_STKFRM(r1)
|
||||
PPC_STL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1)
|
||||
#ifdef __powerpc64__
|
||||
PPC_STL r2, PPC_MIN_STKFRM + STK_GOT(r1)
|
||||
#endif
|
||||
get_datapage r4
|
||||
addi r4, r4, VDSO_DATA_OFFSET
|
||||
bl DOTSYM(\funct)
|
||||
PPC_LL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1)
|
||||
#ifdef __powerpc64__
|
||||
PPC_LL r2, PPC_MIN_STKFRM + STK_GOT(r1)
|
||||
#endif
|
||||
crclr so
|
||||
mtlr r0
|
||||
.cfi_restore lr
|
||||
addi r1, r1, 2 * PPC_MIN_STKFRM
|
||||
blr
|
||||
.cfi_endproc
|
||||
.endm
|
||||
|
||||
#else
|
||||
|
||||
#include <asm/vdso/timebase.h>
|
||||
#include <asm/barrier.h>
|
||||
#include <asm/unistd.h>
|
||||
#include <uapi/linux/time.h>
|
||||
|
||||
#define VDSO_HAS_CLOCK_GETRES 1
|
||||
|
||||
#define VDSO_HAS_TIME 1
|
||||
|
||||
static __always_inline int do_syscall_2(const unsigned long _r0, const unsigned long _r3,
|
||||
const unsigned long _r4)
|
||||
{
|
||||
register long r0 asm("r0") = _r0;
|
||||
register unsigned long r3 asm("r3") = _r3;
|
||||
register unsigned long r4 asm("r4") = _r4;
|
||||
register int ret asm ("r3");
|
||||
|
||||
asm volatile(
|
||||
" sc\n"
|
||||
" bns+ 1f\n"
|
||||
" neg %0, %0\n"
|
||||
"1:\n"
|
||||
: "=r" (ret), "+r" (r4), "+r" (r0)
|
||||
: "r" (r3)
|
||||
: "memory", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "cr0", "ctr");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
int gettimeofday_fallback(struct __kernel_old_timeval *_tv, struct timezone *_tz)
|
||||
{
|
||||
return do_syscall_2(__NR_gettimeofday, (unsigned long)_tv, (unsigned long)_tz);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
int clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
|
||||
{
|
||||
return do_syscall_2(__NR_clock_gettime, _clkid, (unsigned long)_ts);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
int clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
|
||||
{
|
||||
return do_syscall_2(__NR_clock_getres, _clkid, (unsigned long)_ts);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_VDSO32
|
||||
|
||||
#define BUILD_VDSO32 1
|
||||
|
||||
static __always_inline
|
||||
int clock_gettime32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
|
||||
{
|
||||
return do_syscall_2(__NR_clock_gettime, _clkid, (unsigned long)_ts);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
int clock_getres32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
|
||||
{
|
||||
return do_syscall_2(__NR_clock_getres, _clkid, (unsigned long)_ts);
|
||||
}
|
||||
#endif
|
||||
|
||||
static __always_inline u64 __arch_get_hw_counter(s32 clock_mode,
|
||||
const struct vdso_data *vd)
|
||||
{
|
||||
return get_tb();
|
||||
}
|
||||
|
||||
const struct vdso_data *__arch_get_vdso_data(void);
|
||||
|
||||
static inline bool vdso_clocksource_ok(const struct vdso_data *vd)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#define vdso_clocksource_ok vdso_clocksource_ok
|
||||
|
||||
/*
|
||||
* powerpc specific delta calculation.
|
||||
*
|
||||
* This variant removes the masking of the subtraction because the
|
||||
* clocksource mask of all VDSO capable clocksources on powerpc is U64_MAX
|
||||
* which would result in a pointless operation. The compiler cannot
|
||||
* optimize it away as the mask comes from the vdso data and is not compile
|
||||
* time constant.
|
||||
*/
|
||||
static __always_inline u64 vdso_calc_delta(u64 cycles, u64 last, u64 mask, u32 mult)
|
||||
{
|
||||
return (cycles - last) * mult;
|
||||
}
|
||||
#define vdso_calc_delta vdso_calc_delta
|
||||
|
||||
#ifndef __powerpc64__
|
||||
static __always_inline u64 vdso_shift_ns(u64 ns, unsigned long shift)
|
||||
{
|
||||
u32 hi = ns >> 32;
|
||||
u32 lo = ns;
|
||||
|
||||
lo >>= shift;
|
||||
lo |= hi << (32 - shift);
|
||||
hi >>= shift;
|
||||
|
||||
if (likely(hi == 0))
|
||||
return lo;
|
||||
|
||||
return ((u64)hi << 32) | lo;
|
||||
}
|
||||
#define vdso_shift_ns vdso_shift_ns
|
||||
#endif
|
||||
|
||||
#ifdef __powerpc64__
|
||||
int __c_kernel_clock_gettime(clockid_t clock, struct __kernel_timespec *ts,
|
||||
const struct vdso_data *vd);
|
||||
int __c_kernel_clock_getres(clockid_t clock_id, struct __kernel_timespec *res,
|
||||
const struct vdso_data *vd);
|
||||
#else
|
||||
int __c_kernel_clock_gettime(clockid_t clock, struct old_timespec32 *ts,
|
||||
const struct vdso_data *vd);
|
||||
int __c_kernel_clock_gettime64(clockid_t clock, struct __kernel_timespec *ts,
|
||||
const struct vdso_data *vd);
|
||||
int __c_kernel_clock_getres(clockid_t clock_id, struct old_timespec32 *res,
|
||||
const struct vdso_data *vd);
|
||||
#endif
|
||||
int __c_kernel_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz,
|
||||
const struct vdso_data *vd);
|
||||
__kernel_old_time_t __c_kernel_time(__kernel_old_time_t *time,
|
||||
const struct vdso_data *vd);
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* _ASM_POWERPC_VDSO_GETTIMEOFDAY_H */
|
||||
23
arch/powerpc/include/asm/vdso/processor.h
Normal file
23
arch/powerpc/include/asm/vdso/processor.h
Normal file
@@ -0,0 +1,23 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
#ifndef _ASM_POWERPC_VDSO_PROCESSOR_H
|
||||
#define _ASM_POWERPC_VDSO_PROCESSOR_H
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
/* Macros for adjusting thread priority (hardware multi-threading) */
|
||||
#define HMT_very_low() asm volatile("or 31, 31, 31 # very low priority")
|
||||
#define HMT_low() asm volatile("or 1, 1, 1 # low priority")
|
||||
#define HMT_medium_low() asm volatile("or 6, 6, 6 # medium low priority")
|
||||
#define HMT_medium() asm volatile("or 2, 2, 2 # medium priority")
|
||||
#define HMT_medium_high() asm volatile("or 5, 5, 5 # medium high priority")
|
||||
#define HMT_high() asm volatile("or 3, 3, 3 # high priority")
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
#define cpu_relax() do { HMT_low(); HMT_medium(); barrier(); } while (0)
|
||||
#else
|
||||
#define cpu_relax() barrier()
|
||||
#endif
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* _ASM_POWERPC_VDSO_PROCESSOR_H */
|
||||
79
arch/powerpc/include/asm/vdso/timebase.h
Normal file
79
arch/powerpc/include/asm/vdso/timebase.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Common timebase prototypes and such for all ppc machines.
|
||||
*/
|
||||
|
||||
#ifndef _ASM_POWERPC_VDSO_TIMEBASE_H
|
||||
#define _ASM_POWERPC_VDSO_TIMEBASE_H
|
||||
|
||||
#include <asm/reg.h>
|
||||
|
||||
/*
|
||||
* We use __powerpc64__ here because we want the compat VDSO to use the 32-bit
|
||||
* version below in the else case of the ifdef.
|
||||
*/
|
||||
#if defined(__powerpc64__) && (defined(CONFIG_PPC_CELL) || defined(CONFIG_E500))
|
||||
#define mftb() ({unsigned long rval; \
|
||||
asm volatile( \
|
||||
"90: mfspr %0, %2;\n" \
|
||||
ASM_FTR_IFSET( \
|
||||
"97: cmpwi %0,0;\n" \
|
||||
" beq- 90b;\n", "", %1) \
|
||||
: "=r" (rval) \
|
||||
: "i" (CPU_FTR_CELL_TB_BUG), "i" (SPRN_TBRL) : "cr0"); \
|
||||
rval;})
|
||||
#elif defined(CONFIG_PPC_8xx)
|
||||
#define mftb() ({unsigned long rval; \
|
||||
asm volatile("mftbl %0" : "=r" (rval)); rval;})
|
||||
#else
|
||||
#define mftb() ({unsigned long rval; \
|
||||
asm volatile("mfspr %0, %1" : \
|
||||
"=r" (rval) : "i" (SPRN_TBRL)); rval;})
|
||||
#endif /* !CONFIG_PPC_CELL */
|
||||
|
||||
#if defined(CONFIG_PPC_8xx)
|
||||
#define mftbu() ({unsigned long rval; \
|
||||
asm volatile("mftbu %0" : "=r" (rval)); rval;})
|
||||
#else
|
||||
#define mftbu() ({unsigned long rval; \
|
||||
asm volatile("mfspr %0, %1" : "=r" (rval) : \
|
||||
"i" (SPRN_TBRU)); rval;})
|
||||
#endif
|
||||
|
||||
#define mttbl(v) asm volatile("mttbl %0":: "r"(v))
|
||||
#define mttbu(v) asm volatile("mttbu %0":: "r"(v))
|
||||
|
||||
/* For compatibility, get_tbl() is defined as get_tb() on ppc64 */
|
||||
static inline unsigned long get_tbl(void)
|
||||
{
|
||||
return mftb();
|
||||
}
|
||||
|
||||
static inline u64 get_tb(void)
|
||||
{
|
||||
unsigned int tbhi, tblo, tbhi2;
|
||||
|
||||
/*
|
||||
* We use __powerpc64__ here not CONFIG_PPC64 because we want the compat
|
||||
* VDSO to use the 32-bit compatible version in the while loop below.
|
||||
*/
|
||||
if (__is_defined(__powerpc64__))
|
||||
return mftb();
|
||||
|
||||
do {
|
||||
tbhi = mftbu();
|
||||
tblo = mftb();
|
||||
tbhi2 = mftbu();
|
||||
} while (tbhi != tbhi2);
|
||||
|
||||
return ((u64)tbhi << 32) | tblo;
|
||||
}
|
||||
|
||||
static inline void set_tb(unsigned int upper, unsigned int lower)
|
||||
{
|
||||
mtspr(SPRN_TBWL, 0);
|
||||
mtspr(SPRN_TBWU, upper);
|
||||
mtspr(SPRN_TBWL, lower);
|
||||
}
|
||||
|
||||
#endif /* _ASM_POWERPC_VDSO_TIMEBASE_H */
|
||||
25
arch/powerpc/include/asm/vdso/vsyscall.h
Normal file
25
arch/powerpc/include/asm/vdso/vsyscall.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _ASM_POWERPC_VDSO_VSYSCALL_H
|
||||
#define _ASM_POWERPC_VDSO_VSYSCALL_H
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <linux/timekeeper_internal.h>
|
||||
#include <asm/vdso_datapage.h>
|
||||
|
||||
/*
|
||||
* Update the vDSO data page to keep in sync with kernel timekeeping.
|
||||
*/
|
||||
static __always_inline
|
||||
struct vdso_data *__arch_get_k_vdso_data(void)
|
||||
{
|
||||
return vdso_data->data;
|
||||
}
|
||||
#define __arch_get_k_vdso_data __arch_get_k_vdso_data
|
||||
|
||||
/* The asm-generic header needs to be included after the definitions above */
|
||||
#include <asm-generic/vdso/vsyscall.h>
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
#endif /* _ASM_POWERPC_VDSO_VSYSCALL_H */
|
||||
@@ -36,6 +36,7 @@
|
||||
|
||||
#include <linux/unistd.h>
|
||||
#include <linux/time.h>
|
||||
#include <vdso/datapage.h>
|
||||
|
||||
#define SYSCALL_MAP_SIZE ((NR_syscalls + 31) / 32)
|
||||
|
||||
@@ -45,7 +46,7 @@
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
|
||||
struct vdso_data {
|
||||
struct vdso_arch_data {
|
||||
__u8 eye_catcher[16]; /* Eyecatcher: SYSTEMCFG:PPC64 0x00 */
|
||||
struct { /* Systemcfg version numbers */
|
||||
__u32 major; /* Major number 0x10 */
|
||||
@@ -59,13 +60,13 @@ struct vdso_data {
|
||||
__u32 processor; /* Processor type 0x1C */
|
||||
__u64 processorCount; /* # of physical processors 0x20 */
|
||||
__u64 physicalMemorySize; /* Size of real memory(B) 0x28 */
|
||||
__u64 tb_orig_stamp; /* Timebase at boot 0x30 */
|
||||
__u64 tb_orig_stamp; /* (NU) Timebase at boot 0x30 */
|
||||
__u64 tb_ticks_per_sec; /* Timebase tics / sec 0x38 */
|
||||
__u64 tb_to_xs; /* Inverse of TB to 2^20 0x40 */
|
||||
__u64 stamp_xsec; /* 0x48 */
|
||||
__u64 tb_update_count; /* Timebase atomicity ctr 0x50 */
|
||||
__u32 tz_minuteswest; /* Minutes west of Greenwich 0x58 */
|
||||
__u32 tz_dsttime; /* Type of dst correction 0x5C */
|
||||
__u64 tb_to_xs; /* (NU) Inverse of TB to 2^20 0x40 */
|
||||
__u64 stamp_xsec; /* (NU) 0x48 */
|
||||
__u64 tb_update_count; /* (NU) Timebase atomicity ctr 0x50 */
|
||||
__u32 tz_minuteswest; /* (NU) Min. west of Greenwich 0x58 */
|
||||
__u32 tz_dsttime; /* (NU) Type of dst correction 0x5C */
|
||||
__u32 dcache_size; /* L1 d-cache size 0x60 */
|
||||
__u32 dcache_line_size; /* L1 d-cache line size 0x64 */
|
||||
__u32 icache_size; /* L1 i-cache size 0x68 */
|
||||
@@ -78,14 +79,10 @@ struct vdso_data {
|
||||
__u32 icache_block_size; /* L1 i-cache block size */
|
||||
__u32 dcache_log_block_size; /* L1 d-cache log block size */
|
||||
__u32 icache_log_block_size; /* L1 i-cache log block size */
|
||||
__u32 stamp_sec_fraction; /* fractional seconds of stamp_xtime */
|
||||
__s32 wtom_clock_nsec; /* Wall to monotonic clock nsec */
|
||||
__s64 wtom_clock_sec; /* Wall to monotonic clock sec */
|
||||
__s64 stamp_xtime_sec; /* xtime secs as at tb_orig_stamp */
|
||||
__s64 stamp_xtime_nsec; /* xtime nsecs as at tb_orig_stamp */
|
||||
__u32 hrtimer_res; /* hrtimer resolution */
|
||||
__u32 syscall_map_64[SYSCALL_MAP_SIZE]; /* map of syscalls */
|
||||
__u32 syscall_map_32[SYSCALL_MAP_SIZE]; /* map of syscalls */
|
||||
__u32 syscall_map[SYSCALL_MAP_SIZE]; /* Map of syscalls */
|
||||
__u32 compat_syscall_map[SYSCALL_MAP_SIZE]; /* Map of compat syscalls */
|
||||
|
||||
struct vdso_data data[CS_BASES];
|
||||
};
|
||||
|
||||
#else /* CONFIG_PPC64 */
|
||||
@@ -93,35 +90,27 @@ struct vdso_data {
|
||||
/*
|
||||
* And here is the simpler 32 bits version
|
||||
*/
|
||||
struct vdso_data {
|
||||
__u64 tb_orig_stamp; /* Timebase at boot 0x30 */
|
||||
struct vdso_arch_data {
|
||||
__u64 tb_ticks_per_sec; /* Timebase tics / sec 0x38 */
|
||||
__u64 tb_to_xs; /* Inverse of TB to 2^20 0x40 */
|
||||
__u64 stamp_xsec; /* 0x48 */
|
||||
__u32 tb_update_count; /* Timebase atomicity ctr 0x50 */
|
||||
__u32 tz_minuteswest; /* Minutes west of Greenwich 0x58 */
|
||||
__u32 tz_dsttime; /* Type of dst correction 0x5C */
|
||||
__s32 wtom_clock_sec; /* Wall to monotonic clock */
|
||||
__s32 wtom_clock_nsec;
|
||||
__s32 stamp_xtime_sec; /* xtime seconds as at tb_orig_stamp */
|
||||
__s32 stamp_xtime_nsec; /* xtime nsecs as at tb_orig_stamp */
|
||||
__u32 stamp_sec_fraction; /* fractional seconds of stamp_xtime */
|
||||
__u32 hrtimer_res; /* hrtimer resolution */
|
||||
__u32 syscall_map_32[SYSCALL_MAP_SIZE]; /* map of syscalls */
|
||||
__u32 syscall_map[SYSCALL_MAP_SIZE]; /* Map of syscalls */
|
||||
__u32 compat_syscall_map[0]; /* No compat syscalls on PPC32 */
|
||||
struct vdso_data data[CS_BASES];
|
||||
};
|
||||
|
||||
#endif /* CONFIG_PPC64 */
|
||||
|
||||
extern struct vdso_data *vdso_data;
|
||||
extern struct vdso_arch_data *vdso_data;
|
||||
|
||||
#else /* __ASSEMBLY__ */
|
||||
|
||||
.macro get_datapage ptr, tmp
|
||||
.macro get_datapage ptr
|
||||
bcl 20, 31, .+4
|
||||
999:
|
||||
mflr \ptr
|
||||
addi \ptr, \ptr, (__kernel_datapage_offset - (.-4))@l
|
||||
lwz \tmp, 0(\ptr)
|
||||
add \ptr, \tmp, \ptr
|
||||
#if CONFIG_PPC_PAGE_SHIFT > 14
|
||||
addis \ptr, \ptr, (_vdso_datapage - 999b)@ha
|
||||
#endif
|
||||
addi \ptr, \ptr, (_vdso_datapage - 999b)@l
|
||||
.endm
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
@@ -60,13 +60,13 @@ struct xive_irq_data {
|
||||
};
|
||||
#define XIVE_IRQ_FLAG_STORE_EOI 0x01
|
||||
#define XIVE_IRQ_FLAG_LSI 0x02
|
||||
#define XIVE_IRQ_FLAG_SHIFT_BUG 0x04
|
||||
#define XIVE_IRQ_FLAG_MASK_FW 0x08
|
||||
#define XIVE_IRQ_FLAG_EOI_FW 0x10
|
||||
/* #define XIVE_IRQ_FLAG_SHIFT_BUG 0x04 */ /* P9 DD1.0 workaround */
|
||||
/* #define XIVE_IRQ_FLAG_MASK_FW 0x08 */ /* P9 DD1.0 workaround */
|
||||
/* #define XIVE_IRQ_FLAG_EOI_FW 0x10 */ /* P9 DD1.0 workaround */
|
||||
#define XIVE_IRQ_FLAG_H_INT_ESB 0x20
|
||||
|
||||
/* Special flag set by KVM for excalation interrupts */
|
||||
#define XIVE_IRQ_NO_EOI 0x80
|
||||
#define XIVE_IRQ_FLAG_NO_EOI 0x80
|
||||
|
||||
#define XIVE_INVALID_CHIP_ID -1
|
||||
|
||||
|
||||
@@ -173,6 +173,9 @@ KCOV_INSTRUMENT_cputable.o := n
|
||||
KCOV_INSTRUMENT_setup_64.o := n
|
||||
KCOV_INSTRUMENT_paca.o := n
|
||||
|
||||
CFLAGS_setup_64.o += -fno-stack-protector
|
||||
CFLAGS_paca.o += -fno-stack-protector
|
||||
|
||||
extra-$(CONFIG_PPC_FPU) += fpu.o
|
||||
extra-$(CONFIG_ALTIVEC) += vector.o
|
||||
extra-$(CONFIG_PPC64) += entry_64.o
|
||||
|
||||
@@ -110,9 +110,11 @@ int main(void)
|
||||
#ifdef CONFIG_BOOKE
|
||||
OFFSET(THREAD_NORMSAVES, thread_struct, normsave[0]);
|
||||
#endif
|
||||
#ifdef CONFIG_PPC_FPU
|
||||
OFFSET(THREAD_FPEXC_MODE, thread_struct, fpexc_mode);
|
||||
OFFSET(THREAD_FPSTATE, thread_struct, fp_state.fpr);
|
||||
OFFSET(THREAD_FPSAVEAREA, thread_struct, fp_save_area);
|
||||
#endif
|
||||
OFFSET(FPSTATE_FPSCR, thread_fp_state, fpscr);
|
||||
OFFSET(THREAD_LOAD_FP, thread_struct, load_fp);
|
||||
#ifdef CONFIG_ALTIVEC
|
||||
@@ -354,10 +356,15 @@ int main(void)
|
||||
STACK_PT_REGS_OFFSET(_PPR, ppr);
|
||||
#endif /* CONFIG_PPC64 */
|
||||
|
||||
#ifdef CONFIG_PPC_PKEY
|
||||
STACK_PT_REGS_OFFSET(STACK_REGS_AMR, amr);
|
||||
STACK_PT_REGS_OFFSET(STACK_REGS_IAMR, iamr);
|
||||
#endif
|
||||
#ifdef CONFIG_PPC_KUAP
|
||||
STACK_PT_REGS_OFFSET(STACK_REGS_KUAP, kuap);
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(CONFIG_PPC32)
|
||||
#if defined(CONFIG_BOOKE) || defined(CONFIG_40x)
|
||||
DEFINE(EXC_LVL_SIZE, STACK_EXC_LVL_FRAME_SIZE);
|
||||
@@ -398,47 +405,18 @@ int main(void)
|
||||
#endif /* ! CONFIG_PPC64 */
|
||||
|
||||
/* datapage offsets for use by vdso */
|
||||
OFFSET(CFG_TB_ORIG_STAMP, vdso_data, tb_orig_stamp);
|
||||
OFFSET(CFG_TB_TICKS_PER_SEC, vdso_data, tb_ticks_per_sec);
|
||||
OFFSET(CFG_TB_TO_XS, vdso_data, tb_to_xs);
|
||||
OFFSET(CFG_TB_UPDATE_COUNT, vdso_data, tb_update_count);
|
||||
OFFSET(CFG_TZ_MINUTEWEST, vdso_data, tz_minuteswest);
|
||||
OFFSET(CFG_TZ_DSTTIME, vdso_data, tz_dsttime);
|
||||
OFFSET(CFG_SYSCALL_MAP32, vdso_data, syscall_map_32);
|
||||
OFFSET(WTOM_CLOCK_SEC, vdso_data, wtom_clock_sec);
|
||||
OFFSET(WTOM_CLOCK_NSEC, vdso_data, wtom_clock_nsec);
|
||||
OFFSET(STAMP_XTIME_SEC, vdso_data, stamp_xtime_sec);
|
||||
OFFSET(STAMP_XTIME_NSEC, vdso_data, stamp_xtime_nsec);
|
||||
OFFSET(STAMP_SEC_FRAC, vdso_data, stamp_sec_fraction);
|
||||
OFFSET(CLOCK_HRTIMER_RES, vdso_data, hrtimer_res);
|
||||
OFFSET(VDSO_DATA_OFFSET, vdso_arch_data, data);
|
||||
OFFSET(CFG_TB_TICKS_PER_SEC, vdso_arch_data, tb_ticks_per_sec);
|
||||
#ifdef CONFIG_PPC64
|
||||
OFFSET(CFG_ICACHE_BLOCKSZ, vdso_data, icache_block_size);
|
||||
OFFSET(CFG_DCACHE_BLOCKSZ, vdso_data, dcache_block_size);
|
||||
OFFSET(CFG_ICACHE_LOGBLOCKSZ, vdso_data, icache_log_block_size);
|
||||
OFFSET(CFG_DCACHE_LOGBLOCKSZ, vdso_data, dcache_log_block_size);
|
||||
OFFSET(CFG_SYSCALL_MAP64, vdso_data, syscall_map_64);
|
||||
OFFSET(TVAL64_TV_SEC, __kernel_old_timeval, tv_sec);
|
||||
OFFSET(TVAL64_TV_USEC, __kernel_old_timeval, tv_usec);
|
||||
OFFSET(CFG_ICACHE_BLOCKSZ, vdso_arch_data, icache_block_size);
|
||||
OFFSET(CFG_DCACHE_BLOCKSZ, vdso_arch_data, dcache_block_size);
|
||||
OFFSET(CFG_ICACHE_LOGBLOCKSZ, vdso_arch_data, icache_log_block_size);
|
||||
OFFSET(CFG_DCACHE_LOGBLOCKSZ, vdso_arch_data, dcache_log_block_size);
|
||||
OFFSET(CFG_SYSCALL_MAP64, vdso_arch_data, syscall_map);
|
||||
OFFSET(CFG_SYSCALL_MAP32, vdso_arch_data, compat_syscall_map);
|
||||
#else
|
||||
OFFSET(CFG_SYSCALL_MAP32, vdso_arch_data, syscall_map);
|
||||
#endif
|
||||
OFFSET(TSPC64_TV_SEC, __kernel_timespec, tv_sec);
|
||||
OFFSET(TSPC64_TV_NSEC, __kernel_timespec, tv_nsec);
|
||||
OFFSET(TVAL32_TV_SEC, old_timeval32, tv_sec);
|
||||
OFFSET(TVAL32_TV_USEC, old_timeval32, tv_usec);
|
||||
OFFSET(TSPC32_TV_SEC, old_timespec32, tv_sec);
|
||||
OFFSET(TSPC32_TV_NSEC, old_timespec32, tv_nsec);
|
||||
/* timeval/timezone offsets for use by vdso */
|
||||
OFFSET(TZONE_TZ_MINWEST, timezone, tz_minuteswest);
|
||||
OFFSET(TZONE_TZ_DSTTIME, timezone, tz_dsttime);
|
||||
|
||||
/* Other bits used by the vdso */
|
||||
DEFINE(CLOCK_REALTIME, CLOCK_REALTIME);
|
||||
DEFINE(CLOCK_MONOTONIC, CLOCK_MONOTONIC);
|
||||
DEFINE(CLOCK_REALTIME_COARSE, CLOCK_REALTIME_COARSE);
|
||||
DEFINE(CLOCK_MONOTONIC_COARSE, CLOCK_MONOTONIC_COARSE);
|
||||
DEFINE(CLOCK_MAX, CLOCK_TAI);
|
||||
DEFINE(NSEC_PER_SEC, NSEC_PER_SEC);
|
||||
DEFINE(EINVAL, EINVAL);
|
||||
DEFINE(KTIME_LOW_RES, KTIME_LOW_RES);
|
||||
|
||||
#ifdef CONFIG_BUG
|
||||
DEFINE(BUG_ENTRY_SIZE, sizeof(struct bug_entry));
|
||||
|
||||
@@ -655,11 +655,27 @@ static unsigned int index_dir_to_cpu(struct cache_index_dir *index)
|
||||
* On big-core systems, each core has two groups of CPUs each of which
|
||||
* has its own L1-cache. The thread-siblings which share l1-cache with
|
||||
* @cpu can be obtained via cpu_smallcore_mask().
|
||||
*
|
||||
* On some big-core systems, the L2 cache is shared only between some
|
||||
* groups of siblings. This is already parsed and encoded in
|
||||
* cpu_l2_cache_mask().
|
||||
*
|
||||
* TODO: cache_lookup_or_instantiate() needs to be made aware of the
|
||||
* "ibm,thread-groups" property so that cache->shared_cpu_map
|
||||
* reflects the correct siblings on platforms that have this
|
||||
* device-tree property. This helper function is only a stop-gap
|
||||
* solution so that we report the correct siblings to the
|
||||
* userspace via sysfs.
|
||||
*/
|
||||
static const struct cpumask *get_big_core_shared_cpu_map(int cpu, struct cache *cache)
|
||||
static const struct cpumask *get_shared_cpu_map(struct cache_index_dir *index, struct cache *cache)
|
||||
{
|
||||
if (cache->level == 1)
|
||||
return cpu_smallcore_mask(cpu);
|
||||
if (has_big_cores) {
|
||||
int cpu = index_dir_to_cpu(index);
|
||||
if (cache->level == 1)
|
||||
return cpu_smallcore_mask(cpu);
|
||||
if (cache->level == 2 && thread_group_shares_l2)
|
||||
return cpu_l2_cache_mask(cpu);
|
||||
}
|
||||
|
||||
return &cache->shared_cpu_map;
|
||||
}
|
||||
@@ -670,17 +686,11 @@ show_shared_cpumap(struct kobject *k, struct kobj_attribute *attr, char *buf, bo
|
||||
struct cache_index_dir *index;
|
||||
struct cache *cache;
|
||||
const struct cpumask *mask;
|
||||
int cpu;
|
||||
|
||||
index = kobj_to_cache_index_dir(k);
|
||||
cache = index->cache;
|
||||
|
||||
if (has_big_cores) {
|
||||
cpu = index_dir_to_cpu(index);
|
||||
mask = get_big_core_shared_cpu_map(cpu, cache);
|
||||
} else {
|
||||
mask = &cache->shared_cpu_map;
|
||||
}
|
||||
mask = get_shared_cpu_map(index, cache);
|
||||
|
||||
return cpumap_print_to_pagebuf(list, buf, mask);
|
||||
}
|
||||
|
||||
@@ -108,15 +108,6 @@ _GLOBAL(__setup_cpu_e6500)
|
||||
#endif /* CONFIG_PPC_E500MC */
|
||||
|
||||
#ifdef CONFIG_PPC32
|
||||
#ifdef CONFIG_E200
|
||||
_GLOBAL(__setup_cpu_e200)
|
||||
/* enable dedicated debug exception handling resources (Debug APU) */
|
||||
mfspr r3,SPRN_HID0
|
||||
ori r3,r3,HID0_DAPUEN@l
|
||||
mtspr SPRN_HID0,r3
|
||||
b __setup_e200_ivors
|
||||
#endif /* CONFIG_E200 */
|
||||
|
||||
#ifdef CONFIG_E500
|
||||
#ifndef CONFIG_PPC_E500MC
|
||||
_GLOBAL(__setup_cpu_e500v1)
|
||||
|
||||
@@ -1,252 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* This file contains low level CPU setup functions.
|
||||
* Copyright (C) 2003 Benjamin Herrenschmidt (benh@kernel.crashing.org)
|
||||
*/
|
||||
|
||||
#include <asm/processor.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/cputable.h>
|
||||
#include <asm/ppc_asm.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <asm/cache.h>
|
||||
#include <asm/book3s/64/mmu-hash.h>
|
||||
|
||||
/* Entry: r3 = crap, r4 = ptr to cputable entry
|
||||
*
|
||||
* Note that we can be called twice for pseudo-PVRs
|
||||
*/
|
||||
_GLOBAL(__setup_cpu_power7)
|
||||
mflr r11
|
||||
bl __init_hvmode_206
|
||||
mtlr r11
|
||||
beqlr
|
||||
li r0,0
|
||||
mtspr SPRN_LPID,r0
|
||||
LOAD_REG_IMMEDIATE(r0, PCR_MASK)
|
||||
mtspr SPRN_PCR,r0
|
||||
mfspr r3,SPRN_LPCR
|
||||
li r4,(LPCR_LPES1 >> LPCR_LPES_SH)
|
||||
bl __init_LPCR_ISA206
|
||||
mtlr r11
|
||||
blr
|
||||
|
||||
_GLOBAL(__restore_cpu_power7)
|
||||
mflr r11
|
||||
mfmsr r3
|
||||
rldicl. r0,r3,4,63
|
||||
beqlr
|
||||
li r0,0
|
||||
mtspr SPRN_LPID,r0
|
||||
LOAD_REG_IMMEDIATE(r0, PCR_MASK)
|
||||
mtspr SPRN_PCR,r0
|
||||
mfspr r3,SPRN_LPCR
|
||||
li r4,(LPCR_LPES1 >> LPCR_LPES_SH)
|
||||
bl __init_LPCR_ISA206
|
||||
mtlr r11
|
||||
blr
|
||||
|
||||
_GLOBAL(__setup_cpu_power8)
|
||||
mflr r11
|
||||
bl __init_FSCR
|
||||
bl __init_PMU
|
||||
bl __init_PMU_ISA207
|
||||
bl __init_hvmode_206
|
||||
mtlr r11
|
||||
beqlr
|
||||
li r0,0
|
||||
mtspr SPRN_LPID,r0
|
||||
LOAD_REG_IMMEDIATE(r0, PCR_MASK)
|
||||
mtspr SPRN_PCR,r0
|
||||
mfspr r3,SPRN_LPCR
|
||||
ori r3, r3, LPCR_PECEDH
|
||||
li r4,0 /* LPES = 0 */
|
||||
bl __init_LPCR_ISA206
|
||||
bl __init_HFSCR
|
||||
bl __init_PMU_HV
|
||||
bl __init_PMU_HV_ISA207
|
||||
mtlr r11
|
||||
blr
|
||||
|
||||
_GLOBAL(__restore_cpu_power8)
|
||||
mflr r11
|
||||
bl __init_FSCR
|
||||
bl __init_PMU
|
||||
bl __init_PMU_ISA207
|
||||
mfmsr r3
|
||||
rldicl. r0,r3,4,63
|
||||
mtlr r11
|
||||
beqlr
|
||||
li r0,0
|
||||
mtspr SPRN_LPID,r0
|
||||
LOAD_REG_IMMEDIATE(r0, PCR_MASK)
|
||||
mtspr SPRN_PCR,r0
|
||||
mfspr r3,SPRN_LPCR
|
||||
ori r3, r3, LPCR_PECEDH
|
||||
li r4,0 /* LPES = 0 */
|
||||
bl __init_LPCR_ISA206
|
||||
bl __init_HFSCR
|
||||
bl __init_PMU_HV
|
||||
bl __init_PMU_HV_ISA207
|
||||
mtlr r11
|
||||
blr
|
||||
|
||||
_GLOBAL(__setup_cpu_power10)
|
||||
mflr r11
|
||||
bl __init_FSCR_power10
|
||||
bl __init_PMU
|
||||
bl __init_PMU_ISA31
|
||||
b 1f
|
||||
|
||||
_GLOBAL(__setup_cpu_power9)
|
||||
mflr r11
|
||||
bl __init_FSCR_power9
|
||||
bl __init_PMU
|
||||
1: bl __init_hvmode_206
|
||||
mtlr r11
|
||||
beqlr
|
||||
li r0,0
|
||||
mtspr SPRN_PSSCR,r0
|
||||
mtspr SPRN_LPID,r0
|
||||
mtspr SPRN_PID,r0
|
||||
LOAD_REG_IMMEDIATE(r0, PCR_MASK)
|
||||
mtspr SPRN_PCR,r0
|
||||
mfspr r3,SPRN_LPCR
|
||||
LOAD_REG_IMMEDIATE(r4, LPCR_PECEDH | LPCR_PECE_HVEE | LPCR_HVICE | LPCR_HEIC)
|
||||
or r3, r3, r4
|
||||
LOAD_REG_IMMEDIATE(r4, LPCR_UPRT | LPCR_HR)
|
||||
andc r3, r3, r4
|
||||
li r4,0 /* LPES = 0 */
|
||||
bl __init_LPCR_ISA300
|
||||
bl __init_HFSCR
|
||||
bl __init_PMU_HV
|
||||
mtlr r11
|
||||
blr
|
||||
|
||||
_GLOBAL(__restore_cpu_power10)
|
||||
mflr r11
|
||||
bl __init_FSCR_power10
|
||||
bl __init_PMU
|
||||
bl __init_PMU_ISA31
|
||||
b 1f
|
||||
|
||||
_GLOBAL(__restore_cpu_power9)
|
||||
mflr r11
|
||||
bl __init_FSCR_power9
|
||||
bl __init_PMU
|
||||
1: mfmsr r3
|
||||
rldicl. r0,r3,4,63
|
||||
mtlr r11
|
||||
beqlr
|
||||
li r0,0
|
||||
mtspr SPRN_PSSCR,r0
|
||||
mtspr SPRN_LPID,r0
|
||||
mtspr SPRN_PID,r0
|
||||
LOAD_REG_IMMEDIATE(r0, PCR_MASK)
|
||||
mtspr SPRN_PCR,r0
|
||||
mfspr r3,SPRN_LPCR
|
||||
LOAD_REG_IMMEDIATE(r4, LPCR_PECEDH | LPCR_PECE_HVEE | LPCR_HVICE | LPCR_HEIC)
|
||||
or r3, r3, r4
|
||||
LOAD_REG_IMMEDIATE(r4, LPCR_UPRT | LPCR_HR)
|
||||
andc r3, r3, r4
|
||||
li r4,0 /* LPES = 0 */
|
||||
bl __init_LPCR_ISA300
|
||||
bl __init_HFSCR
|
||||
bl __init_PMU_HV
|
||||
mtlr r11
|
||||
blr
|
||||
|
||||
__init_hvmode_206:
|
||||
/* Disable CPU_FTR_HVMODE and exit if MSR:HV is not set */
|
||||
mfmsr r3
|
||||
rldicl. r0,r3,4,63
|
||||
bnelr
|
||||
ld r5,CPU_SPEC_FEATURES(r4)
|
||||
LOAD_REG_IMMEDIATE(r6,CPU_FTR_HVMODE | CPU_FTR_P9_TM_HV_ASSIST)
|
||||
andc r5,r5,r6
|
||||
std r5,CPU_SPEC_FEATURES(r4)
|
||||
blr
|
||||
|
||||
__init_LPCR_ISA206:
|
||||
/* Setup a sane LPCR:
|
||||
* Called with initial LPCR in R3 and desired LPES 2-bit value in R4
|
||||
*
|
||||
* LPES = 0b01 (HSRR0/1 used for 0x500)
|
||||
* PECE = 0b111
|
||||
* DPFD = 4
|
||||
* HDICE = 0
|
||||
* VC = 0b100 (VPM0=1, VPM1=0, ISL=0)
|
||||
* VRMASD = 0b10000 (L=1, LP=00)
|
||||
*
|
||||
* Other bits untouched for now
|
||||
*/
|
||||
li r5,0x10
|
||||
rldimi r3,r5, LPCR_VRMASD_SH, 64-LPCR_VRMASD_SH-5
|
||||
|
||||
/* POWER9 has no VRMASD */
|
||||
__init_LPCR_ISA300:
|
||||
rldimi r3,r4, LPCR_LPES_SH, 64-LPCR_LPES_SH-2
|
||||
ori r3,r3,(LPCR_PECE0|LPCR_PECE1|LPCR_PECE2)
|
||||
li r5,4
|
||||
rldimi r3,r5, LPCR_DPFD_SH, 64-LPCR_DPFD_SH-3
|
||||
clrrdi r3,r3,1 /* clear HDICE */
|
||||
li r5,4
|
||||
rldimi r3,r5, LPCR_VC_SH, 0
|
||||
mtspr SPRN_LPCR,r3
|
||||
isync
|
||||
blr
|
||||
|
||||
__init_FSCR_power10:
|
||||
mfspr r3, SPRN_FSCR
|
||||
ori r3, r3, FSCR_PREFIX
|
||||
mtspr SPRN_FSCR, r3
|
||||
// fall through
|
||||
|
||||
__init_FSCR_power9:
|
||||
mfspr r3, SPRN_FSCR
|
||||
ori r3, r3, FSCR_SCV
|
||||
mtspr SPRN_FSCR, r3
|
||||
// fall through
|
||||
|
||||
__init_FSCR:
|
||||
mfspr r3,SPRN_FSCR
|
||||
ori r3,r3,FSCR_TAR|FSCR_EBB
|
||||
mtspr SPRN_FSCR,r3
|
||||
blr
|
||||
|
||||
__init_HFSCR:
|
||||
mfspr r3,SPRN_HFSCR
|
||||
ori r3,r3,HFSCR_TAR|HFSCR_TM|HFSCR_BHRB|HFSCR_PM|\
|
||||
HFSCR_DSCR|HFSCR_VECVSX|HFSCR_FP|HFSCR_EBB|HFSCR_MSGP
|
||||
mtspr SPRN_HFSCR,r3
|
||||
blr
|
||||
|
||||
__init_PMU_HV:
|
||||
li r5,0
|
||||
mtspr SPRN_MMCRC,r5
|
||||
blr
|
||||
|
||||
__init_PMU_HV_ISA207:
|
||||
li r5,0
|
||||
mtspr SPRN_MMCRH,r5
|
||||
blr
|
||||
|
||||
__init_PMU:
|
||||
li r5,0
|
||||
mtspr SPRN_MMCRA,r5
|
||||
mtspr SPRN_MMCR0,r5
|
||||
mtspr SPRN_MMCR1,r5
|
||||
mtspr SPRN_MMCR2,r5
|
||||
blr
|
||||
|
||||
__init_PMU_ISA207:
|
||||
li r5,0
|
||||
mtspr SPRN_MMCRS,r5
|
||||
blr
|
||||
|
||||
__init_PMU_ISA31:
|
||||
li r5,0
|
||||
mtspr SPRN_MMCR3,r5
|
||||
LOAD_REG_IMMEDIATE(r5, MMCRA_BHRB_DISABLE)
|
||||
mtspr SPRN_MMCRA,r5
|
||||
blr
|
||||
272
arch/powerpc/kernel/cpu_setup_power.c
Normal file
272
arch/powerpc/kernel/cpu_setup_power.c
Normal file
@@ -0,0 +1,272 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright 2020, Jordan Niethe, IBM Corporation.
|
||||
*
|
||||
* This file contains low level CPU setup functions.
|
||||
* Originally written in assembly by Benjamin Herrenschmidt & various other
|
||||
* authors.
|
||||
*/
|
||||
|
||||
#include <asm/reg.h>
|
||||
#include <asm/synch.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <asm/cputable.h>
|
||||
#include <asm/cpu_setup_power.h>
|
||||
|
||||
/* Disable CPU_FTR_HVMODE and return false if MSR:HV is not set */
|
||||
static bool init_hvmode_206(struct cpu_spec *t)
|
||||
{
|
||||
u64 msr;
|
||||
|
||||
msr = mfmsr();
|
||||
if (msr & MSR_HV)
|
||||
return true;
|
||||
|
||||
t->cpu_features &= ~(CPU_FTR_HVMODE | CPU_FTR_P9_TM_HV_ASSIST);
|
||||
return false;
|
||||
}
|
||||
|
||||
static void init_LPCR_ISA300(u64 lpcr, u64 lpes)
|
||||
{
|
||||
/* POWER9 has no VRMASD */
|
||||
lpcr |= (lpes << LPCR_LPES_SH) & LPCR_LPES;
|
||||
lpcr |= LPCR_PECE0|LPCR_PECE1|LPCR_PECE2;
|
||||
lpcr |= (4ull << LPCR_DPFD_SH) & LPCR_DPFD;
|
||||
lpcr &= ~LPCR_HDICE; /* clear HDICE */
|
||||
lpcr |= (4ull << LPCR_VC_SH);
|
||||
mtspr(SPRN_LPCR, lpcr);
|
||||
isync();
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup a sane LPCR:
|
||||
* Called with initial LPCR and desired LPES 2-bit value
|
||||
*
|
||||
* LPES = 0b01 (HSRR0/1 used for 0x500)
|
||||
* PECE = 0b111
|
||||
* DPFD = 4
|
||||
* HDICE = 0
|
||||
* VC = 0b100 (VPM0=1, VPM1=0, ISL=0)
|
||||
* VRMASD = 0b10000 (L=1, LP=00)
|
||||
*
|
||||
* Other bits untouched for now
|
||||
*/
|
||||
static void init_LPCR_ISA206(u64 lpcr, u64 lpes)
|
||||
{
|
||||
lpcr |= (0x10ull << LPCR_VRMASD_SH) & LPCR_VRMASD;
|
||||
init_LPCR_ISA300(lpcr, lpes);
|
||||
}
|
||||
|
||||
static void init_FSCR(void)
|
||||
{
|
||||
u64 fscr;
|
||||
|
||||
fscr = mfspr(SPRN_FSCR);
|
||||
fscr |= FSCR_TAR|FSCR_EBB;
|
||||
mtspr(SPRN_FSCR, fscr);
|
||||
}
|
||||
|
||||
static void init_FSCR_power9(void)
|
||||
{
|
||||
u64 fscr;
|
||||
|
||||
fscr = mfspr(SPRN_FSCR);
|
||||
fscr |= FSCR_SCV;
|
||||
mtspr(SPRN_FSCR, fscr);
|
||||
init_FSCR();
|
||||
}
|
||||
|
||||
static void init_FSCR_power10(void)
|
||||
{
|
||||
u64 fscr;
|
||||
|
||||
fscr = mfspr(SPRN_FSCR);
|
||||
fscr |= FSCR_PREFIX;
|
||||
mtspr(SPRN_FSCR, fscr);
|
||||
init_FSCR_power9();
|
||||
}
|
||||
|
||||
static void init_HFSCR(void)
|
||||
{
|
||||
u64 hfscr;
|
||||
|
||||
hfscr = mfspr(SPRN_HFSCR);
|
||||
hfscr |= HFSCR_TAR|HFSCR_TM|HFSCR_BHRB|HFSCR_PM|HFSCR_DSCR|\
|
||||
HFSCR_VECVSX|HFSCR_FP|HFSCR_EBB|HFSCR_MSGP;
|
||||
mtspr(SPRN_HFSCR, hfscr);
|
||||
}
|
||||
|
||||
static void init_PMU_HV(void)
|
||||
{
|
||||
mtspr(SPRN_MMCRC, 0);
|
||||
}
|
||||
|
||||
static void init_PMU_HV_ISA207(void)
|
||||
{
|
||||
mtspr(SPRN_MMCRH, 0);
|
||||
}
|
||||
|
||||
static void init_PMU(void)
|
||||
{
|
||||
mtspr(SPRN_MMCRA, 0);
|
||||
mtspr(SPRN_MMCR0, 0);
|
||||
mtspr(SPRN_MMCR1, 0);
|
||||
mtspr(SPRN_MMCR2, 0);
|
||||
}
|
||||
|
||||
static void init_PMU_ISA207(void)
|
||||
{
|
||||
mtspr(SPRN_MMCRS, 0);
|
||||
}
|
||||
|
||||
static void init_PMU_ISA31(void)
|
||||
{
|
||||
mtspr(SPRN_MMCR3, 0);
|
||||
mtspr(SPRN_MMCRA, MMCRA_BHRB_DISABLE);
|
||||
mtspr(SPRN_MMCR0, MMCR0_PMCCEXT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Note that we can be called twice of pseudo-PVRs.
|
||||
* The parameter offset is not used.
|
||||
*/
|
||||
|
||||
void __setup_cpu_power7(unsigned long offset, struct cpu_spec *t)
|
||||
{
|
||||
if (!init_hvmode_206(t))
|
||||
return;
|
||||
|
||||
mtspr(SPRN_LPID, 0);
|
||||
mtspr(SPRN_PCR, PCR_MASK);
|
||||
init_LPCR_ISA206(mfspr(SPRN_LPCR), LPCR_LPES1 >> LPCR_LPES_SH);
|
||||
}
|
||||
|
||||
void __restore_cpu_power7(void)
|
||||
{
|
||||
u64 msr;
|
||||
|
||||
msr = mfmsr();
|
||||
if (!(msr & MSR_HV))
|
||||
return;
|
||||
|
||||
mtspr(SPRN_LPID, 0);
|
||||
mtspr(SPRN_PCR, PCR_MASK);
|
||||
init_LPCR_ISA206(mfspr(SPRN_LPCR), LPCR_LPES1 >> LPCR_LPES_SH);
|
||||
}
|
||||
|
||||
void __setup_cpu_power8(unsigned long offset, struct cpu_spec *t)
|
||||
{
|
||||
init_FSCR();
|
||||
init_PMU();
|
||||
init_PMU_ISA207();
|
||||
|
||||
if (!init_hvmode_206(t))
|
||||
return;
|
||||
|
||||
mtspr(SPRN_LPID, 0);
|
||||
mtspr(SPRN_PCR, PCR_MASK);
|
||||
init_LPCR_ISA206(mfspr(SPRN_LPCR) | LPCR_PECEDH, 0); /* LPES = 0 */
|
||||
init_HFSCR();
|
||||
init_PMU_HV();
|
||||
init_PMU_HV_ISA207();
|
||||
}
|
||||
|
||||
void __restore_cpu_power8(void)
|
||||
{
|
||||
u64 msr;
|
||||
|
||||
init_FSCR();
|
||||
init_PMU();
|
||||
init_PMU_ISA207();
|
||||
|
||||
msr = mfmsr();
|
||||
if (!(msr & MSR_HV))
|
||||
return;
|
||||
|
||||
mtspr(SPRN_LPID, 0);
|
||||
mtspr(SPRN_PCR, PCR_MASK);
|
||||
init_LPCR_ISA206(mfspr(SPRN_LPCR) | LPCR_PECEDH, 0); /* LPES = 0 */
|
||||
init_HFSCR();
|
||||
init_PMU_HV();
|
||||
init_PMU_HV_ISA207();
|
||||
}
|
||||
|
||||
void __setup_cpu_power9(unsigned long offset, struct cpu_spec *t)
|
||||
{
|
||||
init_FSCR_power9();
|
||||
init_PMU();
|
||||
|
||||
if (!init_hvmode_206(t))
|
||||
return;
|
||||
|
||||
mtspr(SPRN_PSSCR, 0);
|
||||
mtspr(SPRN_LPID, 0);
|
||||
mtspr(SPRN_PID, 0);
|
||||
mtspr(SPRN_PCR, PCR_MASK);
|
||||
init_LPCR_ISA300((mfspr(SPRN_LPCR) | LPCR_PECEDH | LPCR_PECE_HVEE |\
|
||||
LPCR_HVICE | LPCR_HEIC) & ~(LPCR_UPRT | LPCR_HR), 0);
|
||||
init_HFSCR();
|
||||
init_PMU_HV();
|
||||
}
|
||||
|
||||
void __restore_cpu_power9(void)
|
||||
{
|
||||
u64 msr;
|
||||
|
||||
init_FSCR_power9();
|
||||
init_PMU();
|
||||
|
||||
msr = mfmsr();
|
||||
if (!(msr & MSR_HV))
|
||||
return;
|
||||
|
||||
mtspr(SPRN_PSSCR, 0);
|
||||
mtspr(SPRN_LPID, 0);
|
||||
mtspr(SPRN_PID, 0);
|
||||
mtspr(SPRN_PCR, PCR_MASK);
|
||||
init_LPCR_ISA300((mfspr(SPRN_LPCR) | LPCR_PECEDH | LPCR_PECE_HVEE |\
|
||||
LPCR_HVICE | LPCR_HEIC) & ~(LPCR_UPRT | LPCR_HR), 0);
|
||||
init_HFSCR();
|
||||
init_PMU_HV();
|
||||
}
|
||||
|
||||
void __setup_cpu_power10(unsigned long offset, struct cpu_spec *t)
|
||||
{
|
||||
init_FSCR_power10();
|
||||
init_PMU();
|
||||
init_PMU_ISA31();
|
||||
|
||||
if (!init_hvmode_206(t))
|
||||
return;
|
||||
|
||||
mtspr(SPRN_PSSCR, 0);
|
||||
mtspr(SPRN_LPID, 0);
|
||||
mtspr(SPRN_PID, 0);
|
||||
mtspr(SPRN_PCR, PCR_MASK);
|
||||
init_LPCR_ISA300((mfspr(SPRN_LPCR) | LPCR_PECEDH | LPCR_PECE_HVEE |\
|
||||
LPCR_HVICE | LPCR_HEIC) & ~(LPCR_UPRT | LPCR_HR), 0);
|
||||
init_HFSCR();
|
||||
init_PMU_HV();
|
||||
}
|
||||
|
||||
void __restore_cpu_power10(void)
|
||||
{
|
||||
u64 msr;
|
||||
|
||||
init_FSCR_power10();
|
||||
init_PMU();
|
||||
init_PMU_ISA31();
|
||||
|
||||
msr = mfmsr();
|
||||
if (!(msr & MSR_HV))
|
||||
return;
|
||||
|
||||
mtspr(SPRN_PSSCR, 0);
|
||||
mtspr(SPRN_LPID, 0);
|
||||
mtspr(SPRN_PID, 0);
|
||||
mtspr(SPRN_PCR, PCR_MASK);
|
||||
init_LPCR_ISA300((mfspr(SPRN_LPCR) | LPCR_PECEDH | LPCR_PECE_HVEE |\
|
||||
LPCR_HVICE | LPCR_HEIC) & ~(LPCR_UPRT | LPCR_HR), 0);
|
||||
init_HFSCR();
|
||||
init_PMU_HV();
|
||||
}
|
||||
@@ -36,7 +36,6 @@ const char *powerpc_base_platform;
|
||||
* and ppc64
|
||||
*/
|
||||
#ifdef CONFIG_PPC32
|
||||
extern void __setup_cpu_e200(unsigned long offset, struct cpu_spec* spec);
|
||||
extern void __setup_cpu_e500v1(unsigned long offset, struct cpu_spec* spec);
|
||||
extern void __setup_cpu_e500v2(unsigned long offset, struct cpu_spec* spec);
|
||||
extern void __setup_cpu_e500mc(unsigned long offset, struct cpu_spec* spec);
|
||||
@@ -60,19 +59,15 @@ extern void __setup_cpu_7410(unsigned long offset, struct cpu_spec* spec);
|
||||
extern void __setup_cpu_745x(unsigned long offset, struct cpu_spec* spec);
|
||||
#endif /* CONFIG_PPC32 */
|
||||
#ifdef CONFIG_PPC64
|
||||
#include <asm/cpu_setup_power.h>
|
||||
extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec);
|
||||
extern void __setup_cpu_ppc970MP(unsigned long offset, struct cpu_spec* spec);
|
||||
extern void __setup_cpu_pa6t(unsigned long offset, struct cpu_spec* spec);
|
||||
extern void __restore_cpu_pa6t(void);
|
||||
extern void __restore_cpu_ppc970(void);
|
||||
extern void __setup_cpu_power7(unsigned long offset, struct cpu_spec* spec);
|
||||
extern void __restore_cpu_power7(void);
|
||||
extern void __setup_cpu_power8(unsigned long offset, struct cpu_spec* spec);
|
||||
extern void __restore_cpu_power8(void);
|
||||
extern void __setup_cpu_power9(unsigned long offset, struct cpu_spec* spec);
|
||||
extern void __restore_cpu_power9(void);
|
||||
extern void __setup_cpu_power10(unsigned long offset, struct cpu_spec* spec);
|
||||
extern void __restore_cpu_power10(void);
|
||||
extern long __machine_check_early_realmode_p7(struct pt_regs *regs);
|
||||
extern long __machine_check_early_realmode_p8(struct pt_regs *regs);
|
||||
extern long __machine_check_early_realmode_p9(struct pt_regs *regs);
|
||||
#endif /* CONFIG_PPC64 */
|
||||
#if defined(CONFIG_E500)
|
||||
extern void __setup_cpu_e5500(unsigned long offset, struct cpu_spec* spec);
|
||||
@@ -616,46 +611,8 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
#endif /* CONFIG_PPC_BOOK3S_64 */
|
||||
|
||||
#ifdef CONFIG_PPC32
|
||||
#ifdef CONFIG_PPC_BOOK3S_6xx
|
||||
{ /* 603 */
|
||||
.pvr_mask = 0xffff0000,
|
||||
.pvr_value = 0x00030000,
|
||||
.cpu_name = "603",
|
||||
.cpu_features = CPU_FTRS_603,
|
||||
.cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
|
||||
.mmu_features = 0,
|
||||
.icache_bsize = 32,
|
||||
.dcache_bsize = 32,
|
||||
.cpu_setup = __setup_cpu_603,
|
||||
.machine_check = machine_check_generic,
|
||||
.platform = "ppc603",
|
||||
},
|
||||
{ /* 603e */
|
||||
.pvr_mask = 0xffff0000,
|
||||
.pvr_value = 0x00060000,
|
||||
.cpu_name = "603e",
|
||||
.cpu_features = CPU_FTRS_603,
|
||||
.cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
|
||||
.mmu_features = 0,
|
||||
.icache_bsize = 32,
|
||||
.dcache_bsize = 32,
|
||||
.cpu_setup = __setup_cpu_603,
|
||||
.machine_check = machine_check_generic,
|
||||
.platform = "ppc603",
|
||||
},
|
||||
{ /* 603ev */
|
||||
.pvr_mask = 0xffff0000,
|
||||
.pvr_value = 0x00070000,
|
||||
.cpu_name = "603ev",
|
||||
.cpu_features = CPU_FTRS_603,
|
||||
.cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
|
||||
.mmu_features = 0,
|
||||
.icache_bsize = 32,
|
||||
.dcache_bsize = 32,
|
||||
.cpu_setup = __setup_cpu_603,
|
||||
.machine_check = machine_check_generic,
|
||||
.platform = "ppc603",
|
||||
},
|
||||
#ifdef CONFIG_PPC_BOOK3S_32
|
||||
#ifdef CONFIG_PPC_BOOK3S_604
|
||||
{ /* 604 */
|
||||
.pvr_mask = 0xffff0000,
|
||||
.pvr_value = 0x00040000,
|
||||
@@ -1145,6 +1102,47 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.machine_check = machine_check_generic,
|
||||
.platform = "ppc7450",
|
||||
},
|
||||
#endif /* CONFIG_PPC_BOOK3S_604 */
|
||||
#ifdef CONFIG_PPC_BOOK3S_603
|
||||
{ /* 603 */
|
||||
.pvr_mask = 0xffff0000,
|
||||
.pvr_value = 0x00030000,
|
||||
.cpu_name = "603",
|
||||
.cpu_features = CPU_FTRS_603,
|
||||
.cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
|
||||
.mmu_features = 0,
|
||||
.icache_bsize = 32,
|
||||
.dcache_bsize = 32,
|
||||
.cpu_setup = __setup_cpu_603,
|
||||
.machine_check = machine_check_generic,
|
||||
.platform = "ppc603",
|
||||
},
|
||||
{ /* 603e */
|
||||
.pvr_mask = 0xffff0000,
|
||||
.pvr_value = 0x00060000,
|
||||
.cpu_name = "603e",
|
||||
.cpu_features = CPU_FTRS_603,
|
||||
.cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
|
||||
.mmu_features = 0,
|
||||
.icache_bsize = 32,
|
||||
.dcache_bsize = 32,
|
||||
.cpu_setup = __setup_cpu_603,
|
||||
.machine_check = machine_check_generic,
|
||||
.platform = "ppc603",
|
||||
},
|
||||
{ /* 603ev */
|
||||
.pvr_mask = 0xffff0000,
|
||||
.pvr_value = 0x00070000,
|
||||
.cpu_name = "603ev",
|
||||
.cpu_features = CPU_FTRS_603,
|
||||
.cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
|
||||
.mmu_features = 0,
|
||||
.icache_bsize = 32,
|
||||
.dcache_bsize = 32,
|
||||
.cpu_setup = __setup_cpu_603,
|
||||
.machine_check = machine_check_generic,
|
||||
.platform = "ppc603",
|
||||
},
|
||||
{ /* 82xx (8240, 8245, 8260 are all 603e cores) */
|
||||
.pvr_mask = 0x7fff0000,
|
||||
.pvr_value = 0x00810000,
|
||||
@@ -1234,6 +1232,8 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.platform = "ppc603",
|
||||
},
|
||||
#endif
|
||||
#endif /* CONFIG_PPC_BOOK3S_603 */
|
||||
#ifdef CONFIG_PPC_BOOK3S_604
|
||||
{ /* default match, we assume split I/D cache & TB (non-601)... */
|
||||
.pvr_mask = 0x00000000,
|
||||
.pvr_value = 0x00000000,
|
||||
@@ -1246,7 +1246,8 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.machine_check = machine_check_generic,
|
||||
.platform = "ppc603",
|
||||
},
|
||||
#endif /* CONFIG_PPC_BOOK3S_6xx */
|
||||
#endif /* CONFIG_PPC_BOOK3S_604 */
|
||||
#endif /* CONFIG_PPC_BOOK3S_32 */
|
||||
#ifdef CONFIG_PPC_8xx
|
||||
{ /* 8xx */
|
||||
.pvr_mask = 0xffff0000,
|
||||
@@ -1540,6 +1541,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
|
||||
#endif /* CONFIG_40x */
|
||||
#ifdef CONFIG_44x
|
||||
#ifndef CONFIG_PPC_47x
|
||||
{
|
||||
.pvr_mask = 0xf0000fff,
|
||||
.pvr_value = 0x40000850,
|
||||
@@ -1822,7 +1824,19 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.machine_check = machine_check_440A,
|
||||
.platform = "ppc440",
|
||||
},
|
||||
#ifdef CONFIG_PPC_47x
|
||||
{ /* default match */
|
||||
.pvr_mask = 0x00000000,
|
||||
.pvr_value = 0x00000000,
|
||||
.cpu_name = "(generic 44x PPC)",
|
||||
.cpu_features = CPU_FTRS_44X,
|
||||
.cpu_user_features = COMMON_USER_BOOKE,
|
||||
.mmu_features = MMU_FTR_TYPE_44x,
|
||||
.icache_bsize = 32,
|
||||
.dcache_bsize = 32,
|
||||
.machine_check = machine_check_4xx,
|
||||
.platform = "ppc440",
|
||||
}
|
||||
#else /* CONFIG_PPC_47x */
|
||||
{ /* 476 DD2 core */
|
||||
.pvr_mask = 0xffffffff,
|
||||
.pvr_value = 0x11a52080,
|
||||
@@ -1879,65 +1893,20 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.machine_check = machine_check_47x,
|
||||
.platform = "ppc470",
|
||||
},
|
||||
#endif /* CONFIG_PPC_47x */
|
||||
{ /* default match */
|
||||
.pvr_mask = 0x00000000,
|
||||
.pvr_value = 0x00000000,
|
||||
.cpu_name = "(generic 44x PPC)",
|
||||
.cpu_features = CPU_FTRS_44X,
|
||||
.cpu_name = "(generic 47x PPC)",
|
||||
.cpu_features = CPU_FTRS_47X,
|
||||
.cpu_user_features = COMMON_USER_BOOKE,
|
||||
.mmu_features = MMU_FTR_TYPE_44x,
|
||||
.mmu_features = MMU_FTR_TYPE_47x,
|
||||
.icache_bsize = 32,
|
||||
.dcache_bsize = 32,
|
||||
.machine_check = machine_check_4xx,
|
||||
.platform = "ppc440",
|
||||
.dcache_bsize = 128,
|
||||
.machine_check = machine_check_47x,
|
||||
.platform = "ppc470",
|
||||
}
|
||||
#endif /* CONFIG_PPC_47x */
|
||||
#endif /* CONFIG_44x */
|
||||
#ifdef CONFIG_E200
|
||||
{ /* e200z5 */
|
||||
.pvr_mask = 0xfff00000,
|
||||
.pvr_value = 0x81000000,
|
||||
.cpu_name = "e200z5",
|
||||
/* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */
|
||||
.cpu_features = CPU_FTRS_E200,
|
||||
.cpu_user_features = COMMON_USER_BOOKE |
|
||||
PPC_FEATURE_HAS_EFP_SINGLE |
|
||||
PPC_FEATURE_UNIFIED_CACHE,
|
||||
.mmu_features = MMU_FTR_TYPE_FSL_E,
|
||||
.dcache_bsize = 32,
|
||||
.machine_check = machine_check_e200,
|
||||
.platform = "ppc5554",
|
||||
},
|
||||
{ /* e200z6 */
|
||||
.pvr_mask = 0xfff00000,
|
||||
.pvr_value = 0x81100000,
|
||||
.cpu_name = "e200z6",
|
||||
/* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */
|
||||
.cpu_features = CPU_FTRS_E200,
|
||||
.cpu_user_features = COMMON_USER_BOOKE |
|
||||
PPC_FEATURE_HAS_SPE_COMP |
|
||||
PPC_FEATURE_HAS_EFP_SINGLE_COMP |
|
||||
PPC_FEATURE_UNIFIED_CACHE,
|
||||
.mmu_features = MMU_FTR_TYPE_FSL_E,
|
||||
.dcache_bsize = 32,
|
||||
.machine_check = machine_check_e200,
|
||||
.platform = "ppc5554",
|
||||
},
|
||||
{ /* default match */
|
||||
.pvr_mask = 0x00000000,
|
||||
.pvr_value = 0x00000000,
|
||||
.cpu_name = "(generic E200 PPC)",
|
||||
.cpu_features = CPU_FTRS_E200,
|
||||
.cpu_user_features = COMMON_USER_BOOKE |
|
||||
PPC_FEATURE_HAS_EFP_SINGLE |
|
||||
PPC_FEATURE_UNIFIED_CACHE,
|
||||
.mmu_features = MMU_FTR_TYPE_FSL_E,
|
||||
.dcache_bsize = 32,
|
||||
.cpu_setup = __setup_cpu_e200,
|
||||
.machine_check = machine_check_e200,
|
||||
.platform = "ppc5554",
|
||||
}
|
||||
#endif /* CONFIG_E200 */
|
||||
#endif /* CONFIG_PPC32 */
|
||||
#ifdef CONFIG_E500
|
||||
#ifdef CONFIG_PPC32
|
||||
|
||||
@@ -69,7 +69,6 @@ static int hv_mode;
|
||||
|
||||
static struct {
|
||||
u64 lpcr;
|
||||
u64 lpcr_clear;
|
||||
u64 hfscr;
|
||||
u64 fscr;
|
||||
u64 pcr;
|
||||
@@ -79,24 +78,7 @@ static void (*init_pmu_registers)(void);
|
||||
|
||||
static void __restore_cpu_cpufeatures(void)
|
||||
{
|
||||
u64 lpcr;
|
||||
|
||||
/*
|
||||
* LPCR is restored by the power on engine already. It can be changed
|
||||
* after early init e.g., by radix enable, and we have no unified API
|
||||
* for saving and restoring such SPRs.
|
||||
*
|
||||
* This ->restore hook should really be removed from idle and register
|
||||
* restore moved directly into the idle restore code, because this code
|
||||
* doesn't know how idle is implemented or what it needs restored here.
|
||||
*
|
||||
* The best we can do to accommodate secondary boot and idle restore
|
||||
* for now is "or" LPCR with existing.
|
||||
*/
|
||||
lpcr = mfspr(SPRN_LPCR);
|
||||
lpcr |= system_registers.lpcr;
|
||||
lpcr &= ~system_registers.lpcr_clear;
|
||||
mtspr(SPRN_LPCR, lpcr);
|
||||
mtspr(SPRN_LPCR, system_registers.lpcr);
|
||||
if (hv_mode) {
|
||||
mtspr(SPRN_LPID, 0);
|
||||
mtspr(SPRN_HFSCR, system_registers.hfscr);
|
||||
@@ -273,13 +255,6 @@ static int __init feat_enable_idle_nap(struct dt_cpu_feature *f)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __init feat_enable_align_dsisr(struct dt_cpu_feature *f)
|
||||
{
|
||||
cur_cpu_spec->cpu_features &= ~CPU_FTR_NODSISRALIGN;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __init feat_enable_idle_stop(struct dt_cpu_feature *f)
|
||||
{
|
||||
u64 lpcr;
|
||||
@@ -317,7 +292,6 @@ static int __init feat_enable_mmu_hash_v3(struct dt_cpu_feature *f)
|
||||
{
|
||||
u64 lpcr;
|
||||
|
||||
system_registers.lpcr_clear |= (LPCR_ISL | LPCR_UPRT | LPCR_HR);
|
||||
lpcr = mfspr(SPRN_LPCR);
|
||||
lpcr &= ~(LPCR_ISL | LPCR_UPRT | LPCR_HR);
|
||||
mtspr(SPRN_LPCR, lpcr);
|
||||
@@ -454,6 +428,7 @@ static void init_pmu_power10(void)
|
||||
|
||||
mtspr(SPRN_MMCR3, 0);
|
||||
mtspr(SPRN_MMCRA, MMCRA_BHRB_DISABLE);
|
||||
mtspr(SPRN_MMCR0, MMCR0_PMCCEXT);
|
||||
}
|
||||
|
||||
static int __init feat_enable_pmu_power10(struct dt_cpu_feature *f)
|
||||
@@ -641,7 +616,7 @@ static struct dt_cpu_feature_match __initdata
|
||||
{"tm-suspend-hypervisor-assist", feat_enable, CPU_FTR_P9_TM_HV_ASSIST},
|
||||
{"tm-suspend-xer-so-bug", feat_enable, CPU_FTR_P9_TM_XER_SO_BUG},
|
||||
{"idle-nap", feat_enable_idle_nap, 0},
|
||||
{"alignment-interrupt-dsisr", feat_enable_align_dsisr, 0},
|
||||
/* alignment-interrupt-dsisr ignored */
|
||||
{"idle-stop", feat_enable_idle_stop, 0},
|
||||
{"machine-check-power8", feat_enable_mce_power8, 0},
|
||||
{"performance-monitor-power8", feat_enable_pmu_power8, 0},
|
||||
|
||||
@@ -234,7 +234,10 @@ transfer_to_handler_cont:
|
||||
mtspr SPRN_SRR0,r11
|
||||
mtspr SPRN_SRR1,r10
|
||||
mtlr r9
|
||||
RFI /* jump to handler, enable MMU */
|
||||
rfi /* jump to handler, enable MMU */
|
||||
#ifdef CONFIG_40x
|
||||
b . /* Prevent prefetch past rfi */
|
||||
#endif
|
||||
|
||||
#if defined (CONFIG_PPC_BOOK3S_32) || defined(CONFIG_E500)
|
||||
4: rlwinm r12,r12,0,~_TLF_NAPPING
|
||||
@@ -263,7 +266,10 @@ _ASM_NOKPROBE_SYMBOL(transfer_to_handler_cont)
|
||||
LOAD_REG_IMMEDIATE(r0, MSR_KERNEL)
|
||||
mtspr SPRN_SRR0,r12
|
||||
mtspr SPRN_SRR1,r0
|
||||
RFI
|
||||
rfi
|
||||
#ifdef CONFIG_40x
|
||||
b . /* Prevent prefetch past rfi */
|
||||
#endif
|
||||
|
||||
reenable_mmu:
|
||||
/*
|
||||
@@ -321,7 +327,10 @@ stack_ovf:
|
||||
#endif
|
||||
mtspr SPRN_SRR0,r9
|
||||
mtspr SPRN_SRR1,r10
|
||||
RFI
|
||||
rfi
|
||||
#ifdef CONFIG_40x
|
||||
b . /* Prevent prefetch past rfi */
|
||||
#endif
|
||||
_ASM_NOKPROBE_SYMBOL(stack_ovf)
|
||||
#endif
|
||||
|
||||
@@ -439,15 +448,13 @@ syscall_exit_cont:
|
||||
andis. r10,r0,DBCR0_IDM@h
|
||||
bnel- load_dbcr0
|
||||
#endif
|
||||
#ifdef CONFIG_44x
|
||||
BEGIN_MMU_FTR_SECTION
|
||||
#ifdef CONFIG_PPC_47x
|
||||
lis r4,icache_44x_need_flush@ha
|
||||
lwz r5,icache_44x_need_flush@l(r4)
|
||||
cmplwi cr0,r5,0
|
||||
bne- 2f
|
||||
#endif /* CONFIG_PPC_47x */
|
||||
1:
|
||||
END_MMU_FTR_SECTION_IFCLR(MMU_FTR_TYPE_47x)
|
||||
#endif /* CONFIG_44x */
|
||||
BEGIN_FTR_SECTION
|
||||
lwarx r7,0,r1
|
||||
END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX)
|
||||
@@ -470,7 +477,10 @@ syscall_exit_finish:
|
||||
#endif
|
||||
mtspr SPRN_SRR0,r7
|
||||
mtspr SPRN_SRR1,r8
|
||||
RFI
|
||||
rfi
|
||||
#ifdef CONFIG_40x
|
||||
b . /* Prevent prefetch past rfi */
|
||||
#endif
|
||||
_ASM_NOKPROBE_SYMBOL(syscall_exit_finish)
|
||||
#ifdef CONFIG_44x
|
||||
2: li r7,0
|
||||
@@ -600,7 +610,10 @@ ret_from_kernel_syscall:
|
||||
#endif
|
||||
mtspr SPRN_SRR0, r9
|
||||
mtspr SPRN_SRR1, r10
|
||||
RFI
|
||||
rfi
|
||||
#ifdef CONFIG_40x
|
||||
b . /* Prevent prefetch past rfi */
|
||||
#endif
|
||||
_ASM_NOKPROBE_SYMBOL(ret_from_kernel_syscall)
|
||||
|
||||
/*
|
||||
@@ -671,7 +684,7 @@ handle_page_fault:
|
||||
mr r5,r3
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
lwz r4,_DAR(r1)
|
||||
bl bad_page_fault
|
||||
bl __bad_page_fault
|
||||
b ret_from_except_full
|
||||
|
||||
#ifdef CONFIG_PPC_BOOK3S_32
|
||||
@@ -803,7 +816,10 @@ fast_exception_return:
|
||||
REST_GPR(9, r11)
|
||||
REST_GPR(12, r11)
|
||||
lwz r11,GPR11(r11)
|
||||
RFI
|
||||
rfi
|
||||
#ifdef CONFIG_40x
|
||||
b . /* Prevent prefetch past rfi */
|
||||
#endif
|
||||
_ASM_NOKPROBE_SYMBOL(fast_exception_return)
|
||||
|
||||
#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
|
||||
@@ -948,10 +964,7 @@ restore_kuap:
|
||||
|
||||
/* interrupts are hard-disabled at this point */
|
||||
restore:
|
||||
#ifdef CONFIG_44x
|
||||
BEGIN_MMU_FTR_SECTION
|
||||
b 1f
|
||||
END_MMU_FTR_SECTION_IFSET(MMU_FTR_TYPE_47x)
|
||||
#if defined(CONFIG_44x) && !defined(CONFIG_PPC_47x)
|
||||
lis r4,icache_44x_need_flush@ha
|
||||
lwz r5,icache_44x_need_flush@l(r4)
|
||||
cmplwi cr0,r5,0
|
||||
@@ -1027,7 +1040,7 @@ exc_exit_restart:
|
||||
lwz r1,GPR1(r1)
|
||||
.globl exc_exit_restart_end
|
||||
exc_exit_restart_end:
|
||||
RFI
|
||||
rfi
|
||||
_ASM_NOKPROBE_SYMBOL(exc_exit_restart)
|
||||
_ASM_NOKPROBE_SYMBOL(exc_exit_restart_end)
|
||||
|
||||
@@ -1356,7 +1369,7 @@ _GLOBAL(enter_rtas)
|
||||
stw r7, THREAD + RTAS_SP(r2)
|
||||
mtspr SPRN_SRR0,r8
|
||||
mtspr SPRN_SRR1,r9
|
||||
RFI
|
||||
rfi
|
||||
1: tophys_novmstack r9, r1
|
||||
#ifdef CONFIG_VMAP_STACK
|
||||
li r0, MSR_KERNEL & ~MSR_IR /* can take DTLB miss */
|
||||
@@ -1371,6 +1384,6 @@ _GLOBAL(enter_rtas)
|
||||
stw r0, THREAD + RTAS_SP(r7)
|
||||
mtspr SPRN_SRR0,r8
|
||||
mtspr SPRN_SRR1,r9
|
||||
RFI /* return to caller */
|
||||
rfi /* return to caller */
|
||||
_ASM_NOKPROBE_SYMBOL(enter_rtas)
|
||||
#endif /* CONFIG_PPC_RTAS */
|
||||
|
||||
@@ -653,8 +653,8 @@ _ASM_NOKPROBE_SYMBOL(fast_interrupt_return)
|
||||
kuap_check_amr r3, r4
|
||||
ld r5,_MSR(r1)
|
||||
andi. r0,r5,MSR_PR
|
||||
bne .Lfast_user_interrupt_return
|
||||
kuap_restore_amr r3, r4
|
||||
bne .Lfast_user_interrupt_return_amr
|
||||
kuap_kernel_restore r3, r4
|
||||
andi. r0,r5,MSR_RI
|
||||
li r3,0 /* 0 return value, no EMULATE_STACK_STORE */
|
||||
bne+ .Lfast_kernel_interrupt_return
|
||||
@@ -674,6 +674,8 @@ _ASM_NOKPROBE_SYMBOL(interrupt_return)
|
||||
cmpdi r3,0
|
||||
bne- .Lrestore_nvgprs
|
||||
|
||||
.Lfast_user_interrupt_return_amr:
|
||||
kuap_user_restore r3, r4
|
||||
.Lfast_user_interrupt_return:
|
||||
ld r11,_NIP(r1)
|
||||
ld r12,_MSR(r1)
|
||||
@@ -967,7 +969,7 @@ _GLOBAL(enter_prom)
|
||||
mtsrr1 r11
|
||||
rfi
|
||||
#else /* CONFIG_PPC_BOOK3E */
|
||||
LOAD_REG_IMMEDIATE(r12, MSR_SF | MSR_ISF | MSR_LE)
|
||||
LOAD_REG_IMMEDIATE(r12, MSR_SF | MSR_LE)
|
||||
andc r11,r11,r12
|
||||
mtsrr1 r11
|
||||
RFI_TO_KERNEL
|
||||
|
||||
@@ -1023,7 +1023,7 @@ storage_fault_common:
|
||||
mr r5,r3
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
ld r4,_DAR(r1)
|
||||
bl bad_page_fault
|
||||
bl __bad_page_fault
|
||||
b ret_from_except
|
||||
|
||||
/*
|
||||
|
||||
@@ -1059,7 +1059,7 @@ EXC_COMMON_BEGIN(system_reset_common)
|
||||
ld r10,SOFTE(r1)
|
||||
stb r10,PACAIRQSOFTMASK(r13)
|
||||
|
||||
kuap_restore_amr r9, r10
|
||||
kuap_kernel_restore r9, r10
|
||||
EXCEPTION_RESTORE_REGS
|
||||
RFI_TO_USER_OR_KERNEL
|
||||
|
||||
@@ -2875,7 +2875,7 @@ EXC_COMMON_BEGIN(soft_nmi_common)
|
||||
ld r10,SOFTE(r1)
|
||||
stb r10,PACAIRQSOFTMASK(r13)
|
||||
|
||||
kuap_restore_amr r9, r10
|
||||
kuap_kernel_restore r9, r10
|
||||
EXCEPTION_RESTORE_REGS hsrr=0
|
||||
RFI_TO_KERNEL
|
||||
|
||||
@@ -3259,7 +3259,7 @@ handle_page_fault:
|
||||
mr r5,r3
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
ld r4,_DAR(r1)
|
||||
bl bad_page_fault
|
||||
bl __bad_page_fault
|
||||
b interrupt_return
|
||||
|
||||
/* We have a data breakpoint exception - handle it */
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <asm/firmware.h>
|
||||
#include <asm/kvm_guest.h>
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
unsigned long powerpc_firmware_features __read_mostly;
|
||||
@@ -21,17 +22,19 @@ EXPORT_SYMBOL_GPL(powerpc_firmware_features);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_KVM_GUEST)
|
||||
bool is_kvm_guest(void)
|
||||
DEFINE_STATIC_KEY_FALSE(kvm_guest);
|
||||
bool check_kvm_guest(void)
|
||||
{
|
||||
struct device_node *hyper_node;
|
||||
|
||||
hyper_node = of_find_node_by_path("/hypervisor");
|
||||
if (!hyper_node)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if (!of_device_is_compatible(hyper_node, "linux,kvm"))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
return 1;
|
||||
static_branch_enable(&kvm_guest);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -40,38 +40,31 @@
|
||||
|
||||
.macro EXCEPTION_PROLOG_1 for_rtas=0
|
||||
#ifdef CONFIG_VMAP_STACK
|
||||
mr r11, r1
|
||||
mtspr SPRN_SPRG_SCRATCH2,r1
|
||||
subi r1, r1, INT_FRAME_SIZE /* use r1 if kernel */
|
||||
beq 1f
|
||||
mfspr r1,SPRN_SPRG_THREAD
|
||||
lwz r1,TASK_STACK-THREAD(r1)
|
||||
addi r1, r1, THREAD_SIZE - INT_FRAME_SIZE
|
||||
1:
|
||||
mtcrf 0x7f, r1
|
||||
bt 32 - THREAD_ALIGN_SHIFT, stack_overflow
|
||||
#else
|
||||
subi r11, r1, INT_FRAME_SIZE /* use r1 if kernel */
|
||||
beq 1f
|
||||
mfspr r11,SPRN_SPRG_THREAD
|
||||
lwz r11,TASK_STACK-THREAD(r11)
|
||||
addi r11, r11, THREAD_SIZE - INT_FRAME_SIZE
|
||||
#endif
|
||||
1:
|
||||
tophys_novmstack r11, r11
|
||||
#ifdef CONFIG_VMAP_STACK
|
||||
mtcrf 0x7f, r1
|
||||
bt 32 - THREAD_ALIGN_SHIFT, stack_overflow
|
||||
1: tophys(r11, r11)
|
||||
#endif
|
||||
.endm
|
||||
|
||||
.macro EXCEPTION_PROLOG_2 handle_dar_dsisr=0
|
||||
#ifdef CONFIG_VMAP_STACK
|
||||
mtcr r10
|
||||
li r10, MSR_KERNEL & ~(MSR_IR | MSR_RI) /* can take DTLB miss */
|
||||
mtmsr r10
|
||||
li r11, MSR_KERNEL & ~(MSR_IR | MSR_RI) /* can take DTLB miss */
|
||||
mtmsr r11
|
||||
isync
|
||||
#else
|
||||
stw r10,_CCR(r11) /* save registers */
|
||||
#endif
|
||||
mfspr r10, SPRN_SPRG_SCRATCH0
|
||||
#ifdef CONFIG_VMAP_STACK
|
||||
mfspr r11, SPRN_SPRG_SCRATCH2
|
||||
stw r11,GPR1(r1)
|
||||
stw r11,0(r1)
|
||||
mr r11, r1
|
||||
@@ -80,14 +73,12 @@
|
||||
stw r1,0(r11)
|
||||
tovirt(r1, r11) /* set new kernel sp */
|
||||
#endif
|
||||
stw r10,_CCR(r11) /* save registers */
|
||||
stw r12,GPR12(r11)
|
||||
stw r9,GPR9(r11)
|
||||
stw r10,GPR10(r11)
|
||||
#ifdef CONFIG_VMAP_STACK
|
||||
mfcr r10
|
||||
stw r10, _CCR(r11)
|
||||
#endif
|
||||
mfspr r10,SPRN_SPRG_SCRATCH0
|
||||
mfspr r12,SPRN_SPRG_SCRATCH1
|
||||
stw r10,GPR10(r11)
|
||||
stw r12,GPR11(r11)
|
||||
mflr r10
|
||||
stw r10,_LINK(r11)
|
||||
@@ -101,7 +92,6 @@
|
||||
stw r10, _DSISR(r11)
|
||||
.endif
|
||||
lwz r9, SRR1(r12)
|
||||
andi. r10, r9, MSR_PR
|
||||
lwz r12, SRR0(r12)
|
||||
#else
|
||||
mfspr r12,SPRN_SRR0
|
||||
@@ -222,7 +212,10 @@
|
||||
#endif
|
||||
mtspr SPRN_SRR1,r10
|
||||
mtspr SPRN_SRR0,r11
|
||||
RFI /* jump to handler, enable MMU */
|
||||
rfi /* jump to handler, enable MMU */
|
||||
#ifdef CONFIG_40x
|
||||
b . /* Prevent prefetch past rfi */
|
||||
#endif
|
||||
99: b ret_from_kernel_syscall
|
||||
.endm
|
||||
|
||||
|
||||
@@ -41,6 +41,11 @@
|
||||
#include <asm/ppc-opcode.h>
|
||||
#include <asm/export.h>
|
||||
#include <asm/feature-fixups.h>
|
||||
#ifdef CONFIG_PPC_BOOK3S
|
||||
#include <asm/exception-64s.h>
|
||||
#else
|
||||
#include <asm/exception-64e.h>
|
||||
#endif
|
||||
|
||||
/* The physical memory is laid out such that the secondary processor
|
||||
* spin code sits at 0x0000...0x00ff. On server, the vectors follow
|
||||
@@ -417,6 +422,10 @@ generic_secondary_common_init:
|
||||
/* From now on, r24 is expected to be logical cpuid */
|
||||
mr r24,r5
|
||||
|
||||
/* Create a temp kernel stack for use before relocation is on. */
|
||||
ld r1,PACAEMERGSP(r13)
|
||||
subi r1,r1,STACK_FRAME_OVERHEAD
|
||||
|
||||
/* See if we need to call a cpu state restore handler */
|
||||
LOAD_REG_ADDR(r23, cur_cpu_spec)
|
||||
ld r23,0(r23)
|
||||
@@ -445,10 +454,6 @@ generic_secondary_common_init:
|
||||
sync /* order paca.run and cur_cpu_spec */
|
||||
isync /* In case code patching happened */
|
||||
|
||||
/* Create a temp kernel stack for use before relocation is on. */
|
||||
ld r1,PACAEMERGSP(r13)
|
||||
subi r1,r1,STACK_FRAME_OVERHEAD
|
||||
|
||||
b __secondary_start
|
||||
#endif /* SMP */
|
||||
|
||||
@@ -829,7 +834,7 @@ __secondary_start:
|
||||
|
||||
mtspr SPRN_SRR0,r3
|
||||
mtspr SPRN_SRR1,r4
|
||||
RFI
|
||||
RFI_TO_KERNEL
|
||||
b . /* prevent speculative execution */
|
||||
|
||||
/*
|
||||
@@ -865,8 +870,7 @@ enable_64b_mode:
|
||||
oris r11,r11,0x8000 /* CM bit set, we'll set ICM later */
|
||||
mtmsr r11
|
||||
#else /* CONFIG_PPC_BOOK3E */
|
||||
li r12,(MSR_64BIT | MSR_ISF)@highest
|
||||
sldi r12,r12,48
|
||||
LOAD_REG_IMMEDIATE(r12, MSR_64BIT)
|
||||
or r11,r11,r12
|
||||
mtmsrd r11
|
||||
isync
|
||||
@@ -966,7 +970,7 @@ start_here_multiplatform:
|
||||
ld r4,PACAKMSR(r13)
|
||||
mtspr SPRN_SRR0,r3
|
||||
mtspr SPRN_SRR1,r4
|
||||
RFI
|
||||
RFI_TO_KERNEL
|
||||
b . /* prevent speculative execution */
|
||||
|
||||
/* This is where all platforms converge execution */
|
||||
@@ -990,7 +994,7 @@ start_here_common:
|
||||
bl start_kernel
|
||||
|
||||
/* Not reached */
|
||||
trap
|
||||
0: trap
|
||||
EMIT_BUG_ENTRY 0b, __FILE__, __LINE__, 0
|
||||
.previous
|
||||
|
||||
|
||||
@@ -42,16 +42,6 @@
|
||||
#endif
|
||||
.endm
|
||||
|
||||
/*
|
||||
* We need an ITLB miss handler for kernel addresses if:
|
||||
* - Either we have modules
|
||||
* - Or we have not pinned the first 8M
|
||||
*/
|
||||
#if defined(CONFIG_MODULES) || !defined(CONFIG_PIN_TLB_TEXT) || \
|
||||
defined(CONFIG_DEBUG_PAGEALLOC)
|
||||
#define ITLB_MISS_KERNEL 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Value for the bits that have fixed value in RPN entries.
|
||||
* Also used for tagging DAR for DTLBerror.
|
||||
@@ -190,32 +180,31 @@ SystemCall:
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_8xx_CPU15
|
||||
#define INVALIDATE_ADJACENT_PAGES_CPU15(addr) \
|
||||
addi addr, addr, PAGE_SIZE; \
|
||||
tlbie addr; \
|
||||
addi addr, addr, -(PAGE_SIZE << 1); \
|
||||
tlbie addr; \
|
||||
addi addr, addr, PAGE_SIZE
|
||||
#define INVALIDATE_ADJACENT_PAGES_CPU15(addr, tmp) \
|
||||
addi tmp, addr, PAGE_SIZE; \
|
||||
tlbie tmp; \
|
||||
addi tmp, addr, -PAGE_SIZE; \
|
||||
tlbie tmp
|
||||
#else
|
||||
#define INVALIDATE_ADJACENT_PAGES_CPU15(addr)
|
||||
#define INVALIDATE_ADJACENT_PAGES_CPU15(addr, tmp)
|
||||
#endif
|
||||
|
||||
InstructionTLBMiss:
|
||||
mtspr SPRN_SPRG_SCRATCH0, r10
|
||||
mtspr SPRN_SPRG_SCRATCH1, r11
|
||||
mtspr SPRN_SPRG_SCRATCH2, r10
|
||||
mtspr SPRN_M_TW, r11
|
||||
|
||||
/* If we are faulting a kernel address, we have to use the
|
||||
* kernel page tables.
|
||||
*/
|
||||
mfspr r10, SPRN_SRR0 /* Get effective address of fault */
|
||||
INVALIDATE_ADJACENT_PAGES_CPU15(r10)
|
||||
INVALIDATE_ADJACENT_PAGES_CPU15(r10, r11)
|
||||
mtspr SPRN_MD_EPN, r10
|
||||
#ifdef ITLB_MISS_KERNEL
|
||||
#ifdef CONFIG_MODULES
|
||||
mfcr r11
|
||||
compare_to_kernel_boundary r10, r10
|
||||
#endif
|
||||
mfspr r10, SPRN_M_TWB /* Get level 1 table */
|
||||
#ifdef ITLB_MISS_KERNEL
|
||||
#ifdef CONFIG_MODULES
|
||||
blt+ 3f
|
||||
rlwinm r10, r10, 0, 20, 31
|
||||
oris r10, r10, (swapper_pg_dir - PAGE_OFFSET)@ha
|
||||
@@ -241,8 +230,8 @@ InstructionTLBMiss:
|
||||
mtspr SPRN_MI_RPN, r10 /* Update TLB entry */
|
||||
|
||||
/* Restore registers */
|
||||
0: mfspr r10, SPRN_SPRG_SCRATCH0
|
||||
mfspr r11, SPRN_SPRG_SCRATCH1
|
||||
0: mfspr r10, SPRN_SPRG_SCRATCH2
|
||||
mfspr r11, SPRN_M_TW
|
||||
rfi
|
||||
patch_site 0b, patch__itlbmiss_exit_1
|
||||
|
||||
@@ -251,14 +240,14 @@ InstructionTLBMiss:
|
||||
0: lwz r10, (itlb_miss_counter - PAGE_OFFSET)@l(0)
|
||||
addi r10, r10, 1
|
||||
stw r10, (itlb_miss_counter - PAGE_OFFSET)@l(0)
|
||||
mfspr r10, SPRN_SPRG_SCRATCH0
|
||||
mfspr r11, SPRN_SPRG_SCRATCH1
|
||||
mfspr r10, SPRN_SPRG_SCRATCH2
|
||||
mfspr r11, SPRN_M_TW
|
||||
rfi
|
||||
#endif
|
||||
|
||||
. = 0x1200
|
||||
DataStoreTLBMiss:
|
||||
mtspr SPRN_DAR, r10
|
||||
mtspr SPRN_SPRG_SCRATCH2, r10
|
||||
mtspr SPRN_M_TW, r11
|
||||
mfcr r11
|
||||
|
||||
@@ -297,11 +286,11 @@ DataStoreTLBMiss:
|
||||
li r11, RPN_PATTERN
|
||||
rlwimi r10, r11, 0, 24, 27 /* Set 24-27 */
|
||||
mtspr SPRN_MD_RPN, r10 /* Update TLB entry */
|
||||
mtspr SPRN_DAR, r11 /* Tag DAR */
|
||||
|
||||
/* Restore registers */
|
||||
|
||||
0: mfspr r10, SPRN_DAR
|
||||
mtspr SPRN_DAR, r11 /* Tag DAR */
|
||||
0: mfspr r10, SPRN_SPRG_SCRATCH2
|
||||
mfspr r11, SPRN_M_TW
|
||||
rfi
|
||||
patch_site 0b, patch__dtlbmiss_exit_1
|
||||
@@ -311,8 +300,7 @@ DataStoreTLBMiss:
|
||||
0: lwz r10, (dtlb_miss_counter - PAGE_OFFSET)@l(0)
|
||||
addi r10, r10, 1
|
||||
stw r10, (dtlb_miss_counter - PAGE_OFFSET)@l(0)
|
||||
mfspr r10, SPRN_DAR
|
||||
mtspr SPRN_DAR, r11 /* Tag DAR */
|
||||
mfspr r10, SPRN_SPRG_SCRATCH2
|
||||
mfspr r11, SPRN_M_TW
|
||||
rfi
|
||||
#endif
|
||||
@@ -619,10 +607,6 @@ start_here:
|
||||
lis r0, (MD_TWAM | MD_RSV4I)@h
|
||||
mtspr SPRN_MD_CTR, r0
|
||||
#endif
|
||||
#ifndef CONFIG_PIN_TLB_TEXT
|
||||
li r0, 0
|
||||
mtspr SPRN_MI_CTR, r0
|
||||
#endif
|
||||
#if !defined(CONFIG_PIN_TLB_DATA) && !defined(CONFIG_PIN_TLB_IMMR)
|
||||
lis r0, MD_TWAM@h
|
||||
mtspr SPRN_MD_CTR, r0
|
||||
@@ -718,7 +702,6 @@ initial_mmu:
|
||||
mtspr SPRN_DER, r8
|
||||
blr
|
||||
|
||||
#ifdef CONFIG_PIN_TLB
|
||||
_GLOBAL(mmu_pin_tlb)
|
||||
lis r9, (1f - PAGE_OFFSET)@h
|
||||
ori r9, r9, (1f - PAGE_OFFSET)@l
|
||||
@@ -740,7 +723,6 @@ _GLOBAL(mmu_pin_tlb)
|
||||
mtspr SPRN_MD_CTR, r6
|
||||
tlbia
|
||||
|
||||
#ifdef CONFIG_PIN_TLB_TEXT
|
||||
LOAD_REG_IMMEDIATE(r5, 28 << 8)
|
||||
LOAD_REG_IMMEDIATE(r6, PAGE_OFFSET)
|
||||
LOAD_REG_IMMEDIATE(r7, MI_SVALID | MI_PS8MEG | _PMD_ACCESSED)
|
||||
@@ -761,7 +743,7 @@ _GLOBAL(mmu_pin_tlb)
|
||||
bdnzt lt, 2b
|
||||
lis r0, MI_RSV4I@h
|
||||
mtspr SPRN_MI_CTR, r0
|
||||
#endif
|
||||
|
||||
LOAD_REG_IMMEDIATE(r5, 28 << 8 | MD_TWAM)
|
||||
#ifdef CONFIG_PIN_TLB_DATA
|
||||
LOAD_REG_IMMEDIATE(r6, PAGE_OFFSET)
|
||||
@@ -819,7 +801,6 @@ _GLOBAL(mmu_pin_tlb)
|
||||
mtspr SPRN_SRR1, r10
|
||||
mtspr SPRN_SRR0, r11
|
||||
rfi
|
||||
#endif /* CONFIG_PIN_TLB */
|
||||
|
||||
/*
|
||||
* We put a few things here that have to be page-aligned.
|
||||
|
||||
@@ -155,10 +155,8 @@ __after_mmu_off:
|
||||
|
||||
bl initial_bats
|
||||
bl load_segment_registers
|
||||
BEGIN_MMU_FTR_SECTION
|
||||
bl reloc_offset
|
||||
bl early_hash_table
|
||||
END_MMU_FTR_SECTION_IFSET(MMU_FTR_HPTE_TABLE)
|
||||
#if defined(CONFIG_BOOTX_TEXT)
|
||||
bl setup_disp_bat
|
||||
#endif
|
||||
@@ -207,7 +205,7 @@ turn_on_mmu:
|
||||
lis r0,start_here@h
|
||||
ori r0,r0,start_here@l
|
||||
mtspr SPRN_SRR0,r0
|
||||
RFI /* enables MMU */
|
||||
rfi /* enables MMU */
|
||||
|
||||
/*
|
||||
* We need __secondary_hold as a place to hold the other cpus on
|
||||
@@ -288,51 +286,35 @@ MachineCheck:
|
||||
DO_KVM 0x300
|
||||
DataAccess:
|
||||
#ifdef CONFIG_VMAP_STACK
|
||||
mtspr SPRN_SPRG_SCRATCH0,r10
|
||||
mfspr r10, SPRN_SPRG_THREAD
|
||||
BEGIN_MMU_FTR_SECTION
|
||||
mtspr SPRN_SPRG_SCRATCH2,r10
|
||||
mfspr r10, SPRN_SPRG_THREAD
|
||||
stw r11, THR11(r10)
|
||||
mfspr r10, SPRN_DSISR
|
||||
mfcr r11
|
||||
#ifdef CONFIG_PPC_KUAP
|
||||
andis. r10, r10, (DSISR_BAD_FAULT_32S | DSISR_DABRMATCH | DSISR_PROTFAULT)@h
|
||||
#else
|
||||
andis. r10, r10, (DSISR_BAD_FAULT_32S | DSISR_DABRMATCH)@h
|
||||
#endif
|
||||
mfspr r10, SPRN_SPRG_THREAD
|
||||
beq hash_page_dsi
|
||||
.Lhash_page_dsi_cont:
|
||||
mtcr r11
|
||||
lwz r11, THR11(r10)
|
||||
END_MMU_FTR_SECTION_IFSET(MMU_FTR_HPTE_TABLE)
|
||||
mtspr SPRN_SPRG_SCRATCH1,r11
|
||||
mfspr r11, SPRN_DAR
|
||||
stw r11, DAR(r10)
|
||||
mfspr r11, SPRN_DSISR
|
||||
stw r11, DSISR(r10)
|
||||
mfspr r11, SPRN_SRR0
|
||||
stw r11, SRR0(r10)
|
||||
mfspr r11, SPRN_SRR1 /* check whether user or kernel */
|
||||
stw r11, SRR1(r10)
|
||||
mfcr r10
|
||||
andi. r11, r11, MSR_PR
|
||||
|
||||
mfspr r10, SPRN_SPRG_SCRATCH2
|
||||
MMU_FTR_SECTION_ELSE
|
||||
b 1f
|
||||
ALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_HPTE_TABLE)
|
||||
1: EXCEPTION_PROLOG_0 handle_dar_dsisr=1
|
||||
EXCEPTION_PROLOG_1
|
||||
b handle_page_fault_tramp_1
|
||||
#else /* CONFIG_VMAP_STACK */
|
||||
EXCEPTION_PROLOG handle_dar_dsisr=1
|
||||
get_and_save_dar_dsisr_on_stack r4, r5, r11
|
||||
BEGIN_MMU_FTR_SECTION
|
||||
#ifdef CONFIG_PPC_KUAP
|
||||
andis. r0, r5, (DSISR_BAD_FAULT_32S | DSISR_DABRMATCH | DSISR_PROTFAULT)@h
|
||||
#else
|
||||
andis. r0, r5, (DSISR_BAD_FAULT_32S | DSISR_DABRMATCH)@h
|
||||
#endif
|
||||
bne handle_page_fault_tramp_2 /* if not, try to put a PTE */
|
||||
rlwinm r3, r5, 32 - 15, 21, 21 /* DSISR_STORE -> _PAGE_RW */
|
||||
bl hash_page
|
||||
b handle_page_fault_tramp_1
|
||||
FTR_SECTION_ELSE
|
||||
MMU_FTR_SECTION_ELSE
|
||||
b handle_page_fault_tramp_2
|
||||
ALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_HPTE_TABLE)
|
||||
#endif /* CONFIG_VMAP_STACK */
|
||||
@@ -394,6 +376,7 @@ Alignment:
|
||||
. = 0x800
|
||||
DO_KVM 0x800
|
||||
FPUnavailable:
|
||||
#ifdef CONFIG_PPC_FPU
|
||||
BEGIN_FTR_SECTION
|
||||
/*
|
||||
* Certain Freescale cores don't have a FPU and treat fp instructions
|
||||
@@ -407,6 +390,9 @@ END_FTR_SECTION_IFSET(CPU_FTR_FPU_UNAVAILABLE)
|
||||
b fast_exception_return
|
||||
1: addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
EXC_XFER_LITE(0x800, kernel_fp_unavailable_exception)
|
||||
#else
|
||||
b ProgramCheck
|
||||
#endif
|
||||
|
||||
/* Decrementer */
|
||||
EXCEPTION(0x900, Decrementer, timer_interrupt, EXC_XFER_LITE)
|
||||
@@ -453,13 +439,14 @@ InstructionTLBMiss:
|
||||
*/
|
||||
/* Get PTE (linux-style) and check access */
|
||||
mfspr r3,SPRN_IMISS
|
||||
#if defined(CONFIG_MODULES) || defined(CONFIG_DEBUG_PAGEALLOC)
|
||||
#ifdef CONFIG_MODULES
|
||||
lis r1, TASK_SIZE@h /* check if kernel address */
|
||||
cmplw 0,r1,r3
|
||||
#endif
|
||||
mfspr r2, SPRN_SPRG_PGDIR
|
||||
mfspr r2, SPRN_SDR1
|
||||
li r1,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC
|
||||
#if defined(CONFIG_MODULES) || defined(CONFIG_DEBUG_PAGEALLOC)
|
||||
rlwinm r2, r2, 28, 0xfffff000
|
||||
#ifdef CONFIG_MODULES
|
||||
bgt- 112f
|
||||
lis r2, (swapper_pg_dir - PAGE_OFFSET)@ha /* if kernel address, use */
|
||||
addi r2, r2, (swapper_pg_dir - PAGE_OFFSET)@l /* kernel page table */
|
||||
@@ -519,8 +506,9 @@ DataLoadTLBMiss:
|
||||
mfspr r3,SPRN_DMISS
|
||||
lis r1, TASK_SIZE@h /* check if kernel address */
|
||||
cmplw 0,r1,r3
|
||||
mfspr r2, SPRN_SPRG_PGDIR
|
||||
mfspr r2, SPRN_SDR1
|
||||
li r1, _PAGE_PRESENT | _PAGE_ACCESSED
|
||||
rlwinm r2, r2, 28, 0xfffff000
|
||||
bgt- 112f
|
||||
lis r2, (swapper_pg_dir - PAGE_OFFSET)@ha /* if kernel address, use */
|
||||
addi r2, r2, (swapper_pg_dir - PAGE_OFFSET)@l /* kernel page table */
|
||||
@@ -595,8 +583,9 @@ DataStoreTLBMiss:
|
||||
mfspr r3,SPRN_DMISS
|
||||
lis r1, TASK_SIZE@h /* check if kernel address */
|
||||
cmplw 0,r1,r3
|
||||
mfspr r2, SPRN_SPRG_PGDIR
|
||||
mfspr r2, SPRN_SDR1
|
||||
li r1, _PAGE_RW | _PAGE_DIRTY | _PAGE_PRESENT | _PAGE_ACCESSED
|
||||
rlwinm r2, r2, 28, 0xfffff000
|
||||
bgt- 112f
|
||||
lis r2, (swapper_pg_dir - PAGE_OFFSET)@ha /* if kernel address, use */
|
||||
addi r2, r2, (swapper_pg_dir - PAGE_OFFSET)@l /* kernel page table */
|
||||
@@ -757,14 +746,14 @@ fast_hash_page_return:
|
||||
/* DSI */
|
||||
mtcr r11
|
||||
lwz r11, THR11(r10)
|
||||
mfspr r10, SPRN_SPRG_SCRATCH0
|
||||
RFI
|
||||
mfspr r10, SPRN_SPRG_SCRATCH2
|
||||
rfi
|
||||
|
||||
1: /* ISI */
|
||||
mtcr r11
|
||||
mfspr r11, SPRN_SPRG_SCRATCH1
|
||||
mfspr r10, SPRN_SPRG_SCRATCH0
|
||||
RFI
|
||||
rfi
|
||||
|
||||
stack_overflow:
|
||||
vmap_stack_overflow_exception
|
||||
@@ -889,9 +878,12 @@ __secondary_start:
|
||||
tophys(r4,r2)
|
||||
addi r4,r4,THREAD /* phys address of our thread_struct */
|
||||
mtspr SPRN_SPRG_THREAD,r4
|
||||
BEGIN_MMU_FTR_SECTION
|
||||
lis r4, (swapper_pg_dir - PAGE_OFFSET)@h
|
||||
ori r4, r4, (swapper_pg_dir - PAGE_OFFSET)@l
|
||||
mtspr SPRN_SPRG_PGDIR, r4
|
||||
rlwinm r4, r4, 4, 0xffff01ff
|
||||
mtspr SPRN_SDR1, r4
|
||||
END_MMU_FTR_SECTION_IFCLR(MMU_FTR_HPTE_TABLE)
|
||||
|
||||
/* enable MMU and jump to start_secondary */
|
||||
li r4,MSR_KERNEL
|
||||
@@ -899,7 +891,7 @@ __secondary_start:
|
||||
ori r3,r3,start_secondary@l
|
||||
mtspr SPRN_SRR0,r3
|
||||
mtspr SPRN_SRR1,r4
|
||||
RFI
|
||||
rfi
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
#ifdef CONFIG_KVM_BOOK3S_HANDLER
|
||||
@@ -920,9 +912,6 @@ early_hash_table:
|
||||
lis r6, early_hash - PAGE_OFFSET@h
|
||||
ori r6, r6, 3 /* 256kB table */
|
||||
mtspr SPRN_SDR1, r6
|
||||
lis r6, early_hash@h
|
||||
addis r3, r3, Hash@ha
|
||||
stw r6, Hash@l(r3)
|
||||
blr
|
||||
|
||||
load_up_mmu:
|
||||
@@ -931,11 +920,13 @@ load_up_mmu:
|
||||
tlbia /* Clear all TLB entries */
|
||||
sync /* wait for tlbia/tlbie to finish */
|
||||
TLBSYNC /* ... on all CPUs */
|
||||
BEGIN_MMU_FTR_SECTION
|
||||
/* Load the SDR1 register (hash table base & size) */
|
||||
lis r6,_SDR1@ha
|
||||
tophys(r6,r6)
|
||||
lwz r6,_SDR1@l(r6)
|
||||
mtspr SPRN_SDR1,r6
|
||||
END_MMU_FTR_SECTION_IFSET(MMU_FTR_HPTE_TABLE)
|
||||
|
||||
/* Load the BAT registers with the values set up by MMU_init. */
|
||||
lis r3,BATS@ha
|
||||
@@ -991,9 +982,12 @@ start_here:
|
||||
tophys(r4,r2)
|
||||
addi r4,r4,THREAD /* init task's THREAD */
|
||||
mtspr SPRN_SPRG_THREAD,r4
|
||||
BEGIN_MMU_FTR_SECTION
|
||||
lis r4, (swapper_pg_dir - PAGE_OFFSET)@h
|
||||
ori r4, r4, (swapper_pg_dir - PAGE_OFFSET)@l
|
||||
mtspr SPRN_SPRG_PGDIR, r4
|
||||
rlwinm r4, r4, 4, 0xffff01ff
|
||||
mtspr SPRN_SDR1, r4
|
||||
END_MMU_FTR_SECTION_IFCLR(MMU_FTR_HPTE_TABLE)
|
||||
|
||||
/* stack */
|
||||
lis r1,init_thread_union@ha
|
||||
@@ -1027,7 +1021,7 @@ start_here:
|
||||
.align 4
|
||||
mtspr SPRN_SRR0,r4
|
||||
mtspr SPRN_SRR1,r3
|
||||
RFI
|
||||
rfi
|
||||
/* Load up the kernel context */
|
||||
2: bl load_up_mmu
|
||||
|
||||
@@ -1051,7 +1045,7 @@ start_here:
|
||||
ori r3,r3,start_kernel@l
|
||||
mtspr SPRN_SRR0,r3
|
||||
mtspr SPRN_SRR1,r4
|
||||
RFI
|
||||
rfi
|
||||
|
||||
/*
|
||||
* void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next);
|
||||
@@ -1073,16 +1067,22 @@ _ENTRY(switch_mmu_context)
|
||||
li r0,NUM_USER_SEGMENTS
|
||||
mtctr r0
|
||||
|
||||
lwz r4, MM_PGD(r4)
|
||||
#ifdef CONFIG_BDI_SWITCH
|
||||
/* Context switch the PTE pointer for the Abatron BDI2000.
|
||||
* The PGDIR is passed as second argument.
|
||||
*/
|
||||
lwz r4, MM_PGD(r4)
|
||||
lis r5, abatron_pteptrs@ha
|
||||
stw r4, abatron_pteptrs@l + 0x4(r5)
|
||||
#endif
|
||||
BEGIN_MMU_FTR_SECTION
|
||||
#ifndef CONFIG_BDI_SWITCH
|
||||
lwz r4, MM_PGD(r4)
|
||||
#endif
|
||||
tophys(r4, r4)
|
||||
mtspr SPRN_SPRG_PGDIR, r4
|
||||
rlwinm r4, r4, 4, 0xffff01ff
|
||||
mtspr SPRN_SDR1, r4
|
||||
END_MMU_FTR_SECTION_IFCLR(MMU_FTR_HPTE_TABLE)
|
||||
li r4,0
|
||||
isync
|
||||
3:
|
||||
@@ -1166,7 +1166,7 @@ _ENTRY(update_bats)
|
||||
.align 4
|
||||
mtspr SPRN_SRR0, r4
|
||||
mtspr SPRN_SRR1, r3
|
||||
RFI
|
||||
rfi
|
||||
1: bl clear_bats
|
||||
lis r3, BATS@ha
|
||||
addi r3, r3, BATS@l
|
||||
@@ -1185,7 +1185,7 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
|
||||
mtmsr r3
|
||||
mtspr SPRN_SRR0, r7
|
||||
mtspr SPRN_SRR1, r6
|
||||
RFI
|
||||
rfi
|
||||
|
||||
flush_tlbs:
|
||||
lis r10, 0x40
|
||||
@@ -1206,7 +1206,7 @@ mmu_off:
|
||||
mtspr SPRN_SRR0,r4
|
||||
mtspr SPRN_SRR1,r3
|
||||
sync
|
||||
RFI
|
||||
rfi
|
||||
|
||||
/* We use one BAT to map up to 256M of RAM at _PAGE_OFFSET */
|
||||
initial_bats:
|
||||
|
||||
@@ -176,7 +176,7 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_EMB_HV)
|
||||
#endif
|
||||
mtspr SPRN_SRR1,r10
|
||||
mtspr SPRN_SRR0,r11
|
||||
RFI /* jump to handler, enable MMU */
|
||||
rfi /* jump to handler, enable MMU */
|
||||
99: b ret_from_kernel_syscall
|
||||
.endm
|
||||
|
||||
@@ -185,7 +185,6 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_EMB_HV)
|
||||
*
|
||||
* On 40x critical is the only additional level
|
||||
* On 44x/e500 we have critical and machine check
|
||||
* On e200 we have critical and debug (machine check occurs via critical)
|
||||
*
|
||||
* Additionally we reserve a SPRG for each priority level so we can free up a
|
||||
* GPR to use as the base for indirect access to the exception stacks. This
|
||||
@@ -201,7 +200,7 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_EMB_HV)
|
||||
#define MC_STACK_BASE mcheckirq_ctx
|
||||
#define CRIT_STACK_BASE critirq_ctx
|
||||
|
||||
/* only on e500mc/e200 */
|
||||
/* only on e500mc */
|
||||
#define DBG_STACK_BASE dbgirq_ctx
|
||||
|
||||
#define EXC_LVL_FRAME_OVERHEAD (THREAD_SIZE - INT_FRAME_SIZE - EXC_LVL_SIZE)
|
||||
|
||||
@@ -187,9 +187,6 @@ set_ivor:
|
||||
|
||||
/* Setup the defaults for TLB entries */
|
||||
li r2,(MAS4_TSIZED(BOOK3E_PAGESZ_4K))@l
|
||||
#ifdef CONFIG_E200
|
||||
oris r2,r2,MAS4_TLBSELD(1)@h
|
||||
#endif
|
||||
mtspr SPRN_MAS4, r2
|
||||
|
||||
#if !defined(CONFIG_BDI_SWITCH)
|
||||
@@ -362,13 +359,7 @@ interrupt_base:
|
||||
CRITICAL_EXCEPTION(0x0100, CRITICAL, CriticalInput, unknown_exception)
|
||||
|
||||
/* Machine Check Interrupt */
|
||||
#ifdef CONFIG_E200
|
||||
/* no RFMCI, MCSRRs on E200 */
|
||||
CRITICAL_EXCEPTION(0x0200, MACHINE_CHECK, MachineCheck, \
|
||||
machine_check_exception)
|
||||
#else
|
||||
MCHECK_EXCEPTION(0x0200, MachineCheck, machine_check_exception)
|
||||
#endif
|
||||
|
||||
/* Data Storage Interrupt */
|
||||
START_EXCEPTION(DataStorage)
|
||||
@@ -399,15 +390,9 @@ interrupt_base:
|
||||
/* Floating Point Unavailable Interrupt */
|
||||
#ifdef CONFIG_PPC_FPU
|
||||
FP_UNAVAILABLE_EXCEPTION
|
||||
#else
|
||||
#ifdef CONFIG_E200
|
||||
/* E200 treats 'normal' floating point instructions as FP Unavail exception */
|
||||
EXCEPTION(0x0800, FP_UNAVAIL, FloatingPointUnavailable, \
|
||||
program_check_exception, EXC_XFER_STD)
|
||||
#else
|
||||
EXCEPTION(0x0800, FP_UNAVAIL, FloatingPointUnavailable, \
|
||||
unknown_exception, EXC_XFER_STD)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* System Call Interrupt */
|
||||
@@ -625,7 +610,7 @@ END_BTB_FLUSH_SECTION
|
||||
mfspr r10, SPRN_SPRG_RSCRATCH0
|
||||
b InstructionStorage
|
||||
|
||||
/* Define SPE handlers for e200 and e500v2 */
|
||||
/* Define SPE handlers for e500v2 */
|
||||
#ifdef CONFIG_SPE
|
||||
/* SPE Unavailable */
|
||||
START_EXCEPTION(SPEUnavailable)
|
||||
@@ -807,31 +792,6 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_BIG_PHYS)
|
||||
#endif
|
||||
3: mtspr SPRN_MAS2, r12
|
||||
|
||||
#ifdef CONFIG_E200
|
||||
/* Round robin TLB1 entries assignment */
|
||||
mfspr r12, SPRN_MAS0
|
||||
|
||||
/* Extract TLB1CFG(NENTRY) */
|
||||
mfspr r11, SPRN_TLB1CFG
|
||||
andi. r11, r11, 0xfff
|
||||
|
||||
/* Extract MAS0(NV) */
|
||||
andi. r13, r12, 0xfff
|
||||
addi r13, r13, 1
|
||||
cmpw 0, r13, r11
|
||||
addi r12, r12, 1
|
||||
|
||||
/* check if we need to wrap */
|
||||
blt 7f
|
||||
|
||||
/* wrap back to first free tlbcam entry */
|
||||
lis r13, tlbcam_index@ha
|
||||
lwz r13, tlbcam_index@l(r13)
|
||||
rlwimi r12, r13, 0, 20, 31
|
||||
7:
|
||||
mtspr SPRN_MAS0,r12
|
||||
#endif /* CONFIG_E200 */
|
||||
|
||||
tlb_write_entry:
|
||||
tlbwe
|
||||
|
||||
@@ -933,21 +893,6 @@ get_phys_addr:
|
||||
* Global functions
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_E200
|
||||
/* Adjust or setup IVORs for e200 */
|
||||
_GLOBAL(__setup_e200_ivors)
|
||||
li r3,DebugDebug@l
|
||||
mtspr SPRN_IVOR15,r3
|
||||
li r3,SPEUnavailable@l
|
||||
mtspr SPRN_IVOR32,r3
|
||||
li r3,SPEFloatingPointData@l
|
||||
mtspr SPRN_IVOR33,r3
|
||||
li r3,SPEFloatingPointRound@l
|
||||
mtspr SPRN_IVOR34,r3
|
||||
sync
|
||||
blr
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_E500
|
||||
#ifndef CONFIG_PPC_E500MC
|
||||
/* Adjust or setup IVORs for e500v1/v2 */
|
||||
|
||||
@@ -499,6 +499,11 @@ static bool is_larx_stcx_instr(int type)
|
||||
return type == LARX || type == STCX;
|
||||
}
|
||||
|
||||
static bool is_octword_vsx_instr(int type, int size)
|
||||
{
|
||||
return ((type == LOAD_VSX || type == STORE_VSX) && size == 32);
|
||||
}
|
||||
|
||||
/*
|
||||
* We've failed in reliably handling the hw-breakpoint. Unregister
|
||||
* it and throw a warning message to let the user know about it.
|
||||
@@ -549,6 +554,58 @@ static bool stepping_handler(struct pt_regs *regs, struct perf_event **bp,
|
||||
return true;
|
||||
}
|
||||
|
||||
static void handle_p10dd1_spurious_exception(struct arch_hw_breakpoint **info,
|
||||
int *hit, unsigned long ea)
|
||||
{
|
||||
int i;
|
||||
unsigned long hw_end_addr;
|
||||
|
||||
/*
|
||||
* Handle spurious exception only when any bp_per_reg is set.
|
||||
* Otherwise this might be created by xmon and not actually a
|
||||
* spurious exception.
|
||||
*/
|
||||
for (i = 0; i < nr_wp_slots(); i++) {
|
||||
if (!info[i])
|
||||
continue;
|
||||
|
||||
hw_end_addr = ALIGN(info[i]->address + info[i]->len, HW_BREAKPOINT_SIZE);
|
||||
|
||||
/*
|
||||
* Ending address of DAWR range is less than starting
|
||||
* address of op.
|
||||
*/
|
||||
if ((hw_end_addr - 1) >= ea)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Those addresses need to be in the same or in two
|
||||
* consecutive 512B blocks;
|
||||
*/
|
||||
if (((hw_end_addr - 1) >> 10) != (ea >> 10))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* 'op address + 64B' generates an address that has a
|
||||
* carry into bit 52 (crosses 2K boundary).
|
||||
*/
|
||||
if ((ea & 0x800) == ((ea + 64) & 0x800))
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == nr_wp_slots())
|
||||
return;
|
||||
|
||||
for (i = 0; i < nr_wp_slots(); i++) {
|
||||
if (info[i]) {
|
||||
hit[i] = 1;
|
||||
info[i]->type |= HW_BRK_TYPE_EXTRANEOUS_IRQ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int hw_breakpoint_handler(struct die_args *args)
|
||||
{
|
||||
bool err = false;
|
||||
@@ -607,8 +664,14 @@ int hw_breakpoint_handler(struct die_args *args)
|
||||
goto reset;
|
||||
|
||||
if (!nr_hit) {
|
||||
rc = NOTIFY_DONE;
|
||||
goto out;
|
||||
/* Workaround for Power10 DD1 */
|
||||
if (!IS_ENABLED(CONFIG_PPC_8xx) && mfspr(SPRN_PVR) == 0x800100 &&
|
||||
is_octword_vsx_instr(type, size)) {
|
||||
handle_p10dd1_spurious_exception(info, hit, ea);
|
||||
} else {
|
||||
rc = NOTIFY_DONE;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -11,177 +11,11 @@
|
||||
#include <asm/pci-bridge.h>
|
||||
#include <asm/isa-bridge.h>
|
||||
|
||||
/*
|
||||
* Here comes the ppc64 implementation of the IOMAP
|
||||
* interfaces.
|
||||
*/
|
||||
unsigned int ioread8(const void __iomem *addr)
|
||||
{
|
||||
return readb(addr);
|
||||
}
|
||||
unsigned int ioread16(const void __iomem *addr)
|
||||
{
|
||||
return readw(addr);
|
||||
}
|
||||
unsigned int ioread16be(const void __iomem *addr)
|
||||
{
|
||||
return readw_be(addr);
|
||||
}
|
||||
unsigned int ioread32(const void __iomem *addr)
|
||||
{
|
||||
return readl(addr);
|
||||
}
|
||||
unsigned int ioread32be(const void __iomem *addr)
|
||||
{
|
||||
return readl_be(addr);
|
||||
}
|
||||
EXPORT_SYMBOL(ioread8);
|
||||
EXPORT_SYMBOL(ioread16);
|
||||
EXPORT_SYMBOL(ioread16be);
|
||||
EXPORT_SYMBOL(ioread32);
|
||||
EXPORT_SYMBOL(ioread32be);
|
||||
#ifdef __powerpc64__
|
||||
u64 ioread64(const void __iomem *addr)
|
||||
{
|
||||
return readq(addr);
|
||||
}
|
||||
u64 ioread64_lo_hi(const void __iomem *addr)
|
||||
{
|
||||
return readq(addr);
|
||||
}
|
||||
u64 ioread64_hi_lo(const void __iomem *addr)
|
||||
{
|
||||
return readq(addr);
|
||||
}
|
||||
u64 ioread64be(const void __iomem *addr)
|
||||
{
|
||||
return readq_be(addr);
|
||||
}
|
||||
u64 ioread64be_lo_hi(const void __iomem *addr)
|
||||
{
|
||||
return readq_be(addr);
|
||||
}
|
||||
u64 ioread64be_hi_lo(const void __iomem *addr)
|
||||
{
|
||||
return readq_be(addr);
|
||||
}
|
||||
EXPORT_SYMBOL(ioread64);
|
||||
EXPORT_SYMBOL(ioread64_lo_hi);
|
||||
EXPORT_SYMBOL(ioread64_hi_lo);
|
||||
EXPORT_SYMBOL(ioread64be);
|
||||
EXPORT_SYMBOL(ioread64be_lo_hi);
|
||||
EXPORT_SYMBOL(ioread64be_hi_lo);
|
||||
#endif /* __powerpc64__ */
|
||||
|
||||
void iowrite8(u8 val, void __iomem *addr)
|
||||
{
|
||||
writeb(val, addr);
|
||||
}
|
||||
void iowrite16(u16 val, void __iomem *addr)
|
||||
{
|
||||
writew(val, addr);
|
||||
}
|
||||
void iowrite16be(u16 val, void __iomem *addr)
|
||||
{
|
||||
writew_be(val, addr);
|
||||
}
|
||||
void iowrite32(u32 val, void __iomem *addr)
|
||||
{
|
||||
writel(val, addr);
|
||||
}
|
||||
void iowrite32be(u32 val, void __iomem *addr)
|
||||
{
|
||||
writel_be(val, addr);
|
||||
}
|
||||
EXPORT_SYMBOL(iowrite8);
|
||||
EXPORT_SYMBOL(iowrite16);
|
||||
EXPORT_SYMBOL(iowrite16be);
|
||||
EXPORT_SYMBOL(iowrite32);
|
||||
EXPORT_SYMBOL(iowrite32be);
|
||||
#ifdef __powerpc64__
|
||||
void iowrite64(u64 val, void __iomem *addr)
|
||||
{
|
||||
writeq(val, addr);
|
||||
}
|
||||
void iowrite64_lo_hi(u64 val, void __iomem *addr)
|
||||
{
|
||||
writeq(val, addr);
|
||||
}
|
||||
void iowrite64_hi_lo(u64 val, void __iomem *addr)
|
||||
{
|
||||
writeq(val, addr);
|
||||
}
|
||||
void iowrite64be(u64 val, void __iomem *addr)
|
||||
{
|
||||
writeq_be(val, addr);
|
||||
}
|
||||
void iowrite64be_lo_hi(u64 val, void __iomem *addr)
|
||||
{
|
||||
writeq_be(val, addr);
|
||||
}
|
||||
void iowrite64be_hi_lo(u64 val, void __iomem *addr)
|
||||
{
|
||||
writeq_be(val, addr);
|
||||
}
|
||||
EXPORT_SYMBOL(iowrite64);
|
||||
EXPORT_SYMBOL(iowrite64_lo_hi);
|
||||
EXPORT_SYMBOL(iowrite64_hi_lo);
|
||||
EXPORT_SYMBOL(iowrite64be);
|
||||
EXPORT_SYMBOL(iowrite64be_lo_hi);
|
||||
EXPORT_SYMBOL(iowrite64be_hi_lo);
|
||||
#endif /* __powerpc64__ */
|
||||
|
||||
/*
|
||||
* These are the "repeat read/write" functions. Note the
|
||||
* non-CPU byte order. We do things in "IO byteorder"
|
||||
* here.
|
||||
*
|
||||
* FIXME! We could make these do EEH handling if we really
|
||||
* wanted. Not clear if we do.
|
||||
*/
|
||||
void ioread8_rep(const void __iomem *addr, void *dst, unsigned long count)
|
||||
{
|
||||
readsb(addr, dst, count);
|
||||
}
|
||||
void ioread16_rep(const void __iomem *addr, void *dst, unsigned long count)
|
||||
{
|
||||
readsw(addr, dst, count);
|
||||
}
|
||||
void ioread32_rep(const void __iomem *addr, void *dst, unsigned long count)
|
||||
{
|
||||
readsl(addr, dst, count);
|
||||
}
|
||||
EXPORT_SYMBOL(ioread8_rep);
|
||||
EXPORT_SYMBOL(ioread16_rep);
|
||||
EXPORT_SYMBOL(ioread32_rep);
|
||||
|
||||
void iowrite8_rep(void __iomem *addr, const void *src, unsigned long count)
|
||||
{
|
||||
writesb(addr, src, count);
|
||||
}
|
||||
void iowrite16_rep(void __iomem *addr, const void *src, unsigned long count)
|
||||
{
|
||||
writesw(addr, src, count);
|
||||
}
|
||||
void iowrite32_rep(void __iomem *addr, const void *src, unsigned long count)
|
||||
{
|
||||
writesl(addr, src, count);
|
||||
}
|
||||
EXPORT_SYMBOL(iowrite8_rep);
|
||||
EXPORT_SYMBOL(iowrite16_rep);
|
||||
EXPORT_SYMBOL(iowrite32_rep);
|
||||
|
||||
void __iomem *ioport_map(unsigned long port, unsigned int len)
|
||||
{
|
||||
return (void __iomem *) (port + _IO_BASE);
|
||||
}
|
||||
|
||||
void ioport_unmap(void __iomem *addr)
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
EXPORT_SYMBOL(ioport_map);
|
||||
EXPORT_SYMBOL(ioport_unmap);
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user