From: Dave Hansen <dave.hansen@intel.com>
To: Ashish Kalra <Ashish.Kalra@amd.com>,
tglx@kernel.org, mingo@redhat.com, bp@alien8.de,
dave.hansen@linux.intel.com, x86@kernel.org, hpa@zytor.com,
seanjc@google.com, peterz@infradead.org, thomas.lendacky@amd.com,
herbert@gondor.apana.org.au, davem@davemloft.net,
ardb@kernel.org
Cc: pbonzini@redhat.com, aik@amd.com, Michael.Roth@amd.com,
KPrateek.Nayak@amd.com, Tycho.Andersen@amd.com,
Nathan.Fontenot@amd.com, jackyli@google.com, pgonda@google.com,
rientjes@google.com, jacobhxu@google.com, xin@zytor.com,
pawan.kumar.gupta@linux.intel.com, babu.moger@amd.com,
dyoung@redhat.com, nikunj@amd.com, john.allen@amd.com,
darwi@linutronix.de, linux-kernel@vger.kernel.org,
linux-crypto@vger.kernel.org, kvm@vger.kernel.org,
linux-coco@lists.linux.dev
Subject: Re: [PATCH 2/6] x86/sev: add support for enabling RMPOPT
Date: Tue, 17 Feb 2026 14:06:52 -0800 [thread overview]
Message-ID: <10baddd3-add6-4771-a1ce-f759d3ec69d2@intel.com> (raw)
In-Reply-To: <7df872903e16ccee9fce73b34280ede8dfc37063.1771321114.git.ashish.kalra@amd.com>
> +#define RMPOPT_TABLE_MAX_LIMIT_IN_TB 2
> +#define NUM_TB(pfn_min, pfn_max) \
> + (((pfn_max) - (pfn_min)) / (1 << (40 - PAGE_SHIFT)))
IMNHO, you should just keep these in bytes. No reason to keep them in TB.
> +struct rmpopt_socket_config {
> + unsigned long start_pfn, end_pfn;
> + cpumask_var_t cpulist;
> + int *node_id;
> + int current_node_idx;
> +};
This looks like optimization complexity before the groundwork is in
place. Also, don't we *have* CPU lists for NUMA nodes? This seems rather
redundant.
> +/*
> + * Build a cpumask of online primary threads, accounting for primary threads
> + * that have been offlined while their secondary threads are still online.
> + */
> +static void get_cpumask_of_primary_threads(cpumask_var_t cpulist)
> +{
> + cpumask_t cpus;
> + int cpu;
> +
> + cpumask_copy(&cpus, cpu_online_mask);
> + for_each_cpu(cpu, &cpus) {
> + cpumask_set_cpu(cpu, cpulist);
> + cpumask_andnot(&cpus, &cpus, cpu_smt_mask(cpu));
> + }
> +}
Don't we have a primary thread mask already? I thought we did.
> +static void __configure_rmpopt(void *val)
> +{
> + u64 rmpopt_base = ((u64)val & PUD_MASK) | MSR_AMD64_RMPOPT_ENABLE;
> +
> + wrmsrq(MSR_AMD64_RMPOPT_BASE, rmpopt_base);
> +}
I'd honestly just make the callers align the address..
> +static void configure_rmpopt_non_numa(cpumask_var_t primary_threads_cpulist)
> +{
> + on_each_cpu_mask(primary_threads_cpulist, __configure_rmpopt, (void *)0, true);
> +}
> +
> +static void free_rmpopt_socket_config(struct rmpopt_socket_config *socket)
> +{
> + int i;
> +
> + if (!socket)
> + return;
> +
> + for (i = 0; i < topology_max_packages(); i++) {
> + free_cpumask_var(socket[i].cpulist);
> + kfree(socket[i].node_id);
> + }
> +
> + kfree(socket);
> +}
> +DEFINE_FREE(free_rmpopt_socket_config, struct rmpopt_socket_config *, free_rmpopt_socket_config(_T))
Looking at all this, I really think you need a more organized series.
Make something that's _functional_ and works for all <2TB configs. Then,
go add all this NUMA complexity in a follow-on patch or patches. There's
too much going on here.
> +static void configure_rmpopt_large_physmem(cpumask_var_t primary_threads_cpulist)
> +{
> + struct rmpopt_socket_config *socket __free(free_rmpopt_socket_config) = NULL;
> + int max_packages = topology_max_packages();
> + struct rmpopt_socket_config *sc;
> + int cpu, i;
> +
> + socket = kcalloc(max_packages, sizeof(struct rmpopt_socket_config), GFP_KERNEL);
> + if (!socket)
> + return;
> +
> + for (i = 0; i < max_packages; i++) {
> + sc = &socket[i];
> + if (!zalloc_cpumask_var(&sc->cpulist, GFP_KERNEL))
> + return;
> + sc->node_id = kcalloc(nr_node_ids, sizeof(int), GFP_KERNEL);
> + if (!sc->node_id)
> + return;
> + sc->current_node_idx = -1;
> + }
> +
> + /*
> + * Handle case of virtualized NUMA software domains, such as AMD Nodes Per Socket(NPS)
> + * configurations. The kernel does not have an abstraction for physical sockets,
> + * therefore, enumerate the physical sockets and Nodes Per Socket(NPS) information by
> + * walking the online CPU list.
> + */
By this point, I've forgotten why sockets are important here.
Why are they important?
> + for_each_cpu(cpu, primary_threads_cpulist) {
> + int socket_id, nid;
> +
> + socket_id = topology_logical_package_id(cpu);
> + nid = cpu_to_node(cpu);
> + sc = &socket[socket_id];
> +
> + /*
> + * For each socket, determine the corresponding nodes and the socket's start
> + * and end PFNs.
> + * Record the node and the start and end PFNs of the first node found on the
> + * socket, then record each subsequent node and update the end PFN for that
> + * socket as additional nodes are found.
> + */
> + if (sc->current_node_idx == -1) {
> + sc->current_node_idx = 0;
> + sc->node_id[sc->current_node_idx] = nid;
> + sc->start_pfn = node_start_pfn(nid);
> + sc->end_pfn = node_end_pfn(nid);
> + } else if (sc->node_id[sc->current_node_idx] != nid) {
> + sc->current_node_idx++;
> + sc->node_id[sc->current_node_idx] = nid;
> + sc->end_pfn = node_end_pfn(nid);
> + }
> +
> + cpumask_set_cpu(cpu, sc->cpulist);
> + }
> +
> + /*
> + * If the "physical" socket has up to 2TB of memory, the per-CPU RMPOPT tables are
> + * configured to the starting physical address of the socket, otherwise the tables
> + * are configured per-node.
> + */
> + for (i = 0; i < max_packages; i++) {
> + int num_tb_socket;
> + phys_addr_t pa;
> + int j;
> +
> + sc = &socket[i];
> + num_tb_socket = NUM_TB(sc->start_pfn, sc->end_pfn) + 1;
> +
> + pr_debug("socket start_pfn 0x%lx, end_pfn 0x%lx, socket cpu mask %*pbl\n",
> + sc->start_pfn, sc->end_pfn, cpumask_pr_args(sc->cpulist));
> +
> + if (num_tb_socket <= RMPOPT_TABLE_MAX_LIMIT_IN_TB) {
> + pa = PFN_PHYS(sc->start_pfn);
> + on_each_cpu_mask(sc->cpulist, __configure_rmpopt, (void *)pa, true);
> + continue;
> + }
> +
> + for (j = 0; j <= sc->current_node_idx; j++) {
> + int nid = sc->node_id[j];
> + struct cpumask node_mask;
> +
> + cpumask_and(&node_mask, cpumask_of_node(nid), sc->cpulist);
> + pa = PFN_PHYS(node_start_pfn(nid));
> +
> + pr_debug("RMPOPT_BASE MSR on nodeid %d cpu mask %*pbl set to 0x%llx\n",
> + nid, cpumask_pr_args(&node_mask), pa);
> + on_each_cpu_mask(&node_mask, __configure_rmpopt, (void *)pa, true);
> + }
> + }
> +}
Ahh, so you're not optimizing by NUMA itself: you're assuming that there
are groups of NUMA nodes in a socket and then optimizing for those groups.
It would have been nice to say that. It would make great material for
the changelog for your broken out patches.
I have the feeling that the structure here could be one of these in a patch:
1. Support systems with <2TB of memory
2. Support a RMPOPT range per NUMA node
3. Group NUMA nodes at socket boundaries and have them share a common
RMPOPT config.
Right?
> +static __init void configure_and_enable_rmpopt(void)
> +{
> + cpumask_var_t primary_threads_cpulist;
> + int num_tb;
> +
> + if (!cpu_feature_enabled(X86_FEATURE_RMPOPT)) {
> + pr_debug("RMPOPT not supported on this platform\n");
> + return;
> + }
> +
> + if (!cc_platform_has(CC_ATTR_HOST_SEV_SNP)) {
> + pr_debug("RMPOPT optimizations not enabled as SNP support is not enabled\n");
> + return;
> + }
> +
> + if (!(rmp_cfg & MSR_AMD64_SEG_RMP_ENABLED)) {
> + pr_info("RMPOPT optimizations not enabled, segmented RMP required\n");
> + return;
> + }
> +
> + if (!zalloc_cpumask_var(&primary_threads_cpulist, GFP_KERNEL))
> + return;
> +
> + num_tb = NUM_TB(min_low_pfn, max_pfn) + 1;
> + pr_debug("NUM_TB pages in system %d\n", num_tb);
This looks wrong. Earlier, you program 0 as the base RMPOPT address into
the MSR. But this uses 'min_low_pfn'. Why not 0?
> + /* Only one thread per core needs to set RMPOPT_BASE MSR as it is per-core */
> + get_cpumask_of_primary_threads(primary_threads_cpulist);
> +
> + /*
> + * Per-CPU RMPOPT tables support at most 2 TB of addressable memory for RMP optimizations.
> + *
> + * Fastpath RMPOPT configuration and setup:
> + * For systems with <= 2 TB of RAM, configure each per-core RMPOPT base to 0,
> + * ensuring all system RAM is RMP-optimized on all CPUs.
> + */
> + if (num_tb <= RMPOPT_TABLE_MAX_LIMIT_IN_TB)
> + configure_rmpopt_non_numa(primary_threads_cpulist);
this part:
> + else
> + configure_rmpopt_large_physmem(primary_threads_cpulist);
^^ needs to be broken out into a separate optimization patch.
next prev parent reply other threads:[~2026-02-17 22:06 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-17 20:09 [PATCH 0/6] Add RMPOPT support Ashish Kalra
2026-02-17 20:09 ` [PATCH 1/6] x86/cpufeatures: Add X86_FEATURE_AMD_RMPOPT feature flag Ashish Kalra
2026-02-17 23:06 ` Ahmed S. Darwish
2026-02-17 20:10 ` [PATCH 2/6] x86/sev: add support for enabling RMPOPT Ashish Kalra
2026-02-17 22:06 ` Dave Hansen [this message]
2026-02-18 3:08 ` K Prateek Nayak
2026-02-18 14:59 ` Dave Hansen
2026-02-18 16:55 ` Kalra, Ashish
2026-02-18 17:01 ` Dave Hansen
2026-02-18 17:07 ` Kalra, Ashish
2026-02-18 17:17 ` Dave Hansen
2026-02-18 22:17 ` Kalra, Ashish
2026-02-18 22:56 ` Dave Hansen
2026-02-17 20:10 ` [PATCH 3/6] x86/sev: add support for RMPOPT instruction Ashish Kalra
2026-02-18 16:28 ` Uros Bizjak
2026-02-17 20:11 ` [PATCH 4/6] x86/sev: Add interface to re-enable RMP optimizations Ashish Kalra
2026-02-17 20:11 ` [PATCH 5/6] x86/sev: Use configfs " Ashish Kalra
2026-02-17 22:19 ` Dave Hansen
2026-02-18 3:34 ` Kalra, Ashish
2026-02-18 4:39 ` Kalra, Ashish
2026-02-18 15:10 ` Dave Hansen
2026-02-17 20:11 ` [PATCH 6/6] x86/sev: Add debugfs support for RMPOPT Ashish Kalra
2026-02-17 22:42 ` Ahmed S. Darwish
2026-02-17 22:11 ` [PATCH 0/6] Add RMPOPT support Dave Hansen
2026-02-18 4:12 ` Kalra, Ashish
2026-02-18 15:03 ` Dave Hansen
2026-02-18 17:03 ` Kalra, Ashish
2026-02-18 17:15 ` Dave Hansen
2026-02-18 21:09 ` Kalra, Ashish
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=10baddd3-add6-4771-a1ce-f759d3ec69d2@intel.com \
--to=dave.hansen@intel.com \
--cc=Ashish.Kalra@amd.com \
--cc=KPrateek.Nayak@amd.com \
--cc=Michael.Roth@amd.com \
--cc=Nathan.Fontenot@amd.com \
--cc=Tycho.Andersen@amd.com \
--cc=aik@amd.com \
--cc=ardb@kernel.org \
--cc=babu.moger@amd.com \
--cc=bp@alien8.de \
--cc=darwi@linutronix.de \
--cc=dave.hansen@linux.intel.com \
--cc=davem@davemloft.net \
--cc=dyoung@redhat.com \
--cc=herbert@gondor.apana.org.au \
--cc=hpa@zytor.com \
--cc=jackyli@google.com \
--cc=jacobhxu@google.com \
--cc=john.allen@amd.com \
--cc=kvm@vger.kernel.org \
--cc=linux-coco@lists.linux.dev \
--cc=linux-crypto@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=nikunj@amd.com \
--cc=pawan.kumar.gupta@linux.intel.com \
--cc=pbonzini@redhat.com \
--cc=peterz@infradead.org \
--cc=pgonda@google.com \
--cc=rientjes@google.com \
--cc=seanjc@google.com \
--cc=tglx@kernel.org \
--cc=thomas.lendacky@amd.com \
--cc=x86@kernel.org \
--cc=xin@zytor.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®