Kernel: Add actual register values to x86_64 kernel panic
Very hackish implementation, but we now get actual registers at the time of the interrupt happening
This commit is contained in:
		
							parent
							
								
									bfe3426f6d
								
							
						
					
					
						commit
						6dc22b7251
					
				|  | @ -111,23 +111,16 @@ namespace IDT | ||||||
| 
 | 
 | ||||||
| 	extern "C" void handle_irq() | 	extern "C" void handle_irq() | ||||||
| 	{ | 	{ | ||||||
| 		uint32_t isr[8]; |  | ||||||
| 		InterruptController::Get().GetISR(isr); |  | ||||||
| 
 |  | ||||||
| 		uint8_t irq = 0; | 		uint8_t irq = 0; | ||||||
| 		for (uint8_t i = 0; i < 8; i++) | 		for (uint32_t i = 0; i <= 0xFF; i++) | ||||||
| 		{ | 		{ | ||||||
| 			for (uint8_t j = 0; j < 32; j++) | 			if (InterruptController::Get().IsInService(i)) | ||||||
| 			{ | 			{ | ||||||
| 				if (isr[i] & ((uint32_t)1 << j)) | 				irq = i; | ||||||
| 				{ | 				break; | ||||||
| 					irq = 32 * i + j; |  | ||||||
| 					goto found; |  | ||||||
| 				} |  | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 	found: |  | ||||||
| 		if (irq == 0) | 		if (irq == 0) | ||||||
| 		{ | 		{ | ||||||
| 			dprintln("Spurious irq"); | 			dprintln("Spurious irq"); | ||||||
|  | @ -137,19 +130,7 @@ namespace IDT | ||||||
| 		if (s_irq_handlers[irq]) | 		if (s_irq_handlers[irq]) | ||||||
| 			s_irq_handlers[irq](); | 			s_irq_handlers[irq](); | ||||||
| 		else | 		else | ||||||
| 		{ |  | ||||||
| 			uint32_t isr_byte = irq / 32; |  | ||||||
| 			uint32_t isr_bit  = irq % 32; |  | ||||||
| 
 |  | ||||||
| 			uint32_t isr[8]; |  | ||||||
| 			InterruptController::Get().GetISR(isr); |  | ||||||
| 			if (!(isr[isr_byte] & (1 << isr_bit))) |  | ||||||
| 			{ |  | ||||||
| 				dprintln("spurious irq 0x{2H}", irq); |  | ||||||
| 				return; |  | ||||||
| 			} |  | ||||||
| 			dprintln("no handler for irq 0x{2H}\n", irq); | 			dprintln("no handler for irq 0x{2H}\n", irq); | ||||||
| 		} |  | ||||||
| 
 | 
 | ||||||
| 		InterruptController::Get().EOI(irq); | 		InterruptController::Get().EOI(irq); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -10,6 +10,33 @@ | ||||||
| namespace IDT | namespace IDT | ||||||
| { | { | ||||||
| 
 | 
 | ||||||
|  | 	struct Registers | ||||||
|  | 	{ | ||||||
|  | 		uint64_t rsp; | ||||||
|  | 		uint64_t rip; | ||||||
|  | 		uint64_t rflags; | ||||||
|  | 		uint64_t cr4; | ||||||
|  | 		uint64_t cr3; | ||||||
|  | 		uint64_t cr2; | ||||||
|  | 		uint64_t cr0; | ||||||
|  | 
 | ||||||
|  | 		uint64_t r15; | ||||||
|  | 		uint64_t r14; | ||||||
|  | 		uint64_t r13; | ||||||
|  | 		uint64_t r12; | ||||||
|  | 		uint64_t r11; | ||||||
|  | 		uint64_t r10; | ||||||
|  | 		uint64_t r9; | ||||||
|  | 		uint64_t r8; | ||||||
|  | 		uint64_t rsi; | ||||||
|  | 		uint64_t rdi; | ||||||
|  | 		uint64_t rbp; | ||||||
|  | 		uint64_t rdx; | ||||||
|  | 		uint64_t rcx; | ||||||
|  | 		uint64_t rbx; | ||||||
|  | 		uint64_t rax; | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
| 	struct GateDescriptor | 	struct GateDescriptor | ||||||
| 	{ | 	{ | ||||||
| 		uint16_t offset1; | 		uint16_t offset1; | ||||||
|  | @ -68,25 +95,20 @@ namespace IDT | ||||||
| 		"Unkown Exception 0x1F", | 		"Unkown Exception 0x1F", | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	extern "C" void cpp_isr_handler(uint64_t isr, uint64_t error) | 	extern "C" void cpp_isr_handler(uint64_t isr, uint64_t error, const Registers* regs) | ||||||
| 	{ | 	{ | ||||||
| 		uint64_t rax, rbx, rcx, rdx, rsp, rbp; |  | ||||||
| 		uint64_t cr0, cr2, cr3, cr4; |  | ||||||
| 		asm volatile("" : "=a"(rax), "=b"(rbx), "=c"(rcx), "=d"(rdx)); |  | ||||||
| 		asm volatile("movq %%rsp, %0" : "=r"(rsp)); |  | ||||||
| 		asm volatile("movq %%rbp, %0" : "=r"(rbp)); |  | ||||||
| 		asm volatile("movq %%cr0, %0" : "=r"(cr0)); |  | ||||||
| 		asm volatile("movq %%cr2, %0" : "=r"(cr2)); |  | ||||||
| 		asm volatile("movq %%cr3, %0" : "=r"(cr3)); |  | ||||||
| 		asm volatile("movq %%cr4, %0" : "=r"(cr4)); |  | ||||||
| 
 |  | ||||||
| 		Kernel::Panic( | 		Kernel::Panic( | ||||||
| 			"{} (error code: 0x{16H})\r\n" | 			"{} (error code: 0x{16H})\r\n" | ||||||
| 			"Register dump\r\n" | 			"Register dump\r\n" | ||||||
| 			"rax=0x{16H}, rbx=0x{16H}, rcx=0x{16H}, rdx=0x{16H}\r\n" | 			"rax=0x{16H}, rbx=0x{16H}, rcx=0x{16H}, rdx=0x{16H}\r\n" | ||||||
| 			"rsp=0x{16H}, rbp=0x{16H}\r\n" | 			"rsp=0x{16H}, rbp=0x{16H}, rdi=0x{16H}, rsi=0x{16H}\r\n" | ||||||
| 			"CR0=0x{16H}, CR2=0x{16H}, CR3=0x{16H}, CR4=0x{16H}\r\n", | 			"rip=0x{16H}, rflags=0x{16H}\r\n" | ||||||
| 			isr_exceptions[isr], error, rax, rbx, rcx, rdx, rsp, rbp, cr0, cr2, cr3, cr4 | 			"cr0=0x{16H}, cr2=0x{16H}, cr3=0x{16H}, cr4=0x{16H}\r\n", | ||||||
|  | 			isr_exceptions[isr], error, | ||||||
|  | 			regs->rax, regs->rbx, regs->rcx, regs->rdx, | ||||||
|  | 			regs->rsp, regs->rbp, regs->rdi, regs->rsi, | ||||||
|  | 			regs->rip, regs->rflags, | ||||||
|  | 			regs->cr0, regs->cr2, regs->cr3, regs->cr4 | ||||||
| 		); | 		); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -96,12 +118,7 @@ namespace IDT | ||||||
| 			s_irq_handlers[irq](); | 			s_irq_handlers[irq](); | ||||||
| 		else | 		else | ||||||
| 		{ | 		{ | ||||||
| 			uint32_t isr_byte = irq / 32; | 			if (!InterruptController::Get().IsInService(irq)) | ||||||
| 			uint32_t isr_bit  = irq % 32; |  | ||||||
| 
 |  | ||||||
| 			uint32_t isr[8]; |  | ||||||
| 			InterruptController::Get().GetISR(isr); |  | ||||||
| 			if (!(isr[isr_byte] & (1 << isr_bit))) |  | ||||||
| 			{ | 			{ | ||||||
| 				dprintln("spurious irq 0x{2H}", irq); | 				dprintln("spurious irq 0x{2H}", irq); | ||||||
| 				return; | 				return; | ||||||
|  | @ -117,21 +134,21 @@ namespace IDT | ||||||
| 		asm volatile("lidt %0"::"m"(s_idtr)); | 		asm volatile("lidt %0"::"m"(s_idtr)); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	static void register_interrupt_handler(uint8_t index, void(*f)()) | 	static void register_interrupt_handler(uint8_t index, void(*handler)()) | ||||||
| 	{ | 	{ | ||||||
| 		GateDescriptor& descriptor = s_idt[index]; | 		GateDescriptor& descriptor = s_idt[index]; | ||||||
| 		descriptor.offset1 = (uint16_t)((uint64_t)f >> 0); | 		descriptor.offset1 = (uint16_t)((uint64_t)handler >> 0); | ||||||
| 		descriptor.offset2 = (uint16_t)((uint64_t)f >> 16); | 		descriptor.offset2 = (uint16_t)((uint64_t)handler >> 16); | ||||||
| 		descriptor.offset3 = (uint32_t)((uint64_t)f >> 32); | 		descriptor.offset3 = (uint32_t)((uint64_t)handler >> 32); | ||||||
| 
 | 
 | ||||||
| 		descriptor.selector = 0x08; | 		descriptor.selector = 0x08; | ||||||
| 		descriptor.IST = 0; | 		descriptor.IST = 0; | ||||||
| 		descriptor.flags = 0x8E; | 		descriptor.flags = 0x8E; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void register_irq_handler(uint8_t irq, void(*f)()) | 	void register_irq_handler(uint8_t irq, void(*handler)()) | ||||||
| 	{ | 	{ | ||||||
| 		s_irq_handlers[irq] = f; | 		s_irq_handlers[irq] = handler; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	extern "C" void isr0(); | 	extern "C" void isr0(); | ||||||
|  |  | ||||||
|  | @ -36,16 +36,28 @@ | ||||||
| 
 | 
 | ||||||
| isr_stub: | isr_stub: | ||||||
| 	pushaq | 	pushaq | ||||||
| 	movq 120(%rsp), %rdi | 
 | ||||||
| 	movq 128(%rsp), %rsi | 	movq     %cr0,  %rax; pushq %rax
 | ||||||
|  | 	movq     %cr2,  %rax; pushq %rax
 | ||||||
|  | 	movq     %cr3,  %rax; pushq %rax
 | ||||||
|  | 	movq     %cr4,  %rax; pushq %rax
 | ||||||
|  | 	movq 184(%rsp), %rax; pushq %rax
 | ||||||
|  | 	movq 176(%rsp), %rax; pushq %rax
 | ||||||
|  | 	movq 208(%rsp), %rax; pushq %rax
 | ||||||
|  | 
 | ||||||
|  | 	movq 176(%rsp), %rdi | ||||||
|  | 	movq 184(%rsp), %rsi | ||||||
|  | 	movq %rsp, %rdx | ||||||
|  | 
 | ||||||
| 	call cpp_isr_handler | 	call cpp_isr_handler | ||||||
|  | 	addq $56, %rsp | ||||||
| 	popaq | 	popaq | ||||||
| 	addq $16, %rsp | 	addq $16, %rsp | ||||||
| 	iretq | 	iretq | ||||||
| 
 | 
 | ||||||
| irq_stub: | irq_stub: | ||||||
| 	pushaq | 	pushaq | ||||||
| 	movq 120(%rsp), %rdi | 	movq 0x78(%rsp), %rdi	# irq number | ||||||
| 	call cpp_irq_handler | 	call cpp_irq_handler | ||||||
| 	popaq | 	popaq | ||||||
| 	addq $16, %rsp | 	addq $16, %rsp | ||||||
|  |  | ||||||
|  | @ -8,7 +8,7 @@ class APIC final : public InterruptController | ||||||
| public: | public: | ||||||
| 	virtual void EOI(uint8_t) override; | 	virtual void EOI(uint8_t) override; | ||||||
| 	virtual void EnableIrq(uint8_t) override; | 	virtual void EnableIrq(uint8_t) override; | ||||||
| 	virtual void GetISR(uint32_t[8]) override; | 	virtual bool IsInService(uint8_t) override; | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
| 	uint32_t ReadFromLocalAPIC(ptrdiff_t); | 	uint32_t ReadFromLocalAPIC(ptrdiff_t); | ||||||
|  |  | ||||||
|  | @ -9,7 +9,7 @@ public: | ||||||
| 
 | 
 | ||||||
| 	virtual void EOI(uint8_t) = 0; | 	virtual void EOI(uint8_t) = 0; | ||||||
| 	virtual void EnableIrq(uint8_t) = 0; | 	virtual void EnableIrq(uint8_t) = 0; | ||||||
| 	virtual void GetISR(uint32_t[8]) = 0; | 	virtual bool IsInService(uint8_t) = 0; | ||||||
| 
 | 
 | ||||||
| 	static void Initialize(bool force_pic); | 	static void Initialize(bool force_pic); | ||||||
| 	static InterruptController& Get(); | 	static InterruptController& Get(); | ||||||
|  |  | ||||||
|  | @ -7,7 +7,7 @@ class PIC final : public InterruptController | ||||||
| public: | public: | ||||||
| 	virtual void EOI(uint8_t) override; | 	virtual void EOI(uint8_t) override; | ||||||
| 	virtual void EnableIrq(uint8_t) override; | 	virtual void EnableIrq(uint8_t) override; | ||||||
| 	virtual void GetISR(uint32_t[8]) override; | 	virtual bool IsInService(uint8_t) override; | ||||||
| 
 | 
 | ||||||
| 	static void Remap(); | 	static void Remap(); | ||||||
| 	static void MaskAll(); | 	static void MaskAll(); | ||||||
|  |  | ||||||
|  | @ -358,8 +358,11 @@ void APIC::EnableIrq(uint8_t irq) | ||||||
| 	ioapic->Write(IOAPIC_REDIRS + gsi * 2 + 1,	redir.hi_dword); | 	ioapic->Write(IOAPIC_REDIRS + gsi * 2 + 1,	redir.hi_dword); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void APIC::GetISR(uint32_t out[8]) | bool APIC::IsInService(uint8_t irq) | ||||||
| { | { | ||||||
| 	for (uint32_t i = 0; i < 8; i++) | 	uint32_t dword = (irq + IRQ_VECTOR_BASE) / 32; | ||||||
| 		out[i] = ReadFromLocalAPIC(LAPIC_IS_REG + i * 0x10); | 	uint32_t bit = (irq + IRQ_VECTOR_BASE) % 32; | ||||||
|  | 
 | ||||||
|  | 	uint32_t isr = ReadFromLocalAPIC(LAPIC_IS_REG + dword * 0x10); | ||||||
|  | 	return isr & (1 << bit); | ||||||
| } | } | ||||||
|  | @ -98,14 +98,12 @@ void PIC::EnableIrq(uint8_t irq) | ||||||
| 	IO::outb(port, value); | 	IO::outb(port, value); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void PIC::GetISR(uint32_t out[8]) | bool PIC::IsInService(uint8_t irq) | ||||||
| { | { | ||||||
| 	memset(out, 0, 8 * sizeof(uint32_t)); | 	uint16_t port = irq < 8 ? PIC1_COMMAND : PIC2_COMMAND; | ||||||
| 	IO::outb(PIC1_COMMAND, PIC_READ_ISR); | 	uint8_t  bit  = irq < 8 ? irq : irq - 8; | ||||||
| 	IO::outb(PIC2_COMMAND, PIC_READ_ISR); |  | ||||||
| 	uint16_t isr0 = IO::inb(PIC1_COMMAND); |  | ||||||
| 	uint16_t isr1 = IO::inb(PIC2_COMMAND); |  | ||||||
| 
 | 
 | ||||||
| 	uintptr_t addr = (uintptr_t)out + IRQ_VECTOR_BASE / 8; | 	IO::outb(port, PIC_READ_ISR); | ||||||
| 	*(uint16_t*)addr = (isr1 << 8) | isr0; | 	uint16_t isr = IO::inb(port); | ||||||
|  | 	return isr & (1 << bit); | ||||||
| } | } | ||||||
		Loading…
	
		Reference in New Issue