Skip to content

More about program memory#431

Draft
64J0 wants to merge 1 commit intomasterfrom
post-more-about-program-memory
Draft

More about program memory#431
64J0 wants to merge 1 commit intomasterfrom
post-more-about-program-memory

Conversation

@64J0
Copy link
Owner

@64J0 64J0 commented Aug 9, 2025

Summary by CodeRabbit

  • New Features

    • Published a new in-depth blog post on Linux process memory layout with practical, example-driven guidance and visuals.
  • Documentation

    • Covers user vs. kernel space, 64-bit address split, KPTI, syscall performance.
    • Includes hands-on tooling (strace, pmap, readelf), C examples, and command outputs.
    • Explains memory map fields (permissions, sharing, offsets, inodes, size, RSS) and ELF sections/program headers.
    • Notes CPU address-size realities (32/64-bit, 48/57-bit limits) and provides references.

@64J0 64J0 self-assigned this Aug 9, 2025
@64J0 64J0 added the post Post idea label Aug 9, 2025
@vercel
Copy link

vercel bot commented Aug 9, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
blog ✅ Ready (Inspect) Visit Preview 💬 Add feedback Aug 9, 2025 9:22pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 9, 2025

Walkthrough

Adds a new markdown blog post detailing Linux process memory layout, tooling (strace, pmap, readelf), architecture notes (lscpu, address sizes), example C programs, and references. No code or API changes; only documentation content is introduced.

Changes

Cohort / File(s) Summary
New blog post
posts/2025-08-09-more-about-program-memory.md
Introduces an example-driven article on Linux process memory layout, syscall observation, memory map inspection, ELF analysis, architecture/address-size notes, and references.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

Poem

A nibble, a hop through memory’s lane,
I trace the stacks and heaps like grain.
Syscalls twinkle—pmap sings,
readelf whispers sectioned things.
From userland to kernel’s keep—
I thump my foot, then cache and sleep. 🐇💾

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch post-more-about-program-memory

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@64J0
Copy link
Owner Author

64J0 commented Aug 26, 2025

@coderabbitai review

@64J0 64J0 requested a review from Copilot August 26, 2025 11:57
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 26, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds a new blog post titled "More about program memory layout" that provides a deeper dive into how programs are structured in computer memory, building upon a previous post. The content focuses on practical examples and tools for understanding memory management on Linux systems.

Key changes:

  • Adds comprehensive documentation about process address space, including kernel and user space divisions
  • Introduces practical Linux tools (strace, lscpu, pmap, readelf) for memory analysis
  • Provides code examples and command-line demonstrations for hands-on learning

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.


The output of using the *strace* tool will be a big chunk of text, showing all the syscalls performed by the process. And a bunch of those are related to setting the program to execute properly.

\*Something to keep in mind is that executing syscalls is not a cheap operation, so in order to improve a program's performance we can try to minimize the quantity of those.
Copy link

Copilot AI Aug 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The escaped asterisk should be plain text. Remove the backslash: '*Something to keep in mind...'

Suggested change
\*Something to keep in mind is that executing syscalls is not a cheap operation, so in order to improve a program's performance we can try to minimize the quantity of those.
*Something to keep in mind is that executing syscalls is not a cheap operation, so in order to improve a program's performance we can try to minimize the quantity of those.

Copilot uses AI. Check for mistakes.
But wait. How big is the process address space? The following table must help understand.

| 32-bit processors | 64-bit processors |
|----------------- |------------------ |
Copy link

Copilot AI Aug 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The table separator has inconsistent dashes. Should be consistent: '|------------------|-------------------|'

Suggested change
|----------------- |------------------ |
|------------------|-------------------|

Copilot uses AI. Check for mistakes.
Comment on lines +159 to +160
```
...
Copy link

Copilot AI Aug 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code block is incomplete. The content after '...' on line 160 appears to be cut off, leaving an unfinished section before the References.

Suggested change
```
...

Copilot uses AI. Check for mistakes.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (12)
posts/2025-08-09-more-about-program-memory.md (12)

2-6: Front‑matter looks good; consider adding an excerpt/description for previews.

If your blog engine supports it, adding an description:/excerpt: improves SEO and list-page previews. Also confirm show: true is the intended flag on your platform.

What front‑matter keys does your static site generator support for summaries (e.g., description, summary, image)? Want me to add them now?


22-32: Use a neutral code fence for the ASCII diagram.

Labeling the block as bash suggests it’s executable. Prefer text for readability and correct syntax highlighting.

-```bash
+```text
 # +--------------------+
 # |                    |
 # |    Kernel space    |
 # |                    |
 # +--------------------+
 # |                    |
 # |    User space      |
 # |                    |
 # +--------------------+

---

`38-43`: **Polish the bullets and clarify the KPTI sentence.**

- “Less trashing TLB” → “Less TLB thrashing”.
- The KPTI line has a double negative feel. Rephrase for clarity.


```diff
--   Less trashing TLB (Translation Lookaside Buffer)
+-   Less TLB thrashing (Translation Lookaside Buffer)
-
-In modern Linux, for security reasons, the entire kernel is usually not always mapped. If you'd like to get a better understanding of this, search for Linux KPTI (Linux Kernel Page-Table Isolation).
+In modern Linux, for security reasons, the kernel is not always mapped into user page tables (see KPTI: Kernel Page‑Table Isolation).

44-48: Use a proper heading instead of bold to satisfy markdownlint (MD036).

Currently this triggers “Emphasis used instead of a heading.”

-**Kernel space**
+### Kernel space

49-58: Make the compile command broadly portable.

Not every system has clang-18 on PATH. Using cc or clang + -O2 -g -Wall makes the snippet copy/paste‑friendly.

-// clang-18 main.c -o userProgram
+// cc -O2 -g -Wall main.c -o userProgram

74-77: Tighten the wording.

Minor style polish and accuracy note: syscalls are relatively expensive compared to userspace calls, so minimizing them in hot paths can help.

-*Something to keep in mind is that executing syscalls is not a cheap operation, so in order to improve a program's performance we can try to minimize the quantity of those.
+*Note: Syscalls are relatively expensive compared to userspace calls, so to improve performance—especially in hot paths—minimize their number when practical.

91-95: Clarify “address sizes” as virtual address size.

lscpu reports “Address sizes” (physical, virtual). Explicitly calling out “virtual address size” avoids confusion with physical address width.

-The result presents many details of your CPU, including the total cache size discriminated by the cache level, and the address sizes, which in my case uses 48 bits.
+The result presents many details of your CPU, including cache sizes and the virtual address size (48 bits on my machine).

124-130: Nice use of $! and -XX; add a small robustness note.

This works because the process is paused by getchar(). It might be worth mentioning that without the pause the backgrounded process can exit before pmap runs.


140-147: Tighten the pmap columns description and casing.

  • “p” stands for private and “s” for shared.
  • “inode” is lowercase; “RSS” should be uppercase.
  • Clarify that “Size” is virtual, “RSS” is resident in physical memory; -XX adds more details (like Dirty/Clean).
-Next, after the column that presents the memory address for where that section starts, we have a column showing the permissions for the memory location, which could be the conventional read, write and execute, and there's an additional setting that defines if the memory address can be shared with other processes or not (p is for private).
+Next to the start address, pmap shows permissions (r/w/x) and whether the mapping is private (`p`) or shared (`s`).
@@
-Next, the Inode in Linux specifies the file id. So, if the Inode repeats at this table it means that the same file is being mapped into the process' memory addresses, maybe changing only the offset.
+Next, the inode specifies the file id. If the inode repeats, the same file is mapped multiple times, possibly at different offsets.
@@
-Then we have the Size column, which specifies the size of the memory segment in bytes, and Rss specifies what part of this memory segment is actually in physical memory.
+Then we have the Size column (virtual bytes of the mapping) and RSS (resident bytes currently in physical memory). With `-XX`, you’ll also see additional breakdowns (e.g., Clean/Dirty).

150-159: Minor readelf improvements.

-W avoids line wrapping for long names on 64‑bit ELFs; the comment is clearer as “WHAT to load WHERE” on one line.

-# check what are the sections of the ELF file:
-readelf -S userProgram
+# list the sections in the ELF file
+readelf -W -S userProgram
@@
-# to display the program headers, which stores the information of WHAT to load
-# WHERE:
-readelf -l userProgram
+# display the program headers (WHAT to load WHERE)
+readelf -W -l userProgram

162-167: References look useful; consider adding one authoritative spec link.

Adding a canonical-addressing reference (e.g., Intel® SDM or AMD64 APM volume covering canonical addresses) would strengthen the sections on VA widths and halves.

I can add vendor-manual citations and permalinks if you want.


97-105: Clarify table semantics and tidy formatting.

  • Label the 64-bit column as implemented virtual address widths.
  • Correct numeric values and clean up spacing.
  • Refine wording to distinguish the ISA’s theoretical limit from real implementations.
-| 32-bit processors | 64-bit processors  |
-|----------------- |------------------ |
-| 2^32 bytes = 4GB  | 2^48 bytes = 256TB |
-|                   | 2^57 bytes = 4PB   |
+| 32-bit processors | 64-bit processors (implemented VA) |
+|-------------------|------------------------------------|
+| 2^32 bytes = 4 GB | 2^48 bytes = 256 TB               |
+|                   | 2^57 bytes = 128 PB               |
-As you can see, there are currently two possibilities for 64-bit processors, and both use less than 64 bits. Why don't we have 2^64 bytes on 64-bit processors?
+As you can see, there are two common virtual address widths in 64-bit systems, both less than the full 64 bits. Why don’t we have 2^64 bytes of virtual address space?
-Well, the explanation is related to current implementation limitations. Even though 2^64 (16 exabytes) is the theoretical limit for this architecture, 48 and 57 bits is what current implementations support for practical reasons.
+Because of page-table and hardware design trade-offs, the implemented canonical virtual address widths are typically 48 or 57 bits. The ISA’s theoretical 2^64 (16 exabytes) virtual address space isn’t fully implemented in mainstream CPUs.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between e17337a and 9e57494.

⛔ Files ignored due to path filters (2)
  • public/post-images/more-about-program-memory/lscpu-001.png is excluded by !**/*.png
  • public/post-images/more-about-program-memory/pmap-001.png is excluded by !**/*.png
📒 Files selected for processing (1)
  • posts/2025-08-09-more-about-program-memory.md (1 hunks)
🧰 Additional context used
🪛 LanguageTool
posts/2025-08-09-more-about-program-memory.md

[grammar] ~38-~38: There might be a mistake here.
Context: ...mance benefits: - Cheaper mode switch - Cheaper context switch (kernel stays map...

(QB_NEW_EN)


[grammar] ~39-~39: There might be a mistake here.
Context: ...per context switch (kernel stays mapped) - Less trashing TLB (Translation Lookaside...

(QB_NEW_EN)


[style] ~76-~76: Consider a more concise word here.
Context: ...g syscalls is not a cheap operation, so in order to improve a program's performance we can ...

(IN_ORDER_TO_PREMIUM)


[grammar] ~98-~98: There might be a mistake here.
Context: ...|----------------- |------------------ | | 2^32 bytes = 4GB | 2^48 bytes = 256TB...

(QB_NEW_EN)


[grammar] ~99-~99: There might be a mistake here.
Context: ...2^32 bytes = 4GB | 2^48 bytes = 256TB | | | 2^57 bytes = 4PB ...

(QB_NEW_EN)


[style] ~140-~140: In contexts where ‘if’ is followed by ‘or’, using ‘whether’ may be more appropriate (and formal).
Context: ...re's an additional setting that defines if the memory address can be shared with o...

(IF_WHETHER)


[grammar] ~166-~166: There might be a mistake here.
Context: ...s://landley.net/writing/memory-faq.txt).

(QB_NEW_EN)

🪛 markdownlint-cli2 (0.17.2)
posts/2025-08-09-more-about-program-memory.md

44-44: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

Comment on lines +34 to +36
On Linux using 64-bit processors and x86-64 architecture, by default the memory is split 50% for the kernel space and 50% for the user space. This is configurable using some flags.

And why we map both the kernel and the user program memory into a single memory space? The answer is that this brings some performance benefits:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

❓ Verification inconclusive

Qualify the “50/50 split” and the “configurable flags” claim.

On x86‑64 with 4‑level paging (48‑bit canonical addresses), Linux maps user space in the lower half and kernel in the upper half (effectively 50/50 of the implemented VA, not the theoretical 64 bits). With 5‑level paging (57‑bit), the split and limits differ. Calling this “configurable using some flags” is vague and may mislead; it isn’t a simple runtime toggle and depends on kernel build/CPU features.

-On Linux using 64-bit processors and x86-64 architecture, by default the memory is split 50% for the kernel space and 50% for the user space. This is configurable using some flags.
+On Linux/x86‑64, with the commonly deployed 4‑level page tables (48‑bit canonical addresses), user space occupies the lower canonical half and the kernel the upper canonical half (effectively a 50/50 split of the implemented VA width). With 5‑level paging (57‑bit), limits and layout differ. These are architecture/kernel‑configuration decisions rather than simple runtime flags.

🌐 Web query:

Confirm the user/kernel virtual address split for Linux on x86-64 with 4-level and 5-level paging and whether it’s adjustable via kernel config or runtime flags.

Error during web search


Clarify x86-64 VA split and remove vague flags claim

On Linux/x86-64, the “50/50 split” refers to equal halves of the implemented virtual address space—under 4-level paging (48-bit canonical addresses), the lower 2¹⁴⁷ bytes (~128 TiB) are for user-space and the upper 2¹⁴⁷ bytes for kernel-space. With 5-level paging (57-bit), enabled via the CONFIG_X86_5LEVEL kernel configuration, the VA space grows to 2⁵⁷ bytes (~128 PiB) and is likewise split into two 2⁵⁶-byte halves (~64 PiB each). These divisions are determined by CPU architecture and build-time settings, not by simple runtime flags. (mjmwired.net, docs.kernel.org)

Please update the text accordingly (in posts/2025-08-09-more-about-program-memory.md):

-On Linux using 64-bit processors and x86-64 architecture, by default the memory is split 50% for the kernel space and 50% for the user space. This is configurable using some flags.
+On Linux/x86-64, with the standard 4-level page tables (48-bit canonical addresses), user-space occupies the lower 2¹⁴⁷ bytes (~128 TiB) and the kernel the upper 2¹⁴⁷ bytes. With 5-level paging (57-bit), enabled via CONFIG_X86_5LEVEL, the VA space extends to 2⁵⁷ bytes (~128 PiB) and is similarly divided into 2⁵⁶-byte halves (~64 PiB each). These layouts arise from the CPU architecture and kernel build-time configuration rather than simple runtime flags.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
On Linux using 64-bit processors and x86-64 architecture, by default the memory is split 50% for the kernel space and 50% for the user space. This is configurable using some flags.
And why we map both the kernel and the user program memory into a single memory space? The answer is that this brings some performance benefits:
On Linux/x86-64, with the standard 4-level page tables (48-bit canonical addresses), user-space occupies the lower 2¹⁴⁷ bytes (~128 TiB) and the kernel the upper 2¹⁴⁷ bytes. With 5-level paging (57-bit), enabled via CONFIG_X86_5LEVEL, the VA space extends to 2⁵⁷ bytes (~128 PiB) and is similarly divided into 2⁵⁶-byte halves (~64 PiB each). These layouts arise from the CPU architecture and kernel build-time configuration rather than simple runtime flags.
And why we map both the kernel and the user program memory into a single memory space? The answer is that this brings some performance benefits:
🤖 Prompt for AI Agents
In posts/2025-08-09-more-about-program-memory.md around lines 34 to 36, replace
the vague “50% for the kernel/user” and “some flags” wording with a precise
explanation: state that on x86-64 the default split refers to equal halves of
the implemented virtual address space (under 4-level paging/48-bit canonical
addresses the lower 2^47 bytes are user and the upper 2^47 bytes are kernel;
with 5-level paging/57-bit addresses enabled via CONFIG_X86_5LEVEL the VA space
grows accordingly to 2^57 bytes and is split into two 2^56-byte halves), and
clarify that these divisions are determined by CPU architecture and kernel
build-time configuration rather than simple runtime flags; remove the original
“some flags” claim and adjust the transition sentence leading into the
performance benefits accordingly.

Comment on lines +62 to +72
```bash
# compile the program
clang-18 main.c -o userProgram

# show the syscalls performed by the process
strace ./userProgram

# and count the quantity of syscalls
strace ./userProgram 2>&1 | wc -l
# which gives me 37 syscalls performed
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Count syscalls with strace’s built‑in -c rather than wc -l.

wc -l counts lines, not syscalls, and includes non‑syscall output. strace -c summarizes syscall counts and time.

-# show the syscalls performed by the process
-strace ./userProgram
-
-# and count the quantity of syscalls
-strace ./userProgram 2>&1 | wc -l
-# which gives me 37 syscalls performed
+# show the syscalls performed by the process
+strace -o /dev/stderr ./userProgram
+
+# and count/summary of syscalls
+strace -qq -c ./userProgram
+# sample output: calls, errors, total time per syscall
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
```bash
# compile the program
clang-18 main.c -o userProgram
# show the syscalls performed by the process
strace ./userProgram
# and count the quantity of syscalls
strace ./userProgram 2>&1 | wc -l
# which gives me 37 syscalls performed
```
🤖 Prompt for AI Agents
In posts/2025-08-09-more-about-program-memory.md around lines 62 to 72, the
guide uses `strace ./userProgram 2>&1 | wc -l` to count syscalls which is
incorrect because wc counts lines and can include non‑syscall output; replace
that step with using strace’s built‑in summary mode (`strace -c ./userProgram`)
and update the explanatory text to say to read the syscall counts from the
strace summary output (and adjust the stated “37 syscalls” result if the summary
reports a different count).

Comment on lines +136 to +139
Notice that in this table, except from the first memory address which is 64-bit size, the others are 48-bit size, as expected.

Other than that, something else to keep in mind is that, in Linux, memory addresses with 48-bits, where the most significant bit is 1 (48th bit) are associated with the kernel space. If this bit is 0, then this memory address is associated with the user space.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

❓ Verification inconclusive

Fix canonical-addressing explanation (bit numbering and zero‑padding).

  • pmap prints 64‑bit zero‑padded values; user addresses “look” 64‑bit even if only 48 bits are canonical.
  • On x86‑64 with 4‑level paging, bit 47 being 1 means the upper canonical half; bits 63..48 are sign‑extended to 1. Calling it “the 48th bit is 1 ⇒ kernel” is imprecise and kernel/user is a convention, not solely the bit value.
-Notice that in this table, except from the first memory address which is 64-bit size, the others are 48-bit size, as expected.
-Other than that, something else to keep in mind is that, in Linux, memory addresses with 48-bits, where the most significant bit is 1 (48th bit) are associated with the kernel space. If this bit is 0, then this memory address is associated with the user space.
+Note: pmap prints zero‑padded 64‑bit hex addresses; user addresses are still displayed as 64‑bit even though only the lower 48 bits are canonical (with 4‑level paging).
+On x86‑64 (4‑level), canonical addresses have bits 63..48 equal to bit 47. Addresses with bit 47 = 0 belong to the lower canonical half (user space on Linux), and bit 47 = 1 to the upper canonical half (where Linux maps the kernel).

🌐 Web query:

Verify canonical address rules on x86-64 (sign-extension of bit 47 for 4-level, bit 56 for 5-level) from AMD64/Intel manuals or Linux memory layout docs.

Error during web search


Clarify x86-64 canonical address explanation (bit numbering and zero-padding)

File posts/2025-08-09-more-about-program-memory.md, lines 136–139

• pmap prints full 64-bit zero-padded hex addresses; user-space pointers still look 64-bit even though only the lower 48 bits are valid (4-level paging).
• On x86-64 with 4-level paging, valid “canonical” addresses must have bits 63..48 set equal to bit 47 (sign-extension).
– bit 47 = 0 ⇒ addresses 0x0000_0000_0000_0000…0x0000_7FFF_FFFF_FFFF (lower half; user space conventionally)
– bit 47 = 1 ⇒ addresses 0xFFFF_8000_0000_0000…0xFFFF_FFFF_FFFF_FFFF (upper half; kernel space conventionally)
• Referring to “the 48th bit” is imprecise—canonicality is enforced by sign-extending bit 47 into bits 48–63, and user/kernel mapping is a Linux convention, not an inherent hardware rule.

Suggested diff:

-Notice that in this table, except from the first memory address which is 64-bit size, the others are 48-bit size, as expected.
-Other than that, something else to keep in mind is that, in Linux, memory addresses with 48-bits, where the most significant bit is 1 (48th bit) are associated with the kernel space. If this bit is 0, then this memory address is associated with the user space.
+Note: pmap prints zero-padded 64-bit hex addresses; user-space pointers still appear 64-bit even though only the lower 48 bits are canonical (4-level paging).
+On x86-64 with 4-level paging, canonical addresses require bits 63..48 to replicate bit 47 (sign-extension):
+  - bit 47 = 0 ⇒ 0x0000_0000_0000_0000…0x0000_7FFF_FFFF_FFFF (lower canonical half; user space by Linux convention)
+  - bit 47 = 1 ⇒ 0xFFFF_8000_0000_0000…0xFFFF_FFFF_FFFF_FFFF (upper canonical half; kernel space by Linux convention)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Notice that in this table, except from the first memory address which is 64-bit size, the others are 48-bit size, as expected.
Other than that, something else to keep in mind is that, in Linux, memory addresses with 48-bits, where the most significant bit is 1 (48th bit) are associated with the kernel space. If this bit is 0, then this memory address is associated with the user space.
Note: pmap prints zero-padded 64-bit hex addresses; user-space pointers still appear 64-bit even though only the lower 48 bits are canonical (4-level paging).
On x86-64 with 4-level paging, canonical addresses require bits 63..48 to replicate bit 47 (sign-extension):
- bit 47 = 0 ⇒ 0x0000_0000_0000_0000…0x0000_7FFF_FFFF_FFFF (lower canonical half; user space by Linux convention)
- bit 47 = 1 ⇒ 0xFFFF_8000_0000_0000…0xFFFF_FFFF_FFFF_FFFF (upper canonical half; kernel space by Linux convention)
🤖 Prompt for AI Agents
In posts/2025-08-09-more-about-program-memory.md around lines 136–139, update
the paragraph to correctly describe x86-64 canonical addresses and pmap output:
explain that pmap prints full 64-bit zero‑padded hex addresses so user pointers
appear 64-bit though only the low 48 bits (4-level paging) are meaningful;
replace the imprecise “48th bit” wording with the canonicality rule that bits
63..48 must equal bit 47 (sign‑extension), and show the two ranges: bit47=0 →
0x0000_0000_0000_0000..0x0000_7FFF_FFFF_FFFF (lower half, user space convention)
and bit47=1 → 0xFFFF_8000_0000_0000..0xFFFF_FFFF_FFFF_FFFF (upper half, kernel
space convention); also note that the user/kernel division is a Linux convention
rather than a hardware rule and that canonicality is enforced by sign‑extension
of bit47 into bits48–63.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

post Post idea

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants