From: Ashish Kalra Add a debugfs interface to report per-CPU RMPOPT status across all system RAM. To dump the per-CPU RMPOPT status for all system RAM: /sys/kernel/debug/rmpopt# cat rmpopt-table Memory @ 0GB: CPU(s): none Memory @ 1GB: CPU(s): none Memory @ 2GB: CPU(s): 0-1023 Memory @ 3GB: CPU(s): 0-1023 Memory @ 4GB: CPU(s): none Memory @ 5GB: CPU(s): 0-1023 Memory @ 6GB: CPU(s): 0-1023 Memory @ 7GB: CPU(s): 0-1023 ... Memory @1025GB: CPU(s): 0-1023 Memory @1026GB: CPU(s): 0-1023 Memory @1027GB: CPU(s): 0-1023 Memory @1028GB: CPU(s): 0-1023 Memory @1029GB: CPU(s): 0-1023 Memory @1030GB: CPU(s): 0-1023 Memory @1031GB: CPU(s): 0-1023 Memory @1032GB: CPU(s): 0-1023 Memory @1033GB: CPU(s): 0-1023 Memory @1034GB: CPU(s): 0-1023 Memory @1035GB: CPU(s): 0-1023 Memory @1036GB: CPU(s): 0-1023 Memory @1037GB: CPU(s): 0-1023 Memory @1038GB: CPU(s): none Suggested-by: Thomas Lendacky Signed-off-by: Ashish Kalra --- arch/x86/virt/svm/sev.c | 101 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 100 insertions(+), 1 deletion(-) diff --git a/arch/x86/virt/svm/sev.c b/arch/x86/virt/svm/sev.c index 0f71a045e4aa..c5a11f574e42 100644 --- a/arch/x86/virt/svm/sev.c +++ b/arch/x86/virt/svm/sev.c @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include #include @@ -151,6 +153,13 @@ struct rmpopt_socket_config { static atomic_t rmpopt_in_progress = ATOMIC_INIT(0); +static cpumask_t rmpopt_cpumask; +static struct dentry *rmpopt_debugfs; + +struct seq_paddr { + phys_addr_t next_seq_paddr; +}; + #undef pr_fmt #define pr_fmt(fmt) "SEV-SNP: " fmt @@ -547,9 +556,14 @@ static void get_cpumask_of_primary_threads(cpumask_var_t cpulist) */ static void rmpopt(void *val) { + bool optimized; + asm volatile(".byte 0xf2, 0x0f, 0x01, 0xfc\n\t" - : : "a" ((u64)val & PUD_MASK), "c" ((u64)val & 0x1) + : "=@ccc" (optimized) + : "a" ((u64)val & PUD_MASK), "c" ((u64)val & 0x1) : "memory", "cc"); + + assign_cpu(smp_processor_id(), &rmpopt_cpumask, optimized); } static int rmpopt_kthread(void *__unused) @@ -672,6 +686,89 @@ static int rmpopt_configfs_setup(void) return ret; } +/* + * start() can be called multiple times if allocated buffer has overflowed + * and bigger buffer is allocated. + */ +static void *rmpopt_table_seq_start(struct seq_file *seq, loff_t *pos) +{ + phys_addr_t end_paddr = ALIGN(PFN_PHYS(max_pfn), PUD_SIZE); + struct seq_paddr *p = seq->private; + + if (*pos == 0) { + p->next_seq_paddr = ALIGN_DOWN(PFN_PHYS(min_low_pfn), PUD_SIZE); + return &p->next_seq_paddr; + } + + if (p->next_seq_paddr == end_paddr) + return NULL; + + return &p->next_seq_paddr; +} + +static void *rmpopt_table_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + phys_addr_t end_paddr = ALIGN(PFN_PHYS(max_pfn), PUD_SIZE); + phys_addr_t *curr_paddr = v; + + (*pos)++; + if (*curr_paddr == end_paddr) + return NULL; + *curr_paddr += PUD_SIZE; + + return curr_paddr; +} + +static void rmpopt_table_seq_stop(struct seq_file *seq, void *v) +{ +} + +static int rmpopt_table_seq_show(struct seq_file *seq, void *v) +{ + phys_addr_t *curr_paddr = v; + + seq_printf(seq, "Memory @%3lluGB: ", *curr_paddr >> PUD_SHIFT); + + cpumask_clear(&rmpopt_cpumask); + on_each_cpu_mask(cpu_online_mask, rmpopt, + (void *)(*curr_paddr | RMPOPT_FUNC_REPORT_STATUS), + true); + + if (cpumask_empty(&rmpopt_cpumask)) + seq_puts(seq, "CPU(s): none\n"); + else + seq_printf(seq, "CPU(s): %*pbl\n", cpumask_pr_args(&rmpopt_cpumask)); + + return 0; +} + +static const struct seq_operations rmpopt_table_seq_ops = { + .start = rmpopt_table_seq_start, + .next = rmpopt_table_seq_next, + .stop = rmpopt_table_seq_stop, + .show = rmpopt_table_seq_show +}; + +static int rmpopt_table_open(struct inode *inode, struct file *file) +{ + return seq_open_private(file, &rmpopt_table_seq_ops, sizeof(struct seq_paddr)); +} + +static const struct file_operations rmpopt_table_fops = { + .open = rmpopt_table_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release_private, +}; + +static void rmpopt_debugfs_setup(void) +{ + rmpopt_debugfs = debugfs_create_dir("rmpopt", NULL); + + debugfs_create_file("rmpopt-table", 0444, rmpopt_debugfs, + NULL, &rmpopt_table_fops); +} + static void __configure_rmpopt(void *val) { u64 rmpopt_base = ((u64)val & PUD_MASK) | MSR_AMD64_RMPOPT_ENABLE; @@ -849,6 +946,8 @@ static __init void configure_and_enable_rmpopt(void) rmpopt_configfs_setup(); + rmpopt_debugfs_setup(); + free_cpumask: free_cpumask_var(primary_threads_cpulist); } -- 2.43.0