⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 arch_cpu.c

📁 newos is new operation system
💻 C
字号:
/*** Copyright 2001-2004, Travis Geiselbrecht. All rights reserved.** Distributed under the terms of the NewOS License.*/#include <kernel/kernel.h>#include <kernel/cpu.h>#include <kernel/arch/cpu.h>#include <kernel/heap.h>#include <kernel/vm.h>#include <kernel/debug.h>#include <kernel/smp.h>#include <kernel/debug.h>#include <kernel/arch/x86_64/selector.h>#include <kernel/arch/int.h>#include <kernel/arch/x86_64/interrupts.h>#include <newos/errors.h>#include <boot/stage2.h>#include <string.h>#include <stdio.h>#include <stdlib.h>/* a few debug functions that get added to the kernel debugger menu */static void dbg_in(int argc, char **argv);static void dbg_out(int argc, char **argv);static struct tss_64 **tss;static int *tss_loaded;static desc_table *gdt = 0;int arch_cpu_preboot_init(kernel_args *ka){	write_dr3(0);	return 0;}int arch_cpu_init(kernel_args *ka){	setup_system_time(ka->arch_args.system_time_cv_factor);	return 0;}int arch_cpu_init2(kernel_args *ka){	region_id rid;	struct descriptor_64 *tss_d;	unsigned int i;	// account for the segment descriptors	gdt = (desc_table *)ka->arch_args.vir_gdt;	vm_create_anonymous_region(vm_get_kernel_aspace_id(), "gdt", (void **)&gdt,		REGION_ADDR_EXACT_ADDRESS, PAGE_SIZE, REGION_WIRING_WIRED_ALREADY, LOCK_RW|LOCK_KERNEL);	tss = kmalloc(sizeof(struct tss_64 *) * ka->num_cpus);	if(tss == NULL) {		panic("arch_cpu_init2: could not allocate buffer for tss pointers\n");		return ERR_NO_MEMORY;	}	tss_loaded = kmalloc(sizeof(int) * ka->num_cpus);	if(tss == NULL) {		panic("arch_cpu_init2: could not allocate buffer for tss booleans\n");		return ERR_NO_MEMORY;	}	memset(tss_loaded, 0, sizeof(int) * ka->num_cpus);	for(i=0; i<ka->num_cpus; i++) {		char tss_name[16];		sprintf(tss_name, "tss%d", i);		rid = vm_create_anonymous_region(vm_get_kernel_aspace_id(), tss_name, (void **)&tss[i],			REGION_ADDR_ANY_ADDRESS, PAGE_SIZE, REGION_WIRING_WIRED, LOCK_RW|LOCK_KERNEL);		if(rid < 0) {			panic("arch_cpu_init2: unable to create region for tss\n");			return ERR_NO_MEMORY;		}		memset(tss[i], 0, sizeof(struct tss_64));		// add TSS descriptor for this new TSS		tss_d = (struct descriptor_64 *)&gdt[5 + i];		tss_d->limit_00_15 = sizeof(struct tss_64) & 0xffff;		tss_d->limit_19_16 = 0; // it's not this long		tss_d->base_00_15 = (addr_t)tss[i] & 0xffff;		tss_d->base_23_16 = ((addr_t)tss[i] >> 16) & 0xff;		tss_d->base_31_24 = ((addr_t)tss[i] >> 24) & 0xff;		tss_d->base_63_32 = ((addr_t)tss[i] >> 32) & 0xffffffff;		tss_d->type = 0x9;		tss_d->system = 0;		tss_d->dpl = 0;		tss_d->present = 1;		tss_d->zero = 0;		tss_d->granularity = 1;		tss_d->reserved = 0;		tss_d->zero2 = 0;		tss_d->reserved2 = 0;	}	// set up a few debug commands (in, out)	dbg_add_command(&dbg_in, "in", "read I/O port");	dbg_add_command(&dbg_out, "out", "write I/O port");	return 0;}desc_table *x86_64_get_gdt(void){	return gdt;}void x86_64_set_kstack(addr_t kstack){	int curr_cpu = smp_get_current_cpu();//	dprintf("x86_64_set_kstack: kstack 0x%x, cpu %d\n", kstack, curr_cpu);	if(tss_loaded[curr_cpu] == 0) {		short seg = (TSS + 8*curr_cpu);		asm("movw  %0, %%ax;"			"ltr %%ax;" : : "r" (seg) : "eax");		tss_loaded[curr_cpu] = 1;	}	tss[curr_cpu]->rsp0 = kstack;//	dprintf("done\n");}void reboot(void){	static uint16 null_idt_descr[3];	asm("lidt	%0" : : "m" (null_idt_descr));	asm("int 	$0");	for(;;);}void arch_cpu_invalidate_TLB_range(addr_t start, addr_t end){	for(; start < end; start += PAGE_SIZE) {		invalidate_TLB(start);	}}void arch_cpu_invalidate_TLB_list(addr_t pages[], int num_pages){	int i;	for(i=0; i<num_pages; i++) {		invalidate_TLB(pages[i]);	}}int arch_cpu_user_memcpy(void *to, const void *from, size_t size, addr_t *fault_handler){	char *tmp = (char *)to;	char *s = (char *)from;	*fault_handler = (addr_t)&&error;	while(size--)		*tmp++ = *s++;	*fault_handler = 0;	return 0;error:	*fault_handler = 0;	return ERR_VM_BAD_USER_MEMORY;}int arch_cpu_user_strcpy(char *to, const char *from, addr_t *fault_handler){	*fault_handler = (addr_t)&&error;	while((*to++ = *from++) != '\0')		;	*fault_handler = 0;	return 0;error:	*fault_handler = 0;	return ERR_VM_BAD_USER_MEMORY;}int arch_cpu_user_strncpy(char *to, const char *from, size_t size, addr_t *fault_handler){	*fault_handler = (addr_t)&&error;	while(size-- && (*to++ = *from++) != '\0')		;	*fault_handler = 0;	return 0;error:	*fault_handler = 0;	return ERR_VM_BAD_USER_MEMORY;}int arch_cpu_user_memset(void *s, char c, size_t count, addr_t *fault_handler){	char *xs = (char *) s;	*fault_handler = (addr_t)&&error;	while (count--)		*xs++ = c;	*fault_handler = 0;	return 0;error:	*fault_handler = 0;	return ERR_VM_BAD_USER_MEMORY;}void arch_cpu_idle(void){	switch(smp_get_num_cpus()) {		case 0:			panic("You need at least 1 CPU to run NewOS\n");		case 1:			asm("hlt");		default:			break;	}}void arch_cpu_sync_icache(void *address, size_t len){	// instruction cache is always consistent on x86}static void dbg_in(int argc, char **argv){	int value;	int port;	if(argc < 2) {		dprintf("not enough args\nusage: %s (1|2|4) port\n", argv[0]);		return;	}	port = atoul(argv[2]);	switch(argv[1][0]) {		case '1':		case 'b':			value = in8(port);			break;		case '2':		case 'h':			value = in16(port);			break;		case '4':		case 'w':			value = in32(port);			break;		default:			dprintf("invalid width argument\n");			return;	}	dprintf("I/O port 0x%x = 0x%x\n", port, value);}static void dbg_out(int argc, char **argv){	int value;	int port;	if(argc < 3) {		dprintf("not enough args\nusage: %s (1|2|4) port value\n", argv[0]);		return;	}	port = atoul(argv[2]);	value = atoul(argv[3]);	switch(argv[1][0]) {		case '1':		case 'b':			out8(value, port);			break;		case '2':		case 'h':			out16(value, port);			break;		case '4':		case 'w':			out32(value, port);			break;		default:			dprintf("invalid width argument\n");			return;	}	dprintf("writing 0x%x to I/O port 0x%x\n", value, port);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -