<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>0x646b - uart</title>
    <subtitle>Personal Commentary</subtitle>
    <link rel="self" type="application/atom+xml" href="https://Karthik-d-k.github.io/tags/uart/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://Karthik-d-k.github.io"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-07-02T00:00:00+00:00</updated>
    <id>https://Karthik-d-k.github.io/tags/uart/atom.xml</id>
    <entry xml:lang="en">
        <title>UART in QEMU</title>
        <published>2026-07-02T00:00:00+00:00</published>
        <updated>2026-07-02T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Karthik
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://Karthik-d-k.github.io/blog/qemu-uart/"/>
        <id>https://Karthik-d-k.github.io/blog/qemu-uart/</id>
        
        <content type="html" xml:base="https://Karthik-d-k.github.io/blog/qemu-uart/">&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;&#x2F;h2&gt;
&lt;p&gt;In the &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;karthik-d-k.github.io&#x2F;blog&#x2F;riscv-startup-code&#x2F;&quot;&gt;previous post&lt;&#x2F;a&gt; we looked at how xv6 kernel startup code is implemented and verified the correctness of it by manual inspecting registers inside GDB.&lt;&#x2F;p&gt;
&lt;p&gt;Today we will add print functionality to our kernel, so that we can print at various stages to verify that we are doing things correctly and also we could make use of this for &lt;code&gt;&quot;printf debugging&quot;&lt;&#x2F;code&gt;. &lt;strong&gt;Generic Virtual Platform (virt)&lt;&#x2F;strong&gt; in QEMU on which we run our OS contains one &lt;strong&gt;NS16550A compatible UART&lt;&#x2F;strong&gt; (universal asynchronous receiver&#x2F;transmitter) device.&lt;&#x2F;p&gt;
&lt;p&gt;We will implement the UART driver for this device in Rust and make it as similar as possible to our &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mit-pdos&#x2F;xv6-riscv&quot;&gt;reference C source code&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;&#x2F;strong&gt; I’m implementing just a simple driver without any lock mechanisms, meaning we cannot use the print functionality in a way that a race condition arises. For now, we will just use it in our main core (core 0) to show that UART works fine. Locks will be implemented later. As I’m writing the blog posts as I implement my Rust rewrite, there could be some updates&#x2F;corrections in my latest source code on Github to what I show here.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;ns16550-uart&quot;&gt;NS16550 UART&lt;&#x2F;h2&gt;
&lt;p&gt;I would like to give a brief overview about &lt;strong&gt;NS16550 UART&lt;&#x2F;strong&gt; so that we will know how to implement the driver correctly and in an easy way. This device is the widely used and industry standard in embedded world.&lt;&#x2F;p&gt;
&lt;p&gt;UART acts as a bridge between processor&#x2F;controller to a peripheral device. It performs:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Serial-to-Parallel conversion on data received from a peripheral device.&lt;&#x2F;li&gt;
&lt;li&gt;Parallel-to-Serial conversion on data transmitted to the peripheral device.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;UART’s TX and RX lines should be connected to RX and TX lines of the peripheral respectively and it can receive or transmit data independently. There is no clock source to synchronize the data between these, but we do have to set same &lt;strong&gt;Baud rate&lt;&#x2F;strong&gt; so that the data is received&#x2F;sent correctly, or else we will see garbage when we print the received data to the console.&lt;&#x2F;p&gt;
&lt;p&gt;This UART also contains separate &lt;code&gt;16-byte FIFOs&lt;&#x2F;code&gt; with support circuitry to minimize software overhead when handling interrupts.
Along with FIFO registers we will have access to some control registers to set:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;baud rate&lt;&#x2F;li&gt;
&lt;li&gt;word length&lt;&#x2F;li&gt;
&lt;li&gt;parity type&lt;&#x2F;li&gt;
&lt;li&gt;number of stop bits&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I will explain about these things with the code snippets in the next section.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;uart-driver&quot;&gt;UART Driver&lt;&#x2F;h2&gt;
&lt;p&gt;We will use &lt;code&gt;Polling&lt;&#x2F;code&gt; method instead of &lt;code&gt;Interrupts&lt;&#x2F;code&gt; to implement our driver which makes it easier to implement just by using registers without any involvement of DMA (Direct Memory Access) or other interrupt shenanigans.&lt;&#x2F;p&gt;
&lt;p&gt;QEMU puts UART registers at address &lt;code&gt;0x10000000&lt;&#x2F;code&gt; -&amp;gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;memlayout.rs&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rs&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rs &quot;&gt;&lt;code class=&quot;language-rs&quot; data-lang=&quot;rs&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;UART0&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64 &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0x10000000&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We will use register offsets to read&#x2F;write correct UART registers from this Base address using volatile pointers.
The reason to use volatile read&#x2F;writes instead of normal read&#x2F;writes are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Compiler will optimize the variables if it reasons that the variable&#x2F;memory doesn’t change while it is accessed, it removes it completely.&lt;&#x2F;li&gt;
&lt;li&gt;But MMIO (Memory Mapped I&#x2F;O) that we use for the devices can change at any point in time because it depends on the hardware not software.&lt;&#x2F;li&gt;
&lt;li&gt;So we will explicitly tell the compiler that we know what we are doing, please don’t optimize away MMIO accesses.&lt;&#x2F;li&gt;
&lt;li&gt;C reference also does the same thing here, we follow the same in Rust.&lt;&#x2F;li&gt;
&lt;li&gt;You could see any PAC (Peripheral Access Crate) in Rust embedded world, you will see all MMIOs are accessed this way.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;uart.rs&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rs&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rs &quot;&gt;&lt;code class=&quot;language-rs&quot; data-lang=&quot;rs&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use crate&lt;&#x2F;span&gt;&lt;span&gt;::memlayout::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;UART0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;core::ptr::{read_volatile, write_volatile};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;allow&lt;&#x2F;span&gt;&lt;span&gt;(non_snake_case)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;ReadReg&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;reg&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read_volatile&lt;&#x2F;span&gt;&lt;span&gt;((&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;UART0 &lt;&#x2F;span&gt;&lt;span&gt;+ reg) as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*const u8&lt;&#x2F;span&gt;&lt;span&gt;) }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;allow&lt;&#x2F;span&gt;&lt;span&gt;(non_snake_case)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;WriteReg&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;reg&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;val&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;write_volatile&lt;&#x2F;span&gt;&lt;span&gt;((&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;UART0 &lt;&#x2F;span&gt;&lt;span&gt;+ reg) as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;*mut u8&lt;&#x2F;span&gt;&lt;span&gt;, val) }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We will now define &lt;code&gt;const&lt;&#x2F;code&gt; values to store UART control registers that we use:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;uart.rs&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rs&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rs &quot;&gt;&lt;code class=&quot;language-rs&quot; data-lang=&quot;rs&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;RHR&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64 &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;THR&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64 &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;DLAB_LSB&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64 &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;DLAB_MSB&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64 &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;IER&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64 &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;FCR&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64 &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;FCR_FIFO_ENABLE&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8 &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;FCR_FIFO_CLEAR&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8 &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3 &lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;LCR&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64 &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;LCR_EIGHT_BITS&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8 &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;3 &lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;LCR_BAUD_LATCH&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8 &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;7&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;LSR&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64 &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;LSR_TX_IDLE&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8 &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ul&gt;
&lt;li&gt;We have &lt;strong&gt;Receive and Transmit Holding Registers&lt;&#x2F;strong&gt; (RHR&#x2F;THR) at the same offset &lt;code&gt;0&lt;&#x2F;code&gt;. Device disambiguates which one we are talking to by &lt;code&gt;Direction&lt;&#x2F;code&gt;, meaning if we wrote to that address, its THR, if we read from it its RHR. We read&#x2F;write data to these registers. (For now we only transmit, so &lt;code&gt;RHR&lt;&#x2F;code&gt; is defined for completeness; we will use it when we add input handling.)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Interrupt Enable Register&lt;&#x2F;strong&gt; (IER) is present at offset &lt;code&gt;1&lt;&#x2F;code&gt; which is used to enable&#x2F;disable Interrupts.&lt;&#x2F;li&gt;
&lt;li&gt;We have programmable baud rate functionality which can be used to set to our required baud rate by using DLAB (divisor latch access bit) and Divisor Latch registers. Here device disambiguates whether we are referring to DLAB_LSB&#x2F;DLAB_MSB or RHR&#x2F;THR&#x2F;IER by setting or resetting &lt;strong&gt;LCR_BAUD_LATCH&lt;&#x2F;strong&gt; (DLAB) bit in &lt;strong&gt;Line Control Register&lt;&#x2F;strong&gt; (LCR) register.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;FIFO Control Register&lt;&#x2F;strong&gt; (FCR) is used to enable FIFOs and to reset RX and TX FIFOs.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Line Control Register&lt;&#x2F;strong&gt; (LCR) is used for setting word length, parity, stop bits and enabling programmable baud rate.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Line Status Register&lt;&#x2F;strong&gt; (LSR) is used for polling RX&#x2F;TX statuses to read&#x2F;write RHR&#x2F;THR registers.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;UART Registers (Courtesy: &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.ti.com&#x2F;product&#x2F;TL16C550C?qgpn=tl16c550c&quot;&gt;TI tl16c550c Datasheet&lt;&#x2F;a&gt;)&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;TI-UART-Registers-Summary.png&quot; alt=&quot;TI-UART-Registers-Summary.png&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Now that we have defined all the required Registers and its offsets, we could now &lt;strong&gt;initialize the UART&lt;&#x2F;strong&gt; in the following way for &lt;strong&gt;Polled mode of operation&lt;&#x2F;strong&gt; instead of &lt;strong&gt;Interrupt mode of operation&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;uart.rs&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rs&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rs &quot;&gt;&lt;code class=&quot;language-rs&quot; data-lang=&quot;rs&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;uartinit&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    WriteReg(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;IER&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0x00&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    WriteReg(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;LCR&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;LCR_BAUD_LATCH&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    WriteReg(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;DLAB_LSB&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0x03&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    WriteReg(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;DLAB_MSB&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0x00&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    WriteReg(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;LCR&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;LCR_EIGHT_BITS&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    WriteReg(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;FCR&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;FCR_FIFO_ENABLE &lt;&#x2F;span&gt;&lt;span&gt;| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;FCR_FIFO_CLEAR&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;UART initialization is done as below:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;First we disable interrupts as we are not using UART in &lt;strong&gt;Interrupt operation mode&lt;&#x2F;strong&gt;. Note that the C reference re-enables TX&#x2F;RX interrupts at the end of &lt;code&gt;uartinit&lt;&#x2F;code&gt;; we leave them disabled because we are purely polling, which keeps this driver simpler.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Then we set DLAB bit so that offset 0 and 1 will refer to DLAB_LSB and DLAB_MSB respectively.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;We use &lt;code&gt;0x03&lt;&#x2F;code&gt; as our divisor to get to our desired baud rate of &lt;strong&gt;38400&lt;&#x2F;strong&gt; using the following divisor formula:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;divisor = XIN frequency input ÷ (desired baud rate x 16), where XIN frequency input is 1.8432-MHz Crystal.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;This baud setup has no observable effect on QEMU’s console output (QEMU still consumes the divisor, but synchronous TX doesn’t use it and the host-tty setting is a no-op for our &lt;code&gt;-nographic&lt;&#x2F;code&gt; backend). We program it anyway to stay faithful to real hardware, where it’s what sets the line speed.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;We are using &lt;code&gt;8N1&lt;&#x2F;code&gt;, i.e, 8 data bits (&lt;code&gt;LCR_EIGHT_BITS&lt;&#x2F;code&gt; sets the low two bits of LCR), parity disabled, 1 stop bit. As we are only touching the low 2 bits of LCR register (number of data bits), all other bits will be zero, hence we get no parity, 1 stop bit and DLAB reset back to 0.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Then, we reset the FIFOs and enable them.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Now that we have initialized UART, we can write a simple printf function which sends characters to THR register by polling LSR_TX_IDLE bit until it is set. This bit will say if we can send next character over a UART THR register or not.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;uart.rs&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rs&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rs &quot;&gt;&lt;code class=&quot;language-rs&quot; data-lang=&quot;rs&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;uartputc_sync&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;c&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;while &lt;&#x2F;span&gt;&lt;span&gt;(ReadReg(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;LSR&lt;&#x2F;span&gt;&lt;span&gt;) &amp;amp; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;LSR_TX_IDLE&lt;&#x2F;span&gt;&lt;span&gt;) == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span&gt;{}
&lt;&#x2F;span&gt;&lt;span&gt;    WriteReg(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;THR&lt;&#x2F;span&gt;&lt;span&gt;, c);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;uartputc_sync&lt;&#x2F;strong&gt; is the most important base that we use to add &lt;strong&gt;PRINT&lt;&#x2F;strong&gt; functionality in the kernel.&lt;&#x2F;p&gt;
&lt;p&gt;In C reference code, formatting of values (integers, hex, strings) is done by hand-rolled functions, but in Rust we will make use of &lt;strong&gt;Traits&lt;&#x2F;strong&gt; to get all of that for free from the &lt;code&gt;core::fmt&lt;&#x2F;code&gt; machinery.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;print.rs&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rs&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rs &quot;&gt;&lt;code class=&quot;language-rs&quot; data-lang=&quot;rs&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use crate&lt;&#x2F;span&gt;&lt;span&gt;::uart::uartputc_sync;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;core::fmt::{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, Write};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;UartWriter;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span&gt;Write &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;UartWriter {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;write_str&lt;&#x2F;span&gt;&lt;span&gt;(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; fmt::Result {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;&amp;amp;c in s.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_bytes&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;uartputc_sync&lt;&#x2F;span&gt;&lt;span&gt;(c);
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;        Ok(())
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;_print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;args&lt;&#x2F;span&gt;&lt;span&gt;: fmt::Arguments) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;_ = UartWriter.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;write_fmt&lt;&#x2F;span&gt;&lt;span&gt;(args);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;macro_export&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;macro_rules! &lt;&#x2F;span&gt;&lt;span&gt;print {
&lt;&#x2F;span&gt;&lt;span&gt;    ($(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$arg&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;tt&lt;&#x2F;span&gt;&lt;span&gt;)*) =&amp;gt; {{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$crate&lt;&#x2F;span&gt;&lt;span&gt;::print::_print(format_args!($(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$arg&lt;&#x2F;span&gt;&lt;span&gt;)*));
&lt;&#x2F;span&gt;&lt;span&gt;    }};
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;macro_export&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;macro_rules! &lt;&#x2F;span&gt;&lt;span&gt;println {
&lt;&#x2F;span&gt;&lt;span&gt;    () =&amp;gt; {{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$crate&lt;&#x2F;span&gt;&lt;span&gt;::print::_print(format_args!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;)); }};
&lt;&#x2F;span&gt;&lt;span&gt;    ($(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$arg&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;tt&lt;&#x2F;span&gt;&lt;span&gt;)*) =&amp;gt; {{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$crate&lt;&#x2F;span&gt;&lt;span&gt;::print::_print(format_args!($(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$arg&lt;&#x2F;span&gt;&lt;span&gt;)*));
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;$crate&lt;&#x2F;span&gt;&lt;span&gt;::print::_print(format_args!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;));
&lt;&#x2F;span&gt;&lt;span&gt;    }};
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Above is the full implementation in Rust for using &lt;code&gt;print!&lt;&#x2F;code&gt; and &lt;code&gt;println!&lt;&#x2F;code&gt; macros that we are familiar with in &lt;strong&gt;std&lt;&#x2F;strong&gt; Rust. Now even in &lt;strong&gt;no_std&lt;&#x2F;strong&gt; kernel, we can use the same thing. The way we achieve this is by creating a zero-sized struct called &lt;strong&gt;UartWriter&lt;&#x2F;strong&gt; and implement &lt;strong&gt;Write&lt;&#x2F;strong&gt; Trait for this struct wherein we make use of our base function &lt;strong&gt;uartputc_sync&lt;&#x2F;strong&gt; to send characters over UART. For printing we will make use of &lt;strong&gt;write_fmt&lt;&#x2F;strong&gt; function which will be implemented automatically for us because we implemented &lt;strong&gt;Write&lt;&#x2F;strong&gt; Trait.&lt;&#x2F;p&gt;
&lt;p&gt;Now, In our &lt;strong&gt;main&lt;&#x2F;strong&gt; function, we will make use of this macros:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;main.rs&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rs&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rs &quot;&gt;&lt;code class=&quot;language-rs&quot; data-lang=&quot;rs&quot;&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;unsafe&lt;&#x2F;span&gt;&lt;span&gt;(no_mangle)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub extern &lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;C&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; ! {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;r_tp&lt;&#x2F;span&gt;&lt;span&gt;() == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;uartinit&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;xv6 kernel is booting&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Scheduler is not implemented yet !!&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;STARTED&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;store&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;, Ordering::Release);
&lt;&#x2F;span&gt;&lt;span&gt;    } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;while &lt;&#x2F;span&gt;&lt;span&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;STARTED&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;load&lt;&#x2F;span&gt;&lt;span&gt;(Ordering::Acquire) {}
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;loop &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ core::arch::asm!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;wfi&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;) }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;When we run the QEMU, it should print our 2 println lines.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;running-on-qemu&quot;&gt;Running on QEMU&lt;&#x2F;h2&gt;
&lt;p&gt;Similar to our previous post, we can verify our print functionality as follows:&lt;&#x2F;p&gt;
&lt;p&gt;Follow the below steps:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Checkout my repo at specified commit hash&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;❯&lt;&#x2F;span&gt;&lt;span&gt; git clone https:&#x2F;&#x2F;github.com&#x2F;Karthik-d-k&#x2F;xv6rs.git
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;❯&lt;&#x2F;span&gt;&lt;span&gt; cd xv6rs&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;❯&lt;&#x2F;span&gt;&lt;span&gt; git checkout 1dc5ebbd01ef42c9261b67d6146e1c61d528a881
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Run QEMU&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;❯&lt;&#x2F;span&gt;&lt;span&gt; just qemu
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;cd&lt;&#x2F;span&gt;&lt;span&gt; kernel &amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cargo&lt;&#x2F;span&gt;&lt;span&gt; build&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; --release
&lt;&#x2F;span&gt;&lt;span&gt;   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Compiling&lt;&#x2F;span&gt;&lt;span&gt; kernel v0.1.0 (&#x2F;home&#x2F;adt8kor&#x2F;lws&#x2F;os&#x2F;xv6&#x2F;xv6rs&#x2F;kernel)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Finished &lt;&#x2F;span&gt;&lt;span&gt;`&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;release&lt;&#x2F;span&gt;&lt;span&gt;` profile &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;optimized + debuginfo&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span&gt; target(s) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;in&lt;&#x2F;span&gt;&lt;span&gt; 0.31s
&lt;&#x2F;span&gt;&lt;span&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;HOME&#x2F;tools&#x2F;xpack-riscv-none-elf-gcc-15.2.0-1&#x2F;bin&#x2F;riscv-none-elf-objdump -d&lt;&#x2F;span&gt;&lt;span&gt; target&#x2F;riscv64gc-unknown-none-elf&#x2F;release&#x2F;kernel &amp;gt; kernel&#x2F;kernel.asm
&lt;&#x2F;span&gt;&lt;span&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;HOME&#x2F;tools&#x2F;xpack-riscv-none-elf-gcc-15.2.0-1&#x2F;bin&#x2F;riscv-none-elf-objdump -t&lt;&#x2F;span&gt;&lt;span&gt; target&#x2F;riscv64gc-unknown-none-elf&#x2F;release&#x2F;kernel | &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;sed &lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;1,&#x2F;SYMBOL TABLE&#x2F;d; s&#x2F; .* &#x2F; &#x2F;; &#x2F;^$&#x2F;d&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39; &amp;gt; kernel&#x2F;kernel.sym
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;***&lt;&#x2F;span&gt;&lt;span&gt; Exit QEMU with Ctrl-A X ***
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;qemu-system-riscv64 -machine&lt;&#x2F;span&gt;&lt;span&gt; virt&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; -bios&lt;&#x2F;span&gt;&lt;span&gt; none&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; -m&lt;&#x2F;span&gt;&lt;span&gt; 128M&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; -nographic -smp&lt;&#x2F;span&gt;&lt;span&gt; 3&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; -kernel&lt;&#x2F;span&gt;&lt;span&gt; target&#x2F;riscv64gc-unknown-none-elf&#x2F;release&#x2F;kernel
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;xv6&lt;&#x2F;span&gt;&lt;span&gt; kernel is booting
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Scheduler&lt;&#x2F;span&gt;&lt;span&gt; is not implemented yet !!
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;As you can see, QEMU successfully writes out characters to the UART THR register and we can see the same in the terminal.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h3 id=&quot;mangled-uart-output&quot;&gt;Mangled UART output&lt;&#x2F;h3&gt;
&lt;p&gt;Our print functionality as of now only works if there’s only one writer at a time. I will show exactly how the output will be mix-matched if we were to use print macros from all the cores.&lt;&#x2F;p&gt;
&lt;p&gt;Note that this is a logical race on a shared &lt;strong&gt;hardware&lt;&#x2F;strong&gt; resource (both cores hammering the THR register), not a Rust data race &#x2F; undefined behaviour. This is exactly what a lock will serialize later.&lt;&#x2F;p&gt;
&lt;p&gt;We shall change the main to call println! macro regardless of which core we are in, i.e, both core 1 and core 2 can write the characters at the same time.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rs&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-rs &quot;&gt;&lt;code class=&quot;language-rs&quot; data-lang=&quot;rs&quot;&gt;&lt;span&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;unsafe&lt;&#x2F;span&gt;&lt;span&gt;(no_mangle)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub extern &lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;C&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() -&amp;gt; ! {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; core_no = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;r_tp&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; core_no == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;uartinit&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;xv6 kernel is booting on CORE &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, core_no);
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;Scheduler is not implemented yet !!&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;);
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;STARTED&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;store&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;, Ordering::Release);
&lt;&#x2F;span&gt;&lt;span&gt;    } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;while &lt;&#x2F;span&gt;&lt;span&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;STARTED&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;load&lt;&#x2F;span&gt;&lt;span&gt;(Ordering::Acquire) {}
&lt;&#x2F;span&gt;&lt;span&gt;        println!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;CORE &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;, core_no);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;loop &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ core::arch::asm!(&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;wfi&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;) }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#2b303b;color:#c0c5ce;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;❯&lt;&#x2F;span&gt;&lt;span&gt; just qemu
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;cd&lt;&#x2F;span&gt;&lt;span&gt; kernel &amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;cargo&lt;&#x2F;span&gt;&lt;span&gt; build&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; --release
&lt;&#x2F;span&gt;&lt;span&gt;   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Compiling&lt;&#x2F;span&gt;&lt;span&gt; kernel v0.1.0 (&#x2F;home&#x2F;adt8kor&#x2F;lws&#x2F;os&#x2F;xv6&#x2F;xv6rs&#x2F;kernel)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Finished &lt;&#x2F;span&gt;&lt;span&gt;`&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;release&lt;&#x2F;span&gt;&lt;span&gt;` profile &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;optimized + debuginfo&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span&gt; target(s) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;in&lt;&#x2F;span&gt;&lt;span&gt; 0.31s
&lt;&#x2F;span&gt;&lt;span&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;HOME&#x2F;tools&#x2F;xpack-riscv-none-elf-gcc-15.2.0-1&#x2F;bin&#x2F;riscv-none-elf-objdump -d&lt;&#x2F;span&gt;&lt;span&gt; target&#x2F;riscv64gc-unknown-none-elf&#x2F;release&#x2F;kernel &amp;gt; kernel&#x2F;kernel.asm
&lt;&#x2F;span&gt;&lt;span&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;HOME&#x2F;tools&#x2F;xpack-riscv-none-elf-gcc-15.2.0-1&#x2F;bin&#x2F;riscv-none-elf-objdump -t&lt;&#x2F;span&gt;&lt;span&gt; target&#x2F;riscv64gc-unknown-none-elf&#x2F;release&#x2F;kernel | &lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;sed &lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;1,&#x2F;SYMBOL TABLE&#x2F;d; s&#x2F; .* &#x2F; &#x2F;; &#x2F;^$&#x2F;d&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39; &amp;gt; kernel&#x2F;kernel.sym
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;***&lt;&#x2F;span&gt;&lt;span&gt; Exit QEMU with Ctrl-A X ***
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;qemu-system-riscv64 -machine&lt;&#x2F;span&gt;&lt;span&gt; virt&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; -bios&lt;&#x2F;span&gt;&lt;span&gt; none&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; -m&lt;&#x2F;span&gt;&lt;span&gt; 128M&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; -nographic -smp&lt;&#x2F;span&gt;&lt;span&gt; 3&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt; -kernel&lt;&#x2F;span&gt;&lt;span&gt; target&#x2F;riscv64gc-unknown-none-elf&#x2F;release&#x2F;kernel
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;xv6&lt;&#x2F;span&gt;&lt;span&gt; kernel is booting on CORE 0
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;Scheduler&lt;&#x2F;span&gt;&lt;span&gt; is not implemented yet !!
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;CORE&lt;&#x2F;span&gt;&lt;span&gt; CORE 21
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Last line will be different&#x2F;mangled every time you re-run QEMU.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;That is it for this post, I will come back with new posts when I get time to port new functionality&#x2F;feature to my kernel.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;references&quot;&gt;References&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;http:&#x2F;&#x2F;byterunner.com&#x2F;16550.html&quot;&gt;ByteRunner: 16550&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;embedded.fm&#x2F;blog&#x2F;2017&#x2F;2&#x2F;23&#x2F;explaining-the-c-keyword-volatile&quot;&gt;embedded.fm: c-keyword-volatile&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.ti.com&#x2F;product&#x2F;TL16C550C?qgpn=tl16c550c&quot;&gt;TI tl16c550c Datasheet&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.riscv.org&#x2F;reference&#x2F;isa&#x2F;unpriv&#x2F;unpriv-index.html&quot;&gt;RISC-V Unprivileged Spec&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.riscv.org&#x2F;reference&#x2F;isa&#x2F;priv&#x2F;priv-index.html&quot;&gt;RISC-V Privileged Spec&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mit-pdos&#x2F;xv6-riscv-book&quot;&gt;xv6 RISC-V Book&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mit-pdos&#x2F;xv6-riscv&quot;&gt;xv6 RISC-V Source code&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Karthik-d-k&#x2F;xv6rs&quot;&gt;My xv6rs repo&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
</feed>
