All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2] Virtual memory size detection for 64 bit MIPS CPUs
@ 2010-02-01 21:00 Guenter Roeck
  2010-02-01 21:42 ` David Daney
  0 siblings, 1 reply; 6+ messages in thread
From: Guenter Roeck @ 2010-02-01 21:00 UTC (permalink / raw)
  To: linux-mips; +Cc: Guenter Roeck

Linux kernel 2.6.32 and later allocates memory from the top of virtual memory
space.

This patch implements virtual memory size detection for 64 bit MIPS CPUs
to avoid resulting crashes.

Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com>
---
 arch/mips/include/asm/cpu-features.h |    3 +++
 arch/mips/include/asm/cpu-info.h     |    1 +
 arch/mips/include/asm/pgtable-64.h   |    4 +++-
 arch/mips/kernel/cpu-probe.c         |   22 ++++++++++++++++++++++
 4 files changed, 29 insertions(+), 1 deletions(-)

diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h
index 1f4df64..284eb55 100644
--- a/arch/mips/include/asm/cpu-features.h
+++ b/arch/mips/include/asm/cpu-features.h
@@ -209,6 +209,9 @@
 # ifndef cpu_has_64bit_addresses
 # define cpu_has_64bit_addresses	1
 # endif
+# ifndef cpu_vmbits
+# define cpu_vmbits cpu_data[0].vmbits
+# endif
 #endif
 
 #if defined(CONFIG_CPU_MIPSR2_IRQ_VI) && !defined(cpu_has_vint)
diff --git a/arch/mips/include/asm/cpu-info.h b/arch/mips/include/asm/cpu-info.h
index 1260443..3c694bc 100644
--- a/arch/mips/include/asm/cpu-info.h
+++ b/arch/mips/include/asm/cpu-info.h
@@ -58,6 +58,7 @@ struct cpuinfo_mips {
 	struct cache_desc	tcache;	/* Tertiary/split secondary cache */
 	int			srsets;	/* Shadow register sets */
 	int			core;	/* physical core number */
+	int			vmbits;	/* Virtual memory size in bits */
 #if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_MIPS_MT_SMTC)
 	/*
 	 * In the MIPS MT "SMTC" model, each TC is considered
diff --git a/arch/mips/include/asm/pgtable-64.h b/arch/mips/include/asm/pgtable-64.h
index 9cd5089..259ec58 100644
--- a/arch/mips/include/asm/pgtable-64.h
+++ b/arch/mips/include/asm/pgtable-64.h
@@ -110,7 +110,9 @@
 #define VMALLOC_START		MAP_BASE
 #define VMALLOC_END	\
 	(VMALLOC_START + \
-	 PTRS_PER_PGD * PTRS_PER_PMD * PTRS_PER_PTE * PAGE_SIZE - (1UL << 32))
+	 min(PTRS_PER_PGD * PTRS_PER_PMD * PTRS_PER_PTE * PAGE_SIZE, \
+	     (1UL<<cpu_vmbits)) - (1UL << 32))
+
 #if defined(CONFIG_MODULES) && defined(KBUILD_64BIT_SYM32) && \
 	VMALLOC_START != CKSSEG
 /* Load modules into 32bit-compatible segment. */
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 7a51866..1286b0e 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -282,6 +282,26 @@ static inline int __cpu_has_fpu(void)
 	return ((cpu_get_fpu_id() & 0xff00) != FPIR_IMP_NONE);
 }
 
+static inline void cpu_set_vmbits(struct cpuinfo_mips *c)
+{
+	if (cpu_has_64bits) {
+		unsigned long zbits;
+
+		asm volatile(".set mips64\n"
+			     "and %0, 0\n"
+			     "dsubu %0, 1\n"
+			     "dmtc0 %0, $10, 0\n"
+			     "dmfc0 %0, $10, 0\n"
+			     "dsll %0, %0, 2\n"
+			     "dsra %0, %0, 2\n"
+			     "dclz %0, %0\n"
+			     ".set mips0\n"
+			     : "=r" (zbits));
+		c->vmbits = 64 - zbits;
+	} else
+		c->vmbits = 32;
+}
+
 #define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE \
 		| MIPS_CPU_COUNTER)
 
@@ -967,6 +987,8 @@ __cpuinit void cpu_probe(void)
 		c->srsets = ((read_c0_srsctl() >> 26) & 0x0f) + 1;
 	else
 		c->srsets = 1;
+
+	cpu_set_vmbits(c);
 }
 
 __cpuinit void cpu_report(void)
-- 
1.6.0.4

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v2] Virtual memory size detection for 64 bit MIPS CPUs
  2010-02-01 21:00 [PATCH v2] Virtual memory size detection for 64 bit MIPS CPUs Guenter Roeck
@ 2010-02-01 21:42 ` David Daney
  2010-02-01 22:04   ` Guenter Roeck
  0 siblings, 1 reply; 6+ messages in thread
From: David Daney @ 2010-02-01 21:42 UTC (permalink / raw)
  To: Guenter Roeck; +Cc: linux-mips

Guenter Roeck wrote:
[...]
>  
> +static inline void cpu_set_vmbits(struct cpuinfo_mips *c)
> +{
> +	if (cpu_has_64bits) {
> +		unsigned long zbits;
> +
> +		asm volatile(".set mips64\n"
> +			     "and %0, 0\n"
> +			     "dsubu %0, 1\n"
> +			     "dmtc0 %0, $10, 0\n"
> +			     "dmfc0 %0, $10, 0\n"
> +			     "dsll %0, %0, 2\n"
> +			     "dsra %0, %0, 2\n"
> +			     "dclz %0, %0\n"
> +			     ".set mips0\n"
> +			     : "=r" (zbits));
> +		c->vmbits = 64 - zbits;
> +	} else
> +		c->vmbits = 32;
> +}
> +

It should be possible to express this in 'pure' C using 
read_c0_entryhi()/write_c0_entryhi(), also you need to be sure you are 
not writing 1s to any reserved bits of the register.


David Daney

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2] Virtual memory size detection for 64 bit MIPS CPUs
  2010-02-01 21:42 ` David Daney
@ 2010-02-01 22:04   ` Guenter Roeck
  2010-02-01 22:12     ` David Daney
  2010-02-01 22:39     ` Maciej W. Rozycki
  0 siblings, 2 replies; 6+ messages in thread
From: Guenter Roeck @ 2010-02-01 22:04 UTC (permalink / raw)
  To: David Daney; +Cc: linux-mips@linux-mips.org

On Mon, 2010-02-01 at 16:42 -0500, David Daney wrote:
> Guenter Roeck wrote:
> [...]
> >  
> > +static inline void cpu_set_vmbits(struct cpuinfo_mips *c)
> > +{
> > +	if (cpu_has_64bits) {
> > +		unsigned long zbits;
> > +
> > +		asm volatile(".set mips64\n"
> > +			     "and %0, 0\n"
> > +			     "dsubu %0, 1\n"
> > +			     "dmtc0 %0, $10, 0\n"
> > +			     "dmfc0 %0, $10, 0\n"
> > +			     "dsll %0, %0, 2\n"
> > +			     "dsra %0, %0, 2\n"
> > +			     "dclz %0, %0\n"
> > +			     ".set mips0\n"
> > +			     : "=r" (zbits));
> > +		c->vmbits = 64 - zbits;
> > +	} else
> > +		c->vmbits = 32;
> > +}
> > +
> 
> It should be possible to express this in 'pure' C using 
> read_c0_entryhi()/write_c0_entryhi(), also you need to be sure you are 

Sure, no problem.

> not writing 1s to any reserved bits of the register.
> 
That may be tricky, since the upper bits are reserved in some
architectures. For example, the 20Kc core specification says that bits
61:40 are reserved and must be written with 0.

I can write, say, 0x3fffffffffff0000 to avoid writing into lower
reserved bits, but that won't help for any upper reserved bits. Would
that be acceptable / better ?

Guenter

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2] Virtual memory size detection for 64 bit MIPS CPUs
  2010-02-01 22:04   ` Guenter Roeck
@ 2010-02-01 22:12     ` David Daney
  2010-02-01 22:34       ` Guenter Roeck
  2010-02-01 22:39     ` Maciej W. Rozycki
  1 sibling, 1 reply; 6+ messages in thread
From: David Daney @ 2010-02-01 22:12 UTC (permalink / raw)
  To: guenter.roeck; +Cc: linux-mips@linux-mips.org

Guenter Roeck wrote:
> On Mon, 2010-02-01 at 16:42 -0500, David Daney wrote:
>> Guenter Roeck wrote:
>> [...]
>>>  
>>> +static inline void cpu_set_vmbits(struct cpuinfo_mips *c)
>>> +{
>>> +	if (cpu_has_64bits) {
>>> +		unsigned long zbits;
>>> +
>>> +		asm volatile(".set mips64\n"
>>> +			     "and %0, 0\n"
>>> +			     "dsubu %0, 1\n"
>>> +			     "dmtc0 %0, $10, 0\n"
>>> +			     "dmfc0 %0, $10, 0\n"
>>> +			     "dsll %0, %0, 2\n"
>>> +			     "dsra %0, %0, 2\n"
>>> +			     "dclz %0, %0\n"
>>> +			     ".set mips0\n"
>>> +			     : "=r" (zbits));
>>> +		c->vmbits = 64 - zbits;
>>> +	} else
>>> +		c->vmbits = 32;
>>> +}
>>> +
>> It should be possible to express this in 'pure' C using 
>> read_c0_entryhi()/write_c0_entryhi(), also you need to be sure you are 
> 
> Sure, no problem.
> 
>> not writing 1s to any reserved bits of the register.
>>
> That may be tricky, since the upper bits are reserved in some
> architectures. For example, the 20Kc core specification says that bits
> 61:40 are reserved and must be written with 0.
> 
> I can write, say, 0x3fffffffffff0000 to avoid writing into lower
> reserved bits, but that won't help for any upper reserved bits. Would
> that be acceptable / better ?


The MIPS64® Privileged Resource Architecture manual might be a better 
reference.

I would set 1s only in bits 13-63 (the VPN2 and R fields).  We don't 
support and don't really care about VPN2X, the upper bits are really the 
only ones of interest here.

David Daney

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2] Virtual memory size detection for 64 bit MIPS CPUs
  2010-02-01 22:12     ` David Daney
@ 2010-02-01 22:34       ` Guenter Roeck
  0 siblings, 0 replies; 6+ messages in thread
From: Guenter Roeck @ 2010-02-01 22:34 UTC (permalink / raw)
  To: David Daney; +Cc: linux-mips@linux-mips.org

On Mon, 2010-02-01 at 17:12 -0500, David Daney wrote:
> Guenter Roeck wrote:
> > On Mon, 2010-02-01 at 16:42 -0500, David Daney wrote:
> >> Guenter Roeck wrote:
> >> [...]
> >>>  
> >>> +static inline void cpu_set_vmbits(struct cpuinfo_mips *c)
> >>> +{
> >>> +	if (cpu_has_64bits) {
> >>> +		unsigned long zbits;
> >>> +
> >>> +		asm volatile(".set mips64\n"
> >>> +			     "and %0, 0\n"
> >>> +			     "dsubu %0, 1\n"
> >>> +			     "dmtc0 %0, $10, 0\n"
> >>> +			     "dmfc0 %0, $10, 0\n"
> >>> +			     "dsll %0, %0, 2\n"
> >>> +			     "dsra %0, %0, 2\n"
> >>> +			     "dclz %0, %0\n"
> >>> +			     ".set mips0\n"
> >>> +			     : "=r" (zbits));
> >>> +		c->vmbits = 64 - zbits;
> >>> +	} else
> >>> +		c->vmbits = 32;
> >>> +}
> >>> +
> >> It should be possible to express this in 'pure' C using 
> >> read_c0_entryhi()/write_c0_entryhi(), also you need to be sure you are 
> > 
> > Sure, no problem.
> > 
> >> not writing 1s to any reserved bits of the register.
> >>
> > That may be tricky, since the upper bits are reserved in some
> > architectures. For example, the 20Kc core specification says that bits
> > 61:40 are reserved and must be written with 0.
> > 
> > I can write, say, 0x3fffffffffff0000 to avoid writing into lower
> > reserved bits, but that won't help for any upper reserved bits. Would
> > that be acceptable / better ?
> 
> 
> The MIPS64® Privileged Resource Architecture manual might be a better 
> reference.
> 
Unfortunately, the download link for that manual on mips.com seems to be
broken.

> I would set 1s only in bits 13-63 (the VPN2 and R fields).  We don't 
> support and don't really care about VPN2X, the upper bits are really the 
> only ones of interest here.
> 
Ok, I'll do that.

This is the new code:

static inline void cpu_set_vmbits(struct cpuinfo_mips *c)
{
        if (cpu_has_64bits) {
                write_c0_entryhi(0xfffffffffffff000ULL);
                c->vmbits = __fls(read_c0_entryhi() &
0x3ffffffffffff000ULL) + 1;
        } else
                c->vmbits = 32;
}

Guenter

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2] Virtual memory size detection for 64 bit MIPS CPUs
  2010-02-01 22:04   ` Guenter Roeck
  2010-02-01 22:12     ` David Daney
@ 2010-02-01 22:39     ` Maciej W. Rozycki
  1 sibling, 0 replies; 6+ messages in thread
From: Maciej W. Rozycki @ 2010-02-01 22:39 UTC (permalink / raw)
  To: Guenter Roeck; +Cc: David Daney, linux-mips@linux-mips.org

On Mon, 1 Feb 2010, Guenter Roeck wrote:

> On Mon, 2010-02-01 at 16:42 -0500, David Daney wrote:
> > Guenter Roeck wrote:
> > [...]
> > >  
> > > +static inline void cpu_set_vmbits(struct cpuinfo_mips *c)
> > > +{
> > > +	if (cpu_has_64bits) {
> > > +		unsigned long zbits;
> > > +
> > > +		asm volatile(".set mips64\n"
> > > +			     "and %0, 0\n"
> > > +			     "dsubu %0, 1\n"
> > > +			     "dmtc0 %0, $10, 0\n"
> > > +			     "dmfc0 %0, $10, 0\n"
> > > +			     "dsll %0, %0, 2\n"
> > > +			     "dsra %0, %0, 2\n"
> > > +			     "dclz %0, %0\n"
> > > +			     ".set mips0\n"
> > > +			     : "=r" (zbits));
> > > +		c->vmbits = 64 - zbits;
> > > +	} else
> > > +		c->vmbits = 32;
> > > +}
> > > +
> > 
> > It should be possible to express this in 'pure' C using 
> > read_c0_entryhi()/write_c0_entryhi(), also you need to be sure you are 
> 
> Sure, no problem.

 Especially as:

1. DCLZ is not a valid MIPS III instruction; some 64-bit CPUs will fault 
   on it.

2. You have to take care of CP0 hazards, e.g. with the R4000 if an MTC0 is 
   immediately followed by an MFC0 accessing the same CP0 register, then 
   the result of the latter instruction is unpredictable.

  Maciej

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2010-02-01 22:39 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-02-01 21:00 [PATCH v2] Virtual memory size detection for 64 bit MIPS CPUs Guenter Roeck
2010-02-01 21:42 ` David Daney
2010-02-01 22:04   ` Guenter Roeck
2010-02-01 22:12     ` David Daney
2010-02-01 22:34       ` Guenter Roeck
2010-02-01 22:39     ` Maciej W. Rozycki

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.