Skip to content

Instantly share code, notes, and snippets.

@mark-i-m
Created July 18, 2017 01:47
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mark-i-m/361cbcc39769f965b1c419091b9cbf4f to your computer and use it in GitHub Desktop.
Save mark-i-m/361cbcc39769f965b1c419091b9cbf4f to your computer and use it in GitHub Desktop.
Excerpt from x86_64 OS kernel interrupt/trap handling
#[naked]
pub unsafe extern "C" fn irq0() {
asm!{
"push %rax
movq $$0, %rax "
: /* No outputs */
: /* No inputs */
: "rax", "rsp"
: "volatile"
};
irq_common()
}
#[naked]
pub unsafe extern "C" fn irq1() {
asm!{
"push %rax
movq $$1, %rax "
: /* No outputs */
: /* No inputs */
: "rax", "rsp"
: "volatile"
};
irq_common()
}
#[naked]
pub unsafe extern "C" fn irq2() {
asm!{
"push %rax
movq $$2, %rax "
: /* No outputs */
: /* No inputs */
: "rax", "rsp"
: "volatile"
};
irq_common()
}
#[naked]
pub unsafe extern "C" fn irq3() {
asm!{
"push %rax
movq $$3, %rax "
: /* No outputs */
: /* No inputs */
: "rax", "rsp"
: "volatile"
};
irq_common()
}
#[naked]
pub unsafe extern "C" fn irq4() {
asm!{
"push %rax
movq $$4, %rax "
: /* No outputs */
: /* No inputs */
: "rax", "rsp"
: "volatile"
};
irq_common()
}
#[naked]
pub unsafe extern "C" fn irq5() {
asm!{
"push %rax
movq $$5, %rax "
: /* No outputs */
: /* No inputs */
: "rax", "rsp"
: "volatile"
};
irq_common()
}
#[naked]
pub unsafe extern "C" fn irq6() {
asm!{
"push %rax
movq $$6, %rax "
: /* No outputs */
: /* No inputs */
: "rax", "rsp"
: "volatile"
};
irq_common()
}
#[naked]
pub unsafe extern "C" fn irq7() {
asm!{
"push %rax
movq $$7, %rax "
: /* No outputs */
: /* No inputs */
: "rax", "rsp"
: "volatile"
};
irq_common()
}
#[naked]
pub unsafe extern "C" fn irq8() {
asm!{
"push %rax
movq $$8, %rax "
: /* No outputs */
: /* No inputs */
: "rax", "rsp"
: "volatile"
};
irq_common()
}
#[naked]
pub unsafe extern "C" fn irq9() {
asm!{
"push %rax
movq $$9, %rax "
: /* No outputs */
: /* No inputs */
: "rax", "rsp"
: "volatile"
};
irq_common()
}
#[naked]
pub unsafe extern "C" fn irq10() {
asm!{
"push %rax
movq $$10, %rax "
: /* No outputs */
: /* No inputs */
: "rax", "rsp"
: "volatile"
};
irq_common()
}
#[naked]
pub unsafe extern "C" fn irq11() {
asm!{
"push %rax
movq $$11, %rax "
: /* No outputs */
: /* No inputs */
: "rax", "rsp"
: "volatile"
};
irq_common()
}
#[naked]
pub unsafe extern "C" fn irq12() {
asm!{
"push %rax
movq $$12, %rax "
: /* No outputs */
: /* No inputs */
: "rax", "rsp"
: "volatile"
};
irq_common()
}
#[naked]
pub unsafe extern "C" fn irq13() {
asm!{
"push %rax
movq $$13, %rax "
: /* No outputs */
: /* No inputs */
: "rax", "rsp"
: "volatile"
};
irq_common()
}
#[naked]
pub unsafe extern "C" fn irq14() {
asm!{
"push %rax
movq $$14, %rax "
: /* No outputs */
: /* No inputs */
: "rax", "rsp"
: "volatile"
};
irq_common()
}
#[naked]
pub unsafe extern "C" fn irq15() {
asm!{
"push %rax
movq $$15, %rax "
: /* No outputs */
: /* No inputs */
: "rax", "rsp"
: "volatile"
};
irq_common()
}
#[repr(C,packed)]
pub struct IrqContext {
cr2: u64,
r15: u64,
r14: u64,
r13: u64,
r12: u64,
r11: u64,
r10: u64,
r9: u64,
r8: u64,
rbp: u64,
rdi: u64,
rsi: u64,
rdx: u64,
rcx: u64,
rbx: u64,
rax: u64,
}
#[naked]
#[inline]
unsafe fn irq_common() -> ! {
let irq: usize;
let context_ptr: *mut IrqContext;
// Save all registers
asm!{
"
push %rbx
push %rcx
push %rdx
push %rsi
push %rdi
push %rbp
push %r8
push %r9
push %r10
push %r11
push %r12
push %r13
push %r14
push %r15
mov %cr2, %rbp
push %rbp
mov %rsp, $0
mov %rax, $1
"
: "=r"(context_ptr), "=r"(irq)
: /* No inputs */
: "rbp"
: "volatile"
};
// Handle interrupt
pic_irq(irq, &mut *context_ptr);
// Pop arguments and iretq
asm!{
"
pop %rbp
mov %rbp, %cr2
pop %r15
pop %r14
pop %r13
pop %r12
pop %r11
pop %r10
pop %r9
pop %r8
pop %rbp
pop %rdi
pop %rsi
pop %rdx
pop %rcx
pop %rbx
pop %rax
iretq
"
: /* No outputs */
: /* No inputs */
: "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "rsp", "r8",
"r9", "r10", "r11", "r12", "r13", "r14", "r15"
: "volatile"
};
panic!("Should never get here!");
}
#[naked]
pub unsafe extern "C" fn page_fault_handler() {
use memory::handle_page_fault;
let fault_addr: usize;
asm!{
"
push %rax
push %rbx
push %rcx
push %rdx
push %rsi
push %rdi
push %rbp
push %r8
push %r9
push %r10
push %r11
push %r12
push %r13
push %r14
push %r15
mov %cr2, $0 /* address */
"
: "=r"(fault_addr)
: /* No inputs */
: "rsp"
: "volatile"
};
handle_page_fault(fault_addr);
asm!{
"
pop %r15
pop %r14
pop %r13
pop %r12
pop %r11
pop %r10
pop %r9
pop %r8
pop %rbp
pop %rdi
pop %rsi
pop %rdx
pop %rcx
pop %rbx
pop %rax
add $$8,%rsp /* pop error */
iret
"
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment