Received: from milmhbs1.lsil.com (147.145.21.209) by coscas01.lsi.com
 (172.21.36.60) with Microsoft SMTP Server id 8.1.393.1; Mon, 1 Feb 2010
 14:16:59 -0700
Received: from mail1.lsil.com (mail1.lsil.com [147.145.40.21])	by
 milmhbs1.lsil.com (8.12.11/8.12.11) with ESMTP id o11LGxLV005981	for
 <andy.sharp@lsi.com>; Mon, 1 Feb 2010 13:16:59 -0800
Received: from psmtp.com (na3sys009amx220.postini.com [74.125.149.60])	by
 mail1.lsil.com (8.12.11/8.12.11) with SMTP id o11LGwjC009473	for
 <andy.sharp@lsi.com>; Mon, 1 Feb 2010 13:16:58 -0800 (PST)
Received: from source ([78.24.191.182]) by na3sys009amx220.postini.com
 ([74.125.148.14]) with SMTP;	Mon, 01 Feb 2010 21:16:58 GMT
Received: from localhost.localdomain ([127.0.0.1]:41820 "EHLO
        eddie.linux-mips.org" rhost-flags-OK-OK-OK-FAIL)        by
 eddie.linux-mips.org with ESMTP id S1492261Ab0BAVQu (ORCPT
        <rfc822;andy.sharp@lsi.com>); Mon, 1 Feb 2010 22:16:50 +0100
Received: with ECARTIS (v1.0.0; list linux-mips); Mon, 01 Feb 2010 22:16:32
 +0100 (CET)
Received: from mgate.redback.com ([155.53.3.41]:52606 "EHLO mgate.redback.com"
        rhost-flags-OK-OK-OK-OK) by eddie.linux-mips.org with ESMTP        id
 S1492169Ab0BAVQ2 (ORCPT <rfc822;linux-mips@linux-mips.org>);        Mon, 1
 Feb 2010 22:16:28 +0100
Received: from prattle.redback.com ([155.53.12.9])  by mgate.redback.com with
 ESMTP; 01 Feb 2010 13:16:16 -0800
Received: from localhost (localhost [127.0.0.1])        by prattle.redback.com
 (Postfix) with ESMTP id A07AE11D231A;        Mon,  1 Feb 2010 13:16:25 -0800
 (PST)
Received: from prattle.redback.com ([127.0.0.1]) by localhost (prattle
 [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 15761-04; Mon,  1 Feb
 2010 13:16:25 -0800 (PST)
Received: from localhost (rbos-pc-13.lab.redback.com [10.12.11.133])        by
 prattle.redback.com (Postfix) with ESMTP id 8EB6F11D2319;        Mon,  1 Feb
 2010 13:16:24 -0800 (PST)
From: Guenter Roeck <guenter.roeck@ericsson.com>
To: "linux-mips@linux-mips.org" <linux-mips@linux-mips.org>
CC: Guenter Roeck <guenter.roeck@ericsson.com>
Sender: "linux-mips-bounce@linux-mips.org" <linux-mips-bounce@linux-mips.org>
Date: Mon, 1 Feb 2010 14:00:19 -0700
Subject: [PATCH v2] Virtual memory size detection for 64 bit MIPS CPUs
Thread-Topic: [PATCH v2] Virtual memory size detection for 64 bit MIPS CPUs
Thread-Index: Acqjg+RruVI1KN/EQTGO1+NVPVlBkg==
Message-ID: <1265058019-21484-1-git-send-email-guenter.roeck@ericsson.com>
Accept-Language: en-US
Content-Language: en-US
X-MS-Exchange-Organization-AuthAs: Anonymous
X-MS-Exchange-Organization-AuthSource: coscas01.lsi.com
X-MS-Has-Attach:
X-Auto-Response-Suppress: All
X-MS-TNEF-Correlator:
x-scanned-by: MIMEDefang 2.39
errors-to: linux-mips-bounce@linux-mips.org
x-pstn-levels: (S:51.00452/99.90000 CV:99.9000 FC:95.5390 LC:95.5390
 R:95.9108 P:95.9108 M:97.0282 C:98.6951 )
x-pstn-settings: 3 (1.0000:1.0000) s cv gt3 gt2 gt1 r p m c 
x-pstn-addresses: from <guenter.roeck@ericsson.com> [22/1] 
x-pstn-neptune: 0/0/0.00/0
x-ironport-av: E=Sophos;i="4.49,385,1262592000";    d="scan'208";a="7751151"
Content-Type: text/plain; charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
MIME-Version: 1.0

Linux kernel 2.6.32 and later allocates memory from the top of virtual memo=
ry
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/c=
pu-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
=20
 #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-i=
nfo.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/pgt=
able-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 !=3D 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) !=3D FPIR_IMP_NONE);
 }
=20
+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"
+			     : "=3Dr" (zbits));
+		c->vmbits =3D 64 - zbits;
+	} else
+		c->vmbits =3D 32;
+}
+
 #define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE \
 		| MIPS_CPU_COUNTER)
=20
@@ -967,6 +987,8 @@ __cpuinit void cpu_probe(void)
 		c->srsets =3D ((read_c0_srsctl() >> 26) & 0x0f) + 1;
 	else
 		c->srsets =3D 1;
+
+	cpu_set_vmbits(c);
 }
=20
 __cpuinit void cpu_report(void)
--=20
1.6.0.4


