mirror of
https://github.com/torvalds/linux.git
synced 2026-04-18 06:44:00 -04:00
MPAM allows traffic in the SoC to be labeled by the OS, these labels are used to apply policy in caches and bandwidth regulators, and to monitor traffic in the SoC. The label is made up of a PARTID and PMG value. The x86 equivalent calls these CLOSID and RMID, but they don't map precisely. MPAM has two CPU system registers that is used to hold the PARTID and PMG values that traffic generated at each exception level will use. These can be set per-task by the resctrl file system. (resctrl is the defacto interface for controlling this stuff). Add a helper to switch this. struct task_struct's separate CLOSID and RMID fields are insufficient to implement resctrl using MPAM, as resctrl can change the PARTID (CLOSID) and PMG (sort of like the RMID) separately. On x86, the rmid is an independent number, so a race that writes a mismatched closid and rmid into hardware is benign. On arm64, the pmg bits extend the partid. (i.e. partid-5 has a pmg-0 that is not the same as partid-6's pmg-0). In this case, mismatching the values will 'dirty' a pmg value that resctrl believes is clean, and is not tracking with its 'limbo' code. To avoid this, the partid and pmg are always read and written as a pair. This requires a new u64 field. In struct task_struct there are two u32, rmid and closid for the x86 case, but as we can't use them here do something else. Add this new field, mpam_partid_pmg, to struct thread_info to avoid adding more architecture specific code to struct task_struct. Always use READ_ONCE()/WRITE_ONCE() when accessing this field. Resctrl allows a per-cpu 'default' value to be set, this overrides the values when scheduling a task in the default control-group, which has PARTID 0. The way 'code data prioritisation' gets emulated means the register value for the default group needs to be a variable. The current system register value is kept in a per-cpu variable to avoid writing to the system register if the value isn't going to change. Writes to this register may reset the hardware state for regulating bandwidth. Finally, there is no reason to context switch these registers unless there is a driver changing the values in struct task_struct. Hide the whole thing behind a static key. This also allows the driver to disable MPAM in response to errors reported by hardware. Move the existing static key to belong to the arch code, as in the future the MPAM driver may become a loadable module. All this should depend on whether there is an MPAM driver, hide it behind CONFIG_ARM64_MPAM. Tested-by: Gavin Shan <gshan@redhat.com> Tested-by: Shaopeng Tan <tan.shaopeng@jp.fujitsu.com> Tested-by: Peter Newman <peternewman@google.com> Tested-by: Zeng Heng <zengheng4@huawei.com> Tested-by: Punit Agrawal <punit.agrawal@oss.qualcomm.com> Tested-by: Jesse Chick <jessechick@os.amperecomputing.com> CC: Amit Singh Tomar <amitsinght@marvell.com> Reviewed-by: Zeng Heng <zengheng4@huawei.com> Reviewed-by: Shaopeng Tan <tan.shaopeng@jp.fujitsu.com> Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com> Reviewed-by: Gavin Shan <gshan@redhat.com> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com> Co-developed-by: Ben Horgan <ben.horgan@arm.com> Signed-off-by: Ben Horgan <ben.horgan@arm.com> Signed-off-by: James Morse <james.morse@arm.com>
131 lines
4.1 KiB
C
131 lines
4.1 KiB
C
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/*
|
|
* Based on arch/arm/include/asm/thread_info.h
|
|
*
|
|
* Copyright (C) 2002 Russell King.
|
|
* Copyright (C) 2012 ARM Ltd.
|
|
*/
|
|
#ifndef __ASM_THREAD_INFO_H
|
|
#define __ASM_THREAD_INFO_H
|
|
|
|
#include <linux/compiler.h>
|
|
|
|
#ifndef __ASSEMBLER__
|
|
|
|
struct task_struct;
|
|
|
|
#include <asm/memory.h>
|
|
#include <asm/stack_pointer.h>
|
|
#include <asm/types.h>
|
|
|
|
/*
|
|
* low level task data that entry.S needs immediate access to.
|
|
*/
|
|
struct thread_info {
|
|
unsigned long flags; /* low level flags */
|
|
#ifdef CONFIG_ARM64_SW_TTBR0_PAN
|
|
u64 ttbr0; /* saved TTBR0_EL1 */
|
|
#endif
|
|
union {
|
|
u64 preempt_count; /* 0 => preemptible, <0 => bug */
|
|
struct {
|
|
#ifdef CONFIG_CPU_BIG_ENDIAN
|
|
u32 need_resched;
|
|
u32 count;
|
|
#else
|
|
u32 count;
|
|
u32 need_resched;
|
|
#endif
|
|
} preempt;
|
|
};
|
|
#ifdef CONFIG_SHADOW_CALL_STACK
|
|
void *scs_base;
|
|
void *scs_sp;
|
|
#endif
|
|
#ifdef CONFIG_ARM64_MPAM
|
|
u64 mpam_partid_pmg;
|
|
#endif
|
|
u32 cpu;
|
|
};
|
|
|
|
#define thread_saved_pc(tsk) \
|
|
((unsigned long)(tsk->thread.cpu_context.pc))
|
|
#define thread_saved_sp(tsk) \
|
|
((unsigned long)(tsk->thread.cpu_context.sp))
|
|
#define thread_saved_fp(tsk) \
|
|
((unsigned long)(tsk->thread.cpu_context.fp))
|
|
|
|
void arch_setup_new_exec(void);
|
|
#define arch_setup_new_exec arch_setup_new_exec
|
|
|
|
#endif
|
|
|
|
#define TIF_SIGPENDING 0 /* signal pending */
|
|
#define TIF_NEED_RESCHED 1 /* rescheduling necessary */
|
|
#define TIF_NEED_RESCHED_LAZY 2 /* Lazy rescheduling needed */
|
|
#define TIF_NOTIFY_RESUME 3 /* callback before returning to user */
|
|
#define TIF_FOREIGN_FPSTATE 4 /* CPU's FP state is not current's */
|
|
#define TIF_UPROBE 5 /* uprobe breakpoint or singlestep */
|
|
#define TIF_MTE_ASYNC_FAULT 6 /* MTE Asynchronous Tag Check Fault */
|
|
#define TIF_NOTIFY_SIGNAL 7 /* signal notifications exist */
|
|
#define TIF_SYSCALL_TRACE 8 /* syscall trace active */
|
|
#define TIF_SYSCALL_AUDIT 9 /* syscall auditing */
|
|
#define TIF_SYSCALL_TRACEPOINT 10 /* syscall tracepoint for ftrace */
|
|
#define TIF_SECCOMP 11 /* syscall secure computing */
|
|
#define TIF_SYSCALL_EMU 12 /* syscall emulation active */
|
|
#define TIF_PATCH_PENDING 13 /* pending live patching update */
|
|
#define TIF_MEMDIE 18 /* is terminating due to OOM killer */
|
|
#define TIF_FREEZE 19
|
|
#define TIF_RESTORE_SIGMASK 20
|
|
#define TIF_SINGLESTEP 21
|
|
#define TIF_32BIT 22 /* 32bit process */
|
|
#define TIF_SVE 23 /* Scalable Vector Extension in use */
|
|
#define TIF_SVE_VL_INHERIT 24 /* Inherit SVE vl_onexec across exec */
|
|
#define TIF_SSBD 25 /* Wants SSB mitigation */
|
|
#define TIF_TAGGED_ADDR 26 /* Allow tagged user addresses */
|
|
#define TIF_SME 27 /* SME in use */
|
|
#define TIF_SME_VL_INHERIT 28 /* Inherit SME vl_onexec across exec */
|
|
#define TIF_KERNEL_FPSTATE 29 /* Task is in a kernel mode FPSIMD section */
|
|
#define TIF_TSC_SIGSEGV 30 /* SIGSEGV on counter-timer access */
|
|
#define TIF_LAZY_MMU_PENDING 31 /* Ops pending for lazy mmu mode exit */
|
|
|
|
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
|
|
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
|
|
#define _TIF_NEED_RESCHED_LAZY (1 << TIF_NEED_RESCHED_LAZY)
|
|
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
|
|
#define _TIF_FOREIGN_FPSTATE (1 << TIF_FOREIGN_FPSTATE)
|
|
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
|
|
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
|
|
#define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT)
|
|
#define _TIF_SECCOMP (1 << TIF_SECCOMP)
|
|
#define _TIF_SYSCALL_EMU (1 << TIF_SYSCALL_EMU)
|
|
#define _TIF_PATCH_PENDING (1 << TIF_PATCH_PENDING)
|
|
#define _TIF_UPROBE (1 << TIF_UPROBE)
|
|
#define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP)
|
|
#define _TIF_32BIT (1 << TIF_32BIT)
|
|
#define _TIF_SVE (1 << TIF_SVE)
|
|
#define _TIF_MTE_ASYNC_FAULT (1 << TIF_MTE_ASYNC_FAULT)
|
|
#define _TIF_NOTIFY_SIGNAL (1 << TIF_NOTIFY_SIGNAL)
|
|
#define _TIF_TSC_SIGSEGV (1 << TIF_TSC_SIGSEGV)
|
|
|
|
#define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
|
|
_TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP | \
|
|
_TIF_SYSCALL_EMU)
|
|
|
|
#ifdef CONFIG_SHADOW_CALL_STACK
|
|
#define INIT_SCS \
|
|
.scs_base = init_shadow_call_stack, \
|
|
.scs_sp = init_shadow_call_stack,
|
|
#else
|
|
#define INIT_SCS
|
|
#endif
|
|
|
|
#define INIT_THREAD_INFO(tsk) \
|
|
{ \
|
|
.flags = _TIF_FOREIGN_FPSTATE, \
|
|
.preempt_count = INIT_PREEMPT_COUNT, \
|
|
INIT_SCS \
|
|
}
|
|
|
|
#endif /* __ASM_THREAD_INFO_H */
|