mm: remove MEMORY_DEVICE_PUBLIC support

The code hasn't been used since it was added to the tree, and doesn't
appear to actually be usable.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jason Gunthorpe <jgg@mellanox.com>
Acked-by: Michal Hocko <mhocko@suse.com>
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Tested-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
This commit is contained in:
Christoph Hellwig 2019-06-13 22:50:49 +02:00 committed by Jason Gunthorpe
parent 07ec38917e
commit 25b2995a35
14 changed files with 22 additions and 186 deletions

View File

@ -1279,7 +1279,7 @@ static pagemap_entry_t pte_to_pagemap_entry(struct pagemapread *pm,
if (pm->show_pfn) if (pm->show_pfn)
frame = pte_pfn(pte); frame = pte_pfn(pte);
flags |= PM_PRESENT; flags |= PM_PRESENT;
page = _vm_normal_page(vma, addr, pte, true); page = vm_normal_page(vma, addr, pte);
if (pte_soft_dirty(pte)) if (pte_soft_dirty(pte))
flags |= PM_SOFT_DIRTY; flags |= PM_SOFT_DIRTY;
} else if (is_swap_pte(pte)) { } else if (is_swap_pte(pte)) {

View File

@ -584,7 +584,7 @@ static inline void hmm_mm_destroy(struct mm_struct *mm) {}
static inline void hmm_mm_init(struct mm_struct *mm) {} static inline void hmm_mm_init(struct mm_struct *mm) {}
#endif /* IS_ENABLED(CONFIG_HMM_MIRROR) */ #endif /* IS_ENABLED(CONFIG_HMM_MIRROR) */
#if IS_ENABLED(CONFIG_DEVICE_PRIVATE) || IS_ENABLED(CONFIG_DEVICE_PUBLIC) #if IS_ENABLED(CONFIG_DEVICE_PRIVATE)
struct hmm_devmem; struct hmm_devmem;
struct page *hmm_vma_alloc_locked_page(struct vm_area_struct *vma, struct page *hmm_vma_alloc_locked_page(struct vm_area_struct *vma,
@ -722,9 +722,6 @@ struct hmm_devmem {
struct hmm_devmem *hmm_devmem_add(const struct hmm_devmem_ops *ops, struct hmm_devmem *hmm_devmem_add(const struct hmm_devmem_ops *ops,
struct device *device, struct device *device,
unsigned long size); unsigned long size);
struct hmm_devmem *hmm_devmem_add_resource(const struct hmm_devmem_ops *ops,
struct device *device,
struct resource *res);
/* /*
* hmm_devmem_page_set_drvdata - set per-page driver data field * hmm_devmem_page_set_drvdata - set per-page driver data field
@ -751,7 +748,7 @@ static inline unsigned long hmm_devmem_page_get_drvdata(const struct page *page)
{ {
return page->hmm_data; return page->hmm_data;
} }
#endif /* CONFIG_DEVICE_PRIVATE || CONFIG_DEVICE_PUBLIC */ #endif /* CONFIG_DEVICE_PRIVATE */
#else /* IS_ENABLED(CONFIG_HMM) */ #else /* IS_ENABLED(CONFIG_HMM) */
static inline void hmm_mm_destroy(struct mm_struct *mm) {} static inline void hmm_mm_destroy(struct mm_struct *mm) {}
static inline void hmm_mm_init(struct mm_struct *mm) {} static inline void hmm_mm_init(struct mm_struct *mm) {}

View File

@ -132,7 +132,6 @@ enum {
IORES_DESC_PERSISTENT_MEMORY = 4, IORES_DESC_PERSISTENT_MEMORY = 4,
IORES_DESC_PERSISTENT_MEMORY_LEGACY = 5, IORES_DESC_PERSISTENT_MEMORY_LEGACY = 5,
IORES_DESC_DEVICE_PRIVATE_MEMORY = 6, IORES_DESC_DEVICE_PRIVATE_MEMORY = 6,
IORES_DESC_DEVICE_PUBLIC_MEMORY = 7,
}; };
/* helpers to define resources */ /* helpers to define resources */

View File

@ -37,13 +37,6 @@ struct vmem_altmap {
* A more complete discussion of unaddressable memory may be found in * A more complete discussion of unaddressable memory may be found in
* include/linux/hmm.h and Documentation/vm/hmm.rst. * include/linux/hmm.h and Documentation/vm/hmm.rst.
* *
* MEMORY_DEVICE_PUBLIC:
* Device memory that is cache coherent from device and CPU point of view. This
* is use on platform that have an advance system bus (like CAPI or CCIX). A
* driver can hotplug the device memory using ZONE_DEVICE and with that memory
* type. Any page of a process can be migrated to such memory. However no one
* should be allow to pin such memory so that it can always be evicted.
*
* MEMORY_DEVICE_FS_DAX: * MEMORY_DEVICE_FS_DAX:
* Host memory that has similar access semantics as System RAM i.e. DMA * Host memory that has similar access semantics as System RAM i.e. DMA
* coherent and supports page pinning. In support of coordinating page * coherent and supports page pinning. In support of coordinating page
@ -58,7 +51,6 @@ struct vmem_altmap {
*/ */
enum memory_type { enum memory_type {
MEMORY_DEVICE_PRIVATE = 1, MEMORY_DEVICE_PRIVATE = 1,
MEMORY_DEVICE_PUBLIC,
MEMORY_DEVICE_FS_DAX, MEMORY_DEVICE_FS_DAX,
MEMORY_DEVICE_PCI_P2PDMA, MEMORY_DEVICE_PCI_P2PDMA,
}; };

View File

@ -944,7 +944,6 @@ static inline bool put_devmap_managed_page(struct page *page)
return false; return false;
switch (page->pgmap->type) { switch (page->pgmap->type) {
case MEMORY_DEVICE_PRIVATE: case MEMORY_DEVICE_PRIVATE:
case MEMORY_DEVICE_PUBLIC:
case MEMORY_DEVICE_FS_DAX: case MEMORY_DEVICE_FS_DAX:
__put_devmap_managed_page(page); __put_devmap_managed_page(page);
return true; return true;
@ -960,12 +959,6 @@ static inline bool is_device_private_page(const struct page *page)
page->pgmap->type == MEMORY_DEVICE_PRIVATE; page->pgmap->type == MEMORY_DEVICE_PRIVATE;
} }
static inline bool is_device_public_page(const struct page *page)
{
return is_zone_device_page(page) &&
page->pgmap->type == MEMORY_DEVICE_PUBLIC;
}
#ifdef CONFIG_PCI_P2PDMA #ifdef CONFIG_PCI_P2PDMA
static inline bool is_pci_p2pdma_page(const struct page *page) static inline bool is_pci_p2pdma_page(const struct page *page)
{ {
@ -998,11 +991,6 @@ static inline bool is_device_private_page(const struct page *page)
return false; return false;
} }
static inline bool is_device_public_page(const struct page *page)
{
return false;
}
static inline bool is_pci_p2pdma_page(const struct page *page) static inline bool is_pci_p2pdma_page(const struct page *page)
{ {
return false; return false;
@ -1431,10 +1419,8 @@ struct zap_details {
pgoff_t last_index; /* Highest page->index to unmap */ pgoff_t last_index; /* Highest page->index to unmap */
}; };
struct page *_vm_normal_page(struct vm_area_struct *vma, unsigned long addr, struct page *vm_normal_page(struct vm_area_struct *vma, unsigned long addr,
pte_t pte, bool with_public_device); pte_t pte);
#define vm_normal_page(vma, addr, pte) _vm_normal_page(vma, addr, pte, false)
struct page *vm_normal_page_pmd(struct vm_area_struct *vma, unsigned long addr, struct page *vm_normal_page_pmd(struct vm_area_struct *vma, unsigned long addr,
pmd_t pmd); pmd_t pmd);

View File

@ -718,17 +718,6 @@ config DEVICE_PRIVATE
memory; i.e., memory that is only accessible from the device (or memory; i.e., memory that is only accessible from the device (or
group of devices). You likely also want to select HMM_MIRROR. group of devices). You likely also want to select HMM_MIRROR.
config DEVICE_PUBLIC
bool "Addressable device memory (like GPU memory)"
depends on ARCH_HAS_HMM
select HMM
select DEV_PAGEMAP_OPS
help
Allows creation of struct pages to represent addressable device
memory; i.e., memory that is accessible from both the device and
the CPU
config FRAME_VECTOR config FRAME_VECTOR
bool bool

View File

@ -605,13 +605,6 @@ static int get_gate_page(struct mm_struct *mm, unsigned long address,
if ((gup_flags & FOLL_DUMP) || !is_zero_pfn(pte_pfn(*pte))) if ((gup_flags & FOLL_DUMP) || !is_zero_pfn(pte_pfn(*pte)))
goto unmap; goto unmap;
*page = pte_page(*pte); *page = pte_page(*pte);
/*
* This should never happen (a device public page in the gate
* area).
*/
if (is_device_public_page(*page))
goto unmap;
} }
if (unlikely(!try_get_page(*page))) { if (unlikely(!try_get_page(*page))) {
ret = -ENOMEM; ret = -ENOMEM;

View File

@ -1331,7 +1331,7 @@ EXPORT_SYMBOL(hmm_range_dma_unmap);
#endif /* IS_ENABLED(CONFIG_HMM_MIRROR) */ #endif /* IS_ENABLED(CONFIG_HMM_MIRROR) */
#if IS_ENABLED(CONFIG_DEVICE_PRIVATE) || IS_ENABLED(CONFIG_DEVICE_PUBLIC) #if IS_ENABLED(CONFIG_DEVICE_PRIVATE)
struct page *hmm_vma_alloc_locked_page(struct vm_area_struct *vma, struct page *hmm_vma_alloc_locked_page(struct vm_area_struct *vma,
unsigned long addr) unsigned long addr)
{ {
@ -1478,54 +1478,4 @@ struct hmm_devmem *hmm_devmem_add(const struct hmm_devmem_ops *ops,
return devmem; return devmem;
} }
EXPORT_SYMBOL_GPL(hmm_devmem_add); EXPORT_SYMBOL_GPL(hmm_devmem_add);
#endif /* CONFIG_DEVICE_PRIVATE */
struct hmm_devmem *hmm_devmem_add_resource(const struct hmm_devmem_ops *ops,
struct device *device,
struct resource *res)
{
struct hmm_devmem *devmem;
void *result;
int ret;
if (res->desc != IORES_DESC_DEVICE_PUBLIC_MEMORY)
return ERR_PTR(-EINVAL);
dev_pagemap_get_ops();
devmem = devm_kzalloc(device, sizeof(*devmem), GFP_KERNEL);
if (!devmem)
return ERR_PTR(-ENOMEM);
init_completion(&devmem->completion);
devmem->pfn_first = -1UL;
devmem->pfn_last = -1UL;
devmem->resource = res;
devmem->device = device;
devmem->ops = ops;
ret = percpu_ref_init(&devmem->ref, &hmm_devmem_ref_release,
0, GFP_KERNEL);
if (ret)
return ERR_PTR(ret);
devmem->pfn_first = devmem->resource->start >> PAGE_SHIFT;
devmem->pfn_last = devmem->pfn_first +
(resource_size(devmem->resource) >> PAGE_SHIFT);
devmem->page_fault = hmm_devmem_fault;
devmem->pagemap.type = MEMORY_DEVICE_PUBLIC;
devmem->pagemap.res = *devmem->resource;
devmem->pagemap.page_free = hmm_devmem_free;
devmem->pagemap.altmap_valid = false;
devmem->pagemap.ref = &devmem->ref;
devmem->pagemap.data = devmem;
devmem->pagemap.kill = hmm_devmem_ref_kill;
devmem->pagemap.cleanup = hmm_devmem_ref_exit;
result = devm_memremap_pages(devmem->device, &devmem->pagemap);
if (IS_ERR(result))
return result;
return devmem;
}
EXPORT_SYMBOL_GPL(hmm_devmem_add_resource);
#endif /* CONFIG_DEVICE_PRIVATE || CONFIG_DEVICE_PUBLIC */

View File

@ -354,7 +354,7 @@ static int madvise_free_pte_range(pmd_t *pmd, unsigned long addr,
continue; continue;
} }
page = _vm_normal_page(vma, addr, ptent, true); page = vm_normal_page(vma, addr, ptent);
if (!page) if (!page)
continue; continue;

View File

@ -4793,7 +4793,7 @@ enum mc_target_type {
static struct page *mc_handle_present_pte(struct vm_area_struct *vma, static struct page *mc_handle_present_pte(struct vm_area_struct *vma,
unsigned long addr, pte_t ptent) unsigned long addr, pte_t ptent)
{ {
struct page *page = _vm_normal_page(vma, addr, ptent, true); struct page *page = vm_normal_page(vma, addr, ptent);
if (!page || !page_mapped(page)) if (!page || !page_mapped(page))
return NULL; return NULL;
@ -4994,8 +4994,8 @@ out:
* 2(MC_TARGET_SWAP): if the swap entry corresponding to this pte is a * 2(MC_TARGET_SWAP): if the swap entry corresponding to this pte is a
* target for charge migration. if @target is not NULL, the entry is stored * target for charge migration. if @target is not NULL, the entry is stored
* in target->ent. * in target->ent.
* 3(MC_TARGET_DEVICE): like MC_TARGET_PAGE but page is MEMORY_DEVICE_PUBLIC * 3(MC_TARGET_DEVICE): like MC_TARGET_PAGE but page is MEMORY_DEVICE_PRIVATE
* or MEMORY_DEVICE_PRIVATE (so ZONE_DEVICE page and thus not on the lru). * (so ZONE_DEVICE page and thus not on the lru).
* For now we such page is charge like a regular page would be as for all * For now we such page is charge like a regular page would be as for all
* intent and purposes it is just special memory taking the place of a * intent and purposes it is just special memory taking the place of a
* regular page. * regular page.
@ -5029,8 +5029,7 @@ static enum mc_target_type get_mctgt_type(struct vm_area_struct *vma,
*/ */
if (page->mem_cgroup == mc.from) { if (page->mem_cgroup == mc.from) {
ret = MC_TARGET_PAGE; ret = MC_TARGET_PAGE;
if (is_device_private_page(page) || if (is_device_private_page(page))
is_device_public_page(page))
ret = MC_TARGET_DEVICE; ret = MC_TARGET_DEVICE;
if (target) if (target)
target->page = page; target->page = page;
@ -5101,8 +5100,8 @@ static int mem_cgroup_count_precharge_pte_range(pmd_t *pmd,
if (ptl) { if (ptl) {
/* /*
* Note their can not be MC_TARGET_DEVICE for now as we do not * Note their can not be MC_TARGET_DEVICE for now as we do not
* support transparent huge page with MEMORY_DEVICE_PUBLIC or * support transparent huge page with MEMORY_DEVICE_PRIVATE but
* MEMORY_DEVICE_PRIVATE but this might change. * this might change.
*/ */
if (get_mctgt_type_thp(vma, addr, *pmd, NULL) == MC_TARGET_PAGE) if (get_mctgt_type_thp(vma, addr, *pmd, NULL) == MC_TARGET_PAGE)
mc.precharge += HPAGE_PMD_NR; mc.precharge += HPAGE_PMD_NR;

View File

@ -1177,16 +1177,12 @@ static int memory_failure_dev_pagemap(unsigned long pfn, int flags,
goto unlock; goto unlock;
} }
switch (pgmap->type) { if (pgmap->type == MEMORY_DEVICE_PRIVATE) {
case MEMORY_DEVICE_PRIVATE:
case MEMORY_DEVICE_PUBLIC:
/* /*
* TODO: Handle HMM pages which may need coordination * TODO: Handle HMM pages which may need coordination
* with device-side memory. * with device-side memory.
*/ */
goto unlock; goto unlock;
default:
break;
} }
/* /*

View File

@ -571,8 +571,8 @@ static void print_bad_pte(struct vm_area_struct *vma, unsigned long addr,
* PFNMAP mappings in order to support COWable mappings. * PFNMAP mappings in order to support COWable mappings.
* *
*/ */
struct page *_vm_normal_page(struct vm_area_struct *vma, unsigned long addr, struct page *vm_normal_page(struct vm_area_struct *vma, unsigned long addr,
pte_t pte, bool with_public_device) pte_t pte)
{ {
unsigned long pfn = pte_pfn(pte); unsigned long pfn = pte_pfn(pte);
@ -585,29 +585,6 @@ struct page *_vm_normal_page(struct vm_area_struct *vma, unsigned long addr,
return NULL; return NULL;
if (is_zero_pfn(pfn)) if (is_zero_pfn(pfn))
return NULL; return NULL;
/*
* Device public pages are special pages (they are ZONE_DEVICE
* pages but different from persistent memory). They behave
* allmost like normal pages. The difference is that they are
* not on the lru and thus should never be involve with any-
* thing that involve lru manipulation (mlock, numa balancing,
* ...).
*
* This is why we still want to return NULL for such page from
* vm_normal_page() so that we do not have to special case all
* call site of vm_normal_page().
*/
if (likely(pfn <= highest_memmap_pfn)) {
struct page *page = pfn_to_page(pfn);
if (is_device_public_page(page)) {
if (with_public_device)
return page;
return NULL;
}
}
if (pte_devmap(pte)) if (pte_devmap(pte))
return NULL; return NULL;
@ -797,17 +774,6 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm,
rss[mm_counter(page)]++; rss[mm_counter(page)]++;
} else if (pte_devmap(pte)) { } else if (pte_devmap(pte)) {
page = pte_page(pte); page = pte_page(pte);
/*
* Cache coherent device memory behave like regular page and
* not like persistent memory page. For more informations see
* MEMORY_DEVICE_CACHE_COHERENT in memory_hotplug.h
*/
if (is_device_public_page(page)) {
get_page(page);
page_dup_rmap(page, false);
rss[mm_counter(page)]++;
}
} }
out_set_pte: out_set_pte:
@ -1063,7 +1029,7 @@ again:
if (pte_present(ptent)) { if (pte_present(ptent)) {
struct page *page; struct page *page;
page = _vm_normal_page(vma, addr, ptent, true); page = vm_normal_page(vma, addr, ptent);
if (unlikely(details) && page) { if (unlikely(details) && page) {
/* /*
* unmap_shared_mapping_pages() wants to * unmap_shared_mapping_pages() wants to

View File

@ -246,8 +246,6 @@ static bool remove_migration_pte(struct page *page, struct vm_area_struct *vma,
if (is_device_private_page(new)) { if (is_device_private_page(new)) {
entry = make_device_private_entry(new, pte_write(pte)); entry = make_device_private_entry(new, pte_write(pte));
pte = swp_entry_to_pte(entry); pte = swp_entry_to_pte(entry);
} else if (is_device_public_page(new)) {
pte = pte_mkdevmap(pte);
} }
} }
@ -381,7 +379,6 @@ static int expected_page_refs(struct address_space *mapping, struct page *page)
* ZONE_DEVICE pages. * ZONE_DEVICE pages.
*/ */
expected_count += is_device_private_page(page); expected_count += is_device_private_page(page);
expected_count += is_device_public_page(page);
if (mapping) if (mapping)
expected_count += hpage_nr_pages(page) + page_has_private(page); expected_count += hpage_nr_pages(page) + page_has_private(page);
@ -994,10 +991,7 @@ static int move_to_new_page(struct page *newpage, struct page *page,
if (!PageMappingFlags(page)) if (!PageMappingFlags(page))
page->mapping = NULL; page->mapping = NULL;
if (unlikely(is_zone_device_page(newpage))) { if (likely(!is_zone_device_page(newpage)))
if (is_device_public_page(newpage))
flush_dcache_page(newpage);
} else
flush_dcache_page(newpage); flush_dcache_page(newpage);
} }
@ -2265,7 +2259,7 @@ again:
pfn = 0; pfn = 0;
goto next; goto next;
} }
page = _vm_normal_page(migrate->vma, addr, pte, true); page = vm_normal_page(migrate->vma, addr, pte);
mpfn = migrate_pfn(pfn) | MIGRATE_PFN_MIGRATE; mpfn = migrate_pfn(pfn) | MIGRATE_PFN_MIGRATE;
mpfn |= pte_write(pte) ? MIGRATE_PFN_WRITE : 0; mpfn |= pte_write(pte) ? MIGRATE_PFN_WRITE : 0;
} }
@ -2406,16 +2400,7 @@ static bool migrate_vma_check_page(struct page *page)
* FIXME proper solution is to rework migration_entry_wait() so * FIXME proper solution is to rework migration_entry_wait() so
* it does not need to take a reference on page. * it does not need to take a reference on page.
*/ */
if (is_device_private_page(page)) return is_device_private_page(page);
return true;
/*
* Only allow device public page to be migrated and account for
* the extra reference count imply by ZONE_DEVICE pages.
*/
if (!is_device_public_page(page))
return false;
extra++;
} }
/* For file back page */ /* For file back page */
@ -2665,11 +2650,6 @@ static void migrate_vma_insert_page(struct migrate_vma *migrate,
swp_entry = make_device_private_entry(page, vma->vm_flags & VM_WRITE); swp_entry = make_device_private_entry(page, vma->vm_flags & VM_WRITE);
entry = swp_entry_to_pte(swp_entry); entry = swp_entry_to_pte(swp_entry);
} else if (is_device_public_page(page)) {
entry = pte_mkold(mk_pte(page, READ_ONCE(vma->vm_page_prot)));
if (vma->vm_flags & VM_WRITE)
entry = pte_mkwrite(pte_mkdirty(entry));
entry = pte_mkdevmap(entry);
} }
} else { } else {
entry = mk_pte(page, vma->vm_page_prot); entry = mk_pte(page, vma->vm_page_prot);
@ -2789,7 +2769,7 @@ static void migrate_vma_pages(struct migrate_vma *migrate)
migrate->src[i] &= ~MIGRATE_PFN_MIGRATE; migrate->src[i] &= ~MIGRATE_PFN_MIGRATE;
continue; continue;
} }
} else if (!is_device_public_page(newpage)) { } else {
/* /*
* Other types of ZONE_DEVICE page are not * Other types of ZONE_DEVICE page are not
* supported. * supported.

View File

@ -740,17 +740,6 @@ void release_pages(struct page **pages, int nr)
if (is_huge_zero_page(page)) if (is_huge_zero_page(page))
continue; continue;
/* Device public page can not be huge page */
if (is_device_public_page(page)) {
if (locked_pgdat) {
spin_unlock_irqrestore(&locked_pgdat->lru_lock,
flags);
locked_pgdat = NULL;
}
put_devmap_managed_page(page);
continue;
}
page = compound_head(page); page = compound_head(page);
if (!put_page_testzero(page)) if (!put_page_testzero(page))
continue; continue;