mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 15:22:21 -04:00
Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
Pull arm64 fixes from Will Deacon: "A mixture of ptdump, compat and MTE fixes that came in during the merge window: - Fix address handling of final memory region in ptdump - Fix emulation of decrementing load/store multiple from 32-bit task - Fix SCTLR context-switching for store-only MTE mode - Fix numerous issues in MTE selftests" * tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux: selftests/arm64: Add MTE test config fragment selftests/arm64: Fix MTE prctl TAP plan selftests/arm64: Treat KSM merge_across_nodes as optional selftests/arm64: Print missing MTE TAP headers arm64: compat: Fix decrementing LDM/STM alignment emulation arm64: process: Fix context switching MTE store-only tag check KVM: arm64: ptdump: Flush the last region arm64: ptdump: Make note_page_flush() range aware
This commit is contained in:
@@ -264,7 +264,7 @@ static inline void task_set_sve_vl_onexec(struct task_struct *task,
|
||||
|
||||
#define SCTLR_USER_MASK \
|
||||
(SCTLR_ELx_ENIA | SCTLR_ELx_ENIB | SCTLR_ELx_ENDA | SCTLR_ELx_ENDB | \
|
||||
SCTLR_EL1_TCF0_MASK)
|
||||
SCTLR_EL1_TCF0_MASK | SCTLR_EL1_TCSO0_MASK)
|
||||
|
||||
static inline void arch_thread_struct_whitelist(unsigned long *offset,
|
||||
unsigned long *size)
|
||||
|
||||
@@ -50,6 +50,8 @@ struct ptdump_pg_state {
|
||||
const struct addr_marker *marker;
|
||||
const struct mm_struct *mm;
|
||||
unsigned long start_address;
|
||||
/* exclusive end, ULONG_MAX represents an end at 1 << 64 */
|
||||
unsigned long end_address;
|
||||
int level;
|
||||
ptval_t current_prot;
|
||||
bool check_wx;
|
||||
|
||||
@@ -114,8 +114,8 @@ do_alignment_ldrdstrd(unsigned long addr, u32 instr, struct pt_regs *regs)
|
||||
static int
|
||||
do_alignment_ldmstm(unsigned long addr, u32 instr, struct pt_regs *regs)
|
||||
{
|
||||
unsigned int rd, rn, nr_regs, regbits;
|
||||
unsigned long eaddr, newaddr;
|
||||
unsigned int rd, rn, regbits;
|
||||
unsigned long eaddr, newaddr, nr_regs;
|
||||
unsigned int val;
|
||||
|
||||
/* count the number of registers in the mask to be transferred */
|
||||
|
||||
@@ -130,7 +130,7 @@ static struct kvm_ptdump_guest_state *kvm_ptdump_parser_create(struct kvm_s2_mmu
|
||||
}
|
||||
|
||||
st->ipa_marker[0].name = "Guest IPA";
|
||||
st->ipa_marker[1].start_address = BIT(pgtable->ia_bits);
|
||||
st->ipa_marker[1].start_address = ULONG_MAX;
|
||||
|
||||
st->mmu = mmu;
|
||||
return st;
|
||||
@@ -148,18 +148,21 @@ static int kvm_ptdump_guest_show(struct seq_file *m, void *unused)
|
||||
.flags = KVM_PGTABLE_WALK_LEAF,
|
||||
};
|
||||
|
||||
guard(write_lock)(&kvm->mmu_lock);
|
||||
st->parser_state = (struct ptdump_pg_state) {
|
||||
.marker = &st->ipa_marker[0],
|
||||
.end_address = BIT(mmu->pgt->ia_bits),
|
||||
.level = -1,
|
||||
.pg_level = &st->level[0],
|
||||
.seq = m,
|
||||
};
|
||||
|
||||
write_lock(&kvm->mmu_lock);
|
||||
ret = kvm_pgtable_walk(mmu->pgt, 0, BIT(mmu->pgt->ia_bits), &walker);
|
||||
write_unlock(&kvm->mmu_lock);
|
||||
if (ret)
|
||||
return ret;
|
||||
note_page_flush(&st->parser_state.ptdump);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kvm_ptdump_guest_open(struct inode *m, struct file *file)
|
||||
|
||||
@@ -278,9 +278,19 @@ void note_page_pgd(struct ptdump_state *pt_st, unsigned long addr, pgd_t pgd)
|
||||
|
||||
void note_page_flush(struct ptdump_state *pt_st)
|
||||
{
|
||||
struct ptdump_pg_state *st = container_of(pt_st, struct ptdump_pg_state, ptdump);
|
||||
unsigned long end = st->end_address;
|
||||
pte_t pte_zero = {0};
|
||||
|
||||
note_page(pt_st, 0, -1, pte_val(pte_zero));
|
||||
/*
|
||||
* Address spaces that end at 1 << 64 have end_address == ULONG_MAX,
|
||||
* but note_page() expects the exclusive end. In this case adjust end
|
||||
* to the wraparound value 0.
|
||||
*/
|
||||
if (end == ULONG_MAX)
|
||||
end = 0;
|
||||
|
||||
note_page(pt_st, end, -1, pte_val(pte_zero));
|
||||
}
|
||||
|
||||
void ptdump_walk(struct seq_file *s, struct ptdump_info *info)
|
||||
@@ -296,6 +306,7 @@ void ptdump_walk(struct seq_file *s, struct ptdump_info *info)
|
||||
.marker = info->markers,
|
||||
.mm = info->mm,
|
||||
.pg_level = &kernel_pg_levels[0],
|
||||
.end_address = end,
|
||||
.level = -1,
|
||||
.ptdump = {
|
||||
.note_page_pte = note_page_pte,
|
||||
@@ -337,6 +348,7 @@ bool ptdump_check_wx(void)
|
||||
{ -1, NULL},
|
||||
},
|
||||
.pg_level = &kernel_pg_levels[0],
|
||||
.end_address = ~0UL,
|
||||
.level = -1,
|
||||
.check_wx = true,
|
||||
.ptdump = {
|
||||
|
||||
17
tools/testing/selftests/arm64/config
Normal file
17
tools/testing/selftests/arm64/config
Normal file
@@ -0,0 +1,17 @@
|
||||
CONFIG_ARM64_BTI=y
|
||||
CONFIG_ARM64_GCS=y
|
||||
CONFIG_ARM64_MTE=y
|
||||
CONFIG_ARM64_POE=y
|
||||
CONFIG_ARM64_PTR_AUTH=y
|
||||
CONFIG_ARM64_SME=y
|
||||
CONFIG_ARM64_SVE=y
|
||||
CONFIG_ARM64_TAGGED_ADDR_ABI=y
|
||||
CONFIG_HUGETLBFS=y
|
||||
CONFIG_KSM=y
|
||||
CONFIG_PROC_FS=y
|
||||
CONFIG_SECCOMP=y
|
||||
CONFIG_SECCOMP_FILTER=y
|
||||
CONFIG_SHMEM=y
|
||||
CONFIG_SYSCTL=y
|
||||
CONFIG_SYSFS=y
|
||||
CONFIG_TMPFS=y
|
||||
@@ -406,6 +406,8 @@ int main(int argc, char *argv[])
|
||||
size_t page_size = getpagesize();
|
||||
int item = ARRAY_SIZE(sizes);
|
||||
|
||||
ksft_print_header();
|
||||
|
||||
sizes[item - 3] = page_size - 1;
|
||||
sizes[item - 2] = page_size;
|
||||
sizes[item - 1] = page_size + 1;
|
||||
|
||||
@@ -146,6 +146,8 @@ int main(int argc, char *argv[])
|
||||
int err;
|
||||
int item = ARRAY_SIZE(sizes);
|
||||
|
||||
ksft_print_header();
|
||||
|
||||
page_size = getpagesize();
|
||||
if (!page_size) {
|
||||
ksft_print_msg("ERR: Unable to get page size\n");
|
||||
|
||||
@@ -131,6 +131,7 @@ int main(int argc, char *argv[])
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
ksft_print_header();
|
||||
ksft_set_plan(1);
|
||||
|
||||
evaluate_test(mte_gcr_fork_test(),
|
||||
|
||||
@@ -230,6 +230,8 @@ int main(int argc, char *argv[])
|
||||
void *map_ptr;
|
||||
unsigned long map_size;
|
||||
|
||||
ksft_print_header();
|
||||
|
||||
err = mte_default_setup();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -22,6 +23,20 @@
|
||||
|
||||
static size_t page_sz;
|
||||
static unsigned long ksm_sysfs[5];
|
||||
static bool has_merge_across_nodes;
|
||||
|
||||
static bool merge_across_nodes_available(void)
|
||||
{
|
||||
const char *path = PATH_KSM "merge_across_nodes";
|
||||
|
||||
if (!access(path, R_OK | W_OK))
|
||||
return true;
|
||||
if (errno == ENOENT)
|
||||
return false;
|
||||
|
||||
ksft_exit_skip("Unable to read and write %s: %s\n", path,
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
static unsigned long read_sysfs(char *str)
|
||||
{
|
||||
@@ -56,8 +71,10 @@ static void write_sysfs(char *str, unsigned long val)
|
||||
|
||||
static void mte_ksm_setup(void)
|
||||
{
|
||||
ksm_sysfs[0] = read_sysfs(PATH_KSM "merge_across_nodes");
|
||||
write_sysfs(PATH_KSM "merge_across_nodes", 1);
|
||||
if (has_merge_across_nodes) {
|
||||
ksm_sysfs[0] = read_sysfs(PATH_KSM "merge_across_nodes");
|
||||
write_sysfs(PATH_KSM "merge_across_nodes", 1);
|
||||
}
|
||||
ksm_sysfs[1] = read_sysfs(PATH_KSM "sleep_millisecs");
|
||||
write_sysfs(PATH_KSM "sleep_millisecs", 0);
|
||||
ksm_sysfs[2] = read_sysfs(PATH_KSM "run");
|
||||
@@ -70,7 +87,8 @@ static void mte_ksm_setup(void)
|
||||
|
||||
static void mte_ksm_restore(void)
|
||||
{
|
||||
write_sysfs(PATH_KSM "merge_across_nodes", ksm_sysfs[0]);
|
||||
if (has_merge_across_nodes)
|
||||
write_sysfs(PATH_KSM "merge_across_nodes", ksm_sysfs[0]);
|
||||
write_sysfs(PATH_KSM "sleep_millisecs", ksm_sysfs[1]);
|
||||
write_sysfs(PATH_KSM "run", ksm_sysfs[2]);
|
||||
write_sysfs(PATH_KSM "max_page_sharing", ksm_sysfs[3]);
|
||||
@@ -132,9 +150,16 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
int err;
|
||||
|
||||
ksft_print_header();
|
||||
|
||||
err = mte_default_setup();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (geteuid() != 0)
|
||||
ksft_exit_skip("Please run the test as root\n");
|
||||
|
||||
has_merge_across_nodes = merge_across_nodes_available();
|
||||
page_sz = getpagesize();
|
||||
if (!page_sz) {
|
||||
ksft_print_msg("ERR: Unable to get page size\n");
|
||||
|
||||
@@ -945,6 +945,8 @@ int main(int argc, char *argv[])
|
||||
},
|
||||
};
|
||||
|
||||
ksft_print_header();
|
||||
|
||||
err = mte_default_setup();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -119,7 +119,7 @@ int main(void)
|
||||
int i;
|
||||
|
||||
ksft_print_header();
|
||||
ksft_set_plan(ARRAY_SIZE(mte_modes));
|
||||
ksft_set_plan(ARRAY_SIZE(mte_modes) + 1);
|
||||
|
||||
check_basic_read();
|
||||
for (i = 0; i < ARRAY_SIZE(mte_modes); i++)
|
||||
|
||||
@@ -175,6 +175,8 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
int err;
|
||||
|
||||
ksft_print_header();
|
||||
|
||||
err = mte_default_setup();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -201,6 +201,8 @@ int main(int argc, char *argv[])
|
||||
int tag_offsets[] = {page_sz, MT_GRANULE_SIZE};
|
||||
char test_name[TEST_NAME_MAX];
|
||||
|
||||
ksft_print_header();
|
||||
|
||||
page_sz = getpagesize();
|
||||
if (!page_sz) {
|
||||
ksft_print_msg("ERR: Unable to get page size\n");
|
||||
|
||||
Reference in New Issue
Block a user