Skip to content

Commit 6aa989a

Browse files
Gaurav Batramaddy-kerneldev
Gaurav Batra
authored andcommitted
powerpc/pseries/iommu: memory notifier incorrectly adds TCEs for pmemory
iommu_mem_notifier() is invoked when RAM is dynamically added/removed. This notifier call is responsible to add/remove TCEs from the Dynamic DMA Window (DDW) when TCEs are pre-mapped. TCEs are pre-mapped only for RAM and not for persistent memory (pmemory). For DMA buffers in pmemory, TCEs are dynamically mapped when the device driver instructs to do so. The issue is 'daxctl' command is capable of adding pmemory as "System RAM" after LPAR boot. The command to do so is - daxctl reconfigure-device --mode=system-ram dax0.0 --force This will dynamically add pmemory range to LPAR RAM eventually invoking iommu_mem_notifier(). The address range of pmemory is way beyond the Max RAM that the LPAR can have. Which means, this range is beyond the DDW created for the device, at device initialization time. As a result when TCEs are pre-mapped for the pmemory range, by iommu_mem_notifier(), PHYP HCALL returns H_PARAMETER. This failed the command, daxctl, to add pmemory as RAM. The solution is to not pre-map TCEs for pmemory. Signed-off-by: Gaurav Batra <[email protected]> Tested-by: Donet Tom <[email protected]> Reviewed-by: Donet Tom <[email protected]> Signed-off-by: Madhavan Srinivasan <[email protected]> Link: https://patch.msgid.link/[email protected]
1 parent 67dfc11 commit 6aa989a

File tree

3 files changed

+18
-14
lines changed

3 files changed

+18
-14
lines changed

arch/powerpc/include/asm/mmzone.h

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ extern cpumask_var_t node_to_cpumask_map[];
2929
#ifdef CONFIG_MEMORY_HOTPLUG
3030
extern unsigned long max_pfn;
3131
u64 memory_hotplug_max(void);
32+
u64 hot_add_drconf_memory_max(void);
3233
#else
3334
#define memory_hotplug_max() memblock_end_of_DRAM()
3435
#endif

arch/powerpc/mm/numa.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1336,7 +1336,7 @@ int hot_add_scn_to_nid(unsigned long scn_addr)
13361336
return nid;
13371337
}
13381338

1339-
static u64 hot_add_drconf_memory_max(void)
1339+
u64 hot_add_drconf_memory_max(void)
13401340
{
13411341
struct device_node *memory = NULL;
13421342
struct device_node *dn = NULL;

arch/powerpc/platforms/pseries/iommu.c

+16-13
Original file line numberDiff line numberDiff line change
@@ -1285,17 +1285,13 @@ static LIST_HEAD(failed_ddw_pdn_list);
12851285

12861286
static phys_addr_t ddw_memory_hotplug_max(void)
12871287
{
1288-
resource_size_t max_addr = memory_hotplug_max();
1289-
struct device_node *memory;
1288+
resource_size_t max_addr;
12901289

1291-
for_each_node_by_type(memory, "memory") {
1292-
struct resource res;
1293-
1294-
if (of_address_to_resource(memory, 0, &res))
1295-
continue;
1296-
1297-
max_addr = max_t(resource_size_t, max_addr, res.end + 1);
1298-
}
1290+
#if defined(CONFIG_NUMA) && defined(CONFIG_MEMORY_HOTPLUG)
1291+
max_addr = hot_add_drconf_memory_max();
1292+
#else
1293+
max_addr = memblock_end_of_DRAM();
1294+
#endif
12991295

13001296
return max_addr;
13011297
}
@@ -1672,7 +1668,7 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn, u64 dma_mas
16721668

16731669
if (direct_mapping) {
16741670
/* DDW maps the whole partition, so enable direct DMA mapping */
1675-
ret = walk_system_ram_range(0, memblock_end_of_DRAM() >> PAGE_SHIFT,
1671+
ret = walk_system_ram_range(0, ddw_memory_hotplug_max() >> PAGE_SHIFT,
16761672
win64->value, tce_setrange_multi_pSeriesLP_walk);
16771673
if (ret) {
16781674
dev_info(&dev->dev, "failed to map DMA window for %pOF: %d\n",
@@ -2427,11 +2423,17 @@ static int iommu_mem_notifier(struct notifier_block *nb, unsigned long action,
24272423
struct memory_notify *arg = data;
24282424
int ret = 0;
24292425

2426+
/* This notifier can get called when onlining persistent memory as well.
2427+
* TCEs are not pre-mapped for persistent memory. Persistent memory will
2428+
* always be above ddw_memory_hotplug_max()
2429+
*/
2430+
24302431
switch (action) {
24312432
case MEM_GOING_ONLINE:
24322433
spin_lock(&dma_win_list_lock);
24332434
list_for_each_entry(window, &dma_win_list, list) {
2434-
if (window->direct) {
2435+
if (window->direct && (arg->start_pfn << PAGE_SHIFT) <
2436+
ddw_memory_hotplug_max()) {
24352437
ret |= tce_setrange_multi_pSeriesLP(arg->start_pfn,
24362438
arg->nr_pages, window->prop);
24372439
}
@@ -2443,7 +2445,8 @@ static int iommu_mem_notifier(struct notifier_block *nb, unsigned long action,
24432445
case MEM_OFFLINE:
24442446
spin_lock(&dma_win_list_lock);
24452447
list_for_each_entry(window, &dma_win_list, list) {
2446-
if (window->direct) {
2448+
if (window->direct && (arg->start_pfn << PAGE_SHIFT) <
2449+
ddw_memory_hotplug_max()) {
24472450
ret |= tce_clearrange_multi_pSeriesLP(arg->start_pfn,
24482451
arg->nr_pages, window->prop);
24492452
}

0 commit comments

Comments
 (0)