Re: [PATCH 2/2] pstore-ram: Allow optional mapping with pgprot_noncached

2014-12-10 Thread Kees Cook
On Tue, Sep 16, 2014 at 1:50 PM, Tony Lindgren t...@atomide.com wrote:
 From: Tony Lindgren t...@atomide.com
 Date: Thu, 11 Sep 2014 15:02:37 -0700
 Subject: [PATCH] pstore-ram: Allow optional mapping with pgprot_noncached

 On some ARMs the memory can be mapped pgprot_noncached() and still
 be working for atomic operations. As pointed out by Colin Cross
 ccr...@android.com, in some cases you do want to use
 pgprot_noncached() if the SoC supports it to see a debug printk
 just before a write hanging the system.

 On ARMs, the atomic operations on strongly ordered memory are
 implementation defined. So let's provide an optional kernel parameter
 for configuring pgprot_noncached(), and use pgprot_writecombine() by
 default.

 Cc: Arnd Bergmann a...@arndb.de
 Cc: Rob Herring robherri...@gmail.com
 Cc: Randy Dunlap rdun...@infradead.org
 Cc: Anton Vorontsov an...@enomsg.org
 Cc: Colin Cross ccr...@android.com
 Cc: Kees Cook keesc...@chromium.org
 Cc: Olof Johansson o...@lixom.net
 Cc: Tony Luck tony.l...@intel.com
 Cc: Russell King li...@arm.linux.org.uk
 Signed-off-by: Tony Lindgren t...@atomide.com

Sorry this got missed! I think rmk's concerns were addressed in this
v2. Tony (Luck), can you take this into your tree?

Acked-by: Kees Cook keesc...@chromium.org

Thanks!

-Kees


 --- a/Documentation/ramoops.txt
 +++ b/Documentation/ramoops.txt
 @@ -14,11 +14,19 @@ survive after a restart.

  1. Ramoops concepts

 -Ramoops uses a predefined memory area to store the dump. The start and size 
 of
 -the memory area are set using two variables:
 +Ramoops uses a predefined memory area to store the dump. The start and size
 +and type of the memory area are set using three variables:
* mem_address for the start
* mem_size for the size. The memory size will be rounded down to a
power of two.
 +  * mem_type to specifiy if the memory type (default is 
 pgprot_writecombine).
 +
 +Typically the default value of mem_type=0 should be used as that sets the 
 pstore
 +mapping to pgprot_writecombine. Setting mem_type=1 attempts to use
 +pgprot_noncached, which only works on some platforms. This is because pstore
 +depends on atomic operations. At least on ARM, pgprot_noncached causes the
 +memory to be mapped strongly ordered, and atomic operations on strongly 
 ordered
 +memory are implementation defined, and won't work on many ARMs such as omaps.

  The memory area is divided into record_size chunks (also rounded down to
  power of two) and each oops/panic writes a record_size chunk of
 @@ -55,6 +63,7 @@ Setting the ramoops parameters can be done in 2 different 
 manners:
  static struct ramoops_platform_data ramoops_data = {
  .mem_size   = ...,
  .mem_address= ...,
 +.mem_type   = ...,
  .record_size= ...,
  .dump_oops  = ...,
  .ecc= ...,
 --- a/fs/pstore/ram.c
 +++ b/fs/pstore/ram.c
 @@ -61,6 +61,11 @@ module_param(mem_size, ulong, 0400);
  MODULE_PARM_DESC(mem_size,
 size of reserved RAM used to store oops/panic logs);

 +static unsigned int mem_type;
 +module_param(mem_type, uint, 0600);
 +MODULE_PARM_DESC(mem_type,
 +   set to 1 to try to use unbuffered memory (default 0));
 +
  static int dump_oops = 1;
  module_param(dump_oops, int, 0600);
  MODULE_PARM_DESC(dump_oops,
 @@ -79,6 +84,7 @@ struct ramoops_context {
 struct persistent_ram_zone *fprz;
 phys_addr_t phys_addr;
 unsigned long size;
 +   unsigned int memtype;
 size_t record_size;
 size_t console_size;
 size_t ftrace_size;
 @@ -358,7 +364,8 @@ static int ramoops_init_przs(struct device *dev, struct 
 ramoops_context *cxt,
 size_t sz = cxt-record_size;

 cxt-przs[i] = persistent_ram_new(*paddr, sz, 0,
 - cxt-ecc_info);
 + cxt-ecc_info,
 + cxt-memtype);
 if (IS_ERR(cxt-przs[i])) {
 err = PTR_ERR(cxt-przs[i]);
 dev_err(dev, failed to request mem region 
 (0x%zx@0x%llx): %d\n,
 @@ -388,7 +395,7 @@ static int ramoops_init_prz(struct device *dev, struct 
 ramoops_context *cxt,
 return -ENOMEM;
 }

 -   *prz = persistent_ram_new(*paddr, sz, sig, cxt-ecc_info);
 +   *prz = persistent_ram_new(*paddr, sz, sig, cxt-ecc_info, 
 cxt-memtype);
 if (IS_ERR(*prz)) {
 int err = PTR_ERR(*prz);

 @@ -435,6 +442,7 @@ static int ramoops_probe(struct platform_device *pdev)

 cxt-size = pdata-mem_size;
 cxt-phys_addr = pdata-mem_address;
 +   cxt-memtype = pdata-mem_type;
 cxt-record_size = pdata-record_size;
 cxt-console_size = pdata-console_size;
 cxt-ftrace_size = pdata-ftrace_size;
 @@ -564,6 +572,7 @@ static void 

Re: [PATCH 2/2] pstore-ram: Allow optional mapping with pgprot_noncached

2014-12-10 Thread Tony Lindgren
* Kees Cook keesc...@chromium.org [141210 13:18]:
 On Tue, Sep 16, 2014 at 1:50 PM, Tony Lindgren t...@atomide.com wrote:
  From: Tony Lindgren t...@atomide.com
  Date: Thu, 11 Sep 2014 15:02:37 -0700
  Subject: [PATCH] pstore-ram: Allow optional mapping with pgprot_noncached
 
  On some ARMs the memory can be mapped pgprot_noncached() and still
  be working for atomic operations. As pointed out by Colin Cross
  ccr...@android.com, in some cases you do want to use
  pgprot_noncached() if the SoC supports it to see a debug printk
  just before a write hanging the system.
 
  On ARMs, the atomic operations on strongly ordered memory are
  implementation defined. So let's provide an optional kernel parameter
  for configuring pgprot_noncached(), and use pgprot_writecombine() by
  default.
 
  Cc: Arnd Bergmann a...@arndb.de
  Cc: Rob Herring robherri...@gmail.com
  Cc: Randy Dunlap rdun...@infradead.org
  Cc: Anton Vorontsov an...@enomsg.org
  Cc: Colin Cross ccr...@android.com
  Cc: Kees Cook keesc...@chromium.org
  Cc: Olof Johansson o...@lixom.net
  Cc: Tony Luck tony.l...@intel.com
  Cc: Russell King li...@arm.linux.org.uk
  Signed-off-by: Tony Lindgren t...@atomide.com
 
 Sorry this got missed! I think rmk's concerns were addressed in this
 v2. Tony (Luck), can you take this into your tree?
 
 Acked-by: Kees Cook keesc...@chromium.org

I take your ack covers patch 1/2 also. The first patch in this
series should be tagged cc stable when committing please.

Regards,

Tony
 
 Thanks!
 
 -Kees
 
 
  --- a/Documentation/ramoops.txt
  +++ b/Documentation/ramoops.txt
  @@ -14,11 +14,19 @@ survive after a restart.
 
   1. Ramoops concepts
 
  -Ramoops uses a predefined memory area to store the dump. The start and 
  size of
  -the memory area are set using two variables:
  +Ramoops uses a predefined memory area to store the dump. The start and size
  +and type of the memory area are set using three variables:
 * mem_address for the start
 * mem_size for the size. The memory size will be rounded down to a
 power of two.
  +  * mem_type to specifiy if the memory type (default is 
  pgprot_writecombine).
  +
  +Typically the default value of mem_type=0 should be used as that sets the 
  pstore
  +mapping to pgprot_writecombine. Setting mem_type=1 attempts to use
  +pgprot_noncached, which only works on some platforms. This is because 
  pstore
  +depends on atomic operations. At least on ARM, pgprot_noncached causes the
  +memory to be mapped strongly ordered, and atomic operations on strongly 
  ordered
  +memory are implementation defined, and won't work on many ARMs such as 
  omaps.
 
   The memory area is divided into record_size chunks (also rounded down to
   power of two) and each oops/panic writes a record_size chunk of
  @@ -55,6 +63,7 @@ Setting the ramoops parameters can be done in 2 different 
  manners:
   static struct ramoops_platform_data ramoops_data = {
   .mem_size   = ...,
   .mem_address= ...,
  +.mem_type   = ...,
   .record_size= ...,
   .dump_oops  = ...,
   .ecc= ...,
  --- a/fs/pstore/ram.c
  +++ b/fs/pstore/ram.c
  @@ -61,6 +61,11 @@ module_param(mem_size, ulong, 0400);
   MODULE_PARM_DESC(mem_size,
  size of reserved RAM used to store oops/panic logs);
 
  +static unsigned int mem_type;
  +module_param(mem_type, uint, 0600);
  +MODULE_PARM_DESC(mem_type,
  +   set to 1 to try to use unbuffered memory (default 0));
  +
   static int dump_oops = 1;
   module_param(dump_oops, int, 0600);
   MODULE_PARM_DESC(dump_oops,
  @@ -79,6 +84,7 @@ struct ramoops_context {
  struct persistent_ram_zone *fprz;
  phys_addr_t phys_addr;
  unsigned long size;
  +   unsigned int memtype;
  size_t record_size;
  size_t console_size;
  size_t ftrace_size;
  @@ -358,7 +364,8 @@ static int ramoops_init_przs(struct device *dev, struct 
  ramoops_context *cxt,
  size_t sz = cxt-record_size;
 
  cxt-przs[i] = persistent_ram_new(*paddr, sz, 0,
  - cxt-ecc_info);
  + cxt-ecc_info,
  + cxt-memtype);
  if (IS_ERR(cxt-przs[i])) {
  err = PTR_ERR(cxt-przs[i]);
  dev_err(dev, failed to request mem region 
  (0x%zx@0x%llx): %d\n,
  @@ -388,7 +395,7 @@ static int ramoops_init_prz(struct device *dev, struct 
  ramoops_context *cxt,
  return -ENOMEM;
  }
 
  -   *prz = persistent_ram_new(*paddr, sz, sig, cxt-ecc_info);
  +   *prz = persistent_ram_new(*paddr, sz, sig, cxt-ecc_info, 
  cxt-memtype);
  if (IS_ERR(*prz)) {
  int err = PTR_ERR(*prz);
 
  @@ -435,6 +442,7 @@ static int ramoops_probe(struct platform_device 

Re: [PATCH 2/2] pstore-ram: Allow optional mapping with pgprot_noncached

2014-09-16 Thread Tony Lindgren
* Russell King - ARM Linux li...@arm.linux.org.uk [140912 16:16]:
 On Fri, Sep 12, 2014 at 11:32:25AM -0700, Tony Lindgren wrote:
  On some ARMs at least the memory can be mapped pgprot_noncached()
  and still be working for atomic operations. As pointed out by
  Colin Cross ccr...@android.com, in some cases you do want to use
  pgprot_noncached() if the SoC supports it to see a debug printk
  just before a write hanging the system.
  
  On ARMs, the atomic operations on strongly ordered memory are
  implementation defined. So let's provide an optional kernel parameter
  for configuring noncached memory, and use pgprot_writecombine() by
  default.
 
 Can we clean up this terminology please?
 
 Writecombine memory is not cached - write combine memory bypasses the
 caches entirely.  What it doesn't bypass are store buffers, which may
 combine two writes together.  So, calling it cached is misleading.

Good point. I've pretty much s/cached/memtype/ and updated the
description too in the patch below.
 
 Secondly, memory returned by ioremap() is not strongly ordered, it is
 device memory.  There's three main classifications of memory on ARM:
 strongly ordered, device and normal memory.  Normal memory has attributes
 which define whether it is write combining, or cacheable in some way (and
 if so, how it's cacheable.)
 
 Exclusives are always permitted to normal memory.  The other two are
 implementation defined.  While an implementation may offer it on
 strongly ordered, that doesn't mean that it also supports it on device
 memory.
 
 Lastly, aliased mappings are something that ARM has always strongly
 discouraged on ARMv6+ (it was plain down-right unpredictable, but it's
 now strongly discouraged) and remapping memory with different memory
 type should be avoided.

Yes thanks for the summary again. Maybe let's let this second patch float
on the lists for a while until we have somebody actually test it on
unbuffered memory.

Andrew, if no comments on 1/2 in this series, can you please pick it up
for fixes so we get pstore working?

Here's the updated version of the second patch for reference.

Regards,

Tony

8 -
From: Tony Lindgren t...@atomide.com
Date: Thu, 11 Sep 2014 15:02:37 -0700
Subject: [PATCH] pstore-ram: Allow optional mapping with pgprot_noncached

On some ARMs the memory can be mapped pgprot_noncached() and still
be working for atomic operations. As pointed out by Colin Cross
ccr...@android.com, in some cases you do want to use
pgprot_noncached() if the SoC supports it to see a debug printk
just before a write hanging the system.

On ARMs, the atomic operations on strongly ordered memory are
implementation defined. So let's provide an optional kernel parameter
for configuring pgprot_noncached(), and use pgprot_writecombine() by
default.

Cc: Arnd Bergmann a...@arndb.de
Cc: Rob Herring robherri...@gmail.com
Cc: Randy Dunlap rdun...@infradead.org
Cc: Anton Vorontsov an...@enomsg.org
Cc: Colin Cross ccr...@android.com
Cc: Kees Cook keesc...@chromium.org
Cc: Olof Johansson o...@lixom.net
Cc: Tony Luck tony.l...@intel.com
Cc: Russell King li...@arm.linux.org.uk
Signed-off-by: Tony Lindgren t...@atomide.com

--- a/Documentation/ramoops.txt
+++ b/Documentation/ramoops.txt
@@ -14,11 +14,19 @@ survive after a restart.
 
 1. Ramoops concepts
 
-Ramoops uses a predefined memory area to store the dump. The start and size of
-the memory area are set using two variables:
+Ramoops uses a predefined memory area to store the dump. The start and size
+and type of the memory area are set using three variables:
   * mem_address for the start
   * mem_size for the size. The memory size will be rounded down to a
   power of two.
+  * mem_type to specifiy if the memory type (default is pgprot_writecombine).
+
+Typically the default value of mem_type=0 should be used as that sets the 
pstore
+mapping to pgprot_writecombine. Setting mem_type=1 attempts to use
+pgprot_noncached, which only works on some platforms. This is because pstore
+depends on atomic operations. At least on ARM, pgprot_noncached causes the
+memory to be mapped strongly ordered, and atomic operations on strongly ordered
+memory are implementation defined, and won't work on many ARMs such as omaps.
 
 The memory area is divided into record_size chunks (also rounded down to
 power of two) and each oops/panic writes a record_size chunk of
@@ -55,6 +63,7 @@ Setting the ramoops parameters can be done in 2 different 
manners:
 static struct ramoops_platform_data ramoops_data = {
 .mem_size   = ...,
 .mem_address= ...,
+.mem_type   = ...,
 .record_size= ...,
 .dump_oops  = ...,
 .ecc= ...,
--- a/fs/pstore/ram.c
+++ b/fs/pstore/ram.c
@@ -61,6 +61,11 @@ module_param(mem_size, ulong, 0400);
 MODULE_PARM_DESC(mem_size,
size of reserved RAM used to store oops/panic logs);
 
+static unsigned int mem_type;

[PATCH 2/2] pstore-ram: Allow optional mapping with pgprot_noncached

2014-09-12 Thread Tony Lindgren
On some ARMs at least the memory can be mapped pgprot_noncached()
and still be working for atomic operations. As pointed out by
Colin Cross ccr...@android.com, in some cases you do want to use
pgprot_noncached() if the SoC supports it to see a debug printk
just before a write hanging the system.

On ARMs, the atomic operations on strongly ordered memory are
implementation defined. So let's provide an optional kernel parameter
for configuring noncached memory, and use pgprot_writecombine() by
default.

Cc: Arnd Bergmann a...@arndb.de
Cc: Rob Herring robherri...@gmail.com
Cc: Randy Dunlap rdun...@infradead.org
Cc: Anton Vorontsov an...@enomsg.org
Cc: Colin Cross ccr...@android.com
Cc: Kees Cook keesc...@chromium.org
Cc: Olof Johansson o...@lixom.net
Cc: Tony Luck tony.l...@intel.com
Cc: Russell King li...@arm.linux.org.uk
Signed-off-by: Tony Lindgren t...@atomide.com
---
 Documentation/ramoops.txt  | 12 ++--
 fs/pstore/ram.c| 13 +++--
 fs/pstore/ram_core.c   | 31 ++-
 include/linux/pstore_ram.h |  4 +++-
 4 files changed, 46 insertions(+), 14 deletions(-)

diff --git a/Documentation/ramoops.txt b/Documentation/ramoops.txt
index 69b3cac..2dab135 100644
--- a/Documentation/ramoops.txt
+++ b/Documentation/ramoops.txt
@@ -14,11 +14,18 @@ survive after a restart.
 
 1. Ramoops concepts
 
-Ramoops uses a predefined memory area to store the dump. The start and size of
-the memory area are set using two variables:
+Ramoops uses a predefined memory area to store the dump. The start and size
+and type of the memory area are set using three variables:
   * mem_address for the start
   * mem_size for the size. The memory size will be rounded down to a
   power of two.
+  * mem_cached to specifiy if the memory is cached or not.
+
+Note disabling mem_cached may not be supported on all architectures as
+pstore depends on atomic operations. At least on ARM, clearing mem_cached
+will cause the memory to be mapped strongly ordered. And atomic operations
+on strongly ordered memory are implementation defined, and won't work on
+many ARMs such as omap.
 
 The memory area is divided into record_size chunks (also rounded down to
 power of two) and each oops/panic writes a record_size chunk of
@@ -55,6 +62,7 @@ Setting the ramoops parameters can be done in 2 different 
manners:
 static struct ramoops_platform_data ramoops_data = {
 .mem_size   = ...,
 .mem_address= ...,
+.mem_cached = ...,
 .record_size= ...,
 .dump_oops  = ...,
 .ecc= ...,
diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c
index 3b57443..53ddcb2 100644
--- a/fs/pstore/ram.c
+++ b/fs/pstore/ram.c
@@ -61,6 +61,11 @@ module_param(mem_size, ulong, 0400);
 MODULE_PARM_DESC(mem_size,
size of reserved RAM used to store oops/panic logs);
 
+static unsigned int mem_cached = 1;
+module_param(mem_cached, uint, 0600);
+MODULE_PARM_DESC(mem_cached,
+   set to 1 to use cached memory, 0 to use uncached (default 1));
+
 static int dump_oops = 1;
 module_param(dump_oops, int, 0600);
 MODULE_PARM_DESC(dump_oops,
@@ -79,6 +84,7 @@ struct ramoops_context {
struct persistent_ram_zone *fprz;
phys_addr_t phys_addr;
unsigned long size;
+   unsigned int cached;
size_t record_size;
size_t console_size;
size_t ftrace_size;
@@ -358,7 +364,8 @@ static int ramoops_init_przs(struct device *dev, struct 
ramoops_context *cxt,
size_t sz = cxt-record_size;
 
cxt-przs[i] = persistent_ram_new(*paddr, sz, 0,
- cxt-ecc_info);
+ cxt-ecc_info,
+ cxt-cached);
if (IS_ERR(cxt-przs[i])) {
err = PTR_ERR(cxt-przs[i]);
dev_err(dev, failed to request mem region 
(0x%zx@0x%llx): %d\n,
@@ -388,7 +395,7 @@ static int ramoops_init_prz(struct device *dev, struct 
ramoops_context *cxt,
return -ENOMEM;
}
 
-   *prz = persistent_ram_new(*paddr, sz, sig, cxt-ecc_info);
+   *prz = persistent_ram_new(*paddr, sz, sig, cxt-ecc_info, cxt-cached);
if (IS_ERR(*prz)) {
int err = PTR_ERR(*prz);
 
@@ -435,6 +442,7 @@ static int ramoops_probe(struct platform_device *pdev)
 
cxt-size = pdata-mem_size;
cxt-phys_addr = pdata-mem_address;
+   cxt-cached = pdata-mem_cached;
cxt-record_size = pdata-record_size;
cxt-console_size = pdata-console_size;
cxt-ftrace_size = pdata-ftrace_size;
@@ -564,6 +572,7 @@ static void ramoops_register_dummy(void)
 
dummy_data-mem_size = mem_size;
dummy_data-mem_address = mem_address;
+   dummy_data-mem_cached = 1;
dummy_data-record_size = record_size;
dummy_data-console_size 

Re: [PATCH 2/2] pstore-ram: Allow optional mapping with pgprot_noncached

2014-09-12 Thread Russell King - ARM Linux
On Fri, Sep 12, 2014 at 11:32:25AM -0700, Tony Lindgren wrote:
 On some ARMs at least the memory can be mapped pgprot_noncached()
 and still be working for atomic operations. As pointed out by
 Colin Cross ccr...@android.com, in some cases you do want to use
 pgprot_noncached() if the SoC supports it to see a debug printk
 just before a write hanging the system.
 
 On ARMs, the atomic operations on strongly ordered memory are
 implementation defined. So let's provide an optional kernel parameter
 for configuring noncached memory, and use pgprot_writecombine() by
 default.

Can we clean up this terminology please?

Writecombine memory is not cached - write combine memory bypasses the
caches entirely.  What it doesn't bypass are store buffers, which may
combine two writes together.  So, calling it cached is misleading.

Secondly, memory returned by ioremap() is not strongly ordered, it is
device memory.  There's three main classifications of memory on ARM:
strongly ordered, device and normal memory.  Normal memory has attributes
which define whether it is write combining, or cacheable in some way (and
if so, how it's cacheable.)

Exclusives are always permitted to normal memory.  The other two are
implementation defined.  While an implementation may offer it on
strongly ordered, that doesn't mean that it also supports it on device
memory.

Lastly, aliased mappings are something that ARM has always strongly
discouraged on ARMv6+ (it was plain down-right unpredictable, but it's
now strongly discouraged) and remapping memory with different memory
type should be avoided.

-- 
FTTC broadband for 0.8mile line: currently at 9.5Mbps down 400kbps up
according to speedtest.net.
--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html