<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://homeostasis.scs.carleton.ca/wiki/index.php?action=history&amp;feed=atom&amp;title=Operating_Systems_2022F%3A_Tutorial_9</id>
	<title>Operating Systems 2022F: Tutorial 9 - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://homeostasis.scs.carleton.ca/wiki/index.php?action=history&amp;feed=atom&amp;title=Operating_Systems_2022F%3A_Tutorial_9"/>
	<link rel="alternate" type="text/html" href="https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2022F:_Tutorial_9&amp;action=history"/>
	<updated>2026-04-05T22:41:23Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.42.1</generator>
	<entry>
		<id>https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2022F:_Tutorial_9&amp;diff=24134&amp;oldid=prev</id>
		<title>Soma: /* Watching Kernel Memory Allocations */</title>
		<link rel="alternate" type="text/html" href="https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2022F:_Tutorial_9&amp;diff=24134&amp;oldid=prev"/>
		<updated>2022-11-07T16:26:06Z</updated>

		<summary type="html">&lt;p&gt;&lt;span dir=&quot;auto&quot;&gt;&lt;span class=&quot;autocomment&quot;&gt;Watching Kernel Memory Allocations&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 16:26, 7 November 2022&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l32&quot;&gt;Line 32:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 32:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;==Watching Kernel Memory Allocations==&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;==Watching Kernel Memory Allocations==&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Now let&amp;#039;s trace various kernel memory allocations outside of our module.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Now let&amp;#039;s trace various kernel memory allocations outside of our module.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;# &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Run &lt;/del&gt;&amp;lt;tt&amp;gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;sudo &lt;/del&gt;trace -M 100 -K &#039;t:kmem:kmalloc printf &quot;allocated %d bytes at address 0x%llx&quot; args-&amp;gt;bytes_alloc, args-&amp;gt;ptr&#039;&amp;lt;/tt&amp;gt; to trace the next 100 slab allocations and print the kernel stack. You may wish to pipe this output into &amp;lt;tt&amp;gt;less&amp;lt;/tt&amp;gt; to read it more easily. What do you notice about the kernel&#039;s virtual addresses compared to what you have seen in userspace? Hint: Check the most significant hex digits.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;# &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;As root run &lt;/ins&gt;&amp;lt;tt&amp;gt;trace -M 100 -K &#039;t:kmem:kmalloc printf &quot;allocated %d bytes at address 0x%llx&quot; args-&amp;gt;bytes_alloc, args-&amp;gt;ptr&#039;&amp;lt;/tt&amp;gt; to trace the next 100 slab allocations and print the kernel stack. You may wish to pipe this output into &amp;lt;tt&amp;gt;less&amp;lt;/tt&amp;gt; to read it more easily. What do you notice about the kernel&#039;s virtual addresses compared to what you have seen in userspace? Hint: Check the most significant hex digits.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;# &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Run &lt;/del&gt;&amp;lt;tt&amp;gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;sudo &lt;/del&gt;trace -M 100 -K &#039;t:kmem:mm_page_alloc printf &quot;allocted 2^%d pages at page frame number %lu&quot; args-&amp;gt;order, args-&amp;gt;pfn&#039;&amp;lt;/tt&amp;gt; to trace the next 100 page allocations and print the kernel stack. You may wish to pipe this output into &amp;lt;tt&amp;gt;less&amp;lt;/tt&amp;gt; to read it more easily. Based on what you can see, does page allocation seem to differ from slab allocation? How so?&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;# &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;As root run &lt;/ins&gt;&amp;lt;tt&amp;gt;trace -M 100 -K &#039;t:kmem:mm_page_alloc printf &quot;allocted 2^%d pages at page frame number %lu&quot; args-&amp;gt;order, args-&amp;gt;pfn&#039;&amp;lt;/tt&amp;gt; to trace the next 100 page allocations and print the kernel stack. You may wish to pipe this output into &amp;lt;tt&amp;gt;less&amp;lt;/tt&amp;gt; to read it more easily. Based on what you can see, does page allocation seem to differ from slab allocation? How so?&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;==Code==&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;==Code==&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Soma</name></author>
	</entry>
	<entry>
		<id>https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2022F:_Tutorial_9&amp;diff=24133&amp;oldid=prev</id>
		<title>Soma: Created page with &quot;==Introduction== WARNING: The commands and programs in this tutorial are potentially extremely dangerous and may result in crashes or loss of data. Additionally, questions may not work as expected on a machine other than the course VM. For that reason, you are strongly encouraged to do this tutorial on the provided OpenStack virtual machine.  In this tutorial we will be examining the physical memory mapping of processes with the help of a kernel module that performs a 5-...&quot;</title>
		<link rel="alternate" type="text/html" href="https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2022F:_Tutorial_9&amp;diff=24133&amp;oldid=prev"/>
		<updated>2022-11-07T16:25:21Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;==Introduction== WARNING: The commands and programs in this tutorial are potentially extremely dangerous and may result in crashes or loss of data. Additionally, questions may not work as expected on a machine other than the course VM. For that reason, you are strongly encouraged to do this tutorial on the provided OpenStack virtual machine.  In this tutorial we will be examining the physical memory mapping of processes with the help of a kernel module that performs a 5-...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;==Introduction==&lt;br /&gt;
WARNING: The commands and programs in this tutorial are potentially extremely dangerous and&lt;br /&gt;
may result in crashes or loss of data. Additionally, questions may not work as expected on&lt;br /&gt;
a machine other than the course VM. For that reason, you are strongly encouraged to do this tutorial on the provided OpenStack virtual machine.&lt;br /&gt;
&lt;br /&gt;
In this tutorial we will be examining the physical memory mapping&lt;br /&gt;
of processes with the help of a kernel module that performs a 5-level&lt;br /&gt;
page table walk for userspace addresses. You may wish to&lt;br /&gt;
[https://en.m.wikipedia.org/wiki/Intel_5-level_paging read about 5-level paging].&lt;br /&gt;
&lt;br /&gt;
To get started, we will first examine the source code for &amp;lt;tt&amp;gt;3000physicalview.c&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;3000memview2.c&amp;lt;/tt&amp;gt;, both of which are in [https://homeostasis.scs.carleton.ca/~soma/os-2021f/code/3000physicalview.tar.gz 3000physicalview.tar.gz].&lt;br /&gt;
&lt;br /&gt;
==Getting Started==&lt;br /&gt;
# Download [https://homeostasis.scs.carleton.ca/~soma/os-2021f/code/3000physicalview.tar.gz 3000physicalview.tar.gz] and unpack with the command &amp;lt;tt&amp;gt;tar xzf 3000physicalview.tar.gz&amp;lt;/tt&amp;gt;.  Compile &amp;lt;tt&amp;gt;3000physicalview&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;3000memview2&amp;lt;/tt&amp;gt; using the provided Makefile (i.e. by running &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt;).&lt;br /&gt;
# Insert &amp;lt;tt&amp;gt;3000physicalview&amp;lt;/tt&amp;gt; by running &amp;lt;tt&amp;gt;make insert&amp;lt;/tt&amp;gt;. Confirm that the module is inserted using &amp;lt;tt&amp;gt;lsmod&amp;lt;/tt&amp;gt;.&lt;br /&gt;
# Examine the call to &amp;lt;tt&amp;gt;copy_from_user&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;copy_to_user&amp;lt;/tt&amp;gt; on lines 120 and 132 of &amp;lt;tt&amp;gt;3000physicalview.c&amp;lt;/tt&amp;gt;. Consider the following:&lt;br /&gt;
#* How are these functions different from &amp;lt;tt&amp;gt;put_user&amp;lt;/tt&amp;gt; that we have seen in the previous tutorial?&lt;br /&gt;
#* Why are these functions necessary? Couldn&amp;#039;t we just access the userspace address directly? What would happen if we did?&lt;br /&gt;
# &amp;lt;tt&amp;gt;3000physicalview&amp;lt;/tt&amp;gt; exposes its API to userspace in the form of an &amp;lt;tt&amp;gt;ioctl(2)&amp;lt;/tt&amp;gt; call. Consider the following:&lt;br /&gt;
#* What is an &amp;lt;tt&amp;gt;ioctl&amp;lt;/tt&amp;gt;? How is it different from a &amp;lt;tt&amp;gt;read&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; system call? Hint: check &amp;lt;tt&amp;gt;man 2 ioctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
#* How does &amp;lt;tt&amp;gt;3000physicalview&amp;lt;/tt&amp;gt; implement its &amp;lt;tt&amp;gt;ioctl&amp;lt;/tt&amp;gt;? What arguments does it take?&lt;br /&gt;
#* How does &amp;lt;tt&amp;gt;3000memview2&amp;lt;/tt&amp;gt; call the &amp;lt;tt&amp;gt;ioctl&amp;lt;/tt&amp;gt;? What arguments does it pass to the &amp;lt;tt&amp;gt;ioctl&amp;lt;/tt&amp;gt;?&lt;br /&gt;
&lt;br /&gt;
==Examining Physical Memory Mappings==&lt;br /&gt;
# With &amp;lt;tt&amp;gt;3000physicalview&amp;lt;/tt&amp;gt; inserted, run &amp;lt;tt&amp;gt;3000memview2&amp;lt;/tt&amp;gt; and examine the output. Note that it presents virtual memory addresses on the left, and physical addresses on the right. Are these mappings consistent with what you expected?&lt;br /&gt;
# Compare &amp;lt;tt&amp;gt;3000memview2&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;3000memview&amp;lt;/tt&amp;gt; from [[Operating Systems 2021F: Tutorial 2|Tutorial 2]].  What is similar about their code, and what is different?  How similar is their output?&lt;br /&gt;
# Do you notice a pattern in the virtual addresses of &amp;lt;tt&amp;gt;buf[i]&amp;lt;/tt&amp;gt;? Is this same pattern present in the physical addresses? Why or why not?&lt;br /&gt;
# Run &amp;lt;tt&amp;gt;3000memview2&amp;lt;/tt&amp;gt; a few more times and consider the following:&lt;br /&gt;
#* Are the virtual addresses the same or different between runs? How about physical addresses?&lt;br /&gt;
#* Some physical addresses don&amp;#039;t seem to be changing between runs. Which ones? Why do you think this might be the case?&lt;br /&gt;
&lt;br /&gt;
==Watching Kernel Memory Allocations==&lt;br /&gt;
Now let&amp;#039;s trace various kernel memory allocations outside of our module.&lt;br /&gt;
# Run &amp;lt;tt&amp;gt;sudo trace -M 100 -K &amp;#039;t:kmem:kmalloc printf &amp;quot;allocated %d bytes at address 0x%llx&amp;quot; args-&amp;gt;bytes_alloc, args-&amp;gt;ptr&amp;#039;&amp;lt;/tt&amp;gt; to trace the next 100 slab allocations and print the kernel stack. You may wish to pipe this output into &amp;lt;tt&amp;gt;less&amp;lt;/tt&amp;gt; to read it more easily. What do you notice about the kernel&amp;#039;s virtual addresses compared to what you have seen in userspace? Hint: Check the most significant hex digits.&lt;br /&gt;
# Run &amp;lt;tt&amp;gt;sudo trace -M 100 -K &amp;#039;t:kmem:mm_page_alloc printf &amp;quot;allocted 2^%d pages at page frame number %lu&amp;quot; args-&amp;gt;order, args-&amp;gt;pfn&amp;#039;&amp;lt;/tt&amp;gt; to trace the next 100 page allocations and print the kernel stack. You may wish to pipe this output into &amp;lt;tt&amp;gt;less&amp;lt;/tt&amp;gt; to read it more easily. Based on what you can see, does page allocation seem to differ from slab allocation? How so?&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&lt;br /&gt;
[https://homeostasis.scs.carleton.ca/~soma/os-2021f/code/3000physicalview.tar.gz 3000physicalview.tar.gz]&lt;br /&gt;
&lt;br /&gt;
===3000memview2.c===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
/* 3000memview2.c  Userland demonstration of 3000physicalview ioctl interface&lt;br /&gt;
 * Copyright (C) 2020  William Findlay&lt;br /&gt;
 *&lt;br /&gt;
 * This program is free software: you can redistribute it and/or modify&lt;br /&gt;
 * it under the terms of the GNU General Public License as published by&lt;br /&gt;
 * the Free Software Foundation, either version 3 of the License, or&lt;br /&gt;
 * (at your option) any later version.&lt;br /&gt;
 *&lt;br /&gt;
 * This program is distributed in the hope that it will be useful,&lt;br /&gt;
 * but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt;
 * GNU General Public License for more details.&lt;br /&gt;
 *&lt;br /&gt;
 * You should have received a copy of the GNU General Public License&lt;br /&gt;
 * along with this program.  If not, see &amp;lt;https://www.gnu.org/licenses/&amp;gt;. */&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define USERSPACE&lt;br /&gt;
#include &amp;quot;3000physicalview.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
char *gmsg = &amp;quot;Global Message&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
const int buffer_size = 30;&lt;br /&gt;
&lt;br /&gt;
void report_memory(char *prefix, int fd, unsigned long virt)&lt;br /&gt;
{&lt;br /&gt;
    struct physicalview_memory mem = {};&lt;br /&gt;
    mem.virt = virt;&lt;br /&gt;
&lt;br /&gt;
    if (ioctl(fd, PHYSICALVIEW_WALK, (unsigned long)&amp;amp;mem))&lt;br /&gt;
    {&lt;br /&gt;
        fprintf(stderr, &amp;quot;Error making ioctl call\n&amp;quot;);&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (!mem.phys)&lt;br /&gt;
    {&lt;br /&gt;
        printf(&amp;quot;%s 0x%016lx -&amp;gt; UNKNOWN\n&amp;quot;, prefix, mem.virt);&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    printf(&amp;quot;%s 0x%016lx -&amp;gt; 0x%016lx\n&amp;quot;, prefix, mem.virt, mem.phys);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[], char *envp[])&lt;br /&gt;
{&lt;br /&gt;
        char format[16];&lt;br /&gt;
        char *lmsg = &amp;quot;Local Message&amp;quot;;&lt;br /&gt;
        char *buf[buffer_size];&lt;br /&gt;
        int i;&lt;br /&gt;
&lt;br /&gt;
        int fd = open(&amp;quot;/dev/3000physicalview&amp;quot;, O_RDONLY);&lt;br /&gt;
&lt;br /&gt;
        printf(&amp;quot;Memory map report (virtual -&amp;gt; physical)\n&amp;quot;);&lt;br /&gt;
        report_memory(&amp;quot;argv:      &amp;quot;, fd, (unsigned long)argv);&lt;br /&gt;
        report_memory(&amp;quot;argv[0]:   &amp;quot;, fd, (unsigned long)argv[0]);&lt;br /&gt;
        report_memory(&amp;quot;envp:      &amp;quot;, fd, (unsigned long)envp);&lt;br /&gt;
        report_memory(&amp;quot;envp[0]:   &amp;quot;, fd, (unsigned long)envp[0]);&lt;br /&gt;
&lt;br /&gt;
        report_memory(&amp;quot;lmsg:      &amp;quot;, fd, (unsigned long)lmsg);&lt;br /&gt;
        report_memory(&amp;quot;&amp;amp;lmsg:     &amp;quot;, fd, (unsigned long)&amp;amp;lmsg);&lt;br /&gt;
        report_memory(&amp;quot;gmsg:      &amp;quot;, fd, (unsigned long)gmsg);&lt;br /&gt;
        report_memory(&amp;quot;&amp;amp;gmsg:     &amp;quot;, fd, (unsigned long)&amp;amp;gmsg);&lt;br /&gt;
&lt;br /&gt;
        report_memory(&amp;quot;&amp;amp;buf:      &amp;quot;, fd, (unsigned long)&amp;amp;buf);&lt;br /&gt;
&lt;br /&gt;
        for (i = 0; i&amp;lt;buffer_size; i++) {&lt;br /&gt;
                buf[i] = (char *) malloc(4096);&lt;br /&gt;
                snprintf(format, 16, &amp;quot;buf[%02d]:   &amp;quot;, i);&lt;br /&gt;
                report_memory(format, fd, (unsigned long)buf[i]);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        report_memory(&amp;quot;main:      &amp;quot;, fd, (unsigned long)&amp;amp;main);&lt;br /&gt;
        report_memory(&amp;quot;puts:      &amp;quot;, fd, (unsigned long)&amp;amp;puts);&lt;br /&gt;
&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===3000physicalview.c===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
/* 3000physicalview.c  A kernel module to expose virtual-&amp;gt;physical memory mappings in userspace as an ioctl&lt;br /&gt;
 * Copyright (C) 2020  William Findlay&lt;br /&gt;
 *&lt;br /&gt;
 * This program is free software: you can redistribute it and/or modify&lt;br /&gt;
 * it under the terms of the GNU General Public License as published by&lt;br /&gt;
 * the Free Software Foundation, either version 3 of the License, or&lt;br /&gt;
 * (at your option) any later version.&lt;br /&gt;
 *&lt;br /&gt;
 * This program is distributed in the hope that it will be useful,&lt;br /&gt;
 * but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt;
 * GNU General Public License for more details.&lt;br /&gt;
 *&lt;br /&gt;
 * You should have received a copy of the GNU General Public License&lt;br /&gt;
 * along with this program.  If not, see &amp;lt;https://www.gnu.org/licenses/&amp;gt;. */&lt;br /&gt;
&lt;br /&gt;
/* Warning: This module is extremely insecure.&lt;br /&gt;
 * It is designed purely for teaching purposes.&lt;br /&gt;
 * Using it is stupid unless you are in COMP3000. */&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;3000physicalview.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
static struct device *device = NULL;&lt;br /&gt;
static struct class *class   = NULL;&lt;br /&gt;
static int major_number;&lt;br /&gt;
&lt;br /&gt;
/* Helper functions below this line ---------------- */&lt;br /&gt;
&lt;br /&gt;
/* Walk the page table of current task for virtual address addr */&lt;br /&gt;
static unsigned long get_physical(unsigned long addr)&lt;br /&gt;
{&lt;br /&gt;
    pgd_t *pgd;&lt;br /&gt;
    p4d_t *p4d;&lt;br /&gt;
    pud_t *pud;&lt;br /&gt;
    pmd_t *pmd;&lt;br /&gt;
    pte_t *pte;&lt;br /&gt;
&lt;br /&gt;
    unsigned long pfn = 0;&lt;br /&gt;
    unsigned long phys = 0;&lt;br /&gt;
&lt;br /&gt;
    /* Find pgd */&lt;br /&gt;
    pgd = pgd_offset(current-&amp;gt;mm, addr);&lt;br /&gt;
    if (!pgd || pgd_none(*pgd) || pgd_bad(*pgd))&lt;br /&gt;
    {&lt;br /&gt;
        printk(KERN_ERR &amp;quot;Invalid pgd for address 0x%016lx\n&amp;quot;, addr);&lt;br /&gt;
        return phys;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /* Find p4d */&lt;br /&gt;
    p4d = p4d_offset(pgd, addr);&lt;br /&gt;
    if (!p4d || p4d_none(*p4d) || p4d_bad(*p4d))&lt;br /&gt;
    {&lt;br /&gt;
        printk(KERN_ERR &amp;quot;Invalid p4d for address 0x%016lx\n&amp;quot;, addr);&lt;br /&gt;
        return phys;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /* Find pud */&lt;br /&gt;
    pud = pud_offset(p4d, addr);&lt;br /&gt;
    if (!pud || pud_none(*pud) || pud_bad(*pud))&lt;br /&gt;
    {&lt;br /&gt;
        printk(KERN_ERR &amp;quot;Invalid pud for address 0x%016lx\n&amp;quot;, addr);&lt;br /&gt;
        return phys;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /* Find pmd */&lt;br /&gt;
    pmd = pmd_offset(pud, addr);&lt;br /&gt;
    if (!pmd || pmd_none(*pmd) || pmd_bad(*pmd))&lt;br /&gt;
    {&lt;br /&gt;
        printk(KERN_ERR &amp;quot;Invalid pmd for address 0x%016lx\n&amp;quot;, addr);&lt;br /&gt;
        return phys;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /* Find pte */&lt;br /&gt;
    pte = pte_offset_map(pmd, addr);&lt;br /&gt;
    if (!pte || pte_none(*pte))&lt;br /&gt;
    {&lt;br /&gt;
        printk(KERN_ERR &amp;quot;Invalid pte for address 0x%016lx\n&amp;quot;, addr);&lt;br /&gt;
        return phys;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /* Get physical address of page table entry */&lt;br /&gt;
    pfn = pte_pfn(*pte);&lt;br /&gt;
    phys = (pfn &amp;lt;&amp;lt; PAGE_SHIFT) + (addr % PAGE_SIZE);&lt;br /&gt;
&lt;br /&gt;
    return phys;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Define file operations below this line ------------------- */&lt;br /&gt;
&lt;br /&gt;
/* Callback to device open */&lt;br /&gt;
static int physicalview_open(struct inode * inode, struct file * file)&lt;br /&gt;
{&lt;br /&gt;
    printk(KERN_INFO &amp;quot;3000physicalview open\n&amp;quot;);&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Callback to device close */&lt;br /&gt;
static int physicalview_release(struct inode * inode, struct file * file)&lt;br /&gt;
{&lt;br /&gt;
    printk(KERN_INFO &amp;quot;3000physicalview closed\n&amp;quot;);&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Callback to device ioctl */&lt;br /&gt;
static long physicalview_ioctl(struct file *file, unsigned int cmd, unsigned long addr)&lt;br /&gt;
{&lt;br /&gt;
    struct physicalview_memory *mem;&lt;br /&gt;
    switch (cmd)&lt;br /&gt;
    {&lt;br /&gt;
        case PHYSICALVIEW_WALK:&lt;br /&gt;
            /* Allocate kernel memory for our struct */&lt;br /&gt;
            mem = kmalloc(sizeof(struct physicalview_memory), GFP_KERNEL);&lt;br /&gt;
            if (!mem)&lt;br /&gt;
            {&lt;br /&gt;
                printk(KERN_ERR &amp;quot;Unable to allocate space for struct\n&amp;quot;);&lt;br /&gt;
                return -EFAULT;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            /* Get virt from userspace */&lt;br /&gt;
            if (copy_from_user(mem, (struct physicalview_memory *)addr,&lt;br /&gt;
                        sizeof(struct physicalview_memory)))&lt;br /&gt;
            {&lt;br /&gt;
                printk(KERN_ERR &amp;quot;Unable to copy struct from user\n&amp;quot;);&lt;br /&gt;
                kfree(mem);&lt;br /&gt;
                return -EFAULT;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            /* Call helper to get physical mapping for virtual address */&lt;br /&gt;
            mem-&amp;gt;phys = get_physical(mem-&amp;gt;virt);&lt;br /&gt;
&lt;br /&gt;
            /* Give phys back to userspace */&lt;br /&gt;
            if (copy_to_user((struct physicalview_memory *)addr, mem,&lt;br /&gt;
                        sizeof(struct physicalview_memory)))&lt;br /&gt;
            {&lt;br /&gt;
                printk(KERN_ERR &amp;quot;Unable to copy struct to user\n&amp;quot;);&lt;br /&gt;
                kfree(mem);&lt;br /&gt;
                return -EFAULT;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            /* Cleanup, cleanup, everybody do their share */&lt;br /&gt;
            kfree(mem);&lt;br /&gt;
            break;&lt;br /&gt;
        default:&lt;br /&gt;
            return -EINVAL;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Register file operations */&lt;br /&gt;
static struct file_operations fops = {&lt;br /&gt;
    .open = physicalview_open,&lt;br /&gt;
    .release = physicalview_release,&lt;br /&gt;
    .unlocked_ioctl = physicalview_ioctl,&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* World readable and writable because... security? */&lt;br /&gt;
static char *physicalview_devnode(struct device *device, umode_t *mode)&lt;br /&gt;
{&lt;br /&gt;
    if (mode)&lt;br /&gt;
        *mode = 0666;&lt;br /&gt;
    return NULL;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Entry and exit points below this line ------------------------------------ */&lt;br /&gt;
&lt;br /&gt;
/* Module initialization */&lt;br /&gt;
int init_module(void)&lt;br /&gt;
{&lt;br /&gt;
    printk(KERN_INFO &amp;quot;3000physicalview initializing\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    /* Register character device */&lt;br /&gt;
    major_number = register_chrdev(0, DEVICE_NAME, &amp;amp;fops);&lt;br /&gt;
    if (major_number &amp;lt; 0)&lt;br /&gt;
    {&lt;br /&gt;
        goto failed_chrdevreg;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /* Create device class */&lt;br /&gt;
    class = class_create(THIS_MODULE, CLASS_NAME);&lt;br /&gt;
    if (IS_ERR(class))&lt;br /&gt;
    {&lt;br /&gt;
        goto failed_classreg;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /* Set devnode to set our &amp;quot;super secure&amp;quot; permissions from above */&lt;br /&gt;
    class-&amp;gt;devnode = physicalview_devnode;&lt;br /&gt;
&lt;br /&gt;
    /* Create device */&lt;br /&gt;
    device = device_create(class, NULL, MKDEV(major_number, 0), NULL, DEVICE_NAME);&lt;br /&gt;
    if (IS_ERR(device))&lt;br /&gt;
    {&lt;br /&gt;
        goto failed_devreg;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    printk(KERN_INFO &amp;quot;3000physicalview is loaded and regstered with major number %d!\n&amp;quot;, major_number);&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
&lt;br /&gt;
    /* NOTREACHED... */&lt;br /&gt;
&lt;br /&gt;
    /* Errors here */&lt;br /&gt;
failed_devreg:&lt;br /&gt;
    printk(KERN_ERR &amp;quot;Failed to register 3000physicalview device!\n&amp;quot;);&lt;br /&gt;
    class_unregister(class);&lt;br /&gt;
    class_destroy(class);&lt;br /&gt;
failed_classreg:&lt;br /&gt;
    printk(KERN_ERR &amp;quot;Failed to register 3000physicalview class!\n&amp;quot;);&lt;br /&gt;
    unregister_chrdev(major_number, DEVICE_NAME);&lt;br /&gt;
failed_chrdevreg:&lt;br /&gt;
    printk(KERN_ERR &amp;quot;Failed to register 3000physicalview as a character device!\n&amp;quot;);&lt;br /&gt;
    return -1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/* Module destructor callback */&lt;br /&gt;
void cleanup_module(void)&lt;br /&gt;
{&lt;br /&gt;
    /* Cleanup, cleanup, everybody do their share */&lt;br /&gt;
    device_destroy(class, MKDEV(major_number, 0));&lt;br /&gt;
    class_unregister(class);&lt;br /&gt;
    class_destroy(class);&lt;br /&gt;
    unregister_chrdev(major_number, DEVICE_NAME);&lt;br /&gt;
&lt;br /&gt;
    printk(KERN_INFO &amp;quot;3000physicalview cleanup complete\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===3000physicalview.h===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
/* 3000physicalview.c  A kernel module to expose virtual-&amp;gt;physical memory mappings in userspace as an ioctl&lt;br /&gt;
 * Copyright (C) 2020  William Findlay&lt;br /&gt;
 *&lt;br /&gt;
 * This program is free software: you can redistribute it and/or modify&lt;br /&gt;
 * it under the terms of the GNU General Public License as published by&lt;br /&gt;
 * the Free Software Foundation, either version 3 of the License, or&lt;br /&gt;
 * (at your option) any later version.&lt;br /&gt;
 *&lt;br /&gt;
 * This program is distributed in the hope that it will be useful,&lt;br /&gt;
 * but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt;
 * GNU General Public License for more details.&lt;br /&gt;
 *&lt;br /&gt;
 * You should have received a copy of the GNU General Public License&lt;br /&gt;
 * along with this program.  If not, see &amp;lt;https://www.gnu.org/licenses/&amp;gt;. */&lt;br /&gt;
&lt;br /&gt;
/* Warning: This module is extremely insecure.&lt;br /&gt;
 * It is designed purely for teaching purposes.&lt;br /&gt;
 * Using it is stupid unless you are in COMP3000. */&lt;br /&gt;
&lt;br /&gt;
#ifndef PHYSICALVIEW_H&lt;br /&gt;
#define PHYSICALVIEW_H&lt;br /&gt;
&lt;br /&gt;
#ifndef USERSPACE /* Kernelspace only */&lt;br /&gt;
#include &amp;lt;linux/module.h&amp;gt;&lt;br /&gt;
#include &amp;lt;linux/init.h&amp;gt;&lt;br /&gt;
#include &amp;lt;linux/fs.h&amp;gt;&lt;br /&gt;
#include &amp;lt;linux/device.h&amp;gt;&lt;br /&gt;
#include &amp;lt;linux/string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;linux/sched.h&amp;gt;&lt;br /&gt;
#include &amp;lt;linux/gfp.h&amp;gt;&lt;br /&gt;
#include &amp;lt;linux/slab.h&amp;gt;&lt;br /&gt;
#include &amp;lt;linux/mm.h&amp;gt;&lt;br /&gt;
#include &amp;lt;linux/uaccess.h&amp;gt;&lt;br /&gt;
#include &amp;lt;asm/uaccess.h&amp;gt;&lt;br /&gt;
#include &amp;lt;asm/pgtable.h&amp;gt;&lt;br /&gt;
#include &amp;lt;asm/pgtable_types.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define DEVICE_NAME &amp;quot;3000physicalview&amp;quot;&lt;br /&gt;
#define CLASS_NAME &amp;quot;COMP3000&amp;quot;&lt;br /&gt;
&lt;br /&gt;
MODULE_DESCRIPTION(&amp;quot;Walk page table for userspace virtual address.&amp;quot;);&lt;br /&gt;
MODULE_AUTHOR(&amp;quot;William Findlay&amp;quot;);&lt;br /&gt;
MODULE_LICENSE(&amp;quot;GPL&amp;quot;);&lt;br /&gt;
MODULE_VERSION(&amp;quot;0.0.1&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
#else /* Userspace only */&lt;br /&gt;
#include &amp;lt;sys/ioctl.h&amp;gt;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
/* Both userspace and kernelspace */&lt;br /&gt;
&lt;br /&gt;
struct physicalview_memory&lt;br /&gt;
{&lt;br /&gt;
    unsigned long virt;&lt;br /&gt;
    unsigned long phys;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* Ioctl stuff */&lt;br /&gt;
#define PHYSICALVIEW_BASE &amp;#039;k&amp;#039;&lt;br /&gt;
#define PHYSICALVIEW_WALK _IOWR(PHYSICALVIEW_BASE, 1, struct physicalview_memory)&lt;br /&gt;
&lt;br /&gt;
#endif /* PHYSICALVIEW_H */&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Makefile===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;makefile&amp;quot; line&amp;gt;&lt;br /&gt;
obj-m += 3000physicalview.o&lt;br /&gt;
&lt;br /&gt;
.PHONY: all, clean, insert, remove&lt;br /&gt;
&lt;br /&gt;
all: 3000memview2 3000physicalview.ko&lt;br /&gt;
&lt;br /&gt;
3000physicalview.ko: 3000physicalview.c 3000physicalview.h&lt;br /&gt;
	make ARCH=x86_64 -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules&lt;br /&gt;
&lt;br /&gt;
3000memview2: 3000memview2.c&lt;br /&gt;
	gcc -O2 -o 3000memview2 3000memview2.c&lt;br /&gt;
&lt;br /&gt;
insert:&lt;br /&gt;
	sudo insmod 3000physicalview.ko&lt;br /&gt;
&lt;br /&gt;
remove:&lt;br /&gt;
	sudo rmmod 3000physicalview&lt;br /&gt;
&lt;br /&gt;
clean:&lt;br /&gt;
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean&lt;br /&gt;
	rm 3000memview2&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Soma</name></author>
	</entry>
</feed>