* [PATCH] x86/UV: GRU distributed mode mappings
@ 2013-05-23 15:50 Dimitri Sivanich
2013-05-28 7:59 ` Ingo Molnar
0 siblings, 1 reply; 6+ messages in thread
From: Dimitri Sivanich @ 2013-05-23 15:50 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, H. Peter Anvin, Alexander Gordeev,
Suresh Siddha
Cc: linux-kernel, x86, Russ Anderson, Mike Travis
Setup mappings for GRU distributed mode and include them as untracked
pat ranges.
Signed-off-by: Dimitri Sivanich <sivanich@sgi.com>
---
arch/x86/kernel/apic/x2apic_uv_x.c | 63 +++++++++++++++++++++++++++++----
1 file changed, 57 insertions(+), 6 deletions(-)
Index: linux/arch/x86/kernel/apic/x2apic_uv_x.c
===================================================================
--- linux.orig/arch/x86/kernel/apic/x2apic_uv_x.c
+++ linux/arch/x86/kernel/apic/x2apic_uv_x.c
@@ -51,6 +51,8 @@ DEFINE_PER_CPU(int, x2apic_extra_bits);
static enum uv_system_type uv_system_type;
static u64 gru_start_paddr, gru_end_paddr;
+static u64 gru_dist_base, gru_first_node_paddr = -1LL, gru_last_node_paddr;
+static u64 gru_dist_lmask, gru_dist_umask;
static union uvh_apicid uvh_apicid;
int uv_min_hub_revision_id;
EXPORT_SYMBOL_GPL(uv_min_hub_revision_id);
@@ -72,7 +74,19 @@ static unsigned long __init uv_early_rea
static inline bool is_GRU_range(u64 start, u64 end)
{
- return start >= gru_start_paddr && end <= gru_end_paddr;
+ if (gru_dist_base) {
+ u64 su = start & gru_dist_umask; /* upper (incl pnode) bits */
+ u64 sl = start & gru_dist_lmask; /* base offset bits */
+ u64 eu = end & gru_dist_umask;
+ u64 el = end & gru_dist_lmask;
+
+ /* Must reside completely within a single GRU range */
+ return (sl == gru_dist_base && el == gru_dist_base &&
+ su >= gru_first_node_paddr &&
+ su <= gru_last_node_paddr &&
+ eu == su);
+ } else
+ return start >= gru_start_paddr && end <= gru_end_paddr;
}
static bool uv_is_untracked_pat_range(u64 start, u64 end)
@@ -470,19 +484,56 @@ static __init void map_high(char *id, un
init_extra_mapping_wb(paddr, bytes);
}
+static __init void map_gru_distributed(unsigned long c)
+{
+ union uvh_rh_gam_gru_overlay_config_mmr_u gru;
+ u64 paddr;
+ unsigned long bytes;
+ int nid;
+
+ gru.v = c;
+ /* only base bits 42:28 relevant in dist mode */
+ gru_dist_base = gru.v & 0x000007fff0000000UL;
+ if (!gru_dist_base) {
+ pr_info("UV: Map GRU_DIST base address NULL\n");
+ return;
+ }
+ bytes = 1UL << UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_SHFT;
+ gru_dist_lmask = ((1UL << uv_hub_info->m_val) - 1) & ~(bytes - 1);
+ gru_dist_umask = ~((1UL << uv_hub_info->m_val) - 1);
+ gru_dist_base &= gru_dist_lmask; /* Clear bits above M */
+ for_each_online_node(nid) {
+ paddr = ((u64)uv_node_to_pnode(nid) << uv_hub_info->m_val) |
+ gru_dist_base;
+ init_extra_mapping_wb(paddr, bytes);
+ gru_first_node_paddr = min(paddr, gru_first_node_paddr);
+ gru_last_node_paddr = max(paddr, gru_last_node_paddr);
+ }
+ /* Save upper (63:M) bits of address only for is_GRU_range */
+ gru_first_node_paddr &= gru_dist_umask;
+ gru_last_node_paddr &= gru_dist_umask;
+ pr_info("UV: Map GRU_DIST base 0x%016llx 0x%016llx - 0x%016llx\n",
+ gru_dist_base, gru_first_node_paddr, gru_last_node_paddr);
+}
+
static __init void map_gru_high(int max_pnode)
{
union uvh_rh_gam_gru_overlay_config_mmr_u gru;
int shift = UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_SHFT;
gru.v = uv_read_local_mmr(UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR);
- if (gru.s.enable) {
- map_high("GRU", gru.s.base, shift, shift, max_pnode, map_wb);
- gru_start_paddr = ((u64)gru.s.base << shift);
- gru_end_paddr = gru_start_paddr + (1UL << shift) * (max_pnode + 1);
- } else {
+ if (!gru.s.enable) {
pr_info("UV: GRU disabled\n");
+ return;
+ }
+
+ if (is_uv3_hub() && gru.s3.mode) {
+ map_gru_distributed(gru.v);
+ return;
}
+ map_high("GRU", gru.s.base, shift, shift, max_pnode, map_wb);
+ gru_start_paddr = ((u64)gru.s.base << shift);
+ gru_end_paddr = gru_start_paddr + (1UL << shift) * (max_pnode + 1);
}
static __init void map_mmr_high(int max_pnode)
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] x86/UV: GRU distributed mode mappings
2013-05-23 15:50 [PATCH] x86/UV: GRU distributed mode mappings Dimitri Sivanich
@ 2013-05-28 7:59 ` Ingo Molnar
2013-05-28 13:41 ` Dimitri Sivanich
0 siblings, 1 reply; 6+ messages in thread
From: Ingo Molnar @ 2013-05-28 7:59 UTC (permalink / raw)
To: Dimitri Sivanich
Cc: Thomas Gleixner, Ingo Molnar, H. Peter Anvin, Alexander Gordeev,
Suresh Siddha, linux-kernel, x86, Russ Anderson, Mike Travis
* Dimitri Sivanich <sivanich@sgi.com> wrote:
> Setup mappings for GRU distributed mode and include them as untracked
> pat ranges.
Would be nice to have the customary changelog content:
" Current code does (A), this has a problem when (B).
We can improve this doing (C), because (D)."
Or so - your changelog is pretty light on the 'why' aspect.
Thanks,
Ingo
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] x86/UV: GRU distributed mode mappings
2013-05-28 7:59 ` Ingo Molnar
@ 2013-05-28 13:41 ` Dimitri Sivanich
2013-05-29 8:15 ` Ingo Molnar
0 siblings, 1 reply; 6+ messages in thread
From: Dimitri Sivanich @ 2013-05-28 13:41 UTC (permalink / raw)
To: Ingo Molnar
Cc: Thomas Gleixner, Ingo Molnar, H. Peter Anvin, Alexander Gordeev,
Suresh Siddha, linux-kernel, x86, Russ Anderson, Mike Travis
On Tue, May 28, 2013 at 09:59:12AM +0200, Ingo Molnar wrote:
>
> * Dimitri Sivanich <sivanich@sgi.com> wrote:
>
> > Setup mappings for GRU distributed mode and include them as untracked
> > pat ranges.
>
> Would be nice to have the customary changelog content:
>
> " Current code does (A), this has a problem when (B).
> We can improve this doing (C), because (D)."
>
> Or so - your changelog is pretty light on the 'why' aspect.
>
How about the following?
UV GRU hardware will support an optional distributed mode that will allow
per-node address mapping of local GRU space, as opposed to mapping all GRU
hardware to the same contiguous high space.
If GRU distributed mode is selected, setup per-node page table mappings and
include them as untracked pat ranges.
Signed-off-by: Dimitri Sivanich <sivanich@sgi.com>
---
arch/x86/kernel/apic/x2apic_uv_x.c | 63 +++++++++++++++++++++++++++++----
1 file changed, 57 insertions(+), 6 deletions(-)
Index: linux/arch/x86/kernel/apic/x2apic_uv_x.c
===================================================================
--- linux.orig/arch/x86/kernel/apic/x2apic_uv_x.c
+++ linux/arch/x86/kernel/apic/x2apic_uv_x.c
@@ -51,6 +51,8 @@ DEFINE_PER_CPU(int, x2apic_extra_bits);
static enum uv_system_type uv_system_type;
static u64 gru_start_paddr, gru_end_paddr;
+static u64 gru_dist_base, gru_first_node_paddr = -1LL, gru_last_node_paddr;
+static u64 gru_dist_lmask, gru_dist_umask;
static union uvh_apicid uvh_apicid;
int uv_min_hub_revision_id;
EXPORT_SYMBOL_GPL(uv_min_hub_revision_id);
@@ -72,7 +74,19 @@ static unsigned long __init uv_early_rea
static inline bool is_GRU_range(u64 start, u64 end)
{
- return start >= gru_start_paddr && end <= gru_end_paddr;
+ if (gru_dist_base) {
+ u64 su = start & gru_dist_umask; /* upper (incl pnode) bits */
+ u64 sl = start & gru_dist_lmask; /* base offset bits */
+ u64 eu = end & gru_dist_umask;
+ u64 el = end & gru_dist_lmask;
+
+ /* Must reside completely within a single GRU range */
+ return (sl == gru_dist_base && el == gru_dist_base &&
+ su >= gru_first_node_paddr &&
+ su <= gru_last_node_paddr &&
+ eu == su);
+ } else
+ return start >= gru_start_paddr && end <= gru_end_paddr;
}
static bool uv_is_untracked_pat_range(u64 start, u64 end)
@@ -470,19 +484,56 @@ static __init void map_high(char *id, un
init_extra_mapping_wb(paddr, bytes);
}
+static __init void map_gru_distributed(unsigned long c)
+{
+ union uvh_rh_gam_gru_overlay_config_mmr_u gru;
+ u64 paddr;
+ unsigned long bytes;
+ int nid;
+
+ gru.v = c;
+ /* only base bits 42:28 relevant in dist mode */
+ gru_dist_base = gru.v & 0x000007fff0000000UL;
+ if (!gru_dist_base) {
+ pr_info("UV: Map GRU_DIST base address NULL\n");
+ return;
+ }
+ bytes = 1UL << UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_SHFT;
+ gru_dist_lmask = ((1UL << uv_hub_info->m_val) - 1) & ~(bytes - 1);
+ gru_dist_umask = ~((1UL << uv_hub_info->m_val) - 1);
+ gru_dist_base &= gru_dist_lmask; /* Clear bits above M */
+ for_each_online_node(nid) {
+ paddr = ((u64)uv_node_to_pnode(nid) << uv_hub_info->m_val) |
+ gru_dist_base;
+ init_extra_mapping_wb(paddr, bytes);
+ gru_first_node_paddr = min(paddr, gru_first_node_paddr);
+ gru_last_node_paddr = max(paddr, gru_last_node_paddr);
+ }
+ /* Save upper (63:M) bits of address only for is_GRU_range */
+ gru_first_node_paddr &= gru_dist_umask;
+ gru_last_node_paddr &= gru_dist_umask;
+ pr_info("UV: Map GRU_DIST base 0x%016llx 0x%016llx - 0x%016llx\n",
+ gru_dist_base, gru_first_node_paddr, gru_last_node_paddr);
+}
+
static __init void map_gru_high(int max_pnode)
{
union uvh_rh_gam_gru_overlay_config_mmr_u gru;
int shift = UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_SHFT;
gru.v = uv_read_local_mmr(UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR);
- if (gru.s.enable) {
- map_high("GRU", gru.s.base, shift, shift, max_pnode, map_wb);
- gru_start_paddr = ((u64)gru.s.base << shift);
- gru_end_paddr = gru_start_paddr + (1UL << shift) * (max_pnode + 1);
- } else {
+ if (!gru.s.enable) {
pr_info("UV: GRU disabled\n");
+ return;
+ }
+
+ if (is_uv3_hub() && gru.s3.mode) {
+ map_gru_distributed(gru.v);
+ return;
}
+ map_high("GRU", gru.s.base, shift, shift, max_pnode, map_wb);
+ gru_start_paddr = ((u64)gru.s.base << shift);
+ gru_end_paddr = gru_start_paddr + (1UL << shift) * (max_pnode + 1);
}
static __init void map_mmr_high(int max_pnode)
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] x86/UV: GRU distributed mode mappings
2013-05-28 13:41 ` Dimitri Sivanich
@ 2013-05-29 8:15 ` Ingo Molnar
2013-05-29 15:56 ` Dimitri Sivanich
0 siblings, 1 reply; 6+ messages in thread
From: Ingo Molnar @ 2013-05-29 8:15 UTC (permalink / raw)
To: Dimitri Sivanich
Cc: Thomas Gleixner, Ingo Molnar, H. Peter Anvin, Alexander Gordeev,
Suresh Siddha, linux-kernel, x86, Russ Anderson, Mike Travis
* Dimitri Sivanich <sivanich@sgi.com> wrote:
> On Tue, May 28, 2013 at 09:59:12AM +0200, Ingo Molnar wrote:
> >
> > * Dimitri Sivanich <sivanich@sgi.com> wrote:
> >
> > > Setup mappings for GRU distributed mode and include them as untracked
> > > pat ranges.
> >
> > Would be nice to have the customary changelog content:
> >
> > " Current code does (A), this has a problem when (B).
> > We can improve this doing (C), because (D)."
> >
> > Or so - your changelog is pretty light on the 'why' aspect.
> >
> How about the following?
Looks good to me.
> UV GRU hardware will support an optional distributed mode that will allow
> per-node address mapping of local GRU space, as opposed to mapping all GRU
> hardware to the same contiguous high space.
>
> If GRU distributed mode is selected, setup per-node page table mappings and
> include them as untracked pat ranges.
>
> Signed-off-by: Dimitri Sivanich <sivanich@sgi.com>
> ---
> arch/x86/kernel/apic/x2apic_uv_x.c | 63 +++++++++++++++++++++++++++++----
> 1 file changed, 57 insertions(+), 6 deletions(-)
So this looks like suitable v3.11 material - not an urgent fix needed for
v3.10, right?
Noticed this detail:
> + } else
> + return start >= gru_start_paddr && end <= gru_end_paddr;
in the kernel we generally try to balance curly braces - either all
branches are curly or none.
> + /* Save upper (63:M) bits of address only for is_GRU_range */
> + gru_first_node_paddr &= gru_dist_umask;
> + gru_last_node_paddr &= gru_dist_umask;
> + pr_info("UV: Map GRU_DIST base 0x%016llx 0x%016llx - 0x%016llx\n",
> + gru_dist_base, gru_first_node_paddr, gru_last_node_paddr);
I suspect this should be pr_debug()?
Thanks,
Ingo
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] x86/UV: GRU distributed mode mappings
2013-05-29 8:15 ` Ingo Molnar
@ 2013-05-29 15:56 ` Dimitri Sivanich
2013-05-31 12:26 ` [tip:x86/uv] x86/UV: Add " tip-bot for Dimitri Sivanich
0 siblings, 1 reply; 6+ messages in thread
From: Dimitri Sivanich @ 2013-05-29 15:56 UTC (permalink / raw)
To: Ingo Molnar
Cc: Thomas Gleixner, Ingo Molnar, H. Peter Anvin, Alexander Gordeev,
Suresh Siddha, linux-kernel, x86, Russ Anderson, Mike Travis
On Wed, May 29, 2013 at 10:15:39AM +0200, Ingo Molnar wrote:
>
> So this looks like suitable v3.11 material - not an urgent fix needed for
> v3.10, right?
Correct, v3.11 is fine.
>
> Noticed this detail:
>
> > + } else
> > + return start >= gru_start_paddr && end <= gru_end_paddr;
>
> in the kernel we generally try to balance curly braces - either all
> branches are curly or none.
Fixed, see patch below.
>
> > + /* Save upper (63:M) bits of address only for is_GRU_range */
> > + gru_first_node_paddr &= gru_dist_umask;
> > + gru_last_node_paddr &= gru_dist_umask;
> > + pr_info("UV: Map GRU_DIST base 0x%016llx 0x%016llx - 0x%016llx\n",
> > + gru_dist_base, gru_first_node_paddr, gru_last_node_paddr);
>
> I suspect this should be pr_debug()?
>
I had set it to what was being used in map_high(), but pr_debug should be OK,
so I changed both instances.
GRU hardware will support an optional distributed mode that will allow
per-node address mapping of local GRU space, as opposed to mapping all GRU
hardware to the same contiguous high space.
If GRU distributed mode is selected, setup per-node page table mappings.
Signed-off-by: Dimitri Sivanich <sivanich@sgi.com>
---
arch/x86/kernel/apic/x2apic_uv_x.c | 66 +++++++++++++++++++++++++++++----
1 file changed, 59 insertions(+), 7 deletions(-)
Index: linux/arch/x86/kernel/apic/x2apic_uv_x.c
===================================================================
--- linux.orig/arch/x86/kernel/apic/x2apic_uv_x.c
+++ linux/arch/x86/kernel/apic/x2apic_uv_x.c
@@ -51,6 +51,8 @@ DEFINE_PER_CPU(int, x2apic_extra_bits);
static enum uv_system_type uv_system_type;
static u64 gru_start_paddr, gru_end_paddr;
+static u64 gru_dist_base, gru_first_node_paddr = -1LL, gru_last_node_paddr;
+static u64 gru_dist_lmask, gru_dist_umask;
static union uvh_apicid uvh_apicid;
int uv_min_hub_revision_id;
EXPORT_SYMBOL_GPL(uv_min_hub_revision_id);
@@ -72,7 +74,20 @@ static unsigned long __init uv_early_rea
static inline bool is_GRU_range(u64 start, u64 end)
{
- return start >= gru_start_paddr && end <= gru_end_paddr;
+ if (gru_dist_base) {
+ u64 su = start & gru_dist_umask; /* upper (incl pnode) bits */
+ u64 sl = start & gru_dist_lmask; /* base offset bits */
+ u64 eu = end & gru_dist_umask;
+ u64 el = end & gru_dist_lmask;
+
+ /* Must reside completely within a single GRU range */
+ return (sl == gru_dist_base && el == gru_dist_base &&
+ su >= gru_first_node_paddr &&
+ su <= gru_last_node_paddr &&
+ eu == su);
+ } else {
+ return start >= gru_start_paddr && end <= gru_end_paddr;
+ }
}
static bool uv_is_untracked_pat_range(u64 start, u64 end)
@@ -463,26 +478,63 @@ static __init void map_high(char *id, un
pr_info("UV: Map %s_HI base address NULL\n", id);
return;
}
- pr_info("UV: Map %s_HI 0x%lx - 0x%lx\n", id, paddr, paddr + bytes);
+ pr_debug("UV: Map %s_HI 0x%lx - 0x%lx\n", id, paddr, paddr + bytes);
if (map_type == map_uc)
init_extra_mapping_uc(paddr, bytes);
else
init_extra_mapping_wb(paddr, bytes);
}
+static __init void map_gru_distributed(unsigned long c)
+{
+ union uvh_rh_gam_gru_overlay_config_mmr_u gru;
+ u64 paddr;
+ unsigned long bytes;
+ int nid;
+
+ gru.v = c;
+ /* only base bits 42:28 relevant in dist mode */
+ gru_dist_base = gru.v & 0x000007fff0000000UL;
+ if (!gru_dist_base) {
+ pr_info("UV: Map GRU_DIST base address NULL\n");
+ return;
+ }
+ bytes = 1UL << UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_SHFT;
+ gru_dist_lmask = ((1UL << uv_hub_info->m_val) - 1) & ~(bytes - 1);
+ gru_dist_umask = ~((1UL << uv_hub_info->m_val) - 1);
+ gru_dist_base &= gru_dist_lmask; /* Clear bits above M */
+ for_each_online_node(nid) {
+ paddr = ((u64)uv_node_to_pnode(nid) << uv_hub_info->m_val) |
+ gru_dist_base;
+ init_extra_mapping_wb(paddr, bytes);
+ gru_first_node_paddr = min(paddr, gru_first_node_paddr);
+ gru_last_node_paddr = max(paddr, gru_last_node_paddr);
+ }
+ /* Save upper (63:M) bits of address only for is_GRU_range */
+ gru_first_node_paddr &= gru_dist_umask;
+ gru_last_node_paddr &= gru_dist_umask;
+ pr_debug("UV: Map GRU_DIST base 0x%016llx 0x%016llx - 0x%016llx\n",
+ gru_dist_base, gru_first_node_paddr, gru_last_node_paddr);
+}
+
static __init void map_gru_high(int max_pnode)
{
union uvh_rh_gam_gru_overlay_config_mmr_u gru;
int shift = UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_SHFT;
gru.v = uv_read_local_mmr(UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR);
- if (gru.s.enable) {
- map_high("GRU", gru.s.base, shift, shift, max_pnode, map_wb);
- gru_start_paddr = ((u64)gru.s.base << shift);
- gru_end_paddr = gru_start_paddr + (1UL << shift) * (max_pnode + 1);
- } else {
+ if (!gru.s.enable) {
pr_info("UV: GRU disabled\n");
+ return;
+ }
+
+ if (is_uv3_hub() && gru.s3.mode) {
+ map_gru_distributed(gru.v);
+ return;
}
+ map_high("GRU", gru.s.base, shift, shift, max_pnode, map_wb);
+ gru_start_paddr = ((u64)gru.s.base << shift);
+ gru_end_paddr = gru_start_paddr + (1UL << shift) * (max_pnode + 1);
}
static __init void map_mmr_high(int max_pnode)
^ permalink raw reply [flat|nested] 6+ messages in thread
* [tip:x86/uv] x86/UV: Add GRU distributed mode mappings
2013-05-29 15:56 ` Dimitri Sivanich
@ 2013-05-31 12:26 ` tip-bot for Dimitri Sivanich
0 siblings, 0 replies; 6+ messages in thread
From: tip-bot for Dimitri Sivanich @ 2013-05-31 12:26 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, agordeev, hpa, mingo, travis, sivanich, rja,
suresh.b.siddha, tglx
Commit-ID: 879d5ad0dc3b096170c8f985b1465de5dca88de8
Gitweb: http://git.kernel.org/tip/879d5ad0dc3b096170c8f985b1465de5dca88de8
Author: Dimitri Sivanich <sivanich@sgi.com>
AuthorDate: Wed, 29 May 2013 10:56:09 -0500
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Thu, 30 May 2013 09:46:09 +0200
x86/UV: Add GRU distributed mode mappings
GRU hardware will support an optional distributed mode that will
allow per-node address mapping of local GRU space, as opposed
to mapping all GRU hardware to the same contiguous high space.
If GRU distributed mode is selected, setup per-node page table
mappings.
Signed-off-by: Dimitri Sivanich <sivanich@sgi.com>
Cc: Alexander Gordeev <agordeev@redhat.com>
Cc: Suresh Siddha <suresh.b.siddha@intel.com>
Cc: Russ Anderson <rja@sgi.com>
Cc: Mike Travis <travis@sgi.com>
Link: http://lkml.kernel.org/r/20130529155609.GB22917@sgi.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
arch/x86/kernel/apic/x2apic_uv_x.c | 66 ++++++++++++++++++++++++++++++++++----
1 file changed, 59 insertions(+), 7 deletions(-)
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c
index 794f6eb..39cc7f7 100644
--- a/arch/x86/kernel/apic/x2apic_uv_x.c
+++ b/arch/x86/kernel/apic/x2apic_uv_x.c
@@ -51,6 +51,8 @@ DEFINE_PER_CPU(int, x2apic_extra_bits);
static enum uv_system_type uv_system_type;
static u64 gru_start_paddr, gru_end_paddr;
+static u64 gru_dist_base, gru_first_node_paddr = -1LL, gru_last_node_paddr;
+static u64 gru_dist_lmask, gru_dist_umask;
static union uvh_apicid uvh_apicid;
int uv_min_hub_revision_id;
EXPORT_SYMBOL_GPL(uv_min_hub_revision_id);
@@ -72,7 +74,20 @@ static unsigned long __init uv_early_read_mmr(unsigned long addr)
static inline bool is_GRU_range(u64 start, u64 end)
{
- return start >= gru_start_paddr && end <= gru_end_paddr;
+ if (gru_dist_base) {
+ u64 su = start & gru_dist_umask; /* upper (incl pnode) bits */
+ u64 sl = start & gru_dist_lmask; /* base offset bits */
+ u64 eu = end & gru_dist_umask;
+ u64 el = end & gru_dist_lmask;
+
+ /* Must reside completely within a single GRU range */
+ return (sl == gru_dist_base && el == gru_dist_base &&
+ su >= gru_first_node_paddr &&
+ su <= gru_last_node_paddr &&
+ eu == su);
+ } else {
+ return start >= gru_start_paddr && end <= gru_end_paddr;
+ }
}
static bool uv_is_untracked_pat_range(u64 start, u64 end)
@@ -463,26 +478,63 @@ static __init void map_high(char *id, unsigned long base, int pshift,
pr_info("UV: Map %s_HI base address NULL\n", id);
return;
}
- pr_info("UV: Map %s_HI 0x%lx - 0x%lx\n", id, paddr, paddr + bytes);
+ pr_debug("UV: Map %s_HI 0x%lx - 0x%lx\n", id, paddr, paddr + bytes);
if (map_type == map_uc)
init_extra_mapping_uc(paddr, bytes);
else
init_extra_mapping_wb(paddr, bytes);
}
+static __init void map_gru_distributed(unsigned long c)
+{
+ union uvh_rh_gam_gru_overlay_config_mmr_u gru;
+ u64 paddr;
+ unsigned long bytes;
+ int nid;
+
+ gru.v = c;
+ /* only base bits 42:28 relevant in dist mode */
+ gru_dist_base = gru.v & 0x000007fff0000000UL;
+ if (!gru_dist_base) {
+ pr_info("UV: Map GRU_DIST base address NULL\n");
+ return;
+ }
+ bytes = 1UL << UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_SHFT;
+ gru_dist_lmask = ((1UL << uv_hub_info->m_val) - 1) & ~(bytes - 1);
+ gru_dist_umask = ~((1UL << uv_hub_info->m_val) - 1);
+ gru_dist_base &= gru_dist_lmask; /* Clear bits above M */
+ for_each_online_node(nid) {
+ paddr = ((u64)uv_node_to_pnode(nid) << uv_hub_info->m_val) |
+ gru_dist_base;
+ init_extra_mapping_wb(paddr, bytes);
+ gru_first_node_paddr = min(paddr, gru_first_node_paddr);
+ gru_last_node_paddr = max(paddr, gru_last_node_paddr);
+ }
+ /* Save upper (63:M) bits of address only for is_GRU_range */
+ gru_first_node_paddr &= gru_dist_umask;
+ gru_last_node_paddr &= gru_dist_umask;
+ pr_debug("UV: Map GRU_DIST base 0x%016llx 0x%016llx - 0x%016llx\n",
+ gru_dist_base, gru_first_node_paddr, gru_last_node_paddr);
+}
+
static __init void map_gru_high(int max_pnode)
{
union uvh_rh_gam_gru_overlay_config_mmr_u gru;
int shift = UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_SHFT;
gru.v = uv_read_local_mmr(UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR);
- if (gru.s.enable) {
- map_high("GRU", gru.s.base, shift, shift, max_pnode, map_wb);
- gru_start_paddr = ((u64)gru.s.base << shift);
- gru_end_paddr = gru_start_paddr + (1UL << shift) * (max_pnode + 1);
- } else {
+ if (!gru.s.enable) {
pr_info("UV: GRU disabled\n");
+ return;
+ }
+
+ if (is_uv3_hub() && gru.s3.mode) {
+ map_gru_distributed(gru.v);
+ return;
}
+ map_high("GRU", gru.s.base, shift, shift, max_pnode, map_wb);
+ gru_start_paddr = ((u64)gru.s.base << shift);
+ gru_end_paddr = gru_start_paddr + (1UL << shift) * (max_pnode + 1);
}
static __init void map_mmr_high(int max_pnode)
^ permalink raw reply related [flat|nested] 6+ messages in thread
end of thread, other threads:[~2013-05-31 12:27 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-05-23 15:50 [PATCH] x86/UV: GRU distributed mode mappings Dimitri Sivanich
2013-05-28 7:59 ` Ingo Molnar
2013-05-28 13:41 ` Dimitri Sivanich
2013-05-29 8:15 ` Ingo Molnar
2013-05-29 15:56 ` Dimitri Sivanich
2013-05-31 12:26 ` [tip:x86/uv] x86/UV: Add " tip-bot for Dimitri Sivanich
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).