Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

misc: sram: Only map reserved areas in Tegra SYSRAM

On Tegra186 and later, a portion of the SYSRAM may be reserved for use
by TZ. Non-TZ memory accesses to this portion, including speculative
accesses, trigger SErrors that bring down the system. This does also
happen in practice occasionally (due to speculative accesses).

To fix the issue, add a flag to the SRAM driver to only map the
device tree-specified reserved areas depending on a flag set
based on the compatibility string. This would not affect non-Tegra
systems that rely on the entire thing being memory mapped.

If 64K pages are being used, we cannot exactly map the 4K regions
that are placed in SYSRAM - ioremap code instead aligns to closest
64K pages. However, since in practice the non-accessible memory area
is 64K aligned, these mappings do not overlap with the non-accessible
memory area and things work out.

Reviewed-by: Mian Yousaf Kaukab <ykaukab@suse.de>
Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
Link: https://lore.kernel.org/r/20210715103423.1811101-1-mperttunen@nvidia.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Mikko Perttunen and committed by
Greg Kroah-Hartman
fec29bf0 72674e86

+82 -30
+73 -30
drivers/misc/sram.c
··· 97 97 struct sram_partition *part = &sram->partition[sram->partitions]; 98 98 99 99 mutex_init(&part->lock); 100 - part->base = sram->virt_base + block->start; 100 + 101 + if (sram->config && sram->config->map_only_reserved) { 102 + void __iomem *virt_base; 103 + 104 + if (sram->no_memory_wc) 105 + virt_base = devm_ioremap_resource(sram->dev, &block->res); 106 + else 107 + virt_base = devm_ioremap_resource_wc(sram->dev, &block->res); 108 + 109 + if (IS_ERR(virt_base)) { 110 + dev_err(sram->dev, "could not map SRAM at %pr\n", &block->res); 111 + return PTR_ERR(virt_base); 112 + } 113 + 114 + part->base = virt_base; 115 + } else { 116 + part->base = sram->virt_base + block->start; 117 + } 101 118 102 119 if (block->pool) { 103 120 ret = sram_add_pool(sram, block, start, part); ··· 215 198 216 199 block->start = child_res.start - res->start; 217 200 block->size = resource_size(&child_res); 201 + block->res = child_res; 218 202 list_add_tail(&block->list, &reserve_list); 219 203 220 204 if (of_find_property(child, "export", NULL)) ··· 313 295 */ 314 296 cur_size = block->start - cur_start; 315 297 316 - dev_dbg(sram->dev, "adding chunk 0x%lx-0x%lx\n", 317 - cur_start, cur_start + cur_size); 298 + if (sram->pool) { 299 + dev_dbg(sram->dev, "adding chunk 0x%lx-0x%lx\n", 300 + cur_start, cur_start + cur_size); 318 301 319 - ret = gen_pool_add_virt(sram->pool, 320 - (unsigned long)sram->virt_base + cur_start, 321 - res->start + cur_start, cur_size, -1); 322 - if (ret < 0) { 323 - sram_free_partitions(sram); 324 - goto err_chunks; 302 + ret = gen_pool_add_virt(sram->pool, 303 + (unsigned long)sram->virt_base + cur_start, 304 + res->start + cur_start, cur_size, -1); 305 + if (ret < 0) { 306 + sram_free_partitions(sram); 307 + goto err_chunks; 308 + } 325 309 } 326 310 327 311 /* next allocation after this reserved block */ ··· 351 331 10000, 500000); 352 332 } 353 333 334 + static const struct sram_config atmel_securam_config = { 335 + .init = atmel_securam_wait, 336 + }; 337 + 338 + /* 339 + * SYSRAM contains areas that are not accessible by the 340 + * kernel, such as the first 256K that is reserved for TZ. 341 + * Accesses to those areas (including speculative accesses) 342 + * trigger SErrors. As such we must map only the areas of 343 + * SYSRAM specified in the device tree. 344 + */ 345 + static const struct sram_config tegra_sysram_config = { 346 + .map_only_reserved = true, 347 + }; 348 + 354 349 static const struct of_device_id sram_dt_ids[] = { 355 350 { .compatible = "mmio-sram" }, 356 - { .compatible = "atmel,sama5d2-securam", .data = atmel_securam_wait }, 351 + { .compatible = "atmel,sama5d2-securam", .data = &atmel_securam_config }, 352 + { .compatible = "nvidia,tegra186-sysram", .data = &tegra_sysram_config }, 353 + { .compatible = "nvidia,tegra194-sysram", .data = &tegra_sysram_config }, 357 354 {} 358 355 }; 359 356 360 357 static int sram_probe(struct platform_device *pdev) 361 358 { 359 + const struct sram_config *config; 362 360 struct sram_dev *sram; 363 361 int ret; 364 362 struct resource *res; 365 - int (*init_func)(void); 363 + 364 + config = of_device_get_match_data(&pdev->dev); 366 365 367 366 sram = devm_kzalloc(&pdev->dev, sizeof(*sram), GFP_KERNEL); 368 367 if (!sram) 369 368 return -ENOMEM; 370 369 371 370 sram->dev = &pdev->dev; 371 + sram->no_memory_wc = of_property_read_bool(pdev->dev.of_node, "no-memory-wc"); 372 + sram->config = config; 372 373 373 - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 374 - if (of_property_read_bool(pdev->dev.of_node, "no-memory-wc")) 375 - sram->virt_base = devm_ioremap_resource(&pdev->dev, res); 376 - else 377 - sram->virt_base = devm_ioremap_resource_wc(&pdev->dev, res); 378 - if (IS_ERR(sram->virt_base)) { 379 - dev_err(&pdev->dev, "could not map SRAM registers\n"); 380 - return PTR_ERR(sram->virt_base); 374 + if (!config || !config->map_only_reserved) { 375 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 376 + if (sram->no_memory_wc) 377 + sram->virt_base = devm_ioremap_resource(&pdev->dev, res); 378 + else 379 + sram->virt_base = devm_ioremap_resource_wc(&pdev->dev, res); 380 + if (IS_ERR(sram->virt_base)) { 381 + dev_err(&pdev->dev, "could not map SRAM registers\n"); 382 + return PTR_ERR(sram->virt_base); 383 + } 384 + 385 + sram->pool = devm_gen_pool_create(sram->dev, ilog2(SRAM_GRANULARITY), 386 + NUMA_NO_NODE, NULL); 387 + if (IS_ERR(sram->pool)) 388 + return PTR_ERR(sram->pool); 381 389 } 382 - 383 - sram->pool = devm_gen_pool_create(sram->dev, ilog2(SRAM_GRANULARITY), 384 - NUMA_NO_NODE, NULL); 385 - if (IS_ERR(sram->pool)) 386 - return PTR_ERR(sram->pool); 387 390 388 391 sram->clk = devm_clk_get(sram->dev, NULL); 389 392 if (IS_ERR(sram->clk)) ··· 421 378 422 379 platform_set_drvdata(pdev, sram); 423 380 424 - init_func = of_device_get_match_data(&pdev->dev); 425 - if (init_func) { 426 - ret = init_func(); 381 + if (config && config->init) { 382 + ret = config->init(); 427 383 if (ret) 428 384 goto err_free_partitions; 429 385 } 430 386 431 - dev_dbg(sram->dev, "SRAM pool: %zu KiB @ 0x%p\n", 432 - gen_pool_size(sram->pool) / 1024, sram->virt_base); 387 + if (sram->pool) 388 + dev_dbg(sram->dev, "SRAM pool: %zu KiB @ 0x%p\n", 389 + gen_pool_size(sram->pool) / 1024, sram->virt_base); 433 390 434 391 return 0; 435 392 ··· 448 405 449 406 sram_free_partitions(sram); 450 407 451 - if (gen_pool_avail(sram->pool) < gen_pool_size(sram->pool)) 408 + if (sram->pool && gen_pool_avail(sram->pool) < gen_pool_size(sram->pool)) 452 409 dev_err(sram->dev, "removed while SRAM allocated\n"); 453 410 454 411 if (sram->clk)
+9
drivers/misc/sram.h
··· 5 5 #ifndef __SRAM_H 6 6 #define __SRAM_H 7 7 8 + struct sram_config { 9 + int (*init)(void); 10 + bool map_only_reserved; 11 + }; 12 + 8 13 struct sram_partition { 9 14 void __iomem *base; 10 15 ··· 20 15 }; 21 16 22 17 struct sram_dev { 18 + const struct sram_config *config; 19 + 23 20 struct device *dev; 24 21 void __iomem *virt_base; 22 + bool no_memory_wc; 25 23 26 24 struct gen_pool *pool; 27 25 struct clk *clk; ··· 37 29 struct list_head list; 38 30 u32 start; 39 31 u32 size; 32 + struct resource res; 40 33 bool export; 41 34 bool pool; 42 35 bool protect_exec;