<?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_2020W%3A_Tutorial_8</id>
	<title>Operating Systems 2020W: Tutorial 8 - 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_2020W%3A_Tutorial_8"/>
	<link rel="alternate" type="text/html" href="https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2020W:_Tutorial_8&amp;action=history"/>
	<updated>2026-06-02T21:07:40Z</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_2020W:_Tutorial_8&amp;diff=22614&amp;oldid=prev</id>
		<title>Soma: /* 3000physicalview.c */</title>
		<link rel="alternate" type="text/html" href="https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2020W:_Tutorial_8&amp;diff=22614&amp;oldid=prev"/>
		<updated>2020-03-21T19:41:29Z</updated>

		<summary type="html">&lt;p&gt;&lt;span dir=&quot;auto&quot;&gt;&lt;span class=&quot;autocomment&quot;&gt;3000physicalview.c&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 19:41, 21 March 2020&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-l215&quot;&gt;Line 215:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 215:&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;     /* Get physical address of page table entry */&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;     /* Get physical address of page table entry */&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;     pfn = pte&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-&amp;gt;pte &amp;amp; PTE_PFN_MASK&lt;/del&gt;;&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;     pfn = &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;pte_pfn(*&lt;/ins&gt;pte&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;)&lt;/ins&gt;;&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;     phys = (pfn &amp;lt;&amp;lt; PAGE_SHIFT) + (addr % PAGE_SIZE);&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;     phys = (pfn &amp;lt;&amp;lt; PAGE_SHIFT) + (addr % PAGE_SIZE);&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;/table&gt;</summary>
		<author><name>Soma</name></author>
	</entry>
	<entry>
		<id>https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2020W:_Tutorial_8&amp;diff=22591&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...&quot;</title>
		<link rel="alternate" type="text/html" href="https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2020W:_Tutorial_8&amp;diff=22591&amp;oldid=prev"/>
		<updated>2020-03-20T02:48:26Z</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...&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&lt;br /&gt;
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-2020w/code/3000physicalview.tar.gz 3000physicalview.tar.gz].&lt;br /&gt;
&lt;br /&gt;
==Getting Started==&lt;br /&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 2020W: 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;
# Spawn a root shell with &amp;lt;tt&amp;gt;sudo su&amp;lt;/tt&amp;gt; and force the kernel to drop the virtual memory cache using &amp;lt;tt&amp;gt;sync &amp;amp;&amp;amp; echo 3 &amp;gt; /proc/sys/vm/drop_caches&amp;lt;/tt&amp;gt;. Run &amp;lt;tt&amp;gt;3000memview2&amp;lt;/tt&amp;gt; one more time and note that the physical addresses that stayed the same previously have now changed. What do you think just happened?&lt;br /&gt;
&lt;br /&gt;
==Revisiting Trace==&lt;br /&gt;
# Modify &amp;lt;tt&amp;gt;3000memview2.c&amp;lt;/tt&amp;gt; by adding a call to &amp;lt;tt&amp;gt;sleep(10);&amp;lt;/tt&amp;gt; at the beginning of &amp;lt;tt&amp;gt;main&amp;lt;/tt&amp;gt;. This will give you a chance to run &amp;lt;tt&amp;gt;trace&amp;lt;/tt&amp;gt; attached to its pid. Compile with the Makefile as before. For the following questions, run your new &amp;lt;tt&amp;gt;3000memview2&amp;lt;/tt&amp;gt; in one terminal, and the &amp;lt;tt&amp;gt;trace&amp;lt;/tt&amp;gt; command in another.&lt;br /&gt;
#* Run &amp;lt;tt&amp;gt;trace -p `pidof 3000memview2` -K &amp;#039;p::_copy_to_user&amp;#039;&amp;lt;/tt&amp;gt; to get the kernel stack trace every time the module invokes &amp;lt;tt&amp;gt;copy_to_user&amp;lt;/tt&amp;gt;. How does this differ from the stack trace for &amp;lt;tt&amp;gt;put_user&amp;lt;/tt&amp;gt; from last tutorial?&lt;br /&gt;
#* Run &amp;lt;tt&amp;gt;trace -p `pidof 3000memview2` -K &amp;#039;p::_copy_from_user&amp;#039;&amp;lt;/tt&amp;gt; to get the kernel stack trace every time the module invokes &amp;lt;tt&amp;gt;copy_from_user&amp;lt;/tt&amp;gt;. Compare this stack trace with that of the previous question.&lt;br /&gt;
# Now let&amp;#039;s trace various kernel memory allocations outside of our module. Run the following trace commands:&lt;br /&gt;
#* &amp;lt;tt&amp;gt;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;
#* &amp;lt;tt&amp;gt;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-2020w/code/3000physicalview.tar.gz 3000physicalview.tar.gz]&lt;br /&gt;
&lt;br /&gt;
===3000memview2.c===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source 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;main:      &amp;quot;, fd, (unsigned long)&amp;amp;main);&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;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===3000physicalview.c===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source 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-&amp;gt;pte &amp;amp; PTE_PFN_MASK;&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;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===3000physicalview.h===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source 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;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Soma</name></author>
	</entry>
</feed>