Commit d6138b4a authored by Mark Brown's avatar Mark Brown Committed by Catalin Marinas

arm64/sme: Provide storage for ZT0

When the system supports SME2 there is an additional register ZT0 which
we must store when the task is using SME. Since ZT0 is accessible only
when PSTATE.ZA is set just like ZA we allocate storage for it along with
ZA, increasing the allocation size for the memory region where we store
ZA and storing the data for ZT after that for ZA.
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
Link: https://lore.kernel.org/r/20221208-arm64-sme2-v4-9-f2fa0aef982f@kernel.orgSigned-off-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
parent d4913eee
...@@ -105,6 +105,13 @@ static inline void *sve_pffr(struct thread_struct *thread) ...@@ -105,6 +105,13 @@ static inline void *sve_pffr(struct thread_struct *thread)
return (char *)thread->sve_state + sve_ffr_offset(vl); return (char *)thread->sve_state + sve_ffr_offset(vl);
} }
static inline void *thread_zt_state(struct thread_struct *thread)
{
/* The ZT register state is stored immediately after the ZA state */
unsigned int sme_vq = sve_vq_from_vl(thread_get_sme_vl(thread));
return thread->sme_state + ZA_SIG_REGS_SIZE(sme_vq);
}
extern void sve_save_state(void *state, u32 *pfpsr, int save_ffr); extern void sve_save_state(void *state, u32 *pfpsr, int save_ffr);
extern void sve_load_state(void const *state, u32 const *pfpsr, extern void sve_load_state(void const *state, u32 const *pfpsr,
int restore_ffr); int restore_ffr);
...@@ -354,6 +361,9 @@ extern unsigned int sme_get_vl(void); ...@@ -354,6 +361,9 @@ extern unsigned int sme_get_vl(void);
extern int sme_set_current_vl(unsigned long arg); extern int sme_set_current_vl(unsigned long arg);
extern int sme_get_current_vl(void); extern int sme_get_current_vl(void);
/* Will move with signal support */
#define ZT_SIG_REG_SIZE 512
/* /*
* Return how many bytes of memory are required to store the full SME * Return how many bytes of memory are required to store the full SME
* specific state for task, given task's currently configured vector * specific state for task, given task's currently configured vector
...@@ -366,6 +376,9 @@ static inline size_t sme_state_size(struct task_struct const *task) ...@@ -366,6 +376,9 @@ static inline size_t sme_state_size(struct task_struct const *task)
size = ZA_SIG_REGS_SIZE(sve_vq_from_vl(vl)); size = ZA_SIG_REGS_SIZE(sve_vq_from_vl(vl));
if (system_supports_sme2())
size += ZT_SIG_REG_SIZE;
return size; return size;
} }
......
...@@ -307,11 +307,11 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) ...@@ -307,11 +307,11 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
/* /*
* In the unlikely event that we create a new thread with ZA * In the unlikely event that we create a new thread with ZA
* enabled we should retain the ZA state so duplicate it here. * enabled we should retain the ZA and ZT state so duplicate
* This may be shortly freed if we exec() or if CLONE_SETTLS * it here. This may be shortly freed if we exec() or if
* but it's simpler to do it here. To avoid confusing the rest * CLONE_SETTLS but it's simpler to do it here. To avoid
* of the code ensure that we have a sve_state allocated * confusing the rest of the code ensure that we have a
* whenever sme_state is allocated. * sve_state allocated whenever sme_state is allocated.
*/ */
if (thread_za_enabled(&src->thread)) { if (thread_za_enabled(&src->thread)) {
dst->thread.sve_state = kzalloc(sve_state_size(src), dst->thread.sve_state = kzalloc(sve_state_size(src),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment