Mon 14 Oct 23:06:38 CEST 2024
This commit is contained in:
		
							parent
							
								
									dffe6dee58
								
							
						
					
					
						commit
						f29318a654
					
				
							
								
								
									
										168
									
								
								kernel/interrupt.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								kernel/interrupt.c
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,168 @@ | ||||||
|  | /*
 | ||||||
|  | Copyright (C) 2015-2019 The University of Notre Dame | ||||||
|  | This software is distributed under the GNU General Public License. | ||||||
|  | See the file LICENSE for details. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | #include "interrupt.h" | ||||||
|  | #include "console.h" | ||||||
|  | #include "pic.h" | ||||||
|  | #include "process.h" | ||||||
|  | #include "kernelcore.h" | ||||||
|  | #include "x86.h" | ||||||
|  | 
 | ||||||
|  | static interrupt_handler_t interrupt_handler_table[48]; | ||||||
|  | static uint32_t interrupt_count[48]; | ||||||
|  | static uint8_t interrupt_spurious[48]; | ||||||
|  | 
 | ||||||
|  | static const char *exception_names[] = { | ||||||
|  | 	"division by zero", | ||||||
|  | 	"debug exception", | ||||||
|  | 	"nonmaskable interrupt", | ||||||
|  | 	"breakpoint", | ||||||
|  | 	"overflow", | ||||||
|  | 	"bounds check", | ||||||
|  | 	"invalid instruction", | ||||||
|  | 	"coprocessor error", | ||||||
|  | 	"double fault", | ||||||
|  | 	"copressor overrun", | ||||||
|  | 	"invalid task", | ||||||
|  | 	"segment not present", | ||||||
|  | 	"stack exception", | ||||||
|  | 	"general protection fault", | ||||||
|  | 	"page fault", | ||||||
|  | 	"unknown", | ||||||
|  | 	"coprocessor error" | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static void unknown_exception(int i, int code) | ||||||
|  | { | ||||||
|  | 	unsigned vaddr; // virtual address trying to be accessed
 | ||||||
|  | 	unsigned paddr; // physical address
 | ||||||
|  | 	unsigned esp; // stack pointer
 | ||||||
|  | 
 | ||||||
|  | 	if(i==14) { | ||||||
|  | 		asm("mov %%cr2, %0" : "=r" (vaddr) ); // virtual address trying to be accessed		
 | ||||||
|  | 		esp  = ((struct x86_stack *)(current->kstack_top - sizeof(struct x86_stack)))->esp; // stack pointer of the process that raised the exception
 | ||||||
|  | 		// Check if the requested memory is in the stack or data
 | ||||||
|  | 		int data_access = vaddr < current->vm_data_size; | ||||||
|  | 
 | ||||||
|  | 		// Subtract 128 from esp because of the red-zone 
 | ||||||
|  | 		// According to https:gcc.gnu.org, the red zone is a 128-byte area beyond 
 | ||||||
|  | 		// the stack pointer that will not be modified by signal or interrupt handlers 
 | ||||||
|  | 		// and therefore can be used for temporary data without adjusting the stack pointer.
 | ||||||
|  | 		int stack_access = vaddr >= esp - 128;  | ||||||
|  | 
 | ||||||
|  | 		// Check if the requested memory is already in use
 | ||||||
|  | 		int page_already_present = pagetable_getmap(current->pagetable,vaddr,&paddr,0); | ||||||
|  | 		 | ||||||
|  | 		// Check if page is already mapped (which will result from violating the permissions on page) or that
 | ||||||
|  | 		// we are accessing neither the stack nor the heap, or we are accessing both. If so, error
 | ||||||
|  | 		if (page_already_present || !(data_access ^ stack_access)) { | ||||||
|  | 			printf("interrupt: illegal page access at vaddr %x\n",vaddr); | ||||||
|  | 			process_dump(current); | ||||||
|  | 			process_exit(0); | ||||||
|  | 		} else { | ||||||
|  | 			// XXX update process->vm_stack_size when growing the stack.
 | ||||||
|  | 			pagetable_alloc(current->pagetable, vaddr, PAGE_SIZE, PAGE_FLAG_USER | PAGE_FLAG_READWRITE | PAGE_FLAG_CLEAR); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		printf("interrupt: exception %d: %s (code %x)\n", i, exception_names[i], code); | ||||||
|  | 		process_dump(current); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if(current) { | ||||||
|  | 		process_exit(0); | ||||||
|  | 	} else { | ||||||
|  | 		printf("interrupt: exception in kernel code!\n"); | ||||||
|  | 		halt(); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void unknown_hardware(int i, int code) | ||||||
|  | { | ||||||
|  | 	if(!interrupt_spurious[i]) { | ||||||
|  | 		printf("interrupt: spurious interrupt %d\n", i); | ||||||
|  | 	} | ||||||
|  | 	interrupt_spurious[i]++; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void interrupt_register(int i, interrupt_handler_t handler) | ||||||
|  | { | ||||||
|  | 	interrupt_handler_table[i] = handler; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void interrupt_acknowledge(int i) | ||||||
|  | { | ||||||
|  | 	if(i < 32) { | ||||||
|  | 		/* do nothing */ | ||||||
|  | 	} else { | ||||||
|  | 		pic_acknowledge(i - 32); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void interrupt_init() | ||||||
|  | { | ||||||
|  | 	int i; | ||||||
|  | 	pic_init(32, 40); | ||||||
|  | 	for(i = 32; i < 48; i++) { | ||||||
|  | 		interrupt_disable(i); | ||||||
|  | 		interrupt_acknowledge(i); | ||||||
|  | 	} | ||||||
|  | 	for(i = 0; i < 32; i++) { | ||||||
|  | 		interrupt_handler_table[i] = unknown_exception; | ||||||
|  | 		interrupt_spurious[i] = 0; | ||||||
|  | 		interrupt_count[i] = 0; | ||||||
|  | 	} | ||||||
|  | 	for(i = 32; i < 48; i++) { | ||||||
|  | 		interrupt_handler_table[i] = unknown_hardware; | ||||||
|  | 		interrupt_spurious[i] = 0; | ||||||
|  | 		interrupt_count[i] = 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	interrupt_unblock(); | ||||||
|  | 
 | ||||||
|  | 	printf("interrupt: ready\n"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void interrupt_handler(int i, int code) | ||||||
|  | { | ||||||
|  | 	(interrupt_handler_table[i]) (i, code); | ||||||
|  | 	interrupt_acknowledge(i); | ||||||
|  | 	interrupt_count[i]++; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void interrupt_enable(int i) | ||||||
|  | { | ||||||
|  | 	if(i < 32) { | ||||||
|  | 		/* do nothing */ | ||||||
|  | 	} else { | ||||||
|  | 		pic_enable(i - 32); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void interrupt_disable(int i) | ||||||
|  | { | ||||||
|  | 	if(i < 32) { | ||||||
|  | 		/* do nothing */ | ||||||
|  | 	} else { | ||||||
|  | 		pic_disable(i - 32); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void interrupt_block() | ||||||
|  | { | ||||||
|  | 	asm("cli"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void interrupt_unblock() | ||||||
|  | { | ||||||
|  | 	asm("sti"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void interrupt_wait() | ||||||
|  | { | ||||||
|  | 	asm("sti"); | ||||||
|  | 	asm("hlt"); | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user