<commit_before>/* 
** Copyright 2001, <NAME>. All rights reserved.
** Distributed under the terms of the NewOS License.
*/
#include <kernel/kernel.h>
#include <kernel/vm.h>
#include <kernel/debug.h>
#include <kernel/console.h>
#include <kernel/int.h>
#include <kernel/thread.h>
#include <kernel/smp.h>
#include <kernel/syscalls.h>
#include <kernel/vm_priv.h>

#include <kernel/arch/cpu.h>
#include <kernel/arch/int.h>
#include <kernel/arch/faults.h>
#include <kernel/arch/vm.h>
#include <kernel/arch/smp.h>

#include <kernel/arch/i386/interrupts.h>
#include <kernel/arch/i386/faults.h>

#include <boot/stage2.h>

#include <libc/string.h>

struct int_frame {
	unsigned int gs;
	unsigned int fs;
	unsigned int es;
	unsigned int ds;
	unsigned int edi;
	unsigned int esi;
	unsigned int ebp;
	unsigned int esp;
	unsigned int ebx;
	unsigned int edx;
	unsigned int ecx;
	unsigned int eax;
	unsigned int vector;
	unsigned int error_code;
	unsigned int eip;
	unsigned int cs;
	unsigned int flags;
	unsigned int user_esp;
	unsigned int user_ss;
};

static desc_table *idt = NULL;


void interrupt_ack(int n)
{
	if(n >= 0x20 && n < 0x30) {
		// 8239 controlled interrupt
		if(n > 0x27)
			out8(0x20, 0xa0);	// EOI to pic 2	
		out8(0x20, 0x20);	// EOI to pic 1
	}
}

static void _set_gate(desc_table *gate_addr, unsigned int addr, int type, int dpl)
{
	unsigned int gate1; // first byte of gate desc
	unsigned int gate2; // second byte of gate desc
	
	gate1 = (KERNEL_CODE_SEG << 16) | (0x0000ffff & addr);
	gate2 = (0xffff0000 & addr) | 0x8000 | (dpl << 13) | (type << 8);
	
	gate_addr->a = gate1;
	gate_addr->b = gate2;
}

void arch_int_enable_io_interrupt(int irq)
{
	if(irq < 0x20 || irq >= 0x30) return;
	irq -= 0x20;
	// if this is a external interrupt via 8239, enable it here
	if (irq < 8)
		out8(in8(0x21) & ~(1 << irq), 0x21);
	else
		out8(in8(0xa1) & ~(1 << (irq - 8)), 0xa1);
}

void arch_int_disable_io_interrupt(int irq)
{
	if(irq < 0x20 || irq >= 0x30) return;
	irq -= 0x20;
	// if this is a external interrupt via 8239, disable it here
	if (irq < 8)
		out8(in8(0x21) | (1 << irq), 0x21);
	else
		out8(in8(0xa1) | (1 << (irq - 8)), 0xa1);
}

static void set_intr_gate(int n, void *addr)
{
	_set_gate(&idt[n], (unsigned int)addr, 14, 0);
}

static void set_trap_gate(int n, void *addr)
{
	_set_gate(&idt[n], (unsigned int)addr, 15, 0);
}

static void set_system_gate(int n, void *addr)
{
	_set_gate(&idt[n], (unsigned int)addr, 15, 3);
}

void arch_int_enable_interrupts()
{
	asm("sti");
}

int arch_int_disable_interrupts()
{
	int flags;
	
	asm("pushfl;
		popl %0;
		cli" : "=g" (flags));
	return flags & 0x200 ? 1 : 0;
}

void arch_int_restore_interrupts(int oldstate)
{
	int flags = oldstate ? 0x200 : 0;
	int state = 0;

	asm volatile("pushfl;
		popl	%1;
		andl	$0xfffffdff,%1;
		orl		%0,%1;
		pushl	%1;
		popfl"
		: "=g" (flags) : "r" (state), "0" (flags));
}

void i386_handle_trap(struct int_frame frame)
{
	int ret;

//	if(frame.vector != 0x20)
//		dprintf("i386_handle_trap: vector 0x%x, ip 0x%x, cpu %d\n", frame.vector, frame.eip, smp_get_current_cpu());
	switch(frame.vector) {
		case 8:
			ret = i386_double_fault(frame.error_code);
			break;
		case 13:
			ret = i386_general_protection_fault(frame.error_code);
			break;
		case 14: {
			unsigned int cr2;
		
			asm volatile("movl %%cr2, %0;" : "=g" (cr2));
			
			int_enable_interrupts();
			ret = vm_page_fault(cr2, frame.eip,
				(frame.error_code & 0x2) != 0,
				(frame.error_code & 0x4) != 0);
			break;
		}
		case 99: {
			uint64 retcode;

			thread_atkernel_entry();

			ret = syscall_dispatcher(frame.eax, frame.ebx, frame.ecx, frame.edx, frame.esi, frame.edi, frame.ebp, &retcode);
			frame.eax = retcode & 0xffffffff;
			frame.edx = retcode >> 32;
			break;
		}
		default:
			if(frame.vector >= 0x20) {
				interrupt_ack(frame.vector); // ack the 8239 (if applicable)
				ret = int_io_interrupt_handler(frame.vector);
			} else {
				panic("i386_handle_trap: unhandled cpu trap 0x%x at ip 0x%x!\n", frame.vector, frame.eip);
				ret = INT_NO_RESCHEDULE;
			}
			break;<commit_msg>fixed another potential boot crasher where taking a page fault results in the cpu having it's interrupts enabled, which could cause a reschedule and chaos. Fixed for now, but need to rethink the boot process...<commit_after>/* 
** Copyright 2001, <NAME>. All rights reserved.
** Distributed under the terms of the NewOS License.
*/
#include <kernel/kernel.h>
#include <kernel/vm.h>
#include <kernel/debug.h>
#include <kernel/console.h>
#include <kernel/int.h>
#include <kernel/thread.h>
#include <kernel/smp.h>
#include <kernel/syscalls.h>
#include <kernel/vm_priv.h>

#include <kernel/arch/cpu.h>
#include <kernel/arch/int.h>
#include <kernel/arch/faults.h>
#include <kernel/arch/vm.h>
#include <kernel/arch/smp.h>

#include <kernel/arch/i386/interrupts.h>
#include <kernel/arch/i386/faults.h>

#include <boot/stage2.h>

#include <libc/string.h>

struct int_frame {
	unsigned int gs;
	unsigned int fs;
	unsigned int es;
	unsigned int ds;
	unsigned int edi;
	unsigned int esi;
	unsigned int ebp;
	unsigned int esp;
	unsigned int ebx;
	unsigned int edx;
	unsigned int ecx;
	unsigned int eax;
	unsigned int vector;
	unsigned int error_code;
	unsigned int eip;
	unsigned int cs;
	unsigned int flags;
	unsigned int user_esp;
	unsigned int user_ss;
};

static desc_table *idt = NULL;


void interrupt_ack(int n)
{
	if(n >= 0x20 && n < 0x30) {
		// 8239 controlled interrupt
		if(n > 0x27)
			out8(0x20, 0xa0);	// EOI to pic 2	
		out8(0x20, 0x20);	// EOI to pic 1
	}
}

static void _set_gate(desc_table *gate_addr, unsigned int addr, int type, int dpl)
{
	unsigned int gate1; // first byte of gate desc
	unsigned int gate2; // second byte of gate desc
	
	gate1 = (KERNEL_CODE_SEG << 16) | (0x0000ffff & addr);
	gate2 = (0xffff0000 & addr) | 0x8000 | (dpl << 13) | (type << 8);
	
	gate_addr->a = gate1;
	gate_addr->b = gate2;
}

void arch_int_enable_io_interrupt(int irq)
{
	if(irq < 0x20 || irq >= 0x30) return;
	irq -= 0x20;
	// if this is a external interrupt via 8239, enable it here
	if (irq < 8)
		out8(in8(0x21) & ~(1 << irq), 0x21);
	else
		out8(in8(0xa1) & ~(1 << (irq - 8)), 0xa1);
}

void arch_int_disable_io_interrupt(int irq)
{
	if(irq < 0x20 || irq >= 0x30) return;
	irq -= 0x20;
	// if this is a external interrupt via 8239, disable it here
	if (irq < 8)
		out8(in8(0x21) | (1 << irq), 0x21);
	else
		out8(in8(0xa1) | (1 << (irq - 8)), 0xa1);
}

static void set_intr_gate(int n, void *addr)
{
	_set_gate(&idt[n], (unsigned int)addr, 14, 0);
}

static void set_trap_gate(int n, void *addr)
{
	_set_gate(&idt[n], (unsigned int)addr, 15, 0);
}

static void set_system_gate(int n, void *addr)
{
	_set_gate(&idt[n], (unsigned int)addr, 15, 3);
}

void arch_int_enable_interrupts()
{
	asm("sti");
}

int arch_int_disable_interrupts()
{
	int flags;
	
	asm("pushfl;
		popl %0;
		cli" : "=g" (flags));
	return flags & 0x200 ? 1 : 0;
}

void arch_int_restore_interrupts(int oldstate)
{
	int flags = oldstate ? 0x200 : 0;
	int state = 0;

	asm volatile("pushfl;
		popl	%1;
		andl	$0xfffffdff,%1;
		orl		%0,%1;
		pushl	%1;
		popfl"
		: "=g" (flags) : "r" (state), "0" (flags));
}

void i386_handle_trap(struct int_frame frame)
{
	int ret;

//	if(frame.vector != 0x20)
//		dprintf("i386_handle_trap: vector 0x%x, ip 0x%x, cpu %d\n", frame.vector, frame.eip, smp_get_current_cpu());
	switch(frame.vector) {
		case 8:
			ret = i386_double_fault(frame.error_code);
			break;
		case 13:
			ret = i386_general_protection_fault(frame.error_code);
			break;
		case 14: {
			unsigned int cr2;
		
			asm volatile("movl %%cr2, %0;" : "=g" (cr2));
			
			// get the old interrupt enable/disable state and restore to that
			if(frame.flags & 0x200) {
				dprintf("page_fault: enabling interrupts\n");
				int_enable_interrupts();
			}
			ret = vm_page_fault(cr2, frame.eip,
				(frame.error_code & 0x2) != 0,
				(frame.error_code & 0x4) != 0);
			break;
		}
		case 99: {
			uint64 retcode;

			thread_atkernel_entry();

			ret = syscall_dispatcher(frame.eax, frame.ebx, frame.ecx, frame.edx, frame.esi, frame.edi, frame.ebp, &retcode);
			frame.eax = retcode & 0xffffffff;
			frame.edx = retcode >> 32;
			break;
		}
		default:
			if(frame.vector >= 0x20) {
				interrupt_ack(frame.vector); // ack the 8239 (if applicable)
				ret = int_io_interrupt_handler(frame.vector);
			} else {
				panic("i386_handle_trap: unhandled cpu trap 0x%x at ip 0x%x!\n", frame.vector, frame.eip);
				ret = INT_NO_RESCHEDULE;
			}
			break;
{'fraction_non_alphanumeric': 0.14687463074559848, 'fraction_numerical': 0.04962779156327544, 'mean_word_length': 3.741736694677871, 'pattern_counts': {'":': 0, '<': 79, '<?xml version=': 0, '>': 59, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5295405', 'n_tokens_mistral': 3920, 'n_tokens_neox': 3440, 'n_words': 900}