mirror of
https://github.com/torvalds/linux.git
synced 2026-09-14 16:10:02 +02:00
powerpc updates for 7.3
- powerpc: Enable Rust for ppc64le - ppc4xx gpio driver updates - Add power12 base enablement support - Validate arch_compat against host compatibility mode - Simplify bootx_scan_dt_build_struct() in powermac platform - powerpc: implement get_direction() in cpm2 - Use cpu_relax() in ps3_create_spu() - Add NULL guard for cause_ipi in smp_muxed_ipi_message_pass - fixes to handle pseries watchdogs in kdump path - powerpc/irq: Fix missing r2 clobber in PCREL inline assembly - ppc44x: Set GPIO chip parent - KVM: PPC: Introduce KVM_CAP_PPC_COMPAT_CAPS and wire up ioctl BY: Amit Machhiwal - KVM: powerpc: Use generic xfer to guest work function - Enable to run posix cpu timers in task context - misc fixes and cleanups Thanks to: Aditya Gupta, Alice Ryhl, Amit Machhiwal, Andrew Morton, Anushree Mathur, Athira Rajeev, Bartosz Golaszewski, Cédric Le Goater, Christian König, Christophe Leroy (CS GROUP), Gary Guo, Gaurav Batra, Gautam Menghani, Gou Hao, Hari Bathini, Harsh Prateek Bora, jiazhenyuan, Jinjie Ruan, Link Mauve, Linus Walleij, Mahesh Kumar G Mahesh Salgaonkar, Michael Walle, Michal Suchánek, Mukesh Kumar Chaurasiya (IBM), Nicholas Piggin, Nikhil Kumar Singh, Praveen K Pandey, Ritesh Harjani (IBM), Rosen Penev, Saket Kumar Bhaskar, Shrikanth Hegde, Sourabh Jain, Thorsten Blum, Vaibhav Jain, Venkat Rao Bagalkote, Vishal Chourasia, Wentao Guan, Yanfei Xu -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEqX2DNAOgU8sBX3pRpnEsdPSHZJQFAmqCj/4ACgkQpnEsdPSH ZJSKNg//VNpbzMKVPrdljgLn3P8/flWUUMvbjT0j2s5OExeFPjM9tvJQucMficJz eQWaEZbaczRPdtBDt96NXXDIoXGpfapS1Tj18OjVjCRtQdKV4DGfNdE5wC2tKwvA 1R6x5FT6pGxCRuNY9o3aAo/qcEJLCWCtOvrgdlT8C9ZV8Zh/GRl5TXBYqB4LFYAd WI1Jc4s97VFNtPSh7HtImd5n8T8vNWqQzi1rUAWTYQPduV8eHKFhnyu9vIh2ISv8 p6dZzE6mLrgn7zU8HW2z5nRyRZFRXtWt3i7/0IGSsJYtBoREsFw2d3LJfwMZXwdU hXNbw9OlwDmPUF8+qFIEVu3czfiFW1naNEXP00NJfM+67acXIpFEiJ/LvuLENzC4 gtX1VKUCQthWxJESnX1WrKnP7BAjUGe691CronRoYIJNctLnrCA7SOfJ2El4i40v v0+oz8KceGE3AU/1SpcKC8WlrHGb7qDBHS1HD8wpdcMsL1LTUWlghAptc/CrpRSb vDbiQAK7RHAEVSx6CsW1pVdFGOk5k7QQgeX6ptyK2aliQhuS4UA5b7zMmE+agPY4 Pro2bQLZYPfIW92OB1Zf+h69bUn4aVyp5ov1U1kTJuFHSEH+9+ZVemZg/f2fN8LV bwgErs0YPL/N5099qolj9mmNvn8RcVwub6nIGrVryGbBLprlV3o= =4Mg5 -----END PGP SIGNATURE----- Merge tag 'powerpc-7.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux Pull powerpc updates from Madhavan Srinivasan: - Enable Rust for ppc64le - ppc4xx gpio driver updates - Add power12 base enablement support - Validate arch_compat against host compatibility mode - Simplify bootx_scan_dt_build_struct() in powermac platform - Implement get_direction() in cpm2 - Use cpu_relax() in ps3_create_spu() - Add NULL guard for cause_ipi in smp_muxed_ipi_message_pass - Fixes to handle pseries watchdogs in kdump path - Fix missing r2 clobber in PCREL inline assembly - Set GPIO chip parent on ppc44x - KVM: Introduce KVM_CAP_PPC_COMPAT_CAPS and wire up ioctl - KVM: Use generic xfer to guest work function - Enable to run posix cpu timers in task context - Misc fixes and cleanups Thanks to Aditya Gupta, Alice Ryhl, Amit Machhiwal, Andrew Morton, Anushree Mathur, Athira Rajeev, Bartosz Golaszewski, Cédric Le Goater, Christian König, Christophe Leroy (CS GROUP), Gary Guo, Gaurav Batra, Gautam Menghani, Gou Hao, Hari Bathini, Harsh Prateek Bora, jiazhenyuan, Jinjie Ruan, Link Mauve, Linus Walleij, Mahesh Kumar G Mahesh Salgaonkar, Michael Walle, Michal Suchánek, Mukesh Kumar Chaurasiya (IBM), Nicholas Piggin, Nikhil Kumar Singh, Praveen K Pandey, Ritesh Harjani (IBM), Rosen Penev, Saket Kumar Bhaskar, Shrikanth Hegde, Sourabh Jain, Thorsten Blum, Vaibhav Jain, Venkat Rao Bagalkote, Vishal Chourasia, Wentao Guan, and Yanfei Xu. * tag 'powerpc-7.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: (62 commits) powerpc/pseries/iommu: switch to Default DMA window during kdump powerpc/configs: enable CONFIG_RAS to fix EDAC support KVM: PPC: Document KVM_PPC_GET_COMPAT_CAPS ioctl KVM: PPC: Book3S HV: Add support for compat CPU capabilities for KVM on PowerNV KVM: PPC: Book3S HV: Implement compat CPU capability retrieval for KVM on PowerVM KVM: PPC: Introduce KVM_CAP_PPC_COMPAT_CAPS and wire up ioctl gpio: ppc44x: use dev_name() for chip label gpio: ppc44x: fix undefined behavior in GPIO_MASK2 macro gpio: ppc44x: drop PPC-specific IO helpers gpio: ppc44x: Convert GPIO to generic MMIO gpio: ppc44x: Use platform resource helper for GPIO MMIO gpio: ppc44x: Use module platform driver helper for GPIO gpio: ppc44x: update all 4xx to 44x gpio: move ppc4xx gpio driver from arch/powerpc to drivers/gpio KVM: PPC: Use min() in kvm_vm_ioctl_check_extension() KVM: PPC: booke: Use min() in watchdog_next_timeout() powerpc/perf: Add power12 Base Performance Monitoring support powerpc: Add Power12 architected mode powerpc: Add Power12 raw mode powerpc/pseries: Limit PVR list to 16 entries for CAS negotiation ...
This commit is contained in:
commit
1200d84f4c
|
|
@ -6566,6 +6566,83 @@ KVM_S390_KEYOP_SSKE
|
|||
Sets the storage key for the guest address ``guest_addr`` to the key
|
||||
specified in ``key``, returning the previous value in ``key``.
|
||||
|
||||
4.145 KVM_PPC_GET_COMPAT_CAPS
|
||||
-----------------------------
|
||||
:Capability: KVM_CAP_PPC_COMPAT_CAPS
|
||||
:Architectures: powerpc
|
||||
:Type: vm ioctl
|
||||
:Parameters: struct kvm_ppc_compat_caps (in/out)
|
||||
:Returns: 0 on success, negative value on failure
|
||||
|
||||
Errors include:
|
||||
|
||||
======== ============================================================
|
||||
EFAULT if ``struct kvm_ppc_compat_caps`` cannot be read from or
|
||||
written to userspace
|
||||
EINVAL if the ``size`` field is smaller than
|
||||
``KVM_PPC_COMPAT_CAPS_SIZE_VER0``, if the ``flags`` field
|
||||
is non-zero, or if the backend fails to retrieve or map
|
||||
CPU compatibility capabilities
|
||||
E2BIG if ``size`` exceeds ``PAGE_SIZE`` (pathological input guard),
|
||||
or if ``size`` is larger than the kernel's struct size and
|
||||
the unknown trailing bytes are non-zero (new userspace on
|
||||
old kernel with non-default fields set); in the latter case
|
||||
the kernel writes back its own struct size into the ``size``
|
||||
field so userspace can retry with the correct size
|
||||
ENOTTY if the backend does not implement the ``get_compat_caps``
|
||||
operation (e.g., on non-HV KVM implementations where the
|
||||
required KVM operations are not available)
|
||||
======== ============================================================
|
||||
|
||||
IBM POWER system server-based processors provide a compatibility mode feature
|
||||
where an Nth generation processor can operate in modes consistent with earlier
|
||||
generations such as (N-1) and (N-2).
|
||||
|
||||
This ioctl provides userspace with information about the CPU compatibility modes
|
||||
supported by the current host processor for booting the nested KVM guests on
|
||||
KVM on PowerNV (nested API v1) and KVM on PowerVM (nested API v2) platforms.
|
||||
|
||||
::
|
||||
|
||||
struct kvm_ppc_compat_caps {
|
||||
__u64 size; /* Size of this structure */
|
||||
__u64 flags; /* Reserved for future use, must be 0 */
|
||||
__u64 compat_capabilities; /* Capabilities supported by the host */
|
||||
};
|
||||
|
||||
Before calling this ioctl, userspace must set the ``size`` field to
|
||||
``sizeof(struct kvm_ppc_compat_caps)`` and zero the ``flags`` field.
|
||||
The kernel rejects non-zero ``flags`` with ``-EINVAL`` to prevent
|
||||
uninitialized stack values from being silently accepted, keeping the
|
||||
field available for future use without ABI ambiguity.
|
||||
|
||||
The ioctl uses ``copy_struct_from_user()`` and ``copy_struct_to_user()``
|
||||
to support extensible versioning.
|
||||
|
||||
``KVM_PPC_COMPAT_CAPS_SIZE_VER0`` (24) is a frozen constant marking the
|
||||
size of the initial struct version.
|
||||
|
||||
The ``compat_capabilities`` bit field describes the processor compatibility
|
||||
modes supported by the host. The following bits indicate support for specific
|
||||
processor modes (using IBM's MSB-0 convention where bit 0 is the most
|
||||
significant bit):
|
||||
|
||||
- ``KVM_PPC_COMPAT_CAP_POWER9`` (bit 1) -- KVM guests can run in Power9 processor mode
|
||||
- ``KVM_PPC_COMPAT_CAP_POWER10`` (bit 2) -- KVM guests can run in Power10 processor mode
|
||||
- ``KVM_PPC_COMPAT_CAP_POWER11`` (bit 3) -- KVM guests can run in Power11 processor mode
|
||||
|
||||
.. note::
|
||||
|
||||
The bit numbering above uses IBM's MSB-0 convention (bit 0 is the most
|
||||
significant bit). In the actual implementation, these are defined as:
|
||||
|
||||
- ``KVM_PPC_COMPAT_CAP_POWER9`` = ``(1ULL << 62)``
|
||||
- ``KVM_PPC_COMPAT_CAP_POWER10`` = ``(1ULL << 61)``
|
||||
- ``KVM_PPC_COMPAT_CAP_POWER11`` = ``(1ULL << 60)``
|
||||
|
||||
Userspace should use the defined constants from ``<linux/kvm.h>`` rather
|
||||
than hardcoding bit positions.
|
||||
|
||||
.. _kvm_run:
|
||||
|
||||
5. The kvm_run structure
|
||||
|
|
|
|||
|
|
@ -281,10 +281,13 @@ config PPC
|
|||
select HAVE_PERF_REGS
|
||||
select HAVE_PERF_USER_STACK_DUMP
|
||||
select HAVE_PREEMPT_DYNAMIC_KEY
|
||||
select HAVE_POSIX_CPU_TIMERS_TASK_WORK
|
||||
select HAVE_RETHOOK if KPROBES
|
||||
select HAVE_REGS_AND_STACK_ACCESS_API
|
||||
select HAVE_RELIABLE_STACKTRACE
|
||||
select HAVE_RSEQ
|
||||
select HAVE_RUST if PPC32
|
||||
select HAVE_RUST if PPC64 && CPU_LITTLE_ENDIAN
|
||||
select HAVE_SAMPLE_FTRACE_DIRECT if HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
|
||||
select HAVE_SAMPLE_FTRACE_DIRECT_MULTI if HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
|
||||
select HAVE_SETUP_PER_CPU_AREA if PPC64
|
||||
|
|
|
|||
|
|
@ -61,6 +61,13 @@ else
|
|||
KBUILD_LDFLAGS_MODULE += $(objtree)/arch/powerpc/lib/crtsavres.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_PPC64
|
||||
KBUILD_RUSTFLAGS += --target=powerpc64le-unknown-linux-gnu
|
||||
KBUILD_RUSTFLAGS += -Ctarget-feature=-mma,-vsx,-hard-float,-altivec
|
||||
else
|
||||
KBUILD_RUSTFLAGS += --target=powerpc-unknown-linux-gnu
|
||||
endif
|
||||
|
||||
ifdef CONFIG_CPU_LITTLE_ENDIAN
|
||||
KBUILD_CPPFLAGS += -mlittle-endian
|
||||
KBUILD_LDFLAGS += -EL
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@ static void serial_edit_cmdline(char *buf, int len, unsigned int timeout)
|
|||
char ch, *cp;
|
||||
struct serial_console_data *scdp = console_ops.data;
|
||||
|
||||
cp = buf;
|
||||
count = strlen(buf);
|
||||
cp = &buf[count];
|
||||
count++;
|
||||
|
|
|
|||
|
|
@ -326,17 +326,6 @@ int vsprintf(char *buf, const char *fmt, va_list args)
|
|||
return str-buf;
|
||||
}
|
||||
|
||||
int sprintf(char * buf, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
int i;
|
||||
|
||||
va_start(args, fmt);
|
||||
i=vsprintf(buf,fmt,args);
|
||||
va_end(args);
|
||||
return i;
|
||||
}
|
||||
|
||||
static char sprint_buf[1024];
|
||||
|
||||
int
|
||||
|
|
|
|||
|
|
@ -12,9 +12,6 @@ extern int printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
|
|||
|
||||
#define fprintf(fmt, args...) printf(args)
|
||||
|
||||
extern int sprintf(char *buf, const char *fmt, ...)
|
||||
__attribute__((format(printf, 2, 3)));
|
||||
|
||||
extern int vsprintf(char *buf, const char *fmt, va_list args);
|
||||
|
||||
#endif /* _PPC_BOOT_STDIO_H_ */
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ CONFIG_MODULE_UNLOAD=y
|
|||
# CONFIG_BLK_DEV_BSG is not set
|
||||
# CONFIG_EBONY is not set
|
||||
CONFIG_WARP=y
|
||||
CONFIG_PPC4xx_GPIO=y
|
||||
CONFIG_GPIO_PPC44X=y
|
||||
CONFIG_HZ_1000=y
|
||||
CONFIG_CMDLINE="ip=on"
|
||||
# CONFIG_PCI is not set
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ CONFIG_PPC_EPAPR_HV_BYTECHAN=y
|
|||
CONFIG_QE_GPIO=y
|
||||
CONFIG_QUICC_ENGINE=y
|
||||
CONFIG_RAPIDIO=y
|
||||
CONFIG_RAS=y
|
||||
CONFIG_RTC_CLASS=y
|
||||
CONFIG_RTC_DRV_CMOS=y
|
||||
CONFIG_RTC_DRV_DS1307=y
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ CONFIG_GLACIER=y
|
|||
CONFIG_REDWOOD=y
|
||||
CONFIG_EIGER=y
|
||||
CONFIG_YOSEMITE=y
|
||||
CONFIG_PPC4xx_GPIO=y
|
||||
CONFIG_GPIO_PPC44X=y
|
||||
CONFIG_MATH_EMULATION=y
|
||||
CONFIG_NET=y
|
||||
CONFIG_PACKET=y
|
||||
|
|
|
|||
|
|
@ -9,10 +9,12 @@ void __setup_cpu_power7(unsigned long offset, struct cpu_spec *spec);
|
|||
void __setup_cpu_power8(unsigned long offset, struct cpu_spec *spec);
|
||||
void __setup_cpu_power9(unsigned long offset, struct cpu_spec *spec);
|
||||
void __setup_cpu_power10(unsigned long offset, struct cpu_spec *spec);
|
||||
void __setup_cpu_power12(unsigned long offset, struct cpu_spec *spec);
|
||||
void __restore_cpu_power7(void);
|
||||
void __restore_cpu_power8(void);
|
||||
void __restore_cpu_power9(void);
|
||||
void __restore_cpu_power10(void);
|
||||
void __restore_cpu_power12(void);
|
||||
|
||||
void __setup_cpu_e500v1(unsigned long offset, struct cpu_spec *spec);
|
||||
void __setup_cpu_e500v2(unsigned long offset, struct cpu_spec *spec);
|
||||
|
|
|
|||
|
|
@ -194,6 +194,7 @@ static inline void cpu_feature_keys_init(void) { }
|
|||
#define CPU_FTR_DAWR1 LONG_ASM_CONST(0x0008000000000000)
|
||||
#define CPU_FTR_DEXCR_NPHIE LONG_ASM_CONST(0x0010000000000000)
|
||||
#define CPU_FTR_P11_PVR LONG_ASM_CONST(0x0020000000000000)
|
||||
#define CPU_FTR_ARCH_32 LONG_ASM_CONST(0x0040000000000000)
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
|
|
@ -457,6 +458,18 @@ static inline void cpu_feature_keys_init(void) { }
|
|||
|
||||
#define CPU_FTRS_POWER11 (CPU_FTRS_POWER10 | CPU_FTR_P11_PVR)
|
||||
|
||||
#define CPU_FTRS_POWER12 (CPU_FTR_LWSYNC | \
|
||||
CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | CPU_FTR_ARCH_206 |\
|
||||
CPU_FTR_MMCRA | CPU_FTR_SMT | \
|
||||
CPU_FTR_COHERENT_ICACHE | \
|
||||
CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \
|
||||
CPU_FTR_DSCR | \
|
||||
CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \
|
||||
CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \
|
||||
CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_ARCH_207S | \
|
||||
CPU_FTR_ARCH_300 | CPU_FTR_ARCH_31 | CPU_FTR_ARCH_32 | \
|
||||
CPU_FTR_DAWR | CPU_FTR_DAWR1)
|
||||
|
||||
#define CPU_FTRS_CELL (CPU_FTR_LWSYNC | \
|
||||
CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
|
||||
CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
|
||||
|
|
@ -476,7 +489,7 @@ static inline void cpu_feature_keys_init(void) { }
|
|||
(CPU_FTRS_POWER7 | CPU_FTRS_POWER8E | CPU_FTRS_POWER8 | \
|
||||
CPU_FTR_ALTIVEC_COMP | CPU_FTR_VSX_COMP | CPU_FTRS_POWER9 | \
|
||||
CPU_FTRS_POWER9_DD2_1 | CPU_FTRS_POWER9_DD2_2 | \
|
||||
CPU_FTRS_POWER9_DD2_3 | CPU_FTRS_POWER10 | CPU_FTRS_POWER11)
|
||||
CPU_FTRS_POWER9_DD2_3 | CPU_FTRS_POWER10 | CPU_FTRS_POWER11 | CPU_FTRS_POWER12)
|
||||
#else
|
||||
#define CPU_FTRS_POSSIBLE \
|
||||
(CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | \
|
||||
|
|
@ -484,7 +497,7 @@ static inline void cpu_feature_keys_init(void) { }
|
|||
CPU_FTRS_POWER8 | CPU_FTRS_CELL | CPU_FTRS_PA6T | \
|
||||
CPU_FTR_VSX_COMP | CPU_FTR_ALTIVEC_COMP | CPU_FTRS_POWER9 | \
|
||||
CPU_FTRS_POWER9_DD2_1 | CPU_FTRS_POWER9_DD2_2 | \
|
||||
CPU_FTRS_POWER9_DD2_3 | CPU_FTRS_POWER10 | CPU_FTRS_POWER11)
|
||||
CPU_FTRS_POWER9_DD2_3 | CPU_FTRS_POWER10 | CPU_FTRS_POWER11 | CPU_FTRS_POWER12)
|
||||
#endif /* CONFIG_CPU_LITTLE_ENDIAN */
|
||||
#endif
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -15,14 +15,20 @@
|
|||
#define JUMP_ENTRY_TYPE stringify_in_c(FTR_ENTRY_LONG)
|
||||
#define JUMP_LABEL_NOP_SIZE 4
|
||||
|
||||
#define JUMP_TABLE_ENTRY(key, label) \
|
||||
".pushsection __jump_table, \"aw\" \n\t" \
|
||||
".long 1b - ., " label " - . \n\t" \
|
||||
JUMP_ENTRY_TYPE key " - . \n\t" \
|
||||
".popsection \n\t"
|
||||
|
||||
#define ARCH_STATIC_BRANCH_ASM(key, label) \
|
||||
"1: nop \n\t" \
|
||||
JUMP_TABLE_ENTRY(key, label)
|
||||
|
||||
static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
|
||||
{
|
||||
asm goto("1:\n\t"
|
||||
"nop # arch_static_branch\n\t"
|
||||
".pushsection __jump_table, \"aw\"\n\t"
|
||||
".long 1b - ., %l[l_yes] - .\n\t"
|
||||
JUMP_ENTRY_TYPE "%c0 - .\n\t"
|
||||
".popsection \n\t"
|
||||
asm goto(
|
||||
ARCH_STATIC_BRANCH_ASM("%c0", "%l[l_yes]")
|
||||
: : "i" (&((char *)key)[branch]) : : l_yes);
|
||||
|
||||
return false;
|
||||
|
|
@ -34,10 +40,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
|
|||
{
|
||||
asm goto("1:\n\t"
|
||||
"b %l[l_yes] # arch_static_branch_jump\n\t"
|
||||
".pushsection __jump_table, \"aw\"\n\t"
|
||||
".long 1b - ., %l[l_yes] - .\n\t"
|
||||
JUMP_ENTRY_TYPE "%c0 - .\n\t"
|
||||
".popsection \n\t"
|
||||
JUMP_TABLE_ENTRY("%c0", "%l[l_yes]")
|
||||
: : "i" (&((char *)key)[branch]) : : l_yes);
|
||||
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -319,6 +319,7 @@ struct kvmppc_ops {
|
|||
bool (*hash_v3_possible)(void);
|
||||
int (*create_vm_debugfs)(struct kvm *kvm);
|
||||
int (*create_vcpu_debugfs)(struct kvm_vcpu *vcpu, struct dentry *debugfs_dentry);
|
||||
int (*get_compat_caps)(struct kvm_ppc_compat_caps *host_caps);
|
||||
};
|
||||
|
||||
extern struct kvmppc_ops *kvmppc_hv_ops;
|
||||
|
|
|
|||
|
|
@ -133,6 +133,7 @@
|
|||
#define MMU_FTRS_POWER9 MMU_FTRS_POWER6
|
||||
#define MMU_FTRS_POWER10 MMU_FTRS_POWER6
|
||||
#define MMU_FTRS_POWER11 MMU_FTRS_POWER6
|
||||
#define MMU_FTRS_POWER12 MMU_FTRS_POWER6
|
||||
#define MMU_FTRS_CELL MMU_FTRS_DEFAULT_HPTE_ARCH_V2 | \
|
||||
MMU_FTR_CI_LARGE_PAGE
|
||||
#define MMU_FTRS_PA6T MMU_FTRS_DEFAULT_HPTE_ARCH_V2 | \
|
||||
|
|
|
|||
64
arch/powerpc/include/asm/papr-watchdog.h
Normal file
64
arch/powerpc/include/asm/papr-watchdog.h
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#ifndef _ASM_POWERPC_PAPR_WATCHDOG_H
|
||||
#define _ASM_POWERPC_PAPR_WATCHDOG_H
|
||||
|
||||
/*
|
||||
* H_WATCHDOG Input
|
||||
*
|
||||
* R4: "flags":
|
||||
*
|
||||
* Bits 48-55: "operation"
|
||||
*/
|
||||
#define PSERIES_WDTF_OP_START 0x100UL /* start timer */
|
||||
#define PSERIES_WDTF_OP_STOP 0x200UL /* stop timer */
|
||||
#define PSERIES_WDTF_OP_QUERY 0x300UL /* query timer capabilities */
|
||||
|
||||
/*
|
||||
* Bits 56-63: "timeoutAction" (for "Start Watchdog" only)
|
||||
*/
|
||||
#define PSERIES_WDTF_ACTION_HARD_POWEROFF 0x1UL /* poweroff */
|
||||
#define PSERIES_WDTF_ACTION_HARD_RESTART 0x2UL /* restart */
|
||||
#define PSERIES_WDTF_ACTION_DUMP_RESTART 0x3UL /* dump + restart */
|
||||
|
||||
/*
|
||||
* R5: "watchdogNumber":
|
||||
* PAPR says use -1 (all ones) to stop all watchdogs.
|
||||
*/
|
||||
#define PSERIES_WDT_NUM_ALL ((unsigned long)-1)
|
||||
|
||||
/*
|
||||
* H_WATCHDOG Output
|
||||
*
|
||||
* R3: Return code
|
||||
*
|
||||
* H_SUCCESS The operation completed.
|
||||
*
|
||||
* H_BUSY The hypervisor is too busy; retry the operation.
|
||||
*
|
||||
* H_PARAMETER The given "flags" are somehow invalid. Either the
|
||||
* "operation" or "timeoutAction" is invalid, or a
|
||||
* reserved bit is set.
|
||||
*
|
||||
* H_P2 The given "watchdogNumber" is zero or exceeds the
|
||||
* supported maximum value.
|
||||
*
|
||||
* H_P3 The given "timeoutInMs" is below the supported
|
||||
* minimum value.
|
||||
*
|
||||
* H_NOOP The given "watchdogNumber" is already stopped.
|
||||
*
|
||||
* H_HARDWARE The operation failed for ineffable reasons.
|
||||
*
|
||||
* H_FUNCTION The H_WATCHDOG hypercall is not supported by this
|
||||
* hypervisor.
|
||||
*
|
||||
* R4:
|
||||
*
|
||||
* - For the "Query Watchdog Capabilities" operation, a 64-bit
|
||||
* structure:
|
||||
*/
|
||||
#define PSERIES_WDTQ_MIN_TIMEOUT(cap) (((cap) >> 48) & 0xffff)
|
||||
#define PSERIES_WDTQ_MAX_NUMBER(cap) (((cap) >> 32) & 0xffff)
|
||||
|
||||
#endif /* _ASM_POWERPC_PAPR_WATCHDOG_H */
|
||||
|
|
@ -117,7 +117,8 @@ extern unsigned int boot_cpu_node_count;
|
|||
#define OV1_PPC_2_07 0x01 /* set if we support PowerPC 2.07 */
|
||||
|
||||
#define OV1_PPC_3_00 0x80 /* set if we support PowerPC 3.00 */
|
||||
#define OV1_PPC_3_1 0x40 /* set if we support PowerPC 3.1 */
|
||||
#define OV1_PPC_3_1 0x40 /* set if we support PowerPC 3.1 */
|
||||
#define OV1_PPC_3_2 0x20 /* set if we support PowerPC 3.2 */
|
||||
|
||||
/* Option vector 2: Open Firmware options supported */
|
||||
#define OV2_REAL_MODE 0x20 /* set if we want OF in real mode */
|
||||
|
|
|
|||
|
|
@ -492,11 +492,12 @@
|
|||
* determine both the compatibility level which we want to emulate and the
|
||||
* compatibility level which the host is capable of emulating.
|
||||
*/
|
||||
#define PCR_ARCH_31 0x20 /* Architecture 3.1 */
|
||||
#define PCR_ARCH_300 0x10 /* Architecture 3.00 */
|
||||
#define PCR_ARCH_207 0x8 /* Architecture 2.07 */
|
||||
#define PCR_ARCH_206 0x4 /* Architecture 2.06 */
|
||||
#define PCR_ARCH_205 0x2 /* Architecture 2.05 */
|
||||
#define PCR_LOW_BITS (PCR_ARCH_207 | PCR_ARCH_206 | PCR_ARCH_205 | PCR_ARCH_300)
|
||||
#define PCR_LOW_BITS (PCR_ARCH_207 | PCR_ARCH_206 | PCR_ARCH_205 | PCR_ARCH_300 | PCR_ARCH_31)
|
||||
#define PCR_MASK ~(PCR_HIGH_BITS | PCR_LOW_BITS) /* PCR Reserved Bits */
|
||||
#define SPRN_HEIR 0x153 /* Hypervisor Emulated Instruction Register */
|
||||
#define SPRN_TLBINDEXR 0x154 /* P7 TLB control register */
|
||||
|
|
@ -1344,6 +1345,7 @@
|
|||
#define PVR_POWER9 0x004E
|
||||
#define PVR_POWER10 0x0080
|
||||
#define PVR_POWER11 0x0082
|
||||
#define PVR_POWER12 0x0083
|
||||
#define PVR_BE 0x0070
|
||||
#define PVR_PA6T 0x0090
|
||||
|
||||
|
|
@ -1356,6 +1358,19 @@
|
|||
#define PVR_ARCH_300 0x0f000005
|
||||
#define PVR_ARCH_31 0x0f000006
|
||||
#define PVR_ARCH_31_P11 0x0f000007
|
||||
#define PVR_ARCH_32 0x0f000008
|
||||
|
||||
/*
|
||||
* Kernel-internal sentinel for invalid processor compatibility modes.
|
||||
* PAPR specifies that the first byte of a valid logical PVR value is
|
||||
* 0x0f. So 0xffffffff lies permanently outside the PAPR-defined range
|
||||
* and is safe to repurpose. KVM stores it in vcpu->arch.arch_compat
|
||||
* when userspace requests an unsupported compatibility mode (e.g.,
|
||||
* Power11 PVR on a Power11 host booted in Power10 compat).
|
||||
* kvmppc_sanity_check() detects this and prevents the vCPU from
|
||||
* running with an unsupported arch_compat.
|
||||
*/
|
||||
#define PVR_ARCH_INVALID 0xffffffff
|
||||
|
||||
/* Macros for setting and retrieving special purpose registers */
|
||||
#ifndef __ASSEMBLER__
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@
|
|||
* through the device tree.
|
||||
*/
|
||||
|
||||
/* Default baud base if not found in device-tree */
|
||||
#define BASE_BAUD ( 1843200 / 16 )
|
||||
/* Provides BASE_BAUD, used as fallback if not found in device tree. */
|
||||
#include <asm-generic/serial.h>
|
||||
|
||||
#ifdef CONFIG_PPC_UDBG_16550
|
||||
extern void find_legacy_serial_ports(void);
|
||||
|
|
|
|||
|
|
@ -37,8 +37,12 @@ static inline void ppc_after_tlbiel_barrier(void)
|
|||
* accelerators mapped will use tlbie (which does invalidate the copy)
|
||||
* to invalidate translations. It's not possible to limit POWER10 this
|
||||
* way due to local copy-paste.
|
||||
*
|
||||
* POWER12 does not need it.
|
||||
*/
|
||||
asm volatile(ASM_FTR_IFSET(PPC_CP_ABORT, "", %0) : : "i" (CPU_FTR_ARCH_31) : "memory");
|
||||
asm volatile(ASM_FTR_IF(PPC_CP_ABORT, "", %0, %1) :
|
||||
: "i" (CPU_FTR_ARCH_31|CPU_FTR_ARCH_32), "i" (CPU_FTR_ARCH_31)
|
||||
: "memory");
|
||||
}
|
||||
#endif /* __ASSEMBLER__ */
|
||||
|
||||
|
|
|
|||
|
|
@ -98,6 +98,12 @@ static inline void syscall_set_return_value(struct task_struct *task,
|
|||
regs->gpr[3] = val;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Mark that a return value has been explicitly set by seccomp or
|
||||
* ptrace so that system_call_exception() can skip the syscall
|
||||
* unconditionally, even when the user requested syscall(-1).
|
||||
*/
|
||||
set_thread_flag(TIF_SYSCALL_RET);
|
||||
}
|
||||
|
||||
static inline void syscall_get_arguments(struct task_struct *task,
|
||||
|
|
|
|||
|
|
@ -120,6 +120,7 @@ void arch_setup_new_exec(void);
|
|||
#endif
|
||||
#define TIF_POLLING_NRFLAG 19 /* true if poll_idle() is polling TIF_NEED_RESCHED */
|
||||
#define TIF_32BIT 20 /* 32 bit binary */
|
||||
#define TIF_SYSCALL_RET 21 /* syscall error value set */
|
||||
|
||||
/* as above, but as bit values */
|
||||
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ static inline bool xive_enabled(void) { return __xive_enabled; }
|
|||
|
||||
bool xive_spapr_init(void);
|
||||
bool xive_native_init(void);
|
||||
void xive_smp_probe(void);
|
||||
int xive_smp_probe(void);
|
||||
int xive_smp_prepare_cpu(unsigned int cpu);
|
||||
void xive_smp_setup_cpu(void);
|
||||
void xive_smp_disable_cpu(void);
|
||||
|
|
@ -153,7 +153,7 @@ static inline bool xive_enabled(void) { return false; }
|
|||
|
||||
static inline bool xive_spapr_init(void) { return false; }
|
||||
static inline bool xive_native_init(void) { return false; }
|
||||
static inline void xive_smp_probe(void) { }
|
||||
static inline int xive_smp_probe(void) { return -EINVAL; }
|
||||
static inline int xive_smp_prepare_cpu(unsigned int cpu) { return -EINVAL; }
|
||||
static inline void xive_smp_setup_cpu(void) { }
|
||||
static inline void xive_smp_disable_cpu(void) { }
|
||||
|
|
|
|||
|
|
@ -52,6 +52,8 @@
|
|||
#define PPC_FEATURE2_HTM_NO_SUSPEND 0x00080000 /* TM w/out suspended state */
|
||||
#define PPC_FEATURE2_ARCH_3_1 0x00040000 /* ISA 3.1 */
|
||||
#define PPC_FEATURE2_MMA 0x00020000 /* Matrix Multiply Assist */
|
||||
#define PPC_FEATURE2_ARCH_3_2 0x00010000 /* ISA 3.2 */
|
||||
#define PPC_FEATURE2_DMF 0x00008000 /* Dense Math Facility */
|
||||
|
||||
/*
|
||||
* IMPORTANT!
|
||||
|
|
|
|||
|
|
@ -437,6 +437,24 @@ struct kvm_ppc_cpu_char {
|
|||
__u64 behaviour_mask; /* valid bits in behaviour */
|
||||
};
|
||||
|
||||
/* For KVM_PPC_GET_COMPAT_CAPS */
|
||||
struct kvm_ppc_compat_caps {
|
||||
__u64 size; /* Size of this structure */
|
||||
__u64 flags; /* Reserved for future use */
|
||||
__u64 compat_capabilities; /* Capabilities supported by the host */
|
||||
};
|
||||
#define KVM_PPC_COMPAT_CAPS_SIZE_VER0 24 /* sizeof first published struct */
|
||||
|
||||
/*
|
||||
* Capability bits for compat_capabilities field in kvm_ppc_compat_caps.
|
||||
* These bits indicate which processor compatibility modes are supported.
|
||||
*/
|
||||
#define KVM_PPC_COMPAT_CAP_POWER9 (1ULL << 62)
|
||||
#define KVM_PPC_COMPAT_CAP_POWER10 (1ULL << 61)
|
||||
#define KVM_PPC_COMPAT_CAP_POWER11 (1ULL << 60)
|
||||
#define KVM_PPC_COMPAT_BITMASK (KVM_PPC_COMPAT_CAP_POWER9 | \
|
||||
KVM_PPC_COMPAT_CAP_POWER10 | \
|
||||
KVM_PPC_COMPAT_CAP_POWER11)
|
||||
/*
|
||||
* Values for character and character_mask.
|
||||
* These are identical to the values used by H_GET_CPU_CHARACTERISTICS.
|
||||
|
|
|
|||
|
|
@ -286,3 +286,46 @@ void __restore_cpu_power10(void)
|
|||
init_HFSCR();
|
||||
init_PMU_HV();
|
||||
}
|
||||
|
||||
void __setup_cpu_power12(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_AMOR, ~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_power12(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_AMOR, ~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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,6 +63,11 @@
|
|||
#define COMMON_USER_POWER11 COMMON_USER_POWER10
|
||||
#define COMMON_USER2_POWER11 COMMON_USER2_POWER10
|
||||
|
||||
#define COMMON_USER_POWER12 COMMON_USER_POWER10
|
||||
#define COMMON_USER2_POWER12 (COMMON_USER2_POWER10 | \
|
||||
PPC_FEATURE2_ARCH_3_2)
|
||||
|
||||
|
||||
static struct cpu_spec cpu_specs[] __initdata = {
|
||||
{ /* PPC970 */
|
||||
.pvr_mask = 0xffff0000,
|
||||
|
|
@ -298,6 +303,20 @@ static struct cpu_spec cpu_specs[] __initdata = {
|
|||
.cpu_restore = __restore_cpu_power10,
|
||||
.platform = "power11",
|
||||
},
|
||||
{ /* 3.2-compliant processor, i.e. Power12 "architected" mode */
|
||||
.pvr_mask = 0xffffffff,
|
||||
.pvr_value = 0x0f000008,
|
||||
.cpu_name = "Power12 (architected)",
|
||||
.cpu_features = CPU_FTRS_POWER12,
|
||||
.cpu_user_features = COMMON_USER_POWER12,
|
||||
.cpu_user_features2 = COMMON_USER2_POWER12,
|
||||
.mmu_features = MMU_FTRS_POWER12,
|
||||
.icache_bsize = 128,
|
||||
.dcache_bsize = 128,
|
||||
.cpu_setup = __setup_cpu_power12,
|
||||
.cpu_restore = __restore_cpu_power12,
|
||||
.platform = "power12",
|
||||
},
|
||||
{ /* Power7 */
|
||||
.pvr_mask = 0xffff0000,
|
||||
.pvr_value = 0x003f0000,
|
||||
|
|
@ -485,6 +504,23 @@ static struct cpu_spec cpu_specs[] __initdata = {
|
|||
.machine_check_early = __machine_check_early_realmode_p10,
|
||||
.platform = "power11",
|
||||
},
|
||||
{ /* Power12 */
|
||||
.pvr_mask = 0xffff0000,
|
||||
.pvr_value = 0x00830000,
|
||||
.cpu_name = "Power12 (raw)",
|
||||
.cpu_features = CPU_FTRS_POWER12,
|
||||
.cpu_user_features = COMMON_USER_POWER12,
|
||||
.cpu_user_features2 = COMMON_USER2_POWER12,
|
||||
.mmu_features = MMU_FTRS_POWER12,
|
||||
.icache_bsize = 128,
|
||||
.dcache_bsize = 128,
|
||||
.num_pmcs = 6,
|
||||
.pmc_type = PPC_PMC_IBM,
|
||||
.cpu_setup = __setup_cpu_power12,
|
||||
.cpu_restore = __restore_cpu_power12,
|
||||
.machine_check_early = __machine_check_early_realmode_p10,
|
||||
.platform = "power12",
|
||||
},
|
||||
{ /* Cell Broadband Engine */
|
||||
.pvr_mask = 0xffff0000,
|
||||
.pvr_value = 0x00700000,
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
/* Device-tree visible constants follow */
|
||||
#define ISA_V3_0B 3000
|
||||
#define ISA_V3_1 3100
|
||||
#define ISA_V3_2 3200
|
||||
|
||||
#define USABLE_PR (1U << 0)
|
||||
#define USABLE_OS (1U << 1)
|
||||
|
|
@ -90,8 +91,6 @@ static void __restore_cpu_cpufeatures(void)
|
|||
init_pmu_registers();
|
||||
}
|
||||
|
||||
static char dt_cpu_name[64];
|
||||
|
||||
static struct cpu_spec __initdata base_cpu_spec = {
|
||||
.cpu_name = NULL,
|
||||
.cpu_features = CPU_FTRS_DT_CPU_BASE,
|
||||
|
|
@ -466,6 +465,35 @@ static int __init feat_enable_mce_power11(struct dt_cpu_feature *f)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static void init_pmu_power12(void)
|
||||
{
|
||||
init_pmu_power10();
|
||||
}
|
||||
|
||||
static int __init feat_enable_pmu_power12(struct dt_cpu_feature *f)
|
||||
{
|
||||
hfscr_pmu_enable();
|
||||
|
||||
init_pmu_power12();
|
||||
init_pmu_registers = init_pmu_power12;
|
||||
|
||||
cur_cpu_spec->cpu_features |= CPU_FTR_MMCRA;
|
||||
cur_cpu_spec->cpu_user_features |= PPC_FEATURE_PSERIES_PERFMON_COMPAT;
|
||||
|
||||
cur_cpu_spec->num_pmcs = 6;
|
||||
cur_cpu_spec->pmc_type = PPC_PMC_IBM;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __init feat_enable_mce_power12(struct dt_cpu_feature *f)
|
||||
{
|
||||
cur_cpu_spec->platform = "power12";
|
||||
cur_cpu_spec->machine_check_early = __machine_check_early_realmode_p10;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __init feat_enable_tm(struct dt_cpu_feature *f)
|
||||
{
|
||||
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
||||
|
|
@ -657,9 +685,11 @@ static struct dt_cpu_feature_match __initdata
|
|||
{"machine-check-power9", feat_enable_mce_power9, 0},
|
||||
{"machine-check-power10", feat_enable_mce_power10, 0},
|
||||
{"machine-check-power11", feat_enable_mce_power11, 0},
|
||||
{"machine-check-power12", feat_enable_mce_power12, 0},
|
||||
{"performance-monitor-power9", feat_enable_pmu_power9, 0},
|
||||
{"performance-monitor-power10", feat_enable_pmu_power10, 0},
|
||||
{"performance-monitor-power11", feat_enable_pmu_power10, 0},
|
||||
{"performance-monitor-power12", feat_enable_pmu_power12, 0},
|
||||
{"event-based-branch-v3", feat_enable, 0},
|
||||
{"random-number-generator", feat_enable, 0},
|
||||
{"system-call-vectored", feat_disable, 0},
|
||||
|
|
@ -714,6 +744,11 @@ static void __init cpufeatures_setup_start(u32 isa)
|
|||
if (PVR_VER(mfspr(SPRN_PVR)) >= PVR_POWER11)
|
||||
cur_cpu_spec->cpu_features |= CPU_FTR_P11_PVR;
|
||||
}
|
||||
|
||||
if (isa >= ISA_V3_2) {
|
||||
cur_cpu_spec->cpu_features |= CPU_FTR_ARCH_32;
|
||||
cur_cpu_spec->cpu_user_features2 |= PPC_FEATURE2_ARCH_3_2;
|
||||
}
|
||||
}
|
||||
|
||||
static bool __init cpufeatures_process_feature(struct dt_cpu_feature *f)
|
||||
|
|
@ -1078,6 +1113,7 @@ static int __init count_cpufeatures_subnodes(unsigned long node,
|
|||
static int __init dt_cpu_ftrs_scan_callback(unsigned long node, const char
|
||||
*uname, int depth, void *data)
|
||||
{
|
||||
static char dt_cpu_name[64];
|
||||
const __be32 *prop;
|
||||
int count, i;
|
||||
u32 isa;
|
||||
|
|
@ -1115,8 +1151,8 @@ static int __init dt_cpu_ftrs_scan_callback(unsigned long node, const char
|
|||
}
|
||||
|
||||
prop = of_get_flat_dt_prop(node, "display-name", NULL);
|
||||
if (prop && strlen((char *)prop) != 0) {
|
||||
strscpy(dt_cpu_name, (char *)prop, sizeof(dt_cpu_name));
|
||||
if (prop && *(char *)prop != 0) {
|
||||
strscpy(dt_cpu_name, (char *)prop);
|
||||
cur_cpu_spec->cpu_name = dt_cpu_name;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -713,14 +713,18 @@ p_end: .8byte _end - copy_to_here
|
|||
_GLOBAL(copy_and_flush)
|
||||
addi r5,r5,-8
|
||||
addi r6,r6,-8
|
||||
4: li r0,8 /* Use the smallest common */
|
||||
/* denominator cache line */
|
||||
/* size. This results in */
|
||||
/* extra cache line flushes */
|
||||
/* but operation is correct. */
|
||||
/* Can't get cache line size */
|
||||
/* from NACA as it is being */
|
||||
/* moved too. */
|
||||
4: li r0,8 /* r0 is the number of 8-byte words */
|
||||
/* to copy per cache sync iteration. */
|
||||
/* 8 words * 8 bytes = 64 bytes. 64B is */
|
||||
/* the current default cache line size. */
|
||||
/* This is a loop count, not a byte */
|
||||
/* count. Increasing it may skip */
|
||||
/* dcbst/icbi for lines in between and */
|
||||
/* leave stale instructions in icache. */
|
||||
/* This results in extra cache line */
|
||||
/* flushes but operation is correct. */
|
||||
/* Can't get cache line size from NACA */
|
||||
/* as it is being moved too. */
|
||||
|
||||
mtctr r0 /* put # words/line in ctr */
|
||||
3: addi r6,r6,8 /* copy a cache line */
|
||||
|
|
|
|||
|
|
@ -217,8 +217,12 @@ static __always_inline void call_do_softirq(const void *sp)
|
|||
[sp] "b" (sp), [offset] "i" (THREAD_SIZE - STACK_FRAME_MIN_SIZE),
|
||||
[callee] "i" (__do_softirq)
|
||||
: // Clobbers
|
||||
"lr", "xer", "ctr", "memory", "cr0", "cr1", "cr5", "cr6",
|
||||
"cr7", "r0", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
|
||||
"lr", "xer", "ctr", "memory", "cr0", "cr1", "cr5", "cr6", "cr7", "r0",
|
||||
/* r2 may be clobbered by the callee when using PCREL mode in the ELFv2 ABI. */
|
||||
#ifdef CONFIG_PPC_KERNEL_PCREL
|
||||
"r2",
|
||||
#endif
|
||||
"r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
|
||||
"r11", "r12"
|
||||
);
|
||||
}
|
||||
|
|
@ -275,8 +279,12 @@ static __always_inline void call_do_irq(struct pt_regs *regs, void *sp)
|
|||
[sp] "b" (sp), [offset] "i" (THREAD_SIZE - STACK_FRAME_MIN_SIZE),
|
||||
[callee] "i" (__do_irq)
|
||||
: // Clobbers
|
||||
"lr", "xer", "ctr", "memory", "cr0", "cr1", "cr5", "cr6",
|
||||
"cr7", "r0", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
|
||||
"lr", "xer", "ctr", "memory", "cr0", "cr1", "cr5", "cr6", "cr7", "r0",
|
||||
/* r2 may be clobbered by the callee when using PCREL mode in the ELFv2 ABI. */
|
||||
#ifdef CONFIG_PPC_KERNEL_PCREL
|
||||
"r2",
|
||||
#endif
|
||||
"r4", "r5", "r6", "r7", "r8", "r9", "r10",
|
||||
"r11", "r12"
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -86,6 +86,12 @@
|
|||
*/
|
||||
#define ADDR(x) (u32)(unsigned long)(x)
|
||||
|
||||
/*
|
||||
* Current Power system firmware caps the PVR list array size at 16 entries
|
||||
* during CAS (Client Architecture Support) negotiation.
|
||||
*/
|
||||
#define CAS_MAX_PVR_ENTRIES 16
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
#define OF_WORKAROUNDS 0
|
||||
#else
|
||||
|
|
@ -947,7 +953,7 @@ struct option_vector7 {
|
|||
} __packed;
|
||||
|
||||
struct ibm_arch_vec {
|
||||
struct { __be32 mask, val; } pvrs[16];
|
||||
struct { __be32 mask, val; } pvrs[18];
|
||||
|
||||
u8 num_vectors;
|
||||
|
||||
|
|
@ -979,6 +985,10 @@ static const struct ibm_arch_vec ibm_architecture_vec_template __initconst = {
|
|||
.mask = cpu_to_be32(0xfffe0000), /* POWER5/POWER5+ */
|
||||
.val = cpu_to_be32(0x003a0000),
|
||||
},
|
||||
{
|
||||
.mask = cpu_to_be32(0xffffffff), /* all 2.04-compliant and earlier */
|
||||
.val = cpu_to_be32(0x0f000001),
|
||||
},
|
||||
{
|
||||
.mask = cpu_to_be32(0xffff0000), /* POWER6 */
|
||||
.val = cpu_to_be32(0x003e0000),
|
||||
|
|
@ -1011,6 +1021,14 @@ static const struct ibm_arch_vec ibm_architecture_vec_template __initconst = {
|
|||
.mask = cpu_to_be32(0xffff0000), /* POWER11 */
|
||||
.val = cpu_to_be32(0x00820000),
|
||||
},
|
||||
{
|
||||
.mask = cpu_to_be32(0xffff0000), /* POWER12 */
|
||||
.val = cpu_to_be32(0x00830000),
|
||||
},
|
||||
{
|
||||
.mask = cpu_to_be32(0xffffffff), /* all 3.2-compliant */
|
||||
.val = cpu_to_be32(0x0f000008),
|
||||
},
|
||||
{
|
||||
.mask = cpu_to_be32(0xffffffff), /* P11 compliant */
|
||||
.val = cpu_to_be32(0x0f000007),
|
||||
|
|
@ -1032,13 +1050,9 @@ static const struct ibm_arch_vec ibm_architecture_vec_template __initconst = {
|
|||
.val = cpu_to_be32(0x0f000003),
|
||||
},
|
||||
{
|
||||
.mask = cpu_to_be32(0xffffffff), /* all 2.05-compliant */
|
||||
.mask = cpu_to_be32(0xfffffffd), /* all 2.05-compliant */
|
||||
.val = cpu_to_be32(0x0f000002),
|
||||
},
|
||||
{
|
||||
.mask = cpu_to_be32(0xfffffffe), /* all 2.04-compliant and earlier */
|
||||
.val = cpu_to_be32(0x0f000001),
|
||||
},
|
||||
},
|
||||
|
||||
.num_vectors = NUM_VECTORS(6),
|
||||
|
|
@ -1048,7 +1062,7 @@ static const struct ibm_arch_vec ibm_architecture_vec_template __initconst = {
|
|||
.byte1 = 0,
|
||||
.arch_versions = OV1_PPC_2_00 | OV1_PPC_2_01 | OV1_PPC_2_02 | OV1_PPC_2_03 |
|
||||
OV1_PPC_2_04 | OV1_PPC_2_05 | OV1_PPC_2_06 | OV1_PPC_2_07,
|
||||
.arch_versions3 = OV1_PPC_3_00 | OV1_PPC_3_1,
|
||||
.arch_versions3 = OV1_PPC_3_00 | OV1_PPC_3_1 | OV1_PPC_3_2,
|
||||
},
|
||||
|
||||
.vec2_len = VECTOR_LENGTH(sizeof(struct option_vector2)),
|
||||
|
|
@ -1403,6 +1417,22 @@ static void __init prom_send_capabilities(void)
|
|||
ihandle root;
|
||||
prom_arg_t ret;
|
||||
u32 cores;
|
||||
int start_index = 0;
|
||||
|
||||
/*
|
||||
* Ensure that when running on Power11 or below hardware, the number
|
||||
* of PVR entries passed during CAS negotiation does not exceed the
|
||||
* firmware-imposed limit of 16.
|
||||
*
|
||||
* Compute the start_index to skip the oldest leading pvrs[] entries
|
||||
* when running on Power11 or below hardware, so that the pointer
|
||||
* passed to ibm,client-architecture-support points to
|
||||
* ibm_architecture_vec.pvrs[start_index], presenting exactly 16
|
||||
* entries to firmware.
|
||||
*/
|
||||
if ((ARRAY_SIZE(ibm_architecture_vec_template.pvrs) > CAS_MAX_PVR_ENTRIES) &&
|
||||
(PVR_VER(mfspr(SPRN_PVR)) <= PVR_POWER11))
|
||||
start_index = ARRAY_SIZE(ibm_architecture_vec_template.pvrs) - CAS_MAX_PVR_ENTRIES;
|
||||
|
||||
/* Check ibm,arch-vec-5-platform-support and fixup vec5 if required */
|
||||
prom_check_platform_support();
|
||||
|
|
@ -1427,7 +1457,7 @@ static void __init prom_send_capabilities(void)
|
|||
if (call_prom_ret("call-method", 3, 2, &ret,
|
||||
ADDR("ibm,client-architecture-support"),
|
||||
root,
|
||||
ADDR(&ibm_architecture_vec)) == 0) {
|
||||
ADDR(&ibm_architecture_vec.pvrs[start_index])) == 0) {
|
||||
/* the call exists... */
|
||||
if (ret)
|
||||
prom_printf("\nWARNING: ibm,client-architecture"
|
||||
|
|
|
|||
|
|
@ -394,30 +394,23 @@ static ssize_t manage_flash_write(struct file *file, const char __user *buf,
|
|||
size_t count, loff_t *off)
|
||||
{
|
||||
struct rtas_manage_flash_t *const args_buf = &rtas_manage_flash_data;
|
||||
static const char reject_str[] = "0";
|
||||
static const char commit_str[] = "1";
|
||||
char stkbuf[10];
|
||||
int op;
|
||||
unsigned int op;
|
||||
char cmd;
|
||||
|
||||
guard(mutex)(&rtas_manage_flash_mutex);
|
||||
|
||||
if ((args_buf->status == MANAGE_AUTH) || (count == 0))
|
||||
return count;
|
||||
|
||||
op = -1;
|
||||
if (buf) {
|
||||
if (count > 9) count = 9;
|
||||
if (copy_from_user (stkbuf, buf, count))
|
||||
return -EFAULT;
|
||||
if (strncmp(stkbuf, reject_str, strlen(reject_str)) == 0)
|
||||
op = RTAS_REJECT_TMP_IMG;
|
||||
else if (strncmp(stkbuf, commit_str, strlen(commit_str)) == 0)
|
||||
op = RTAS_COMMIT_TMP_IMG;
|
||||
}
|
||||
|
||||
if (op == -1) { /* buf is empty, or contains invalid string */
|
||||
if (get_user(cmd, buf))
|
||||
return -EFAULT;
|
||||
|
||||
if (cmd == '0')
|
||||
op = RTAS_REJECT_TMP_IMG;
|
||||
else if (cmd == '1')
|
||||
op = RTAS_COMMIT_TMP_IMG;
|
||||
else
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
manage_flash(args_buf, op);
|
||||
return count;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include <linux/sched.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/overflow.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/init.h>
|
||||
|
|
@ -160,25 +161,17 @@ static void printk_log_rtas(char *buf, int len)
|
|||
|
||||
static int log_rtas_len(char * buf)
|
||||
{
|
||||
int len;
|
||||
size_t len;
|
||||
struct rtas_error_log *err;
|
||||
uint32_t extended_log_length;
|
||||
u32 extended_log_length;
|
||||
|
||||
/* rtas fixed header */
|
||||
len = 8;
|
||||
err = (struct rtas_error_log *)buf;
|
||||
extended_log_length = rtas_error_extended_log_length(err);
|
||||
if (rtas_error_extended(err) && extended_log_length) {
|
||||
|
||||
/* extended header */
|
||||
len += extended_log_length;
|
||||
}
|
||||
extended_log_length = rtas_error_extended(err) ? rtas_error_extended_log_length(err) : 0;
|
||||
len = struct_size(err, buffer, extended_log_length);
|
||||
|
||||
if (rtas_error_log_max == 0)
|
||||
rtas_error_log_max = rtas_get_error_log_max();
|
||||
|
||||
if (len > rtas_error_log_max)
|
||||
len = rtas_error_log_max;
|
||||
len = min(len, rtas_error_log_max);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -304,6 +304,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
|
|||
break;
|
||||
case 0x004e: /* POWER9 bits 12-15 give chip type */
|
||||
case 0x0080: /* POWER10 bit 12 gives SMT8/4 */
|
||||
case 0x0083: /* POWER12 bit 12 gives SMT8/4 */
|
||||
maj = (pvr >> 8) & 0x0F;
|
||||
min = pvr & 0xFF;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -289,6 +289,9 @@ void smp_muxed_ipi_set_message(int cpu, int msg)
|
|||
|
||||
void smp_muxed_ipi_message_pass(int cpu, int msg)
|
||||
{
|
||||
if (!smp_ops->cause_ipi)
|
||||
return;
|
||||
|
||||
smp_muxed_ipi_set_message(cpu, msg);
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -22,6 +22,9 @@ notrace long system_call_exception(struct pt_regs *regs, unsigned long r0)
|
|||
add_random_kstack_offset();
|
||||
r0 = syscall_enter_from_user_mode(regs, r0);
|
||||
|
||||
if (unlikely(test_and_clear_thread_flag(TIF_SYSCALL_RET)))
|
||||
return syscall_get_error(current, regs);
|
||||
|
||||
if (unlikely(r0 >= NR_syscalls)) {
|
||||
if (unlikely(trap_is_unsupported_scv(regs))) {
|
||||
/* Unsupported scv vector */
|
||||
|
|
|
|||
|
|
@ -502,7 +502,7 @@ static void update_crash_elfcorehdr(struct kimage *image, struct memory_notify *
|
|||
ret = get_crash_memory_ranges(&cmem);
|
||||
if (ret) {
|
||||
pr_err("Failed to get crash mem range\n");
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -36,25 +36,19 @@
|
|||
char *setup_kdump_cmdline(struct kimage *image, char *cmdline,
|
||||
unsigned long cmdline_len)
|
||||
{
|
||||
int elfcorehdr_strlen;
|
||||
char *cmdline_ptr;
|
||||
|
||||
cmdline_ptr = kzalloc(COMMAND_LINE_SIZE, GFP_KERNEL);
|
||||
cmdline_ptr = kmalloc(COMMAND_LINE_SIZE, GFP_KERNEL);
|
||||
if (!cmdline_ptr)
|
||||
return NULL;
|
||||
|
||||
elfcorehdr_strlen = sprintf(cmdline_ptr, "elfcorehdr=0x%lx ",
|
||||
image->elf_load_addr);
|
||||
|
||||
if (elfcorehdr_strlen + cmdline_len > COMMAND_LINE_SIZE) {
|
||||
pr_err("Appending elfcorehdr=<addr> exceeds cmdline size\n");
|
||||
if (snprintf(cmdline_ptr, COMMAND_LINE_SIZE, "elfcorehdr=0x%lx %s",
|
||||
image->elf_load_addr, cmdline_len ? cmdline : "") >= COMMAND_LINE_SIZE) {
|
||||
pr_err("Prepending elfcorehdr=<addr> exceeds cmdline size\n");
|
||||
kfree(cmdline_ptr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(cmdline_ptr + elfcorehdr_strlen, cmdline, cmdline_len);
|
||||
// Ensure it's nul terminated
|
||||
cmdline_ptr[COMMAND_LINE_SIZE - 1] = '\0';
|
||||
return cmdline_ptr;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -664,7 +664,7 @@ unsigned int kexec_extra_fdt_size_ppc64(struct kimage *image, struct crash_mem *
|
|||
extra_size += (cpu_nodes - boot_cpu_node_count) * cpu_node_size();
|
||||
|
||||
/* Consider extra space for reserved memory ranges if any */
|
||||
if (rmem->nr_ranges > 0)
|
||||
if (rmem && rmem->nr_ranges > 0)
|
||||
extra_size += sizeof(struct fdt_reserve_entry) * rmem->nr_ranges;
|
||||
|
||||
return extra_size + kdump_extra_fdt_size_ppc64(image, cpu_nodes);
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include <linux/of.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/minmax.h>
|
||||
#include <linux/crash_core.h>
|
||||
#include <asm/sections.h>
|
||||
#include <asm/kexec_ranges.h>
|
||||
|
|
@ -105,19 +106,16 @@ static void __merge_memory_ranges(struct crash_mem *mem_rngs)
|
|||
struct range *ranges;
|
||||
int i, idx;
|
||||
|
||||
if (!mem_rngs)
|
||||
if (!mem_rngs || mem_rngs->nr_ranges <= 1)
|
||||
return;
|
||||
|
||||
idx = 0;
|
||||
ranges = &(mem_rngs->ranges[0]);
|
||||
ranges = mem_rngs->ranges;
|
||||
for (i = 1; i < mem_rngs->nr_ranges; i++) {
|
||||
if (ranges[i].start <= (ranges[i-1].end + 1))
|
||||
ranges[idx].end = ranges[i].end;
|
||||
if (ranges[i].start <= (ranges[idx].end + 1))
|
||||
ranges[idx].end = max(ranges[idx].end, ranges[i].end);
|
||||
else {
|
||||
idx++;
|
||||
if (i == idx)
|
||||
continue;
|
||||
|
||||
ranges[idx] = ranges[i];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ config KVM
|
|||
select KVM_COMMON
|
||||
select KVM_VFIO
|
||||
select HAVE_KVM_IRQ_BYPASS
|
||||
select VIRT_XFER_TO_GUEST_WORK
|
||||
|
||||
config KVM_BOOK3S_HANDLER
|
||||
bool
|
||||
|
|
|
|||
|
|
@ -388,7 +388,7 @@ static void kvmppc_set_pvr_hv(struct kvm_vcpu *vcpu, u32 pvr)
|
|||
}
|
||||
|
||||
/* Dummy value used in computing PCR value below */
|
||||
#define PCR_ARCH_31 (PCR_ARCH_300 << 1)
|
||||
#define PCR_ARCH_32 (PCR_ARCH_31 << 1)
|
||||
|
||||
static inline unsigned long map_pcr_to_cap(unsigned long pcr)
|
||||
{
|
||||
|
|
@ -417,7 +417,9 @@ static int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, u32 arch_compat)
|
|||
struct kvmppc_vcore *vc = vcpu->arch.vcore;
|
||||
|
||||
/* We can (emulate) our own architecture version and anything older */
|
||||
if (cpu_has_feature(CPU_FTR_P11_PVR) || cpu_has_feature(CPU_FTR_ARCH_31))
|
||||
if (cpu_has_feature(CPU_FTR_ARCH_32))
|
||||
host_pcr_bit = PCR_ARCH_32;
|
||||
else if (cpu_has_feature(CPU_FTR_P11_PVR) || cpu_has_feature(CPU_FTR_ARCH_31))
|
||||
host_pcr_bit = PCR_ARCH_31;
|
||||
else if (cpu_has_feature(CPU_FTR_ARCH_300))
|
||||
host_pcr_bit = PCR_ARCH_300;
|
||||
|
|
@ -446,9 +448,24 @@ static int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, u32 arch_compat)
|
|||
guest_pcr_bit = PCR_ARCH_300;
|
||||
break;
|
||||
case PVR_ARCH_31:
|
||||
case PVR_ARCH_31_P11:
|
||||
guest_pcr_bit = PCR_ARCH_31;
|
||||
break;
|
||||
case PVR_ARCH_31_P11:
|
||||
/*
|
||||
* Need to check this for ISA 3.1, as Power10 and
|
||||
* Power11 share the same PCR. For any subsequent ISA
|
||||
* versions, this will be taken care of by the guest vs
|
||||
* host PCR comparison below.
|
||||
*/
|
||||
if (!cpu_has_feature(CPU_FTR_P11_PVR)) {
|
||||
arch_compat = PVR_ARCH_INVALID;
|
||||
goto out;
|
||||
}
|
||||
guest_pcr_bit = PCR_ARCH_31;
|
||||
break;
|
||||
case PVR_ARCH_32:
|
||||
guest_pcr_bit = PCR_ARCH_32;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -469,6 +486,7 @@ static int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, u32 arch_compat)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
out:
|
||||
spin_lock(&vc->lock);
|
||||
vc->arch_compat = arch_compat;
|
||||
kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_LOGICAL_PVR);
|
||||
|
|
@ -479,7 +497,7 @@ static int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, u32 arch_compat)
|
|||
vc->pcr = (host_pcr_bit - guest_pcr_bit) | PCR_MASK;
|
||||
spin_unlock(&vc->lock);
|
||||
|
||||
return 0;
|
||||
return kvmppc_sanity_check(vcpu);
|
||||
}
|
||||
|
||||
static void kvmppc_dump_regs(struct kvm_vcpu *vcpu)
|
||||
|
|
@ -3853,7 +3871,8 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)
|
|||
*/
|
||||
local_irq_disable();
|
||||
hard_irq_disable();
|
||||
if (lazy_irq_pending() || need_resched() ||
|
||||
xfer_to_guest_mode_prepare();
|
||||
if (lazy_irq_pending() || xfer_to_guest_mode_work_pending() ||
|
||||
recheck_signals_and_mmu(&core_info)) {
|
||||
local_irq_enable();
|
||||
vc->vcore_state = VCORE_INACTIVE;
|
||||
|
|
@ -4824,10 +4843,16 @@ static int kvmppc_run_vcpu(struct kvm_vcpu *vcpu)
|
|||
vc->runner = vcpu;
|
||||
if (n_ceded == vc->n_runnable) {
|
||||
kvmppc_vcore_blocked(vc);
|
||||
} else if (need_resched()) {
|
||||
} else if (__xfer_to_guest_mode_work_pending()) {
|
||||
kvmppc_vcore_preempt(vc);
|
||||
/* Let something else run */
|
||||
cond_resched_lock(&vc->lock);
|
||||
/*
|
||||
* Let something else run. The raw helper is used as
|
||||
* signal exits are accounted by this path already;
|
||||
* it may schedule(), so drop the vcore lock.
|
||||
*/
|
||||
spin_unlock(&vc->lock);
|
||||
xfer_to_guest_mode_handle_work();
|
||||
spin_lock(&vc->lock);
|
||||
if (vc->vcore_state == VCORE_PREEMPT)
|
||||
kvmppc_vcore_end_preempt(vc);
|
||||
} else {
|
||||
|
|
@ -4895,12 +4920,16 @@ int kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, u64 time_limit,
|
|||
run->exit_reason = KVM_EXIT_FAIL_ENTRY;
|
||||
run->fail_entry.hardware_entry_failure_reason = 0;
|
||||
vcpu->arch.ret = r;
|
||||
return r;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (need_resched())
|
||||
cond_resched();
|
||||
r = kvm_xfer_to_guest_mode_handle_work(vcpu);
|
||||
if (r) {
|
||||
/* -EINTR: signal pending, exit to userspace (KVM_EXIT_INTR) */
|
||||
vcpu->arch.ret = r;
|
||||
goto done;
|
||||
}
|
||||
|
||||
kvmppc_update_vpas(vcpu);
|
||||
|
||||
|
|
@ -4914,9 +4943,13 @@ int kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, u64 time_limit,
|
|||
|
||||
vcpu->arch.state = KVMPPC_VCPU_RUNNABLE;
|
||||
|
||||
if (signal_pending(current))
|
||||
goto sigpend;
|
||||
if (need_resched() || !kvm->arch.mmu_ready)
|
||||
xfer_to_guest_mode_prepare();
|
||||
|
||||
/*
|
||||
* IRQs are disabled here, so on pending work bail to the outer loop,
|
||||
* which handles it via kvm_xfer_to_guest_mode_handle_work() above.
|
||||
*/
|
||||
if (xfer_to_guest_mode_work_pending() || !kvm->arch.mmu_ready)
|
||||
goto out;
|
||||
|
||||
vcpu->cpu = pcpu;
|
||||
|
|
@ -5068,10 +5101,6 @@ int kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, u64 time_limit,
|
|||
|
||||
return vcpu->arch.ret;
|
||||
|
||||
sigpend:
|
||||
vcpu->stat.signal_exits++;
|
||||
run->exit_reason = KVM_EXIT_INTR;
|
||||
vcpu->arch.ret = -EINTR;
|
||||
out:
|
||||
vcpu->cpu = -1;
|
||||
vcpu->arch.thread_cpu = -1;
|
||||
|
|
@ -6510,6 +6539,61 @@ static bool kvmppc_hash_v3_possible(void)
|
|||
return true;
|
||||
}
|
||||
|
||||
static int kvmppc_map_compat_capabilities(u32 cpu_version,
|
||||
unsigned long *capabilities)
|
||||
{
|
||||
switch (cpu_version) {
|
||||
case PVR_ARCH_31_P11:
|
||||
*capabilities |= KVM_PPC_COMPAT_CAP_POWER11;
|
||||
fallthrough;
|
||||
case PVR_ARCH_31:
|
||||
*capabilities |= KVM_PPC_COMPAT_CAP_POWER10;
|
||||
fallthrough;
|
||||
case PVR_ARCH_300:
|
||||
*capabilities |= KVM_PPC_COMPAT_CAP_POWER9;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kvmppc_get_compat_caps(struct kvm_ppc_compat_caps *host_caps)
|
||||
{
|
||||
struct device_node *np;
|
||||
unsigned long capabilities = 0;
|
||||
long rc = -EINVAL;
|
||||
u32 cpu_version = 0;
|
||||
|
||||
if (kvmhv_on_pseries()) {
|
||||
if (kvmhv_is_nestedv2()) {
|
||||
WARN_ON_ONCE(!nested_capabilities);
|
||||
capabilities = nested_capabilities;
|
||||
rc = 0;
|
||||
} else {
|
||||
for_each_node_by_type(np, "cpu") {
|
||||
if (!of_property_read_u32(np, "cpu-version",
|
||||
&cpu_version)) {
|
||||
of_node_put(np);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!cpu_version)
|
||||
return -EINVAL;
|
||||
rc = kvmppc_map_compat_capabilities(cpu_version,
|
||||
&capabilities);
|
||||
}
|
||||
}
|
||||
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
host_caps->compat_capabilities = capabilities & KVM_PPC_COMPAT_BITMASK;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static struct kvmppc_ops kvm_ops_hv = {
|
||||
.get_sregs = kvm_arch_vcpu_ioctl_get_sregs_hv,
|
||||
.set_sregs = kvm_arch_vcpu_ioctl_set_sregs_hv,
|
||||
|
|
@ -6552,6 +6636,7 @@ static struct kvmppc_ops kvm_ops_hv = {
|
|||
.hash_v3_possible = kvmppc_hash_v3_possible,
|
||||
.create_vcpu_debugfs = kvmppc_arch_create_vcpu_debugfs_hv,
|
||||
.create_vm_debugfs = kvmppc_arch_create_vm_debugfs_hv,
|
||||
.get_compat_caps = kvmppc_get_compat_caps,
|
||||
};
|
||||
|
||||
static int kvm_init_subcore_bitmap(void)
|
||||
|
|
|
|||
|
|
@ -598,7 +598,7 @@ static unsigned long watchdog_next_timeout(struct kvm_vcpu *vcpu)
|
|||
if (do_div(nr_jiffies, tb_ticks_per_jiffy))
|
||||
nr_jiffies++;
|
||||
|
||||
return min_t(unsigned long long, nr_jiffies, TIMER_NEXT_MAX_DELTA);
|
||||
return min(nr_jiffies, TIMER_NEXT_MAX_DELTA);
|
||||
}
|
||||
|
||||
static void arm_next_watchdog(struct kvm_vcpu *vcpu)
|
||||
|
|
@ -722,6 +722,7 @@ int kvmppc_core_prepare_to_enter(struct kvm_vcpu *vcpu)
|
|||
if (vcpu->arch.shared->msr & MSR_WE) {
|
||||
local_irq_enable();
|
||||
kvm_vcpu_halt(vcpu);
|
||||
local_irq_disable();
|
||||
hard_irq_disable();
|
||||
|
||||
kvmppc_set_exit_type(vcpu, EMULATED_MTMSRWE_EXITS);
|
||||
|
|
|
|||
|
|
@ -1833,7 +1833,8 @@ int kvm_set_routing_entry(struct kvm *kvm,
|
|||
e->set = mpic_set_irq;
|
||||
e->irqchip.irqchip = ue->u.irqchip.irqchip;
|
||||
e->irqchip.pin = ue->u.irqchip.pin;
|
||||
if (e->irqchip.pin >= KVM_IRQCHIP_NUM_PINS)
|
||||
if (e->irqchip.pin >= KVM_IRQCHIP_NUM_PINS ||
|
||||
e->irqchip.irqchip >= KVM_NR_IRQCHIPS)
|
||||
goto out;
|
||||
break;
|
||||
case KVM_IRQ_ROUTING_MSI:
|
||||
|
|
|
|||
|
|
@ -81,21 +81,39 @@ int kvmppc_prepare_to_enter(struct kvm_vcpu *vcpu)
|
|||
int r;
|
||||
|
||||
WARN_ON(irqs_disabled());
|
||||
/*
|
||||
* local_irq_disable() first: on 32-bit, hard_irq_disable() alone is a
|
||||
* raw MSR[EE] clear that bypasses the lockdep/irq-tracing state, and
|
||||
* the xfer_to_guest_mode helpers assert IRQs are seen as disabled.
|
||||
*/
|
||||
local_irq_disable();
|
||||
hard_irq_disable();
|
||||
|
||||
while (true) {
|
||||
if (need_resched()) {
|
||||
local_irq_enable();
|
||||
cond_resched();
|
||||
hard_irq_disable();
|
||||
continue;
|
||||
}
|
||||
xfer_to_guest_mode_prepare();
|
||||
|
||||
if (signal_pending(current)) {
|
||||
kvmppc_account_exit(vcpu, SIGNAL_EXITS);
|
||||
vcpu->run->exit_reason = KVM_EXIT_INTR;
|
||||
r = -EINTR;
|
||||
break;
|
||||
if (xfer_to_guest_mode_work_pending()) {
|
||||
/*
|
||||
* The helper must run with IRQs enabled and may
|
||||
* schedule(). On a pending signal it returns -EINTR
|
||||
* with run->exit_reason and vcpu->stat.signal_exits
|
||||
* already set, so just return to userspace.
|
||||
*/
|
||||
local_irq_enable();
|
||||
r = kvm_xfer_to_guest_mode_handle_work(vcpu);
|
||||
local_irq_disable();
|
||||
hard_irq_disable();
|
||||
if (r) {
|
||||
/*
|
||||
* The generic helper does not set the exit
|
||||
* type; record it for the E500
|
||||
* CONFIG_KVM_EXIT_TIMING histogram (a no-op
|
||||
* otherwise).
|
||||
*/
|
||||
kvmppc_set_exit_type(vcpu, SIGNAL_EXITS);
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
vcpu->mode = IN_GUEST_MODE;
|
||||
|
|
@ -116,6 +134,7 @@ int kvmppc_prepare_to_enter(struct kvm_vcpu *vcpu)
|
|||
local_irq_enable();
|
||||
trace_kvm_check_requests(vcpu);
|
||||
r = kvmppc_core_check_requests(vcpu);
|
||||
local_irq_disable();
|
||||
hard_irq_disable();
|
||||
if (r > 0)
|
||||
continue;
|
||||
|
|
@ -258,6 +277,12 @@ int kvmppc_sanity_check(struct kvm_vcpu *vcpu)
|
|||
if (!vcpu->arch.pvr)
|
||||
goto out;
|
||||
|
||||
#if defined(CONFIG_KVM_BOOK3S_HV_POSSIBLE)
|
||||
if (vcpu->arch.vcore &&
|
||||
vcpu->arch.vcore->arch_compat == PVR_ARCH_INVALID)
|
||||
goto out;
|
||||
#endif
|
||||
|
||||
/* PAPR only works with book3s_64 */
|
||||
if ((vcpu->arch.cpu_type != KVM_CPU_3S_64) && vcpu->arch.papr_enabled)
|
||||
goto out;
|
||||
|
|
@ -635,9 +660,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
|
|||
* implementations just count online CPUs.
|
||||
*/
|
||||
if (hv_enabled)
|
||||
r = min_t(unsigned int, num_present_cpus(), KVM_MAX_VCPUS);
|
||||
r = min(num_present_cpus(), KVM_MAX_VCPUS);
|
||||
else
|
||||
r = min_t(unsigned int, num_online_cpus(), KVM_MAX_VCPUS);
|
||||
r = min(num_online_cpus(), KVM_MAX_VCPUS);
|
||||
break;
|
||||
case KVM_CAP_MAX_VCPUS:
|
||||
r = KVM_MAX_VCPUS;
|
||||
|
|
@ -697,6 +722,13 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
|
|||
}
|
||||
}
|
||||
break;
|
||||
#if defined(CONFIG_KVM_BOOK3S_HV_POSSIBLE)
|
||||
case KVM_CAP_PPC_COMPAT_CAPS:
|
||||
r = 0;
|
||||
if (hv_enabled && kvmhv_on_pseries())
|
||||
r = 1;
|
||||
break;
|
||||
#endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */
|
||||
default:
|
||||
r = 0;
|
||||
break;
|
||||
|
|
@ -2463,6 +2495,77 @@ int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
|
|||
r = kvm->arch.kvm_ops->svm_off(kvm);
|
||||
break;
|
||||
}
|
||||
case KVM_PPC_GET_COMPAT_CAPS: {
|
||||
struct kvm_ppc_compat_caps host_caps = {};
|
||||
u64 usize;
|
||||
|
||||
/*
|
||||
* Read the size field first to drive copy_struct_from_user.
|
||||
* size must be the first field of the struct.
|
||||
*/
|
||||
r = -EFAULT;
|
||||
if (get_user(usize, (__u64 __user *)argp))
|
||||
goto out;
|
||||
|
||||
r = -E2BIG;
|
||||
if (unlikely(usize > PAGE_SIZE))
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Enforce a minimum: reject buffers smaller than the initial
|
||||
* struct version (VER0). This allows old userspace compiled
|
||||
* against the original struct to still work on a newer kernel
|
||||
* that has grown the struct with appended fields.
|
||||
*/
|
||||
r = -EINVAL;
|
||||
if (usize < KVM_PPC_COMPAT_CAPS_SIZE_VER0)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* copy_struct_from_user() handles forward/backward compat:
|
||||
* usize == ksize: verbatim copy
|
||||
* usize < ksize: zero-pad trailing (old userspace, new kernel)
|
||||
* usize > ksize: succeed iff trailing bytes are zero, else -E2BIG
|
||||
*/
|
||||
r = copy_struct_from_user(&host_caps, sizeof(host_caps),
|
||||
argp, usize);
|
||||
if (r) {
|
||||
/*
|
||||
* New userspace with a larger struct called an older
|
||||
* kernel. Write back ksize in host_caps.size so
|
||||
* userspace knows which older struct to retry with,
|
||||
* then fail with -E2BIG.
|
||||
*/
|
||||
if (r == -E2BIG)
|
||||
if (put_user((__u64)sizeof(host_caps),
|
||||
(__u64 __user *)argp))
|
||||
r = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Reserved fields must be zero */
|
||||
r = -EINVAL;
|
||||
if (host_caps.flags)
|
||||
goto out;
|
||||
|
||||
r = -ENOTTY;
|
||||
if (!kvm->arch.kvm_ops->get_compat_caps)
|
||||
goto out;
|
||||
|
||||
r = kvm->arch.kvm_ops->get_compat_caps(&host_caps);
|
||||
if (r)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Report the number of bytes actually populated by the kernel,
|
||||
* not usize: if new userspace passed a larger struct with zero
|
||||
* trailing bytes, we only filled sizeof(host_caps) bytes.
|
||||
*/
|
||||
host_caps.size = min_t(u64, usize, sizeof(host_caps));
|
||||
r = copy_struct_to_user(argp, usize, &host_caps,
|
||||
sizeof(host_caps), NULL);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
struct kvm *kvm = filp->private_data;
|
||||
r = kvm->arch.kvm_ops->arch_vm_ioctl(filp, ioctl, arg);
|
||||
|
|
|
|||
|
|
@ -184,9 +184,14 @@ static inline void __tlbiel(unsigned long vpn, int psize, int apsize, int ssize)
|
|||
va |= ssize << 8;
|
||||
sllp = get_sllp_encoding(apsize);
|
||||
va |= sllp << 5;
|
||||
asm volatile(ASM_FTR_IFSET("tlbiel %0", PPC_TLBIEL_v205(%0, 0), %1)
|
||||
: : "r" (va), "i" (CPU_FTR_ARCH_206)
|
||||
: "memory");
|
||||
|
||||
if (cpu_has_feature(CPU_FTR_ARCH_32)) {
|
||||
asm volatile(PPC_TLBIEL(%0, %1, 0, 0, 0) : : "r"(va), "r"(0) : "memory");
|
||||
} else {
|
||||
asm volatile(ASM_FTR_IFSET("tlbiel %0", PPC_TLBIEL_v205(%0, 0), %1)
|
||||
: : "r" (va), "i" (CPU_FTR_ARCH_206)
|
||||
: "memory");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* We need 14 to 14 + i bits of va */
|
||||
|
|
@ -203,9 +208,14 @@ static inline void __tlbiel(unsigned long vpn, int psize, int apsize, int ssize)
|
|||
*/
|
||||
va |= (vpn & 0xfe);
|
||||
va |= 1; /* L */
|
||||
asm volatile(ASM_FTR_IFSET("tlbiel %0", PPC_TLBIEL_v205(%0, 1), %1)
|
||||
: : "r" (va), "i" (CPU_FTR_ARCH_206)
|
||||
: "memory");
|
||||
|
||||
if (cpu_has_feature(CPU_FTR_ARCH_32)) {
|
||||
asm volatile(PPC_TLBIEL(%0, %1, 0, 0, 0) : : "r"(va), "r"(0) : "memory");
|
||||
} else {
|
||||
asm volatile(ASM_FTR_IFSET("tlbiel %0", PPC_TLBIEL_v205(%0, 1), %1)
|
||||
: : "r" (va), "i" (CPU_FTR_ARCH_206)
|
||||
: "memory");
|
||||
}
|
||||
break;
|
||||
}
|
||||
trace_tlbie(0, 1, va, 0, 0, 0, 0);
|
||||
|
|
|
|||
|
|
@ -628,7 +628,9 @@ void __init mmu_early_init_devtree(void)
|
|||
|
||||
of_scan_flat_dt(dt_scan_mmu_pid_width, NULL);
|
||||
if (hvmode && !mmu_lpid_bits) {
|
||||
if (early_cpu_has_feature(CPU_FTR_ARCH_207S))
|
||||
if (early_cpu_has_feature(CPU_FTR_ARCH_32))
|
||||
mmu_lpid_bits = 16; /* POWER12 */
|
||||
else if (early_cpu_has_feature(CPU_FTR_ARCH_207S))
|
||||
mmu_lpid_bits = 12; /* POWER8-10 */
|
||||
else
|
||||
mmu_lpid_bits = 10; /* POWER7 */
|
||||
|
|
|
|||
|
|
@ -471,8 +471,6 @@ static int bpf_jit_emit_func_call(u32 *image, struct codegen_context *ctx, u64 f
|
|||
int bpf_jit_emit_func_call_rel(u32 *image, u32 *fimage, struct codegen_context *ctx, u64 func)
|
||||
{
|
||||
unsigned long func_addr = func ? ppc_function_entry((void *)func) : 0;
|
||||
long __maybe_unused reladdr;
|
||||
int ret;
|
||||
|
||||
/* bpf to bpf call, func is not known in the initial pass. Emit 5 nops as a placeholder */
|
||||
if (!func) {
|
||||
|
|
@ -487,6 +485,8 @@ int bpf_jit_emit_func_call_rel(u32 *image, u32 *fimage, struct codegen_context *
|
|||
}
|
||||
|
||||
#ifdef CONFIG_PPC_KERNEL_PCREL
|
||||
long reladdr;
|
||||
|
||||
reladdr = func_addr - local_paca->kernelbase;
|
||||
|
||||
/*
|
||||
|
|
@ -525,7 +525,7 @@ int bpf_jit_emit_func_call_rel(u32 *image, u32 *fimage, struct codegen_context *
|
|||
EMIT(PPC_RAW_BCTRL());
|
||||
#else
|
||||
if (core_kernel_text(func_addr)) {
|
||||
ret = bpf_jit_emit_func_call(image, ctx, func_addr, _R12);
|
||||
int ret = bpf_jit_emit_func_call(image, ctx, func_addr, _R12);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ SYM_FUNC_START(arch_bpf_timed_may_goto)
|
|||
* BPF_REG_FP is r31; BPF_REG_AX is r12 (stack offset in bytes).
|
||||
*/
|
||||
add r3, r31, r12
|
||||
bl bpf_check_timed_may_goto
|
||||
bl CFUNC(bpf_check_timed_may_goto)
|
||||
|
||||
/* Put return value back into AX */
|
||||
mr r12, r3
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ obj-$(CONFIG_PPC_PERF_CTRS) += core-book3s.o
|
|||
obj64-$(CONFIG_PPC_PERF_CTRS) += ppc970-pmu.o power5-pmu.o \
|
||||
power5+-pmu.o power6-pmu.o power7-pmu.o \
|
||||
isa207-common.o power8-pmu.o power9-pmu.o \
|
||||
generic-compat-pmu.o power10-pmu.o bhrb.o
|
||||
generic-compat-pmu.o power10-pmu.o bhrb.o power12-pmu.o
|
||||
obj32-$(CONFIG_PPC_PERF_CTRS) += mpc7450-pmu.o
|
||||
|
||||
obj-$(CONFIG_PPC_POWERNV) += imc-pmu.o
|
||||
|
|
|
|||
|
|
@ -2613,6 +2613,8 @@ static int __init init_ppc64_pmu(void)
|
|||
return 0;
|
||||
else if (!init_power11_pmu())
|
||||
return 0;
|
||||
else if (!init_power12_pmu())
|
||||
return 0;
|
||||
else if (!init_ppc970_pmu())
|
||||
return 0;
|
||||
else
|
||||
|
|
|
|||
|
|
@ -11,4 +11,5 @@ int __init init_power8_pmu(void);
|
|||
int __init init_power9_pmu(void);
|
||||
int __init init_power10_pmu(void);
|
||||
int __init init_power11_pmu(void);
|
||||
int __init init_power12_pmu(void);
|
||||
int __init init_generic_compat_pmu(void);
|
||||
|
|
|
|||
78
arch/powerpc/perf/power12-events-list.h
Normal file
78
arch/powerpc/perf/power12-events-list.h
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Performance counter support for POWER12 processors.
|
||||
*
|
||||
* Copyright 2026 Athira Rajeev, IBM Corporation.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Power12 event codes.
|
||||
*/
|
||||
EVENT(PM_CYC, 0x600f4);
|
||||
EVENT(PM_DISP_STALL_CYC, 0x100f8);
|
||||
EVENT(PM_EXEC_STALL, 0x30008);
|
||||
EVENT(PM_INST_CMPL, 0x500fa);
|
||||
EVENT(PM_BR_CMPL, 0x4d05e);
|
||||
EVENT(PM_BR_MPRED_CMPL, 0x400f6);
|
||||
EVENT(PM_BR_FIN, 0x10068);
|
||||
EVENT(PM_MPRED_BR_FIN, 0x27098);
|
||||
EVENT(PM_LD_DEMAND_MISS_L1_FIN, 0x400f0);
|
||||
|
||||
/* All L1 D cache load references counted at finish, gated by reject */
|
||||
EVENT(PM_LD_REF_L1, 0x100fc);
|
||||
/* Load Missed L1 */
|
||||
EVENT(PM_LD_MISS_L1, 0x3e054);
|
||||
/* Store Missed L1 */
|
||||
EVENT(PM_ST_MISS_L1, 0x300f0);
|
||||
/* L1 cache data prefetches */
|
||||
EVENT(PM_LD_PREFETCH_CACHE_LINE_MISS, 0x1002c);
|
||||
/* Demand iCache Miss */
|
||||
EVENT(PM_L1_ICACHE_MISS, 0x200fc);
|
||||
/* Instruction fetches from L1 */
|
||||
EVENT(PM_INST_FROM_L1, 0x04080);
|
||||
/* Instruction Demand sectors writtent into IL1 */
|
||||
EVENT(PM_INST_FROM_L1MISS, 0x03F00000001C040);
|
||||
/* Instruction prefetch written into IL1 */
|
||||
EVENT(PM_IC_PREF_REQ, 0x040a0);
|
||||
/* The data cache was reloaded from local core's L3 due to a demand load */
|
||||
EVENT(PM_DATA_FROM_L3, 0x10340000003C040);
|
||||
/* Demand LD - L3 Miss (not L2 hit and not L3 hit) */
|
||||
EVENT(PM_DATA_FROM_L3MISS, 0x300fe);
|
||||
/* All successful D-side store dispatches for this thread */
|
||||
EVENT(PM_L2_ST, 0x010000046080);
|
||||
/* All successful D-side store dispatches for this thread that were L2 Miss */
|
||||
EVENT(PM_L2_ST_MISS, 0x26880);
|
||||
/* Total HW L3 prefetches(Load+store) */
|
||||
EVENT(PM_L3_PF_MISS_L3, 0x100000016080);
|
||||
/* Data PTEG reload */
|
||||
EVENT(PM_DTLB_MISS, 0x300fc);
|
||||
/* ITLB Reloaded */
|
||||
EVENT(PM_ITLB_MISS, 0x400fc);
|
||||
|
||||
EVENT(PM_CYC_ALT, 0x0001e);
|
||||
EVENT(PM_INST_CMPL_ALT, 0x00002);
|
||||
|
||||
/*
|
||||
* Memory Access Events
|
||||
*
|
||||
* Primary PMU event used here is PM_MRK_INST_CMPL (0x401e0)
|
||||
* To enable capturing of memory profiling, these MMCRA bits
|
||||
* needs to be programmed and corresponding raw event format
|
||||
* encoding.
|
||||
*
|
||||
* MMCRA bits encoding needed are
|
||||
* SM (Sampling Mode)
|
||||
* EM (Eligibility for Random Sampling)
|
||||
* TECE (Threshold Event Counter Event)
|
||||
* TS (Threshold Start Event)
|
||||
* TE (Threshold End Event)
|
||||
*
|
||||
* Corresponding Raw Encoding bits:
|
||||
* sample [EM,SM]
|
||||
* thresh_sel (TECE)
|
||||
* thresh start (TS)
|
||||
* thresh end (TE)
|
||||
*/
|
||||
|
||||
EVENT(MEM_LOADS, 0x35340401e0);
|
||||
EVENT(MEM_STORES, 0x353c0401e0);
|
||||
466
arch/powerpc/perf/power12-pmu.c
Normal file
466
arch/powerpc/perf/power12-pmu.c
Normal file
|
|
@ -0,0 +1,466 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Performance counter support for Power12 processors.
|
||||
*
|
||||
* Copyright 2026 Athira Rajeev, IBM Corporation.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "power12-pmu: " fmt
|
||||
|
||||
#include "isa207-common.h"
|
||||
|
||||
/*
|
||||
* Raw event encoding for Power12:
|
||||
*
|
||||
* 60 56 52 48 44 40 36 32
|
||||
* | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - |
|
||||
* | | [ ] [ src_match ] [ src_mask ] | [ ] [ l2l3_sel ] [ thresh_ctl ]
|
||||
* | | | | | |
|
||||
* | | *- IFM (Linux) | | thresh start/stop -*
|
||||
* | *- BHRB (Linux) | src_sel
|
||||
* *- EBB (Linux) *invert_bit
|
||||
*
|
||||
* 28 24 20 16 12 8 4 0
|
||||
* | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - |
|
||||
* [ ] [ sample ] [ ] [ ] [ pmc ] [unit ] [ ] | m [ pmcxsel ]
|
||||
* | | | | | | |
|
||||
* | | | | | | *- mark
|
||||
* | | | *- L1/L2/L3 cache_sel | |*-radix_scope_qual
|
||||
* | | sdar_mode |
|
||||
* | *- sampling mode for marked events *- combine
|
||||
* |
|
||||
* *- thresh_sel
|
||||
*
|
||||
* Below uses IBM bit numbering.
|
||||
*
|
||||
* MMCR1[x:y] = unit (PMCxUNIT)
|
||||
* MMCR1[24] = pmc1combine[0]
|
||||
* MMCR1[25] = pmc1combine[1]
|
||||
* MMCR1[26] = pmc2combine[0]
|
||||
* MMCR1[27] = pmc2combine[1]
|
||||
* MMCR1[28] = pmc3combine[0]
|
||||
* MMCR1[29] = pmc3combine[1]
|
||||
* MMCR1[30] = pmc4combine[0]
|
||||
* MMCR1[31] = pmc4combine[1]
|
||||
*
|
||||
* if pmc == 3 and unit == 0 and pmcxsel[0:6] == 0b0101011
|
||||
* MMCR1[20:27] = thresh_ctl
|
||||
* else if pmc == 4 and unit == 0xf and pmcxsel[0:6] == 0b0101001
|
||||
* MMCR1[20:27] = thresh_ctl
|
||||
* else
|
||||
* MMCRA[48:55] = thresh_ctl (THRESH START/END)
|
||||
*
|
||||
* if thresh_sel:
|
||||
* MMCRA[45:47] = thresh_sel
|
||||
*
|
||||
* if l2l3_sel:
|
||||
* MMCR2[56:60] = l2l3_sel[0:4]
|
||||
*
|
||||
* MMCR1[16] = cache_sel[0]
|
||||
* MMCR1[17] = cache_sel[1]
|
||||
* MMCR1[18] = radix_scope_qual
|
||||
*
|
||||
* if mark:
|
||||
* MMCRA[63] = 1 (SAMPLE_ENABLE)
|
||||
* MMCRA[57:59] = sample[0:2] (RAND_SAMP_ELIG)
|
||||
* MMCRA[61:62] = sample[3:4] (RAND_SAMP_MODE)
|
||||
*
|
||||
* if EBB and BHRB:
|
||||
* MMCRA[32:33] = IFM
|
||||
*
|
||||
* MMCRA[SDAR_MODE] = sdar_mode[0:1]
|
||||
*/
|
||||
|
||||
/*
|
||||
* Some power12 event codes.
|
||||
*/
|
||||
#define EVENT(_name, _code) enum{_name = _code}
|
||||
|
||||
#include "power12-events-list.h"
|
||||
|
||||
#undef EVENT
|
||||
|
||||
/* MMCRA IFM bits - POWER12 */
|
||||
#define POWER12_MMCRA_IFM1 0x0000000040000000UL
|
||||
#define POWER12_MMCRA_IFM2 0x0000000080000000UL
|
||||
#define POWER12_MMCRA_IFM3 0x00000000C0000000UL
|
||||
#define POWER12_MMCRA_BHRB_MASK 0x00000000C0000000UL
|
||||
|
||||
extern u64 PERF_REG_EXTENDED_MASK;
|
||||
|
||||
/* Table of alternatives, sorted by column 0 */
|
||||
static const unsigned int power12_event_alternatives[][MAX_ALT] = {
|
||||
{ PM_INST_CMPL_ALT, PM_INST_CMPL },
|
||||
{ PM_CYC_ALT, PM_CYC },
|
||||
};
|
||||
|
||||
static int power12_get_alternatives(u64 event, unsigned int flags, u64 alt[])
|
||||
{
|
||||
int num_alt = 0;
|
||||
|
||||
num_alt = isa207_get_alternatives(event, alt,
|
||||
ARRAY_SIZE(power12_event_alternatives), flags,
|
||||
power12_event_alternatives);
|
||||
|
||||
return num_alt;
|
||||
}
|
||||
|
||||
static int power12_check_attr_config(struct perf_event *ev)
|
||||
{
|
||||
u64 val;
|
||||
u64 event = ev->attr.config;
|
||||
|
||||
val = (event >> EVENT_SAMPLE_SHIFT) & EVENT_SAMPLE_MASK;
|
||||
if (val == 0x10 || isa3XX_check_attr_config(ev))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
GENERIC_EVENT_ATTR(cpu-cycles, PM_CYC);
|
||||
GENERIC_EVENT_ATTR(instructions, PM_INST_CMPL);
|
||||
GENERIC_EVENT_ATTR(branch-instructions, PM_BR_FIN);
|
||||
GENERIC_EVENT_ATTR(branch-misses, PM_MPRED_BR_FIN);
|
||||
GENERIC_EVENT_ATTR(cache-references, PM_LD_REF_L1);
|
||||
GENERIC_EVENT_ATTR(cache-misses, PM_LD_DEMAND_MISS_L1_FIN);
|
||||
GENERIC_EVENT_ATTR(mem-loads, MEM_LOADS);
|
||||
GENERIC_EVENT_ATTR(mem-stores, MEM_STORES);
|
||||
|
||||
CACHE_EVENT_ATTR(L1-dcache-load-misses, PM_LD_MISS_L1);
|
||||
CACHE_EVENT_ATTR(L1-dcache-loads, PM_LD_REF_L1);
|
||||
CACHE_EVENT_ATTR(L1-dcache-prefetches, PM_LD_PREFETCH_CACHE_LINE_MISS);
|
||||
CACHE_EVENT_ATTR(L1-dcache-store-misses, PM_ST_MISS_L1);
|
||||
CACHE_EVENT_ATTR(L1-icache-load-misses, PM_L1_ICACHE_MISS);
|
||||
CACHE_EVENT_ATTR(L1-icache-loads, PM_INST_FROM_L1);
|
||||
CACHE_EVENT_ATTR(L1-icache-prefetches, PM_IC_PREF_REQ);
|
||||
CACHE_EVENT_ATTR(LLC-load-misses, PM_DATA_FROM_L3MISS);
|
||||
CACHE_EVENT_ATTR(LLC-loads, PM_DATA_FROM_L3);
|
||||
CACHE_EVENT_ATTR(LLC-prefetches, PM_L3_PF_MISS_L3);
|
||||
CACHE_EVENT_ATTR(LLC-store-misses, PM_L2_ST_MISS);
|
||||
CACHE_EVENT_ATTR(LLC-stores, PM_L2_ST);
|
||||
CACHE_EVENT_ATTR(branch-load-misses, PM_BR_MPRED_CMPL);
|
||||
CACHE_EVENT_ATTR(branch-loads, PM_BR_CMPL);
|
||||
CACHE_EVENT_ATTR(dTLB-load-misses, PM_DTLB_MISS);
|
||||
CACHE_EVENT_ATTR(iTLB-load-misses, PM_ITLB_MISS);
|
||||
|
||||
static struct attribute *power12_events_attr[] = {
|
||||
GENERIC_EVENT_PTR(PM_CYC),
|
||||
GENERIC_EVENT_PTR(PM_INST_CMPL),
|
||||
GENERIC_EVENT_PTR(PM_BR_FIN),
|
||||
GENERIC_EVENT_PTR(PM_MPRED_BR_FIN),
|
||||
GENERIC_EVENT_PTR(PM_LD_REF_L1),
|
||||
GENERIC_EVENT_PTR(PM_LD_DEMAND_MISS_L1_FIN),
|
||||
GENERIC_EVENT_PTR(MEM_LOADS),
|
||||
GENERIC_EVENT_PTR(MEM_STORES),
|
||||
CACHE_EVENT_PTR(PM_LD_MISS_L1),
|
||||
CACHE_EVENT_PTR(PM_LD_REF_L1),
|
||||
CACHE_EVENT_PTR(PM_LD_PREFETCH_CACHE_LINE_MISS),
|
||||
CACHE_EVENT_PTR(PM_ST_MISS_L1),
|
||||
CACHE_EVENT_PTR(PM_L1_ICACHE_MISS),
|
||||
CACHE_EVENT_PTR(PM_INST_FROM_L1),
|
||||
CACHE_EVENT_PTR(PM_IC_PREF_REQ),
|
||||
CACHE_EVENT_PTR(PM_DATA_FROM_L3MISS),
|
||||
CACHE_EVENT_PTR(PM_DATA_FROM_L3),
|
||||
CACHE_EVENT_PTR(PM_L3_PF_MISS_L3),
|
||||
CACHE_EVENT_PTR(PM_L2_ST_MISS),
|
||||
CACHE_EVENT_PTR(PM_L2_ST),
|
||||
CACHE_EVENT_PTR(PM_BR_MPRED_CMPL),
|
||||
CACHE_EVENT_PTR(PM_BR_CMPL),
|
||||
CACHE_EVENT_PTR(PM_DTLB_MISS),
|
||||
CACHE_EVENT_PTR(PM_ITLB_MISS),
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct attribute_group power12_pmu_events_group = {
|
||||
.name = "events",
|
||||
.attrs = power12_events_attr,
|
||||
};
|
||||
|
||||
PMU_FORMAT_ATTR(event, "config:0-59");
|
||||
PMU_FORMAT_ATTR(pmcxsel, "config:0-7");
|
||||
PMU_FORMAT_ATTR(mark, "config:8");
|
||||
PMU_FORMAT_ATTR(combine, "config:10-11");
|
||||
PMU_FORMAT_ATTR(unit, "config:12-15");
|
||||
PMU_FORMAT_ATTR(pmc, "config:16-19");
|
||||
PMU_FORMAT_ATTR(cache_sel, "config:20-21");
|
||||
PMU_FORMAT_ATTR(sdar_mode, "config:22-23");
|
||||
PMU_FORMAT_ATTR(sample_mode, "config:24-28");
|
||||
PMU_FORMAT_ATTR(thresh_sel, "config:29-31");
|
||||
PMU_FORMAT_ATTR(thresh_stop, "config:32-35");
|
||||
PMU_FORMAT_ATTR(thresh_start, "config:36-39");
|
||||
PMU_FORMAT_ATTR(l2l3_sel, "config:40-44");
|
||||
PMU_FORMAT_ATTR(src_sel, "config:45-46");
|
||||
PMU_FORMAT_ATTR(invert_bit, "config:47");
|
||||
PMU_FORMAT_ATTR(src_mask, "config:48-53");
|
||||
PMU_FORMAT_ATTR(src_match, "config:54-59");
|
||||
PMU_FORMAT_ATTR(radix_scope, "config:9");
|
||||
PMU_FORMAT_ATTR(thresh_cmp, "config1:0-17");
|
||||
|
||||
static struct attribute *power12_pmu_format_attr[] = {
|
||||
&format_attr_event.attr,
|
||||
&format_attr_pmcxsel.attr,
|
||||
&format_attr_mark.attr,
|
||||
&format_attr_combine.attr,
|
||||
&format_attr_unit.attr,
|
||||
&format_attr_pmc.attr,
|
||||
&format_attr_cache_sel.attr,
|
||||
&format_attr_sdar_mode.attr,
|
||||
&format_attr_sample_mode.attr,
|
||||
&format_attr_thresh_sel.attr,
|
||||
&format_attr_thresh_stop.attr,
|
||||
&format_attr_thresh_start.attr,
|
||||
&format_attr_l2l3_sel.attr,
|
||||
&format_attr_src_sel.attr,
|
||||
&format_attr_invert_bit.attr,
|
||||
&format_attr_src_mask.attr,
|
||||
&format_attr_src_match.attr,
|
||||
&format_attr_radix_scope.attr,
|
||||
&format_attr_thresh_cmp.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group power12_pmu_format_group = {
|
||||
.name = "format",
|
||||
.attrs = power12_pmu_format_attr,
|
||||
};
|
||||
|
||||
static const struct attribute_group *power12_pmu_attr_groups[] = {
|
||||
&power12_pmu_format_group,
|
||||
&power12_pmu_events_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static int power12_generic_events[] = {
|
||||
[PERF_COUNT_HW_CPU_CYCLES] = PM_CYC,
|
||||
[PERF_COUNT_HW_INSTRUCTIONS] = PM_INST_CMPL,
|
||||
[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = PM_BR_FIN,
|
||||
[PERF_COUNT_HW_BRANCH_MISSES] = PM_MPRED_BR_FIN,
|
||||
[PERF_COUNT_HW_CACHE_REFERENCES] = PM_LD_REF_L1,
|
||||
[PERF_COUNT_HW_CACHE_MISSES] = PM_LD_DEMAND_MISS_L1_FIN,
|
||||
};
|
||||
|
||||
static u64 power12_bhrb_filter_map(u64 branch_sample_type)
|
||||
{
|
||||
u64 pmu_bhrb_filter = 0;
|
||||
|
||||
/* BHRB and regular PMU events share the same privilege state
|
||||
* filter configuration. BHRB is always recorded along with a
|
||||
* regular PMU event. As the privilege state filter is handled
|
||||
* in the basic PMC configuration of the accompanying regular
|
||||
* PMU event, we ignore any separate BHRB specific request.
|
||||
*/
|
||||
|
||||
/* No branch filter requested */
|
||||
if (branch_sample_type & PERF_SAMPLE_BRANCH_ANY)
|
||||
return pmu_bhrb_filter;
|
||||
|
||||
/* Invalid branch filter options - HW does not support */
|
||||
if (branch_sample_type & PERF_SAMPLE_BRANCH_ANY_RETURN)
|
||||
return -1;
|
||||
|
||||
if (branch_sample_type & PERF_SAMPLE_BRANCH_IND_CALL) {
|
||||
pmu_bhrb_filter |= POWER12_MMCRA_IFM2;
|
||||
return pmu_bhrb_filter;
|
||||
}
|
||||
|
||||
if (branch_sample_type & PERF_SAMPLE_BRANCH_COND) {
|
||||
pmu_bhrb_filter |= POWER12_MMCRA_IFM3;
|
||||
return pmu_bhrb_filter;
|
||||
}
|
||||
|
||||
if (branch_sample_type & PERF_SAMPLE_BRANCH_CALL)
|
||||
return -1;
|
||||
|
||||
if (branch_sample_type & PERF_SAMPLE_BRANCH_ANY_CALL) {
|
||||
pmu_bhrb_filter |= POWER12_MMCRA_IFM1;
|
||||
return pmu_bhrb_filter;
|
||||
}
|
||||
|
||||
/* Every thing else is unsupported */
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void power12_config_bhrb(u64 pmu_bhrb_filter)
|
||||
{
|
||||
pmu_bhrb_filter &= POWER12_MMCRA_BHRB_MASK;
|
||||
|
||||
/* Enable BHRB filter in PMU */
|
||||
mtspr(SPRN_MMCRA, (mfspr(SPRN_MMCRA) | pmu_bhrb_filter));
|
||||
}
|
||||
|
||||
#define C(x) PERF_COUNT_HW_CACHE_##x
|
||||
|
||||
/*
|
||||
* Table of generalized cache-related events.
|
||||
* 0 means not supported, -1 means nonsensical, other values
|
||||
* are event codes.
|
||||
*/
|
||||
static u64 power12_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
|
||||
[C(L1D)] = {
|
||||
[C(OP_READ)] = {
|
||||
[C(RESULT_ACCESS)] = PM_LD_REF_L1,
|
||||
[C(RESULT_MISS)] = PM_LD_MISS_L1,
|
||||
},
|
||||
[C(OP_WRITE)] = {
|
||||
[C(RESULT_ACCESS)] = 0,
|
||||
[C(RESULT_MISS)] = PM_ST_MISS_L1,
|
||||
},
|
||||
[C(OP_PREFETCH)] = {
|
||||
[C(RESULT_ACCESS)] = PM_LD_PREFETCH_CACHE_LINE_MISS,
|
||||
[C(RESULT_MISS)] = 0,
|
||||
},
|
||||
},
|
||||
[C(L1I)] = {
|
||||
[C(OP_READ)] = {
|
||||
[C(RESULT_ACCESS)] = PM_INST_FROM_L1,
|
||||
[C(RESULT_MISS)] = PM_L1_ICACHE_MISS,
|
||||
},
|
||||
[C(OP_WRITE)] = {
|
||||
[C(RESULT_ACCESS)] = PM_INST_FROM_L1MISS,
|
||||
[C(RESULT_MISS)] = -1,
|
||||
},
|
||||
[C(OP_PREFETCH)] = {
|
||||
[C(RESULT_ACCESS)] = PM_IC_PREF_REQ,
|
||||
[C(RESULT_MISS)] = 0,
|
||||
},
|
||||
},
|
||||
[C(LL)] = {
|
||||
[C(OP_READ)] = {
|
||||
[C(RESULT_ACCESS)] = PM_DATA_FROM_L3,
|
||||
[C(RESULT_MISS)] = PM_DATA_FROM_L3MISS,
|
||||
},
|
||||
[C(OP_WRITE)] = {
|
||||
[C(RESULT_ACCESS)] = PM_L2_ST,
|
||||
[C(RESULT_MISS)] = PM_L2_ST_MISS,
|
||||
},
|
||||
[C(OP_PREFETCH)] = {
|
||||
[C(RESULT_ACCESS)] = PM_L3_PF_MISS_L3,
|
||||
[C(RESULT_MISS)] = 0,
|
||||
},
|
||||
},
|
||||
[C(DTLB)] = {
|
||||
[C(OP_READ)] = {
|
||||
[C(RESULT_ACCESS)] = 0,
|
||||
[C(RESULT_MISS)] = PM_DTLB_MISS,
|
||||
},
|
||||
[C(OP_WRITE)] = {
|
||||
[C(RESULT_ACCESS)] = -1,
|
||||
[C(RESULT_MISS)] = -1,
|
||||
},
|
||||
[C(OP_PREFETCH)] = {
|
||||
[C(RESULT_ACCESS)] = -1,
|
||||
[C(RESULT_MISS)] = -1,
|
||||
},
|
||||
},
|
||||
[C(ITLB)] = {
|
||||
[C(OP_READ)] = {
|
||||
[C(RESULT_ACCESS)] = 0,
|
||||
[C(RESULT_MISS)] = PM_ITLB_MISS,
|
||||
},
|
||||
[C(OP_WRITE)] = {
|
||||
[C(RESULT_ACCESS)] = -1,
|
||||
[C(RESULT_MISS)] = -1,
|
||||
},
|
||||
[C(OP_PREFETCH)] = {
|
||||
[C(RESULT_ACCESS)] = -1,
|
||||
[C(RESULT_MISS)] = -1,
|
||||
},
|
||||
},
|
||||
[C(BPU)] = {
|
||||
[C(OP_READ)] = {
|
||||
[C(RESULT_ACCESS)] = PM_BR_CMPL,
|
||||
[C(RESULT_MISS)] = PM_BR_MPRED_CMPL,
|
||||
},
|
||||
[C(OP_WRITE)] = {
|
||||
[C(RESULT_ACCESS)] = -1,
|
||||
[C(RESULT_MISS)] = -1,
|
||||
},
|
||||
[C(OP_PREFETCH)] = {
|
||||
[C(RESULT_ACCESS)] = -1,
|
||||
[C(RESULT_MISS)] = -1,
|
||||
},
|
||||
},
|
||||
[C(NODE)] = {
|
||||
[C(OP_READ)] = {
|
||||
[C(RESULT_ACCESS)] = -1,
|
||||
[C(RESULT_MISS)] = -1,
|
||||
},
|
||||
[C(OP_WRITE)] = {
|
||||
[C(RESULT_ACCESS)] = -1,
|
||||
[C(RESULT_MISS)] = -1,
|
||||
},
|
||||
[C(OP_PREFETCH)] = {
|
||||
[C(RESULT_ACCESS)] = -1,
|
||||
[C(RESULT_MISS)] = -1,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
#undef C
|
||||
|
||||
/*
|
||||
* Set the MMCR0[CC56RUN] bit to enable counting for
|
||||
* PMC5 and PMC6 regardless of the state of CTRL[RUN],
|
||||
* so that we can use counters 5 and 6 as PM_INST_CMPL and
|
||||
* PM_CYC.
|
||||
*/
|
||||
static int power12_compute_mmcr(u64 event[], int n_ev,
|
||||
unsigned int hwc[], struct mmcr_regs *mmcr,
|
||||
struct perf_event *pevents[], u32 flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = isa207_compute_mmcr(event, n_ev, hwc, mmcr, pevents, flags);
|
||||
if (!ret)
|
||||
mmcr->mmcr0 |= MMCR0_C56RUN;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct power_pmu power12_pmu = {
|
||||
.name = "Power12",
|
||||
.n_counter = MAX_PMU_COUNTERS,
|
||||
.add_fields = ISA207_ADD_FIELDS,
|
||||
.test_adder = ISA207_TEST_ADDER,
|
||||
.group_constraint_mask = CNST_CACHE_PMC4_MASK,
|
||||
.group_constraint_val = CNST_CACHE_PMC4_VAL,
|
||||
.compute_mmcr = power12_compute_mmcr,
|
||||
.config_bhrb = power12_config_bhrb,
|
||||
.bhrb_filter_map = power12_bhrb_filter_map,
|
||||
.get_constraint = isa207_get_constraint,
|
||||
.get_alternatives = power12_get_alternatives,
|
||||
.get_mem_data_src = isa207_get_mem_data_src,
|
||||
.get_mem_weight = isa207_get_mem_weight,
|
||||
.disable_pmc = isa207_disable_pmc,
|
||||
.flags = PPMU_HAS_SIER | PPMU_ARCH_207S |
|
||||
PPMU_ARCH_31 | PPMU_HAS_ATTR_CONFIG1 |
|
||||
PPMU_P10,
|
||||
.n_generic = ARRAY_SIZE(power12_generic_events),
|
||||
.generic_events = power12_generic_events,
|
||||
.cache_events = &power12_cache_events,
|
||||
.attr_groups = power12_pmu_attr_groups,
|
||||
.bhrb_nr = 32,
|
||||
.capabilities = PERF_PMU_CAP_EXTENDED_REGS,
|
||||
.check_attr_config = power12_check_attr_config,
|
||||
};
|
||||
|
||||
int __init init_power12_pmu(void)
|
||||
{
|
||||
unsigned int pvr;
|
||||
int rc;
|
||||
|
||||
pvr = mfspr(SPRN_PVR);
|
||||
if (PVR_VER(pvr) != PVR_POWER12)
|
||||
return -ENODEV;
|
||||
|
||||
/* Set the PERF_REG_EXTENDED_MASK here */
|
||||
PERF_REG_EXTENDED_MASK = PERF_REG_PMU_MASK_31;
|
||||
|
||||
rc = register_power_pmu(&power12_pmu);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* Tell userspace that EBB is supported */
|
||||
cur_cpu_spec->cpu_user_features2 |= PPC_FEATURE2_EBB;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -227,13 +227,6 @@ config PPC44x_SIMPLE
|
|||
help
|
||||
This option enables the simple PowerPC 44x platform support.
|
||||
|
||||
config PPC4xx_GPIO
|
||||
bool "PPC4xx GPIO support"
|
||||
depends on 44x
|
||||
select GPIOLIB
|
||||
help
|
||||
Enable gpiolib support for ppc440 based boards
|
||||
|
||||
# 44x specific CPU modules, selected based on the board above.
|
||||
config 440EP
|
||||
bool
|
||||
|
|
|
|||
|
|
@ -15,4 +15,4 @@ obj-$(CONFIG_FSP2) += fsp2.o
|
|||
obj-$(CONFIG_PCI) += pci.o
|
||||
obj-$(CONFIG_PPC4xx_HSTA_MSI) += hsta_msi.o
|
||||
obj-$(CONFIG_PPC4xx_CPM) += cpm.o
|
||||
obj-$(CONFIG_PPC4xx_GPIO) += gpio.o
|
||||
|
||||
|
|
|
|||
|
|
@ -1,210 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* PPC4xx gpio driver
|
||||
*
|
||||
* Copyright (c) 2008 Harris Corporation
|
||||
* Copyright (c) 2008 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
|
||||
* Copyright (c) MontaVista Software, Inc. 2008.
|
||||
*
|
||||
* Author: Steve Falco <sfalco@harris.com>
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#define GPIO_MASK(gpio) (0x80000000 >> (gpio))
|
||||
#define GPIO_MASK2(gpio) (0xc0000000 >> ((gpio) * 2))
|
||||
|
||||
/* Physical GPIO register layout */
|
||||
struct ppc4xx_gpio {
|
||||
__be32 or;
|
||||
__be32 tcr;
|
||||
__be32 osrl;
|
||||
__be32 osrh;
|
||||
__be32 tsrl;
|
||||
__be32 tsrh;
|
||||
__be32 odr;
|
||||
__be32 ir;
|
||||
__be32 rr1;
|
||||
__be32 rr2;
|
||||
__be32 rr3;
|
||||
__be32 reserved1;
|
||||
__be32 isr1l;
|
||||
__be32 isr1h;
|
||||
__be32 isr2l;
|
||||
__be32 isr2h;
|
||||
__be32 isr3l;
|
||||
__be32 isr3h;
|
||||
};
|
||||
|
||||
struct ppc4xx_gpio_chip {
|
||||
struct gpio_chip gc;
|
||||
void __iomem *regs;
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
/*
|
||||
* GPIO LIB API implementation for GPIOs
|
||||
*
|
||||
* There are a maximum of 32 gpios in each gpio controller.
|
||||
*/
|
||||
|
||||
static int ppc4xx_gpio_get(struct gpio_chip *gc, unsigned int gpio)
|
||||
{
|
||||
struct ppc4xx_gpio_chip *chip = gpiochip_get_data(gc);
|
||||
struct ppc4xx_gpio __iomem *regs = chip->regs;
|
||||
|
||||
return !!(in_be32(®s->ir) & GPIO_MASK(gpio));
|
||||
}
|
||||
|
||||
static inline void
|
||||
__ppc4xx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
|
||||
{
|
||||
struct ppc4xx_gpio_chip *chip = gpiochip_get_data(gc);
|
||||
struct ppc4xx_gpio __iomem *regs = chip->regs;
|
||||
|
||||
if (val)
|
||||
setbits32(®s->or, GPIO_MASK(gpio));
|
||||
else
|
||||
clrbits32(®s->or, GPIO_MASK(gpio));
|
||||
}
|
||||
|
||||
static int ppc4xx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
|
||||
{
|
||||
struct ppc4xx_gpio_chip *chip = gpiochip_get_data(gc);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&chip->lock, flags);
|
||||
|
||||
__ppc4xx_gpio_set(gc, gpio, val);
|
||||
|
||||
spin_unlock_irqrestore(&chip->lock, flags);
|
||||
|
||||
pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ppc4xx_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
|
||||
{
|
||||
struct ppc4xx_gpio_chip *chip = gpiochip_get_data(gc);
|
||||
struct ppc4xx_gpio __iomem *regs = chip->regs;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&chip->lock, flags);
|
||||
|
||||
/* Disable open-drain function */
|
||||
clrbits32(®s->odr, GPIO_MASK(gpio));
|
||||
|
||||
/* Float the pin */
|
||||
clrbits32(®s->tcr, GPIO_MASK(gpio));
|
||||
|
||||
/* Bits 0-15 use TSRL/OSRL, bits 16-31 use TSRH/OSRH */
|
||||
if (gpio < 16) {
|
||||
clrbits32(®s->osrl, GPIO_MASK2(gpio));
|
||||
clrbits32(®s->tsrl, GPIO_MASK2(gpio));
|
||||
} else {
|
||||
clrbits32(®s->osrh, GPIO_MASK2(gpio));
|
||||
clrbits32(®s->tsrh, GPIO_MASK2(gpio));
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&chip->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ppc4xx_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
|
||||
{
|
||||
struct ppc4xx_gpio_chip *chip = gpiochip_get_data(gc);
|
||||
struct ppc4xx_gpio __iomem *regs = chip->regs;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&chip->lock, flags);
|
||||
|
||||
/* First set initial value */
|
||||
__ppc4xx_gpio_set(gc, gpio, val);
|
||||
|
||||
/* Disable open-drain function */
|
||||
clrbits32(®s->odr, GPIO_MASK(gpio));
|
||||
|
||||
/* Drive the pin */
|
||||
setbits32(®s->tcr, GPIO_MASK(gpio));
|
||||
|
||||
/* Bits 0-15 use TSRL, bits 16-31 use TSRH */
|
||||
if (gpio < 16) {
|
||||
clrbits32(®s->osrl, GPIO_MASK2(gpio));
|
||||
clrbits32(®s->tsrl, GPIO_MASK2(gpio));
|
||||
} else {
|
||||
clrbits32(®s->osrh, GPIO_MASK2(gpio));
|
||||
clrbits32(®s->tsrh, GPIO_MASK2(gpio));
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&chip->lock, flags);
|
||||
|
||||
pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ppc4xx_gpio_probe(struct platform_device *ofdev)
|
||||
{
|
||||
struct device *dev = &ofdev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct ppc4xx_gpio_chip *chip;
|
||||
struct gpio_chip *gc;
|
||||
|
||||
chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
|
||||
if (!chip)
|
||||
return -ENOMEM;
|
||||
|
||||
spin_lock_init(&chip->lock);
|
||||
|
||||
gc = &chip->gc;
|
||||
|
||||
gc->base = -1;
|
||||
gc->ngpio = 32;
|
||||
gc->direction_input = ppc4xx_gpio_dir_in;
|
||||
gc->direction_output = ppc4xx_gpio_dir_out;
|
||||
gc->get = ppc4xx_gpio_get;
|
||||
gc->set = ppc4xx_gpio_set;
|
||||
|
||||
gc->label = devm_kasprintf(dev, GFP_KERNEL, "%pOF", np);
|
||||
if (!gc->label)
|
||||
return -ENOMEM;
|
||||
|
||||
chip->regs = devm_of_iomap(dev, np, 0, NULL);
|
||||
if (IS_ERR(chip->regs))
|
||||
return PTR_ERR(chip->regs);
|
||||
|
||||
return devm_gpiochip_add_data(dev, gc, chip);
|
||||
}
|
||||
|
||||
static const struct of_device_id ppc4xx_gpio_match[] = {
|
||||
{
|
||||
.compatible = "ibm,ppc4xx-gpio",
|
||||
},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ppc4xx_gpio_match);
|
||||
|
||||
static struct platform_driver ppc4xx_gpio_driver = {
|
||||
.probe = ppc4xx_gpio_probe,
|
||||
.driver = {
|
||||
.name = "ppc4xx-gpio",
|
||||
.of_match_table = ppc4xx_gpio_match,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init ppc4xx_gpio_init(void)
|
||||
{
|
||||
return platform_driver_register(&ppc4xx_gpio_driver);
|
||||
}
|
||||
arch_initcall(ppc4xx_gpio_init);
|
||||
|
|
@ -284,9 +284,7 @@ static void __init bootx_scan_dt_build_struct(unsigned long base,
|
|||
dt_push_token(OF_DT_BEGIN_NODE, mem_end);
|
||||
|
||||
/* get the node's full name */
|
||||
namep = np->full_name ? (char *)(base + np->full_name) : NULL;
|
||||
if (namep == NULL)
|
||||
namep = "";
|
||||
namep = np->full_name ? (char *)(base + np->full_name) : "";
|
||||
l = strlen(namep);
|
||||
|
||||
DBG("* struct: %s\n", namep);
|
||||
|
|
|
|||
|
|
@ -312,7 +312,7 @@ static void __noreturn pnv_restart(char *cmd)
|
|||
pnv_prepare_going_down();
|
||||
|
||||
do {
|
||||
if (!cmd || !strlen(cmd))
|
||||
if (!cmd || *cmd == '\0')
|
||||
rc = opal_cec_reboot();
|
||||
else if (strcmp(cmd, "full") == 0)
|
||||
rc = opal_cec_reboot2(OPAL_REBOOT_FULL_IPL, NULL);
|
||||
|
|
|
|||
|
|
@ -332,10 +332,12 @@ static void pnv_cause_ipi(int cpu)
|
|||
|
||||
static void __init pnv_smp_probe(void)
|
||||
{
|
||||
if (xive_enabled())
|
||||
xive_smp_probe();
|
||||
else
|
||||
if (xive_enabled()) {
|
||||
if (xive_smp_probe() < 0)
|
||||
return;
|
||||
} else {
|
||||
xics_smp_probe();
|
||||
}
|
||||
|
||||
if (cpu_has_feature(CPU_FTR_DBELL)) {
|
||||
ic_cause_ipi = smp_ops->cause_ipi;
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include <linux/export.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/processor.h>
|
||||
|
||||
#include <asm/spu.h>
|
||||
#include <asm/spu_priv1.h>
|
||||
|
|
@ -361,12 +362,9 @@ static int __init ps3_create_spu(struct spu *spu, void *data)
|
|||
if (result)
|
||||
goto fail_enable;
|
||||
|
||||
/* Make sure the spu is in SPE_EX_STATE_EXECUTED. */
|
||||
|
||||
/* need something better here!!! */
|
||||
while (in_be64(&spu_pdata(spu)->shadow->spe_execution_status)
|
||||
!= SPE_EX_STATE_EXECUTED)
|
||||
(void)0;
|
||||
while (in_be64(&spu_pdata(spu)->shadow->spe_execution_status) !=
|
||||
SPE_EX_STATE_EXECUTED)
|
||||
cpu_relax();
|
||||
|
||||
return result;
|
||||
|
||||
|
|
|
|||
|
|
@ -812,18 +812,11 @@ static struct device_node *pci_dma_find(struct device_node *dn,
|
|||
|
||||
/* parse DMA window property. During normal system boot, only default
|
||||
* DMA window is passed in OF. But, for kdump, a dedicated adapter might
|
||||
* have both default and DDW in FDT. In this scenario, DDW takes precedence
|
||||
* over default window.
|
||||
* have both default and DDW in FDT. In this scenario, default window
|
||||
* takes precedence over DDW. For a dedicated adapter, default window will
|
||||
* potentially have more unused TCEs.
|
||||
*/
|
||||
if (ddw_win) {
|
||||
struct dynamic_dma_window_prop *p;
|
||||
|
||||
p = (struct dynamic_dma_window_prop *)ddw_prop;
|
||||
prop->liobn = p->liobn;
|
||||
prop->dma_base = p->dma_base;
|
||||
prop->tce_shift = p->tce_shift;
|
||||
prop->window_shift = p->window_shift;
|
||||
} else if (default_win) {
|
||||
if (default_win) {
|
||||
unsigned long offset, size, liobn;
|
||||
|
||||
of_parse_dma_window(rdn, default_prop, &liobn, &offset, &size);
|
||||
|
|
@ -832,6 +825,14 @@ static struct device_node *pci_dma_find(struct device_node *dn,
|
|||
prop->dma_base = cpu_to_be64(offset);
|
||||
prop->tce_shift = cpu_to_be32(IOMMU_PAGE_SHIFT_4K);
|
||||
prop->window_shift = cpu_to_be32(order_base_2(size));
|
||||
} else {
|
||||
struct dynamic_dma_window_prop *p;
|
||||
|
||||
p = (struct dynamic_dma_window_prop *)ddw_prop;
|
||||
prop->liobn = p->liobn;
|
||||
prop->dma_base = p->dma_base;
|
||||
prop->tce_shift = p->tce_shift;
|
||||
prop->window_shift = p->window_shift;
|
||||
}
|
||||
|
||||
return rdn;
|
||||
|
|
|
|||
|
|
@ -323,12 +323,8 @@ static int __init papr_init(void)
|
|||
}
|
||||
|
||||
for (idx = 0; idx < num_attrs; idx++) {
|
||||
bool show_val_desc = true;
|
||||
|
||||
/* Do not add the value desc attr if it does not exist */
|
||||
if (strnlen(esi_attrs[idx].value_desc,
|
||||
sizeof(esi_attrs[idx].value_desc)) == 0)
|
||||
show_val_desc = false;
|
||||
bool show_val_desc = *esi_attrs[idx].value_desc != '\0';
|
||||
|
||||
if (add_attr_group(be64_to_cpu(esi_attrs[idx].id),
|
||||
&papr_groups[idx],
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/overflow.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/irq_work.h>
|
||||
|
|
@ -440,6 +441,8 @@ static __be64 *fwnmi_get_savep(struct pt_regs *regs)
|
|||
static struct rtas_error_log *fwnmi_get_errinfo(struct pt_regs *regs)
|
||||
{
|
||||
struct rtas_error_log *h;
|
||||
u32 extended_log_length;
|
||||
size_t len;
|
||||
__be64 *savep;
|
||||
|
||||
savep = fwnmi_get_savep(regs);
|
||||
|
|
@ -449,17 +452,12 @@ static struct rtas_error_log *fwnmi_get_errinfo(struct pt_regs *regs)
|
|||
regs->gpr[3] = be64_to_cpu(savep[0]); /* restore original r3 */
|
||||
|
||||
h = (struct rtas_error_log *)&savep[1];
|
||||
extended_log_length = rtas_error_extended(h) ? rtas_error_extended_log_length(h) : 0;
|
||||
len = struct_size(h, buffer, extended_log_length);
|
||||
len = min(len, RTAS_ERROR_LOG_MAX);
|
||||
/* Use the per cpu buffer from paca to store rtas error log */
|
||||
memset(local_paca->mce_data_buf, 0, RTAS_ERROR_LOG_MAX);
|
||||
if (!rtas_error_extended(h)) {
|
||||
memcpy(local_paca->mce_data_buf, h, sizeof(__u64));
|
||||
} else {
|
||||
int len, error_log_length;
|
||||
|
||||
error_log_length = 8 + rtas_error_extended_log_length(h);
|
||||
len = min_t(int, error_log_length, RTAS_ERROR_LOG_MAX);
|
||||
memcpy(local_paca->mce_data_buf, h, len);
|
||||
}
|
||||
memcpy(local_paca->mce_data_buf, h, len);
|
||||
|
||||
return (struct rtas_error_log *)local_paca->mce_data_buf;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -307,7 +307,7 @@ static int do_remove_property(char *buf, size_t bufsize)
|
|||
if (tmp)
|
||||
*tmp = '\0';
|
||||
|
||||
if (strlen(buf) == 0)
|
||||
if (*buf == '\0')
|
||||
return -EINVAL;
|
||||
|
||||
return of_remove_property(np, of_find_property(np, buf, NULL));
|
||||
|
|
@ -330,7 +330,7 @@ static int do_update_property(char *buf, size_t bufsize)
|
|||
if (!next_prop)
|
||||
return -EINVAL;
|
||||
|
||||
if (!strlen(name))
|
||||
if (*name == '\0')
|
||||
return -ENODEV;
|
||||
|
||||
newprop = new_property(name, length, value, NULL);
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@
|
|||
#include <asm/dtl.h>
|
||||
#include <asm/hvconsole.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/papr-watchdog.h>
|
||||
|
||||
#include "pseries.h"
|
||||
|
||||
|
|
@ -185,14 +186,37 @@ static void __init fwnmi_init(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
static void pseries_crash_stop_watchdogs(void)
|
||||
{
|
||||
long rc;
|
||||
|
||||
rc = plpar_hcall_norets_notrace(H_WATCHDOG, PSERIES_WDTF_OP_STOP,
|
||||
PSERIES_WDT_NUM_ALL);
|
||||
if (rc != H_SUCCESS && rc != H_NOOP)
|
||||
pr_warn("Could not stop watchdogs before kdump rc=%ld\n", rc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Affix a device for the first timer to the platform bus if
|
||||
* we have firmware support for the H_WATCHDOG hypercall.
|
||||
*/
|
||||
static __init int pseries_wdt_init(void)
|
||||
{
|
||||
if (firmware_has_feature(FW_FEATURE_WATCHDOG))
|
||||
platform_device_register_simple("pseries-wdt", 0, NULL, 0);
|
||||
struct platform_device *pdev;
|
||||
|
||||
if (!firmware_has_feature(FW_FEATURE_WATCHDOG))
|
||||
return 0;
|
||||
|
||||
pdev = platform_device_register_simple("pseries-wdt", 0, NULL, 0);
|
||||
|
||||
if (IS_ERR(pdev)) {
|
||||
pr_err("Failed to register pseries-wdt platform device\n");
|
||||
return PTR_ERR(pdev);
|
||||
}
|
||||
|
||||
if (crash_shutdown_register(pseries_crash_stop_watchdogs))
|
||||
pr_warn("Could not register watchdog crash shutdown handler\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
machine_subsys_initcall(pseries, pseries_wdt_init);
|
||||
|
|
|
|||
|
|
@ -199,10 +199,12 @@ static int pseries_cause_nmi_ipi(int cpu)
|
|||
|
||||
static __init void pSeries_smp_probe(void)
|
||||
{
|
||||
if (xive_enabled())
|
||||
xive_smp_probe();
|
||||
else
|
||||
if (xive_enabled()) {
|
||||
if (xive_smp_probe() < 0)
|
||||
return;
|
||||
} else {
|
||||
xics_smp_probe();
|
||||
}
|
||||
|
||||
/* No doorbell facility, must use the interrupt controller for IPIs */
|
||||
if (!cpu_has_feature(CPU_FTR_DBELL))
|
||||
|
|
|
|||
|
|
@ -181,6 +181,18 @@ static int cpm2_gpio32_dir_in(struct gpio_chip *gc, unsigned int gpio)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cpm2_gpio32_get_direction(struct gpio_chip *gc, unsigned int gpio)
|
||||
{
|
||||
struct cpm2_gpio32_chip *cpm2_gc = gpiochip_get_data(gc);
|
||||
struct cpm2_ioports __iomem *iop = cpm2_gc->regs;
|
||||
u32 pin_mask = 1 << (31 - gpio);
|
||||
|
||||
if (in_be32(&iop->dir) & pin_mask)
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
int cpm2_gpiochip_add32(struct device *dev)
|
||||
{
|
||||
struct device_node *np = dev->of_node;
|
||||
|
|
@ -199,6 +211,7 @@ int cpm2_gpiochip_add32(struct device *dev)
|
|||
gc->ngpio = 32;
|
||||
gc->direction_input = cpm2_gpio32_dir_in;
|
||||
gc->direction_output = cpm2_gpio32_dir_out;
|
||||
gc->get_direction = cpm2_gpio32_get_direction;
|
||||
gc->get = cpm2_gpio32_get;
|
||||
gc->set = cpm2_gpio32_set;
|
||||
gc->parent = dev;
|
||||
|
|
|
|||
|
|
@ -74,6 +74,8 @@ static struct xive_ipi_desc {
|
|||
*/
|
||||
static unsigned int xive_ipi_cpu_to_irq(unsigned int cpu)
|
||||
{
|
||||
if (!xive_ipis)
|
||||
return XIVE_BAD_IRQ;
|
||||
return xive_ipis[early_cpu_to_node(cpu)].irq;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1132,8 +1134,7 @@ static int __init xive_init_ipis(void)
|
|||
if (!ipi_domain)
|
||||
goto out_free_fwnode;
|
||||
|
||||
xive_ipis = kzalloc_objs(*xive_ipis, nr_node_ids,
|
||||
GFP_KERNEL | __GFP_NOFAIL);
|
||||
xive_ipis = kzalloc_objs(*xive_ipis, nr_node_ids, GFP_KERNEL);
|
||||
if (!xive_ipis)
|
||||
goto out_free_domain;
|
||||
|
||||
|
|
@ -1158,6 +1159,7 @@ static int __init xive_init_ipis(void)
|
|||
|
||||
out_free_xive_ipis:
|
||||
kfree(xive_ipis);
|
||||
xive_ipis = NULL;
|
||||
out_free_domain:
|
||||
irq_domain_remove(ipi_domain);
|
||||
out_free_fwnode:
|
||||
|
|
@ -1190,6 +1192,9 @@ static int xive_setup_cpu_ipi(unsigned int cpu)
|
|||
|
||||
pr_debug("Setting up IPI for CPU %d\n", cpu);
|
||||
|
||||
if (xive_ipi_irq == XIVE_BAD_IRQ)
|
||||
return -EIO;
|
||||
|
||||
xc = per_cpu(xive_cpu, cpu);
|
||||
|
||||
/* Check if we are already setup */
|
||||
|
|
@ -1234,6 +1239,9 @@ noinstr static void xive_cleanup_cpu_ipi(unsigned int cpu, struct xive_cpu *xc)
|
|||
|
||||
/* Disable the IPI and free the IRQ data */
|
||||
|
||||
if (xive_ipi_irq == XIVE_BAD_IRQ)
|
||||
return;
|
||||
|
||||
/* Already cleaned up ? */
|
||||
if (xc->hw_ipi == XIVE_BAD_IRQ)
|
||||
return;
|
||||
|
|
@ -1257,15 +1265,23 @@ noinstr static void xive_cleanup_cpu_ipi(unsigned int cpu, struct xive_cpu *xc)
|
|||
xive_ops->put_ipi(cpu, xc);
|
||||
}
|
||||
|
||||
void __init xive_smp_probe(void)
|
||||
int __init xive_smp_probe(void)
|
||||
{
|
||||
smp_ops->cause_ipi = xive_cause_ipi;
|
||||
int ret;
|
||||
|
||||
/* Register the IPI */
|
||||
xive_init_ipis();
|
||||
ret = xive_init_ipis();
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Allocate and setup IPI for the boot CPU */
|
||||
xive_setup_cpu_ipi(smp_processor_id());
|
||||
ret = xive_setup_cpu_ipi(smp_processor_id());
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
smp_ops->cause_ipi = xive_cause_ipi;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SMP */
|
||||
|
|
|
|||
|
|
@ -593,6 +593,13 @@ config GPIO_POLARFIRE_SOC
|
|||
help
|
||||
Say yes here to support the GPIO controllers on Microchip FPGAs.
|
||||
|
||||
config GPIO_PPC44X
|
||||
tristate "PPC44x GPIO support"
|
||||
depends on 44x || COMPILE_TEST
|
||||
select GPIO_GENERIC
|
||||
help
|
||||
Enable gpiolib support for ppc440 based boards.
|
||||
|
||||
config GPIO_PXA
|
||||
bool "PXA GPIO support"
|
||||
depends on ARCH_PXA || ARCH_MMP || COMPILE_TEST
|
||||
|
|
|
|||
|
|
@ -147,6 +147,7 @@ obj-$(CONFIG_GPIO_PCIE_IDIO_24) += gpio-pcie-idio-24.o
|
|||
obj-$(CONFIG_GPIO_PCI_IDIO_16) += gpio-pci-idio-16.o
|
||||
obj-$(CONFIG_GPIO_PISOSR) += gpio-pisosr.o
|
||||
obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o
|
||||
obj-$(CONFIG_GPIO_PPC44X) += gpio-ppc44x.o
|
||||
obj-$(CONFIG_GPIO_PMIC_EIC_SPRD) += gpio-pmic-eic-sprd.o
|
||||
obj-$(CONFIG_GPIO_POLARFIRE_SOC) += gpio-mpfs.o
|
||||
obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o
|
||||
|
|
|
|||
208
drivers/gpio/gpio-ppc44x.c
Normal file
208
drivers/gpio/gpio-ppc44x.c
Normal file
|
|
@ -0,0 +1,208 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* PPC44x gpio driver
|
||||
*
|
||||
* Copyright (c) 2008 Harris Corporation
|
||||
* Copyright (c) 2008 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
|
||||
* Copyright (c) MontaVista Software, Inc. 2008.
|
||||
*
|
||||
* Author: Steve Falco <sfalco@harris.com>
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/gpio/generic.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#define GPIO_MASK(gpio) (0x80000000 >> (gpio))
|
||||
#define GPIO_MASK2(gpio) (0xc0000000 >> (((gpio) % 16) * 2))
|
||||
|
||||
/* Physical GPIO register layout */
|
||||
struct ppc44x_gpio {
|
||||
__be32 or;
|
||||
__be32 tcr;
|
||||
__be32 osrl;
|
||||
__be32 osrh;
|
||||
__be32 tsrl;
|
||||
__be32 tsrh;
|
||||
__be32 odr;
|
||||
__be32 ir;
|
||||
__be32 rr1;
|
||||
__be32 rr2;
|
||||
__be32 rr3;
|
||||
__be32 reserved1;
|
||||
__be32 isr1l;
|
||||
__be32 isr1h;
|
||||
__be32 isr2l;
|
||||
__be32 isr2h;
|
||||
__be32 isr3l;
|
||||
__be32 isr3h;
|
||||
};
|
||||
|
||||
struct ppc44x_gpio_chip {
|
||||
struct gpio_generic_chip chip;
|
||||
void __iomem *regs;
|
||||
};
|
||||
|
||||
static inline void ppc44x_clrbits32(void __iomem *addr, u32 mask)
|
||||
{
|
||||
u32 val = ioread32be(addr);
|
||||
|
||||
val &= ~mask;
|
||||
iowrite32be(val, addr);
|
||||
}
|
||||
|
||||
static inline void ppc44x_setbits32(void __iomem *addr, u32 mask)
|
||||
{
|
||||
u32 val = ioread32be(addr);
|
||||
|
||||
val |= mask;
|
||||
iowrite32be(val, addr);
|
||||
}
|
||||
|
||||
/*
|
||||
* GPIO LIB API implementation for GPIOs
|
||||
*
|
||||
* There are a maximum of 32 gpios in each gpio controller.
|
||||
*/
|
||||
|
||||
static inline void
|
||||
__ppc44x_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
|
||||
{
|
||||
struct ppc44x_gpio_chip *chip = gpiochip_get_data(gc);
|
||||
struct gpio_generic_chip *gen_gc = &chip->chip;
|
||||
|
||||
if (val)
|
||||
gen_gc->sdata |= GPIO_MASK(gpio);
|
||||
else
|
||||
gen_gc->sdata &= ~GPIO_MASK(gpio);
|
||||
|
||||
gpio_generic_write_reg(gen_gc, gen_gc->reg_set, gen_gc->sdata);
|
||||
}
|
||||
|
||||
static int ppc44x_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
|
||||
{
|
||||
struct ppc44x_gpio_chip *chip = gpiochip_get_data(gc);
|
||||
struct gpio_generic_chip *gen_gc = &chip->chip;
|
||||
struct ppc44x_gpio __iomem *regs = chip->regs;
|
||||
|
||||
guard(gpio_generic_lock_irqsave)(gen_gc);
|
||||
|
||||
/* Disable open-drain function */
|
||||
ppc44x_clrbits32(®s->odr, GPIO_MASK(gpio));
|
||||
|
||||
/* Float the pin */
|
||||
ppc44x_clrbits32(®s->tcr, GPIO_MASK(gpio));
|
||||
gen_gc->sdir &= ~GPIO_MASK(gpio);
|
||||
|
||||
/* Bits 0-15 use TSRL/OSRL, bits 16-31 use TSRH/OSRH */
|
||||
if (gpio < 16) {
|
||||
ppc44x_clrbits32(®s->osrl, GPIO_MASK2(gpio));
|
||||
ppc44x_clrbits32(®s->tsrl, GPIO_MASK2(gpio));
|
||||
} else {
|
||||
ppc44x_clrbits32(®s->osrh, GPIO_MASK2(gpio));
|
||||
ppc44x_clrbits32(®s->tsrh, GPIO_MASK2(gpio));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ppc44x_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
|
||||
{
|
||||
struct ppc44x_gpio_chip *chip = gpiochip_get_data(gc);
|
||||
struct gpio_generic_chip *gen_gc = &chip->chip;
|
||||
struct ppc44x_gpio __iomem *regs = chip->regs;
|
||||
|
||||
guard(gpio_generic_lock_irqsave)(gen_gc);
|
||||
|
||||
/* First set initial value */
|
||||
__ppc44x_gpio_set(gc, gpio, val);
|
||||
|
||||
/* Disable open-drain function */
|
||||
ppc44x_clrbits32(®s->odr, GPIO_MASK(gpio));
|
||||
|
||||
/* Drive the pin */
|
||||
ppc44x_setbits32(®s->tcr, GPIO_MASK(gpio));
|
||||
gen_gc->sdir |= GPIO_MASK(gpio);
|
||||
|
||||
/* Bits 0-15 use TSRL, bits 16-31 use TSRH */
|
||||
if (gpio < 16) {
|
||||
ppc44x_clrbits32(®s->osrl, GPIO_MASK2(gpio));
|
||||
ppc44x_clrbits32(®s->tsrl, GPIO_MASK2(gpio));
|
||||
} else {
|
||||
ppc44x_clrbits32(®s->osrh, GPIO_MASK2(gpio));
|
||||
ppc44x_clrbits32(®s->tsrh, GPIO_MASK2(gpio));
|
||||
}
|
||||
|
||||
pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ppc44x_gpio_probe(struct platform_device *ofdev)
|
||||
{
|
||||
struct device *dev = &ofdev->dev;
|
||||
struct ppc44x_gpio __iomem *regs;
|
||||
struct ppc44x_gpio_chip *chip;
|
||||
struct gpio_generic_chip_config config;
|
||||
struct gpio_chip *gc;
|
||||
int ret;
|
||||
|
||||
regs = devm_platform_ioremap_resource(ofdev, 0);
|
||||
if (IS_ERR(regs))
|
||||
return PTR_ERR(regs);
|
||||
|
||||
chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
|
||||
if (!chip)
|
||||
return -ENOMEM;
|
||||
|
||||
chip->regs = regs;
|
||||
|
||||
config = (struct gpio_generic_chip_config) {
|
||||
.dev = dev,
|
||||
.sz = 4,
|
||||
.dat = ®s->ir,
|
||||
.set = ®s->or,
|
||||
.dirout = ®s->tcr,
|
||||
.flags = GPIO_GENERIC_BIG_ENDIAN |
|
||||
GPIO_GENERIC_BIG_ENDIAN_BYTE_ORDER,
|
||||
};
|
||||
|
||||
ret = gpio_generic_chip_init(&chip->chip, &config);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
gc = &chip->chip.gc;
|
||||
gc->label = dev_name(dev);
|
||||
gc->parent = dev;
|
||||
gc->direction_input = ppc44x_gpio_dir_in;
|
||||
gc->direction_output = ppc44x_gpio_dir_out;
|
||||
|
||||
return devm_gpiochip_add_data(dev, gc, chip);
|
||||
}
|
||||
|
||||
static const struct of_device_id ppc44x_gpio_match[] = {
|
||||
{
|
||||
.compatible = "ibm,ppc4xx-gpio",
|
||||
},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ppc44x_gpio_match);
|
||||
|
||||
static struct platform_driver ppc44x_gpio_driver = {
|
||||
.probe = ppc44x_gpio_probe,
|
||||
.driver = {
|
||||
.name = "ppc44x-gpio",
|
||||
.of_match_table = ppc44x_gpio_match,
|
||||
},
|
||||
};
|
||||
|
||||
MODULE_DESCRIPTION("PPC44x gpio driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
module_platform_driver(ppc44x_gpio_driver);
|
||||
|
|
@ -12,61 +12,10 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/time64.h>
|
||||
#include <linux/watchdog.h>
|
||||
#include <asm/papr-watchdog.h>
|
||||
|
||||
#define DRV_NAME "pseries-wdt"
|
||||
|
||||
/*
|
||||
* H_WATCHDOG Input
|
||||
*
|
||||
* R4: "flags":
|
||||
*
|
||||
* Bits 48-55: "operation"
|
||||
*/
|
||||
#define PSERIES_WDTF_OP_START 0x100UL /* start timer */
|
||||
#define PSERIES_WDTF_OP_STOP 0x200UL /* stop timer */
|
||||
#define PSERIES_WDTF_OP_QUERY 0x300UL /* query timer capabilities */
|
||||
|
||||
/*
|
||||
* Bits 56-63: "timeoutAction" (for "Start Watchdog" only)
|
||||
*/
|
||||
#define PSERIES_WDTF_ACTION_HARD_POWEROFF 0x1UL /* poweroff */
|
||||
#define PSERIES_WDTF_ACTION_HARD_RESTART 0x2UL /* restart */
|
||||
#define PSERIES_WDTF_ACTION_DUMP_RESTART 0x3UL /* dump + restart */
|
||||
|
||||
/*
|
||||
* H_WATCHDOG Output
|
||||
*
|
||||
* R3: Return code
|
||||
*
|
||||
* H_SUCCESS The operation completed.
|
||||
*
|
||||
* H_BUSY The hypervisor is too busy; retry the operation.
|
||||
*
|
||||
* H_PARAMETER The given "flags" are somehow invalid. Either the
|
||||
* "operation" or "timeoutAction" is invalid, or a
|
||||
* reserved bit is set.
|
||||
*
|
||||
* H_P2 The given "watchdogNumber" is zero or exceeds the
|
||||
* supported maximum value.
|
||||
*
|
||||
* H_P3 The given "timeoutInMs" is below the supported
|
||||
* minimum value.
|
||||
*
|
||||
* H_NOOP The given "watchdogNumber" is already stopped.
|
||||
*
|
||||
* H_HARDWARE The operation failed for ineffable reasons.
|
||||
*
|
||||
* H_FUNCTION The H_WATCHDOG hypercall is not supported by this
|
||||
* hypervisor.
|
||||
*
|
||||
* R4:
|
||||
*
|
||||
* - For the "Query Watchdog Capabilities" operation, a 64-bit
|
||||
* structure:
|
||||
*/
|
||||
#define PSERIES_WDTQ_MIN_TIMEOUT(cap) (((cap) >> 48) & 0xffff)
|
||||
#define PSERIES_WDTQ_MAX_NUMBER(cap) (((cap) >> 32) & 0xffff)
|
||||
|
||||
static const unsigned long pseries_wdt_action[] = {
|
||||
[0] = PSERIES_WDTF_ACTION_HARD_POWEROFF,
|
||||
[1] = PSERIES_WDTF_ACTION_HARD_RESTART,
|
||||
|
|
|
|||
|
|
@ -997,6 +997,7 @@ struct kvm_enable_cap {
|
|||
#define KVM_CAP_S390_KEYOP 247
|
||||
#define KVM_CAP_S390_VSIE_ESAMODE 248
|
||||
#define KVM_CAP_S390_HPAGE_2G 249
|
||||
#define KVM_CAP_PPC_COMPAT_CAPS 250
|
||||
|
||||
struct kvm_irq_routing_irqchip {
|
||||
__u32 irqchip;
|
||||
|
|
@ -1341,6 +1342,8 @@ struct kvm_s390_keyop {
|
|||
/* Available with KVM_CAP_COUNTER_OFFSET */
|
||||
#define KVM_ARM_SET_COUNTER_OFFSET _IOW(KVMIO, 0xb5, struct kvm_arm_counter_offset)
|
||||
#define KVM_ARM_GET_REG_WRITABLE_MASKS _IOR(KVMIO, 0xb6, struct reg_mask_range)
|
||||
/* Available with KVM_CAP_PPC_COMPAT_CAPS */
|
||||
#define KVM_PPC_GET_COMPAT_CAPS _IO(KVMIO, 0xb8)
|
||||
|
||||
/* ioctl for vm fd */
|
||||
#define KVM_CREATE_DEVICE _IOWR(KVMIO, 0xe0, struct kvm_create_device)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,9 @@
|
|||
# Where to place rustdoc generated documentation
|
||||
rustdoc_output := $(objtree)/Documentation/output/rust/rustdoc
|
||||
|
||||
# Clean generated host directory
|
||||
clean-files := host/
|
||||
|
||||
obj-$(CONFIG_RUST) += core.o compiler_builtins.o ffi.o
|
||||
always-$(CONFIG_RUST) += exports_core_generated.h
|
||||
|
||||
|
|
@ -33,7 +36,7 @@ endif
|
|||
|
||||
obj-$(CONFIG_RUST) += exports.o
|
||||
|
||||
always-$(CONFIG_RUST) += libproc_macro2.rlib libquote.rlib libsyn.rlib
|
||||
always-$(CONFIG_RUST) += host/libproc_macro2.rlib host/libquote.rlib host/libsyn.rlib
|
||||
|
||||
always-$(CONFIG_RUST_KERNEL_DOCTESTS) += doctests_kernel_generated.rs
|
||||
always-$(CONFIG_RUST_KERNEL_DOCTESTS) += doctests_kernel_generated_kunit.c
|
||||
|
|
@ -171,7 +174,7 @@ quiet_cmd_rustdoc = RUSTDOC $(if $(rustdoc_host),H, ) $<
|
|||
$(rustc_target_envs) \
|
||||
OBJTREE=$(abspath $(objtree)) \
|
||||
$(RUSTDOC) $(filter-out $(skip_flags) --remap-path-scope=%,$(if $(rustdoc_host),$(rust_common_flags),$(rust_flags))) \
|
||||
$(rustc_target_flags) -L$(objtree)/$(obj) \
|
||||
$(rustc_target_flags) -L$(objtree)/$(obj)$(if $(rustdoc_host),/host) \
|
||||
-Zunstable-options --generate-link-to-definition \
|
||||
--output $(rustdoc_output) \
|
||||
--crate-name $(subst rustdoc-,,$@) \
|
||||
|
|
@ -269,6 +272,7 @@ rustdoc-pin_init_internal: $(src)/pin-init/internal/src/lib.rs \
|
|||
|
||||
rustdoc-pin_init: private rustdoc_host = yes
|
||||
rustdoc-pin_init: private rustc_target_flags = $(pin_init-flags) \
|
||||
--extern pin_init_internal=$(objtree)/$(obj)/$(libpin_init_internal_name) \
|
||||
--extern alloc --cfg feature=\"alloc\"
|
||||
rustdoc-pin_init: $(src)/pin-init/src/lib.rs rustdoc-pin_init_internal \
|
||||
rustdoc-macros FORCE
|
||||
|
|
@ -452,7 +456,8 @@ bindgen_skip_c_flags := -mno-fp-ret-in-387 -mpreferred-stack-boundary=% \
|
|||
-fstrict-flex-arrays=% -fmin-function-alignment=% \
|
||||
-fzero-init-padding-bits=% -mno-fdpic \
|
||||
-fdiagnostics-show-context -fdiagnostics-show-context=% \
|
||||
--param=% --param asan-% -fno-isolate-erroneous-paths-dereference
|
||||
--param=% --param asan-% -fno-isolate-erroneous-paths-dereference \
|
||||
-ffixed-r2 -mmultiple -mno-readonly-in-sdata
|
||||
|
||||
# Derived from `scripts/Makefile.clang`.
|
||||
BINDGEN_TARGET_x86 := x86_64-linux-gnu
|
||||
|
|
@ -462,6 +467,13 @@ BINDGEN_TARGET_loongarch := loongarch64-linux-gnusf
|
|||
BINDGEN_TARGET_s390 := s390x-linux-gnu
|
||||
# This is only for i386 UM builds, which need the 32-bit target not -m32
|
||||
BINDGEN_TARGET_i386 := i386-linux-gnu
|
||||
|
||||
ifdef CONFIG_PPC64
|
||||
BINDGEN_TARGET_powerpc := powerpc64le-linux-gnu
|
||||
else
|
||||
BINDGEN_TARGET_powerpc := powerpc-linux-gnu
|
||||
endif
|
||||
|
||||
BINDGEN_TARGET_um := $(BINDGEN_TARGET_$(SUBARCH))
|
||||
BINDGEN_TARGET := $(BINDGEN_TARGET_$(SRCARCH))
|
||||
|
||||
|
|
@ -580,23 +592,23 @@ quiet_cmd_rustc_procmacrolibrary = $(if $(skip_clippy),RUSTC,$(RUSTC_OR_CLIPPY_Q
|
|||
$(if $(skip_clippy),$(RUSTC),$(RUSTC_OR_CLIPPY)) \
|
||||
$(filter-out $(skip_flags),$(rust_common_flags) $(rustc_target_flags)) \
|
||||
--emit=dep-info=$(depfile) --emit=link=$@ --crate-type rlib -O \
|
||||
--out-dir $(objtree)/$(obj) -L$(objtree)/$(obj) \
|
||||
--out-dir $(objtree)/$(obj)/host -L$(objtree)/$(obj)/host \
|
||||
--crate-name $(patsubst lib%.rlib,%,$(notdir $@)) $<
|
||||
|
||||
$(obj)/libproc_macro2.rlib: private skip_clippy = 1
|
||||
$(obj)/libproc_macro2.rlib: private rustc_target_flags = $(proc_macro2-flags)
|
||||
$(obj)/libproc_macro2.rlib: $(src)/proc-macro2/lib.rs FORCE
|
||||
$(obj)/host/libproc_macro2.rlib: private skip_clippy = 1
|
||||
$(obj)/host/libproc_macro2.rlib: private rustc_target_flags = $(proc_macro2-flags)
|
||||
$(obj)/host/libproc_macro2.rlib: $(src)/proc-macro2/lib.rs FORCE
|
||||
+$(call if_changed_dep,rustc_procmacrolibrary)
|
||||
|
||||
$(obj)/libquote.rlib: private skip_clippy = 1
|
||||
$(obj)/libquote.rlib: private skip_flags = $(quote-skip_flags)
|
||||
$(obj)/libquote.rlib: private rustc_target_flags = $(quote-flags)
|
||||
$(obj)/libquote.rlib: $(src)/quote/lib.rs $(obj)/libproc_macro2.rlib FORCE
|
||||
$(obj)/host/libquote.rlib: private skip_clippy = 1
|
||||
$(obj)/host/libquote.rlib: private skip_flags = $(quote-skip_flags)
|
||||
$(obj)/host/libquote.rlib: private rustc_target_flags = $(quote-flags)
|
||||
$(obj)/host/libquote.rlib: $(src)/quote/lib.rs $(obj)/host/libproc_macro2.rlib FORCE
|
||||
+$(call if_changed_dep,rustc_procmacrolibrary)
|
||||
|
||||
$(obj)/libsyn.rlib: private skip_clippy = 1
|
||||
$(obj)/libsyn.rlib: private rustc_target_flags = $(syn-flags)
|
||||
$(obj)/libsyn.rlib: $(src)/syn/lib.rs $(obj)/libquote.rlib FORCE
|
||||
$(obj)/host/libsyn.rlib: private skip_clippy = 1
|
||||
$(obj)/host/libsyn.rlib: private rustc_target_flags = $(syn-flags)
|
||||
$(obj)/host/libsyn.rlib: $(src)/syn/lib.rs $(obj)/host/libquote.rlib FORCE
|
||||
+$(call if_changed_dep,rustc_procmacrolibrary)
|
||||
|
||||
quiet_cmd_rustc_procmacro = $(if $(skip_clippy),RUSTC,$(RUSTC_OR_CLIPPY_QUIET)) P $@
|
||||
|
|
@ -606,26 +618,26 @@ quiet_cmd_rustc_procmacro = $(if $(skip_clippy),RUSTC,$(RUSTC_OR_CLIPPY_QUIET))
|
|||
-Clinker-flavor=gcc -Clinker=$(HOSTCC) \
|
||||
-Clink-args='$(call escsq,$(KBUILD_PROCMACROLDFLAGS))' \
|
||||
--emit=dep-info=$(depfile) --emit=link=$@ --extern proc_macro \
|
||||
--crate-type proc-macro -L$(objtree)/$(obj) \
|
||||
--crate-type proc-macro -L$(objtree)/$(obj)/host \
|
||||
--crate-name $(patsubst lib%.$(procmacro-extension),%,$(notdir $@)) \
|
||||
@$(objtree)/include/generated/rustc_cfg $<
|
||||
|
||||
# Procedural macros can only be used with the `rustc` that compiled it.
|
||||
$(obj)/$(libzerocopy_derive_name): private skip_clippy = 1
|
||||
$(obj)/$(libzerocopy_derive_name): private rustc_target_flags = $(zerocopy_derive-flags)
|
||||
$(obj)/$(libzerocopy_derive_name): $(src)/zerocopy-derive/lib.rs $(obj)/libproc_macro2.rlib \
|
||||
$(obj)/libquote.rlib $(obj)/libsyn.rlib FORCE
|
||||
$(obj)/$(libzerocopy_derive_name): $(src)/zerocopy-derive/lib.rs $(obj)/host/libproc_macro2.rlib \
|
||||
$(obj)/host/libquote.rlib $(obj)/host/libsyn.rlib FORCE
|
||||
+$(call if_changed_dep,rustc_procmacro)
|
||||
|
||||
$(obj)/$(libmacros_name): private rustc_target_flags = \
|
||||
--extern proc_macro2 --extern quote --extern syn
|
||||
$(obj)/$(libmacros_name): $(src)/macros/lib.rs $(obj)/libproc_macro2.rlib \
|
||||
$(obj)/libquote.rlib $(obj)/libsyn.rlib FORCE
|
||||
$(obj)/$(libmacros_name): $(src)/macros/lib.rs $(obj)/host/libproc_macro2.rlib \
|
||||
$(obj)/host/libquote.rlib $(obj)/host/libsyn.rlib FORCE
|
||||
+$(call if_changed_dep,rustc_procmacro)
|
||||
|
||||
$(obj)/$(libpin_init_internal_name): private rustc_target_flags = $(pin_init_internal-flags)
|
||||
$(obj)/$(libpin_init_internal_name): $(src)/pin-init/internal/src/lib.rs \
|
||||
$(obj)/libproc_macro2.rlib $(obj)/libquote.rlib $(obj)/libsyn.rlib FORCE
|
||||
$(obj)/host/libproc_macro2.rlib $(obj)/host/libquote.rlib $(obj)/host/libsyn.rlib FORCE
|
||||
+$(call if_changed_dep,rustc_procmacro)
|
||||
|
||||
# `rustc` requires `-Zunstable-options` to use custom target specifications
|
||||
|
|
@ -683,6 +695,10 @@ ifneq ($(or $(CONFIG_ARM64),$(and $(CONFIG_RISCV),$(CONFIG_64BIT))),)
|
|||
__ashrti3 \
|
||||
__ashlti3 __lshrti3
|
||||
endif
|
||||
ifdef CONFIG_PPC32
|
||||
redirect-intrinsics += \
|
||||
__udivdi3 __umoddi3
|
||||
endif
|
||||
|
||||
ifdef CONFIG_MODVERSIONS
|
||||
cmd_gendwarfksyms = $(if $(skip_gendwarfksyms),, \
|
||||
|
|
|
|||
|
|
@ -97,5 +97,11 @@ pub extern "C" fn $ident() {
|
|||
__aeabi_uldivmod,
|
||||
});
|
||||
|
||||
#[cfg(target_arch = "powerpc")]
|
||||
define_panicking_intrinsics!("`u64` division/modulo should not be used", {
|
||||
__udivdi3,
|
||||
__umoddi3,
|
||||
});
|
||||
|
||||
// NOTE: if you are adding a new intrinsic here, you should also add it to
|
||||
// `redirect-intrinsics` in `rust/Makefile`.
|
||||
|
|
|
|||
|
|
@ -58,7 +58,9 @@
|
|||
#include "cred.c"
|
||||
#include "device.c"
|
||||
#include "dma.c"
|
||||
#ifdef CONFIG_DMA_SHARED_BUFFER
|
||||
#include "dma-resv.c"
|
||||
#endif
|
||||
#include "drm.c"
|
||||
#include "drm_gpuvm.c"
|
||||
#include "err.c"
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@ llvm)
|
|||
rustc)
|
||||
if [ "$SRCARCH" = "s390" ]; then
|
||||
echo 1.96.0
|
||||
elif [ "$ARCH" = powerpc ]; then
|
||||
echo 1.95.0
|
||||
else
|
||||
echo 1.85.0
|
||||
fi
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user