diff --git a/unix/main.c b/unix/main.c
index a1c204cab08f69f15fa4849e64dd04c4741e4d58..edea7900d29d906dcc556e650173ba30de2b8dce 100644
--- a/unix/main.c
+++ b/unix/main.c
@@ -425,9 +425,6 @@ MP_NOINLINE int main_(int argc, char **argv) {
 
     mp_init();
 
-    // create keyboard interrupt object
-    MP_STATE_VM(keyboard_interrupt_obj) = mp_obj_new_exception(&mp_type_KeyboardInterrupt);
-
     char *home = getenv("HOME");
     char *path = getenv("MICROPYPATH");
     if (path == NULL) {
diff --git a/unix/mpconfigport.h b/unix/mpconfigport.h
index 7ecfc28c09c181b74230c150f9dbaaa4bd711fbc..4067e19500ff64782754d51c785a180d9c331d71 100644
--- a/unix/mpconfigport.h
+++ b/unix/mpconfigport.h
@@ -156,6 +156,7 @@
 
 #define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF   (1)
 #define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE  (256)
+#define MICROPY_KBD_EXCEPTION       (1)
 #define MICROPY_ASYNC_KBD_INTR      (1)
 
 extern const struct _mp_obj_module_t mp_module_machine;
@@ -283,7 +284,6 @@ void mp_unix_mark_exec(void);
 
 #define MICROPY_PORT_ROOT_POINTERS \
     const char *readline_hist[50]; \
-    mp_obj_t keyboard_interrupt_obj; \
     void *mmap_region_head; \
 
 // We need to provide a declaration/definition of alloca()
diff --git a/unix/mpconfigport_minimal.h b/unix/mpconfigport_minimal.h
index 788c8519d211db9b7b6f6b7f149e95950dd27ed2..b4d9f814391e0accb82c9f07401e0cc26a66464d 100644
--- a/unix/mpconfigport_minimal.h
+++ b/unix/mpconfigport_minimal.h
@@ -47,6 +47,7 @@
 #define MICROPY_ERROR_REPORTING     (MICROPY_ERROR_REPORTING_TERSE)
 #define MICROPY_WARNINGS            (0)
 #define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF   (0)
+#define MICROPY_KBD_EXCEPTION       (1)
 #define MICROPY_FLOAT_IMPL          (MICROPY_FLOAT_IMPL_NONE)
 #define MICROPY_LONGINT_IMPL        (MICROPY_LONGINT_IMPL_NONE)
 #define MICROPY_STREAMS_NON_BLOCK   (0)
@@ -99,7 +100,6 @@ extern const struct _mp_obj_module_t mp_module_os;
     { MP_OBJ_NEW_QSTR(MP_QSTR_uos), (mp_obj_t)&mp_module_os }, \
 
 #define MICROPY_PORT_ROOT_POINTERS \
-    mp_obj_t keyboard_interrupt_obj;
 
 //////////////////////////////////////////
 // Do not change anything beyond this line
diff --git a/unix/unix_mphal.c b/unix/unix_mphal.c
index 6c666623628a4e9e071514509b184aac02d3231c..800484498e671f4efea49d086a3719c0ecc331cd 100644
--- a/unix/unix_mphal.c
+++ b/unix/unix_mphal.c
@@ -40,20 +40,20 @@
 STATIC void sighandler(int signum) {
     if (signum == SIGINT) {
         #if MICROPY_ASYNC_KBD_INTR
-        mp_obj_exception_clear_traceback(MP_STATE_VM(keyboard_interrupt_obj));
+        mp_obj_exception_clear_traceback(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)));
         sigset_t mask;
         sigemptyset(&mask);
         // On entry to handler, its signal is blocked, and unblocked on
         // normal exit. As we instead perform longjmp, unblock it manually.
         sigprocmask(SIG_SETMASK, &mask, NULL);
-        nlr_raise(MP_STATE_VM(keyboard_interrupt_obj));
+        nlr_raise(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)));
         #else
-        if (MP_STATE_VM(mp_pending_exception) == MP_STATE_VM(keyboard_interrupt_obj)) {
+        if (MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))) {
             // this is the second time we are called, so die straight away
             exit(1);
         }
-        mp_obj_exception_clear_traceback(MP_STATE_VM(keyboard_interrupt_obj));
-        MP_STATE_VM(mp_pending_exception) = MP_STATE_VM(keyboard_interrupt_obj);
+        mp_obj_exception_clear_traceback(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)));
+        MP_STATE_VM(mp_pending_exception) = MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception));
         #endif
     }
 }
diff --git a/windows/mpconfigport.h b/windows/mpconfigport.h
index 844e2618f4794216f4cec34199ef0e47bcc4c675..b91662af482766e288f8edd7ba29e35c61dcfbee 100644
--- a/windows/mpconfigport.h
+++ b/windows/mpconfigport.h
@@ -104,6 +104,7 @@
 
 #define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF   (1)
 #define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE     (256)
+#define MICROPY_KBD_EXCEPTION       (1)
 
 #define MICROPY_PORT_INIT_FUNC      init()
 #define MICROPY_PORT_DEINIT_FUNC    deinit()
@@ -161,8 +162,7 @@ extern const struct _mp_obj_module_t mp_module_time;
 
 #if MICROPY_USE_READLINE == 1
 #define MICROPY_PORT_ROOT_POINTERS \
-    char *readline_hist[50]; \
-    mp_obj_t keyboard_interrupt_obj;
+    char *readline_hist[50];
 #endif
 
 #define MP_STATE_PORT               MP_STATE_VM
diff --git a/windows/windows_mphal.c b/windows/windows_mphal.c
index 3ad6939059d9f5cfc1f77ccee0ccc4224281347f..1dd3105d86fac6df8f7b8b178dfec1402b6463cc 100644
--- a/windows/windows_mphal.c
+++ b/windows/windows_mphal.c
@@ -79,12 +79,12 @@ void mp_hal_stdio_mode_orig(void) {
 // the thread created for handling it might not be running yet so we'd miss the notification.
 BOOL WINAPI console_sighandler(DWORD evt) {
     if (evt == CTRL_C_EVENT) {
-        if (MP_STATE_VM(mp_pending_exception) == MP_STATE_VM(keyboard_interrupt_obj)) {
+        if (MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))) {
             // this is the second time we are called, so die straight away
             exit(1);
         }
-        mp_obj_exception_clear_traceback(MP_STATE_VM(keyboard_interrupt_obj));
-        MP_STATE_VM(mp_pending_exception) = MP_STATE_VM(keyboard_interrupt_obj);
+        mp_obj_exception_clear_traceback(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)));
+        MP_STATE_VM(mp_pending_exception) = MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception));
         return TRUE;
     }
     return FALSE;