diff --git a/src/arch/x86_64/debug.rs b/src/arch/x86_64/debug.rs
index 1c173a7dcfdabcc5159d53d1fe0013a94336bd62..aeddf40b2d8d3f3559f68dfaf036bc2879ba9b43 100644
--- a/src/arch/x86_64/debug.rs
+++ b/src/arch/x86_64/debug.rs
@@ -3,6 +3,7 @@ use core::fmt;
 use spin::Mutex;
 use spin::MutexGuard;
 
+use log::{LOG, Log};
 #[cfg(feature = "qemu_debug")]
 use syscall::io::Io;
 use syscall::io::Pio;
@@ -18,6 +19,7 @@ use super::device::serial::COM1;
 pub static QEMU: Mutex<Pio<u8>> = Mutex::new(Pio::<u8>::new(0x402));
 
 pub struct Writer<'a> {
+    log: MutexGuard<'a, Option<Log>>,
     #[cfg(feature = "graphical_debug")]
     display: MutexGuard<'a, Option<DebugDisplay>>,
     #[cfg(feature = "qemu_debug")]
@@ -29,6 +31,7 @@ pub struct Writer<'a> {
 impl<'a> Writer<'a> {
     pub fn new() -> Writer<'a> {
         Writer {
+            log: LOG.lock(),
             #[cfg(feature = "graphical_debug")]
             display: DEBUG_DISPLAY.lock(),
             #[cfg(feature = "qemu_debug")]
@@ -39,6 +42,12 @@ impl<'a> Writer<'a> {
     }
 
     pub fn write(&mut self, buf: &[u8]) {
+        {
+            if let Some(ref mut log) = *self.log {
+                log.write(buf);
+            }
+        }
+
         #[cfg(feature = "graphical_debug")]
         {
             if let Some(ref mut display) = *self.display {
diff --git a/src/arch/x86_64/start.rs b/src/arch/x86_64/start.rs
index e135116241802f6b5ce2c9610139c1b8544fab6f..d3ed63f28abefd75be30c6ce3ddfc509038212f4 100644
--- a/src/arch/x86_64/start.rs
+++ b/src/arch/x86_64/start.rs
@@ -16,6 +16,7 @@ use device;
 use gdt;
 use idt;
 use interrupt;
+use log;
 use memory;
 use paging;
 
@@ -111,6 +112,9 @@ pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! {
         // Setup kernel heap
         allocator::init(&mut active_table);
 
+        // Activate memory logging
+        log::init();
+
         // Use graphical debug
         #[cfg(feature="graphical_debug")]
         graphical_debug::init(&mut active_table);
diff --git a/src/lib.rs b/src/lib.rs
index 6161003f13a29e5a6d26296f719bd196e22974b5..e0a9969b450121078d148165c9f9833ed5adc259 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -82,6 +82,9 @@ pub mod event;
 /// External functions
 pub mod externs;
 
+/// Logging
+pub mod log;
+
 /// Memory management
 pub mod memory;
 
diff --git a/src/log.rs b/src/log.rs
new file mode 100644
index 0000000000000000000000000000000000000000..b0866cf357b464560452ebe115a7aed866d88fa1
--- /dev/null
+++ b/src/log.rs
@@ -0,0 +1,35 @@
+use alloc::collections::VecDeque;
+use spin::Mutex;
+
+pub static LOG: Mutex<Option<Log>> = Mutex::new(None);
+
+pub fn init() {
+    *LOG.lock() = Some(Log::new(1024 * 1024));
+}
+
+pub struct Log {
+    data: VecDeque<u8>,
+    size: usize,
+}
+
+impl Log {
+    pub fn new(size: usize) -> Log {
+        Log {
+            data: VecDeque::with_capacity(size),
+            size: size
+        }
+    }
+
+    pub fn read(&self) -> (&[u8], &[u8]) {
+        self.data.as_slices()
+    }
+
+    pub fn write(&mut self, buf: &[u8]) {
+        for &b in buf {
+            while self.data.len() + 1 >= self.size {
+                self.data.pop_front();
+            }
+            self.data.push_back(b);
+        }
+    }
+}
diff --git a/src/scheme/sys/log.rs b/src/scheme/sys/log.rs
new file mode 100644
index 0000000000000000000000000000000000000000..ec34da226c2a7a1d956aa9d48c05abf90921c5ed
--- /dev/null
+++ b/src/scheme/sys/log.rs
@@ -0,0 +1,17 @@
+use alloc::vec::Vec;
+
+use log::LOG;
+use syscall::error::Result;
+
+pub fn resource() -> Result<Vec<u8>> {
+    let mut vec = Vec::new();
+
+    if let Some(ref log) = *LOG.lock() {
+        let slices = log.read();
+        vec.reserve_exact(slices.0.len() + slices.1.len());
+        vec.extend_from_slice(slices.0);
+        vec.extend_from_slice(slices.1);
+    }
+
+    Ok(vec)
+}
diff --git a/src/scheme/sys/mod.rs b/src/scheme/sys/mod.rs
index 85ccab24ee093caf9fb0fd30f59439608a0e6180..71ab698c475d39f2a739f34421a45677f27bb4d7 100644
--- a/src/scheme/sys/mod.rs
+++ b/src/scheme/sys/mod.rs
@@ -14,6 +14,7 @@ mod context;
 mod cpu;
 mod exe;
 mod iostat;
+mod log;
 mod scheme;
 mod scheme_num;
 mod syscall;
@@ -43,6 +44,7 @@ impl SysScheme {
         files.insert(b"cpu", Box::new(move || cpu::resource()));
         files.insert(b"exe", Box::new(move || exe::resource()));
         files.insert(b"iostat", Box::new(move || iostat::resource()));
+        files.insert(b"log", Box::new(move || log::resource()));
         files.insert(b"scheme", Box::new(move || scheme::resource()));
         files.insert(b"scheme_num", Box::new(move || scheme_num::resource()));
         files.insert(b"syscall", Box::new(move || syscall::resource()));