<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.friendos.dev/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Repnop</id>
	<title>FriendOS Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.friendos.dev/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Repnop"/>
	<link rel="alternate" type="text/html" href="https://wiki.friendos.dev/index.php/Special:Contributions/Repnop"/>
	<updated>2026-04-21T04:39:46Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.38.4</generator>
	<entry>
		<id>https://wiki.friendos.dev/index.php?title=Main_Page&amp;diff=98</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://wiki.friendos.dev/index.php?title=Main_Page&amp;diff=98"/>
		<updated>2024-12-18T14:03:24Z</updated>

		<summary type="html">&lt;p&gt;Repnop: Remove old invite link from Helpful Links section&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Welcome to the FriendOS Wiki! ==&lt;br /&gt;
&lt;br /&gt;
The FriendOS Wiki is a community-driven wiki for the [https://discord.gg/U9feA9z669 FriendOS Discord server]. This wiki, as well as the Discord server, are intended to create a more inclusive, supportive, and welcoming environment for people learning about operating systems development, which historically is not very common. The purpose of this wiki is to provide resources for newbies and veterans alike, as well as allowing contributions from the community members so that people can easily create &amp;amp; share information about the concepts that they frequently work with. If you think you have something to contribute, make an account and start writing! If you have comments or questions, you can discuss the wiki in the #wiki channel on the Discord server.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Helpful Links ==&lt;br /&gt;
&lt;br /&gt;
* [[Special:AllPages|See all pages]]&lt;br /&gt;
* [[:Category:Architectures|Architectures Index]]&lt;/div&gt;</summary>
		<author><name>Repnop</name></author>
	</entry>
	<entry>
		<id>https://wiki.friendos.dev/index.php?title=PLIC&amp;diff=20</id>
		<title>PLIC</title>
		<link rel="alternate" type="text/html" href="https://wiki.friendos.dev/index.php?title=PLIC&amp;diff=20"/>
		<updated>2023-02-03T02:29:24Z</updated>

		<summary type="html">&lt;p&gt;Repnop: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The Platform Interrupt Controller (PLIC) is the standardized device for receiving, routing, and completing [[Interrupts#External|external interrupts]] with configuration per-[[hart]] and per-[[Privilege Mode|privilege mode]]. Originally, the PLIC design is based on early SiFive designs which were then slightly refined and standardized and only supports basic interrupt enabling/disabling, prioritization and routing. As part of the [[RISC-V Advanced Interrupt Architecture]] (AIA), the original PLIC design is extended to support more types of interrupts, namely [[Message Signaled Interrupt]]&amp;lt;nowiki/&amp;gt;s (MSIs), which are important for technologies like [[PCI]]. The PLIC specification can be found at https://github.com/riscv/riscv-plic-spec while the APLIC specification is available at https://github.com/riscv/riscv-aia.&lt;br /&gt;
&lt;br /&gt;
== Original PLIC Design ==&lt;br /&gt;
The original PLIC design consist of a set of: interrupt source priorities, interrupt pending bits, per-context interrupt enable bits, and then per-context priority threshold &amp;amp; claim/complete regions. A context is the combination of a hart ID and a privilege mode, though the specific ordering of contexts is platform-specific and cannot be generalized between them. A small table below has been added for quick reference, but likely will not contain a formula for calculating the context for every platform. The memory layout for the PLIC is as follows (taken from the PLIC spec):&lt;br /&gt;
 base + 0x000000: Reserved (interrupt source 0 does not exist)&lt;br /&gt;
 base + 0x000004: Interrupt source 1 priority&lt;br /&gt;
 base + 0x000008: Interrupt source 2 priority&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x000FFC: Interrupt source 1023 priority&lt;br /&gt;
 base + 0x001000: Interrupt Pending bit 0-31&lt;br /&gt;
 base + 0x00107C: Interrupt Pending bit 992-1023&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x002000: Enable bits for sources 0-31 on context 0&lt;br /&gt;
 base + 0x002004: Enable bits for sources 32-63 on context 0&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x00207C: Enable bits for sources 992-1023 on context 0&lt;br /&gt;
 base + 0x002080: Enable bits for sources 0-31 on context 1&lt;br /&gt;
 base + 0x002084: Enable bits for sources 32-63 on context 1&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x0020FC: Enable bits for sources 992-1023 on context 1&lt;br /&gt;
 base + 0x002100: Enable bits for sources 0-31 on context 2&lt;br /&gt;
 base + 0x002104: Enable bits for sources 32-63 on context 2&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x00217C: Enable bits for sources 992-1023 on context 2&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x1F1F80: Enable bits for sources 0-31 on context 15871&lt;br /&gt;
 base + 0x1F1F84: Enable bits for sources 32-63 on context 15871&lt;br /&gt;
 base + 0x1F1FFC: Enable bits for sources 992-1023 on context 15871&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x1FFFFC: Reserved&lt;br /&gt;
 base + 0x200000: Priority threshold for context 0&lt;br /&gt;
 base + 0x200004: Claim/complete for context 0&lt;br /&gt;
 base + 0x200008: Reserved&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x200FFC: Reserved&lt;br /&gt;
 base + 0x201000: Priority threshold for context 1&lt;br /&gt;
 base + 0x201004: Claim/complete for context 1&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x3FFF000: Priority threshold for context 15871&lt;br /&gt;
 base + 0x3FFF004: Claim/complete for context 15871&lt;br /&gt;
 base + 0x3FFF008: Reserved&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x3FFFFFC: Reserved&lt;br /&gt;
&lt;br /&gt;
Or, more usefully:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;rust&amp;quot; line&amp;gt;&lt;br /&gt;
#[repr(C)]&lt;br /&gt;
struct Plic {&lt;br /&gt;
    source_priorities: [u32; 1024],&lt;br /&gt;
    interrupt_pending: [u32; 32],&lt;br /&gt;
    _padding1: [u8; 3968],&lt;br /&gt;
    interrupt_enable: [[u32; 32]; 15872],&lt;br /&gt;
    _padding2: [u8; 57344],&lt;br /&gt;
    threshold_and_claim: [[u32; 1024]; 15872],&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Each &amp;lt;code&amp;gt;u32&amp;lt;/code&amp;gt; inside of the &amp;lt;code&amp;gt;source_priorities&amp;lt;/code&amp;gt; is a priority level from &amp;lt;code&amp;gt;0..=7&amp;lt;/code&amp;gt; (on most platforms, see your platform specification for more complete information) of increasing priority level where priority &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; is considered &amp;quot;never interrupt&amp;quot; and will cause the interrupt to effectively be disabled, with the exception of interrupt #0, which does not exist and is reserved. &amp;lt;code&amp;gt;interrupt_pending&amp;lt;/code&amp;gt; is a read-only bitmap of the pending status for priorities &amp;lt;code&amp;gt;1..=1024&amp;lt;/code&amp;gt; (with the interrupt #0 bit hardwired to zero). Both &amp;lt;code&amp;gt;interrupt_enable&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;threshold_and_claim&amp;lt;/code&amp;gt; work on the aforementioned contexts, and need to be indexed at a platform-specific index for a given hart and privilege mode combination. The &amp;lt;code&amp;gt;interrupt_enable&amp;lt;/code&amp;gt; consists of another bitmap of interrupt sources (again with interrupt #0 for each context being hardwired to zero) which allow enabling and disabling specific interrupt sources at the context level, but also means that if you wish for a given interrupt to trigger across any hart, it will need to be enabled for each context for the privilege mode you are executing in. &amp;lt;code&amp;gt;threshold_and_claim&amp;lt;/code&amp;gt; is made up of a threshold &amp;lt;code&amp;gt;u32&amp;lt;/code&amp;gt; value and a claim &amp;lt;code&amp;gt;u32&amp;lt;/code&amp;gt; value, with the rest of the &amp;lt;code&amp;gt;u32&amp;lt;/code&amp;gt;s being reserved and should not be written to.&lt;br /&gt;
&lt;br /&gt;
=== Hart &amp;amp; Privilege Context Mappings ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Platform&lt;br /&gt;
!M-mode Context&lt;br /&gt;
!S-mode Context&lt;br /&gt;
|-&lt;br /&gt;
|QEMU virt&lt;br /&gt;
|&amp;lt;code&amp;gt;hart_id * 2&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
 hart_id * 2 + 1&lt;br /&gt;
|-&lt;br /&gt;
|QEMU sifive_u&amp;lt;sup&amp;gt;†&amp;lt;/sup&amp;gt;&lt;br /&gt;
|Monitor hart: &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Other harts: &amp;lt;code&amp;gt;hart_id * 2 + 1&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;hart_id * 2&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;sup&amp;gt;†&amp;lt;/sup&amp;gt;This platform contains a [[Monitor Hart]] which does not support S-mode and does not have the same extension availability as the general-purpose harts&lt;br /&gt;
&lt;br /&gt;
=== Setting Interrupt Source Priorities &amp;amp; Thresholds ===&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
=== Enabling and Disabling Interrupts ===&lt;br /&gt;
To enable or disable any given interrupt source, simply toggle the specific bit that corresponds to the interrupt source in the &amp;lt;code&amp;gt;interrupt_enable&amp;lt;/code&amp;gt; for the context for which you wish to enable or disable the interrupt. Example Rust code:&amp;lt;syntaxhighlight lang=&amp;quot;rust&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
unsafe fn enable_interrupt(plic: *mut Plic, context: usize, interrupt_source: usize) {&lt;br /&gt;
    // Sanity checks, neither values would be valid&lt;br /&gt;
    if context &amp;gt;= 15872 || interrupt_source &amp;gt;= 1024 {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // Calculate the bit-group index and the bit index for that bit-group&lt;br /&gt;
    let (u32_index, bit) = (interrupt_source / 32, interrupt_source % 32);&lt;br /&gt;
    &lt;br /&gt;
    // Calculate the address of the bit-group&lt;br /&gt;
    let bit_group_ptr = unsafe { core::ptr::addr_of_mut!((*plic).interrupt_enable[context][u32_index]) };&lt;br /&gt;
    &lt;br /&gt;
    // Read the current value&lt;br /&gt;
    let previous = unsafe { bit_group_ptr.read_volatile() };&lt;br /&gt;
    &lt;br /&gt;
    // Set the bit for the interrupt source&lt;br /&gt;
    let new = previous | (1 &amp;lt;&amp;lt; bit);&lt;br /&gt;
    &lt;br /&gt;
    // Write the new value&lt;br /&gt;
    unsafe { bit_group_ptr.write_volatile(new) };&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
unsafe fn disable_interrupt(plic: *mut Plic, context: usize, interrupt_source: usize) {&lt;br /&gt;
    // Sanity checks, neither values would be valid&lt;br /&gt;
    if context &amp;gt;= 15872 || interrupt_source &amp;gt;= 1024 {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // Calculate the bit-group index and the bit index for that bit-group&lt;br /&gt;
    let (u32_index, bit) = (interrupt_source / 32, interrupt_source % 32);&lt;br /&gt;
    &lt;br /&gt;
    // Calculate the address of the bit-group&lt;br /&gt;
    let bit_group_ptr = unsafe { core::ptr::addr_of_mut!((*plic).interrupt_enable[context][u32_index]) };&lt;br /&gt;
    &lt;br /&gt;
    // Read the current value&lt;br /&gt;
    let previous = unsafe { bit_group_ptr.read_volatile() };&lt;br /&gt;
    &lt;br /&gt;
    // Clear the bit for the interrupt source&lt;br /&gt;
    let new = previous &amp;amp; !(1 &amp;lt;&amp;lt; bit);&lt;br /&gt;
    &lt;br /&gt;
    // Write the new value&lt;br /&gt;
    unsafe { bit_group_ptr.write_volatile(new) };&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Acknowledging Interrupts — Claim/Complete Mechanism ===&lt;br /&gt;
TODO&lt;br /&gt;
__FORCETOC__&lt;/div&gt;</summary>
		<author><name>Repnop</name></author>
	</entry>
	<entry>
		<id>https://wiki.friendos.dev/index.php?title=PLIC&amp;diff=19</id>
		<title>PLIC</title>
		<link rel="alternate" type="text/html" href="https://wiki.friendos.dev/index.php?title=PLIC&amp;diff=19"/>
		<updated>2023-02-03T02:15:21Z</updated>

		<summary type="html">&lt;p&gt;Repnop: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The Platform Interrupt Controller (PLIC) is the standardized device for receiving, routing, and completing [[Interrupts#External|external interrupts]] with configuration per-[[hart]] and per-[[Privilege Mode|privilege mode]]. Originally, the PLIC design is based on early SiFive designs which were then slightly refined and standardized and only supports basic interrupt enabling/disabling, prioritization and routing. As part of the [[RISC-V Advanced Interrupt Architecture]] (AIA), the original PLIC design is extended to support more types of interrupts, namely [[Message Signaled Interrupt]]&amp;lt;nowiki/&amp;gt;s (MSIs), which are important for technologies like [[PCI]]. The PLIC specification can be found at https://github.com/riscv/riscv-plic-spec while the APLIC specification is available at https://github.com/riscv/riscv-aia.&lt;br /&gt;
&lt;br /&gt;
== Original PLIC Design ==&lt;br /&gt;
The original PLIC design consist of a set of: interrupt source priorities, interrupt pending bits, per-context interrupt enable bits, and then per-context priority threshold &amp;amp; claim/complete regions. A context is the combination of a hart ID and a privilege mode, though the specific ordering of contexts is platform-specific and cannot be generalized between them. A small table below has been added for quick reference, but likely will not contain a formula for calculating the context for every platform. The memory layout for the PLIC is as follows (taken from the PLIC spec):&lt;br /&gt;
 base + 0x000000: Reserved (interrupt source 0 does not exist)&lt;br /&gt;
 base + 0x000004: Interrupt source 1 priority&lt;br /&gt;
 base + 0x000008: Interrupt source 2 priority&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x000FFC: Interrupt source 1023 priority&lt;br /&gt;
 base + 0x001000: Interrupt Pending bit 0-31&lt;br /&gt;
 base + 0x00107C: Interrupt Pending bit 992-1023&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x002000: Enable bits for sources 0-31 on context 0&lt;br /&gt;
 base + 0x002004: Enable bits for sources 32-63 on context 0&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x00207C: Enable bits for sources 992-1023 on context 0&lt;br /&gt;
 base + 0x002080: Enable bits for sources 0-31 on context 1&lt;br /&gt;
 base + 0x002084: Enable bits for sources 32-63 on context 1&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x0020FC: Enable bits for sources 992-1023 on context 1&lt;br /&gt;
 base + 0x002100: Enable bits for sources 0-31 on context 2&lt;br /&gt;
 base + 0x002104: Enable bits for sources 32-63 on context 2&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x00217C: Enable bits for sources 992-1023 on context 2&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x1F1F80: Enable bits for sources 0-31 on context 15871&lt;br /&gt;
 base + 0x1F1F84: Enable bits for sources 32-63 on context 15871&lt;br /&gt;
 base + 0x1F1FFC: Enable bits for sources 992-1023 on context 15871&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x1FFFFC: Reserved&lt;br /&gt;
 base + 0x200000: Priority threshold for context 0&lt;br /&gt;
 base + 0x200004: Claim/complete for context 0&lt;br /&gt;
 base + 0x200008: Reserved&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x200FFC: Reserved&lt;br /&gt;
 base + 0x201000: Priority threshold for context 1&lt;br /&gt;
 base + 0x201004: Claim/complete for context 1&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x3FFF000: Priority threshold for context 15871&lt;br /&gt;
 base + 0x3FFF004: Claim/complete for context 15871&lt;br /&gt;
 base + 0x3FFF008: Reserved&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x3FFFFFC: Reserved&lt;br /&gt;
&lt;br /&gt;
Or, more usefully:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;rust&amp;quot; line&amp;gt;&lt;br /&gt;
#[repr(C)]&lt;br /&gt;
struct Plic {&lt;br /&gt;
    source_priorities: [u32; 1024],&lt;br /&gt;
    interrupt_pending: [u32; 32],&lt;br /&gt;
    _padding1: [u8; 3968],&lt;br /&gt;
    interrupt_enable: [[u32; 32]; 15872],&lt;br /&gt;
    _padding2: [u8; 57344],&lt;br /&gt;
    threshold_and_claim: [[u32; 1024]; 15872],&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Each &amp;lt;code&amp;gt;u32&amp;lt;/code&amp;gt; inside of the &amp;lt;code&amp;gt;source_priorities&amp;lt;/code&amp;gt; is a priority level from &amp;lt;code&amp;gt;0..=7&amp;lt;/code&amp;gt; (on most platforms, see your platform specification for more complete information) of increasing priority level where priority &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; is considered &amp;quot;never interrupt&amp;quot; and will cause the interrupt to effectively be disabled, with the exception of interrupt #0, which does not exist and is reserved. &amp;lt;code&amp;gt;interrupt_pending&amp;lt;/code&amp;gt; is a read-only bitmap of the pending status for priorities &amp;lt;code&amp;gt;1..=1024&amp;lt;/code&amp;gt; (with the interrupt #0 bit hardwired to zero). Both &amp;lt;code&amp;gt;interrupt_enable&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;threshold_and_claim&amp;lt;/code&amp;gt; work on the aforementioned contexts, and need to be indexed at a platform-specific index for a given hart and privilege mode combination. The &amp;lt;code&amp;gt;interrupt_enable&amp;lt;/code&amp;gt; consists of another bitmap of interrupt sources (again with interrupt #0 for each context being hardwired to zero) which allow enabling and disabling specific interrupt sources at the context level, but also means that if you wish for a given interrupt to trigger across any hart, it will need to be enabled for each context for the privilege mode you are executing in. &amp;lt;code&amp;gt;threshold_and_claim&amp;lt;/code&amp;gt; is made up of a threshold &amp;lt;code&amp;gt;u32&amp;lt;/code&amp;gt; value and a claim &amp;lt;code&amp;gt;u32&amp;lt;/code&amp;gt; value, with the rest of the &amp;lt;code&amp;gt;u32&amp;lt;/code&amp;gt;s being reserved and should not be written to.&lt;br /&gt;
&lt;br /&gt;
=== Hart &amp;amp; Privilege Context Mappings ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Platform&lt;br /&gt;
!M-mode Context&lt;br /&gt;
!S-mode Context&lt;br /&gt;
|-&lt;br /&gt;
|QEMU virt&lt;br /&gt;
|&amp;lt;code&amp;gt;hart_id * 2&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
 hart_id * 2 + 1&lt;br /&gt;
|-&lt;br /&gt;
|QEMU sifive_u&amp;lt;sup&amp;gt;†&amp;lt;/sup&amp;gt;&lt;br /&gt;
|Monitor hart: &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Other harts: &amp;lt;code&amp;gt;hart_id * 2 + 1&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;hart_id * 2&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;sup&amp;gt;†&amp;lt;/sup&amp;gt;This platform contains a [[Monitor Hart]] which does not support S-mode and does not have the same extension availability as the general-purpose harts&lt;br /&gt;
&lt;br /&gt;
=== Enabling and Disabling Interrupts ===&lt;br /&gt;
To enable or disable any given interrupt source, simply toggle the specific bit that corresponds to the interrupt source in the &amp;lt;code&amp;gt;interrupt_enable&amp;lt;/code&amp;gt; for the context for which you wish to enable or disable the interrupt. Example Rust code:&amp;lt;syntaxhighlight lang=&amp;quot;rust&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
unsafe fn enable_interrupt(plic: *mut Plic, context: usize, interrupt_source: usize) {&lt;br /&gt;
    // Sanity checks, neither values would be valid&lt;br /&gt;
    if context &amp;gt;= 15872 || interrupt_source &amp;gt;= 1024 {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // Calculate the bit-group index and the bit index for that bit-group&lt;br /&gt;
    let (u32_index, bit) = (interrupt_source / 32, interrupt_source % 32);&lt;br /&gt;
    &lt;br /&gt;
    // Calculate the address of the bit-group&lt;br /&gt;
    let bit_group_ptr = unsafe { core::ptr::addr_of_mut!((*plic).interrupt_enable[context][u32_index]) };&lt;br /&gt;
    &lt;br /&gt;
    // Read the current value&lt;br /&gt;
    let previous = unsafe { bit_group_ptr.read_volatile() };&lt;br /&gt;
    &lt;br /&gt;
    // Set the bit for the interrupt source&lt;br /&gt;
    let new = previous | (1 &amp;lt;&amp;lt; bit);&lt;br /&gt;
    &lt;br /&gt;
    // Write the new value&lt;br /&gt;
    unsafe { bit_group_ptr.write_volatile(new) };&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
unsafe fn disable_interrupt(plic: *mut Plic, context: usize, interrupt_source: usize) {&lt;br /&gt;
    // Sanity checks, neither values would be valid&lt;br /&gt;
    if context &amp;gt;= 15872 || interrupt_source &amp;gt;= 1024 {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // Calculate the bit-group index and the bit index for that bit-group&lt;br /&gt;
    let (u32_index, bit) = (interrupt_source / 32, interrupt_source % 32);&lt;br /&gt;
    &lt;br /&gt;
    // Calculate the address of the bit-group&lt;br /&gt;
    let bit_group_ptr = unsafe { core::ptr::addr_of_mut!((*plic).interrupt_enable[context][u32_index]) };&lt;br /&gt;
    &lt;br /&gt;
    // Read the current value&lt;br /&gt;
    let previous = unsafe { bit_group_ptr.read_volatile() };&lt;br /&gt;
    &lt;br /&gt;
    // Clear the bit for the interrupt source&lt;br /&gt;
    let new = previous &amp;amp; !(1 &amp;lt;&amp;lt; bit);&lt;br /&gt;
    &lt;br /&gt;
    // Write the new value&lt;br /&gt;
    unsafe { bit_group_ptr.write_volatile(new) };&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
__FORCETOC__&lt;/div&gt;</summary>
		<author><name>Repnop</name></author>
	</entry>
	<entry>
		<id>https://wiki.friendos.dev/index.php?title=PLIC&amp;diff=18</id>
		<title>PLIC</title>
		<link rel="alternate" type="text/html" href="https://wiki.friendos.dev/index.php?title=PLIC&amp;diff=18"/>
		<updated>2023-02-03T02:13:41Z</updated>

		<summary type="html">&lt;p&gt;Repnop: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The Platform Interrupt Controller (PLIC) is the standardized device for receiving, routing, and completing [[Interrupts#External|external interrupts]] with configuration per-[[hart]] and per-[[Privilege Mode|privilege mode]]. Originally, the PLIC design is based on early SiFive designs which were then slightly refined and standardized and only supports basic interrupt enabling/disabling, prioritization and routing. As part of the [[RISC-V Advanced Interrupt Architecture]] (AIA), the original PLIC design is extended to support more types of interrupts, namely [[Message Signaled Interrupt]]&amp;lt;nowiki/&amp;gt;s (MSIs), which are important for technologies like [[PCI]]. The PLIC specification can be found at https://github.com/riscv/riscv-plic-spec while the APLIC specification is available at https://github.com/riscv/riscv-aia.&lt;br /&gt;
&lt;br /&gt;
== Original PLIC Design ==&lt;br /&gt;
The original PLIC design consist of a set of: interrupt source priorities, interrupt pending bits, per-context interrupt enable bits, and then per-context priority threshold &amp;amp; claim/complete regions. A context is the combination of a hart ID and a privilege mode, though the specific ordering of contexts is platform-specific and cannot be generalized between them. A small table below has been added for quick reference, but likely will not contain a formula for calculating the context for every platform. The memory layout for the PLIC is as follows (taken from the PLIC spec):&lt;br /&gt;
 base + 0x000000: Reserved (interrupt source 0 does not exist)&lt;br /&gt;
 base + 0x000004: Interrupt source 1 priority&lt;br /&gt;
 base + 0x000008: Interrupt source 2 priority&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x000FFC: Interrupt source 1023 priority&lt;br /&gt;
 base + 0x001000: Interrupt Pending bit 0-31&lt;br /&gt;
 base + 0x00107C: Interrupt Pending bit 992-1023&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x002000: Enable bits for sources 0-31 on context 0&lt;br /&gt;
 base + 0x002004: Enable bits for sources 32-63 on context 0&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x00207C: Enable bits for sources 992-1023 on context 0&lt;br /&gt;
 base + 0x002080: Enable bits for sources 0-31 on context 1&lt;br /&gt;
 base + 0x002084: Enable bits for sources 32-63 on context 1&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x0020FC: Enable bits for sources 992-1023 on context 1&lt;br /&gt;
 base + 0x002100: Enable bits for sources 0-31 on context 2&lt;br /&gt;
 base + 0x002104: Enable bits for sources 32-63 on context 2&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x00217C: Enable bits for sources 992-1023 on context 2&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x1F1F80: Enable bits for sources 0-31 on context 15871&lt;br /&gt;
 base + 0x1F1F84: Enable bits for sources 32-63 on context 15871&lt;br /&gt;
 base + 0x1F1FFC: Enable bits for sources 992-1023 on context 15871&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x1FFFFC: Reserved&lt;br /&gt;
 base + 0x200000: Priority threshold for context 0&lt;br /&gt;
 base + 0x200004: Claim/complete for context 0&lt;br /&gt;
 base + 0x200008: Reserved&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x200FFC: Reserved&lt;br /&gt;
 base + 0x201000: Priority threshold for context 1&lt;br /&gt;
 base + 0x201004: Claim/complete for context 1&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x3FFF000: Priority threshold for context 15871&lt;br /&gt;
 base + 0x3FFF004: Claim/complete for context 15871&lt;br /&gt;
 base + 0x3FFF008: Reserved&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x3FFFFFC: Reserved&lt;br /&gt;
&lt;br /&gt;
Or, more usefully:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;rust&amp;quot; line&amp;gt;&lt;br /&gt;
#[repr(C)]&lt;br /&gt;
struct Plic {&lt;br /&gt;
    source_priorities: [u32; 1024],&lt;br /&gt;
    interrupt_pending: [u32; 32],&lt;br /&gt;
    _padding1: [u8; 3968],&lt;br /&gt;
    interrupt_enable: [[u32; 32]; 15872],&lt;br /&gt;
    _padding2: [u8; 57344],&lt;br /&gt;
    threshold_and_claim: [[u32; 1024]; 15872],&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Each &amp;lt;code&amp;gt;u32&amp;lt;/code&amp;gt; inside of the &amp;lt;code&amp;gt;source_priorities&amp;lt;/code&amp;gt; is a priority level from &amp;lt;code&amp;gt;0..=7&amp;lt;/code&amp;gt; (on most platforms, see your platform specification for more complete information) of increasing priority level where priority &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; is considered &amp;quot;never interrupt&amp;quot; and will cause the interrupt to effectively be disabled, with the exception of interrupt #0, which does not exist and is reserved. &amp;lt;code&amp;gt;interrupt_pending&amp;lt;/code&amp;gt; is a read-only bitmap of the pending status for priorities &amp;lt;code&amp;gt;1..=1024&amp;lt;/code&amp;gt; (with the interrupt #0 bit hardwired to zero). Both &amp;lt;code&amp;gt;interrupt_enable&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;threshold_and_claim&amp;lt;/code&amp;gt; work on the aforementioned contexts, and need to be indexed at a platform-specific index for a given hart and privilege mode combination. The &amp;lt;code&amp;gt;interrupt_enable&amp;lt;/code&amp;gt; consists of another bitmap of interrupt sources (again with interrupt #0 for each context being hardwired to zero) which allow enabling and disabling specific interrupt sources at the context level, but also means that if you wish for a given interrupt to trigger across any hart, it will need to be enabled for each context for the privilege mode you are executing in. &amp;lt;code&amp;gt;threshold_and_claim&amp;lt;/code&amp;gt; is made up of a threshold &amp;lt;code&amp;gt;u32&amp;lt;/code&amp;gt; value and a claim &amp;lt;code&amp;gt;u32&amp;lt;/code&amp;gt; value, with the rest of the &amp;lt;code&amp;gt;u32&amp;lt;/code&amp;gt;s being reserved and should not be written to.&lt;br /&gt;
&lt;br /&gt;
=== Hart &amp;amp; Privilege Context Mappings ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Platform&lt;br /&gt;
!M-mode Context&lt;br /&gt;
!S-mode Context&lt;br /&gt;
|-&lt;br /&gt;
|QEMU virt&lt;br /&gt;
|&amp;lt;code&amp;gt;hart_id * 2&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
 hart_id * 2 + 1&lt;br /&gt;
|-&lt;br /&gt;
|QEMU sifive_u&amp;lt;sup&amp;gt;†&amp;lt;/sup&amp;gt;&lt;br /&gt;
|Monitor hart: &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Other harts: &amp;lt;code&amp;gt;hart_id * 2 + 1&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;hart_id * 2&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;sup&amp;gt;†&amp;lt;/sup&amp;gt;This platform contains a [[Monitor Hart]] which does not support S-mode and does not have the same extension availability as the general-purpose harts&lt;br /&gt;
&lt;br /&gt;
=== Enabling and Disabling Interrupts ===&lt;br /&gt;
To enable or disable any given interrupt source, simply toggle the specific bit that corresponds to the interrupt source in the &amp;lt;code&amp;gt;interrupt_enable&amp;lt;/code&amp;gt; for the context for which you wish to enable or disable the interrupt. Example Rust code:&amp;lt;syntaxhighlight lang=&amp;quot;rust&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
unsafe fn enable_interrupt(plic: *mut Plic, context: usize, interrupt_source: usize) {&lt;br /&gt;
    // Sanity checks, neither values would be valid&lt;br /&gt;
    if context &amp;gt;= 15872 || interrupt_source &amp;gt;= 1024 {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // Calculate the bit-group index and the bit index for that bit-group&lt;br /&gt;
    let (u32_index, bit) = (interrupt_source / 32, interrupt_source % 32);&lt;br /&gt;
    &lt;br /&gt;
    // Calculate the address of the bit-group&lt;br /&gt;
    let bit_group_ptr = unsafe { core::ptr::addr_of_mut!((*plic).interrupt_enable[context][u32_index]) };&lt;br /&gt;
    &lt;br /&gt;
    // Read the current value&lt;br /&gt;
    let previous = unsafe { bit_group_ptr.read_volatile() };&lt;br /&gt;
    &lt;br /&gt;
    // Set the bit for the interrupt source&lt;br /&gt;
    let new = previous | (1 &amp;lt;&amp;lt; bit);&lt;br /&gt;
    &lt;br /&gt;
    // Write the new value&lt;br /&gt;
    unsafe { bit_group_ptr.write_volatile(new) };&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
unsafe fn disable_interrupt(plic: *mut Plic, context: usize, interrupt_source: usize) {&lt;br /&gt;
    // Sanity checks, neither values would be valid&lt;br /&gt;
    if context &amp;gt;= 15872 || interrupt_source &amp;gt;= 1024 {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // Calculate the bit-group index and the bit index for that bit-group&lt;br /&gt;
    let (u32_index, bit) = (interrupt_source / 32, interrupt_source % 32);&lt;br /&gt;
    &lt;br /&gt;
    // Calculate the address of the bit-group&lt;br /&gt;
    let bit_group_ptr = unsafe { core::ptr::addr_of_mut!((*plic).interrupt_enable[context][u32_index]) };&lt;br /&gt;
    &lt;br /&gt;
    // Read the current value&lt;br /&gt;
    let previous = unsafe { bit_group_ptr.read_volatile() };&lt;br /&gt;
    &lt;br /&gt;
    // Set the bit for the interrupt source&lt;br /&gt;
    let new = previous &amp;amp; !(1 &amp;lt;&amp;lt; bit);&lt;br /&gt;
    &lt;br /&gt;
    // Write the new value&lt;br /&gt;
    unsafe { bit_group_ptr.write_volatile(new) };&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
__FORCETOC__&lt;/div&gt;</summary>
		<author><name>Repnop</name></author>
	</entry>
	<entry>
		<id>https://wiki.friendos.dev/index.php?title=PLIC&amp;diff=17</id>
		<title>PLIC</title>
		<link rel="alternate" type="text/html" href="https://wiki.friendos.dev/index.php?title=PLIC&amp;diff=17"/>
		<updated>2023-02-02T02:45:36Z</updated>

		<summary type="html">&lt;p&gt;Repnop: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The Platform Interrupt Controller (PLIC) is the standardized device for receiving, routing, and completing [[Interrupts#External|external interrupts]] with configuration per-[[hart]] and per-[[Privilege Mode|privilege mode]]. Originally, the PLIC design is based on early SiFive designs which were then slightly refined and standardized and only supports basic interrupt enabling/disabling, prioritization and routing. As part of the [[RISC-V Advanced Interrupt Architecture]] (AIA), the original PLIC design is extended to support more types of interrupts, namely [[Message Signaled Interrupt]]&amp;lt;nowiki/&amp;gt;s (MSIs), which are important for technologies like [[PCI]]. The PLIC specification can be found at https://github.com/riscv/riscv-plic-spec while the APLIC specification is available at https://github.com/riscv/riscv-aia.&lt;br /&gt;
&lt;br /&gt;
== Original PLIC Design ==&lt;br /&gt;
The original PLIC design consist of a set of: interrupt source priorities, interrupt pending bits, per-context interrupt enable bits, and then per-context priority threshold &amp;amp; claim/complete regions. A context is the combination of a hart ID and a privilege mode, though the specific ordering of contexts is platform-specific and cannot be generalized between them. A small table below has been added for quick reference, but likely will not contain a formula for calculating the context for every platform. The memory layout for the PLIC is as follows (taken from the PLIC spec):&lt;br /&gt;
 base + 0x000000: Reserved (interrupt source 0 does not exist)&lt;br /&gt;
 base + 0x000004: Interrupt source 1 priority&lt;br /&gt;
 base + 0x000008: Interrupt source 2 priority&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x000FFC: Interrupt source 1023 priority&lt;br /&gt;
 base + 0x001000: Interrupt Pending bit 0-31&lt;br /&gt;
 base + 0x00107C: Interrupt Pending bit 992-1023&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x002000: Enable bits for sources 0-31 on context 0&lt;br /&gt;
 base + 0x002004: Enable bits for sources 32-63 on context 0&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x00207C: Enable bits for sources 992-1023 on context 0&lt;br /&gt;
 base + 0x002080: Enable bits for sources 0-31 on context 1&lt;br /&gt;
 base + 0x002084: Enable bits for sources 32-63 on context 1&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x0020FC: Enable bits for sources 992-1023 on context 1&lt;br /&gt;
 base + 0x002100: Enable bits for sources 0-31 on context 2&lt;br /&gt;
 base + 0x002104: Enable bits for sources 32-63 on context 2&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x00217C: Enable bits for sources 992-1023 on context 2&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x1F1F80: Enable bits for sources 0-31 on context 15871&lt;br /&gt;
 base + 0x1F1F84: Enable bits for sources 32-63 on context 15871&lt;br /&gt;
 base + 0x1F1FFC: Enable bits for sources 992-1023 on context 15871&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x1FFFFC: Reserved&lt;br /&gt;
 base + 0x200000: Priority threshold for context 0&lt;br /&gt;
 base + 0x200004: Claim/complete for context 0&lt;br /&gt;
 base + 0x200008: Reserved&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x200FFC: Reserved&lt;br /&gt;
 base + 0x201000: Priority threshold for context 1&lt;br /&gt;
 base + 0x201004: Claim/complete for context 1&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x3FFF000: Priority threshold for context 15871&lt;br /&gt;
 base + 0x3FFF004: Claim/complete for context 15871&lt;br /&gt;
 base + 0x3FFF008: Reserved&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x3FFFFFC: Reserved&lt;br /&gt;
&lt;br /&gt;
Or, more usefully:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;rust&amp;quot; line&amp;gt;&lt;br /&gt;
#[repr(C)]&lt;br /&gt;
struct Plic {&lt;br /&gt;
    source_priorities: [u32; 1024],&lt;br /&gt;
    interrupt_pending: [u32; 32],&lt;br /&gt;
    _padding1: [u8; 3968],&lt;br /&gt;
    interrupt_enable: [[u32; 32]; 15872],&lt;br /&gt;
    _padding2: [u8; 57344],&lt;br /&gt;
    threshold_and_claim: [[u32; 1024]; 15872],&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Each &amp;lt;code&amp;gt;u32&amp;lt;/code&amp;gt; inside of the &amp;lt;code&amp;gt;source_priorities&amp;lt;/code&amp;gt; is a priority level from &amp;lt;code&amp;gt;0..=7&amp;lt;/code&amp;gt; (on most platforms, see your platform specification for more complete information) of increasing priority level where priority &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; is considered &amp;quot;never interrupt&amp;quot; and will cause the interrupt to effectively be disabled, with the exception of interrupt #0, which does not exist and is reserved. &amp;lt;code&amp;gt;interrupt_pending&amp;lt;/code&amp;gt; is a read-only bitmap of the pending status for priorities &amp;lt;code&amp;gt;1..=1024&amp;lt;/code&amp;gt; (with the interrupt #0 bit hardwired to zero). Both &amp;lt;code&amp;gt;interrupt_enable&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;threshold_and_claim&amp;lt;/code&amp;gt; work on the aforementioned contexts, and need to be indexed at a platform-specific index for a given hart and privilege mode combination. The &amp;lt;code&amp;gt;interrupt_enable&amp;lt;/code&amp;gt; consists of another bitmap of interrupt sources (again with interrupt #0 for each context being hardwired to zero) which allow enabling and disabling specific interrupt sources at the context level, but also means that if you wish for a given interrupt to trigger across any hart, it will need to be enabled for each context for the privilege mode you are executing in. &amp;lt;code&amp;gt;threshold_and_claim&amp;lt;/code&amp;gt; is made up of a threshold &amp;lt;code&amp;gt;u32&amp;lt;/code&amp;gt; value and a claim &amp;lt;code&amp;gt;u32&amp;lt;/code&amp;gt; value, with the rest of the &amp;lt;code&amp;gt;u32&amp;lt;/code&amp;gt;s being reserved and should not be written to.&lt;/div&gt;</summary>
		<author><name>Repnop</name></author>
	</entry>
	<entry>
		<id>https://wiki.friendos.dev/index.php?title=PLIC&amp;diff=16</id>
		<title>PLIC</title>
		<link rel="alternate" type="text/html" href="https://wiki.friendos.dev/index.php?title=PLIC&amp;diff=16"/>
		<updated>2023-02-02T02:44:13Z</updated>

		<summary type="html">&lt;p&gt;Repnop: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The Platform Interrupt Controller (PLIC) is the standardized device for receiving, routing, and completing [[Interrupts#External|external interrupts]] with configuration per-[[hart]] and per-[[Privilege Mode|privilege mode]]. Originally, the PLIC design is based on early SiFive designs which were then slightly refined and standardized and only supports basic interrupt enabling/disabling, prioritization and routing. As part of the [[RISC-V Advanced Interrupt Architecture]] (AIA), the original PLIC design is extended to support more types of interrupts, namely [[Message Signaled Interrupt]]&amp;lt;nowiki/&amp;gt;s (MSIs), which are important for technologies like [[PCI]]. The PLIC specification can be found at https://github.com/riscv/riscv-plic-spec while the APLIC specification is available at https://github.com/riscv/riscv-aia.&lt;br /&gt;
&lt;br /&gt;
== Original PLIC Design ==&lt;br /&gt;
The original PLIC design consist of a set of: interrupt source priorities, interrupt pending bits, per-context interrupt enable bits, and then per-context priority threshold &amp;amp; claim/complete regions. A context is the combination of a hart ID and a privilege mode, though the specific ordering of contexts is platform-specific and cannot be generalized between them. A small table below has been added for quick reference, but likely will not contain a formula for calculating the context for every platform. The memory layout for the PLIC is as follows (taken from the PLIC spec):&lt;br /&gt;
 base + 0x000000: Reserved (interrupt source 0 does not exist)&lt;br /&gt;
 base + 0x000004: Interrupt source 1 priority&lt;br /&gt;
 base + 0x000008: Interrupt source 2 priority&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x000FFC: Interrupt source 1023 priority&lt;br /&gt;
 base + 0x001000: Interrupt Pending bit 0-31&lt;br /&gt;
 base + 0x00107C: Interrupt Pending bit 992-1023&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x002000: Enable bits for sources 0-31 on context 0&lt;br /&gt;
 base + 0x002004: Enable bits for sources 32-63 on context 0&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x00207C: Enable bits for sources 992-1023 on context 0&lt;br /&gt;
 base + 0x002080: Enable bits for sources 0-31 on context 1&lt;br /&gt;
 base + 0x002084: Enable bits for sources 32-63 on context 1&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x0020FC: Enable bits for sources 992-1023 on context 1&lt;br /&gt;
 base + 0x002100: Enable bits for sources 0-31 on context 2&lt;br /&gt;
 base + 0x002104: Enable bits for sources 32-63 on context 2&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x00217C: Enable bits for sources 992-1023 on context 2&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x1F1F80: Enable bits for sources 0-31 on context 15871&lt;br /&gt;
 base + 0x1F1F84: Enable bits for sources 32-63 on context 15871&lt;br /&gt;
 base + 0x1F1FFC: Enable bits for sources 992-1023 on context 15871&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x1FFFFC: Reserved&lt;br /&gt;
 base + 0x200000: Priority threshold for context 0&lt;br /&gt;
 base + 0x200004: Claim/complete for context 0&lt;br /&gt;
 base + 0x200008: Reserved&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x200FFC: Reserved&lt;br /&gt;
 base + 0x201000: Priority threshold for context 1&lt;br /&gt;
 base + 0x201004: Claim/complete for context 1&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x3FFF000: Priority threshold for context 15871&lt;br /&gt;
 base + 0x3FFF004: Claim/complete for context 15871&lt;br /&gt;
 base + 0x3FFF008: Reserved&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x3FFFFFC: Reserved&lt;br /&gt;
&lt;br /&gt;
Or, more usefully:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;rust&amp;quot; line&amp;gt;&lt;br /&gt;
#[repr(C)]&lt;br /&gt;
struct Plic {&lt;br /&gt;
    source_priorities: [u32; 1024],&lt;br /&gt;
    interrupt_pending: [u32; 32],&lt;br /&gt;
    _padding1: [u8; 3968],&lt;br /&gt;
    interrupt_enable: [[u32; 32]; 15872],&lt;br /&gt;
    _padding2: [u8; 57344],&lt;br /&gt;
    threshold_and_claim: [[u32; 1024]; 15872],&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Each &amp;lt;pre&amp;gt;u32&amp;lt;/pre&amp;gt; inside of the &amp;lt;pre&amp;gt;source_priorities&amp;lt;/pre&amp;gt; is a priority level from &amp;lt;pre&amp;gt;0..=7&amp;lt;/pre&amp;gt; (on most platforms, see your platform specification for more complete information) of increasing priority level where priority &amp;lt;pre&amp;gt;0&amp;lt;/pre&amp;gt; is considered &amp;quot;never interrupt&amp;quot; and will cause the interrupt to effectively be disabled, with the exception of interrupt #0, which does not exist and is reserved. &amp;lt;pre&amp;gt;interrupt_pending&amp;lt;/pre&amp;gt; is a read-only bitmap of the pending status for priorities &amp;lt;pre&amp;gt;1..=1024&amp;lt;/pre&amp;gt; (with the interrupt #0 bit hardwired to zero). Both &amp;lt;pre&amp;gt;interrupt_enable&amp;lt;/pre&amp;gt; and &amp;lt;pre&amp;gt;threshold_and_claim&amp;lt;/pre&amp;gt; work on the aforementioned contexts, and need to be indexed at a platform-specific index for a given hart and privilege mode combination. The &amp;lt;pre&amp;gt;interrupt_enable&amp;lt;/pre&amp;gt; consists of another bitmap of interrupt sources (again with interrupt #0 for each context being hardwired to zero) which allow enabling and disabling specific interrupt sources at the context level, but also means that if you wish for a given interrupt to trigger across any hart, it will need to be enabled for each context for the privilege mode you are executing in. &amp;lt;pre&amp;gt;threshold_and_claim&amp;lt;/pre&amp;gt; is made up of a threshold &amp;lt;pre&amp;gt;u32&amp;lt;/pre&amp;gt; value and a claim &amp;lt;pre&amp;gt;u32&amp;lt;/pre&amp;gt; value, with the rest of the &amp;lt;pre&amp;gt;u32&amp;lt;/pre&amp;gt;s being reserved and should not be written to.&lt;/div&gt;</summary>
		<author><name>Repnop</name></author>
	</entry>
	<entry>
		<id>https://wiki.friendos.dev/index.php?title=PLIC&amp;diff=15</id>
		<title>PLIC</title>
		<link rel="alternate" type="text/html" href="https://wiki.friendos.dev/index.php?title=PLIC&amp;diff=15"/>
		<updated>2023-02-02T01:54:49Z</updated>

		<summary type="html">&lt;p&gt;Repnop: Initial writeup -- incomplete but need to restart&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The Platform Interrupt Controller (PLIC) is the standardized device for receiving, routing, and completing [[Interrupts#External|external interrupts]] with configuration per-[[hart]] and per-[[Privilege Mode|privilege mode]]. Originally, the PLIC design is based on early SiFive designs which were then slightly refined and standardized and only supports basic interrupt enabling/disabling, prioritization and routing. As part of the [[RISC-V Advanced Interrupt Architecture]] (AIA), the original PLIC design is extended to support more types of interrupts, namely [[Message Signaled Interrupt]]&amp;lt;nowiki/&amp;gt;s (MSIs), which are important for technologies like [[PCI]]. The PLIC specification can be found at https://github.com/riscv/riscv-plic-spec while the APLIC specification is available at https://github.com/riscv/riscv-aia.&lt;br /&gt;
&lt;br /&gt;
== Original PLIC Design ==&lt;br /&gt;
The original PLIC design consist of a set of: interrupt source priorities, interrupt pending bits, per-context interrupt enable bits, and then per-context priority threshold &amp;amp; claim/complete regions. A context is the combination of a hart ID and a privilege mode, though the specific ordering of contexts is platform-specific and cannot be generalized between them. A small table below has been added for quick reference, but likely will not contain a formula for calculating the context for every platform. The memory layout for the PLIC is as follows (taken from the PLIC spec):&lt;br /&gt;
 base + 0x000000: Reserved (interrupt source 0 does not exist)&lt;br /&gt;
 base + 0x000004: Interrupt source 1 priority&lt;br /&gt;
 base + 0x000008: Interrupt source 2 priority&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x000FFC: Interrupt source 1023 priority&lt;br /&gt;
 base + 0x001000: Interrupt Pending bit 0-31&lt;br /&gt;
 base + 0x00107C: Interrupt Pending bit 992-1023&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x002000: Enable bits for sources 0-31 on context 0&lt;br /&gt;
 base + 0x002004: Enable bits for sources 32-63 on context 0&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x00207C: Enable bits for sources 992-1023 on context 0&lt;br /&gt;
 base + 0x002080: Enable bits for sources 0-31 on context 1&lt;br /&gt;
 base + 0x002084: Enable bits for sources 32-63 on context 1&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x0020FC: Enable bits for sources 992-1023 on context 1&lt;br /&gt;
 base + 0x002100: Enable bits for sources 0-31 on context 2&lt;br /&gt;
 base + 0x002104: Enable bits for sources 32-63 on context 2&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x00217C: Enable bits for sources 992-1023 on context 2&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x1F1F80: Enable bits for sources 0-31 on context 15871&lt;br /&gt;
 base + 0x1F1F84: Enable bits for sources 32-63 on context 15871&lt;br /&gt;
 base + 0x1F1FFC: Enable bits for sources 992-1023 on context 15871&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x1FFFFC: Reserved&lt;br /&gt;
 base + 0x200000: Priority threshold for context 0&lt;br /&gt;
 base + 0x200004: Claim/complete for context 0&lt;br /&gt;
 base + 0x200008: Reserved&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x200FFC: Reserved&lt;br /&gt;
 base + 0x201000: Priority threshold for context 1&lt;br /&gt;
 base + 0x201004: Claim/complete for context 1&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x3FFF000: Priority threshold for context 15871&lt;br /&gt;
 base + 0x3FFF004: Claim/complete for context 15871&lt;br /&gt;
 base + 0x3FFF008: Reserved&lt;br /&gt;
 ...&lt;br /&gt;
 base + 0x3FFFFFC: Reserved&lt;br /&gt;
Or, more usefully:&lt;br /&gt;
 #[repr(C)]&lt;br /&gt;
 pub struct Plic {&lt;br /&gt;
     source_priorities: [u32; 1024],&lt;br /&gt;
     interrupt_pending: [u32; 32],&lt;br /&gt;
     _padding1: [u8; 3968],&lt;br /&gt;
     interrupt_enable: [[u32; 32]; 15872],&lt;br /&gt;
     _padding2: [u8; 57344],&lt;br /&gt;
     threshold_and_claim: [[u32; 4090]; 15872],&lt;br /&gt;
     _padding3: [u8; 8184],&lt;br /&gt;
 }&lt;/div&gt;</summary>
		<author><name>Repnop</name></author>
	</entry>
	<entry>
		<id>https://wiki.friendos.dev/index.php?title=Main_Page&amp;diff=11</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://wiki.friendos.dev/index.php?title=Main_Page&amp;diff=11"/>
		<updated>2022-11-24T02:22:59Z</updated>

		<summary type="html">&lt;p&gt;Repnop: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Welcome to the FriendOS Wiki! ==&lt;br /&gt;
&lt;br /&gt;
The FriendOS Wiki is a community-driven wiki for the [https://discord.gg/U9feA9z669 FriendOS Discord server]. This wiki, as well as the Discord server, are intended to create a more inclusive, supportive, and welcoming environment for people learning about operating systems development, which historically is not very common. The purpose of this wiki is to provide resources for newbies and veterans alike, as well as allowing contributions from the community members so that people can easily create &amp;amp; share information about the concepts that they frequently work with. If you think you have something to contribute, make an account and start writing! If you have comments or questions, you can discuss the wiki in the #wiki channel on the Discord server.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Helpful Links ==&lt;br /&gt;
&lt;br /&gt;
* [https://discord.gg/U9feA9z669 Discord invite link]&lt;br /&gt;
* [[Special:AllPages|See all pages]]&lt;/div&gt;</summary>
		<author><name>Repnop</name></author>
	</entry>
	<entry>
		<id>https://wiki.friendos.dev/index.php?title=Main_Page&amp;diff=10</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://wiki.friendos.dev/index.php?title=Main_Page&amp;diff=10"/>
		<updated>2022-11-24T02:18:32Z</updated>

		<summary type="html">&lt;p&gt;Repnop: Add a bit more context&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Welcome to the FriendOS Wiki! ==&lt;br /&gt;
&lt;br /&gt;
The FriendOS Wiki is a community-driven wiki for the [https://discord.gg/U9feA9z669 FriendOS Discord server]. This wiki, as well as the Discord server, are intended to create a more inclusive, supportive, and welcoming environment for people learning about operating systems development, which historically is not very common. The purpose of this wiki is to provide resources for newbies and veterans alike, as well as allowing contributions from the community members so that people can easily create &amp;amp; share information about the concepts that they frequently work with.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Helpful Links ==&lt;br /&gt;
&lt;br /&gt;
* [https://discord.gg/U9feA9z669 Discord invite link]&lt;br /&gt;
* [[Special:AllPages|See all pages]]&lt;/div&gt;</summary>
		<author><name>Repnop</name></author>
	</entry>
	<entry>
		<id>https://wiki.friendos.dev/index.php?title=VirtIO&amp;diff=5</id>
		<title>VirtIO</title>
		<link rel="alternate" type="text/html" href="https://wiki.friendos.dev/index.php?title=VirtIO&amp;diff=5"/>
		<updated>2022-11-22T23:02:44Z</updated>

		<summary type="html">&lt;p&gt;Repnop: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;VirtIO is a standard for performant virtualized hardware for use within virtual machines, created and managed by the [https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=virtio OASIS Open Virtual I/O Device TC]. VirtIO supports a variety of devices, such as, but not limited to: block (e.g. hard drive), network card, GPU, etc. Each of these devices have their own specific configuration and features, but all use the same underlying VirtIO queue structure for relaying data and commands to &amp;amp; from the device.&lt;br /&gt;
&lt;br /&gt;
=== Device Types ===&lt;br /&gt;
{| class=&amp;quot;wikitable sortable mw-collapsible&amp;quot;&lt;br /&gt;
|+VirtIO Device Types&lt;br /&gt;
!Device Name&lt;br /&gt;
!Device ID&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|Network Card&lt;br /&gt;
|1&lt;br /&gt;
|Ethernet network interface&lt;br /&gt;
|-&lt;br /&gt;
|Block Device&lt;br /&gt;
|2&lt;br /&gt;
|Block storage capabilities, e.g. hard drive, for storing files and other information&lt;br /&gt;
|-&lt;br /&gt;
|Console&lt;br /&gt;
|3&lt;br /&gt;
|Serial console device for simple I/O communication&lt;br /&gt;
|-&lt;br /&gt;
|Entropy Source&lt;br /&gt;
|4&lt;br /&gt;
|A source of entropy for cryptographically secure [[PRNG]]&amp;lt;nowiki/&amp;gt;s&lt;br /&gt;
|-&lt;br /&gt;
|Memory Ballooning (Traditional)&lt;br /&gt;
|5&lt;br /&gt;
|[TODO]&lt;br /&gt;
|-&lt;br /&gt;
|ioMemory&lt;br /&gt;
|6&lt;br /&gt;
|[TODO]&lt;br /&gt;
|-&lt;br /&gt;
|rpmsg&lt;br /&gt;
|7&lt;br /&gt;
|[TODO]&lt;br /&gt;
|-&lt;br /&gt;
|SCSI Host&lt;br /&gt;
|8&lt;br /&gt;
|Grouping of one or more virtual logical units (e.g. disks) that can be managed via the SCSI protocol&lt;br /&gt;
|-&lt;br /&gt;
|9P Transport&lt;br /&gt;
|9&lt;br /&gt;
|[TODO]&lt;br /&gt;
|-&lt;br /&gt;
|MAC80211 WLAN&lt;br /&gt;
|10&lt;br /&gt;
|802.11 WLAN interface for wireless [[LAN]] communication&lt;br /&gt;
|-&lt;br /&gt;
|rproc Serial&lt;br /&gt;
|11&lt;br /&gt;
|[TODO]&lt;br /&gt;
|-&lt;br /&gt;
|VirtIO CAIF&lt;br /&gt;
|12&lt;br /&gt;
|[TODO]&lt;br /&gt;
|-&lt;br /&gt;
|Memory Balloon&lt;br /&gt;
|13&lt;br /&gt;
|[TODO]&lt;br /&gt;
|-&lt;br /&gt;
|GPU&lt;br /&gt;
|16&lt;br /&gt;
|2D &amp;amp; 3D GPU device, requires a 3D GPU on the host machine for 3D mode, as well as negotiating specific features&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Device Transports ===&lt;br /&gt;
VirtIO supports three different types of device transports: [[PCI|PCI Bus]], [[MMIO]], and [[Channel I/O]]. The PCIe transport is configured via the normal PCIe configuration mechanisms, while the MMIO transport is configured strictly via MMIO reads and writes.&lt;/div&gt;</summary>
		<author><name>Repnop</name></author>
	</entry>
	<entry>
		<id>https://wiki.friendos.dev/index.php?title=File:Friendos-wikiicon.png&amp;diff=4</id>
		<title>File:Friendos-wikiicon.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.friendos.dev/index.php?title=File:Friendos-wikiicon.png&amp;diff=4"/>
		<updated>2022-11-22T22:13:55Z</updated>

		<summary type="html">&lt;p&gt;Repnop: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Repnop</name></author>
	</entry>
	<entry>
		<id>https://wiki.friendos.dev/index.php?title=File:Friendos.png&amp;diff=3</id>
		<title>File:Friendos.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.friendos.dev/index.php?title=File:Friendos.png&amp;diff=3"/>
		<updated>2022-11-22T22:11:03Z</updated>

		<summary type="html">&lt;p&gt;Repnop: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Repnop</name></author>
	</entry>
	<entry>
		<id>https://wiki.friendos.dev/index.php?title=VirtIO&amp;diff=2</id>
		<title>VirtIO</title>
		<link rel="alternate" type="text/html" href="https://wiki.friendos.dev/index.php?title=VirtIO&amp;diff=2"/>
		<updated>2022-11-22T21:54:06Z</updated>

		<summary type="html">&lt;p&gt;Repnop: Initial page test&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;VirtIO is a standard for performant virtualized hardware for use within virtual machines created and managed by the [https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=virtio OASIS Open Virtual I/O Device TC].&lt;/div&gt;</summary>
		<author><name>Repnop</name></author>
	</entry>
</feed>