Thursday, November 5, 2026

Understanding the Building Blocks of Persistent Memory in Linux : PMEM DAX Folios

  

Introduction

When debugging DAX-related issues, engineers often encounter terms like:

  • PMEM

  • devdax

  • fsdax

  • folio

  • compound page

  • page order

  • MAX_FOLIO_ORDER

  • vmemmap_shift

This blog explains how these concepts fit together and why a seemingly simple operation such as creating a DAX namespace can trigger complex memory-management behavior inside the kernel.


What is Persistent Memory (PMEM)?





Persistent Memory (PMEM) is storage that retains data across power cycles while being directly addressable like memory.

Traditionally:

TechnologyFastPersistent
DRAM✅ Yes❌ No
SSD/HDD❌ No✅ Yes
PMEM✅ Yes✅ Yes

PMEM combines characteristics of both memory and storage.

Examples include:

  • Intel Optane Persistent Memory

  • NVDIMM

  • Future CXL-attached persistent memory devices




Where is PMEM Located?




Think of PMEM as being physically attached to the memory subsystem rather than accessed through traditional storage controllers.

Traditional storage path:

Application
      ↓
Page Cache
      ↓
SSD / NVMe
----------------------

PMEM path:

Application
      ↓
CPU Memory Bus
      ↓
Persistent Memory

On Power systems and x86 systems, PMEM is exposed to Linux as a memory region that can be mapped directly into applications.

You can view PMEM devices using:

ndctl list

or

daxctl list

What is DAX?

DAX stands for Direct Access.

DAX allows applications to bypass the page cache and directly access persistent memory.

Without DAX:

Application
      ↓
Page Cache
      ↓
Storage Device

With DAX:

Application
      ↓
Persistent Memory

This removes:

  • Extra memory copies

  • Page cache overhead

  • Additional latency

Benefits:

  • Faster databases

  • Lower latency

  • Better HPC performance

  • Reduced memory consumption


Types of DAX

1. Filesystem DAX (fsdax)

Uses a filesystem such as:

  • XFS

  • ext4

Example:

PMEM
 └── XFS (DAX enabled)
      └── File

Applications access files directly from persistent memory.


2. Device DAX (devdax)

Provides direct raw access to the PMEM device.

Example:

/dev/dax0.0

Applications mmap() the region directly.

No filesystem is involved.

Creation example:

ndctl create-namespace \
    --mode=devdax

What is a Folio?

A folio is a Linux kernel memory object used to represent one or more physically contiguous pages.

Before folios:

struct page

represented every individual page.

Now:

struct folio

can represent:

  • 1 page

  • 2 pages

  • 512 pages

  • 16384 pages

as a single unit.

Benefits:

  • Less memory-management overhead

  • Better performance

  • Improved page-cache scalability


Understanding Page Order

Linux measures compound page size using order.

Formula:

Size = PAGE_SIZE × 2^order

For ppc64le:

PAGE_SIZE = 64 KB

Examples:

OrderSize
064 KB
1128 KB
2256 KB
41 MB
52 MB
1064 MB
141 GB

For example:

64 KB × 2^14
= 1 GB

Therefore:

Order 14 = 1 GB object

What is a Compound Page?

A compound page is a collection of many base pages treated as a single memory object.

Example:

Compound Page
     │
 ├── Page 0
 ├── Page 1
 ├── Page 2
 ├── ...
 └── Page N

Instead of handling thousands of pages individually, Linux manages them as a single object.

This improves:

  • TLB efficiency

  • Memory management

  • Mapping performance


What is a DAX Folio?

A DAX folio is simply a folio backing DAX memory.

Normal memory:

RAM
 ↓
Folio

DAX memory:

Persistent Memory
      ↓
ZONE_DEVICE
      ↓
DAX Folio

A DAX folio represents PMEM pages that can be directly mapped into applications.


How a 1 GB DAX Folio Gets Created

Suppose we create:

ndctl create-namespace \
    --mode=devdax \
    -a 1073741824

Notice:

1073741824 = 1 GB

The kernel interprets this alignment requirement and calculates:

PAGE_SHIFT = 16

because:

64 KB pages

and

1 GB = 2^30

Therefore:

Order = 30 - 16
       = 14

Linux now attempts to create:

Order-14 folio

which represents:

16384 pages

or:

1 GB DAX folio

Why Does MAX_FOLIO_ORDER Matter?

The kernel limits how large a folio can be.

Inside memory management code:

folio_set_order(folio, order);

Linux verifies:

VM_WARN_ON_ONCE(order > MAX_FOLIO_ORDER);

This prevents creation of excessively large folios.

If:

Order = 14

but

MAX_FOLIO_ORDER < 14

then Linux generates:

VM_WARN_ON_ONCE()

indicating the folio exceeds supported limits.


Real Example

User creates:

ndctl create-namespace \
    --mode=devdax \
    -a 1073741824

Kernel receives:

1 GB aligned PMEM range

Kernel computes:

Order 14 folio

During initialization:

memremap_pages()
    ↓
memmap_init_zone_device()
    ↓
memmap_init_compound()
    ↓
prep_compound_head()
    ↓
folio_set_order()

Kernel checks:

order > MAX_FOLIO_ORDER

and generates a warning if the architecture does not support such a large folio.


Commands Useful for DAX Investigation

Commands Useful for DAX Investigation

List PMEM devices

ndctl list

Show namespaces

ndctl list -N

Show DAX devices

daxctl list

View PMEM regions

ndctl list -R

Check memory block size

getconf PAGE_SIZE

Check DAX device

ls -l /dev/dax*

View DAX mappings

dmesg | grep dax

View compound page warnings

dmesg | grep -i folio

Key Takeaways

  • PMEM is persistent memory that combines storage persistence with memory-like access.

  • DAX allows direct access to PMEM without page cache involvement.

  • devdax exposes PMEM as a raw memory device.

  • Folios are Linux memory objects representing one or more pages.

  • Order defines folio size as PAGE_SIZE × 2^order.

  • On ppc64le with 64 KB pages, a 1 GB DAX alignment translates to order 14.

  • The kernel creates a DAX folio to represent that PMEM region.

  • If the calculated order exceeds MAX_FOLIO_ORDER, Linux triggers a warning during DAX initialization.

Final One-Line Summary DAX device

ls -l /dev/dax*

View DAX mappings

dmesg | grep dax

View compound page warnings

dmesg | grep -i folio

Key Takeaways

  • PMEM is persistent memory that combines storage persistence with memory-like access.

  • DAX allows direct access to PMEM without page cache involvement.

  • devdax exposes PMEM as a raw memory device.

  • Folios are Linux memory objects representing one or more pages.

  • Order defines folio size as PAGE_SIZE × 2^order.

  • On ppc64le with 64 KB pages, a 1 GB DAX alignment translates to order 14.

  • The kernel creates a DAX folio to represent that PMEM region.

  • If the calculated order exceeds MAX_FOLIO_ORDER, Linux triggers a warning during DAX initialization.

DAX enables direct access to persistent memory, and a DAX folio is the kernel's representation of that PMEM region; large DAX alignments can create large compound folios whose order may exceed architecture-specific folio limits.

No comments:

Post a Comment