<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>

<channel>
	<title>HelenOS Blog</title>
	<atom:link href="http://helenos-blog.pavel-rimsky.cz/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://helenos-blog.pavel-rimsky.cz</link>
	<description>mainly about improvement of the ultrasparc port</description>
	<pubDate>Thu, 19 Mar 2009 23:00:19 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6</generator>
	<language>en</language>
			<item>
		<title>Tetris on Niagara</title>
		<link>http://helenos-blog.pavel-rimsky.cz/?p=51</link>
		<comments>http://helenos-blog.pavel-rimsky.cz/?p=51#comments</comments>
		<pubDate>Thu, 19 Mar 2009 22:59:30 +0000</pubDate>
		<dc:creator>pavel</dc:creator>
		
		<category><![CDATA[UltraSPARC port improvement]]></category>

		<guid isPermaLink="false">http://helenos-blog.pavel-rimsky.cz/?p=51</guid>
		<description><![CDATA[During the last three months I have been trying to port HelenOS to the sun4v UltraSPARC architecture (Niagara). The sun4v architecture is very interesting from the system programmer&#8217;s point of view, so I will definitely put a link to my master thesis here (but I have write the thesis first, of course).
For the time being, [...]]]></description>
			<content:encoded><![CDATA[<p>During the last three months I have been trying to port HelenOS to the sun4v UltraSPARC architecture (Niagara). The sun4v architecture is very interesting from the system programmer&#8217;s point of view, so I will definitely put a link to my master thesis here (but I have write the thesis first, of course).</p>
<p>For the time being, you can just enjoy the screenshots of Tetris running on a (Simics-simulated) T2000 server and on a (remotely accessed) real T1000 server.</p>
<p>The only big feature missing is a support for SMP. This is what I will play with in the following weeks, because Niagara without multiprocessing would be like&#8230; (If you have an idea of a good simile, post it as a comment).</p>
<p><span id="more-51"></span></p>
<p><div class="wp-caption aligncenter" style="width: 419px"><img title="Tetris on Simics T2000 server" src="http://img.pavel-rimsky.cz/tetris_niagara.png" alt="Tetris on Simics T2000 server" width="409" height="222" /><p class="wp-caption-text">Tetris on Simics T2000 server</p></div></p>
<p><div class="wp-caption aligncenter" style="width: 450px"><img title="Tetris on T1000" src="http://img.pavel-rimsky.cz/tetris_niagara2.png" alt="Tetris on T1000" width="440" height="283" /><p class="wp-caption-text">Tetris on T1000</p></div></p>
]]></content:encoded>
			<wfw:commentRss>http://helenos-blog.pavel-rimsky.cz/?feed=rss2&amp;p=51</wfw:commentRss>
		</item>
		<item>
		<title>Two plugins I can&#8217;t imagine Vim without</title>
		<link>http://helenos-blog.pavel-rimsky.cz/?p=35</link>
		<comments>http://helenos-blog.pavel-rimsky.cz/?p=35#comments</comments>
		<pubDate>Thu, 19 Mar 2009 21:41:20 +0000</pubDate>
		<dc:creator>pavel</dc:creator>
		
		<category><![CDATA[UltraSPARC port improvement]]></category>

		<guid isPermaLink="false">http://helenos-blog.pavel-rimsky.cz/?p=35</guid>
		<description><![CDATA[I like Vim. Especially for editing C code. I would like to introduce two extensions I especially like.
The first one is a Vim binding for Cscope. Cscope is a tool which makes an index from your source tree and uses the index to quickly tell you

where a function with a given name is defined,
where a [...]]]></description>
			<content:encoded><![CDATA[<p>I like Vim. Especially for editing <code>C</code> code. I would like to introduce two extensions I especially like.</p>
<p>The first one is a Vim binding for <em>Cscope</em>. Cscope is a tool which makes an index from your source tree and uses the index to quickly tell you</p>
<ul>
<li>where a function with a given name is defined,</li>
<li>where a function with a given name is called from,</li>
<li>where a given string occurs in your source files,</li>
<li>etc.</li>
</ul>
<p><span id="more-35"></span><br />
Cscope can be used either as a standalone command-line application, or via a binding into a text editor. Using the Vim binding for Cscope is very easy. Imagine you would like to get a list of all places from which a function is called. All you must do is to move the caret above the function name and press a certain key combination (<code>Ctrl+\ c</code>). You can use Vim command line as well (<code>:cs find c my_function</code>). Having the list, you just type the number of the occurrence you are interested in and Vim will jump to the occurrence.</p>
<p>Since this is a blog about HelenOS, I will mention how to use Cscope for HelenOS development. In our Makefile we define a target called cscope. The target creates the Cscope index. Just <code>cd</code> to the HelenOS root directory and type</p>
<blockquote><p><code>make cscope</code></p></blockquote>
<p>and an index file called <code>cscope.out</code> will be generated for you. Now when you start Vim from the HelenOS root directory, it will automatically connect to Cscope so that the above key shortcuts (or Vim commands) can be used. A tutorial on using Cscope with Vim can be found at <a href="http://cscope.sourceforge.net/cscope_vim_tutorial.html">http://cscope.sourceforge.net/cscope_vim_tutorial.html</a>.</p>
<p>The second Vim extension I appreciate is called <em>Mini Buffer Explorer</em> (<a href="http://vim.sourceforge.net/scripts/script.php?script_id=159">http://vim.sourceforge.net/scripts/script.php?script_id=159</a>). I don&#8217;t know exactly what is meant by &#8216;buffer&#8217; in Vim&#8230; So let me simply say that this extension allows you to switch between opened files using tabs. It is especially useful in combination with the Cscope binding. If you jump from a location in file <code>a.c</code> to some location in file <code>b.c</code>, the latest edit location in file <code>a.c</code> will not be lost. Instead, two &#8216;tabs&#8217; will be shown above the edit area: <code>[a.c]</code> and <code>[b.c]</code>. When you are done with investigating the contents of the <code>b.c</code> file, you will just switch back to <code>a.c</code> using the tabs.</p>
<p>With the Mini Buffer Explorer extension you can have as many concurrently opened files in one running Vim instance as you want. To open a new file, just use a standard Vim command <code>:E</code>. To close a current file, use the <code>:bd</code> command (<code>:q</code> would close Vim completely).</p>
<p>Your favorite Linux distribution will probably contain a package called &#8216;cscope&#8217;. Installing the two extensions is just a matter of copying a couple of files to the <code>~/.vim/plugin</code> directory.</p>
<p><div class="wp-caption aligncenter" style="width: 839px"><img title="Mini Buffer Explorer with two tabs representing two concurrently opened files" src="http://img.pavel-rimsky.cz/twotabs.png" alt="Mini Buffer Explorer with two tabs representing two concurrently opened files" width="829" height="588" /><p class="wp-caption-text">Mini Buffer Explorer with two tabs representing two concurrently opened files</p></div></p>
<p><div class="wp-caption aligncenter" style="width: 839px"><img title="Looking up a place where a function is defined or declared" src="http://img.pavel-rimsky.cz/select.png" alt="Looking up a place where a function is defined or declared" width="829" height="588" /><p class="wp-caption-text">Looking up a place where a function is defined or declared</p></div></p>
<p><div class="wp-caption aligncenter" style="width: 839px"><img title="Opening a file using the :E command" src="http://img.pavel-rimsky.cz/open.png" alt="Opening a file using the :E command" width="829" height="588" /><p class="wp-caption-text">Opening a file using the :E command</p></div></p>
]]></content:encoded>
			<wfw:commentRss>http://helenos-blog.pavel-rimsky.cz/?feed=rss2&amp;p=35</wfw:commentRss>
		</item>
		<item>
		<title>Debugging using stripes</title>
		<link>http://helenos-blog.pavel-rimsky.cz/?p=25</link>
		<comments>http://helenos-blog.pavel-rimsky.cz/?p=25#comments</comments>
		<pubDate>Sat, 15 Nov 2008 18:08:59 +0000</pubDate>
		<dc:creator>pavel</dc:creator>
		
		<category><![CDATA[UltraSPARC port improvement]]></category>

		<guid isPermaLink="false">http://helenos-blog.pavel-rimsky.cz/?p=25</guid>
		<description><![CDATA[After several months of playing with a simulated Serengeti machine I have started to have some fun with a real hardware containing an UltraSPARC III CPU. It is a Sun Blade 1500 workstation which I&#8217;ve been lent by Sun Microsystems globalization division.
A Spanish (or French?) keyboard is connected to it (you know, globalization division&#8230;), but [...]]]></description>
			<content:encoded><![CDATA[<p>After several months of playing with a simulated Serengeti machine I have started to have some fun with a real hardware containing an UltraSPARC III CPU. It is a Sun Blade 1500 workstation which I&#8217;ve been lent by Sun Microsystems globalization division.</p>
<p>A Spanish (or French?) keyboard is connected to it (you know, globalization division&#8230;), but this is not the most interesting challenge. The most interesting thing is a way how to debug the kernel on such a machine.</p>
<p><span id="more-25"></span> The kernel crashes before the output gets initialized, so it is not possible to use <code>printf</code> to identify the exact point of failure. With some help of the OpenBoot PROM, however, it is possible to find an area in the physical address space to which the screen is (pixel by pixel) mapped and draw something to the screen by writing to that area.</p>
<p>The code which makes it can look like this:</p>
<pre>static void sb1500stripe(int color, int position)
{
    int i;
    for (i = 0; i &lt; 0xA00; i++)
        asm volatile ("stba %0, [%1] 0x15 \n" ::
            "r" ((color)),
            "r" (0x7f708000000 + (position)*0x1400 + i));
}</pre>
<p>This will draw a thin horizontal stripe. The value 0&#215;7f708000000 is the physical address where the framebuffer starts, <code>position</code> determines a distance from the top of the screen.</p>
<p>The basic idea how to use this for debugging purposes is simple: call <code>sb1500stripe</code> from several places of a function you suspect of causing the crash, each time passing a different value of <code>position</code> to it. Then deduce the exact line in your source code which is to blame.</p>
<p>The idea is simple, yet not always working. There are basically two problems with this approach. The first one is that some functions do not cause the crash generally, but only when called with some special parameters. If such a function is called <em>n</em> times before it causes the crash, it succeeds <em>n</em> - 1 times, each time drawing all the stripes. From the programmer&#8217;s point of view all the stripes have been drawn, so it seems that the function has not caused any crash at all. The solution is straightforward: at the beginning the function must clear (blank) the area where it is about to draw the stripes.</p>
<p>The second problem is much more tricky. When I first encountered it, it seemed that <code>malloc</code> failed when calling <code>slab_alloc</code>, but the <code>slab_alloc</code> function seemed to proceed until the <code>return</code> statement. I was quite confused. What the hell can break during the return? I checked the value of the <code>CANRESTORE</code> register (maybe some strange error during register window fill?), but its value was 3. Then I was trying to find (using binary lookup) the value of the <code>%i7</code> register (which contains the return address during the function call), which was complicated by the fact that this value depends on the kernel binaries, hence changes when you modify the kernel code (which I was doing). After several hours I found out that even the <code>%i7</code> register was correct.</p>
<p>Actually, the return statement was causing no failure at all! But the debugging method was wrong. What happened was that the <code>slab_alloc</code> function called itself recursively. The nested call succeeded (painted all the stripes), but not the call which made the recursive call. Blanking the area for the stripes did not help here, as all the stripes were being painted during the recursive call (i. e. after the blanking took place).</p>
<p>The solution which I came with and which works just fine for me is that I have a static variable (<code>call_order</code>) defined in the suspect function, which is being incremented (and copied to a local variable <code>call_order_copy</code>) at the beginning of the function call. The position of the particular stripe depends not only on the place within the function from which it is being painted, but also on the value of the <code>call_order_copy</code> variable. So every call of the suspect function has its own set of stripes. From that the exact point of failure within the suspect function can be determined.</p>
]]></content:encoded>
			<wfw:commentRss>http://helenos-blog.pavel-rimsky.cz/?feed=rss2&amp;p=25</wfw:commentRss>
		</item>
		<item>
		<title>Standard output to Simics CLI window</title>
		<link>http://helenos-blog.pavel-rimsky.cz/?p=13</link>
		<comments>http://helenos-blog.pavel-rimsky.cz/?p=13#comments</comments>
		<pubDate>Fri, 19 Sep 2008 15:35:00 +0000</pubDate>
		<dc:creator>pavel</dc:creator>
		
		<category><![CDATA[UltraSPARC port improvement]]></category>

		<guid isPermaLink="false">http://helenos-blog.pavel-rimsky.cz/?p=13</guid>
		<description><![CDATA[Simics is a brilliant tool, but what it lacks is a simple way how to make an output from the simulated code. On some simulators, such as MSIM, the simulated code can print a character by writing its code to a special address of memory. It is a priceless feature - debugging output is possible [...]]]></description>
			<content:encoded><![CDATA[<p>Simics is a brilliant tool, but what it lacks is a simple way how to make an output from the simulated code. On some simulators, such as MSIM, the simulated code can print a character by writing its code to a special address of memory. It is a priceless feature - debugging output is possible without having to write a driver for a framebuffer or a serial console.</p>
<p>I&#8217;ve had some troubles making the graphical console work on the Serengeti machine. On the Simics forum (<a href="https://www.simics.net/mwf/forum_show.pl">https://www.simics.net/mwf/forum_show.pl</a>) a guy from Virtutech told me that it is theoretically possible to configure the simulated Simics machine to support a graphical console, but&#8230;</p>
<blockquote><p><em>First, why do you want the graphical console in the serengeti machine? The Serengeti architecture does not have any serial ports where mouse and keyboards can be connected, i.e. even if you get the graphics card to work, it can only be used to view output. No interactive programs can be run using it. The older SunFire architecture has better support for a graphical device with keyboard/mouse input.</em></p>
<p><em>The graphics card was never tested as output device for OBP. Instead the machine was booted as usual and then an X server was started with no mouse/keyboard configured. This required some manual setup and since this was several years ago, I don&#8217;t know if it works with more modern Solaris versions.</em></p></blockquote>
<p>As HelenOS UltraSPARC port does not support the serial console yet, I will have to write a serial console driver one day. It is, however, difficult to debug a kernel with no possibility of debugging output and I don&#8217;t have mood for writing the serial console driver now. So I feel a little bit envious of the ones who can debug their kernels in MIPS-like simulators. Wait a moment&#8230; Is it really impossible to use some simple way of output in Simics? With some sort of invention, one can achieve it!</p>
<p><span id="more-13"></span></p>
<p>Simics API (see <a href="http://www.cs.sfu.ca/~fedorova/Tech/simics-guides-3.0.26/simics-reference-manual-public-all.pdf">http://www.cs.sfu.ca/~fedorova/Tech/simics-guides-3.0.26/simics-reference-manual-public-all.pdf</a> to get its full description) can be used by Python scripts, which can be included directly in the Simics configuration file.</p>
<p>An API function called <code>SIM_realtime_event</code> exist, via which a Python routine, which will be called in a given number of milliseconds, can be registered. It is therefore possible to regularly run a background Python routine while the simulation is running.</p>
<p>Such a routine can use other Simics API functions, such as <code>SIM_read_register</code>, <code>SIM_write_register</code>, <code>SIM_read_phys_memory</code> or<code> SIM_write_phys_memory</code> to &#8220;communicate&#8221; with the simulated code. It can also use standard Python output routines to write to the Simics CLI window.</p>
<p>The final solution uses a buffer the simulated code writes to and the Python routine reads from (bytes to which the simulated code is free to write are set to zero). The address of the buffer is transmitted to the Python script by</p>
<ul>
<li>setting the <code>g3</code> register to the buffer address, and</li>
<li>writting a magic value to the <code>g2</code> register.</li>
</ul>
<p>The code on the HelenOS side looks like this:</p>
<pre>/* all buffer positions are free at the beginning */
uint16_t i;
	for (i = 0; i &lt; BUFSIZE; i++) {
buffer[i] = '\0';
}

/*
 * pass the address of the buffer to the Simics' Python script
 *   - write it to the %g3 register
 *   - write the magic value to the %g2 register
 *     (so that the script knows that the value in %g3 is valid)
 *   - loop until the value is read
 *     (the script notifies us by setting %g2 to 0)
 */
asm volatile (
	"or %0, 0, %%g3\n"

	"set 0x18273645, %%g2\n"

	"0: cmp %%g2, 0\n"
	"bnz 0b\n"
	"nop"
	:: "r" (buffer)
);</pre>
<p>And on the Python side:</p>
<pre>if ((buf == 0) and (register2Value == 0x18273645)):
	buf = SIM_read_register(SIM_current_processor(), register3Number);
	SIM_write_register(SIM_current_processor(), register2Number, 0);</pre>
<p>Once the Python script knows the location of the buffer, the simulated code can write to the buffer&#8230;</p>
<pre>/** Writes a single character to the Simics CLI.
 *
 * The character is not written immediately, but it is stored to the first free
 * position in the buffer, waiting for Simics' Python routine to pick it
 * and print it.
 */
static void simics_putchar(struct chardev * cd, char c)
{
	/* the first free position in the buffer */
	static uint16_t current = 0;

	/* '\0' terminates a contiguous block of characters to be printed! */
	if (c == '\0')
		return;

	/* wait till buffer is non-full and other processors aren't writing to it */
	while (1) {
		while (buffer[current] != 0)
			;
		if (spinlock_trylock(&amp;simics_buf_lock))
			break;
	}

	buffer[current] = c;

	current = (current + 1) % BUFSIZE;
	membar();

	spinlock_unlock(&amp;simics_buf_lock);
}</pre>
<p>&#8230; and the Python script can read from the buffer, printing the characters to the CLI window:</p>
<pre>byte = SIM_read_phys_memory(SIM_current_processor(), buf + offset, 1);
while byte != 0:
	SIM_putchar(byte);
	SIM_flush();
	SIM_write_phys_memory(SIM_current_processor(), buf + offset, 0, 1);
	offset = (offset + 1) % 512;
	byte = SIM_read_phys_memory(SIM_current_processor(), buf + offset, 1);</pre>
<p>This mechanism is easy and significantly faster than writing the output to the graphical console. Moreover, as the Simics CLI runs in the Unix terminal window, the output can be processed by standard Unix means (the <code>tee</code> command, pipes, etc.). It will be necessary to implement a serial console driver in the future, but for the time being, the mechanism described in this post is pretty sufficient.<!--more--></p>
]]></content:encoded>
			<wfw:commentRss>http://helenos-blog.pavel-rimsky.cz/?feed=rss2&amp;p=13</wfw:commentRss>
		</item>
		<item>
		<title>Bootable CD for Serengeti</title>
		<link>http://helenos-blog.pavel-rimsky.cz/?p=3</link>
		<comments>http://helenos-blog.pavel-rimsky.cz/?p=3#comments</comments>
		<pubDate>Tue, 12 Aug 2008 21:50:18 +0000</pubDate>
		<dc:creator>pavel</dc:creator>
		
		<category><![CDATA[UltraSPARC port improvement]]></category>

		<guid isPermaLink="false">http://helenos-blog.pavel-rimsky.cz/?p=3</guid>
		<description><![CDATA[Recently I have been trying to create a bootable HelenOS CD for the Serengeti machine containing the UltraSPARC III processor. I decided to use SILO as a bootloader. The Sunfire machine with the UltraSPARC II processor was able to boot from the CD without any problems. On Serengeti, however, the boot process ended with an [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I have been trying to create a bootable HelenOS CD for the Serengeti machine containing the UltraSPARC III processor. I decided to use SILO as a bootloader. The Sunfire machine with the UltraSPARC II processor was able to boot from the CD without any problems. On Serengeti, however, the boot process ended with an error. SILO even did not print its banner.</p>
<p><span id="more-3"></span><br />
<code> SmartFirmware, Copyright (C) 1996-2001. All rights reserved.<br />
Boot path: /ssm@0,0/pci@19,700000/scsi@2/disk@6,0:f Boot args:<br />
ERROR: Illegal instruction<br />
debugger entered.<br />
ok<br />
</code></p>
<p>I was trying to boot different operating systems on the Serengeti machine. With Aurora Linux, I got exactly the same error. OpenBSD and NetBSD printed their banners, but ended with an error later. OpenSolaris (marTux distribution) booted without any problems.</p>
<p>As Linux and HelenOS (both using SILO) were unable to boot due to the same error, I was suspicious about two things:</p>
<ul>
<li>the SILO bootloader, and</li>
<li>the way how the bootable CD is being made.</li>
</ul>
<p>After checking the <code>mkisofs</code> manual pages, I was almost convinced that the way how the bootable CD is being made is alright. Therefore, SILO seemed to be the most probable cause. The problem was that the SILO website had been out of order since January, it seemed that the SILO community had not paid for the <tt>sparc-boot.org</tt> domain. I found an archived version of the website at <tt>http://web.archive.org</tt>, but found no solution to my problem. I also mailed to the sparc-linux mailinglist, but (which I was really disappointed by) got no answer.</p>
<p>My colleages adviced me to explore the binary contents of the CD, find the SILO code inside it and then to find out whether the processor really executes the code or whether it executes some rubbish. I learned how to use <tt>hexdump</tt> and <tt>dd</tt> utilities (see <a href="http://helenos.pavel-rimsky.cz/doku.php?id=handy_shell_commands">http://helenos.pavel-rimsky.cz/doku.php?id=handy_shell_commands</a> for my notes) and found the location of the SILO&#8217;s isofs.b file inside the image of the CD. Finding out whether the CPU is executing the right instructions was an easy task, as I tested the CD on the Simics simulator, not on a real piece of hardware (see <a href="http://helenos.pavel-rimsky.cz/doku.php?id=handy_simics_commands">http://helenos.pavel-rimsky.cz/doku.php?id=handy_simics_commands</a> for some handy Simics commands).</p>
<p>I was a little bit confused. The 2nd to 8th instructions of the <tt>isofs.b</tt> file where illegal trap (<tt>ILLTRAP</tt>) instructions. These were the instructions that the Serengeti machine failed due to! Firstly, how come the <tt>ILLTRAP</tt> instruction is there in the <tt>isofs.b</tt> file? Secondly, how come it works without any problems on the US-II machine, even though the instructions are illegal on US-II as well?</p>
<p>I mailed to the HelenOS mailing list to discuss it with more experienced hackers. More experiments showed that the Sunfire (US-II) machine does not execute the first eight instructions of the <tt>isofs.b</tt> file, but its firmware jumps to the nineth instrution. On the other hand, the Serengeti (US-III) machine&#8217;s firmware jumps to the first instrucrion contained in the <tt>isofs.b</tt> file, thus ending with an Illegal Instruction trap. What the hell the eight instructions mean?</p>
<p>Jakub Jermář suggested (and verified) that those eight &#8220;instructions&#8221; are in fact the ELF header of the SPARC executable. While the Sunfire (US-II) machine understands this format and its firmware really loads the <tt>isofs.b</tt> file into the memory <em>without this 8-bit header</em>, the Serengeti machine loads the whole contents of the <tt>isofs.b</tt> file onto memory, jumping to the fist word of it. The first eight words are not instructions, but an ELF header, so the Illegal Instruction trap occurs.</p>
<p>The solution is pretty easy. Just remove the first eight words from the <tt>isofs.b</tt> file (to be more precise, those eight words are contained after the initial 512-byte sequence of zeros in <tt>isofs.b</tt>; the sequence of zeros is ignored by the Firmware, however).</p>
<p>I wrote a bash script which downloads SILO from WWW and patches it. You can download it from <a href="http://helenos.pavel-rimsky.cz/doku.php?id=download_and_patch_silo">http://helenos.pavel-rimsky.cz/doku.php?id=download_and_patch_silo</a>. Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://helenos-blog.pavel-rimsky.cz/?feed=rss2&amp;p=3</wfw:commentRss>
		</item>
	</channel>
</rss>
