* [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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.