►
Description
Gabriel Ferrer reports on experiences teaching the construction of a bare-metal OS in Rust.The course is facilitated by Ferrer’s Pluggable Interrupt OS crate, which provides provides an easy API for building a co-operative interrupt-driven multitasking OS.
The Pluggable Interrupt OS crate source is available through crates.io at https://crates.io/crates/pluggable_interrupt_os.
A
Real
glad
to
be
here
everybody
and
have
a
chance
to
share
this
work.
I've
been
doing
so.
I've
created
this
crate.
I
call
the
plugable
interrupt
operating
system.
Here
are
the
goals
I
had
in
creating
this
crate.
I've
been
teaching
operating
systems
and
rust
for
four
semesters.
Now
the
most
recent
time
I
ran
it.
I
really
wanted
to
get
students
writing
bare
metal
rust,
and
this
is
how
I
went
about
it.
A
So
my
goals
were
to
enable
students
to
write
100
pure
rust,
bare
metal
code,
there's
no
rust
experience
prior
to
the
os
course
now
earlier
in
the
course
before
we
use
this
utility,
I
have
students
implement
a
bunch
of
unix
utilities
in
order
to
start
learning
rust,
so
ls,
rm,
cp
and
so
forth.
Then
I
have
them
write
a
unix
shell
and
a
web
server.
The
web
server
the
main
goal
there
is
to
really
get
them
understanding,
concurrency
as
well
as
possible.
A
Then
what
I
wanted
to
do
was
for
the
bare
metal
part
encapsulate
code
from
the
blog
writing
an
os
and
rust,
which
is
an
absolutely
phenomenal
resource.
I
had
a
goal
of
no
unsafe
blocks
in
my
student
code
and
I
wanted
straightforward
abstractions
for
setup
for
the
vga
buffer
for
interrupts
and
background
code.
A
A
So,
like
I
mentioned,
I've
taught
os
using
rust
four
times
so
far.
I
developed
this
crate
in
the
most
recent
incarnation
and
I'm
gonna
teach
it
again
in
spring
of
2022
super
excited
about
it.
So
key
background
ideas.
So
what
I
mean
by
bare
metal
programming,
no
running
code
beyond
what
the
student
writes?
A
No
os
services
provided,
but
no
hesitation
provide
library,
calls
lots
of
libraries
and
so
forth,
but
the
code
that's
running
is
fundamentally
either
what
the
student
wrote
or
the
student
called
running
this
on
the
x86
architecture.
That's
in
part,
of
course,
because
writing
an
os
and
rust
is
targeted
to
that.
It's
also
easily
emulated
using
kimu
for
output.
A
We
use
the
vga
buffer,
which,
on
the
x86
is
a
memory,
mapped
in
a
character-based
way,
which
is
really
handy
because
the
fonts
are
just
available
straight
away
in
hardware,
and
it
really
saves
a
lot
of
of
effort.
Then
finally
interrupts
so
interrupts
are
code
blocks
triggered
by
specific
hardware
events.
The
two
types
of
interrupts
that
I'm
focusing
on
in
this
work
are
timer
interrupts
and
keyboard
interrupts.
A
So
my
views
on
unsafe
relative
to
this
work
unsafe
is
essential
for
interacting
with
hardware.
If
you're
going
to
be
invoking
a
low-level
machine
instructions
and
doing
direct
memory
accesses
you're
using
unsafe,
there's
no
getting
around
it.
That
said,
the
way
that
unsafe
is
talked
about
in
the
writing
and
os
and
rust
blog
really
allows
its
uses
to
effectively
be
scripted.
So
to
speak.
That
is,
it
always
looks
the
same
every
time,
so
it's
code
that
readily
lends
itself
to
abstraction.
A
Now.
One
of
my
concerns
here
is,
after
one
semester
of
learning
rust.
I
don't
necessarily
think
students
should
think
they're
ready
for
unsafe.
That
is,
I
really
want
them
immersed
in
rust
for
a
while
understanding.
What
safe
mode
gives
you
and
relying
learning
to
rely
on
those
guarantees
and
not
be
so
tempted
to
just
start
jumping
into
the
back
doors,
and
so
that,
philosophically,
is
part
of
what
lay
behind
that
design
decision.
A
It
is
important,
though,
that
students
are
aware
of
the
issues
and
the
unsafe
code.
That's
within
the
crate
is
discussed
at
length
during
lecture,
and
so
three
key
examples
from
lecture
are
on
a
keyboard
interrupt
whenever
you
hit
a
key
that
causes
a
key
code
to
be
stored
at
a
specific
address
in
ram.
So
I
show
students
how
to
write
the
unsafe
code
that
just
reads
that
straight
out
of
ram
initializing
the
interrupt
so
telling
the
interrupt
hardware.
A
These
are
the
functions
to
execute
when
the
interrupts
happen,
of
course
requires
an
unsafe
block
and
then,
when
an
interrupt
ends,
you
have
to
tell
the
interrupt
controller
that
you're
done,
and
that
also
needs
an
unsafe
block.
None
of
those
are
a
lot
of
code
in
an
unsafe
block
and
it
gives
students.
A
sense
of
this
is
where
unsafe
is
really
necessary
for
interacting
with
the
hardware.
A
So
I'm
going
to
begin
by
showing
what
I'm
going
to
call
a
hello
world
example
of
the
crate
very
simple
little
program.
It's
got
an
interrupt
handler
for
clock,
ticks
that
just
prints
a
period
on
each
tick.
It
has
an
interrupt
handler
for
keyboard
events,
it
just
prints
the
typed
character
and
it
has
a
main
that
defines
these
and
then
launches
the
handler
code.
So
this
is
literally
the
entire
main
for
a
minimal
use
of
the
crate.
A
So
a
couple
of
compiler
directives,
a
couple
of
imports
and
then
from
here
it
defined
a
function
to
this
is
what
happens
on
a
tick.
You
print
a
dot,
defined
a
function
for
dealing
with
a
key.
That's
using
this
pc
keyboard
library
that
has
the
decoded
keys,
which
is
pretty
nice
because
it's
got
a
nice
enum
for
encoding
them
and
then
we
just
go
ahead
and
print
those
out
as
they
arrive
and
then
here's
the
setup.
A
Basically,
so
you
define
a
start
method
that
of
course,
does
not
terminate
whoops
and
I've
created
a
data
structure
called
a
handler
table.
You
set
up
with
its
constructor
and
using
the
builder
pattern
you
say:
dot
keyboard,
here's
my
keyboard,
handler
dot,
timer,
here's
my
timer
handler
and
then
dot
start.
Let
it
run
and
let
it
do
its
thing
and
that's
a
minimal
program
right
there.
A
So
one
screenful,
we
actually
have
a
running
kernel
now,
obviously,
it's
not
an
enormously
functional
kernel,
but
it
is
legitimately
a
kernel
code
that
is
either
student
authored
or
called
by
a
student
from
a
library
talk
a
little
bit
about
the
handler
table
data
type
that
I
illustrated
on
the
last
page.
So
it's
got
four
data
fields:
an
optional
timer
function,
an
optional
keyboard
handler
a
startup
function
which
is
optional
and
then
a
cpu
loop.
A
A
So,
behind
the
scenes
to
set
up
the
interrupts,
we
create
a
global
variable
of
the
handler
table
type
using
lazy
static
right.
There
are
some
interrupt
handlers
that
relay
interrupts
to
the
appropriate
data
fields.
Of
that
global
object.
All
the
ins
unsafe
code
again
is
inside
those
provided
handlers.
A
The
bulk
of
the
code
is
from
philip
operman's
blog
the
bridge
code,
the
handler
table.
I
wrote
it
did
a
lot
of
packaging,
but
in
many
ways
the
bulk
of
the
crate
is
is
from
his
blog
and
he
was
pretty.
I
mean
he
gave
it
under
a
pretty
unrestricted
license,
but
he's
still
pretty
generously
blessed
to
the
project.
When
I
contacted
him
about
it,
the
vga
buffer
code
is
almost
entirely
taken
from
operands
code,
especially
he
wrote
very
nice
print
and
println
macros.
A
I
did
add
a
plot
function,
so
you
could
directly
update
columns
and
rows,
though
these
memory
accesses
are
concealed
behind
buffer
and
writer
objects
which
conceal
the
unsafe
blocks
that
are
wrapped
around
the
memory,
mapped
output
for
the
vga
buffer,
so
big
assignment
at
the
end
of
the
semester
is
students
write
a
cooperative,
multitasking
kernel.
This
is
a
screenshot
of
what
it
looks
like
once
it's
running
so
in
the
vga
buffer.
A
A
You
can
kind
of
see
an
example
of
it
down
here
or
a
program
to
compute
pi,
and
you
give
it
a
tolerance
and
then
it'll
run
a
certain
number
of
ticks
in
the
background.
A
little
side
here
tells
you
how
many
ticks
each
of
these
processes
have
run,
so
they
actually
get
to
write
like
a
nice
little
multi-programming
operating
system
with
two
built-in
programs.
A
So,
like
I
mentioned
in
the
last
slide
up
to
four
processes,
we
compute
pi
view
of
power
series.
Those
are
the
process,
actions,
keyboard
input,
send
output
to
the
terminal
and
perform
one
step
of
an
algorithm.
A
So
what
handler
table
does
for
this
one
startup?
It
clears
the
screen.
The
timer
updates,
the
system
clock
count.
The
keyboard
saves
the
most
recent
key
press,
the
cpu
loop
relays,
the
most
recent
key
press
to
the
kernel.
So
it
looks
in
an
atomic
cell
refreshes
the
screen
when
the
system
clock,
updates
and
advances
the
currently
running
process
by
one
step.
So
here
is
the
kind
of
the
main
code
for
that.
A
A
Every
time
we
have
a
key
handler
that
updates
the
last
key
atomic
cell
with
the
most
recently
received
key,
then
within
the
cpu
loop
at
the
beginning
of
the
loop,
it
creates
a
kernel
object
and
sets
up
a
local
variable
also
for
the
last
tick.
Then
it
just
goes
into
an
infinite
loop
where
each
time
it
finds
out
is
there
a
key
to
load
and
if
so,
it
stores
it
a
none.
Because
we've
now
read
the
key
and
then
tells
the
kernel
about
it.
Then
it
finds
out.
A
What's
the
current
tick,
if
it's
advanced
since
last
time,
it
does
a
redraw
of
the
screen
and
then
finally,
it
tells
the
kernel
every
time
through
the
loop,
regardless
of
what
happens
with
the
interrupts
to
run
one
instruction.
This
is
the
basic
structure
of
the
program.
The
students
are
asked
to
write
so
kind
of,
as
I
mentioned
earlier,
user
selects
the
one
with
the
function
keys
and
the
currently
selected
windows,
either
blocked
on
input
or
it
executes.
A
One
step
of
the
algorithm
did
a
couple
other
little
assignments
for
this
be
to
kind
of
set
them
up.
For
this
I
had
them
implement
a
little
vga
video
game,
so
in
other
words,
they
had
to
write
a
program
that
had
animation
controlled
by
a
timer
interrupt
and
controls
with
from
a
keyboard
interrupt,
and
I
gave
them
an
example
of
my
own
creation,
which
I
I
call
ghost
hunter
I'll,
leave
it
to
your
imagination.
What
exactly
inspired
that
and
then
the
next
assignment
is
they
actually
create?
A
What
I
call
a
video
game
kernel,
it's
kind
of
like
a
video
game
console
where
you've
got
a
menu
of
games
which
are
the
games.
They
wrote
actually
and
you
can
choose
a
game
to
run
pause.
It
have
multiple
ones,
paused,
kill
them
and
so
forth.
So
otherwise
they
learn
about
process
management
from
writing
that
video
game
kernel.
A
A
The
code,
I
wrote,
enabled
preemptive
cooperative
multitasking
learning
how
to
let
it
do
preemptive.
I
think
would
be
interesting,
develop
some
more
model
assignments
and
maybe
handle
some
additional
interrupts.
I
am
actively
interested
in
collaborating
if
anybody's
got
ideas
or
concepts
for
expanding
on
this.
I've
got
a
list
of
urls
here
of
some
of
the
resources
I
created.
I
put
a
couple
of
them
already
in
the
chat
for
your
reference
and
I'll
share.
All
of
these
in
the
in
the
zulip
chat
as
well.
So
that's
my
presentation.
A
I'm
gonna
start
looking
at
the
chat
to
see
what
questions
might
have
arisen
during
its
fourth.
Okay,
let's
see
sorry,
I'm
just
scrolling
through
it.
A
Okay
with
starting
with
command
line,
unix
utilities
inspired
by
the
book
on
this
topic-
not
really
I
I
was
inspired
by
that
just
because
I
thought
they
would
be
easy
to
code
and
be
a
nice
on-ramp
into
rust.
A
It
also
kind
of
dovetailed
the
overall
philosophy
of
my
class,
which
was
start
with
the
os
at
the
level
students
have
been
interacting
with
it
and
then
kind
of
gradually
dive
downward.
So
it
was
pretty
useful
in
that
way.
This
be
hard
to
adapt
to
an
alternate
isa,
for
example
an
arm
board.
That's
a
really
great
question
part
the
I'm
relying
a
lot
on
some
of
the
fairly
high
level
hardware
support
that
you
get
on
the
x86
most
especially
the
vga
buffer.
A
A
A
And
click
there,
if
you
go
into
the
repository
and
the
source
code
whoops,
it's
not
there,
it
is
in
vga
buffer
dot,
rs,
specifically
so
yeah
there's
a
lot
to
it.
It
pretty
follows
pretty
closely
from
the
phil
oppermann
blog,
but
that's
where
you
would
find
it
in
my
code,
so
bart
mentions
an
alternative
architecture
would
replace
cpu
loop
with
a
main
that
was
required
to
call
the
kernel
housekeeping
inside
the
loop.
What
are
the
trade-offs
here?
So
that's
an
interesting
question.
I've
been
pondering
this
a
little
bit.
A
One
thing
I
like
about
having
the
students
write
explicit
interrupt
handlers.
Is
it
forces
them
to
think
clearly
about
the
concurrency
issues
that
are
involved?
I've
imagined
a
variation
on
this
in
which
students
would
just
provide
a
kernel
data
structure
and
it
would
kind
of
relay
things
to
them
automatically,
but
it
would
detract
from
what
I
want
to
do
in
that
regard.
A
Does
the
os
do
virtual
memory
management?
Not
really
I
mean
x86
requires
you
to
do
it
just
as
a
matter
of
course,
but
what
I
did
with
it
was
really
pretty
trivial.
There's
been
some
interesting
work
done
in
gosh.
I
forget
the
name
of
the
colonel,
but
the
author
is
named
kevin
boos.
He
was
a
phd
student
at
rice
university,
who
constructed
a
rust
based
operating
system
with
the
underlying
principle
that
you
don't
necessarily
need
to
use
hardware
mechanisms
for
virtual
memory.
A
Given
that
you're
doing
everything
in
rust,
you
can
let
the
language
mechanisms
ensure
process
isolation,
so
I
haven't
actually
gotten
to
really
thinking
about
virtual
memory
management.
Yet
what
are
the
biggest
learning
challenges
induced
by
using
no
standard
great
question?
I
tried
to
give
students
an
awful
lot
of
hand-holding
in
this
regard,
so,
for
my
own
sake,
I
would
say
learning
which
crate,
which
libraries
you
had
to
import,
I
think
from
core
rather
than
std,
was
kind
of
annoying
and
then
just
figuring
out.
Okay,
what
are
all
the
pieces?
A
What's
all
the
stuff,
I
need
to
lay
down
like
println
in
order
to
to
get
anywhere
really
and
how
far
do
students
come
in
this
course
compared
to
similar
courses
in
c
man?
That's
a
great
question.
To
be
blunt,
I
only
really
was
ready
to
teach
this
class
when
I
was
able
to
teach
it
and
rest
because
the
thought
of
teaching
it
in
c
was
kind
of
a
nightmare
based
on
my
own
memories
as
an
undergrad
taking
it
and
see
you
know
just
the
endless
memory,
errors
and
so
forth.
A
So
bottom
line
is,
I
think
we
got
just
about
as
far
as
if
I
were
teaching
it
in
c,
because
things
like
concurrency
errors,
get
pointed
out
to
them
by
the
compiler
and
aren't
the
subject
of
three-hour
sessions
and
office
hours.
So
that's
that's
something.
I've
really
really
appreciated
about
rust.
Yes,
theseus
os
was
the
one
thanks
arthur
that
that
was
the
one
so
totally
check
that
out.
Well,
I
think
that's
probably
time
on
my
session,
so
thanks
everybody
for
all
the
great
questions
and
interactions
I'm
active
on
the
zulip.